blob: 369cf1252871e76ed28937c06f0c84a7129bcb62 [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302 * Copyright (c) 2013-2015, 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.
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080018 *
19 * This file was modified by DTS, Inc. The portions of the
20 * code modified by DTS, Inc are copyrighted and
21 * licensed separately, as follows:
22 *
23 * (C) 2014 DTS, Inc.
24 *
25 * Licensed under the Apache License, Version 2.0 (the "License");
26 * you may not use this file except in compliance with the License.
27 * You may obtain a copy of the License at
28 *
29 * http://www.apache.org/licenses/LICENSE-2.0
30 *
31 * Unless required by applicable law or agreed to in writing, software
32 * distributed under the License is distributed on an "AS IS" BASIS,
33 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
34 * See the License for the specific language governing permissions and
35 * limitations under the License.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080036 */
37
38#define LOG_TAG "audio_hw_primary"
39/*#define LOG_NDEBUG 0*/
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070040/*#define VERY_VERY_VERBOSE_LOGGING*/
41#ifdef VERY_VERY_VERBOSE_LOGGING
42#define ALOGVV ALOGV
43#else
44#define ALOGVV(a...) do { } while(0)
45#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080046
47#include <errno.h>
48#include <pthread.h>
49#include <stdint.h>
50#include <sys/time.h>
51#include <stdlib.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080052#include <math.h>
Eric Laurentc4aef752013-09-12 17:45:53 -070053#include <dlfcn.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070054#include <sys/resource.h>
55#include <sys/prctl.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080056
57#include <cutils/log.h>
58#include <cutils/str_parms.h>
59#include <cutils/properties.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070060#include <cutils/atomic.h>
61#include <cutils/sched_policy.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080062
Eric Laurentb23d5282013-05-14 15:27:20 -070063#include <hardware/audio_effect.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070064#include <system/thread_defs.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070065#include <audio_effects/effect_aec.h>
66#include <audio_effects/effect_ns.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080067#include "audio_hw.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070068#include "platform_api.h"
69#include <platform.h>
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -070070#include "audio_extn.h"
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080071#include "voice_extn.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080072
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070073#include "sound/compress_params.h"
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080074#include "sound/asound.h"
ApurupaPattapu2e084df2013-12-18 15:47:59 -080075
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070076#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 4
77/* ToDo: Check and update a proper value in msec */
Alexy Joseph01e54e62015-03-03 19:01:03 -080078#define COMPRESS_OFFLOAD_PLAYBACK_LATENCY 50
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070079#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
80
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -070081#define PROXY_OPEN_RETRY_COUNT 100
82#define PROXY_OPEN_WAIT_TIME 20
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080083
Mingming Yin08c7e312015-03-16 18:10:58 -070084#ifdef USE_LL_AS_PRIMARY_OUTPUT
85#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_LOW_LATENCY
86#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_low_latency
87#else
Haynes Mathew Georgebf143712013-12-03 13:02:53 -080088#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_DEEP_BUFFER
Mingming Yin08c7e312015-03-16 18:10:58 -070089#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_deep_buffer
90#endif
Haynes Mathew Georgebf143712013-12-03 13:02:53 -080091
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070092static unsigned int configured_low_latency_capture_period_size =
93 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
94
Eric Laurentb23d5282013-05-14 15:27:20 -070095struct pcm_config pcm_config_deep_buffer = {
96 .channels = 2,
97 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
98 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
99 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
100 .format = PCM_FORMAT_S16_LE,
101 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
102 .stop_threshold = INT_MAX,
103 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
104};
105
106struct pcm_config pcm_config_low_latency = {
107 .channels = 2,
108 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
109 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
110 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
111 .format = PCM_FORMAT_S16_LE,
112 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
113 .stop_threshold = INT_MAX,
114 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
115};
116
117struct pcm_config pcm_config_hdmi_multi = {
118 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
119 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
120 .period_size = HDMI_MULTI_PERIOD_SIZE,
121 .period_count = HDMI_MULTI_PERIOD_COUNT,
122 .format = PCM_FORMAT_S16_LE,
123 .start_threshold = 0,
124 .stop_threshold = INT_MAX,
125 .avail_min = 0,
126};
127
128struct pcm_config pcm_config_audio_capture = {
129 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -0700130 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
131 .format = PCM_FORMAT_S16_LE,
132};
133
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700134#define AFE_PROXY_CHANNEL_COUNT 2
135#define AFE_PROXY_SAMPLING_RATE 48000
136
137#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
138#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
139
140struct pcm_config pcm_config_afe_proxy_playback = {
141 .channels = AFE_PROXY_CHANNEL_COUNT,
142 .rate = AFE_PROXY_SAMPLING_RATE,
143 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
144 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
145 .format = PCM_FORMAT_S16_LE,
146 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
147 .stop_threshold = INT_MAX,
148 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
149};
150
151#define AFE_PROXY_RECORD_PERIOD_SIZE 768
152#define AFE_PROXY_RECORD_PERIOD_COUNT 4
153
154struct pcm_config pcm_config_afe_proxy_record = {
155 .channels = AFE_PROXY_CHANNEL_COUNT,
156 .rate = AFE_PROXY_SAMPLING_RATE,
157 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
158 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
159 .format = PCM_FORMAT_S16_LE,
160 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
161 .stop_threshold = INT_MAX,
162 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
163};
164
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800165const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700166 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
167 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
168 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700169 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700170#ifdef MULTIPLE_OFFLOAD_ENABLED
171 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
172 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
173 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
174 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
175 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
176 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
177 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
178 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
179#endif
Eric Laurentb23d5282013-05-14 15:27:20 -0700180 [USECASE_AUDIO_RECORD] = "audio-record",
Mingming Yine62d7842013-10-25 16:26:03 -0700181 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Eric Laurentb23d5282013-05-14 15:27:20 -0700182 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700183 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700184 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800185 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800186 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700187 [USECASE_VOICE_CALL] = "voice-call",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700188
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700189 [USECASE_VOICE2_CALL] = "voice2-call",
190 [USECASE_VOLTE_CALL] = "volte-call",
191 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800192 [USECASE_VOWLAN_CALL] = "vowlan-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800193 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700194 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
195 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
196 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800197 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
198 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
199 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
200
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700201 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
202 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700203 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
204 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700205
206 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
207 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Eric Laurentb23d5282013-05-14 15:27:20 -0700208};
209
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700210static const audio_usecase_t offload_usecases[] = {
211 USECASE_AUDIO_PLAYBACK_OFFLOAD,
212#ifdef MULTIPLE_OFFLOAD_ENABLED
213 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
214 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
215 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
216 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
217 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
218 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
219 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
220 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
221#endif
222};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800223
224#define STRING_TO_ENUM(string) { #string, string }
225
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800226struct string_to_enum {
227 const char *name;
228 uint32_t value;
229};
230
231static const struct string_to_enum out_channels_name_to_enum_table[] = {
232 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700233 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),/* QUAD_BACK is same as QUAD */
234 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD_SIDE),
235 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
236 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1), /* 5POINT1_BACK is same as 5POINT1 */
237 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1_SIDE),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800238 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
239};
240
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700241static const struct string_to_enum out_formats_name_to_enum_table[] = {
242 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
243 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
244 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
245};
246
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700247static struct audio_device *adev = NULL;
248static pthread_mutex_t adev_init_lock;
Kiran Kandi910e1862013-10-29 13:29:42 -0700249static unsigned int audio_device_ref_count;
250
Haynes Mathew George5191a852013-09-11 14:19:36 -0700251static int set_voice_volume_l(struct audio_device *adev, float volume);
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800252
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800253static int check_and_set_gapless_mode(struct audio_device *adev) {
254
255
256 char value[PROPERTY_VALUE_MAX] = {0};
257 bool gapless_enabled = false;
258 const char *mixer_ctl_name = "Compress Gapless Playback";
259 struct mixer_ctl *ctl;
260
261 ALOGV("%s:", __func__);
262 property_get("audio.offload.gapless.enabled", value, NULL);
263 gapless_enabled = atoi(value) || !strncmp("true", value, 4);
264
265 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
266 if (!ctl) {
267 ALOGE("%s: Could not get ctl for mixer cmd - %s",
268 __func__, mixer_ctl_name);
269 return -EINVAL;
270 }
271
272 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
273 ALOGE("%s: Could not set gapless mode %d",
274 __func__, gapless_enabled);
275 return -EINVAL;
276 }
277 return 0;
278}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700279
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700280static bool is_supported_format(audio_format_t format)
281{
Eric Laurent86e17132013-09-12 17:49:30 -0700282 if (format == AUDIO_FORMAT_MP3 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530283 format == AUDIO_FORMAT_AAC_LC ||
284 format == AUDIO_FORMAT_AAC_HE_V1 ||
285 format == AUDIO_FORMAT_AAC_HE_V2 ||
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800286 format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD ||
Mingming Yin3ee55c62014-08-04 14:23:35 -0700287 format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800288 format == AUDIO_FORMAT_FLAC ||
289 format == AUDIO_FORMAT_WMA ||
290 format == AUDIO_FORMAT_WMA_PRO)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800291 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700292
293 return false;
294}
295
296static int get_snd_codec_id(audio_format_t format)
297{
298 int id = 0;
299
Ashish Jainf9b78162014-08-25 20:36:25 +0530300 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700301 case AUDIO_FORMAT_MP3:
302 id = SND_AUDIOCODEC_MP3;
303 break;
304 case AUDIO_FORMAT_AAC:
305 id = SND_AUDIOCODEC_AAC;
306 break;
Ashish Jainf9b78162014-08-25 20:36:25 +0530307 case AUDIO_FORMAT_PCM_OFFLOAD:
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800308 id = SND_AUDIOCODEC_PCM;
309 break;
Mingming Yin3ee55c62014-08-04 14:23:35 -0700310 case AUDIO_FORMAT_FLAC:
311 id = SND_AUDIOCODEC_FLAC;
312 break;
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800313 case AUDIO_FORMAT_WMA:
314 id = SND_AUDIOCODEC_WMA;
315 break;
316 case AUDIO_FORMAT_WMA_PRO:
317 id = SND_AUDIOCODEC_WMA_PRO;
318 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700319 default:
Mingming Yin90310102013-11-13 16:57:00 -0800320 ALOGE("%s: Unsupported audio format :%x", __func__, format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700321 }
322
323 return id;
324}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800325
Venkata Narendra Kumar Guttaed0f94f2014-07-09 16:29:28 +0530326int get_snd_card_state(struct audio_device *adev)
Naresh Tanniru80659832014-06-04 18:17:56 +0530327{
328 int snd_scard_state;
329
330 if (!adev)
331 return SND_CARD_STATE_OFFLINE;
332
333 pthread_mutex_lock(&adev->snd_card_status.lock);
334 snd_scard_state = adev->snd_card_status.state;
335 pthread_mutex_unlock(&adev->snd_card_status.lock);
336
337 return snd_scard_state;
338}
339
340static int set_snd_card_state(struct audio_device *adev, int snd_scard_state)
341{
342 if (!adev)
343 return -ENOSYS;
344
345 pthread_mutex_lock(&adev->snd_card_status.lock);
346 adev->snd_card_status.state = snd_scard_state;
347 pthread_mutex_unlock(&adev->snd_card_status.lock);
348
349 return 0;
350}
351
Avinash Vaish71a8b972014-07-24 15:36:33 +0530352static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
353 struct audio_usecase *uc_info)
354{
355 struct listnode *node;
356 struct audio_usecase *usecase;
357
358 if (uc_info == NULL)
359 return -EINVAL;
360
361 /* Re-route all voice usecases on the shared backend other than the
362 specified usecase to new snd devices */
363 list_for_each(node, &adev->usecase_list) {
364 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800365 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530366 enable_audio_route(adev, usecase);
367 }
368 return 0;
369}
370
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700371int pcm_ioctl(struct pcm *pcm, int request, ...)
372{
373 va_list ap;
374 void * arg;
375 int pcm_fd = *(int*)pcm;
376
377 va_start(ap, request);
378 arg = va_arg(ap, void *);
379 va_end(ap);
380
381 return ioctl(pcm_fd, request, arg);
382}
383
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700384int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700385 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800386{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700387 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700388 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800389
390 if (usecase == NULL)
391 return -EINVAL;
392
393 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
394
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800395 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700396 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800397 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700398 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800399
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -0800400#ifdef DS1_DOLBY_DAP_ENABLED
401 audio_extn_dolby_set_dmid(adev);
402 audio_extn_dolby_set_endpoint(adev);
403#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700404 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700405 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530406 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700407 audio_extn_utils_send_audio_calibration(adev, usecase);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700408 audio_extn_utils_send_app_type_cfg(usecase);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800409 strcpy(mixer_path, use_case_table[usecase->id]);
Eric Laurentb23d5282013-05-14 15:27:20 -0700410 platform_add_backend_name(mixer_path, snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700411 ALOGV("%s: apply mixer and update path: %s", __func__, mixer_path);
412 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800413 ALOGV("%s: exit", __func__);
414 return 0;
415}
416
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700417int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700418 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800419{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700420 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700421 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800422
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +0530423 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800424 return -EINVAL;
425
426 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700427 if (usecase->type == PCM_CAPTURE)
428 snd_device = usecase->in_snd_device;
429 else
430 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800431 strcpy(mixer_path, use_case_table[usecase->id]);
Eric Laurentb23d5282013-05-14 15:27:20 -0700432 platform_add_backend_name(mixer_path, snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700433 ALOGV("%s: reset and update mixer path: %s", __func__, mixer_path);
434 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700435 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530436 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800437 ALOGV("%s: exit", __func__);
438 return 0;
439}
440
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700441int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700442 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800443{
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700444 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
445
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800446 if (snd_device < SND_DEVICE_MIN ||
447 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800448 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800449 return -EINVAL;
450 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700451
452 adev->snd_dev_ref_cnt[snd_device]++;
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700453
454 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
455 ALOGE("%s: Invalid sound device returned", __func__);
456 return -EINVAL;
457 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700458 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700459 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700460 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700461 return 0;
462 }
463
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -0700464 if (audio_extn_spkr_prot_is_enabled())
465 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700466 /* start usb playback thread */
467 if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
468 SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
469 audio_extn_usb_start_playback(adev);
470
471 /* start usb capture thread */
472 if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
473 audio_extn_usb_start_capture(adev);
474
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800475 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
476 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700477 audio_extn_spkr_prot_is_enabled()) {
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700478 if (audio_extn_spkr_prot_get_acdb_id(snd_device) < 0) {
479 adev->snd_dev_ref_cnt[snd_device]--;
480 return -EINVAL;
481 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200482 audio_extn_dev_arbi_acquire(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800483 if (audio_extn_spkr_prot_start_processing(snd_device)) {
484 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200485 audio_extn_dev_arbi_release(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800486 return -EINVAL;
487 }
488 } else {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700489 ALOGV("%s: snd_device(%d: %s)", __func__,
490 snd_device, device_name);
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -0700491 /* due to the possibility of calibration overwrite between listen
492 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700493 audio_extn_sound_trigger_update_device_status(snd_device,
494 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530495 audio_extn_listen_update_device_status(snd_device,
496 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700497 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700498 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700499 audio_extn_sound_trigger_update_device_status(snd_device,
500 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530501 audio_extn_listen_update_device_status(snd_device,
502 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700503 return -EINVAL;
504 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300505 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700506 audio_route_apply_and_update_path(adev->audio_route, device_name);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800507 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800508 return 0;
509}
510
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700511int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700512 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800513{
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700514 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
515
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800516 if (snd_device < SND_DEVICE_MIN ||
517 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800518 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800519 return -EINVAL;
520 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700521 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
522 ALOGE("%s: device ref cnt is already 0", __func__);
523 return -EINVAL;
524 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700525
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700526 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700527
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700528 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
529 ALOGE("%s: Invalid sound device returned", __func__);
530 return -EINVAL;
531 }
532
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700533 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Eric Laurent994a6932013-07-17 11:51:42 -0700534 ALOGV("%s: snd_device(%d: %s)", __func__,
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700535 snd_device, device_name);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -0800536 /* exit usb play back thread */
537 if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
538 SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
539 audio_extn_usb_stop_playback();
540
541 /* exit usb capture thread */
542 if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -0700543 audio_extn_usb_stop_capture();
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -0800544
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800545 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
546 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700547 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -0700548 audio_extn_spkr_prot_stop_processing(snd_device);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300549 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700550 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300551 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700552
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200553 audio_extn_dev_arbi_release(snd_device);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700554 audio_extn_sound_trigger_update_device_status(snd_device,
555 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530556 audio_extn_listen_update_device_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -0800557 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700558 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700559
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800560 return 0;
561}
562
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700563static void check_usecases_codec_backend(struct audio_device *adev,
564 struct audio_usecase *uc_info,
565 snd_device_t snd_device)
566{
567 struct listnode *node;
568 struct audio_usecase *usecase;
569 bool switch_device[AUDIO_USECASE_MAX];
570 int i, num_uc_to_switch = 0;
571
572 /*
573 * This function is to make sure that all the usecases that are active on
574 * the hardware codec backend are always routed to any one device that is
575 * handled by the hardware codec.
576 * For example, if low-latency and deep-buffer usecases are currently active
577 * on speaker and out_set_parameters(headset) is received on low-latency
578 * output, then we have to make sure deep-buffer is also switched to headset,
579 * because of the limitation that both the devices cannot be enabled
580 * at the same time as they share the same backend.
581 */
Mingming Yin3ee55c62014-08-04 14:23:35 -0700582 /*
583 * This call is to check if we need to force routing for a particular stream
584 * If there is a backend configuration change for the device when a
585 * new stream starts, then ADM needs to be closed and re-opened with the new
586 * configuraion. This call check if we need to re-route all the streams
587 * associated with the backend. Touch tone + 24 bit playback.
588 */
589 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info);
590
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700591 /* Disable all the usecases on the shared backend other than the
592 specified usecase */
593 for (i = 0; i < AUDIO_USECASE_MAX; i++)
594 switch_device[i] = false;
595
596 list_for_each(node, &adev->usecase_list) {
597 usecase = node_to_item(node, struct audio_usecase, list);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800598 if (usecase->type != PCM_CAPTURE &&
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700599 usecase != uc_info &&
Mingming Yin3ee55c62014-08-04 14:23:35 -0700600 (usecase->out_snd_device != snd_device || force_routing) &&
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700601 usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
602 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
603 __func__, use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700604 platform_get_snd_device_name(usecase->out_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700605 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700606 switch_device[usecase->id] = true;
607 num_uc_to_switch++;
608 }
609 }
610
611 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700612 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700613
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530614 /* Make sure the previous devices to be disabled first and then enable the
615 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700616 list_for_each(node, &adev->usecase_list) {
617 usecase = node_to_item(node, struct audio_usecase, list);
618 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700619 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700620 }
621 }
622
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700623 list_for_each(node, &adev->usecase_list) {
624 usecase = node_to_item(node, struct audio_usecase, list);
625 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700626 enable_snd_device(adev, snd_device);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700627 }
628 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700629
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700630 /* Re-route all the usecases on the shared backend other than the
631 specified usecase to new snd devices */
632 list_for_each(node, &adev->usecase_list) {
633 usecase = node_to_item(node, struct audio_usecase, list);
634 /* Update the out_snd_device only before enabling the audio route */
635 if (switch_device[usecase->id] ) {
636 usecase->out_snd_device = snd_device;
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800637 if (usecase->type != VOICE_CALL)
Avinash Vaish71a8b972014-07-24 15:36:33 +0530638 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700639 }
640 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700641 }
642}
643
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700644static void check_and_route_capture_usecases(struct audio_device *adev,
645 struct audio_usecase *uc_info,
646 snd_device_t snd_device)
647{
648 struct listnode *node;
649 struct audio_usecase *usecase;
650 bool switch_device[AUDIO_USECASE_MAX];
651 int i, num_uc_to_switch = 0;
652
653 /*
654 * This function is to make sure that all the active capture usecases
655 * are always routed to the same input sound device.
656 * For example, if audio-record and voice-call usecases are currently
657 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
658 * is received for voice call then we have to make sure that audio-record
659 * usecase is also switched to earpiece i.e. voice-dmic-ef,
660 * because of the limitation that two devices cannot be enabled
661 * at the same time if they share the same backend.
662 */
663 for (i = 0; i < AUDIO_USECASE_MAX; i++)
664 switch_device[i] = false;
665
666 list_for_each(node, &adev->usecase_list) {
667 usecase = node_to_item(node, struct audio_usecase, list);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800668 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700669 usecase != uc_info &&
Anish Kumara020a7c2014-10-17 11:13:22 -0700670 usecase->in_snd_device != snd_device &&
Avinash Vaishcc46ef12015-03-27 14:46:04 +0530671 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Anish Kumara020a7c2014-10-17 11:13:22 -0700672 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700673 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
674 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700675 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700676 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700677 switch_device[usecase->id] = true;
678 num_uc_to_switch++;
679 }
680 }
681
682 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700683 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700684
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530685 /* Make sure the previous devices to be disabled first and then enable the
686 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700687 list_for_each(node, &adev->usecase_list) {
688 usecase = node_to_item(node, struct audio_usecase, list);
689 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700690 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800691 }
692 }
693
694 list_for_each(node, &adev->usecase_list) {
695 usecase = node_to_item(node, struct audio_usecase, list);
696 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700697 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700698 }
699 }
700
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700701 /* Re-route all the usecases on the shared backend other than the
702 specified usecase to new snd devices */
703 list_for_each(node, &adev->usecase_list) {
704 usecase = node_to_item(node, struct audio_usecase, list);
705 /* Update the in_snd_device only before enabling the audio route */
706 if (switch_device[usecase->id] ) {
707 usecase->in_snd_device = snd_device;
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800708 if (usecase->type != VOICE_CALL)
Avinash Vaish71a8b972014-07-24 15:36:33 +0530709 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700710 }
711 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700712 }
713}
714
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800715/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700716static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800717{
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700718 int ret = 0, i = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700719 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800720
721 switch (channels) {
722 /*
723 * Do not handle stereo output in Multi-channel cases
724 * Stereo case is handled in normal playback path
725 */
726 case 6:
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700727 ALOGV("%s: HDMI supports Quad and 5.1", __func__);
728 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
729 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD_SIDE;
730 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
731 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
732 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1_SIDE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800733 break;
734 case 8:
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700735 ALOGV("%s: HDMI supports Quad, 5.1 and 7.1 channels", __func__);
736 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
737 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD_SIDE;
738 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
739 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
740 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1_SIDE;
741 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800742 break;
743 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700744 ALOGE("HDMI does not support multi channel playback");
745 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800746 break;
747 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700748 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800749}
750
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800751audio_usecase_t get_usecase_id_from_usecase_type(struct audio_device *adev,
752 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700753{
754 struct audio_usecase *usecase;
755 struct listnode *node;
756
757 list_for_each(node, &adev->usecase_list) {
758 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800759 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700760 ALOGV("%s: usecase id %d", __func__, usecase->id);
761 return usecase->id;
762 }
763 }
764 return USECASE_INVALID;
765}
766
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700767struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700768 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700769{
770 struct audio_usecase *usecase;
771 struct listnode *node;
772
773 list_for_each(node, &adev->usecase_list) {
774 usecase = node_to_item(node, struct audio_usecase, list);
775 if (usecase->id == uc_id)
776 return usecase;
777 }
778 return NULL;
779}
780
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700781int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800782{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800783 snd_device_t out_snd_device = SND_DEVICE_NONE;
784 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700785 struct audio_usecase *usecase = NULL;
786 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800787 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800788 struct audio_usecase *hfp_usecase = NULL;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -0800789 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800790 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700791 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800792
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700793 usecase = get_usecase_from_list(adev, uc_id);
794 if (usecase == NULL) {
795 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
796 return -EINVAL;
797 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800798
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800799 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800800 (usecase->type == VOIP_CALL) ||
801 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700802 out_snd_device = platform_get_output_snd_device(adev->platform,
803 usecase->stream.out->devices);
804 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700805 usecase->devices = usecase->stream.out->devices;
806 } else {
807 /*
808 * If the voice call is active, use the sound devices of voice call usecase
809 * so that it would not result any device switch. All the usecases will
810 * be switched to new device when select_devices() is called for voice call
811 * usecase. This is to avoid switching devices for voice call when
812 * check_usecases_codec_backend() is called below.
813 */
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700814 if (voice_is_in_call(adev) && adev->mode == AUDIO_MODE_IN_CALL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700815 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800816 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700817 if ((vc_usecase) && ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
818 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700819 in_snd_device = vc_usecase->in_snd_device;
820 out_snd_device = vc_usecase->out_snd_device;
821 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800822 } else if (voice_extn_compress_voip_is_active(adev)) {
823 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700824 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Avinash Vaish4d6167d2014-06-25 12:20:37 +0530825 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700826 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800827 in_snd_device = voip_usecase->in_snd_device;
828 out_snd_device = voip_usecase->out_snd_device;
829 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800830 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -0800831 hfp_ucid = audio_extn_hfp_get_usecase();
832 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700833 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800834 in_snd_device = hfp_usecase->in_snd_device;
835 out_snd_device = hfp_usecase->out_snd_device;
836 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700837 }
838 if (usecase->type == PCM_PLAYBACK) {
839 usecase->devices = usecase->stream.out->devices;
840 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700841 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700842 out_snd_device = platform_get_output_snd_device(adev->platform,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700843 usecase->stream.out->devices);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700844 if (usecase->stream.out == adev->primary_output &&
845 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -0800846 adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
847 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700848 select_devices(adev, adev->active_input->usecase);
849 }
850 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700851 } else if (usecase->type == PCM_CAPTURE) {
852 usecase->devices = usecase->stream.in->device;
853 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700854 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700855 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +0530856 if ((adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
857 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
858 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
859 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700860 out_device = adev->primary_output->devices;
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -0800861 platform_set_echo_reference(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700862 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
863 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700864 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700865 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700866 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700867 }
868 }
869
870 if (out_snd_device == usecase->out_snd_device &&
871 in_snd_device == usecase->in_snd_device) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800872 return 0;
873 }
874
sangwoobc677242013-08-08 16:53:43 +0900875 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -0700876 out_snd_device, platform_get_snd_device_name(out_snd_device),
877 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800878
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800879 /*
880 * Limitation: While in call, to do a device switch we need to disable
881 * and enable both RX and TX devices though one of them is same as current
882 * device.
883 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700884 if ((usecase->type == VOICE_CALL) &&
885 (usecase->in_snd_device != SND_DEVICE_NONE) &&
886 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700887 status = platform_switch_voice_call_device_pre(adev->platform);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800888 }
889
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700890 /* Disable current sound devices */
891 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700892 disable_audio_route(adev, usecase);
893 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800894 }
895
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700896 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700897 disable_audio_route(adev, usecase);
898 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800899 }
900
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800901 /* Applicable only on the targets that has external modem.
902 * New device information should be sent to modem before enabling
903 * the devices to reduce in-call device switch time.
904 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700905 if ((usecase->type == VOICE_CALL) &&
906 (usecase->in_snd_device != SND_DEVICE_NONE) &&
907 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800908 status = platform_switch_voice_call_enable_device_config(adev->platform,
909 out_snd_device,
910 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700911 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800912
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700913 /* Enable new sound devices */
914 if (out_snd_device != SND_DEVICE_NONE) {
915 if (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)
916 check_usecases_codec_backend(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700917 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800918 }
919
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700920 if (in_snd_device != SND_DEVICE_NONE) {
921 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700922 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700923 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700924
Avinash Vaish71a8b972014-07-24 15:36:33 +0530925 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700926 status = platform_switch_voice_call_device_post(adev->platform,
927 out_snd_device,
928 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +0530929 enable_audio_route_for_voice_usecases(adev, usecase);
930 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800931
sangwoo170731f2013-06-08 15:36:36 +0900932 usecase->in_snd_device = in_snd_device;
933 usecase->out_snd_device = out_snd_device;
934
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530935 if (usecase->type == PCM_PLAYBACK) {
Amit Shekhar1d896042014-10-03 13:16:09 -0700936 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530937 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -0700938 usecase->stream.out->devices,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530939 usecase->stream.out->flags,
940 usecase->stream.out->format,
941 usecase->stream.out->sample_rate,
942 usecase->stream.out->bit_width,
943 &usecase->stream.out->app_type_cfg);
Amit Shekhar1d896042014-10-03 13:16:09 -0700944 ALOGI("%s Selected apptype: %d", __func__, usecase->stream.out->app_type_cfg.app_type);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530945 }
Amit Shekhar1d896042014-10-03 13:16:09 -0700946
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700947 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +0900948
Vidyakumar Athota1fd21792013-11-15 14:50:57 -0800949 /* Applicable only on the targets that has external modem.
950 * Enable device command should be sent to modem only after
951 * enabling voice call mixer controls
952 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -0700953 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -0800954 status = platform_switch_voice_call_usecase_route_post(adev->platform,
955 out_snd_device,
956 in_snd_device);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +0530957 ALOGD("%s: done",__func__);
958
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800959 return status;
960}
961
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800962static int stop_input_stream(struct stream_in *in)
963{
964 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800965 struct audio_usecase *uc_info;
966 struct audio_device *adev = in->dev;
967
Eric Laurentc8400632013-02-14 19:04:54 -0800968 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800969
Eric Laurent994a6932013-07-17 11:51:42 -0700970 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700971 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800972 uc_info = get_usecase_from_list(adev, in->usecase);
973 if (uc_info == NULL) {
974 ALOGE("%s: Could not find the usecase (%d) in the list",
975 __func__, in->usecase);
976 return -EINVAL;
977 }
978
Vidyakumar Athota2850d532013-11-19 16:02:12 -0800979 /* Close in-call recording streams */
980 voice_check_and_stop_incall_rec_usecase(adev, in);
981
Eric Laurent150dbfe2013-02-27 14:31:02 -0800982 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700983 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700984
985 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700986 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800987
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800988 list_remove(&uc_info->list);
989 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800990
Eric Laurent994a6932013-07-17 11:51:42 -0700991 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800992 return ret;
993}
994
995int start_input_stream(struct stream_in *in)
996{
997 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -0800998 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800999 struct audio_usecase *uc_info;
1000 struct audio_device *adev = in->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301001 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001002
Mingming Yine62d7842013-10-25 16:26:03 -07001003 in->usecase = platform_update_usecase_from_source(in->source,in->usecase);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301004 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1005 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001006
Naresh Tanniru80659832014-06-04 18:17:56 +05301007
1008 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301009 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301010 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301011 goto error_config;
1012 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301013
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001014 /* Check if source matches incall recording usecase criteria */
1015 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1016 if (ret)
1017 goto error_config;
1018 else
Narsinga Rao Chella212e2542014-11-17 19:57:04 -08001019 ALOGD("%s: Updated usecase(%d: %s)",
1020 __func__, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001021
Eric Laurentb23d5282013-05-14 15:27:20 -07001022 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001023 if (in->pcm_device_id < 0) {
1024 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1025 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001026 ret = -EINVAL;
1027 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001028 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001029
1030 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001031 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001032
1033 if (!uc_info) {
1034 ret = -ENOMEM;
1035 goto error_config;
1036 }
1037
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001038 uc_info->id = in->usecase;
1039 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001040 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001041 uc_info->devices = in->device;
1042 uc_info->in_snd_device = SND_DEVICE_NONE;
1043 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001044
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001045 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301046 audio_extn_perf_lock_acquire();
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001047 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001048
Eric Laurentc8400632013-02-14 19:04:54 -08001049 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001050 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1051
1052 unsigned int flags = PCM_IN;
1053 unsigned int pcm_open_retry_count = 0;
1054
1055 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1056 flags |= PCM_MMAP | PCM_NOIRQ;
1057 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1058 }
1059
1060 while (1) {
1061 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1062 flags, &in->config);
1063 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1064 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1065 if (in->pcm != NULL) {
1066 pcm_close(in->pcm);
1067 in->pcm = NULL;
1068 }
1069 if (pcm_open_retry_count-- == 0) {
1070 ret = -EIO;
1071 goto error_open;
1072 }
1073 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1074 continue;
1075 }
1076 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001077 }
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301078 audio_extn_perf_lock_release();
Naresh Tanniru4c630392014-05-12 01:05:52 +05301079
Eric Laurent994a6932013-07-17 11:51:42 -07001080 ALOGV("%s: exit", __func__);
Eric Laurentc8400632013-02-14 19:04:54 -08001081 return ret;
1082
1083error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001084 stop_input_stream(in);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301085 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001086
1087error_config:
1088 adev->active_input = NULL;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001089 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001090
1091 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001092}
1093
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001094/* must be called with out->lock locked */
1095static int send_offload_cmd_l(struct stream_out* out, int command)
1096{
1097 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1098
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001099 if (!cmd) {
1100 ALOGE("failed to allocate mem for command 0x%x", command);
1101 return -ENOMEM;
1102 }
1103
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001104 ALOGVV("%s %d", __func__, command);
1105
1106 cmd->cmd = command;
1107 list_add_tail(&out->offload_cmd_list, &cmd->node);
1108 pthread_cond_signal(&out->offload_cond);
1109 return 0;
1110}
1111
1112/* must be called iwth out->lock locked */
1113static void stop_compressed_output_l(struct stream_out *out)
1114{
1115 out->offload_state = OFFLOAD_STATE_IDLE;
1116 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001117 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001118 if (out->compr != NULL) {
1119 compress_stop(out->compr);
1120 while (out->offload_thread_blocked) {
1121 pthread_cond_wait(&out->cond, &out->lock);
1122 }
1123 }
1124}
1125
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001126bool is_offload_usecase(audio_usecase_t uc_id)
1127{
1128 unsigned int i;
1129 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1130 if (uc_id == offload_usecases[i])
1131 return true;
1132 }
1133 return false;
1134}
1135
1136static audio_usecase_t get_offload_usecase(struct audio_device *adev)
1137{
1138 audio_usecase_t ret = USECASE_AUDIO_PLAYBACK_OFFLOAD;
1139 unsigned int i, num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
1140 char value[PROPERTY_VALUE_MAX] = {0};
1141
1142 property_get("audio.offload.multiple.enabled", value, NULL);
1143 if (!(atoi(value) || !strncmp("true", value, 4)))
1144 num_usecase = 1; /* If prop is not set, limit the num of offload usecases to 1 */
1145
1146 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
1147 for (i = 0; i < num_usecase; i++) {
1148 if (!(adev->offload_usecases_state & (0x1<<i))) {
1149 adev->offload_usecases_state |= 0x1 << i;
1150 ret = offload_usecases[i];
1151 break;
1152 }
1153 }
1154 ALOGV("%s: offload usecase is %d", __func__, ret);
1155 return ret;
1156}
1157
1158static void free_offload_usecase(struct audio_device *adev,
1159 audio_usecase_t uc_id)
1160{
1161 unsigned int i;
1162 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1163 if (offload_usecases[i] == uc_id) {
1164 adev->offload_usecases_state &= ~(0x1<<i);
1165 break;
1166 }
1167 }
1168 ALOGV("%s: free offload usecase %d", __func__, uc_id);
1169}
1170
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001171static void *offload_thread_loop(void *context)
1172{
1173 struct stream_out *out = (struct stream_out *) context;
1174 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001175 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001176
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001177 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1178 set_sched_policy(0, SP_FOREGROUND);
1179 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1180
1181 ALOGV("%s", __func__);
1182 pthread_mutex_lock(&out->lock);
1183 for (;;) {
1184 struct offload_cmd *cmd = NULL;
1185 stream_callback_event_t event;
1186 bool send_callback = false;
1187
1188 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1189 __func__, list_empty(&out->offload_cmd_list),
1190 out->offload_state);
1191 if (list_empty(&out->offload_cmd_list)) {
1192 ALOGV("%s SLEEPING", __func__);
1193 pthread_cond_wait(&out->offload_cond, &out->lock);
1194 ALOGV("%s RUNNING", __func__);
1195 continue;
1196 }
1197
1198 item = list_head(&out->offload_cmd_list);
1199 cmd = node_to_item(item, struct offload_cmd, node);
1200 list_remove(item);
1201
1202 ALOGVV("%s STATE %d CMD %d out->compr %p",
1203 __func__, out->offload_state, cmd->cmd, out->compr);
1204
1205 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1206 free(cmd);
1207 break;
1208 }
1209
1210 if (out->compr == NULL) {
1211 ALOGE("%s: Compress handle is NULL", __func__);
1212 pthread_cond_signal(&out->cond);
1213 continue;
1214 }
1215 out->offload_thread_blocked = true;
1216 pthread_mutex_unlock(&out->lock);
1217 send_callback = false;
1218 switch(cmd->cmd) {
1219 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001220 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001221 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001222 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001223 send_callback = true;
1224 event = STREAM_CBK_EVENT_WRITE_READY;
1225 break;
1226 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001227 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05301228 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001229 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301230 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001231 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301232 if (ret < 0)
1233 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05301234 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301235 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001236 compress_drain(out->compr);
1237 else
1238 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301239 if (ret != -ENETRESET) {
1240 send_callback = true;
1241 event = STREAM_CBK_EVENT_DRAIN_READY;
1242 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
1243 } else
1244 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001245 break;
1246 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001247 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001248 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001249 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001250 send_callback = true;
1251 event = STREAM_CBK_EVENT_DRAIN_READY;
1252 break;
1253 default:
1254 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1255 break;
1256 }
1257 pthread_mutex_lock(&out->lock);
1258 out->offload_thread_blocked = false;
1259 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001260 if (send_callback) {
Ravi Kumar Alamanda38e6fe32014-12-02 19:21:51 -08001261 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001262 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001263 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001264 free(cmd);
1265 }
1266
1267 pthread_cond_signal(&out->cond);
1268 while (!list_empty(&out->offload_cmd_list)) {
1269 item = list_head(&out->offload_cmd_list);
1270 list_remove(item);
1271 free(node_to_item(item, struct offload_cmd, node));
1272 }
1273 pthread_mutex_unlock(&out->lock);
1274
1275 return NULL;
1276}
1277
1278static int create_offload_callback_thread(struct stream_out *out)
1279{
1280 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1281 list_init(&out->offload_cmd_list);
1282 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1283 offload_thread_loop, out);
1284 return 0;
1285}
1286
1287static int destroy_offload_callback_thread(struct stream_out *out)
1288{
1289 pthread_mutex_lock(&out->lock);
1290 stop_compressed_output_l(out);
1291 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1292
1293 pthread_mutex_unlock(&out->lock);
1294 pthread_join(out->offload_thread, (void **) NULL);
1295 pthread_cond_destroy(&out->offload_cond);
1296
1297 return 0;
1298}
1299
Eric Laurent07eeafd2013-10-06 12:52:49 -07001300static bool allow_hdmi_channel_config(struct audio_device *adev)
1301{
1302 struct listnode *node;
1303 struct audio_usecase *usecase;
1304 bool ret = true;
1305
1306 list_for_each(node, &adev->usecase_list) {
1307 usecase = node_to_item(node, struct audio_usecase, list);
1308 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1309 /*
1310 * If voice call is already existing, do not proceed further to avoid
1311 * disabling/enabling both RX and TX devices, CSD calls, etc.
1312 * Once the voice call done, the HDMI channels can be configured to
1313 * max channels of remaining use cases.
1314 */
1315 if (usecase->id == USECASE_VOICE_CALL) {
1316 ALOGD("%s: voice call is active, no change in HDMI channels",
1317 __func__);
1318 ret = false;
1319 break;
1320 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
1321 ALOGD("%s: multi channel playback is active, "
1322 "no change in HDMI channels", __func__);
1323 ret = false;
1324 break;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001325 } else if (is_offload_usecase(usecase->id) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001326 audio_channel_count_from_out_mask(usecase->stream.out->channel_mask) > 2) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001327 ALOGD("%s:multi-channel(%x) compress offload playback is active"
1328 ", no change in HDMI channels", __func__,
1329 usecase->stream.out->channel_mask);
Mingming Yin139f1072014-02-24 17:56:01 -08001330 ret = false;
1331 break;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001332 }
1333 }
1334 }
1335 return ret;
1336}
1337
1338static int check_and_set_hdmi_channels(struct audio_device *adev,
1339 unsigned int channels)
1340{
1341 struct listnode *node;
1342 struct audio_usecase *usecase;
1343
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001344 unsigned int supported_channels = platform_edid_get_max_channels(
1345 adev->platform);
1346 ALOGV("supported_channels %d, channels %d", supported_channels, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001347 /* Check if change in HDMI channel config is allowed */
1348 if (!allow_hdmi_channel_config(adev))
1349 return 0;
1350
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001351 if (channels > supported_channels)
1352 channels = supported_channels;
1353
Eric Laurent07eeafd2013-10-06 12:52:49 -07001354 if (channels == adev->cur_hdmi_channels) {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001355 ALOGD("%s: Requested channels are same as current channels(%d)",
1356 __func__, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001357 return 0;
1358 }
1359
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001360 /*TODO: CHECK for passthrough don't set channel map for passthrough*/
Eric Laurent07eeafd2013-10-06 12:52:49 -07001361 platform_set_hdmi_channels(adev->platform, channels);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001362 platform_set_edid_channels_configuration(adev->platform, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001363 adev->cur_hdmi_channels = channels;
1364
1365 /*
1366 * Deroute all the playback streams routed to HDMI so that
1367 * the back end is deactivated. Note that backend will not
1368 * be deactivated if any one stream is connected to it.
1369 */
1370 list_for_each(node, &adev->usecase_list) {
1371 usecase = node_to_item(node, struct audio_usecase, list);
1372 if (usecase->type == PCM_PLAYBACK &&
1373 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001374 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001375 }
1376 }
1377
1378 /*
1379 * Enable all the streams disabled above. Now the HDMI backend
1380 * will be activated with new channel configuration
1381 */
1382 list_for_each(node, &adev->usecase_list) {
1383 usecase = node_to_item(node, struct audio_usecase, list);
1384 if (usecase->type == PCM_PLAYBACK &&
1385 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001386 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001387 }
1388 }
1389
1390 return 0;
1391}
1392
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001393static int stop_output_stream(struct stream_out *out)
1394{
1395 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001396 struct audio_usecase *uc_info;
1397 struct audio_device *adev = out->dev;
1398
Eric Laurent994a6932013-07-17 11:51:42 -07001399 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001400 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001401 uc_info = get_usecase_from_list(adev, out->usecase);
1402 if (uc_info == NULL) {
1403 ALOGE("%s: Could not find the usecase (%d) in the list",
1404 __func__, out->usecase);
1405 return -EINVAL;
1406 }
1407
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001408 if (is_offload_usecase(out->usecase) &&
1409 !(audio_extn_dolby_is_passthrough_stream(out->flags))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001410 if (adev->visualizer_stop_output != NULL)
1411 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001412
1413 audio_extn_dts_remove_state_notifier_node(out->usecase);
1414
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001415 if (adev->offload_effects_stop_output != NULL)
1416 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1417 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001418
Eric Laurent150dbfe2013-02-27 14:31:02 -08001419 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001420 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001421
1422 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001423 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001424
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001425 list_remove(&uc_info->list);
1426 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001427
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001428 if (is_offload_usecase(out->usecase) &&
1429 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
1430 (audio_extn_dolby_is_passthrough_stream(out->flags))) {
1431 ALOGV("Disable passthrough , reset mixer to pcm");
1432 /* NO_PASSTHROUGH */
1433 out->compr_config.codec->compr_passthr = 0;
1434 audio_extn_dolby_set_hdmi_config(adev, out);
1435 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
1436 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001437 /* Must be called after removing the usecase from list */
1438 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1439 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
1440
Eric Laurent994a6932013-07-17 11:51:42 -07001441 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001442 return ret;
1443}
1444
1445int start_output_stream(struct stream_out *out)
1446{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001447 int ret = 0;
Mingming Yin9c041392014-05-01 15:37:31 -07001448 int sink_channels = 0;
1449 char prop_value[PROPERTY_VALUE_MAX] = {0};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001450 struct audio_usecase *uc_info;
1451 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301452 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001453
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001454 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
1455 ret = -EINVAL;
1456 goto error_config;
1457 }
1458
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301459 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
1460 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
1461 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05301462
Naresh Tanniru80659832014-06-04 18:17:56 +05301463 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301464 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301465 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301466 goto error_config;
1467 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301468
Eric Laurentb23d5282013-05-14 15:27:20 -07001469 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001470 if (out->pcm_device_id < 0) {
1471 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1472 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001473 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001474 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001475 }
1476
1477 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001478
1479 if (!uc_info) {
1480 ret = -ENOMEM;
1481 goto error_config;
1482 }
1483
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001484 uc_info->id = out->usecase;
1485 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001486 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001487 uc_info->devices = out->devices;
1488 uc_info->in_snd_device = SND_DEVICE_NONE;
1489 uc_info->out_snd_device = SND_DEVICE_NONE;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001490 /* This must be called before adding this usecase to the list */
Mingming Yin10fef6a2013-11-26 17:17:01 -08001491 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001492 if (is_offload_usecase(out->usecase)) {
1493 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001494 audio_extn_dolby_update_passt_stream_configuration(adev, out);
1495 }
1496 }
Mingming Yin9c041392014-05-01 15:37:31 -07001497 property_get("audio.use.hdmi.sink.cap", prop_value, NULL);
1498 if (!strncmp("true", prop_value, 4)) {
1499 sink_channels = platform_edid_get_max_channels(out->dev->platform);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001500 ALOGD("%s: set HDMI channel count[%d] based on sink capability",
1501 __func__, sink_channels);
Mingming Yin9c041392014-05-01 15:37:31 -07001502 check_and_set_hdmi_channels(adev, sink_channels);
1503 } else {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001504 if (is_offload_usecase(out->usecase)) {
1505 unsigned int ch_count = out->compr_config.codec->ch_in;
1506 if (audio_extn_dolby_is_passthrough_stream(out->flags))
1507 /* backend channel config for passthrough stream is stereo */
1508 ch_count = 2;
1509 check_and_set_hdmi_channels(adev, ch_count);
1510 } else
Mingming Yin9c041392014-05-01 15:37:31 -07001511 check_and_set_hdmi_channels(adev, out->config.channels);
1512 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001513 audio_extn_dolby_set_hdmi_config(adev, out);
Mingming Yin10fef6a2013-11-26 17:17:01 -08001514 }
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001515 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001516
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001517 select_devices(adev, out->usecase);
1518
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001519 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
1520 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001521 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001522 unsigned int flags = PCM_OUT;
1523 unsigned int pcm_open_retry_count = 0;
1524 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1525 flags |= PCM_MMAP | PCM_NOIRQ;
1526 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1527 } else
1528 flags |= PCM_MONOTONIC;
1529
1530 while (1) {
1531 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1532 flags, &out->config);
1533 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1534 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1535 if (out->pcm != NULL) {
1536 pcm_close(out->pcm);
1537 out->pcm = NULL;
1538 }
1539 if (pcm_open_retry_count-- == 0) {
1540 ret = -EIO;
1541 goto error_open;
1542 }
1543 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1544 continue;
1545 }
1546 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001547 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001548 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1549 out->pcm_device_id);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001550 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001551 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1552 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001553 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08001554 out->compr = compress_open(adev->snd_card,
1555 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001556 COMPRESS_IN, &out->compr_config);
1557 if (out->compr && !is_compress_ready(out->compr)) {
1558 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1559 compress_close(out->compr);
1560 out->compr = NULL;
1561 ret = -EIO;
1562 goto error_open;
1563 }
1564 if (out->offload_callback)
1565 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07001566
Fred Oh3f43e742015-03-04 18:42:34 -08001567 /* Since small bufs uses blocking writes, a write will be blocked
1568 for the default max poll time (20s) in the event of an SSR.
1569 Reduce the poll time to observe and deal with SSR faster.
1570 */
1571 if (out->use_small_bufs) {
1572 compress_set_max_poll_wait(out->compr, 1000);
1573 }
1574
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001575 audio_extn_dts_create_state_notifier_node(out->usecase);
1576 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1577 popcount(out->channel_mask),
1578 out->playback_started);
1579
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001580#ifdef DS1_DOLBY_DDP_ENABLED
1581 if (audio_extn_is_dolby_format(out->format))
1582 audio_extn_dolby_send_ddp_endp_params(adev);
1583#endif
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001584 if (!(audio_extn_dolby_is_passthrough_stream(out->flags))) {
1585 if (adev->visualizer_start_output != NULL)
1586 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1587 if (adev->offload_effects_start_output != NULL)
1588 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001589 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001590 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001591 }
Eric Laurent994a6932013-07-17 11:51:42 -07001592 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001593 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001594error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001595 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001596error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001597 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001598}
1599
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001600static int check_input_parameters(uint32_t sample_rate,
1601 audio_format_t format,
1602 int channel_count)
1603{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001604 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001605
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001606 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
Mingming Yine62d7842013-10-25 16:26:03 -07001607 !voice_extn_compress_voip_is_format_supported(format) &&
1608 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001609
1610 switch (channel_count) {
1611 case 1:
1612 case 2:
1613 case 6:
1614 break;
1615 default:
1616 ret = -EINVAL;
1617 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001618
1619 switch (sample_rate) {
1620 case 8000:
1621 case 11025:
1622 case 12000:
1623 case 16000:
1624 case 22050:
1625 case 24000:
1626 case 32000:
1627 case 44100:
1628 case 48000:
1629 break;
1630 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001631 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001632 }
1633
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001634 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001635}
1636
1637static size_t get_input_buffer_size(uint32_t sample_rate,
1638 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001639 int channel_count,
1640 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001641{
1642 size_t size = 0;
1643
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001644 if (check_input_parameters(sample_rate, format, channel_count) != 0)
1645 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001646
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001647 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001648 if (is_low_latency)
1649 size = configured_low_latency_capture_period_size;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001650 /* ToDo: should use frame_size computed based on the format and
1651 channel_count here. */
1652 size *= sizeof(short) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001653
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001654 /* make sure the size is multiple of 32 bytes
1655 * At 48 kHz mono 16-bit PCM:
1656 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
1657 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
1658 */
1659 size += 0x1f;
1660 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001661
1662 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001663}
1664
1665static uint32_t out_get_sample_rate(const struct audio_stream *stream)
1666{
1667 struct stream_out *out = (struct stream_out *)stream;
1668
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001669 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001670}
1671
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001672static int out_set_sample_rate(struct audio_stream *stream __unused,
1673 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001674{
1675 return -ENOSYS;
1676}
1677
1678static size_t out_get_buffer_size(const struct audio_stream *stream)
1679{
1680 struct stream_out *out = (struct stream_out *)stream;
1681
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001682 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001683 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001684 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
1685 return voice_extn_compress_voip_out_get_buffer_size(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001686
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001687 return out->config.period_size *
1688 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001689}
1690
1691static uint32_t out_get_channels(const struct audio_stream *stream)
1692{
1693 struct stream_out *out = (struct stream_out *)stream;
1694
1695 return out->channel_mask;
1696}
1697
1698static audio_format_t out_get_format(const struct audio_stream *stream)
1699{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001700 struct stream_out *out = (struct stream_out *)stream;
1701
1702 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001703}
1704
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001705static int out_set_format(struct audio_stream *stream __unused,
1706 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001707{
1708 return -ENOSYS;
1709}
1710
1711static int out_standby(struct audio_stream *stream)
1712{
1713 struct stream_out *out = (struct stream_out *)stream;
1714 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001715
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301716 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
1717 stream, out->usecase, use_case_table[out->usecase]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001718 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
1719 /* Ignore standby in case of voip call because the voip output
1720 * stream is closed in adev_close_output_stream()
1721 */
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301722 ALOGD("%s: Ignore Standby in VOIP call", __func__);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001723 return 0;
1724 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001725
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001726 pthread_mutex_lock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001727 if (!out->standby) {
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08001728 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001729 out->standby = true;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001730 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001731 if (out->pcm) {
1732 pcm_close(out->pcm);
1733 out->pcm = NULL;
1734 }
1735 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001736 ALOGD("copl(%p):standby", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001737 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001738 out->gapless_mdata.encoder_delay = 0;
1739 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001740 if (out->compr != NULL) {
1741 compress_close(out->compr);
1742 out->compr = NULL;
1743 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08001744 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001745 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001746 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001747 }
1748 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07001749 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001750 return 0;
1751}
1752
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001753static int out_dump(const struct audio_stream *stream __unused,
1754 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001755{
1756 return 0;
1757}
1758
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001759static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
1760{
1761 int ret = 0;
1762 char value[32];
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001763 bool is_meta_data_params = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001764 struct compr_gapless_mdata tmp_mdata;
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001765 tmp_mdata.encoder_delay = 0;
1766 tmp_mdata.encoder_padding = 0;
Amit Shekharcbf04982015-01-20 20:19:31 -08001767 tmp_mdata.min_blk_size = 0;
1768 tmp_mdata.max_blk_size = 0;
ApurupaPattapu2e084df2013-12-18 15:47:59 -08001769
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001770 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001771 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001772 return -EINVAL;
1773 }
1774
ApurupaPattapu2e084df2013-12-18 15:47:59 -08001775 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FORMAT, value, sizeof(value));
1776 if (ret >= 0) {
1777 if (atoi(value) == SND_AUDIOSTREAMFORMAT_MP4ADTS) {
1778 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
1779 ALOGV("ADTS format is set in offload mode");
1780 }
1781 out->send_new_metadata = 1;
1782 }
1783
Mingming Yin3ee55c62014-08-04 14:23:35 -07001784 if (out->format == AUDIO_FORMAT_FLAC) {
1785 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FLAC_MIN_BLK_SIZE, value, sizeof(value));
1786 if (ret >= 0) {
Amit Shekharcbf04982015-01-20 20:19:31 -08001787 tmp_mdata.min_blk_size =
Mingming Yin3ee55c62014-08-04 14:23:35 -07001788 out->compr_config.codec->options.flac_dec.min_blk_size = atoi(value);
1789 out->send_new_metadata = 1;
1790 }
1791 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FLAC_MAX_BLK_SIZE, value, sizeof(value));
1792 if (ret >= 0) {
Amit Shekharcbf04982015-01-20 20:19:31 -08001793 tmp_mdata.max_blk_size =
Mingming Yin3ee55c62014-08-04 14:23:35 -07001794 out->compr_config.codec->options.flac_dec.max_blk_size = atoi(value);
1795 out->send_new_metadata = 1;
1796 }
1797 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FLAC_MIN_FRAME_SIZE, value, sizeof(value));
1798 if (ret >= 0) {
1799 out->compr_config.codec->options.flac_dec.min_frame_size = atoi(value);
1800 out->send_new_metadata = 1;
1801 }
1802 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FLAC_MAX_FRAME_SIZE, value, sizeof(value));
1803 if (ret >= 0) {
1804 out->compr_config.codec->options.flac_dec.max_frame_size = atoi(value);
1805 out->send_new_metadata = 1;
1806 }
1807 }
1808
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08001809 if (out->format == AUDIO_FORMAT_WMA || out->format == AUDIO_FORMAT_WMA_PRO) {
1810 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_WMA_FORMAT_TAG, value, sizeof(value));
1811 if (ret >= 0) {
1812 out->compr_config.codec->format = atoi(value);
1813 out->send_new_metadata = 1;
1814 }
1815 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_WMA_BLOCK_ALIGN, value, sizeof(value));
1816 if (ret >= 0) {
1817 out->compr_config.codec->options.wma.super_block_align = atoi(value);
1818 out->send_new_metadata = 1;
1819 }
1820 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_WMA_BIT_PER_SAMPLE, value, sizeof(value));
1821 if (ret >= 0) {
1822 out->compr_config.codec->options.wma.bits_per_sample = atoi(value);
1823 out->send_new_metadata = 1;
1824 }
1825 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_WMA_CHANNEL_MASK, value, sizeof(value));
1826 if (ret >= 0) {
1827 out->compr_config.codec->options.wma.channelmask = atoi(value);
1828 out->send_new_metadata = 1;
1829 }
1830 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_WMA_ENCODE_OPTION, value, sizeof(value));
1831 if (ret >= 0) {
1832 out->compr_config.codec->options.wma.encodeopt = atoi(value);
1833 out->send_new_metadata = 1;
1834 }
1835 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_WMA_ENCODE_OPTION1, value, sizeof(value));
1836 if (ret >= 0) {
1837 out->compr_config.codec->options.wma.encodeopt1 = atoi(value);
1838 out->send_new_metadata = 1;
1839 }
1840 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_WMA_ENCODE_OPTION2, value, sizeof(value));
1841 if (ret >= 0) {
1842 out->compr_config.codec->options.wma.encodeopt2 = atoi(value);
1843 out->send_new_metadata = 1;
1844 }
1845 ALOGV("WMA params: fmt %x, balgn %x, sr %d, chmsk %x, encop %x, op1 %x, op2 %x",
1846 out->compr_config.codec->format,
1847 out->compr_config.codec->options.wma.super_block_align,
1848 out->compr_config.codec->options.wma.bits_per_sample,
1849 out->compr_config.codec->options.wma.channelmask,
1850 out->compr_config.codec->options.wma.encodeopt,
1851 out->compr_config.codec->options.wma.encodeopt1,
1852 out->compr_config.codec->options.wma.encodeopt2);
1853 }
1854
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001855 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_SAMPLE_RATE, value, sizeof(value));
1856 if(ret >= 0)
1857 is_meta_data_params = true;
1858 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_NUM_CHANNEL, value, sizeof(value));
1859 if(ret >= 0 )
1860 is_meta_data_params = true;
1861 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_AVG_BIT_RATE, value, sizeof(value));
1862 if(ret >= 0 )
1863 is_meta_data_params = true;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001864 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
1865 if (ret >= 0) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001866 is_meta_data_params = true;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001867 tmp_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001868 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001869 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
1870 if (ret >= 0) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001871 is_meta_data_params = true;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001872 tmp_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001873 }
1874
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001875 if(!is_meta_data_params) {
1876 ALOGV("%s: Not gapless meta data params", __func__);
1877 return 0;
1878 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001879 out->gapless_mdata = tmp_mdata;
1880 out->send_new_metadata = 1;
1881 ALOGV("%s new encoder delay %u and padding %u", __func__,
1882 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
1883
1884 return 0;
1885}
1886
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001887static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
1888{
1889 return out == adev->primary_output || out == adev->voice_tx_output;
1890}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001891
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001892static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
1893{
1894 struct stream_out *out = (struct stream_out *)stream;
1895 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001896 struct audio_usecase *usecase;
1897 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001898 struct str_parms *parms;
1899 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001900 int ret = 0, val = 0, err;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001901 bool select_new_device = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001902
sangwoobc677242013-08-08 16:53:43 +09001903 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001904 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001905 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301906 if (!parms)
1907 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001908 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
1909 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001910 val = atoi(value);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001911 pthread_mutex_lock(&out->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001912 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001913
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001914 /*
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05301915 * When HDMI cable is unplugged/usb hs is disconnected the
1916 * music playback is paused and the policy manager sends routing=0
1917 * But the audioflingercontinues to write data until standby time
1918 * (3sec). As the HDMI core is turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001919 * Avoid this by routing audio to speaker until standby.
1920 */
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05301921 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL ||
1922 out->devices == AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET) &&
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001923 val == AUDIO_DEVICE_NONE) {
Pradnya Chaphekard5349ce2014-11-05 11:40:26 -08001924 if (!audio_extn_dolby_is_passthrough_stream(out->flags))
1925 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001926 }
1927
1928 /*
1929 * select_devices() call below switches all the usecases on the same
1930 * backend to the new device. Refer to check_usecases_codec_backend() in
1931 * the select_devices(). But how do we undo this?
1932 *
1933 * For example, music playback is active on headset (deep-buffer usecase)
1934 * and if we go to ringtones and select a ringtone, low-latency usecase
1935 * will be started on headset+speaker. As we can't enable headset+speaker
1936 * and headset devices at the same time, select_devices() switches the music
1937 * playback to headset+speaker while starting low-lateny usecase for ringtone.
1938 * So when the ringtone playback is completed, how do we undo the same?
1939 *
1940 * We are relying on the out_set_parameters() call on deep-buffer output,
1941 * once the ringtone playback is ended.
1942 * NOTE: We should not check if the current devices are same as new devices.
1943 * Because select_devices() must be called to switch back the music
1944 * playback to headset.
1945 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001946 if (val != 0) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001947 out->devices = val;
1948
1949 if (!out->standby)
1950 select_devices(adev, out->usecase);
1951
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07001952 if (output_drives_call(adev, out)) {
1953 if(!voice_is_in_call(adev)) {
1954 if (adev->mode == AUDIO_MODE_IN_CALL) {
1955 adev->current_call_output = out;
1956 ret = voice_start_call(adev);
1957 }
1958 } else {
1959 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001960 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07001961 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001962 }
1963 }
1964
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001965 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001966 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001967 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001968
1969 if (out == adev->primary_output) {
1970 pthread_mutex_lock(&adev->lock);
1971 audio_extn_set_parameters(adev, parms);
1972 pthread_mutex_unlock(&adev->lock);
1973 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001974 if (is_offload_usecase(out->usecase)) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001975 pthread_mutex_lock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001976 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001977
1978 audio_extn_dts_create_state_notifier_node(out->usecase);
1979 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1980 popcount(out->channel_mask),
1981 out->playback_started);
1982
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001983 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001984 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001985
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001986 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301987error:
Eric Laurent994a6932013-07-17 11:51:42 -07001988 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001989 return ret;
1990}
1991
1992static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
1993{
1994 struct stream_out *out = (struct stream_out *)stream;
1995 struct str_parms *query = str_parms_create_str(keys);
1996 char *str;
1997 char value[256];
1998 struct str_parms *reply = str_parms_create();
1999 size_t i, j;
2000 int ret;
2001 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002002
2003 if (!query || !reply) {
2004 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
2005 return NULL;
2006 }
2007
Eric Laurent994a6932013-07-17 11:51:42 -07002008 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002009 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2010 if (ret >= 0) {
2011 value[0] = '\0';
2012 i = 0;
2013 while (out->supported_channel_masks[i] != 0) {
2014 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2015 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2016 if (!first) {
2017 strcat(value, "|");
2018 }
2019 strcat(value, out_channels_name_to_enum_table[j].name);
2020 first = false;
2021 break;
2022 }
2023 }
2024 i++;
2025 }
2026 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2027 str = str_parms_to_str(reply);
2028 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002029 voice_extn_out_get_parameters(out, query, reply);
2030 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08002031 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08002032 free(str);
2033 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002034 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002035 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002036
2037 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
2038 if (ret >= 0) {
2039 value[0] = '\0';
2040 i = 0;
2041 first = true;
2042 while (out->supported_formats[i] != 0) {
2043 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
2044 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
2045 if (!first) {
2046 strcat(value, "|");
2047 }
2048 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
2049 first = false;
2050 break;
2051 }
2052 }
2053 i++;
2054 }
2055 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
2056 str = str_parms_to_str(reply);
2057 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002058 str_parms_destroy(query);
2059 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002060 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002061 return str;
2062}
2063
2064static uint32_t out_get_latency(const struct audio_stream_out *stream)
2065{
2066 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002067 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002068
Alexy Josephaa54c872014-12-03 02:46:47 -08002069 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002070 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Alexy Josephaa54c872014-12-03 02:46:47 -08002071 } else {
2072 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002073 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002074 }
2075
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302076 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002077 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002078}
2079
2080static int out_set_volume(struct audio_stream_out *stream, float left,
2081 float right)
2082{
Eric Laurenta9024de2013-04-04 09:19:12 -07002083 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002084 int volume[2];
2085
Eric Laurenta9024de2013-04-04 09:19:12 -07002086 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2087 /* only take left channel into account: the API is for stereo anyway */
2088 out->muted = (left == 0.0f);
2089 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002090 } else if (is_offload_usecase(out->usecase)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002091 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
2092 /*
2093 * Set mute or umute on HDMI passthrough stream.
2094 * Only take left channel into account.
2095 * Mute is 0 and unmute 1
2096 */
2097 audio_extn_dolby_set_passt_volume(out, (left == 0.0f));
2098 } else {
2099 char mixer_ctl_name[128];
2100 struct audio_device *adev = out->dev;
2101 struct mixer_ctl *ctl;
2102 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002103 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002104
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002105 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2106 "Compress Playback %d Volume", pcm_device_id);
2107 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2108 if (!ctl) {
2109 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2110 __func__, mixer_ctl_name);
2111 return -EINVAL;
2112 }
2113 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2114 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2115 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2116 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002117 }
Eric Laurenta9024de2013-04-04 09:19:12 -07002118 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002119
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002120 return -ENOSYS;
2121}
2122
2123static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2124 size_t bytes)
2125{
2126 struct stream_out *out = (struct stream_out *)stream;
2127 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302128 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002129 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002130
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002131 pthread_mutex_lock(&out->lock);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302132
Naresh Tanniru80659832014-06-04 18:17:56 +05302133 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08002134 // increase written size during SSR to avoid mismatch
2135 // with the written frames count in AF
2136 if (!is_offload_usecase(out->usecase))
2137 out->written += bytes / (out->config.channels * sizeof(short));
2138
Naresh Tanniru80659832014-06-04 18:17:56 +05302139 if (out->pcm) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05302140 ALOGD(" %s: sound card is not active/SSR state", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302141 ret= -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302142 goto exit;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07002143 } else if (is_offload_usecase(out->usecase)) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302144 //during SSR for compress usecase we should return error to flinger
2145 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2146 pthread_mutex_unlock(&out->lock);
2147 return -ENETRESET;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302148 }
2149 }
2150
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002151 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002152 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002153 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002154 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
2155 ret = voice_extn_compress_voip_start_output_stream(out);
2156 else
2157 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002158 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002159 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002160 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002161 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002162 goto exit;
2163 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002164 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002165
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002166 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002167 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002168 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002169 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002170 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2171 out->send_new_metadata = 0;
2172 }
2173
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002174 ret = compress_write(out->compr, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302175 if (ret < 0)
2176 ret = -errno;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002177 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %d", __func__, bytes, ret);
Eric Laurent6e895242013-09-05 16:10:57 -07002178 if (ret >= 0 && ret < (ssize_t)bytes) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05302179 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002180 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05302181 } else if (-ENETRESET == ret) {
2182 ALOGE("copl %s: received sound card offline state on compress write", __func__);
2183 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2184 pthread_mutex_unlock(&out->lock);
2185 out_standby(&out->stream.common);
2186 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002187 }
Naresh Tanniru80659832014-06-04 18:17:56 +05302188 if (!out->playback_started && ret >= 0) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002189 compress_start(out->compr);
Alexy Joseph7de344d2015-03-30 10:40:03 -07002190 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002191 out->playback_started = 1;
2192 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002193
2194 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2195 popcount(out->channel_mask),
2196 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002197 }
2198 pthread_mutex_unlock(&out->lock);
2199 return ret;
2200 } else {
2201 if (out->pcm) {
2202 if (out->muted)
2203 memset((void *)buffer, 0, bytes);
2204 ALOGVV("%s: writing buffer (%d bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002205 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY)
2206 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
2207 else
2208 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302209 if (ret < 0)
2210 ret = -errno;
2211 else if (ret == 0)
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002212 out->written += bytes / (out->config.channels * sizeof(short));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002213 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002214 }
2215
2216exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302217 /* ToDo: There may be a corner case when SSR happens back to back during
2218 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05302219 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302220 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302221 }
2222
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002223 pthread_mutex_unlock(&out->lock);
2224
2225 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002226 if (out->pcm)
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002227 ALOGE("%s: error %ld - %s", __func__, ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302228 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302229 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302230 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302231 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302232 out->standby = true;
2233 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002234 out_standby(&out->stream.common);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002235 usleep(bytes * 1000000 / audio_stream_out_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302236 out_get_sample_rate(&out->stream.common));
2237
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002238 }
2239 return bytes;
2240}
2241
2242static int out_get_render_position(const struct audio_stream_out *stream,
2243 uint32_t *dsp_frames)
2244{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002245 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302246 struct audio_device *adev = out->dev;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002247 if (is_offload_usecase(out->usecase) && (dsp_frames != NULL)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08002248 ssize_t ret = 0;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002249 *dsp_frames = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002250 pthread_mutex_lock(&out->lock);
2251 if (out->compr != NULL) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302252 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002253 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302254 if (ret < 0)
2255 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002256 ALOGVV("%s rendered frames %d sample_rate %d",
2257 __func__, *dsp_frames, out->sample_rate);
2258 }
2259 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05302260 if (-ENETRESET == ret) {
2261 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2262 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2263 return -EINVAL;
2264 } else if(ret < 0) {
2265 ALOGE(" ERROR: Unable to get time stamp from compress driver");
2266 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302267 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
2268 /*
2269 * Handle corner case where compress session is closed during SSR
2270 * and timestamp is queried
2271 */
2272 ALOGE(" ERROR: sound card not active, return error");
2273 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302274 } else {
2275 return 0;
2276 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002277 } else
2278 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002279}
2280
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002281static int out_add_audio_effect(const struct audio_stream *stream __unused,
2282 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002283{
2284 return 0;
2285}
2286
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002287static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2288 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002289{
2290 return 0;
2291}
2292
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002293static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2294 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002295{
2296 return -EINVAL;
2297}
2298
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002299static int out_get_presentation_position(const struct audio_stream_out *stream,
2300 uint64_t *frames, struct timespec *timestamp)
2301{
2302 struct stream_out *out = (struct stream_out *)stream;
2303 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07002304 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002305
2306 pthread_mutex_lock(&out->lock);
2307
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002308 if (is_offload_usecase(out->usecase)) {
Eric Laurent949a0892013-09-20 09:20:13 -07002309 if (out->compr != NULL) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302310 ret = compress_get_tstamp(out->compr, &dsp_frames,
Eric Laurent949a0892013-09-20 09:20:13 -07002311 &out->sample_rate);
2312 ALOGVV("%s rendered frames %ld sample_rate %d",
2313 __func__, dsp_frames, out->sample_rate);
2314 *frames = dsp_frames;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302315 if (ret < 0)
2316 ret = -errno;
2317 if (-ENETRESET == ret) {
2318 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2319 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2320 ret = -EINVAL;
2321 } else
2322 ret = 0;
2323
Eric Laurent949a0892013-09-20 09:20:13 -07002324 /* this is the best we can do */
2325 clock_gettime(CLOCK_MONOTONIC, timestamp);
2326 }
2327 } else {
2328 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002329 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002330 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2331 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002332 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002333 // This adjustment accounts for buffering after app processor.
2334 // It is based on estimated DSP latency per use case, rather than exact.
2335 signed_frames -=
2336 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2337
Eric Laurent949a0892013-09-20 09:20:13 -07002338 // It would be unusual for this value to be negative, but check just in case ...
2339 if (signed_frames >= 0) {
2340 *frames = signed_frames;
2341 ret = 0;
2342 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002343 }
2344 }
2345 }
2346
2347 pthread_mutex_unlock(&out->lock);
2348
2349 return ret;
2350}
2351
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002352static int out_set_callback(struct audio_stream_out *stream,
2353 stream_callback_t callback, void *cookie)
2354{
2355 struct stream_out *out = (struct stream_out *)stream;
2356
2357 ALOGV("%s", __func__);
2358 pthread_mutex_lock(&out->lock);
2359 out->offload_callback = callback;
2360 out->offload_cookie = cookie;
2361 pthread_mutex_unlock(&out->lock);
2362 return 0;
2363}
2364
2365static int out_pause(struct audio_stream_out* stream)
2366{
2367 struct stream_out *out = (struct stream_out *)stream;
2368 int status = -ENOSYS;
2369 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002370 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002371 ALOGD("copl(%p):pause compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002372 pthread_mutex_lock(&out->lock);
2373 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302374 struct audio_device *adev = out->dev;
2375 int snd_scard_state = get_snd_card_state(adev);
2376
2377 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2378 status = compress_pause(out->compr);
2379
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002380 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002381
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302382 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002383 audio_extn_dts_notify_playback_state(out->usecase, 0,
2384 out->sample_rate, popcount(out->channel_mask),
2385 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002386 }
2387 pthread_mutex_unlock(&out->lock);
2388 }
2389 return status;
2390}
2391
2392static int out_resume(struct audio_stream_out* stream)
2393{
2394 struct stream_out *out = (struct stream_out *)stream;
2395 int status = -ENOSYS;
2396 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002397 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002398 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002399 status = 0;
2400 pthread_mutex_lock(&out->lock);
2401 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302402 struct audio_device *adev = out->dev;
2403 int snd_scard_state = get_snd_card_state(adev);
2404
2405 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2406 status = compress_resume(out->compr);
2407
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002408 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002409
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302410 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002411 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2412 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002413 }
2414 pthread_mutex_unlock(&out->lock);
2415 }
2416 return status;
2417}
2418
2419static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2420{
2421 struct stream_out *out = (struct stream_out *)stream;
2422 int status = -ENOSYS;
2423 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002424 if (is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002425 pthread_mutex_lock(&out->lock);
2426 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2427 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2428 else
2429 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2430 pthread_mutex_unlock(&out->lock);
2431 }
2432 return status;
2433}
2434
2435static int out_flush(struct audio_stream_out* stream)
2436{
2437 struct stream_out *out = (struct stream_out *)stream;
2438 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002439 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002440 ALOGD("copl(%p):calling compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002441 pthread_mutex_lock(&out->lock);
2442 stop_compressed_output_l(out);
2443 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002444 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002445 return 0;
2446 }
2447 return -ENOSYS;
2448}
2449
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002450/** audio_stream_in implementation **/
2451static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2452{
2453 struct stream_in *in = (struct stream_in *)stream;
2454
2455 return in->config.rate;
2456}
2457
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002458static int in_set_sample_rate(struct audio_stream *stream __unused,
2459 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002460{
2461 return -ENOSYS;
2462}
2463
2464static size_t in_get_buffer_size(const struct audio_stream *stream)
2465{
2466 struct stream_in *in = (struct stream_in *)stream;
2467
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002468 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
2469 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07002470 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
2471 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002472
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002473 return in->config.period_size *
2474 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002475}
2476
2477static uint32_t in_get_channels(const struct audio_stream *stream)
2478{
2479 struct stream_in *in = (struct stream_in *)stream;
2480
2481 return in->channel_mask;
2482}
2483
2484static audio_format_t in_get_format(const struct audio_stream *stream)
2485{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002486 struct stream_in *in = (struct stream_in *)stream;
2487
2488 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002489}
2490
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002491static int in_set_format(struct audio_stream *stream __unused,
2492 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002493{
2494 return -ENOSYS;
2495}
2496
2497static int in_standby(struct audio_stream *stream)
2498{
2499 struct stream_in *in = (struct stream_in *)stream;
2500 struct audio_device *adev = in->dev;
2501 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302502 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2503 stream, in->usecase, use_case_table[in->usecase]);
2504
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002505 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
2506 /* Ignore standby in case of voip call because the voip input
2507 * stream is closed in adev_close_input_stream()
2508 */
2509 ALOGV("%s: Ignore Standby in VOIP call", __func__);
2510 return status;
2511 }
2512
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002513 pthread_mutex_lock(&in->lock);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002514 if (!in->standby && in->is_st_session) {
2515 ALOGD("%s: sound trigger pcm stop lab", __func__);
2516 audio_extn_sound_trigger_stop_lab(in);
2517 in->standby = 1;
2518 }
2519
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002520 if (!in->standby) {
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002521 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002522 in->standby = true;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002523 if (in->pcm) {
2524 pcm_close(in->pcm);
2525 in->pcm = NULL;
2526 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002527 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002528 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002529 }
2530 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002531 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002532 return status;
2533}
2534
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002535static int in_dump(const struct audio_stream *stream __unused,
2536 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002537{
2538 return 0;
2539}
2540
2541static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
2542{
2543 struct stream_in *in = (struct stream_in *)stream;
2544 struct audio_device *adev = in->dev;
2545 struct str_parms *parms;
2546 char *str;
2547 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002548 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002549
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302550 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002551 parms = str_parms_create_str(kvpairs);
2552
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302553 if (!parms)
2554 goto error;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002555 pthread_mutex_lock(&in->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002556 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002557
2558 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
2559 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002560 val = atoi(value);
2561 /* no audio source uses val == 0 */
2562 if ((in->source != val) && (val != 0)) {
2563 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002564 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2565 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2566 (voice_extn_compress_voip_is_format_supported(in->format)) &&
2567 (in->config.rate == 8000 || in->config.rate == 16000) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002568 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002569 err = voice_extn_compress_voip_open_input_stream(in);
2570 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002571 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002572 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002573 }
2574 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002575 }
2576 }
2577
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002578 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2579 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002580 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002581 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002582 in->device = val;
2583 /* If recording is in progress, change the tx device to new device */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002584 if (!in->standby && !in->is_st_session)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002585 ret = select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002586 }
2587 }
2588
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002589done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002590 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002591 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002592
2593 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302594error:
Eric Laurent994a6932013-07-17 11:51:42 -07002595 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002596 return ret;
2597}
2598
2599static char* in_get_parameters(const struct audio_stream *stream,
2600 const char *keys)
2601{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002602 struct stream_in *in = (struct stream_in *)stream;
2603 struct str_parms *query = str_parms_create_str(keys);
2604 char *str;
2605 char value[256];
2606 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002607
2608 if (!query || !reply) {
2609 ALOGE("in_get_parameters: failed to create query or reply");
2610 return NULL;
2611 }
2612
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002613 ALOGV("%s: enter: keys - %s", __func__, keys);
2614
2615 voice_extn_in_get_parameters(in, query, reply);
2616
2617 str = str_parms_to_str(reply);
2618 str_parms_destroy(query);
2619 str_parms_destroy(reply);
2620
2621 ALOGV("%s: exit: returns - %s", __func__, str);
2622 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002623}
2624
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002625static int in_set_gain(struct audio_stream_in *stream __unused,
2626 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002627{
2628 return 0;
2629}
2630
2631static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
2632 size_t bytes)
2633{
2634 struct stream_in *in = (struct stream_in *)stream;
2635 struct audio_device *adev = in->dev;
2636 int i, ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05302637 int snd_scard_state = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002638
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002639 pthread_mutex_lock(&in->lock);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302640
2641 if (in->pcm) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302642 if(SND_CARD_STATE_OFFLINE == snd_scard_state) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05302643 ALOGD(" %s: sound card is not active/SSR state", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302644 ret= -EIO;;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302645 goto exit;
Bharath Ramachandramurthy837535b2015-02-05 14:27:59 -08002646 } else {
2647 if (in->is_st_session && !in->is_st_session_active) {
2648 ALOGD(" %s: Sound trigger is not active/SSR", __func__);
2649 ret= -EIO;;
2650 goto exit;
2651 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05302652 }
2653 }
2654
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002655 if (in->standby) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002656 if (!in->is_st_session) {
2657 pthread_mutex_lock(&adev->lock);
2658 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
2659 ret = voice_extn_compress_voip_start_input_stream(in);
2660 else
2661 ret = start_input_stream(in);
2662 pthread_mutex_unlock(&adev->lock);
2663 if (ret != 0) {
2664 goto exit;
2665 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002666 }
2667 in->standby = 0;
2668 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002669
2670 if (in->pcm) {
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002671 if (audio_extn_ssr_get_enabled() &&
2672 audio_channel_count_from_in_mask(in->channel_mask) == 6)
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002673 ret = audio_extn_ssr_read(stream, buffer, bytes);
Mingming Yine62d7842013-10-25 16:26:03 -07002674 else if (audio_extn_compr_cap_usecase_supported(in->usecase))
2675 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002676 else if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY)
2677 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002678 else
2679 ret = pcm_read(in->pcm, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302680 if (ret < 0)
2681 ret = -errno;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002682 }
2683
2684 /*
2685 * Instead of writing zeroes here, we could trust the hardware
2686 * to always provide zeroes when muted.
2687 */
Pavan Chikkala63964842014-12-04 10:48:28 +05302688 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
2689 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002690 memset(buffer, 0, bytes);
2691
2692exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302693 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302694 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05302695 if (-ENETRESET == ret) {
Bharath Ramachandramurthy837535b2015-02-05 14:27:59 -08002696 /* CPE SSR results in kernel returning ENETRESET for sound trigger
2697 session reading on LAB data. In this case do not set sound card state
2698 offline, instead mark this sound trigger session inactive to avoid
2699 further reading of LAB data from CPE driver. Marking the session
2700 inactive handles both CPE and ADSP SSR for sound trigger session */
2701 if (!in->is_st_session)
2702 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2703 else
2704 in->is_st_session_active = false;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302705 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002706 pthread_mutex_unlock(&in->lock);
2707
2708 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302709 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302710 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302711 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302712 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302713 in->standby = true;
2714 }
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302715 memset(buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002716 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002717 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002718 usleep(bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302719 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002720 }
2721 return bytes;
2722}
2723
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002724static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002725{
2726 return 0;
2727}
2728
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002729static int add_remove_audio_effect(const struct audio_stream *stream,
2730 effect_handle_t effect,
2731 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002732{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002733 struct stream_in *in = (struct stream_in *)stream;
2734 int status = 0;
2735 effect_descriptor_t desc;
2736
2737 status = (*effect)->get_descriptor(effect, &desc);
2738 if (status != 0)
2739 return status;
2740
2741 pthread_mutex_lock(&in->lock);
2742 pthread_mutex_lock(&in->dev->lock);
2743 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2744 in->enable_aec != enable &&
2745 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
2746 in->enable_aec = enable;
2747 if (!in->standby)
2748 select_devices(in->dev, in->usecase);
2749 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08002750 if (in->enable_ns != enable &&
2751 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
2752 in->enable_ns = enable;
2753 if (!in->standby)
2754 select_devices(in->dev, in->usecase);
2755 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002756 pthread_mutex_unlock(&in->dev->lock);
2757 pthread_mutex_unlock(&in->lock);
2758
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002759 return 0;
2760}
2761
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002762static int in_add_audio_effect(const struct audio_stream *stream,
2763 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002764{
Eric Laurent994a6932013-07-17 11:51:42 -07002765 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002766 return add_remove_audio_effect(stream, effect, true);
2767}
2768
2769static int in_remove_audio_effect(const struct audio_stream *stream,
2770 effect_handle_t effect)
2771{
Eric Laurent994a6932013-07-17 11:51:42 -07002772 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002773 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002774}
2775
2776static int adev_open_output_stream(struct audio_hw_device *dev,
2777 audio_io_handle_t handle,
2778 audio_devices_t devices,
2779 audio_output_flags_t flags,
2780 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002781 struct audio_stream_out **stream_out,
2782 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002783{
2784 struct audio_device *adev = (struct audio_device *)dev;
2785 struct stream_out *out;
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08002786 int i, ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002787 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002788
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002789 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302790
2791 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2792 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
2793 ALOGE(" sound card is not active rejecting compress output open request");
2794 return -EINVAL;
2795 }
2796
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002797 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
2798
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302799 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
2800 stream_handle(%p)",__func__, config->sample_rate, config->channel_mask,
2801 devices, flags, &out->stream);
2802
2803
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08002804 if (!out) {
2805 return -ENOMEM;
2806 }
2807
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002808 if (devices == AUDIO_DEVICE_NONE)
2809 devices = AUDIO_DEVICE_OUT_SPEAKER;
2810
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002811 out->flags = flags;
2812 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07002813 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002814 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002815 out->sample_rate = config->sample_rate;
2816 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
2817 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07002818 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002819 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08002820 out->non_blocking = 0;
2821 out->use_small_bufs = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002822
2823 /* Init use case and pcm_config */
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002824 if ((out->flags == AUDIO_OUTPUT_FLAG_DIRECT) &&
2825 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
2826 out->devices & AUDIO_DEVICE_OUT_PROXY)) {
2827
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002828 pthread_mutex_lock(&adev->lock);
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002829 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
2830 ret = read_hdmi_channel_masks(out);
2831
2832 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
2833 ret = audio_extn_read_afe_proxy_channel_masks(out);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002834 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002835 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002836 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002837
2838 if (config->sample_rate == 0)
2839 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2840 if (config->channel_mask == 0)
2841 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
2842
2843 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002844 out->sample_rate = config->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002845 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
2846 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002847 out->config.rate = config->sample_rate;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002848 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002849 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002850 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2851 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08002852 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002853 ret = voice_extn_compress_voip_open_output_stream(out);
2854 if (ret != 0) {
2855 ALOGE("%s: Compress voip output cannot be opened, error:%d",
2856 __func__, ret);
2857 goto error_open;
2858 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002859 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
2860 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
2861 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
2862 ALOGE("%s: Unsupported Offload information", __func__);
2863 ret = -EINVAL;
2864 goto error_open;
2865 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002866
2867 if ((out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
2868 ((audio_extn_dolby_is_passthrough_stream(out->flags)))) {
2869 ALOGV("read and update_pass through formats");
2870 ret = audio_extn_dolby_update_passt_formats(adev, out);
2871 if(ret != 0) {
2872 goto error_open;
2873 }
2874 if(config->offload_info.format == 0)
2875 config->offload_info.format = out->supported_formats[0];
2876 }
2877
Mingming Yin90310102013-11-13 16:57:00 -08002878 if (!is_supported_format(config->offload_info.format) &&
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002879 !audio_extn_is_dolby_format(config->offload_info.format)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002880 ALOGE("%s: Unsupported audio format", __func__);
2881 ret = -EINVAL;
2882 goto error_open;
2883 }
2884
2885 out->compr_config.codec = (struct snd_codec *)
2886 calloc(1, sizeof(struct snd_codec));
2887
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002888 if (!out->compr_config.codec) {
2889 ret = -ENOMEM;
2890 goto error_open;
2891 }
2892
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002893 out->usecase = get_offload_usecase(adev);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002894 if (config->offload_info.channel_mask)
2895 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002896 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002897 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002898 config->offload_info.channel_mask = config->channel_mask;
2899 }
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002900 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002901 out->sample_rate = config->offload_info.sample_rate;
2902
2903 out->stream.set_callback = out_set_callback;
2904 out->stream.pause = out_pause;
2905 out->stream.resume = out_resume;
2906 out->stream.drain = out_drain;
2907 out->stream.flush = out_flush;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002908 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002909
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002910 if (audio_extn_is_dolby_format(config->offload_info.format))
Mingming Yin90310102013-11-13 16:57:00 -08002911 out->compr_config.codec->id =
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002912 audio_extn_dolby_get_snd_codec_id(adev, out,
2913 config->offload_info.format);
Mingming Yin90310102013-11-13 16:57:00 -08002914 else
2915 out->compr_config.codec->id =
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002916 get_snd_codec_id(config->offload_info.format);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002917 if (audio_is_offload_pcm(config->offload_info.format)) {
2918 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002919 platform_get_pcm_offload_buffer_size(&config->offload_info);
2920 } else if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
2921 out->compr_config.fragment_size =
2922 audio_extn_dolby_get_passt_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002923 } else {
2924 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002925 platform_get_compress_offload_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002926 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002927 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
2928 out->compr_config.codec->sample_rate =
2929 compress_get_alsa_rate(config->offload_info.sample_rate);
2930 out->compr_config.codec->bit_rate =
2931 config->offload_info.bit_rate;
2932 out->compr_config.codec->ch_in =
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002933 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002934 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002935 out->bit_width = PCM_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002936 /*TODO: Do we need to change it for passthrough */
2937 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002938
Mingming Yin3ee55c62014-08-04 14:23:35 -07002939 if (config->offload_info.format == AUDIO_FORMAT_AAC)
2940 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002941 if (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD)
2942 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002943 if(config->offload_info.format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002944 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
2945
Mingming Yin3ee55c62014-08-04 14:23:35 -07002946 if (out->bit_width == 24) {
2947 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
2948 }
2949
Amit Shekhar6f461b12014-08-01 14:52:58 -07002950 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Mingming Yinc9efb4f2014-09-19 12:16:36 -07002951 out->compr_config.codec->options.flac_dec.sample_size = PCM_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002952
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002953 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
2954 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002955
Alexy Josephaa54c872014-12-03 02:46:47 -08002956 if (config->offload_info.use_small_bufs) {
2957 //this flag is set from framework only if its for PCM formats
2958 //no need to check for PCM format again
2959 out->non_blocking = 0;
2960 out->use_small_bufs = true;
2961 ALOGI("Keep write blocking for small buff: non_blockling %d",
2962 out->non_blocking);
2963 }
2964
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002965 out->send_new_metadata = 1;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08002966 out->offload_state = OFFLOAD_STATE_IDLE;
2967 out->playback_started = 0;
2968
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002969 audio_extn_dts_create_state_notifier_node(out->usecase);
2970
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002971 create_offload_callback_thread(out);
2972 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
2973 __func__, config->offload_info.version,
2974 config->offload_info.bit_rate);
Krishnankutty Kolathappillyb165a8a2014-01-07 11:25:51 -08002975 //Decide if we need to use gapless mode by default
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -08002976 check_and_set_gapless_mode(adev);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07002977 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
2978 ret = voice_check_and_set_incall_music_usecase(adev, out);
2979 if (ret != 0) {
2980 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
2981 __func__, ret);
2982 goto error_open;
2983 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002984 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
2985 if (config->sample_rate == 0)
2986 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2987 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
2988 config->sample_rate != 8000) {
2989 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2990 ret = -EINVAL;
2991 goto error_open;
2992 }
2993 out->sample_rate = config->sample_rate;
2994 out->config.rate = config->sample_rate;
2995 if (config->format == AUDIO_FORMAT_DEFAULT)
2996 config->format = AUDIO_FORMAT_PCM_16_BIT;
2997 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
2998 config->format = AUDIO_FORMAT_PCM_16_BIT;
2999 ret = -EINVAL;
3000 goto error_open;
3001 }
3002 out->format = config->format;
3003 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
3004 out->config = pcm_config_afe_proxy_playback;
3005 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003006 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003007 format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003008 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
3009 out->config = pcm_config_low_latency;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003010 out->sample_rate = out->config.rate;
Mingming Yin08c7e312015-03-16 18:10:58 -07003011 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
3012 format = AUDIO_FORMAT_PCM_16_BIT;
3013 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
3014 out->config = pcm_config_deep_buffer;
3015 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003016 } else {
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003017 /* primary path is the default path selected if no other outputs are available/suitable */
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003018 format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003019 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
Mingming Yin08c7e312015-03-16 18:10:58 -07003020 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003021 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003022 }
3023
Amit Shekhar1d896042014-10-03 13:16:09 -07003024 ALOGV("%s devices %d,flags %x, format %x, out->sample_rate %d, out->bit_width %d",
3025 __func__, devices, flags, format, out->sample_rate, out->bit_width);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003026 /* TODO remove this hardcoding and check why width is zero*/
3027 if (out->bit_width == 0)
3028 out->bit_width = 16;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003029 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
3030 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07003031 devices, flags, format, out->sample_rate,
Amit Shekhar6f461b12014-08-01 14:52:58 -07003032 out->bit_width, &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003033 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
3034 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
3035 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003036 if(adev->primary_output == NULL)
3037 adev->primary_output = out;
3038 else {
3039 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003040 ret = -EEXIST;
3041 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003042 }
3043 }
3044
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003045 /* Check if this usecase is already existing */
3046 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07003047 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
3048 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003049 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003050 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003051 ret = -EEXIST;
3052 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003053 }
3054 pthread_mutex_unlock(&adev->lock);
3055
3056 out->stream.common.get_sample_rate = out_get_sample_rate;
3057 out->stream.common.set_sample_rate = out_set_sample_rate;
3058 out->stream.common.get_buffer_size = out_get_buffer_size;
3059 out->stream.common.get_channels = out_get_channels;
3060 out->stream.common.get_format = out_get_format;
3061 out->stream.common.set_format = out_set_format;
3062 out->stream.common.standby = out_standby;
3063 out->stream.common.dump = out_dump;
3064 out->stream.common.set_parameters = out_set_parameters;
3065 out->stream.common.get_parameters = out_get_parameters;
3066 out->stream.common.add_audio_effect = out_add_audio_effect;
3067 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3068 out->stream.get_latency = out_get_latency;
3069 out->stream.set_volume = out_set_volume;
3070 out->stream.write = out_write;
3071 out->stream.get_render_position = out_get_render_position;
3072 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003073 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003074
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003075 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003076 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003077 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003078
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003079 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
3080 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3081
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003082 config->format = out->stream.common.get_format(&out->stream.common);
3083 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3084 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3085
3086 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303087 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
3088 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003089
3090 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
3091 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3092 popcount(out->channel_mask), out->playback_started);
3093
Eric Laurent994a6932013-07-17 11:51:42 -07003094 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003095 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003096
3097error_open:
3098 free(out);
3099 *stream_out = NULL;
3100 ALOGD("%s: exit: ret %d", __func__, ret);
3101 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003102}
3103
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003104static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003105 struct audio_stream_out *stream)
3106{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003107 struct stream_out *out = (struct stream_out *)stream;
3108 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003109 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003110
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303111 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
3112
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003113 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303114 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003115 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303116 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003117 if(ret != 0)
3118 ALOGE("%s: Compress voip output cannot be closed, error:%d",
3119 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003120 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003121 out_standby(&stream->common);
3122
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003123 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003124 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003125 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003126 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003127 if (out->compr_config.codec != NULL)
3128 free(out->compr_config.codec);
3129 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003130
3131 if (adev->voice_tx_output == out)
3132 adev->voice_tx_output = NULL;
3133
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003134 pthread_cond_destroy(&out->cond);
3135 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003136 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003137 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003138}
3139
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003140static void close_compress_sessions(struct audio_device *adev)
3141{
Mingming Yin7b762e72015-03-04 13:47:32 -08003142 struct stream_out *out;
3143 struct listnode *node;
3144 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003145 pthread_mutex_lock(&adev->lock);
Mingming Yin7b762e72015-03-04 13:47:32 -08003146 list_for_each(node, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003147 usecase = node_to_item(node, struct audio_usecase, list);
Mingming Yin7b762e72015-03-04 13:47:32 -08003148 if (usecase && is_offload_usecase(usecase->id)) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003149 if (usecase && usecase->stream.out) {
3150 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
3151 out = usecase->stream.out;
3152 pthread_mutex_unlock(&adev->lock);
3153 out_standby(&out->stream.common);
3154 pthread_mutex_lock(&adev->lock);
3155 }
3156 }
3157 }
3158 pthread_mutex_unlock(&adev->lock);
3159}
3160
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003161static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3162{
3163 struct audio_device *adev = (struct audio_device *)dev;
3164 struct str_parms *parms;
3165 char *str;
3166 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003167 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003168 int ret;
3169 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003170
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003171 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003172 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003173
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303174 if (!parms)
3175 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003176 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
3177 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05303178 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303179 if (strstr(snd_card_status, "OFFLINE")) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303180 struct listnode *node;
3181 struct audio_usecase *usecase;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303182 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303183 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003184 //close compress sessions on OFFLINE status
3185 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303186 } else if (strstr(snd_card_status, "ONLINE")) {
3187 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303188 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303189 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303190 }
3191
3192 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003193 status = voice_set_parameters(adev, parms);
3194 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003195 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003196
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003197 status = platform_set_parameters(adev->platform, parms);
3198 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003199 goto done;
3200
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003201 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3202 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07003203 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003204 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3205 adev->bluetooth_nrec = true;
3206 else
3207 adev->bluetooth_nrec = false;
3208 }
3209
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003210 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3211 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003212 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3213 adev->screen_off = false;
3214 else
3215 adev->screen_off = true;
3216 }
3217
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003218 ret = str_parms_get_int(parms, "rotation", &val);
3219 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003220 bool reverse_speakers = false;
3221 switch(val) {
3222 // FIXME: note that the code below assumes that the speakers are in the correct placement
3223 // relative to the user when the device is rotated 90deg from its default rotation. This
3224 // assumption is device-specific, not platform-specific like this code.
3225 case 270:
3226 reverse_speakers = true;
3227 break;
3228 case 0:
3229 case 90:
3230 case 180:
3231 break;
3232 default:
3233 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003234 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003235 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003236 if (status == 0) {
3237 if (adev->speaker_lr_swap != reverse_speakers) {
3238 adev->speaker_lr_swap = reverse_speakers;
3239 // only update the selected device if there is active pcm playback
3240 struct audio_usecase *usecase;
3241 struct listnode *node;
3242 list_for_each(node, &adev->usecase_list) {
3243 usecase = node_to_item(node, struct audio_usecase, list);
3244 if (usecase->type == PCM_PLAYBACK) {
3245 select_devices(adev, usecase->id);
3246 break;
3247 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003248 }
3249 }
3250 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003251 }
3252
Mingming Yin514a8bc2014-07-29 15:22:21 -07003253 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
3254 if (ret >= 0) {
3255 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3256 adev->bt_wb_speech_enabled = true;
3257 else
3258 adev->bt_wb_speech_enabled = false;
3259 }
3260
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003261 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
3262 if (ret >= 0) {
3263 val = atoi(value);
3264 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3265 ALOGV("cache new edid");
3266 platform_cache_edid(adev->platform);
3267 }
3268 }
3269
3270 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
3271 if (ret >= 0) {
3272 val = atoi(value);
3273 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3274 ALOGV("invalidate cached edid");
3275 platform_invalidate_edid(adev->platform);
3276 }
3277 }
3278
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003279 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003280
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003281done:
3282 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003283 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303284error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003285 ALOGV("%s: exit with code(%d)", __func__, status);
3286 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003287}
3288
3289static char* adev_get_parameters(const struct audio_hw_device *dev,
3290 const char *keys)
3291{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003292 struct audio_device *adev = (struct audio_device *)dev;
3293 struct str_parms *reply = str_parms_create();
3294 struct str_parms *query = str_parms_create_str(keys);
3295 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05303296 char value[256] = {0};
3297 int ret = 0;
3298
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003299 if (!query || !reply) {
3300 ALOGE("adev_get_parameters: failed to create query or reply");
3301 return NULL;
3302 }
3303
Naresh Tannirud7205b62014-06-20 02:54:48 +05303304 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
3305 sizeof(value));
3306 if (ret >=0) {
3307 int val = 1;
3308 pthread_mutex_lock(&adev->snd_card_status.lock);
3309 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
3310 val = 0;
3311 pthread_mutex_unlock(&adev->snd_card_status.lock);
3312 str_parms_add_int(reply, "SND_CARD_STATUS", val);
3313 goto exit;
3314 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003315
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003316 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003317 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08003318 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003319 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05303320 pthread_mutex_unlock(&adev->lock);
3321
Naresh Tannirud7205b62014-06-20 02:54:48 +05303322exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003323 str = str_parms_to_str(reply);
3324 str_parms_destroy(query);
3325 str_parms_destroy(reply);
3326
3327 ALOGV("%s: exit: returns - %s", __func__, str);
3328 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003329}
3330
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003331static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003332{
3333 return 0;
3334}
3335
3336static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
3337{
Haynes Mathew George5191a852013-09-11 14:19:36 -07003338 int ret;
3339 struct audio_device *adev = (struct audio_device *)dev;
3340 pthread_mutex_lock(&adev->lock);
3341 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07003342 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07003343 pthread_mutex_unlock(&adev->lock);
3344 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003345}
3346
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003347static int adev_set_master_volume(struct audio_hw_device *dev __unused,
3348 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003349{
3350 return -ENOSYS;
3351}
3352
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003353static int adev_get_master_volume(struct audio_hw_device *dev __unused,
3354 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003355{
3356 return -ENOSYS;
3357}
3358
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003359static int adev_set_master_mute(struct audio_hw_device *dev __unused,
3360 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003361{
3362 return -ENOSYS;
3363}
3364
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003365static int adev_get_master_mute(struct audio_hw_device *dev __unused,
3366 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003367{
3368 return -ENOSYS;
3369}
3370
3371static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
3372{
3373 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003374
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003375 pthread_mutex_lock(&adev->lock);
3376 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003377 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003378 adev->mode = mode;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003379 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
3380 voice_is_in_call(adev)) {
3381 voice_stop_call(adev);
3382 adev->current_call_output = NULL;
3383 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003384 }
3385 pthread_mutex_unlock(&adev->lock);
3386 return 0;
3387}
3388
3389static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
3390{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003391 int ret;
3392
3393 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003394 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003395 ret = voice_set_mic_mute((struct audio_device *)dev, state);
3396 pthread_mutex_unlock(&adev->lock);
3397
3398 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003399}
3400
3401static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
3402{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003403 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003404 return 0;
3405}
3406
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003407static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003408 const struct audio_config *config)
3409{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003410 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003411
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003412 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
3413 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003414}
3415
3416static int adev_open_input_stream(struct audio_hw_device *dev,
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003417 audio_io_handle_t handle __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003418 audio_devices_t devices,
3419 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003420 struct audio_stream_in **stream_in,
3421 audio_input_flags_t flags __unused,
3422 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003423 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003424{
3425 struct audio_device *adev = (struct audio_device *)dev;
3426 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003427 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003428 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003429 bool is_low_latency = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303430
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003431 *stream_in = NULL;
3432 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
3433 return -EINVAL;
3434
3435 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003436
3437 if (!in) {
3438 ALOGE("failed to allocate input stream");
3439 return -ENOMEM;
3440 }
3441
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303442 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003443 stream_handle(%p) io_handle(%d) source(%d)",__func__, config->sample_rate, config->channel_mask,
3444 devices, &in->stream, handle, source);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003445
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003446 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
3447
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003448 in->stream.common.get_sample_rate = in_get_sample_rate;
3449 in->stream.common.set_sample_rate = in_set_sample_rate;
3450 in->stream.common.get_buffer_size = in_get_buffer_size;
3451 in->stream.common.get_channels = in_get_channels;
3452 in->stream.common.get_format = in_get_format;
3453 in->stream.common.set_format = in_set_format;
3454 in->stream.common.standby = in_standby;
3455 in->stream.common.dump = in_dump;
3456 in->stream.common.set_parameters = in_set_parameters;
3457 in->stream.common.get_parameters = in_get_parameters;
3458 in->stream.common.add_audio_effect = in_add_audio_effect;
3459 in->stream.common.remove_audio_effect = in_remove_audio_effect;
3460 in->stream.set_gain = in_set_gain;
3461 in->stream.read = in_read;
3462 in->stream.get_input_frames_lost = in_get_input_frames_lost;
3463
3464 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003465 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003466 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003467 in->standby = 1;
3468 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003469 in->capture_handle = handle;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003470
3471 /* Update config params with the requested sample rate and channels */
3472 in->usecase = USECASE_AUDIO_RECORD;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003473 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
3474 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
3475 is_low_latency = true;
3476#if LOW_LATENCY_CAPTURE_USE_CASE
3477 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
3478#endif
3479 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003480 in->config = pcm_config_audio_capture;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003481 in->config.rate = config->sample_rate;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003482 in->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003483
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003484 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
Pavan Chikkalac862f712014-12-17 16:45:10 +05303485 if (adev->mode != AUDIO_MODE_IN_CALL) {
3486 ret = -EINVAL;
3487 goto err_open;
3488 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003489 if (config->sample_rate == 0)
3490 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3491 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3492 config->sample_rate != 8000) {
3493 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3494 ret = -EINVAL;
3495 goto err_open;
3496 }
3497 if (config->format == AUDIO_FORMAT_DEFAULT)
3498 config->format = AUDIO_FORMAT_PCM_16_BIT;
3499 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3500 config->format = AUDIO_FORMAT_PCM_16_BIT;
3501 ret = -EINVAL;
3502 goto err_open;
3503 }
3504
3505 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
3506 in->config = pcm_config_afe_proxy_record;
3507 in->config.channels = channel_count;
3508 in->config.rate = config->sample_rate;
3509 } else if (channel_count == 6) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003510 if(audio_extn_ssr_get_enabled()) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003511 if(audio_extn_ssr_init(in)) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003512 ALOGE("%s: audio_extn_ssr_init failed", __func__);
3513 ret = -EINVAL;
3514 goto err_open;
3515 }
3516 } else {
Mingming Yin3cf99da2014-09-16 17:41:33 -07003517 ALOGW("%s: surround sound recording is not supported", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003518 }
Mingming Yine62d7842013-10-25 16:26:03 -07003519 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003520 audio_extn_compr_cap_format_supported(config->format) &&
3521 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003522 audio_extn_compr_cap_init(in);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003523 } else {
3524 in->config.channels = channel_count;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003525 frame_size = audio_stream_in_frame_size(&in->stream);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003526 buffer_size = get_input_buffer_size(config->sample_rate,
3527 config->format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003528 channel_count,
3529 is_low_latency);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003530 in->config.period_size = buffer_size / frame_size;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003531 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3532 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3533 (voice_extn_compress_voip_is_format_supported(in->format)) &&
3534 (in->config.rate == 8000 || in->config.rate == 16000) &&
3535 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
3536 voice_extn_compress_voip_open_input_stream(in);
3537 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003538 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003539
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003540 /* This stream could be for sound trigger lab,
3541 get sound trigger pcm if present */
3542 audio_extn_sound_trigger_check_and_get_session(in);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05303543 audio_extn_perf_lock_init();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003544
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003545 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07003546 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003547 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003548
3549err_open:
3550 free(in);
3551 *stream_in = NULL;
3552 return ret;
3553}
3554
3555static void adev_close_input_stream(struct audio_hw_device *dev,
3556 struct audio_stream_in *stream)
3557{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003558 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003559 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003560 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303561
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303562 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003563
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05303564 /* Disable echo reference while closing input stream */
3565 platform_set_echo_reference(adev->platform, false);
3566
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003567 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303568 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003569 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303570 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003571 if (ret != 0)
3572 ALOGE("%s: Compress voip input cannot be closed, error:%d",
3573 __func__, ret);
3574 } else
3575 in_standby(&stream->common);
3576
Mingming Yin7b762e72015-03-04 13:47:32 -08003577 if (audio_extn_ssr_get_enabled() &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003578 (audio_channel_count_from_in_mask(in->channel_mask) == 6)) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003579 audio_extn_ssr_deinit();
3580 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003581
Mingming Yine62d7842013-10-25 16:26:03 -07003582 if(audio_extn_compr_cap_enabled() &&
3583 audio_extn_compr_cap_format_supported(in->config.format))
3584 audio_extn_compr_cap_deinit();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003585
3586 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003587 return;
3588}
3589
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003590static int adev_dump(const audio_hw_device_t *device __unused,
3591 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003592{
3593 return 0;
3594}
3595
3596static int adev_close(hw_device_t *device)
3597{
3598 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07003599
3600 if (!adev)
3601 return 0;
3602
3603 pthread_mutex_lock(&adev_init_lock);
3604
3605 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003606 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08003607 audio_extn_listen_deinit(adev);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003608 audio_extn_utils_release_streams_output_cfg_list(&adev->streams_output_cfg_list);
Kiran Kandi910e1862013-10-29 13:29:42 -07003609 audio_route_free(adev->audio_route);
3610 free(adev->snd_dev_ref_cnt);
3611 platform_deinit(adev->platform);
Kiran Kandi910e1862013-10-29 13:29:42 -07003612 free(device);
3613 adev = NULL;
3614 }
3615 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003616 return 0;
3617}
3618
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003619/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
3620 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
3621 * just that it _might_ work.
3622 */
3623static int period_size_is_plausible_for_low_latency(int period_size)
3624{
3625 switch (period_size) {
3626 case 160:
3627 case 240:
3628 case 320:
3629 case 480:
3630 return 1;
3631 default:
3632 return 0;
3633 }
3634}
3635
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003636static int adev_open(const hw_module_t *module, const char *name,
3637 hw_device_t **device)
3638{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003639 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003640
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003641 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003642 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
3643
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003644 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07003645 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003646 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07003647 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003648 ALOGD("%s: returning existing instance of adev", __func__);
3649 ALOGD("%s: exit", __func__);
3650 pthread_mutex_unlock(&adev_init_lock);
3651 return 0;
3652 }
3653
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003654 adev = calloc(1, sizeof(struct audio_device));
3655
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003656 if (!adev) {
3657 pthread_mutex_unlock(&adev_init_lock);
3658 return -ENOMEM;
3659 }
3660
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003661 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
3662
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003663 adev->device.common.tag = HARDWARE_DEVICE_TAG;
3664 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
3665 adev->device.common.module = (struct hw_module_t *)module;
3666 adev->device.common.close = adev_close;
3667
3668 adev->device.init_check = adev_init_check;
3669 adev->device.set_voice_volume = adev_set_voice_volume;
3670 adev->device.set_master_volume = adev_set_master_volume;
3671 adev->device.get_master_volume = adev_get_master_volume;
3672 adev->device.set_master_mute = adev_set_master_mute;
3673 adev->device.get_master_mute = adev_get_master_mute;
3674 adev->device.set_mode = adev_set_mode;
3675 adev->device.set_mic_mute = adev_set_mic_mute;
3676 adev->device.get_mic_mute = adev_get_mic_mute;
3677 adev->device.set_parameters = adev_set_parameters;
3678 adev->device.get_parameters = adev_get_parameters;
3679 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
3680 adev->device.open_output_stream = adev_open_output_stream;
3681 adev->device.close_output_stream = adev_close_output_stream;
3682 adev->device.open_input_stream = adev_open_input_stream;
3683 adev->device.close_input_stream = adev_close_input_stream;
3684 adev->device.dump = adev_dump;
3685
3686 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003687 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08003688 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003689 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003690 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003691 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08003692 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07003693 /* adev->cur_hdmi_channels = 0; by calloc() */
Mingming Yin3ee55c62014-08-04 14:23:35 -07003694 adev->cur_codec_backend_samplerate = CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
3695 adev->cur_codec_backend_bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Eric Laurentb23d5282013-05-14 15:27:20 -07003696 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003697 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003698 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08003699 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003700 adev->offload_usecases_state = 0;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303701
3702 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
3703 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003704 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07003705 adev->platform = platform_init(adev);
3706 if (!adev->platform) {
3707 free(adev->snd_dev_ref_cnt);
3708 free(adev);
3709 ALOGE("%s: Failed to init platform data, aborting.", __func__);
3710 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08003711 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07003712 return -EINVAL;
3713 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003714
Naresh Tanniru4c630392014-05-12 01:05:52 +05303715 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
3716
Eric Laurentc4aef752013-09-12 17:45:53 -07003717 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
3718 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
3719 if (adev->visualizer_lib == NULL) {
3720 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
3721 } else {
3722 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
3723 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003724 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003725 "visualizer_hal_start_output");
3726 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003727 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003728 "visualizer_hal_stop_output");
3729 }
3730 }
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08003731 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003732 audio_extn_sound_trigger_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07003733
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003734 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
3735 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
3736 if (adev->offload_effects_lib == NULL) {
3737 ALOGE("%s: DLOPEN failed for %s", __func__,
3738 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3739 } else {
3740 ALOGV("%s: DLOPEN successful for %s", __func__,
3741 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3742 adev->offload_effects_start_output =
3743 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3744 "offload_effects_bundle_hal_start_output");
3745 adev->offload_effects_stop_output =
3746 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3747 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003748 adev->offload_effects_set_hpx_state =
3749 (int (*)(bool))dlsym(adev->offload_effects_lib,
3750 "offload_effects_bundle_set_hpx_state");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003751 }
3752 }
3753
Mingming Yin514a8bc2014-07-29 15:22:21 -07003754 adev->bt_wb_speech_enabled = false;
3755
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07003756 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003757 *device = &adev->device.common;
3758
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003759 audio_extn_utils_update_streams_output_cfg_list(adev->platform, adev->mixer,
3760 &adev->streams_output_cfg_list);
3761
Kiran Kandi910e1862013-10-29 13:29:42 -07003762 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003763
3764 char value[PROPERTY_VALUE_MAX];
3765 int trial;
3766 if (property_get("audio_hal.period_size", value, NULL) > 0) {
3767 trial = atoi(value);
3768 if (period_size_is_plausible_for_low_latency(trial)) {
3769 pcm_config_low_latency.period_size = trial;
3770 pcm_config_low_latency.start_threshold = trial / 4;
3771 pcm_config_low_latency.avail_min = trial / 4;
3772 configured_low_latency_capture_period_size = trial;
3773 }
3774 }
3775 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
3776 trial = atoi(value);
3777 if (period_size_is_plausible_for_low_latency(trial)) {
3778 configured_low_latency_capture_period_size = trial;
3779 }
3780 }
3781
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003782 pthread_mutex_unlock(&adev_init_lock);
3783
Eric Laurent994a6932013-07-17 11:51:42 -07003784 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003785 return 0;
3786}
3787
3788static struct hw_module_methods_t hal_module_methods = {
3789 .open = adev_open,
3790};
3791
3792struct audio_module HAL_MODULE_INFO_SYM = {
3793 .common = {
3794 .tag = HARDWARE_MODULE_TAG,
3795 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
3796 .hal_api_version = HARDWARE_HAL_API_VERSION,
3797 .id = AUDIO_HARDWARE_MODULE_ID,
3798 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08003799 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003800 .methods = &hal_module_methods,
3801 },
3802};