blob: 32eb4594572afc9ead040c713eb2cb25b904ff7a [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05302 * Copyright (c) 2013-2017, 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"
Haynes Mathew George5beddd42016-06-27 18:33:40 -070039#define ATRACE_TAG (ATRACE_TAG_AUDIO|ATRACE_TAG_HAL)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080040/*#define LOG_NDEBUG 0*/
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070041/*#define VERY_VERY_VERBOSE_LOGGING*/
42#ifdef VERY_VERY_VERBOSE_LOGGING
43#define ALOGVV ALOGV
44#else
45#define ALOGVV(a...) do { } while(0)
46#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080047
48#include <errno.h>
49#include <pthread.h>
50#include <stdint.h>
51#include <sys/time.h>
52#include <stdlib.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080053#include <math.h>
Eric Laurentc4aef752013-09-12 17:45:53 -070054#include <dlfcn.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070055#include <sys/resource.h>
56#include <sys/prctl.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080057
58#include <cutils/log.h>
Haynes Mathew George5beddd42016-06-27 18:33:40 -070059#include <cutils/trace.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080060#include <cutils/str_parms.h>
61#include <cutils/properties.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070062#include <cutils/atomic.h>
63#include <cutils/sched_policy.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080064
Eric Laurentb23d5282013-05-14 15:27:20 -070065#include <hardware/audio_effect.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070066#include <system/thread_defs.h>
Haynes Mathew George16081042017-05-31 17:16:49 -070067#include <tinyalsa/asoundlib.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070068#include <audio_effects/effect_aec.h>
69#include <audio_effects/effect_ns.h>
Ashish Jainf1eaa582016-05-23 20:54:24 +053070#include <audio_utils/format.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080071#include "audio_hw.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070072#include "platform_api.h"
73#include <platform.h>
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -070074#include "audio_extn.h"
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080075#include "voice_extn.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080076
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070077#include "sound/compress_params.h"
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080078#include "sound/asound.h"
ApurupaPattapu2e084df2013-12-18 15:47:59 -080079
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +053080#ifdef DYNAMIC_LOG_ENABLED
81#include <log_xml_parser.h>
82#define LOG_MASK HAL_MOD_FILE_AUDIO_HW
83#include <log_utils.h>
84#endif
85
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070086#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 4
Ashish Jain5106d362016-05-11 19:23:33 +053087/*DIRECT PCM has same buffer sizes as DEEP Buffer*/
88#define DIRECT_PCM_NUM_FRAGMENTS 2
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070089#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
Vikram Panduranga93f080e2017-06-07 18:16:14 -070090#define VOIP_PLAYBACK_VOLUME_MAX 0x2000
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +053091#define DSD_VOLUME_MIN_DB (-110)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070092
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -070093#define PROXY_OPEN_RETRY_COUNT 100
94#define PROXY_OPEN_WAIT_TIME 20
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080095
Mingming Yin08c7e312015-03-16 18:10:58 -070096#ifdef USE_LL_AS_PRIMARY_OUTPUT
97#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_LOW_LATENCY
98#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_low_latency
99#else
Haynes Mathew Georgebf143712013-12-03 13:02:53 -0800100#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_DEEP_BUFFER
Mingming Yin08c7e312015-03-16 18:10:58 -0700101#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_deep_buffer
102#endif
Haynes Mathew Georgebf143712013-12-03 13:02:53 -0800103
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700104#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700105#define DEFAULT_VOIP_BUF_DURATION_MS 20
106#define DEFAULT_VOIP_BIT_DEPTH_BYTE sizeof(int16_t)
107#define DEFAULT_VOIP_SAMP_RATE 48000
108
109#define VOIP_IO_BUF_SIZE(SR, DURATION_MS, BIT_DEPTH) (SR)/1000 * DURATION_MS * BIT_DEPTH
110
111struct pcm_config default_pcm_config_voip_copp = {
112 .channels = 1,
113 .rate = DEFAULT_VOIP_SAMP_RATE, /* changed when the stream is opened */
114 .period_size = VOIP_IO_BUF_SIZE(DEFAULT_VOIP_SAMP_RATE, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2,
115 .period_count = 2,
116 .format = PCM_FORMAT_S16_LE,
117};
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700118
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700119static unsigned int configured_low_latency_capture_period_size =
120 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
121
Haynes Mathew George16081042017-05-31 17:16:49 -0700122#define MMAP_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
123#define MMAP_PERIOD_COUNT_MIN 32
124#define MMAP_PERIOD_COUNT_MAX 512
125#define MMAP_PERIOD_COUNT_DEFAULT (MMAP_PERIOD_COUNT_MAX)
126
Eric Laurentb23d5282013-05-14 15:27:20 -0700127struct pcm_config pcm_config_deep_buffer = {
128 .channels = 2,
129 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
130 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
131 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
132 .format = PCM_FORMAT_S16_LE,
133 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
134 .stop_threshold = INT_MAX,
135 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
136};
137
138struct pcm_config pcm_config_low_latency = {
139 .channels = 2,
140 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
141 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
142 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
143 .format = PCM_FORMAT_S16_LE,
144 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
145 .stop_threshold = INT_MAX,
146 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
147};
148
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700149static int af_period_multiplier = 4;
150struct pcm_config pcm_config_rt = {
151 .channels = 2,
152 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
153 .period_size = ULL_PERIOD_SIZE, //1 ms
154 .period_count = 512, //=> buffer size is 512ms
155 .format = PCM_FORMAT_S16_LE,
156 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
157 .stop_threshold = INT_MAX,
158 .silence_threshold = 0,
159 .silence_size = 0,
160 .avail_min = ULL_PERIOD_SIZE, //1 ms
161};
162
Eric Laurentb23d5282013-05-14 15:27:20 -0700163struct pcm_config pcm_config_hdmi_multi = {
164 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
165 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
166 .period_size = HDMI_MULTI_PERIOD_SIZE,
167 .period_count = HDMI_MULTI_PERIOD_COUNT,
168 .format = PCM_FORMAT_S16_LE,
169 .start_threshold = 0,
170 .stop_threshold = INT_MAX,
171 .avail_min = 0,
172};
173
Haynes Mathew George16081042017-05-31 17:16:49 -0700174struct pcm_config pcm_config_mmap_playback = {
175 .channels = 2,
176 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
177 .period_size = MMAP_PERIOD_SIZE,
178 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
179 .format = PCM_FORMAT_S16_LE,
180 .start_threshold = MMAP_PERIOD_SIZE*8,
181 .stop_threshold = INT32_MAX,
182 .silence_threshold = 0,
183 .silence_size = 0,
184 .avail_min = MMAP_PERIOD_SIZE, //1 ms
185};
186
Eric Laurentb23d5282013-05-14 15:27:20 -0700187struct pcm_config pcm_config_audio_capture = {
188 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -0700189 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
190 .format = PCM_FORMAT_S16_LE,
191};
192
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700193struct pcm_config pcm_config_audio_capture_rt = {
194 .channels = 2,
195 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
196 .period_size = ULL_PERIOD_SIZE,
197 .period_count = 512,
198 .format = PCM_FORMAT_S16_LE,
199 .start_threshold = 0,
200 .stop_threshold = INT_MAX,
201 .silence_threshold = 0,
202 .silence_size = 0,
203 .avail_min = ULL_PERIOD_SIZE, //1 ms
204};
205
Haynes Mathew George16081042017-05-31 17:16:49 -0700206struct pcm_config pcm_config_mmap_capture = {
207 .channels = 2,
208 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
209 .period_size = MMAP_PERIOD_SIZE,
210 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
211 .format = PCM_FORMAT_S16_LE,
212 .start_threshold = 0,
213 .stop_threshold = INT_MAX,
214 .silence_threshold = 0,
215 .silence_size = 0,
216 .avail_min = MMAP_PERIOD_SIZE, //1 ms
217};
218
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700219#define AFE_PROXY_CHANNEL_COUNT 2
220#define AFE_PROXY_SAMPLING_RATE 48000
221
222#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
223#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
224
225struct pcm_config pcm_config_afe_proxy_playback = {
226 .channels = AFE_PROXY_CHANNEL_COUNT,
227 .rate = AFE_PROXY_SAMPLING_RATE,
228 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
229 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
230 .format = PCM_FORMAT_S16_LE,
231 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
232 .stop_threshold = INT_MAX,
233 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
234};
235
236#define AFE_PROXY_RECORD_PERIOD_SIZE 768
237#define AFE_PROXY_RECORD_PERIOD_COUNT 4
238
239struct pcm_config pcm_config_afe_proxy_record = {
240 .channels = AFE_PROXY_CHANNEL_COUNT,
241 .rate = AFE_PROXY_SAMPLING_RATE,
242 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
243 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
244 .format = PCM_FORMAT_S16_LE,
245 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
246 .stop_threshold = INT_MAX,
247 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
248};
249
Ashish Jainf1eaa582016-05-23 20:54:24 +0530250#define AUDIO_MAX_PCM_FORMATS 7
251
252const uint32_t format_to_bitwidth_table[AUDIO_MAX_PCM_FORMATS] = {
253 [AUDIO_FORMAT_DEFAULT] = 0,
254 [AUDIO_FORMAT_PCM_16_BIT] = sizeof(uint16_t),
255 [AUDIO_FORMAT_PCM_8_BIT] = sizeof(uint8_t),
256 [AUDIO_FORMAT_PCM_32_BIT] = sizeof(uint32_t),
257 [AUDIO_FORMAT_PCM_8_24_BIT] = sizeof(uint32_t),
258 [AUDIO_FORMAT_PCM_FLOAT] = sizeof(float),
259 [AUDIO_FORMAT_PCM_24_BIT_PACKED] = sizeof(uint8_t) * 3,
260};
261
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800262const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700263 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
264 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -0700265 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
266 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700267 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
vivek mehta446c3962015-09-14 10:57:35 -0700268 //Enabled for Direct_PCM
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700269 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
270 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
271 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
272 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
273 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
274 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
275 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
276 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
Haynes Mathew George16081042017-05-31 17:16:49 -0700277 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
278 [USECASE_AUDIO_PLAYBACK_MMAP] = "mmap-playback",
vivek mehta0ea887a2015-08-26 14:01:20 -0700279
Eric Laurentb23d5282013-05-14 15:27:20 -0700280 [USECASE_AUDIO_RECORD] = "audio-record",
Mingming Yine62d7842013-10-25 16:26:03 -0700281 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Dhananjay Kumaree4d2002016-10-25 18:02:58 +0530282 [USECASE_AUDIO_RECORD_COMPRESS2] = "audio-record-compress2",
283 [USECASE_AUDIO_RECORD_COMPRESS3] = "audio-record-compress3",
284 [USECASE_AUDIO_RECORD_COMPRESS4] = "audio-record-compress4",
Eric Laurentb23d5282013-05-14 15:27:20 -0700285 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700286 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Haynes Mathew George16081042017-05-31 17:16:49 -0700287 [USECASE_AUDIO_RECORD_MMAP] = "mmap-record",
288
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800289 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800290 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700291 [USECASE_VOICE_CALL] = "voice-call",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700292
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700293 [USECASE_VOICE2_CALL] = "voice2-call",
294 [USECASE_VOLTE_CALL] = "volte-call",
295 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800296 [USECASE_VOWLAN_CALL] = "vowlan-call",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800297 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
298 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800299 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700300 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
301 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
302 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800303 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
304 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
305 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
306
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700307 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
308 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700309 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
310 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700311
312 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
313 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -0700314 [USECASE_AUDIO_PLAYBACK_EXT_DISP_SILENCE] = "silence-playback",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700315
Siddartha Shaik31b530e2017-05-19 15:26:33 +0530316 /* Transcode loopback cases */
317 [USECASE_AUDIO_TRANSCODE_LOOPBACK] = "audio-transcode-loopback",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700318
319 [USECASE_AUDIO_PLAYBACK_VOIP] = "audio-playback-voip",
320 [USECASE_AUDIO_RECORD_VOIP] = "audio-record-voip",
Varun Balaraje49253e2017-07-06 19:48:56 +0530321 /* For Interactive Audio Streams */
322 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1] = "audio-interactive-stream1",
323 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2] = "audio-interactive-stream2",
324 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3] = "audio-interactive-stream3",
325 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4] = "audio-interactive-stream4",
326 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5] = "audio-interactive-stream5",
327 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6] = "audio-interactive-stream6",
328 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7] = "audio-interactive-stream7",
329 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8] = "audio-interactive-stream8",
Garmond Leunge2433c32017-09-28 21:51:22 -0700330
331 [USECASE_AUDIO_EC_REF_LOOPBACK] = "ec-ref-audio-capture"
Eric Laurentb23d5282013-05-14 15:27:20 -0700332};
333
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700334static const audio_usecase_t offload_usecases[] = {
335 USECASE_AUDIO_PLAYBACK_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700336 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
337 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
338 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
339 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
340 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
341 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
342 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
343 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700344};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800345
Varun Balaraje49253e2017-07-06 19:48:56 +0530346static const audio_usecase_t interactive_usecases[] = {
347 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1,
348 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2,
349 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3,
350 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4,
351 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5,
352 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6,
353 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7,
354 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8,
355};
356
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800357#define STRING_TO_ENUM(string) { #string, string }
358
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800359struct string_to_enum {
360 const char *name;
361 uint32_t value;
362};
363
364static const struct string_to_enum out_channels_name_to_enum_table[] = {
365 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Mingming Yin3a941d42016-02-17 18:08:05 -0800366 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_2POINT1),
367 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),
368 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_SURROUND),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700369 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
Mingming Yin3a941d42016-02-17 18:08:05 -0800370 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
371 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_6POINT1),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800372 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
373};
374
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700375static const struct string_to_enum out_formats_name_to_enum_table[] = {
376 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
377 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
378 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
Ben Romberger1aaaf862017-04-06 17:49:46 -0700379 STRING_TO_ENUM(AUDIO_FORMAT_DOLBY_TRUEHD),
Mingming Yin3a941d42016-02-17 18:08:05 -0800380 STRING_TO_ENUM(AUDIO_FORMAT_DTS),
381 STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD),
Naresh Tanniru928f0862017-04-07 16:44:23 -0700382 STRING_TO_ENUM(AUDIO_FORMAT_IEC61937)
Mingming Yin3a941d42016-02-17 18:08:05 -0800383};
384
385//list of all supported sample rates by HDMI specification.
386static const int out_hdmi_sample_rates[] = {
387 32000, 44100, 48000, 88200, 96000, 176400, 192000,
388};
389
390static const struct string_to_enum out_hdmi_sample_rates_name_to_enum_table[] = {
391 STRING_TO_ENUM(32000),
392 STRING_TO_ENUM(44100),
393 STRING_TO_ENUM(48000),
394 STRING_TO_ENUM(88200),
395 STRING_TO_ENUM(96000),
396 STRING_TO_ENUM(176400),
397 STRING_TO_ENUM(192000),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700398};
399
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700400static struct audio_device *adev = NULL;
401static pthread_mutex_t adev_init_lock;
Kiran Kandi910e1862013-10-29 13:29:42 -0700402static unsigned int audio_device_ref_count;
vivek mehtab72d08d2016-04-29 03:16:47 -0700403//cache last MBDRC cal step level
404static int last_known_cal_step = -1 ;
Kiran Kandi910e1862013-10-29 13:29:42 -0700405
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530406static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore);
407static int out_set_compr_volume(struct audio_stream_out *stream, float left, float right);
Zhou Song2b8f28f2017-09-11 10:51:38 +0800408static int out_set_voip_volume(struct audio_stream_out *stream, float left, float right);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530409
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700410static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
411 int flags __unused)
412{
413 int dir = 0;
414 switch (uc_id) {
415 case USECASE_AUDIO_RECORD_LOW_LATENCY:
416 dir = 1;
417 case USECASE_AUDIO_PLAYBACK_ULL:
418 break;
419 default:
420 return false;
421 }
422
423 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
424 PCM_PLAYBACK : PCM_CAPTURE);
425 if (adev->adm_is_noirq_avail)
426 return adev->adm_is_noirq_avail(adev->adm_data,
427 adev->snd_card, dev_id, dir);
428 return false;
429}
430
431static void register_out_stream(struct stream_out *out)
432{
433 struct audio_device *adev = out->dev;
434 if (is_offload_usecase(out->usecase) ||
435 !adev->adm_register_output_stream)
436 return;
437
438 // register stream first for backward compatibility
439 adev->adm_register_output_stream(adev->adm_data,
440 out->handle,
441 out->flags);
442
443 if (!adev->adm_set_config)
444 return;
445
446 if (out->realtime)
447 adev->adm_set_config(adev->adm_data,
448 out->handle,
449 out->pcm, &out->config);
450}
451
452static void register_in_stream(struct stream_in *in)
453{
454 struct audio_device *adev = in->dev;
455 if (!adev->adm_register_input_stream)
456 return;
457
458 adev->adm_register_input_stream(adev->adm_data,
459 in->capture_handle,
460 in->flags);
461
462 if (!adev->adm_set_config)
463 return;
464
465 if (in->realtime)
466 adev->adm_set_config(adev->adm_data,
467 in->capture_handle,
468 in->pcm,
469 &in->config);
470}
471
472static void request_out_focus(struct stream_out *out, long ns)
473{
474 struct audio_device *adev = out->dev;
475
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700476 if (adev->adm_request_focus_v2)
477 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
478 else if (adev->adm_request_focus)
479 adev->adm_request_focus(adev->adm_data, out->handle);
480}
481
482static void request_in_focus(struct stream_in *in, long ns)
483{
484 struct audio_device *adev = in->dev;
485
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700486 if (adev->adm_request_focus_v2)
487 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
488 else if (adev->adm_request_focus)
489 adev->adm_request_focus(adev->adm_data, in->capture_handle);
490}
491
492static void release_out_focus(struct stream_out *out)
493{
494 struct audio_device *adev = out->dev;
495
496 if (adev->adm_abandon_focus)
497 adev->adm_abandon_focus(adev->adm_data, out->handle);
498}
499
500static void release_in_focus(struct stream_in *in)
501{
502 struct audio_device *adev = in->dev;
503 if (adev->adm_abandon_focus)
504 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
505}
506
Dhananjay Kumare6293dd2017-05-25 17:25:30 +0530507static int parse_snd_card_status(struct str_parms *parms, int *card,
508 card_status_t *status)
509{
510 char value[32]={0};
511 char state[32]={0};
512
513 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
514 if (ret < 0)
515 return -1;
516
517 // sscanf should be okay as value is of max length 32.
518 // same as sizeof state.
519 if (sscanf(value, "%d,%s", card, state) < 2)
520 return -1;
521
522 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
523 CARD_STATUS_OFFLINE;
524 return 0;
525}
526
vivek mehtaa76401a2015-04-24 14:12:15 -0700527__attribute__ ((visibility ("default")))
528bool audio_hw_send_gain_dep_calibration(int level) {
529 bool ret_val = false;
vivek mehtab72d08d2016-04-29 03:16:47 -0700530 ALOGV("%s: called ...", __func__);
vivek mehtaa76401a2015-04-24 14:12:15 -0700531
532 pthread_mutex_lock(&adev_init_lock);
533
534 if (adev != NULL && adev->platform != NULL) {
535 pthread_mutex_lock(&adev->lock);
536 ret_val = platform_send_gain_dep_cal(adev->platform, level);
vivek mehtab72d08d2016-04-29 03:16:47 -0700537
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +0530538 // cache level info for any of the use case which
539 // was not started.
540 last_known_cal_step = level;;
vivek mehtab72d08d2016-04-29 03:16:47 -0700541
vivek mehtaa76401a2015-04-24 14:12:15 -0700542 pthread_mutex_unlock(&adev->lock);
543 } else {
544 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
545 }
546
547 pthread_mutex_unlock(&adev_init_lock);
548
549 return ret_val;
550}
551
Ashish Jain5106d362016-05-11 19:23:33 +0530552static int check_and_set_gapless_mode(struct audio_device *adev, bool enable_gapless)
553{
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800554 bool gapless_enabled = false;
555 const char *mixer_ctl_name = "Compress Gapless Playback";
556 struct mixer_ctl *ctl;
557
558 ALOGV("%s:", __func__);
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -0700559 gapless_enabled = property_get_bool("vendor.audio.offload.gapless.enabled", false);
Ashish Jain5106d362016-05-11 19:23:33 +0530560
561 /*Disable gapless if its AV playback*/
562 gapless_enabled = gapless_enabled && enable_gapless;
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800563
564 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
565 if (!ctl) {
566 ALOGE("%s: Could not get ctl for mixer cmd - %s",
567 __func__, mixer_ctl_name);
568 return -EINVAL;
569 }
570
571 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
572 ALOGE("%s: Could not set gapless mode %d",
573 __func__, gapless_enabled);
574 return -EINVAL;
575 }
576 return 0;
577}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700578
Aniket Kumar Lataf56b6402016-10-27 12:03:18 -0700579__attribute__ ((visibility ("default")))
580int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
581 int table_size) {
582 int ret_val = 0;
583 ALOGV("%s: enter ... ", __func__);
584
585 pthread_mutex_lock(&adev_init_lock);
586 if (adev == NULL) {
587 ALOGW("%s: adev is NULL .... ", __func__);
588 goto done;
589 }
590
591 pthread_mutex_lock(&adev->lock);
592 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
593 pthread_mutex_unlock(&adev->lock);
594done:
595 pthread_mutex_unlock(&adev_init_lock);
596 ALOGV("%s: exit ... ", __func__);
597 return ret_val;
598}
599
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700600static bool is_supported_format(audio_format_t format)
601{
Eric Laurent86e17132013-09-12 17:49:30 -0700602 if (format == AUDIO_FORMAT_MP3 ||
Satish Babu Patakokila0c313922016-12-08 12:07:08 +0530603 format == AUDIO_FORMAT_MP2 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530604 format == AUDIO_FORMAT_AAC_LC ||
605 format == AUDIO_FORMAT_AAC_HE_V1 ||
606 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530607 format == AUDIO_FORMAT_AAC_ADTS_LC ||
608 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
609 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
Arun Kumar Dasari3b174182016-12-27 13:01:14 +0530610 format == AUDIO_FORMAT_AAC_LATM_LC ||
611 format == AUDIO_FORMAT_AAC_LATM_HE_V1 ||
612 format == AUDIO_FORMAT_AAC_LATM_HE_V2 ||
Ashish Jain5106d362016-05-11 19:23:33 +0530613 format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
614 format == AUDIO_FORMAT_PCM_8_24_BIT ||
Ashish Jainf1eaa582016-05-23 20:54:24 +0530615 format == AUDIO_FORMAT_PCM_FLOAT ||
616 format == AUDIO_FORMAT_PCM_32_BIT ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700617 format == AUDIO_FORMAT_PCM_16_BIT ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530618 format == AUDIO_FORMAT_AC3 ||
619 format == AUDIO_FORMAT_E_AC3 ||
Ben Romberger1aaaf862017-04-06 17:49:46 -0700620 format == AUDIO_FORMAT_DOLBY_TRUEHD ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530621 format == AUDIO_FORMAT_DTS ||
622 format == AUDIO_FORMAT_DTS_HD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800623 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530624 format == AUDIO_FORMAT_ALAC ||
625 format == AUDIO_FORMAT_APE ||
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530626 format == AUDIO_FORMAT_DSD ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530627 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800628 format == AUDIO_FORMAT_WMA ||
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +0530629 format == AUDIO_FORMAT_WMA_PRO ||
Naresh Tanniru928f0862017-04-07 16:44:23 -0700630 format == AUDIO_FORMAT_APTX ||
631 format == AUDIO_FORMAT_IEC61937)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800632 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700633
634 return false;
635}
636
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700637static inline bool is_mmap_usecase(audio_usecase_t uc_id)
638{
639 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
640 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
641}
642
Avinash Vaish71a8b972014-07-24 15:36:33 +0530643static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
644 struct audio_usecase *uc_info)
645{
646 struct listnode *node;
647 struct audio_usecase *usecase;
648
649 if (uc_info == NULL)
650 return -EINVAL;
651
652 /* Re-route all voice usecases on the shared backend other than the
653 specified usecase to new snd devices */
654 list_for_each(node, &adev->usecase_list) {
655 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800656 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530657 enable_audio_route(adev, usecase);
658 }
659 return 0;
660}
661
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530662static void enable_asrc_mode(struct audio_device *adev)
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530663{
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530664 ALOGV("%s", __func__);
665 audio_route_apply_and_update_path(adev->audio_route,
666 "asrc-mode");
667 adev->asrc_mode_enabled = true;
668}
669
670static void disable_asrc_mode(struct audio_device *adev)
671{
672 ALOGV("%s", __func__);
673 audio_route_reset_and_update_path(adev->audio_route,
674 "asrc-mode");
675 adev->asrc_mode_enabled = false;
676}
677
678/*
679 * - Enable ASRC mode for incoming mix path use case(Headphone backend)if Headphone
680 * 44.1 or Native DSD backends are enabled for any of current use case.
681 * e.g. 48-> + (Naitve DSD or Headphone 44.1)
682 * - Disable current mix path use case(Headphone backend) and re-enable it with
683 * ASRC mode for incoming Headphone 44.1 or Native DSD use case.
684 * e.g. Naitve DSD or Headphone 44.1 -> + 48
685 */
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530686static void check_and_set_asrc_mode(struct audio_device *adev,
687 struct audio_usecase *uc_info,
688 snd_device_t snd_device)
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530689{
690 ALOGV("%s snd device %d", __func__, snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530691 int i, num_new_devices = 0;
692 snd_device_t split_new_snd_devices[SND_DEVICE_OUT_END];
693 /*
694 *Split snd device for new combo use case
695 *e.g. Headphopne 44.1-> + Ringtone (Headphone + Speaker)
696 */
697 if (platform_split_snd_device(adev->platform,
698 snd_device,
699 &num_new_devices,
700 split_new_snd_devices) == 0) {
701 for (i = 0; i < num_new_devices; i++)
702 check_and_set_asrc_mode(adev, uc_info, split_new_snd_devices[i]);
703 } else {
704 int new_backend_idx = platform_get_backend_index(snd_device);
705 if (((new_backend_idx == HEADPHONE_BACKEND) ||
706 (new_backend_idx == HEADPHONE_44_1_BACKEND) ||
707 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
708 !adev->asrc_mode_enabled) {
709 struct listnode *node = NULL;
710 struct audio_usecase *uc = NULL;
711 struct stream_out *curr_out = NULL;
712 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
713 int i, num_devices, ret = 0;
714 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530715
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530716 list_for_each(node, &adev->usecase_list) {
717 uc = node_to_item(node, struct audio_usecase, list);
718 curr_out = (struct stream_out*) uc->stream.out;
719 if (curr_out && PCM_PLAYBACK == uc->type && uc != uc_info) {
720 /*
721 *Split snd device for existing combo use case
722 *e.g. Ringtone (Headphone + Speaker) + Headphopne 44.1
723 */
724 ret = platform_split_snd_device(adev->platform,
725 uc->out_snd_device,
726 &num_devices,
727 split_snd_devices);
728 if (ret < 0 || num_devices == 0) {
729 ALOGV("%s: Unable to split uc->out_snd_device: %d",__func__, uc->out_snd_device);
730 split_snd_devices[0] = uc->out_snd_device;
731 num_devices = 1;
Garmond Leung50058f62017-02-08 09:49:30 -0800732 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530733 for (i = 0; i < num_devices; i++) {
734 usecase_backend_idx = platform_get_backend_index(split_snd_devices[i]);
735 ALOGD("%s:snd_dev %d usecase_backend_idx %d",__func__, split_snd_devices[i],usecase_backend_idx);
736 if((new_backend_idx == HEADPHONE_BACKEND) &&
737 ((usecase_backend_idx == HEADPHONE_44_1_BACKEND) ||
738 (usecase_backend_idx == DSD_NATIVE_BACKEND))) {
739 ALOGD("%s:DSD or native stream detected enabling asrcmode in hardware",
740 __func__);
741 enable_asrc_mode(adev);
742 break;
743 } else if(((new_backend_idx == HEADPHONE_44_1_BACKEND) ||
744 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
745 (usecase_backend_idx == HEADPHONE_BACKEND)) {
746 ALOGD("%s:48K stream detected, disabling and enabling it with asrcmode in hardware",
747 __func__);
748 disable_audio_route(adev, uc);
749 disable_snd_device(adev, uc->out_snd_device);
750 // Apply true-high-quality-mode if DSD or > 44.1KHz or >=24-bit
751 if (new_backend_idx == DSD_NATIVE_BACKEND)
752 audio_route_apply_and_update_path(adev->audio_route,
753 "hph-true-highquality-mode");
754 else if ((new_backend_idx == HEADPHONE_44_1_BACKEND) &&
755 (curr_out->bit_width >= 24))
756 audio_route_apply_and_update_path(adev->audio_route,
757 "hph-highquality-mode");
758 enable_asrc_mode(adev);
759 enable_snd_device(adev, uc->out_snd_device);
760 enable_audio_route(adev, uc);
761 break;
762 }
763 }
764 // reset split devices count
765 num_devices = 0;
Garmond Leung50058f62017-02-08 09:49:30 -0800766 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530767 if (adev->asrc_mode_enabled)
768 break;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530769 }
770 }
771 }
772}
773
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700774int pcm_ioctl(struct pcm *pcm, int request, ...)
775{
776 va_list ap;
777 void * arg;
778 int pcm_fd = *(int*)pcm;
779
780 va_start(ap, request);
781 arg = va_arg(ap, void *);
782 va_end(ap);
783
784 return ioctl(pcm_fd, request, arg);
785}
786
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700787int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700788 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800789{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700790 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700791 char mixer_path[MIXER_PATH_MAX_LENGTH];
Manish Dewangan58229382017-02-02 15:48:41 +0530792 struct stream_out *out = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800793
794 if (usecase == NULL)
795 return -EINVAL;
796
797 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
798
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800799 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700800 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800801 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700802 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800803
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -0800804#ifdef DS1_DOLBY_DAP_ENABLED
805 audio_extn_dolby_set_dmid(adev);
806 audio_extn_dolby_set_endpoint(adev);
807#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700808 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700809 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530810 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -0700811 audio_extn_utils_send_app_type_cfg(adev, usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +0530812 audio_extn_utils_send_audio_calibration(adev, usecase);
Manish Dewangan58229382017-02-02 15:48:41 +0530813 if ((usecase->type == PCM_PLAYBACK) && is_offload_usecase(usecase->id)) {
814 out = usecase->stream.out;
815 if (out && out->compr)
816 audio_extn_utils_compress_set_clk_rec_mode(usecase);
817 }
818
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800819 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700820 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700821 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700822 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800823 ALOGV("%s: exit", __func__);
824 return 0;
825}
826
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700827int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700828 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800829{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700830 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700831 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800832
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +0530833 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800834 return -EINVAL;
835
836 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700837 if (usecase->type == PCM_CAPTURE)
838 snd_device = usecase->in_snd_device;
839 else
840 snd_device = usecase->out_snd_device;
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800841 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700842 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700843 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700844 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700845 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530846 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800847 ALOGV("%s: exit", __func__);
848 return 0;
849}
850
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700851int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700852 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800853{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530854 int i, num_devices = 0;
855 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700856 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
857
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800858 if (snd_device < SND_DEVICE_MIN ||
859 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800860 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800861 return -EINVAL;
862 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700863
864 adev->snd_dev_ref_cnt[snd_device]++;
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700865
866 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
867 ALOGE("%s: Invalid sound device returned", __func__);
868 return -EINVAL;
869 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700870 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700871 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700872 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700873 return 0;
874 }
875
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530876
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -0700877 if (audio_extn_spkr_prot_is_enabled())
878 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700879
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800880 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
881 audio_extn_spkr_prot_is_enabled()) {
882 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700883 adev->snd_dev_ref_cnt[snd_device]--;
884 return -EINVAL;
885 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200886 audio_extn_dev_arbi_acquire(snd_device);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800887 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800888 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200889 audio_extn_dev_arbi_release(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800890 return -EINVAL;
891 }
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -0700892 } else if (platform_split_snd_device(adev->platform,
893 snd_device,
894 &num_devices,
895 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530896 for (i = 0; i < num_devices; i++) {
897 enable_snd_device(adev, new_snd_devices[i]);
898 }
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800899 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700900 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530901
Preetam Singh Ranawatf1d417c2017-01-10 17:00:32 +0530902
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530903 if ((SND_DEVICE_OUT_BT_A2DP == snd_device) &&
904 (audio_extn_a2dp_start_playback() < 0)) {
905 ALOGE(" fail to configure A2dp control path ");
906 return -EINVAL;
907 }
908
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -0700909 /* due to the possibility of calibration overwrite between listen
910 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700911 audio_extn_sound_trigger_update_device_status(snd_device,
912 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530913 audio_extn_listen_update_device_status(snd_device,
914 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700915 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700916 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700917 audio_extn_sound_trigger_update_device_status(snd_device,
918 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530919 audio_extn_listen_update_device_status(snd_device,
920 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700921 return -EINVAL;
922 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300923 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700924 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530925
926 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
927 !adev->native_playback_enabled &&
928 audio_is_true_native_stream_active(adev)) {
929 ALOGD("%s: %d: napb: enabling native mode in hardware",
930 __func__, __LINE__);
931 audio_route_apply_and_update_path(adev->audio_route,
932 "true-native-mode");
933 adev->native_playback_enabled = true;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530934 }
Garmond Leunge2433c32017-09-28 21:51:22 -0700935 if ((snd_device == SND_DEVICE_IN_HANDSET_6MIC) &&
936 (audio_extn_ffv_get_stream() == adev->active_input)) {
937 ALOGD("%s: init ec ref loopback", __func__);
938 audio_extn_ffv_init_ec_ref_loopback(adev, snd_device);
939 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800940 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800941 return 0;
942}
943
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700944int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700945 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800946{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530947 int i, num_devices = 0;
948 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700949 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
950
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800951 if (snd_device < SND_DEVICE_MIN ||
952 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800953 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800954 return -EINVAL;
955 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700956 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
957 ALOGE("%s: device ref cnt is already 0", __func__);
958 return -EINVAL;
959 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700960
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700961 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700962
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700963 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
964 ALOGE("%s: Invalid sound device returned", __func__);
965 return -EINVAL;
966 }
967
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700968 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700969 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530970
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800971 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
972 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -0700973 audio_extn_spkr_prot_stop_processing(snd_device);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -0700974 } else if (platform_split_snd_device(adev->platform,
975 snd_device,
976 &num_devices,
977 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530978 for (i = 0; i < num_devices; i++) {
979 disable_snd_device(adev, new_snd_devices[i]);
980 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300981 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700982 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300983 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700984
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530985 if (SND_DEVICE_OUT_BT_A2DP == snd_device)
986 audio_extn_a2dp_stop_playback();
987
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -0700988 if (snd_device == SND_DEVICE_OUT_HDMI || snd_device == SND_DEVICE_OUT_DISPLAY_PORT)
Ashish Jain81eb2a82015-05-13 10:52:34 +0530989 adev->is_channel_status_set = false;
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530990 else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
991 adev->native_playback_enabled) {
992 ALOGD("%s: %d: napb: disabling native mode in hardware",
993 __func__, __LINE__);
994 audio_route_reset_and_update_path(adev->audio_route,
995 "true-native-mode");
996 adev->native_playback_enabled = false;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530997 } else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
998 adev->asrc_mode_enabled) {
999 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301000 disable_asrc_mode(adev);
1001 audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301002 }
Garmond Leunge2433c32017-09-28 21:51:22 -07001003 if ((snd_device == SND_DEVICE_IN_HANDSET_6MIC) &&
1004 (audio_extn_ffv_get_stream() == adev->active_input)) {
1005 ALOGD("%s: deinit ec ref loopback", __func__);
1006 audio_extn_ffv_deinit_ec_ref_loopback(adev, snd_device);
1007 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +02001008 audio_extn_dev_arbi_release(snd_device);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001009 audio_extn_sound_trigger_update_device_status(snd_device,
1010 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301011 audio_extn_listen_update_device_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -08001012 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001013 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001014
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001015 return 0;
1016}
1017
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001018/*
1019 legend:
1020 uc - existing usecase
1021 new_uc - new usecase
1022 d1, d11, d2 - SND_DEVICE enums
1023 a1, a2 - corresponding ANDROID device enums
1024 B1, B2 - backend strings
1025
1026case 1
1027 uc->dev d1 (a1) B1
1028 new_uc->dev d1 (a1), d2 (a2) B1, B2
1029
1030 resolution: disable and enable uc->dev on d1
1031
1032case 2
1033 uc->dev d1 (a1) B1
1034 new_uc->dev d11 (a1) B1
1035
1036 resolution: need to switch uc since d1 and d11 are related
1037 (e.g. speaker and voice-speaker)
1038 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
1039
1040case 3
1041 uc->dev d1 (a1) B1
1042 new_uc->dev d2 (a2) B2
1043
1044 resolution: no need to switch uc
1045
1046case 4
1047 uc->dev d1 (a1) B1
1048 new_uc->dev d2 (a2) B1
1049
1050 resolution: disable enable uc-dev on d2 since backends match
1051 we cannot enable two streams on two different devices if they
1052 share the same backend. e.g. if offload is on speaker device using
1053 QUAD_MI2S backend and a low-latency stream is started on voice-handset
1054 using the same backend, offload must also be switched to voice-handset.
1055
1056case 5
1057 uc->dev d1 (a1) B1
1058 new_uc->dev d1 (a1), d2 (a2) B1
1059
1060 resolution: disable enable uc-dev on d2 since backends match
1061 we cannot enable two streams on two different devices if they
1062 share the same backend.
1063
1064case 6
1065 uc->dev d1 (a1) B1
1066 new_uc->dev d2 (a1) B2
1067
1068 resolution: no need to switch
1069
1070case 7
1071 uc->dev d1 (a1), d2 (a2) B1, B2
1072 new_uc->dev d1 (a1) B1
1073
1074 resolution: no need to switch
1075
1076*/
1077static snd_device_t derive_playback_snd_device(void * platform,
1078 struct audio_usecase *uc,
1079 struct audio_usecase *new_uc,
1080 snd_device_t new_snd_device)
1081{
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301082 audio_devices_t a1, a2;
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001083
1084 snd_device_t d1 = uc->out_snd_device;
1085 snd_device_t d2 = new_snd_device;
1086
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301087 switch (uc->type) {
1088 case TRANSCODE_LOOPBACK :
1089 a1 = uc->stream.inout->out_config.devices;
1090 a2 = new_uc->stream.inout->out_config.devices;
1091 break;
1092 default :
1093 a1 = uc->stream.out->devices;
1094 a2 = new_uc->stream.out->devices;
1095 break;
1096 }
1097
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001098 // Treat as a special case when a1 and a2 are not disjoint
1099 if ((a1 != a2) && (a1 & a2)) {
1100 snd_device_t d3[2];
1101 int num_devices = 0;
1102 int ret = platform_split_snd_device(platform,
1103 popcount(a1) > 1 ? d1 : d2,
1104 &num_devices,
1105 d3);
1106 if (ret < 0) {
1107 if (ret != -ENOSYS) {
1108 ALOGW("%s failed to split snd_device %d",
1109 __func__,
1110 popcount(a1) > 1 ? d1 : d2);
1111 }
1112 goto end;
1113 }
1114
1115 // NB: case 7 is hypothetical and isn't a practical usecase yet.
1116 // But if it does happen, we need to give priority to d2 if
1117 // the combo devices active on the existing usecase share a backend.
1118 // This is because we cannot have a usecase active on a combo device
1119 // and a new usecase requests one device in this combo pair.
1120 if (platform_check_backends_match(d3[0], d3[1])) {
1121 return d2; // case 5
1122 } else {
1123 return d1; // case 1
1124 }
1125 } else {
1126 if (platform_check_backends_match(d1, d2)) {
1127 return d2; // case 2, 4
1128 } else {
1129 return d1; // case 6, 3
1130 }
1131 }
1132
1133end:
1134 return d2; // return whatever was calculated before.
1135}
1136
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001137static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301138 struct audio_usecase *uc_info,
1139 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001140{
1141 struct listnode *node;
1142 struct audio_usecase *usecase;
1143 bool switch_device[AUDIO_USECASE_MAX];
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301144 snd_device_t uc_derive_snd_device;
1145 snd_device_t derive_snd_device[AUDIO_USECASE_MAX];
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001146 int i, num_uc_to_switch = 0;
kunleiz5cd52b82016-11-07 17:22:52 +08001147 int status = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301148 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001149 /*
1150 * This function is to make sure that all the usecases that are active on
1151 * the hardware codec backend are always routed to any one device that is
1152 * handled by the hardware codec.
1153 * For example, if low-latency and deep-buffer usecases are currently active
1154 * on speaker and out_set_parameters(headset) is received on low-latency
1155 * output, then we have to make sure deep-buffer is also switched to headset,
1156 * because of the limitation that both the devices cannot be enabled
1157 * at the same time as they share the same backend.
1158 */
Mingming Yin3ee55c62014-08-04 14:23:35 -07001159 /*
1160 * This call is to check if we need to force routing for a particular stream
1161 * If there is a backend configuration change for the device when a
1162 * new stream starts, then ADM needs to be closed and re-opened with the new
1163 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001164 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -07001165 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001166 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
1167 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301168 /* For a2dp device reconfigure all active sessions
1169 * with new AFE encoder format based on a2dp state
1170 */
1171 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
1172 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device) &&
1173 audio_extn_a2dp_is_force_device_switch()) {
1174 force_routing = true;
1175 force_restart_session = true;
1176 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301177 ALOGD("%s:becf: force routing %d", __func__, force_routing);
1178
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001179 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001180 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001181 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001182 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1183 switch_device[i] = false;
1184
1185 list_for_each(node, &adev->usecase_list) {
1186 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001187
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301188 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
1189 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301190 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301191 platform_get_snd_device_name(usecase->out_snd_device),
1192 platform_check_backends_match(snd_device, usecase->out_snd_device));
Ashish Jain6a65b352017-03-21 17:24:40 +05301193 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info)) {
1194 uc_derive_snd_device = derive_playback_snd_device(adev->platform,
1195 usecase, uc_info, snd_device);
1196 if (((uc_derive_snd_device != usecase->out_snd_device) || force_routing) &&
1197 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1198 (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
1199 (usecase->devices & AUDIO_DEVICE_OUT_USB_DEVICE) ||
1200 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP) ||
1201 (usecase->devices & AUDIO_DEVICE_OUT_ALL_SCO)) &&
1202 ((force_restart_session) ||
1203 (platform_check_backends_match(snd_device, usecase->out_snd_device)))) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301204 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
1205 __func__, use_case_table[usecase->id],
1206 platform_get_snd_device_name(usecase->out_snd_device));
1207 disable_audio_route(adev, usecase);
1208 switch_device[usecase->id] = true;
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301209 /* Enable existing usecase on derived playback device */
1210 derive_snd_device[usecase->id] = uc_derive_snd_device;
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301211 num_uc_to_switch++;
Ashish Jain6a65b352017-03-21 17:24:40 +05301212 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001213 }
1214 }
1215
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301216 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
1217 num_uc_to_switch);
1218
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001219 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001220 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001221
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301222 /* Make sure the previous devices to be disabled first and then enable the
1223 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001224 list_for_each(node, &adev->usecase_list) {
1225 usecase = node_to_item(node, struct audio_usecase, list);
1226 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001227 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001228 }
1229 }
1230
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001231 list_for_each(node, &adev->usecase_list) {
1232 usecase = node_to_item(node, struct audio_usecase, list);
1233 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301234 enable_snd_device(adev, derive_snd_device[usecase->id]);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001235 }
1236 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001237
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001238 /* Re-route all the usecases on the shared backend other than the
1239 specified usecase to new snd devices */
1240 list_for_each(node, &adev->usecase_list) {
1241 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301242 /* Update the out_snd_device only before enabling the audio route */
1243 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301244 usecase->out_snd_device = derive_snd_device[usecase->id];
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301245 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301246 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301247 use_case_table[usecase->id],
1248 platform_get_snd_device_name(usecase->out_snd_device));
kunleiz5cd52b82016-11-07 17:22:52 +08001249 /* Update voc calibration before enabling VoIP route */
1250 if (usecase->type == VOIP_CALL)
1251 status = platform_switch_voice_call_device_post(adev->platform,
1252 usecase->out_snd_device,
kunleizab514ca2017-01-09 14:59:50 +08001253 platform_get_input_snd_device(adev->platform, uc_info->devices));
Avinash Vaish71a8b972014-07-24 15:36:33 +05301254 enable_audio_route(adev, usecase);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301255 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001256 }
1257 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001258 }
1259}
1260
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301261static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001262 struct audio_usecase *uc_info,
1263 snd_device_t snd_device)
1264{
1265 struct listnode *node;
1266 struct audio_usecase *usecase;
1267 bool switch_device[AUDIO_USECASE_MAX];
1268 int i, num_uc_to_switch = 0;
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301269 int backend_check_cond = AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND;
kunleiz5cd52b82016-11-07 17:22:52 +08001270 int status = 0;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001271
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301272 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1273 snd_device);
1274 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301275
1276 /*
1277 * Make sure out devices is checked against out codec backend device and
1278 * also in devices against in codec backend. Checking out device against in
1279 * codec backend or vice versa causes issues.
1280 */
1281 if (uc_info->type == PCM_CAPTURE)
1282 backend_check_cond = AUDIO_DEVICE_IN_ALL_CODEC_BACKEND;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001283 /*
1284 * This function is to make sure that all the active capture usecases
1285 * are always routed to the same input sound device.
1286 * For example, if audio-record and voice-call usecases are currently
1287 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1288 * is received for voice call then we have to make sure that audio-record
1289 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1290 * because of the limitation that two devices cannot be enabled
1291 * at the same time if they share the same backend.
1292 */
1293 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1294 switch_device[i] = false;
1295
1296 list_for_each(node, &adev->usecase_list) {
1297 usecase = node_to_item(node, struct audio_usecase, list);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301298 /*
1299 * TODO: Enhance below condition to handle BT sco/USB multi recording
1300 */
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001301 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001302 usecase != uc_info &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301303 (usecase->in_snd_device != snd_device || force_routing) &&
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301304 ((uc_info->devices & backend_check_cond) &&
Karthik Reddy Katta0d471762015-08-20 13:36:07 +05301305 (((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND) ||
Satya Krishna Pindiproli458b5a72017-03-13 15:14:24 +05301306 (usecase->type == VOIP_CALL))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07001307 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001308 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1309 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001310 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001311 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001312 switch_device[usecase->id] = true;
1313 num_uc_to_switch++;
1314 }
1315 }
1316
1317 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001318 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001319
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301320 /* Make sure the previous devices to be disabled first and then enable the
1321 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001322 list_for_each(node, &adev->usecase_list) {
1323 usecase = node_to_item(node, struct audio_usecase, list);
1324 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001325 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001326 }
1327 }
1328
1329 list_for_each(node, &adev->usecase_list) {
1330 usecase = node_to_item(node, struct audio_usecase, list);
1331 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001332 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001333 }
1334 }
1335
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001336 /* Re-route all the usecases on the shared backend other than the
1337 specified usecase to new snd devices */
1338 list_for_each(node, &adev->usecase_list) {
1339 usecase = node_to_item(node, struct audio_usecase, list);
1340 /* Update the in_snd_device only before enabling the audio route */
1341 if (switch_device[usecase->id] ) {
1342 usecase->in_snd_device = snd_device;
kunleiz5cd52b82016-11-07 17:22:52 +08001343 if (usecase->type != VOICE_CALL) {
1344 /* Update voc calibration before enabling VoIP route */
1345 if (usecase->type == VOIP_CALL)
1346 status = platform_switch_voice_call_device_post(adev->platform,
Zhou Song557e7282017-05-05 17:18:18 +08001347 platform_get_output_snd_device(adev->platform, uc_info->stream.out),
kunleiz5cd52b82016-11-07 17:22:52 +08001348 usecase->in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301349 enable_audio_route(adev, usecase);
kunleiz5cd52b82016-11-07 17:22:52 +08001350 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001351 }
1352 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001353 }
1354}
1355
Mingming Yin3a941d42016-02-17 18:08:05 -08001356static void reset_hdmi_sink_caps(struct stream_out *out) {
1357 int i = 0;
1358
1359 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
1360 out->supported_channel_masks[i] = 0;
1361 }
1362 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
1363 out->supported_formats[i] = 0;
1364 }
1365 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
1366 out->supported_sample_rates[i] = 0;
1367 }
1368}
1369
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001370/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08001371static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001372{
Mingming Yin3a941d42016-02-17 18:08:05 -08001373 int ret = 0, i = 0, j = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001374 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001375
Mingming Yin3a941d42016-02-17 18:08:05 -08001376 reset_hdmi_sink_caps(out);
1377
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001378 /* Cache ext disp type */
Garmond Leung37850ab2016-10-06 11:42:18 -07001379 if (platform_get_ext_disp_type(adev->platform) <= 0) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001380 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07001381 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001382 }
1383
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001384 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001385 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08001386 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001387 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08001388 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
1389 case 6:
1390 ALOGV("%s: HDMI supports 5.1 channels", __func__);
1391 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
1392 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
1393 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
1394 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
1395 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001396 break;
1397 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08001398 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001399 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001400 break;
1401 }
Mingming Yin3a941d42016-02-17 18:08:05 -08001402
1403 // check channel format caps
1404 i = 0;
1405 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_AC3)) {
1406 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
1407 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
1408 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
1409 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
1410 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
1411 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
1412 }
1413
Ben Romberger1aaaf862017-04-06 17:49:46 -07001414 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DOLBY_TRUEHD)) {
1415 ALOGV(":%s HDMI supports TRUE HD format", __func__);
1416 out->supported_formats[i++] = AUDIO_FORMAT_DOLBY_TRUEHD;
1417 }
1418
Mingming Yin3a941d42016-02-17 18:08:05 -08001419 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS)) {
1420 ALOGV(":%s HDMI supports DTS format", __func__);
1421 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
1422 }
1423
1424 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS_HD)) {
1425 ALOGV(":%s HDMI supports DTS HD format", __func__);
1426 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
1427 }
1428
Naresh Tanniru928f0862017-04-07 16:44:23 -07001429 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_IEC61937)) {
1430 ALOGV(":%s HDMI supports IEC61937 format", __func__);
1431 out->supported_formats[i++] = AUDIO_FORMAT_IEC61937;
1432 }
1433
Mingming Yin3a941d42016-02-17 18:08:05 -08001434
1435 // check sample rate caps
1436 i = 0;
1437 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
1438 if (platform_is_edid_supported_sample_rate(out->dev->platform, out_hdmi_sample_rates[j])) {
1439 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
1440 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
1441 }
1442 }
1443
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001444 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001445}
1446
Alexy Josephb1379942016-01-29 15:49:38 -08001447audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001448 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001449{
1450 struct audio_usecase *usecase;
1451 struct listnode *node;
1452
1453 list_for_each(node, &adev->usecase_list) {
1454 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001455 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001456 ALOGV("%s: usecase id %d", __func__, usecase->id);
1457 return usecase->id;
1458 }
1459 }
1460 return USECASE_INVALID;
1461}
1462
Alexy Josephb1379942016-01-29 15:49:38 -08001463struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001464 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001465{
1466 struct audio_usecase *usecase;
1467 struct listnode *node;
1468
1469 list_for_each(node, &adev->usecase_list) {
1470 usecase = node_to_item(node, struct audio_usecase, list);
1471 if (usecase->id == uc_id)
1472 return usecase;
1473 }
1474 return NULL;
1475}
1476
Dhananjay Kumard4833242016-10-06 22:09:12 +05301477struct stream_in *get_next_active_input(const struct audio_device *adev)
1478{
1479 struct audio_usecase *usecase;
1480 struct listnode *node;
1481
1482 list_for_each_reverse(node, &adev->usecase_list) {
1483 usecase = node_to_item(node, struct audio_usecase, list);
1484 if (usecase->type == PCM_CAPTURE)
1485 return usecase->stream.in;
1486 }
1487 return NULL;
1488}
1489
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301490/*
1491 * is a true native playback active
1492 */
1493bool audio_is_true_native_stream_active(struct audio_device *adev)
1494{
1495 bool active = false;
1496 int i = 0;
1497 struct listnode *node;
1498
1499 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
1500 ALOGV("%s:napb: not in true mode or non hdphones device",
1501 __func__);
1502 active = false;
1503 goto exit;
1504 }
1505
1506 list_for_each(node, &adev->usecase_list) {
1507 struct audio_usecase *uc;
1508 uc = node_to_item(node, struct audio_usecase, list);
1509 struct stream_out *curr_out =
1510 (struct stream_out*) uc->stream.out;
1511
1512 if (curr_out && PCM_PLAYBACK == uc->type) {
1513 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
1514 "(%d) device %s", __func__, i++, use_case_table[uc->id],
1515 uc->id, curr_out->sample_rate,
1516 curr_out->bit_width,
1517 platform_get_snd_device_name(uc->out_snd_device));
1518
1519 if (is_offload_usecase(uc->id) &&
1520 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
1521 active = true;
1522 ALOGD("%s:napb:native stream detected", __func__);
1523 }
1524 }
1525 }
1526exit:
1527 return active;
1528}
1529
Xiaojun Sang785b5da2017-08-03 15:52:29 +08001530uint32_t adev_get_dsp_bit_width_enforce_mode()
1531{
1532 if (adev == NULL) {
1533 ALOGE("%s: adev is null. Disable DSP bit width enforce mode.\n", __func__);
1534 return 0;
1535 }
1536 return adev->dsp_bit_width_enforce_mode;
1537}
1538
1539static uint32_t adev_init_dsp_bit_width_enforce_mode(struct mixer *mixer)
1540{
1541 char value[PROPERTY_VALUE_MAX];
1542 int trial;
1543 uint32_t dsp_bit_width_enforce_mode = 0;
1544
1545 if (!mixer) {
1546 ALOGE("%s: adev mixer is null. cannot update DSP bitwidth.\n",
1547 __func__);
1548 return 0;
1549 }
1550
1551 if (property_get("persist.vendor.audio_hal.dsp_bit_width_enforce_mode",
1552 value, NULL) > 0) {
1553 trial = atoi(value);
1554 switch (trial) {
1555 case 16:
1556 dsp_bit_width_enforce_mode = 16;
1557 break;
1558 case 24:
1559 dsp_bit_width_enforce_mode = 24;
1560 break;
1561 case 32:
1562 dsp_bit_width_enforce_mode = 32;
1563 break;
1564 default:
1565 dsp_bit_width_enforce_mode = 0;
1566 ALOGD("%s Dynamic DSP bitwidth config is disabled.", __func__);
1567 break;
1568 }
1569 }
1570
1571 return dsp_bit_width_enforce_mode;
1572}
1573
1574static void audio_enable_asm_bit_width_enforce_mode(struct mixer *mixer,
1575 uint32_t enforce_mode,
1576 bool enable)
1577{
1578 struct mixer_ctl *ctl = NULL;
1579 const char *mixer_ctl_name = "ASM Bit Width";
1580 uint32_t asm_bit_width_mode = 0;
1581
1582 if (enforce_mode == 0) {
1583 ALOGD("%s: DSP bitwidth feature is disabled.", __func__);
1584 return;
1585 }
1586
1587 ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
1588 if (!ctl) {
1589 ALOGE("%s: Could not get ctl for mixer cmd - %s",
1590 __func__, mixer_ctl_name);
1591 return;
1592 }
1593
1594 if (enable)
1595 asm_bit_width_mode = enforce_mode;
1596 else
1597 asm_bit_width_mode = 0;
1598
1599 ALOGV("%s DSP bit width feature status is %d width=%d",
1600 __func__, enable, asm_bit_width_mode);
1601 if (mixer_ctl_set_value(ctl, 0, asm_bit_width_mode) < 0)
1602 ALOGE("%s: Could not set ASM biwidth %d", __func__,
1603 asm_bit_width_mode);
1604
1605 return;
1606}
1607
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301608/*
1609 * if native DSD playback active
1610 */
1611bool audio_is_dsd_native_stream_active(struct audio_device *adev)
1612{
1613 bool active = false;
1614 struct listnode *node = NULL;
1615 struct audio_usecase *uc = NULL;
1616 struct stream_out *curr_out = NULL;
1617
1618 list_for_each(node, &adev->usecase_list) {
1619 uc = node_to_item(node, struct audio_usecase, list);
1620 curr_out = (struct stream_out*) uc->stream.out;
1621
1622 if (curr_out && PCM_PLAYBACK == uc->type &&
1623 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
1624 active = true;
1625 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05301626 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301627 }
1628 }
1629 return active;
1630}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301631
1632static bool force_device_switch(struct audio_usecase *usecase)
1633{
1634 bool ret = false;
1635 bool is_it_true_mode = false;
1636
1637 if (is_offload_usecase(usecase->id) &&
1638 (usecase->stream.out) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08001639 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
1640 (usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADSET ||
1641 usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADPHONE)) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301642 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
1643 if ((is_it_true_mode && !adev->native_playback_enabled) ||
1644 (!is_it_true_mode && adev->native_playback_enabled)){
1645 ret = true;
1646 ALOGD("napb: time to toggle native mode");
1647 }
1648 }
1649
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301650 // Force all a2dp output devices to reconfigure for proper AFE encode format
Ashish Jainc597d102016-12-12 10:31:34 +05301651 //Also handle a case where in earlier a2dp start failed as A2DP stream was
1652 //in suspended state, hence try to trigger a retry when we again get a routing request.
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301653 if((usecase->stream.out) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07001654 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Ashish Jainc597d102016-12-12 10:31:34 +05301655 audio_extn_a2dp_is_force_device_switch()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301656 ALOGD("Force a2dp device switch to update new encoder config");
1657 ret = true;
1658 }
1659
Manish Dewangan671a4202017-08-18 17:30:46 +05301660 if (usecase->stream.out->stream_config_changed) {
1661 ALOGD("Force stream_config_changed to update iec61937 transmission config");
1662 return true;
1663 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301664 return ret;
1665}
1666
Ashish Jain1b9b30c2017-05-18 20:57:40 +05301667bool is_btsco_device(snd_device_t out_snd_device, snd_device_t in_snd_device)
1668{
1669 bool ret=false;
1670 if ((out_snd_device == SND_DEVICE_OUT_BT_SCO ||
1671 out_snd_device == SND_DEVICE_OUT_BT_SCO_WB) ||
1672 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB_NREC ||
1673 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB ||
1674 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_NREC ||
1675 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC)
1676 ret = true;
1677
1678 return ret;
1679}
1680
1681bool is_a2dp_device(snd_device_t out_snd_device)
1682{
1683 bool ret=false;
1684 if (out_snd_device == SND_DEVICE_OUT_BT_A2DP)
1685 ret = true;
1686
1687 return ret;
1688}
1689
1690bool is_bt_soc_on(struct audio_device *adev)
1691{
1692 struct mixer_ctl *ctl;
1693 char *mixer_ctl_name = "BT SOC status";
1694 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
1695 bool bt_soc_status = true;
1696 if (!ctl) {
1697 ALOGE("%s: Could not get ctl for mixer cmd - %s",
1698 __func__, mixer_ctl_name);
1699 /*This is to ensure we dont break targets which dont have the kernel change*/
1700 return true;
1701 }
1702 bt_soc_status = mixer_ctl_get_value(ctl, 0);
1703 ALOGD("BT SOC status: %d",bt_soc_status);
1704 return bt_soc_status;
1705}
1706
1707int out_standby_l(struct audio_stream *stream);
1708
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001709int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001710{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001711 snd_device_t out_snd_device = SND_DEVICE_NONE;
1712 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001713 struct audio_usecase *usecase = NULL;
1714 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001715 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001716 struct audio_usecase *hfp_usecase = NULL;
Siddartha Shaik44dd7702017-06-14 12:13:25 +05301717 struct stream_out stream_out;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001718 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001719 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001720
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301721 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
1722
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001723 usecase = get_usecase_from_list(adev, uc_id);
1724 if (usecase == NULL) {
1725 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1726 return -EINVAL;
1727 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001728
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001729 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08001730 (usecase->type == VOIP_CALL) ||
1731 (usecase->type == PCM_HFP_CALL)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301732 if(usecase->stream.out == NULL) {
1733 ALOGE("%s: stream.out is NULL", __func__);
1734 return -EINVAL;
1735 }
Eric Laurentb23d5282013-05-14 15:27:20 -07001736 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001737 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -07001738 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001739 usecase->devices = usecase->stream.out->devices;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301740 } else if (usecase->type == TRANSCODE_LOOPBACK ) {
1741 if (usecase->stream.inout == NULL) {
1742 ALOGE("%s: stream.inout is NULL", __func__);
1743 return -EINVAL;
1744 }
Siddartha Shaik44dd7702017-06-14 12:13:25 +05301745 stream_out.devices = usecase->stream.inout->out_config.devices;
1746 stream_out.sample_rate = usecase->stream.inout->out_config.sample_rate;
1747 stream_out.format = usecase->stream.inout->out_config.format;
1748 stream_out.channel_mask = usecase->stream.inout->out_config.channel_mask;
1749 out_snd_device = platform_get_output_snd_device(adev->platform,
1750 &stream_out);
1751 in_snd_device = platform_get_input_snd_device(adev->platform, AUDIO_DEVICE_NONE);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301752 usecase->devices = (out_snd_device | in_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001753 } else {
1754 /*
1755 * If the voice call is active, use the sound devices of voice call usecase
1756 * so that it would not result any device switch. All the usecases will
1757 * be switched to new device when select_devices() is called for voice call
1758 * usecase. This is to avoid switching devices for voice call when
1759 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07001760 * choose voice call device only if the use case device is
1761 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001762 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08001763 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001764 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001765 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Alexy Josephdbcddf22016-05-16 17:54:09 -07001766 if ((vc_usecase) && (((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1767 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) ||
Preetam Singh Ranawat097cb1f2016-07-19 13:49:04 +05301768 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1769 (usecase->devices & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) ||
Alexy Josephdbcddf22016-05-16 17:54:09 -07001770 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001771 in_snd_device = vc_usecase->in_snd_device;
1772 out_snd_device = vc_usecase->out_snd_device;
1773 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001774 } else if (voice_extn_compress_voip_is_active(adev)) {
yidongh02ef86f2017-04-21 15:36:04 +08001775 bool out_snd_device_backend_match = true;
yidongh47785a82017-05-08 19:29:29 +08001776 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
yidongh6261d8e2017-05-15 17:04:02 +08001777 if ((voip_usecase != NULL) &&
1778 (usecase->type == PCM_PLAYBACK) &&
1779 (usecase->stream.out != NULL)) {
yidongh02ef86f2017-04-21 15:36:04 +08001780 out_snd_device_backend_match = platform_check_backends_match(
1781 voip_usecase->out_snd_device,
1782 platform_get_output_snd_device(
1783 adev->platform,
1784 usecase->stream.out));
1785 }
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001786 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Zhou Song0154bf12016-08-04 10:48:16 +08001787 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1788 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
yidongh02ef86f2017-04-21 15:36:04 +08001789 out_snd_device_backend_match &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001790 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001791 in_snd_device = voip_usecase->in_snd_device;
1792 out_snd_device = voip_usecase->out_snd_device;
1793 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001794 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001795 hfp_ucid = audio_extn_hfp_get_usecase();
1796 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001797 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001798 in_snd_device = hfp_usecase->in_snd_device;
1799 out_snd_device = hfp_usecase->out_snd_device;
1800 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001801 }
1802 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301803 if (usecase->stream.out == NULL) {
1804 ALOGE("%s: stream.out is NULL", __func__);
1805 return -EINVAL;
1806 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001807 usecase->devices = usecase->stream.out->devices;
1808 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001809 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001810 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001811 usecase->stream.out);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001812 if (usecase->stream.out == adev->primary_output &&
1813 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -08001814 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001815 select_devices(adev, adev->active_input->usecase);
1816 }
1817 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001818 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301819 if (usecase->stream.in == NULL) {
1820 ALOGE("%s: stream.in is NULL", __func__);
1821 return -EINVAL;
1822 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001823 usecase->devices = usecase->stream.in->device;
1824 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001825 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001826 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08001827 if (adev->active_input &&
1828 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +05301829 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
1830 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
1831 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001832 out_device = adev->primary_output->devices;
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07001833 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001834 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1835 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001836 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001837 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001838 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001839 }
1840 }
1841
1842 if (out_snd_device == usecase->out_snd_device &&
1843 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301844
1845 if (!force_device_switch(usecase))
1846 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001847 }
1848
Ashish Jain1b9b30c2017-05-18 20:57:40 +05301849 if ((is_btsco_device(out_snd_device,in_snd_device) && !adev->bt_sco_on) ||
1850 (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_is_ready())) {
1851 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
1852 return 0;
1853 }
1854
sangwoobc677242013-08-08 16:53:43 +09001855 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -07001856 out_snd_device, platform_get_snd_device_name(out_snd_device),
1857 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001858
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001859 /*
1860 * Limitation: While in call, to do a device switch we need to disable
1861 * and enable both RX and TX devices though one of them is same as current
1862 * device.
1863 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001864 if ((usecase->type == VOICE_CALL) &&
1865 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1866 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001867 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07001868 }
1869
1870 if (((usecase->type == VOICE_CALL) ||
1871 (usecase->type == VOIP_CALL)) &&
1872 (usecase->out_snd_device != SND_DEVICE_NONE)) {
1873 /* Disable sidetone only if voice/voip call already exists */
1874 if (voice_is_call_state_active(adev) ||
1875 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07001876 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07001877
1878 /* Disable aanc only if voice call exists */
1879 if (voice_is_call_state_active(adev))
1880 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001881 }
1882
Zhou Songc66eb7e2017-08-08 18:29:07 +08001883 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP) &&
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05301884 (!audio_extn_a2dp_is_ready())) {
1885 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
Zhou Songc66eb7e2017-08-08 18:29:07 +08001886 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05301887 }
1888
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001889 /* Disable current sound devices */
1890 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001891 disable_audio_route(adev, usecase);
1892 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001893 }
1894
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001895 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001896 disable_audio_route(adev, usecase);
1897 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001898 }
1899
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001900 /* Applicable only on the targets that has external modem.
1901 * New device information should be sent to modem before enabling
1902 * the devices to reduce in-call device switch time.
1903 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001904 if ((usecase->type == VOICE_CALL) &&
1905 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1906 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001907 status = platform_switch_voice_call_enable_device_config(adev->platform,
1908 out_snd_device,
1909 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001910 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001911
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001912 /* Enable new sound devices */
1913 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001914 check_usecases_codec_backend(adev, usecase, out_snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301915 if (platform_check_codec_asrc_support(adev->platform))
1916 check_and_set_asrc_mode(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001917 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001918 }
1919
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001920 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301921 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001922 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001923 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001924
Avinash Vaish71a8b972014-07-24 15:36:33 +05301925 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001926 status = platform_switch_voice_call_device_post(adev->platform,
1927 out_snd_device,
1928 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301929 enable_audio_route_for_voice_usecases(adev, usecase);
1930 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001931
sangwoo170731f2013-06-08 15:36:36 +09001932 usecase->in_snd_device = in_snd_device;
1933 usecase->out_snd_device = out_snd_device;
1934
Dhananjay Kumard6d32152016-10-13 16:11:03 +05301935 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
1936 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301937 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001938 if ((24 == usecase->stream.out->bit_width) &&
1939 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
1940 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
1941 } else if ((out_snd_device == SND_DEVICE_OUT_HDMI ||
1942 out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
1943 out_snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
1944 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
1945 /*
1946 * To best utlize DSP, check if the stream sample rate is supported/multiple of
1947 * configured device sample rate, if not update the COPP rate to be equal to the
1948 * device sample rate, else open COPP at stream sample rate
1949 */
1950 platform_check_and_update_copp_sample_rate(adev->platform, out_snd_device,
1951 usecase->stream.out->sample_rate,
1952 &usecase->stream.out->app_type_cfg.sample_rate);
Ashish Jain4826f6c2017-02-06 13:33:20 +05301953 } else if (((out_snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
1954 !audio_is_true_native_stream_active(adev)) &&
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001955 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
1956 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
1957 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
1958 }
1959
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001960 /* Notify device change info to effect clients registered */
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001961 pthread_mutex_unlock(&adev->lock);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001962 audio_extn_gef_notify_device_config(
1963 usecase->stream.out->devices,
1964 usecase->stream.out->channel_mask,
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001965 usecase->stream.out->app_type_cfg.sample_rate,
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001966 platform_get_snd_device_acdb_id(usecase->out_snd_device));
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001967 pthread_mutex_lock(&adev->lock);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301968 }
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001969 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001970
Vidyakumar Athota493f2892016-08-14 11:56:55 -07001971 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07001972 /* Enable aanc only if voice call exists */
1973 if (voice_is_call_state_active(adev))
1974 voice_check_and_update_aanc_path(adev, out_snd_device, true);
1975
Vidyakumar Athota493f2892016-08-14 11:56:55 -07001976 /* Enable sidetone only if other voice/voip call already exists */
1977 if (voice_is_call_state_active(adev) ||
1978 voice_extn_compress_voip_is_started(adev))
1979 voice_set_sidetone(adev, out_snd_device, true);
1980 }
1981
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001982 /* Applicable only on the targets that has external modem.
1983 * Enable device command should be sent to modem only after
1984 * enabling voice call mixer controls
1985 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07001986 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001987 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1988 out_snd_device,
1989 in_snd_device);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05301990
1991 if (is_btsco_device(out_snd_device, in_snd_device) || is_a2dp_device(out_snd_device)) {
1992
1993 if (usecase->type == VOIP_CALL) {
1994 if (adev->active_input != NULL &&
1995 !adev->active_input->standby) {
1996 if (is_bt_soc_on(adev) == false){
1997 ALOGD("BT SCO MIC disconnected while in connection");
1998 if (adev->active_input->pcm != NULL)
1999 pcm_stop(adev->active_input->pcm);
2000 }
2001 }
2002 if ((usecase->stream.out != NULL) && (usecase->stream.out != adev->primary_output)
2003 && usecase->stream.out->started) {
2004 if (is_bt_soc_on(adev) == false) {
2005 ALOGD("BT SCO/A2DP disconnected while in connection");
2006 out_standby_l(&usecase->stream.out->stream.common);
2007 }
2008 }
2009 } else if ((usecase->stream.out != NULL) &&
2010 !(usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2011 usecase->stream.out->started) {
2012 if (is_bt_soc_on(adev) == false) {
2013 ALOGD("BT SCO/A2dp disconnected while in connection");
2014 out_standby_l(&usecase->stream.out->stream.common);
2015 }
2016 }
2017 }
2018
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302019 ALOGD("%s: done",__func__);
2020
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002021 return status;
2022}
2023
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002024static int stop_input_stream(struct stream_in *in)
2025{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302026 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002027 struct audio_usecase *uc_info;
2028 struct audio_device *adev = in->dev;
2029
Eric Laurent994a6932013-07-17 11:51:42 -07002030 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002031 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002032 uc_info = get_usecase_from_list(adev, in->usecase);
2033 if (uc_info == NULL) {
2034 ALOGE("%s: Could not find the usecase (%d) in the list",
2035 __func__, in->usecase);
2036 return -EINVAL;
2037 }
2038
Vidyakumar Athota2850d532013-11-19 16:02:12 -08002039 /* Close in-call recording streams */
2040 voice_check_and_stop_incall_rec_usecase(adev, in);
2041
Eric Laurent150dbfe2013-02-27 14:31:02 -08002042 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002043 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002044
2045 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002046 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002047
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002048 list_remove(&uc_info->list);
2049 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002050
Aalique Grahame2e9b2e42016-12-07 12:43:48 -08002051 adev->active_input = get_next_active_input(adev);
2052
Eric Laurent994a6932013-07-17 11:51:42 -07002053 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002054 return ret;
2055}
2056
2057int start_input_stream(struct stream_in *in)
2058{
2059 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08002060 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002061 struct audio_usecase *uc_info;
2062 struct audio_device *adev = in->dev;
Garmond Leunge2433c32017-09-28 21:51:22 -07002063 int snd_card_status;
2064 struct pcm_config config = in->config;
2065 int usecase;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002066
Garmond Leunge2433c32017-09-28 21:51:22 -07002067 snd_card_status = get_snd_card_state(adev);
2068 usecase = platform_update_usecase_from_source(in->source,in->usecase);
Mingming Yin2664a5b2015-09-03 10:53:11 -07002069 if (get_usecase_from_list(adev, usecase) == NULL)
2070 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302071 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
2072 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002073
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302074 if (CARD_STATUS_OFFLINE == in->card_status||
2075 CARD_STATUS_OFFLINE == adev->card_status) {
2076 ALOGW("in->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302077 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302078 goto error_config;
2079 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05302080
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302081 if (audio_is_bluetooth_sco_device(in->device)) {
2082 if (!adev->bt_sco_on) {
2083 ALOGE("%s: SCO profile is not ready, return error", __func__);
2084 ret = -EIO;
2085 goto error_config;
2086 }
2087 }
2088
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002089 /* Check if source matches incall recording usecase criteria */
2090 ret = voice_check_and_set_incall_rec_usecase(adev, in);
2091 if (ret)
2092 goto error_config;
2093 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07002094 ALOGV("%s: usecase(%d)", __func__, in->usecase);
2095
2096 if (get_usecase_from_list(adev, in->usecase) != NULL) {
2097 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
2098 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08002099 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07002100 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002101
Eric Laurentb23d5282013-05-14 15:27:20 -07002102 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002103 if (in->pcm_device_id < 0) {
2104 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
2105 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08002106 ret = -EINVAL;
2107 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002108 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002109
2110 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002111 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002112
2113 if (!uc_info) {
2114 ret = -ENOMEM;
2115 goto error_config;
2116 }
2117
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002118 uc_info->id = in->usecase;
2119 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002120 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002121 uc_info->devices = in->device;
2122 uc_info->in_snd_device = SND_DEVICE_NONE;
2123 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002124
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002125 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302126 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2127 adev->perf_lock_opts,
2128 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002129 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002130
Haynes Mathew George16081042017-05-31 17:16:49 -07002131 if (audio_extn_cin_attached_usecase(in->usecase)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05302132 ret = audio_extn_cin_start_input_stream(in);
2133 if (ret)
2134 goto error_open;
2135 else
2136 goto done_open;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002137 }
2138
Haynes Mathew George16081042017-05-31 17:16:49 -07002139 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002140 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07002141 ALOGE("%s: pcm stream not ready", __func__);
2142 goto error_open;
2143 }
2144 ret = pcm_start(in->pcm);
2145 if (ret < 0) {
2146 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
2147 goto error_open;
2148 }
2149 } else {
2150 unsigned int flags = PCM_IN | PCM_MONOTONIC;
2151 unsigned int pcm_open_retry_count = 0;
2152
2153 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
2154 flags |= PCM_MMAP | PCM_NOIRQ;
2155 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
2156 } else if (in->realtime) {
2157 flags |= PCM_MMAP | PCM_NOIRQ;
2158 }
2159
Garmond Leunge2433c32017-09-28 21:51:22 -07002160 if (audio_extn_ffv_get_stream() == in) {
2161 ALOGD("%s: ffv stream, update pcm config", __func__);
2162 audio_extn_ffv_update_pcm_config(&config);
2163 }
Haynes Mathew George16081042017-05-31 17:16:49 -07002164 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
2165 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
2166
2167 while (1) {
2168 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
2169 flags, &in->config);
2170 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
2171 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
2172 if (in->pcm != NULL) {
2173 pcm_close(in->pcm);
2174 in->pcm = NULL;
2175 }
2176 if (pcm_open_retry_count-- == 0) {
2177 ret = -EIO;
2178 goto error_open;
2179 }
2180 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2181 continue;
2182 }
2183 break;
2184 }
2185
2186 ALOGV("%s: pcm_prepare", __func__);
2187 ret = pcm_prepare(in->pcm);
2188 if (ret < 0) {
2189 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2190 pcm_close(in->pcm);
2191 in->pcm = NULL;
2192 goto error_open;
2193 }
2194 register_in_stream(in);
2195 if (in->realtime) {
2196 ret = pcm_start(in->pcm);
2197 if (ret < 0) {
2198 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002199 pcm_close(in->pcm);
2200 in->pcm = NULL;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002201 goto error_open;
2202 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002203 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002204 }
2205
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05302206done_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302207 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002208 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002209
Eric Laurentc8400632013-02-14 19:04:54 -08002210 return ret;
2211
2212error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302213 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002214 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -08002215error_config:
Dhananjay Kumard4833242016-10-06 22:09:12 +05302216 adev->active_input = get_next_active_input(adev);
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05302217 /*
2218 * sleep 50ms to allow sufficient time for kernel
2219 * drivers to recover incases like SSR.
2220 */
2221 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002222 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08002223
2224 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002225}
2226
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002227void lock_input_stream(struct stream_in *in)
2228{
2229 pthread_mutex_lock(&in->pre_lock);
2230 pthread_mutex_lock(&in->lock);
2231 pthread_mutex_unlock(&in->pre_lock);
2232}
2233
2234void lock_output_stream(struct stream_out *out)
2235{
2236 pthread_mutex_lock(&out->pre_lock);
2237 pthread_mutex_lock(&out->lock);
2238 pthread_mutex_unlock(&out->pre_lock);
2239}
2240
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002241/* must be called with out->lock locked */
2242static int send_offload_cmd_l(struct stream_out* out, int command)
2243{
2244 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
2245
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002246 if (!cmd) {
2247 ALOGE("failed to allocate mem for command 0x%x", command);
2248 return -ENOMEM;
2249 }
2250
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002251 ALOGVV("%s %d", __func__, command);
2252
2253 cmd->cmd = command;
2254 list_add_tail(&out->offload_cmd_list, &cmd->node);
2255 pthread_cond_signal(&out->offload_cond);
2256 return 0;
2257}
2258
2259/* must be called iwth out->lock locked */
2260static void stop_compressed_output_l(struct stream_out *out)
2261{
2262 out->offload_state = OFFLOAD_STATE_IDLE;
2263 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002264 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002265 if (out->compr != NULL) {
2266 compress_stop(out->compr);
2267 while (out->offload_thread_blocked) {
2268 pthread_cond_wait(&out->cond, &out->lock);
2269 }
2270 }
2271}
2272
Varun Balaraje49253e2017-07-06 19:48:56 +05302273bool is_interactive_usecase(audio_usecase_t uc_id)
2274{
2275 unsigned int i;
2276 for (i = 0; i < sizeof(interactive_usecases)/sizeof(interactive_usecases[0]); i++) {
2277 if (uc_id == interactive_usecases[i])
2278 return true;
2279 }
2280 return false;
2281}
2282
2283static audio_usecase_t get_interactive_usecase(struct audio_device *adev)
2284{
2285 audio_usecase_t ret_uc = USECASE_INVALID;
2286 unsigned int intract_uc_index;
2287 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
2288
2289 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
2290 for (intract_uc_index = 0; intract_uc_index < num_usecase; intract_uc_index++) {
2291 if (!(adev->interactive_usecase_state & (0x1 << intract_uc_index))) {
2292 adev->interactive_usecase_state |= 0x1 << intract_uc_index;
2293 ret_uc = interactive_usecases[intract_uc_index];
2294 break;
2295 }
2296 }
2297
2298 ALOGV("%s: Interactive usecase is %d", __func__, ret_uc);
2299 return ret_uc;
2300}
2301
2302static void free_interactive_usecase(struct audio_device *adev,
2303 audio_usecase_t uc_id)
2304{
2305 unsigned int interact_uc_index;
2306 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
2307
2308 for (interact_uc_index = 0; interact_uc_index < num_usecase; interact_uc_index++) {
2309 if (interactive_usecases[interact_uc_index] == uc_id) {
2310 adev->interactive_usecase_state &= ~(0x1 << interact_uc_index);
2311 break;
2312 }
2313 }
2314 ALOGV("%s: free Interactive usecase %d", __func__, uc_id);
2315}
2316
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002317bool is_offload_usecase(audio_usecase_t uc_id)
2318{
2319 unsigned int i;
2320 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
2321 if (uc_id == offload_usecases[i])
2322 return true;
2323 }
2324 return false;
2325}
2326
Dhananjay Kumarac341582017-02-23 23:42:25 +05302327static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_compress)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002328{
vivek mehta446c3962015-09-14 10:57:35 -07002329 audio_usecase_t ret_uc = USECASE_INVALID;
2330 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08002331 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07002332 if (!adev->multi_offload_enable) {
Dhananjay Kumarac341582017-02-23 23:42:25 +05302333 if (!is_compress)
vivek mehta446c3962015-09-14 10:57:35 -07002334 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
2335 else
2336 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002337
vivek mehta446c3962015-09-14 10:57:35 -07002338 pthread_mutex_lock(&adev->lock);
2339 if (get_usecase_from_list(adev, ret_uc) != NULL)
2340 ret_uc = USECASE_INVALID;
2341 pthread_mutex_unlock(&adev->lock);
2342
2343 return ret_uc;
2344 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002345
2346 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07002347 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
2348 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
2349 adev->offload_usecases_state |= 0x1 << offload_uc_index;
2350 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002351 break;
2352 }
2353 }
vivek mehta446c3962015-09-14 10:57:35 -07002354
2355 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
2356 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002357}
2358
2359static void free_offload_usecase(struct audio_device *adev,
2360 audio_usecase_t uc_id)
2361{
vivek mehta446c3962015-09-14 10:57:35 -07002362 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08002363 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07002364
2365 if (!adev->multi_offload_enable)
2366 return;
2367
2368 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
2369 if (offload_usecases[offload_uc_index] == uc_id) {
2370 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002371 break;
2372 }
2373 }
2374 ALOGV("%s: free offload usecase %d", __func__, uc_id);
2375}
2376
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002377static void *offload_thread_loop(void *context)
2378{
2379 struct stream_out *out = (struct stream_out *) context;
2380 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002381 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002382
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002383 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
2384 set_sched_policy(0, SP_FOREGROUND);
2385 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
2386
2387 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002388 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002389 for (;;) {
2390 struct offload_cmd *cmd = NULL;
2391 stream_callback_event_t event;
2392 bool send_callback = false;
2393
2394 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
2395 __func__, list_empty(&out->offload_cmd_list),
2396 out->offload_state);
2397 if (list_empty(&out->offload_cmd_list)) {
2398 ALOGV("%s SLEEPING", __func__);
2399 pthread_cond_wait(&out->offload_cond, &out->lock);
2400 ALOGV("%s RUNNING", __func__);
2401 continue;
2402 }
2403
2404 item = list_head(&out->offload_cmd_list);
2405 cmd = node_to_item(item, struct offload_cmd, node);
2406 list_remove(item);
2407
2408 ALOGVV("%s STATE %d CMD %d out->compr %p",
2409 __func__, out->offload_state, cmd->cmd, out->compr);
2410
2411 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
2412 free(cmd);
2413 break;
2414 }
2415
2416 if (out->compr == NULL) {
2417 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07002418 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002419 pthread_cond_signal(&out->cond);
2420 continue;
2421 }
2422 out->offload_thread_blocked = true;
2423 pthread_mutex_unlock(&out->lock);
2424 send_callback = false;
2425 switch(cmd->cmd) {
2426 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002427 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002428 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002429 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002430 send_callback = true;
2431 event = STREAM_CBK_EVENT_WRITE_READY;
2432 break;
2433 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002434 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05302435 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002436 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302437 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002438 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302439 if (ret < 0)
2440 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05302441 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302442 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002443 compress_drain(out->compr);
2444 else
2445 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302446 if (ret != -ENETRESET) {
2447 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302448 pthread_mutex_lock(&out->lock);
2449 out->send_new_metadata = 1;
2450 out->send_next_track_params = true;
2451 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302452 event = STREAM_CBK_EVENT_DRAIN_READY;
2453 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
2454 } else
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302455 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002456 break;
2457 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002458 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002459 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002460 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002461 send_callback = true;
2462 event = STREAM_CBK_EVENT_DRAIN_READY;
2463 break;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302464 case OFFLOAD_CMD_ERROR:
2465 ALOGD("copl(%p): sending error callback to AF", out);
2466 send_callback = true;
2467 event = STREAM_CBK_EVENT_ERROR;
2468 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002469 default:
2470 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
2471 break;
2472 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002473 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002474 out->offload_thread_blocked = false;
2475 pthread_cond_signal(&out->cond);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08002476 if (send_callback && out->client_callback) {
2477 ALOGVV("%s: sending client_callback event %d", __func__, event);
2478 out->client_callback(event, NULL, out->client_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07002479 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002480 free(cmd);
2481 }
2482
2483 pthread_cond_signal(&out->cond);
2484 while (!list_empty(&out->offload_cmd_list)) {
2485 item = list_head(&out->offload_cmd_list);
2486 list_remove(item);
2487 free(node_to_item(item, struct offload_cmd, node));
2488 }
2489 pthread_mutex_unlock(&out->lock);
2490
2491 return NULL;
2492}
2493
2494static int create_offload_callback_thread(struct stream_out *out)
2495{
2496 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
2497 list_init(&out->offload_cmd_list);
2498 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
2499 offload_thread_loop, out);
2500 return 0;
2501}
2502
2503static int destroy_offload_callback_thread(struct stream_out *out)
2504{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002505 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002506 stop_compressed_output_l(out);
2507 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
2508
2509 pthread_mutex_unlock(&out->lock);
2510 pthread_join(out->offload_thread, (void **) NULL);
2511 pthread_cond_destroy(&out->offload_cond);
2512
2513 return 0;
2514}
2515
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002516static int stop_output_stream(struct stream_out *out)
2517{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302518 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002519 struct audio_usecase *uc_info;
2520 struct audio_device *adev = out->dev;
2521
Eric Laurent994a6932013-07-17 11:51:42 -07002522 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002523 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002524 uc_info = get_usecase_from_list(adev, out->usecase);
2525 if (uc_info == NULL) {
2526 ALOGE("%s: Could not find the usecase (%d) in the list",
2527 __func__, out->usecase);
2528 return -EINVAL;
2529 }
2530
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002531 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302532 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002533 if (adev->visualizer_stop_output != NULL)
2534 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002535
2536 audio_extn_dts_remove_state_notifier_node(out->usecase);
2537
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002538 if (adev->offload_effects_stop_output != NULL)
2539 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
2540 }
Eric Laurentc4aef752013-09-12 17:45:53 -07002541
Eric Laurent150dbfe2013-02-27 14:31:02 -08002542 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002543 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002544
2545 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002546 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002547
Xiaojun Sang785b5da2017-08-03 15:52:29 +08002548 if (is_offload_usecase(out->usecase)) {
2549 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
2550 adev->dsp_bit_width_enforce_mode,
2551 false);
2552 }
2553
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002554 list_remove(&uc_info->list);
2555 free(uc_info);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302556 out->started = 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002557 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302558 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002559 ALOGV("Disable passthrough , reset mixer to pcm");
2560 /* NO_PASSTHROUGH */
2561 out->compr_config.codec->compr_passthr = 0;
Mingming Yin21854652016-04-13 11:54:02 -07002562 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002563 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
2564 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07002565
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302566 /* Must be called after removing the usecase from list */
2567 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302568 audio_extn_keep_alive_start();
2569
Manish Dewangan21a850a2017-08-14 12:03:55 +05302570 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07002571 ret = audio_extn_ip_hdlr_intf_close(out->ip_hdlr_handle, true, out);
2572 if (ret < 0)
2573 ALOGE("%s: audio_extn_ip_hdlr_intf_close failed %d",__func__, ret);
2574 }
2575
Eric Laurent994a6932013-07-17 11:51:42 -07002576 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002577 return ret;
2578}
2579
2580int start_output_stream(struct stream_out *out)
2581{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002582 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002583 struct audio_usecase *uc_info;
2584 struct audio_device *adev = out->dev;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08002585 char mixer_ctl_name[128];
2586 struct mixer_ctl *ctl = NULL;
2587 char* perf_mode[] = {"ULL", "ULL_PP", "LL"};
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302588 bool a2dp_combo = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002589
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002590 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
2591 ret = -EINVAL;
2592 goto error_config;
2593 }
2594
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302595 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
2596 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
2597 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302598
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302599 if (CARD_STATUS_OFFLINE == out->card_status ||
2600 CARD_STATUS_OFFLINE == adev->card_status) {
2601 ALOGW("out->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302602 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302603 goto error_config;
2604 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05302605
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05302606 if (out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) {
2607 if (!audio_extn_a2dp_is_ready()) {
2608 if (out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302609 a2dp_combo = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05302610 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302611 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
2612 ALOGE("%s: A2DP profile is not ready, return error", __func__);
2613 ret = -EAGAIN;
2614 goto error_config;
2615 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05302616 }
2617 }
2618 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302619 if (out->devices & AUDIO_DEVICE_OUT_ALL_SCO) {
2620 if (!adev->bt_sco_on) {
2621 if (out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
2622 //combo usecase just by pass a2dp
2623 ALOGW("%s: SCO is not connected, route it to speaker", __func__);
2624 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
2625 } else {
2626 ALOGE("%s: SCO profile is not ready, return error", __func__);
2627 ret = -EAGAIN;
2628 goto error_config;
2629 }
2630 }
2631 }
2632
Eric Laurentb23d5282013-05-14 15:27:20 -07002633 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002634 if (out->pcm_device_id < 0) {
2635 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
2636 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002637 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002638 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002639 }
2640
2641 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002642
2643 if (!uc_info) {
2644 ret = -ENOMEM;
2645 goto error_config;
2646 }
2647
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002648 uc_info->id = out->usecase;
2649 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002650 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002651 uc_info->devices = out->devices;
2652 uc_info->in_snd_device = SND_DEVICE_NONE;
2653 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002654 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002655
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302656 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2657 adev->perf_lock_opts,
2658 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302659
2660 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
2661 audio_extn_keep_alive_stop();
2662 if (audio_extn_passthru_is_enabled() &&
2663 audio_extn_passthru_is_passthrough_stream(out)) {
2664 audio_extn_passthru_on_start(out);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302665 }
2666 }
2667
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302668 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
2669 (!audio_extn_a2dp_is_ready())) {
2670 if (!a2dp_combo) {
2671 check_a2dp_restore_l(adev, out, false);
2672 } else {
2673 audio_devices_t dev = out->devices;
2674 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
2675 select_devices(adev, out->usecase);
2676 out->devices = dev;
2677 }
2678 } else {
2679 select_devices(adev, out->usecase);
2680 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002681
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002682 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
2683 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Haynes Mathew George16081042017-05-31 17:16:49 -07002684
2685 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2686 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2687 ALOGE("%s: pcm stream not ready", __func__);
2688 goto error_open;
2689 }
2690 ret = pcm_start(out->pcm);
2691 if (ret < 0) {
2692 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
2693 goto error_open;
2694 }
2695 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002696 unsigned int flags = PCM_OUT;
2697 unsigned int pcm_open_retry_count = 0;
2698 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
2699 flags |= PCM_MMAP | PCM_NOIRQ;
2700 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002701 } else if (out->realtime) {
2702 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002703 } else
2704 flags |= PCM_MONOTONIC;
2705
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08002706 if ((adev->vr_audio_mode_enabled) &&
2707 (out->flags & AUDIO_OUTPUT_FLAG_RAW)) {
2708 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2709 "PCM_Dev %d Topology", out->pcm_device_id);
2710 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2711 if (!ctl) {
2712 ALOGI("%s: Could not get ctl for mixer cmd might be ULL - %s",
2713 __func__, mixer_ctl_name);
2714 } else {
2715 //if success use ULLPP
2716 ALOGI("%s: mixer ctrl %s succeeded setting up ULL for %d",
2717 __func__, mixer_ctl_name, out->pcm_device_id);
2718 //There is a still a possibility that some sessions
2719 // that request for FAST|RAW when 3D audio is active
2720 //can go through ULLPP. Ideally we expects apps to
2721 //listen to audio focus and stop concurrent playback
2722 //Also, we will look for mode flag (voice_in_communication)
2723 //before enabling the realtime flag.
2724 mixer_ctl_set_enum_by_string(ctl, perf_mode[1]);
2725 }
2726 }
2727
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002728 while (1) {
2729 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
2730 flags, &out->config);
2731 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2732 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
2733 if (out->pcm != NULL) {
2734 pcm_close(out->pcm);
2735 out->pcm = NULL;
2736 }
2737 if (pcm_open_retry_count-- == 0) {
2738 ret = -EIO;
2739 goto error_open;
2740 }
2741 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2742 continue;
2743 }
2744 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002745 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002746
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002747 ALOGV("%s: pcm_prepare", __func__);
2748 if (pcm_is_ready(out->pcm)) {
2749 ret = pcm_prepare(out->pcm);
2750 if (ret < 0) {
2751 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2752 pcm_close(out->pcm);
2753 out->pcm = NULL;
2754 goto error_open;
2755 }
2756 }
Divya Narayanan Poojary2c429012017-04-20 16:37:20 +05302757 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05302758 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Zhou Song2b8f28f2017-09-11 10:51:38 +08002759 // apply volume for voip playback after path is set up
2760 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
2761 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002762 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002763 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05302764 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Xiaojun Sang785b5da2017-08-03 15:52:29 +08002765 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
2766 adev->dsp_bit_width_enforce_mode,
2767 true);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002768 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08002769 out->compr = compress_open(adev->snd_card,
2770 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002771 COMPRESS_IN, &out->compr_config);
2772 if (out->compr && !is_compress_ready(out->compr)) {
2773 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
2774 compress_close(out->compr);
2775 out->compr = NULL;
2776 ret = -EIO;
2777 goto error_open;
2778 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302779 /* compress_open sends params of the track, so reset the flag here */
2780 out->is_compr_metadata_avail = false;
2781
Ben Rombergerd771a7c2017-02-22 18:05:17 -08002782 if (out->client_callback)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002783 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07002784
Fred Oh3f43e742015-03-04 18:42:34 -08002785 /* Since small bufs uses blocking writes, a write will be blocked
2786 for the default max poll time (20s) in the event of an SSR.
2787 Reduce the poll time to observe and deal with SSR faster.
2788 */
Ashish Jain5106d362016-05-11 19:23:33 +05302789 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08002790 compress_set_max_poll_wait(out->compr, 1000);
2791 }
2792
Manish Dewangan69426c82017-01-30 17:35:36 +05302793 audio_extn_utils_compress_set_render_mode(out);
Manish Dewangan58229382017-02-02 15:48:41 +05302794 audio_extn_utils_compress_set_clk_rec_mode(uc_info);
Manish Dewangan69426c82017-01-30 17:35:36 +05302795
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002796 audio_extn_dts_create_state_notifier_node(out->usecase);
2797 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2798 popcount(out->channel_mask),
2799 out->playback_started);
2800
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002801#ifdef DS1_DOLBY_DDP_ENABLED
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05302802 if (audio_extn_utils_is_dolby_format(out->format))
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002803 audio_extn_dolby_send_ddp_endp_params(adev);
2804#endif
Preetam Singh Ranawatd18d8832017-02-08 17:34:54 +05302805 if (!(audio_extn_passthru_is_passthrough_stream(out)) &&
2806 (out->sample_rate != 176400 && out->sample_rate <= 192000)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002807 if (adev->visualizer_start_output != NULL)
2808 adev->visualizer_start_output(out->handle, out->pcm_device_id);
2809 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05302810 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002811 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002812 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002813 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002814
2815 if (ret == 0) {
2816 register_out_stream(out);
2817 if (out->realtime) {
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07002818 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2819 ALOGE("%s: pcm stream not ready", __func__);
2820 goto error_open;
2821 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002822 ret = pcm_start(out->pcm);
2823 if (ret < 0)
2824 goto error_open;
2825 }
2826 }
2827
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302828 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002829 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002830
Manish Dewangan21a850a2017-08-14 12:03:55 +05302831 if (out->ip_hdlr_handle) {
Vidyakumar Athota6d655882017-05-22 18:26:24 -07002832 ret = audio_extn_ip_hdlr_intf_open(out->ip_hdlr_handle, true, out, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07002833 if (ret < 0)
2834 ALOGE("%s: audio_extn_ip_hdlr_intf_open failed %d",__func__, ret);
2835 }
2836
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002837 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002838error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302839 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002840 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002841error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05302842 /*
2843 * sleep 50ms to allow sufficient time for kernel
2844 * drivers to recover incases like SSR.
2845 */
2846 usleep(50000);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002847 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002848}
2849
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002850static int check_input_parameters(uint32_t sample_rate,
2851 audio_format_t format,
2852 int channel_count)
2853{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002854 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002855
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302856 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
2857 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
2858 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07002859 !voice_extn_compress_voip_is_format_supported(format) &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302860 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002861
2862 switch (channel_count) {
2863 case 1:
2864 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05302865 case 3:
2866 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002867 case 6:
2868 break;
2869 default:
2870 ret = -EINVAL;
2871 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002872
2873 switch (sample_rate) {
2874 case 8000:
2875 case 11025:
2876 case 12000:
2877 case 16000:
2878 case 22050:
2879 case 24000:
2880 case 32000:
2881 case 44100:
2882 case 48000:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302883 case 96000:
2884 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002885 break;
2886 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002887 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002888 }
2889
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002890 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002891}
2892
2893static size_t get_input_buffer_size(uint32_t sample_rate,
2894 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002895 int channel_count,
2896 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002897{
2898 size_t size = 0;
2899
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002900 if (check_input_parameters(sample_rate, format, channel_count) != 0)
2901 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002902
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002903 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002904 if (is_low_latency)
2905 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302906
2907 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002908
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002909 /* make sure the size is multiple of 32 bytes
2910 * At 48 kHz mono 16-bit PCM:
2911 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2912 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2913 */
2914 size += 0x1f;
2915 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002916
2917 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002918}
2919
Ashish Jain058165c2016-09-28 23:18:48 +05302920static size_t get_output_period_size(uint32_t sample_rate,
2921 audio_format_t format,
2922 int channel_count,
2923 int duration /*in millisecs*/)
2924{
2925 size_t size = 0;
2926 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
2927
2928 if ((duration == 0) || (sample_rate == 0) ||
2929 (bytes_per_sample == 0) || (channel_count == 0)) {
2930 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
2931 bytes_per_sample, channel_count);
2932 return -EINVAL;
2933 }
2934
2935 size = (sample_rate *
2936 duration *
2937 bytes_per_sample *
2938 channel_count) / 1000;
2939 /*
2940 * To have same PCM samples for all channels, the buffer size requires to
2941 * be multiple of (number of channels * bytes per sample)
2942 * For writes to succeed, the buffer must be written at address which is multiple of 32
2943 */
2944 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
2945
2946 return (size/(channel_count * bytes_per_sample));
2947}
2948
Ashish Jain5106d362016-05-11 19:23:33 +05302949static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out)
2950{
2951 uint64_t actual_frames_rendered = 0;
2952 size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
2953
2954 /* This adjustment accounts for buffering after app processor.
2955 * It is based on estimated DSP latency per use case, rather than exact.
2956 */
2957 int64_t platform_latency = platform_render_latency(out->usecase) *
2958 out->sample_rate / 1000000LL;
2959
2960 /* not querying actual state of buffering in kernel as it would involve an ioctl call
2961 * which then needs protection, this causes delay in TS query for pcm_offload usecase
2962 * hence only estimate.
2963 */
2964 int64_t signed_frames = out->written - kernel_buffer_size;
2965
2966 signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask)) - platform_latency;
2967
2968 if (signed_frames > 0)
2969 actual_frames_rendered = signed_frames;
2970
2971 ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
2972 "bytes/sample %zu channel count %d", __func__,(long long int)signed_frames,
2973 (long long int)out->written, (int)kernel_buffer_size,
2974 audio_bytes_per_sample(out->compr_config.codec->format),
2975 popcount(out->channel_mask));
2976
2977 return actual_frames_rendered;
2978}
2979
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002980static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2981{
2982 struct stream_out *out = (struct stream_out *)stream;
2983
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002984 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002985}
2986
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002987static int out_set_sample_rate(struct audio_stream *stream __unused,
2988 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002989{
2990 return -ENOSYS;
2991}
2992
2993static size_t out_get_buffer_size(const struct audio_stream *stream)
2994{
2995 struct stream_out *out = (struct stream_out *)stream;
2996
Varun Balaraje49253e2017-07-06 19:48:56 +05302997 if (is_interactive_usecase(out->usecase)) {
Sri Karri27279e12017-08-07 16:05:20 +05302998 return out->config.period_size * out->config.period_count;
Varun Balaraje49253e2017-07-06 19:48:56 +05302999 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Naresh Tanniruee3499a2017-01-05 14:05:35 +05303000 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
3001 return out->compr_config.fragment_size - sizeof(struct snd_codec_metadata);
3002 else
3003 return out->compr_config.fragment_size;
3004 } else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003005 return voice_extn_compress_voip_out_get_buffer_size(out);
Vikram Panduranga93f080e2017-06-07 18:16:14 -07003006 else if(out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
3007 return VOIP_IO_BUF_SIZE(out->config.rate, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE);
Dhananjay Kumarac341582017-02-23 23:42:25 +05303008 else if (is_offload_usecase(out->usecase) &&
3009 out->flags == AUDIO_OUTPUT_FLAG_DIRECT)
Ashish Jain83a6cc22016-06-28 14:34:17 +05303010 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003011
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003012 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003013 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003014}
3015
3016static uint32_t out_get_channels(const struct audio_stream *stream)
3017{
3018 struct stream_out *out = (struct stream_out *)stream;
3019
3020 return out->channel_mask;
3021}
3022
3023static audio_format_t out_get_format(const struct audio_stream *stream)
3024{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003025 struct stream_out *out = (struct stream_out *)stream;
3026
3027 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003028}
3029
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003030static int out_set_format(struct audio_stream *stream __unused,
3031 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003032{
3033 return -ENOSYS;
3034}
3035
3036static int out_standby(struct audio_stream *stream)
3037{
3038 struct stream_out *out = (struct stream_out *)stream;
3039 struct audio_device *adev = out->dev;
kunleiza9d11682017-08-04 14:14:09 +08003040 struct audio_usecase *uc_info;
3041 struct listnode *node;
Haynes Mathew George16081042017-05-31 17:16:49 -07003042 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003043
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303044 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3045 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003046
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003047 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003048 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003049 if (adev->adm_deregister_stream)
3050 adev->adm_deregister_stream(adev->adm_data, out->handle);
3051
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07003052 if (is_offload_usecase(out->usecase))
3053 stop_compressed_output_l(out);
3054
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003055 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003056 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08003057 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
3058 voice_extn_compress_voip_close_output_stream(stream);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303059 out->started = 0;
Zhou Songa8895042016-07-05 17:54:22 +08003060 pthread_mutex_unlock(&adev->lock);
3061 pthread_mutex_unlock(&out->lock);
3062 ALOGD("VOIP output entered standby");
3063 return 0;
3064 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003065 if (out->pcm) {
3066 pcm_close(out->pcm);
3067 out->pcm = NULL;
3068 }
Haynes Mathew George16081042017-05-31 17:16:49 -07003069 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3070 do_stop = out->playback_started;
3071 out->playback_started = false;
3072 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003073 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003074 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303075 out->send_next_track_params = false;
3076 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003077 out->gapless_mdata.encoder_delay = 0;
3078 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003079 if (out->compr != NULL) {
3080 compress_close(out->compr);
3081 out->compr = NULL;
3082 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003083 }
Haynes Mathew George16081042017-05-31 17:16:49 -07003084 if (do_stop) {
3085 stop_output_stream(out);
3086 }
kunleiza9d11682017-08-04 14:14:09 +08003087 //restore output device for active usecase when current snd device and output device mismatch
3088 list_for_each(node, &adev->usecase_list) {
3089 uc_info = node_to_item(node, struct audio_usecase, list);
3090 if ((uc_info->type == PCM_PLAYBACK) &&
3091 (uc_info->out_snd_device != platform_get_output_snd_device(adev->platform, uc_info->stream.out)))
3092 select_devices(adev, uc_info->id);
3093 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003094 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003095 }
3096 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05303097 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003098 return 0;
3099}
3100
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303101static int out_on_error(struct audio_stream *stream)
3102{
3103 struct stream_out *out = (struct stream_out *)stream;
3104 bool do_standby = false;
3105
3106 lock_output_stream(out);
3107 if (!out->standby) {
3108 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
3109 stop_compressed_output_l(out);
3110 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
3111 } else
3112 do_standby = true;
3113 }
3114 pthread_mutex_unlock(&out->lock);
3115
3116 if (do_standby)
3117 return out_standby(&out->stream.common);
3118
3119 return 0;
3120}
3121
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303122/*
3123 *standby implementation without locks, assumes that the callee already
3124 *has taken adev and out lock.
3125 */
3126int out_standby_l(struct audio_stream *stream)
3127{
3128 struct stream_out *out = (struct stream_out *)stream;
3129 struct audio_device *adev = out->dev;
3130
3131 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3132 stream, out->usecase, use_case_table[out->usecase]);
3133
3134 if (!out->standby) {
3135 if (adev->adm_deregister_stream)
3136 adev->adm_deregister_stream(adev->adm_data, out->handle);
3137
3138 if (is_offload_usecase(out->usecase))
3139 stop_compressed_output_l(out);
3140
3141 out->standby = true;
3142 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
3143 voice_extn_compress_voip_close_output_stream(stream);
3144 out->started = 0;
3145 ALOGD("VOIP output entered standby");
3146 return 0;
3147 } else if (!is_offload_usecase(out->usecase)) {
3148 if (out->pcm) {
3149 pcm_close(out->pcm);
3150 out->pcm = NULL;
3151 }
3152 } else {
3153 ALOGD("copl(%p):standby", out);
3154 out->send_next_track_params = false;
3155 out->is_compr_metadata_avail = false;
3156 out->gapless_mdata.encoder_delay = 0;
3157 out->gapless_mdata.encoder_padding = 0;
3158 if (out->compr != NULL) {
3159 compress_close(out->compr);
3160 out->compr = NULL;
3161 }
3162 }
3163 stop_output_stream(out);
3164 }
3165 ALOGD("%s: exit", __func__);
3166 return 0;
3167}
3168
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003169static int out_dump(const struct audio_stream *stream __unused,
3170 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003171{
3172 return 0;
3173}
3174
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003175static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
3176{
3177 int ret = 0;
3178 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08003179
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003180 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08003181 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003182 return -EINVAL;
3183 }
3184
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05303185 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08003186
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003187 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
3188 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05303189 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003190 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003191 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
3192 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05303193 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003194 }
3195
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003196 ALOGV("%s new encoder delay %u and padding %u", __func__,
3197 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
3198
3199 return 0;
3200}
3201
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003202static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
3203{
3204 return out == adev->primary_output || out == adev->voice_tx_output;
3205}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003206
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303207// note: this call is safe only if the stream_cb is
3208// removed first in close_output_stream (as is done now).
3209static void out_snd_mon_cb(void * stream, struct str_parms * parms)
3210{
3211 if (!stream || !parms)
3212 return;
3213
3214 struct stream_out *out = (struct stream_out *)stream;
3215 struct audio_device *adev = out->dev;
3216
3217 card_status_t status;
3218 int card;
3219 if (parse_snd_card_status(parms, &card, &status) < 0)
3220 return;
3221
3222 pthread_mutex_lock(&adev->lock);
3223 bool valid_cb = (card == adev->snd_card);
3224 pthread_mutex_unlock(&adev->lock);
3225
3226 if (!valid_cb)
3227 return;
3228
3229 lock_output_stream(out);
3230 if (out->card_status != status)
3231 out->card_status = status;
3232 pthread_mutex_unlock(&out->lock);
3233
3234 ALOGI("out_snd_mon_cb for card %d usecase %s, status %s", card,
3235 use_case_table[out->usecase],
3236 status == CARD_STATUS_OFFLINE ? "offline" : "online");
3237
3238 if (status == CARD_STATUS_OFFLINE)
3239 out_on_error(stream);
3240
3241 return;
3242}
3243
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003244static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
3245{
3246 struct stream_out *out = (struct stream_out *)stream;
3247 struct audio_device *adev = out->dev;
3248 struct str_parms *parms;
3249 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003250 int ret = 0, val = 0, err;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303251 bool bypass_a2dp = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003252
sangwoobc677242013-08-08 16:53:43 +09003253 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003254 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003255 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303256 if (!parms)
3257 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003258 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
3259 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003260 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003261 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003262 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003263
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003264 /*
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08003265 * When HDMI cable is unplugged the music playback is paused and
3266 * the policy manager sends routing=0. But the audioflinger continues
3267 * to write data until standby time (3sec). As the HDMI core is
3268 * turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003269 * Avoid this by routing audio to speaker until standby.
3270 */
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08003271 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
3272 (val == AUDIO_DEVICE_NONE) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303273 !audio_extn_passthru_is_passthrough_stream(out) &&
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08003274 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
3275 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003276 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05303277 /*
3278 * When A2DP is disconnected the
3279 * music playback is paused and the policy manager sends routing=0
3280 * But the audioflingercontinues to write data until standby time
3281 * (3sec). As BT is turned off, the write gets blocked.
3282 * Avoid this by routing audio to speaker until standby.
3283 */
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07003284 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Naresh Tanniru9d027a62015-03-13 01:32:10 +05303285 (val == AUDIO_DEVICE_NONE)) {
3286 val = AUDIO_DEVICE_OUT_SPEAKER;
3287 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303288 /* To avoid a2dp to sco overlapping / BT device improper state
3289 * check with BT lib about a2dp streaming support before routing
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05303290 */
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303291 if (val & AUDIO_DEVICE_OUT_ALL_A2DP) {
3292 if (!audio_extn_a2dp_is_ready()) {
3293 if (val & AUDIO_DEVICE_OUT_SPEAKER) {
3294 //combo usecase just by pass a2dp
3295 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303296 bypass_a2dp = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303297 } else {
3298 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
3299 /* update device to a2dp and don't route as BT returned error
3300 * However it is still possible a2dp routing called because
3301 * of current active device disconnection (like wired headset)
3302 */
3303 out->devices = val;
3304 pthread_mutex_unlock(&out->lock);
3305 pthread_mutex_unlock(&adev->lock);
3306 goto error;
3307 }
3308 }
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05303309 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003310 /*
3311 * select_devices() call below switches all the usecases on the same
3312 * backend to the new device. Refer to check_usecases_codec_backend() in
3313 * the select_devices(). But how do we undo this?
3314 *
3315 * For example, music playback is active on headset (deep-buffer usecase)
3316 * and if we go to ringtones and select a ringtone, low-latency usecase
3317 * will be started on headset+speaker. As we can't enable headset+speaker
3318 * and headset devices at the same time, select_devices() switches the music
3319 * playback to headset+speaker while starting low-lateny usecase for ringtone.
3320 * So when the ringtone playback is completed, how do we undo the same?
3321 *
3322 * We are relying on the out_set_parameters() call on deep-buffer output,
3323 * once the ringtone playback is ended.
3324 * NOTE: We should not check if the current devices are same as new devices.
3325 * Because select_devices() must be called to switch back the music
3326 * playback to headset.
3327 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003328 if (val != 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003329 audio_devices_t new_dev = val;
3330 bool same_dev = out->devices == new_dev;
3331 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003332
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07003333 if (output_drives_call(adev, out)) {
3334 if(!voice_is_in_call(adev)) {
3335 if (adev->mode == AUDIO_MODE_IN_CALL) {
3336 adev->current_call_output = out;
3337 ret = voice_start_call(adev);
3338 }
3339 } else {
3340 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003341 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07003342 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003343 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08003344
3345 if (!out->standby) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003346 if (!same_dev) {
3347 ALOGV("update routing change");
Sudheer Papothi80266982016-08-16 02:36:18 +05303348 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3349 adev->perf_lock_opts,
3350 adev->perf_lock_opts_size);
Haynes Mathew George822b5492016-07-01 16:57:24 -07003351 if (adev->adm_on_routing_change)
3352 adev->adm_on_routing_change(adev->adm_data,
3353 out->handle);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003354 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303355 if (!bypass_a2dp) {
3356 select_devices(adev, out->usecase);
3357 } else {
3358 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
3359 select_devices(adev, out->usecase);
3360 out->devices = new_dev;
3361 }
Sudheer Papothi80266982016-08-16 02:36:18 +05303362 if (!same_dev)
3363 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303364 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
3365 out->a2dp_compress_mute &&
Zhou Songc66eb7e2017-08-08 18:29:07 +08003366 (!(out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) || audio_extn_a2dp_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303367 pthread_mutex_lock(&out->compr_mute_lock);
3368 out->a2dp_compress_mute = false;
3369 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
3370 pthread_mutex_unlock(&out->compr_mute_lock);
3371 }
3372
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08003373 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003374 }
3375
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003376 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003377 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003378 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003379
3380 if (out == adev->primary_output) {
3381 pthread_mutex_lock(&adev->lock);
3382 audio_extn_set_parameters(adev, parms);
3383 pthread_mutex_unlock(&adev->lock);
3384 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003385 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003386 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003387 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003388
3389 audio_extn_dts_create_state_notifier_node(out->usecase);
3390 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3391 popcount(out->channel_mask),
3392 out->playback_started);
3393
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08003394 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003395 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003396
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05303397 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
3398 if (err >= 0) {
3399 strlcpy(out->profile, value, sizeof(out->profile));
3400 ALOGV("updating stream profile with value '%s'", out->profile);
3401 lock_output_stream(out);
3402 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
3403 &adev->streams_output_cfg_list,
Aalique Grahame65780b52017-09-27 14:59:56 -07003404 out->devices, out->flags, out->hal_op_format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05303405 out->sample_rate, out->bit_width,
3406 out->channel_mask, out->profile,
3407 &out->app_type_cfg);
3408 pthread_mutex_unlock(&out->lock);
3409 }
3410
Alexy Joseph98988832017-01-13 14:56:59 -08003411 //suspend, resume handling block
3412 if (out->dynamic_pm_qos_enabled) {
3413 //check suspend parameter only for low latency and if the property
3414 //is enabled
3415 if (str_parms_get_str(parms, "suspend_playback", value, sizeof(value)) >= 0) {
3416 ALOGI("%s: got suspend_playback %s", __func__, value);
3417 lock_output_stream(out);
3418 if (!strncmp(value, "false", 5)) {
3419 //suspend_playback=false is supposed to set QOS value back to 75%
3420 //the mixer control sent with value Enable will achieve that
3421 ret = audio_route_apply_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
3422 } else if (!strncmp (value, "true", 4)) {
3423 //suspend_playback=true is supposed to remove QOS value
3424 //resetting the mixer control will set the default value
3425 //for the mixer control which is Disable and this removes the QOS vote
3426 ret = audio_route_reset_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
3427 } else {
3428 ALOGE("%s: Wrong value sent for suspend_playback, expected true/false,"
3429 " got %s", __func__, value);
3430 ret = -1;
3431 }
3432
3433 if (ret != 0) {
3434 ALOGE("%s: %s mixer ctl failed with %d, ignore suspend/resume setparams",
3435 __func__, out->pm_qos_mixer_path, ret);
3436 }
3437
3438 pthread_mutex_unlock(&out->lock);
3439 }
3440 }
3441 //end suspend, resume handling block
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003442 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303443error:
Eric Laurent994a6932013-07-17 11:51:42 -07003444 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003445 return ret;
3446}
3447
3448static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
3449{
3450 struct stream_out *out = (struct stream_out *)stream;
3451 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003452 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003453 char value[256];
3454 struct str_parms *reply = str_parms_create();
3455 size_t i, j;
3456 int ret;
3457 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003458
3459 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003460 if (reply) {
3461 str_parms_destroy(reply);
3462 }
3463 if (query) {
3464 str_parms_destroy(query);
3465 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003466 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
3467 return NULL;
3468 }
3469
Eric Laurent994a6932013-07-17 11:51:42 -07003470 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003471 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
3472 if (ret >= 0) {
3473 value[0] = '\0';
3474 i = 0;
3475 while (out->supported_channel_masks[i] != 0) {
3476 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
3477 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
3478 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08003479 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003480 }
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08003481 strlcat(value, out_channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003482 first = false;
3483 break;
3484 }
3485 }
3486 i++;
3487 }
3488 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
3489 str = str_parms_to_str(reply);
3490 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003491 voice_extn_out_get_parameters(out, query, reply);
3492 str = str_parms_to_str(reply);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003493 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003494
Alexy Joseph62142aa2015-11-16 15:10:34 -08003495
3496 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
3497 if (ret >= 0) {
3498 value[0] = '\0';
Dhananjay Kumarac341582017-02-23 23:42:25 +05303499 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
3500 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Alexy Joseph62142aa2015-11-16 15:10:34 -08003501 ALOGV("in direct_pcm");
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05303502 strlcat(value, "true", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08003503 } else {
3504 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05303505 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08003506 }
3507 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003508 if (str)
3509 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08003510 str = str_parms_to_str(reply);
3511 }
3512
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003513 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
3514 if (ret >= 0) {
3515 value[0] = '\0';
3516 i = 0;
3517 first = true;
3518 while (out->supported_formats[i] != 0) {
3519 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
3520 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
3521 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08003522 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003523 }
3524 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
3525 first = false;
3526 break;
3527 }
3528 }
3529 i++;
3530 }
3531 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003532 if (str)
3533 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003534 str = str_parms_to_str(reply);
3535 }
Mingming Yin3a941d42016-02-17 18:08:05 -08003536
3537 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
3538 if (ret >= 0) {
3539 value[0] = '\0';
3540 i = 0;
3541 first = true;
3542 while (out->supported_sample_rates[i] != 0) {
3543 for (j = 0; j < ARRAY_SIZE(out_hdmi_sample_rates_name_to_enum_table); j++) {
3544 if (out_hdmi_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
3545 if (!first) {
3546 strlcat(value, "|", sizeof(value));
3547 }
3548 strlcat(value, out_hdmi_sample_rates_name_to_enum_table[j].name, sizeof(value));
3549 first = false;
3550 break;
3551 }
3552 }
3553 i++;
3554 }
3555 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
3556 if (str)
3557 free(str);
3558 str = str_parms_to_str(reply);
3559 }
3560
Alexy Joseph98988832017-01-13 14:56:59 -08003561 if (str_parms_get_str(query, "supports_hw_suspend", value, sizeof(value)) >= 0) {
3562 //only low latency track supports suspend_resume
3563 str_parms_add_int(reply, "supports_hw_suspend",
3564 (out->dynamic_pm_qos_enabled));
3565 if (str)
3566 free(str);
3567 str = str_parms_to_str(reply);
3568 }
3569
3570
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003571 str_parms_destroy(query);
3572 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07003573 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003574 return str;
3575}
3576
3577static uint32_t out_get_latency(const struct audio_stream_out *stream)
3578{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003579 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003580 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08003581 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003582
Alexy Josephaa54c872014-12-03 02:46:47 -08003583 if (is_offload_usecase(out->usecase)) {
Manish Dewangan07de2142017-02-27 19:27:20 +05303584 lock_output_stream(out);
3585 latency = audio_extn_utils_compress_get_dsp_latency(out);
3586 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07003587 } else if ((out->realtime) ||
3588 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003589 // since the buffer won't be filled up faster than realtime,
3590 // return a smaller number
3591 if (out->config.rate)
3592 period_ms = (out->af_period_multiplier * out->config.period_size *
3593 1000) / (out->config.rate);
3594 else
3595 period_ms = 0;
3596 latency = period_ms + platform_render_latency(out->usecase)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08003597 } else {
3598 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003599 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08003600 }
3601
yidongh0515e042017-07-06 15:00:34 +08003602 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices)
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -08003603 latency += audio_extn_a2dp_get_encoder_latency();
3604
Anish Kumar50ebcbf2014-12-09 04:01:39 +05303605 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08003606 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003607}
3608
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303609static float AmpToDb(float amplification)
3610{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05303611 float db = DSD_VOLUME_MIN_DB;
3612 if (amplification > 0) {
3613 db = 20 * log10(amplification);
3614 if(db < DSD_VOLUME_MIN_DB)
3615 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303616 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05303617 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303618}
3619
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303620static int out_set_compr_volume(struct audio_stream_out *stream, float left,
3621 float right)
3622{
3623 struct stream_out *out = (struct stream_out *)stream;
3624 int volume[2];
3625 char mixer_ctl_name[128];
3626 struct audio_device *adev = out->dev;
3627 struct mixer_ctl *ctl;
3628 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
3629 PCM_PLAYBACK);
3630
3631 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
3632 "Compress Playback %d Volume", pcm_device_id);
3633 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3634 if (!ctl) {
3635 ALOGE("%s: Could not get ctl for mixer cmd - %s",
3636 __func__, mixer_ctl_name);
3637 return -EINVAL;
3638 }
3639 ALOGE("%s:ctl for mixer cmd - %s, left %f, right %f",
3640 __func__, mixer_ctl_name, left, right);
3641 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
3642 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
3643 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
3644
3645 return 0;
3646}
3647
Zhou Song2b8f28f2017-09-11 10:51:38 +08003648static int out_set_voip_volume(struct audio_stream_out *stream, float left,
3649 float right)
3650{
3651 struct stream_out *out = (struct stream_out *)stream;
3652 char mixer_ctl_name[] = "App Type Gain";
3653 struct audio_device *adev = out->dev;
3654 struct mixer_ctl *ctl;
3655 uint32_t set_values[4];
3656
3657 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3658 if (!ctl) {
3659 ALOGE("%s: Could not get ctl for mixer cmd - %s",
3660 __func__, mixer_ctl_name);
3661 return -EINVAL;
3662 }
3663
3664 set_values[0] = 0; //0: Rx Session 1:Tx Session
3665 set_values[1] = out->app_type_cfg.app_type;
3666 set_values[2] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
3667 set_values[3] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
3668
3669 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
3670 return 0;
3671}
3672
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003673static int out_set_volume(struct audio_stream_out *stream, float left,
3674 float right)
3675{
Eric Laurenta9024de2013-04-04 09:19:12 -07003676 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003677 int volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303678 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003679
Eric Laurenta9024de2013-04-04 09:19:12 -07003680 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
3681 /* only take left channel into account: the API is for stereo anyway */
3682 out->muted = (left == 0.0f);
3683 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003684 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303685 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003686 /*
3687 * Set mute or umute on HDMI passthrough stream.
3688 * Only take left channel into account.
3689 * Mute is 0 and unmute 1
3690 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303691 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303692 } else if (out->format == AUDIO_FORMAT_DSD){
3693 char mixer_ctl_name[128] = "DSD Volume";
3694 struct audio_device *adev = out->dev;
3695 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3696
3697 if (!ctl) {
3698 ALOGE("%s: Could not get ctl for mixer cmd - %s",
3699 __func__, mixer_ctl_name);
3700 return -EINVAL;
3701 }
3702 volume[0] = (int)(AmpToDb(left));
3703 volume[1] = (int)(AmpToDb(right));
3704 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
3705 return 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003706 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303707 pthread_mutex_lock(&out->compr_mute_lock);
3708 ALOGE("%s: compress mute %d", __func__, out->a2dp_compress_mute);
3709 if (!out->a2dp_compress_mute)
3710 ret = out_set_compr_volume(stream, left, right);
3711 out->volume_l = left;
3712 out->volume_r = right;
3713 pthread_mutex_unlock(&out->compr_mute_lock);
3714 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003715 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07003716 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
Zhou Song2b8f28f2017-09-11 10:51:38 +08003717 if (!out->standby)
3718 ret = out_set_voip_volume(stream, left, right);
3719 out->volume_l = left;
3720 out->volume_r = right;
3721 return ret;
Eric Laurenta9024de2013-04-04 09:19:12 -07003722 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003723
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003724 return -ENOSYS;
3725}
3726
Zhou Songc9672822017-08-16 16:01:39 +08003727static void update_frames_written(struct stream_out *out, size_t bytes)
3728{
3729 size_t bpf = 0;
3730
3731 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
3732 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
3733 bpf = 1;
3734 else if (!is_offload_usecase(out->usecase))
3735 bpf = audio_bytes_per_sample(out->format) *
3736 audio_channel_count_from_out_mask(out->channel_mask);
3737 if (bpf != 0)
3738 out->written += bytes / bpf;
3739}
3740
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003741static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
3742 size_t bytes)
3743{
3744 struct stream_out *out = (struct stream_out *)stream;
3745 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07003746 ssize_t ret = 0;
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05303747 int channels = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003748
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003749 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303750
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303751 if (CARD_STATUS_OFFLINE == out->card_status) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08003752
Dhananjay Kumarac341582017-02-23 23:42:25 +05303753 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Ashish Jainbbce4322016-02-16 13:25:27 +05303754 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05303755 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
3756 pthread_mutex_unlock(&out->lock);
3757 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05303758 } else {
Ashish Jainbbce4322016-02-16 13:25:27 +05303759 ALOGD(" %s: sound card is not active/SSR state", __func__);
3760 ret= -EIO;
3761 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303762 }
3763 }
3764
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303765 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303766 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303767 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303768 goto exit;
3769 }
3770
Haynes Mathew George16081042017-05-31 17:16:49 -07003771 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3772 ret = -EINVAL;
3773 goto exit;
3774 }
3775
Manish Dewangan37864bc2017-06-09 12:28:37 +05303776 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05303777 channels = platform_edid_get_max_channels(out->dev->platform);
Manish Dewangan672001f2017-08-16 13:44:07 +05303778 if (audio_extn_passthru_is_enabled() &&
3779 !out->is_iec61937_info_available &&
3780 audio_extn_passthru_is_passthrough_stream(out)) {
Manish Dewangan37864bc2017-06-09 12:28:37 +05303781 audio_extn_passthru_update_stream_configuration(adev, out,
3782 buffer, bytes);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05303783 if ((out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
3784 !out->is_iec61937_info_available) {
3785
3786 if (!audio_extn_passthru_is_passthrough_stream(out)) {
3787 out->is_iec61937_info_available = true;
3788 } else if (audio_extn_passthru_is_enabled()) {
3789 audio_extn_passthru_update_stream_configuration(adev, out, buffer, bytes);
Manish Dewangan37864bc2017-06-09 12:28:37 +05303790 out->is_iec61937_info_available = true;
Manish Dewangan671a4202017-08-18 17:30:46 +05303791
3792 if((out->format == AUDIO_FORMAT_DTS) ||
3793 (out->format == AUDIO_FORMAT_DTS_HD)) {
3794 ret = audio_extn_passthru_update_dts_stream_configuration(out,
3795 buffer, bytes);
3796 if (ret) {
3797 if (ret != -ENOSYS) {
3798 out->is_iec61937_info_available = false;
3799 ALOGD("iec61937 transmission info not yet updated retry");
3800 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05303801 } else if (!out->standby) {
Manish Dewangan671a4202017-08-18 17:30:46 +05303802 /* if stream has started and after that there is
3803 * stream config change (iec transmission config)
3804 * then trigger select_device to update backend configuration.
3805 */
3806 out->stream_config_changed = true;
3807 pthread_mutex_lock(&adev->lock);
3808 select_devices(adev, out->usecase);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05303809 if (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out)) {
3810 ret = -EINVAL;
3811 goto exit;
3812 }
Manish Dewangan671a4202017-08-18 17:30:46 +05303813 pthread_mutex_unlock(&adev->lock);
3814 out->stream_config_changed = false;
3815 out->is_iec61937_info_available = true;
3816 }
3817 }
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05303818
Garmond Leung317cbf12017-09-13 16:20:50 -07003819 if ((channels < (int)audio_channel_count_from_out_mask(out->channel_mask)) &&
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05303820 (out->compr_config.codec->compr_passthr == PASSTHROUGH) &&
3821 (out->is_iec61937_info_available == true)) {
3822 ALOGE("%s: ERROR: Unsupported channel config in passthrough mode", __func__);
3823 ret = -EINVAL;
3824 goto exit;
3825 }
Manish Dewangan37864bc2017-06-09 12:28:37 +05303826 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05303827 }
Manish Dewangan37864bc2017-06-09 12:28:37 +05303828 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303829
3830 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
3831 (audio_extn_a2dp_is_suspended())) {
3832 if (!(out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
3833 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303834 ret = -EIO;
3835 goto exit;
3836 }
3837 }
3838 }
3839
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003840 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003841 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08003842 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003843 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
3844 ret = voice_extn_compress_voip_start_output_stream(out);
3845 else
3846 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003847 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003848 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003849 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003850 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003851 goto exit;
3852 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303853 out->started = 1;
vivek mehtab72d08d2016-04-29 03:16:47 -07003854 if (last_known_cal_step != -1) {
3855 ALOGD("%s: retry previous failed cal level set", __func__);
3856 audio_hw_send_gain_dep_calibration(last_known_cal_step);
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +05303857 last_known_cal_step = -1;
vivek mehtab72d08d2016-04-29 03:16:47 -07003858 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05303859
3860 if ((out->is_iec61937_info_available == true) &&
3861 (audio_extn_passthru_is_passthrough_stream(out))&&
3862 (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out))) {
3863 ret = -EINVAL;
3864 goto exit;
3865 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003866 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003867
Ashish Jain81eb2a82015-05-13 10:52:34 +05303868 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08003869 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05303870 adev->is_channel_status_set = true;
3871 }
3872
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003873 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08003874 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003875 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003876 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003877 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
3878 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303879 if (out->send_next_track_params && out->is_compr_metadata_avail) {
3880 ALOGD("copl(%p):send next track params in gapless", out);
3881 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
3882 out->send_next_track_params = false;
3883 out->is_compr_metadata_avail = false;
3884 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003885 }
Dhananjay Kumarac341582017-02-23 23:42:25 +05303886 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05303887 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003888
Ashish Jain83a6cc22016-06-28 14:34:17 +05303889 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05303890 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05303891 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05303892 pthread_mutex_unlock(&out->lock);
3893 return -EINVAL;
3894 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05303895 audio_format_t dst_format = out->hal_op_format;
3896 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303897
3898 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
3899 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
3900
Ashish Jain83a6cc22016-06-28 14:34:17 +05303901 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05303902 dst_format,
3903 buffer,
3904 src_format,
3905 frames);
3906
Ashish Jain83a6cc22016-06-28 14:34:17 +05303907 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05303908 bytes_to_write);
3909
3910 /*Convert written bytes in audio flinger format*/
3911 if (ret > 0)
3912 ret = ((ret * format_to_bitwidth_table[out->format]) /
3913 format_to_bitwidth_table[dst_format]);
3914 }
3915 } else
3916 ret = compress_write(out->compr, buffer, bytes);
3917
Zhou Songc9672822017-08-16 16:01:39 +08003918 if ((ret < 0 || ret == (ssize_t)bytes) && !out->non_blocking)
3919 update_frames_written(out, bytes);
3920
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303921 if (ret < 0)
3922 ret = -errno;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303923 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %zd", __func__, bytes, ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05303924 /*msg to cb thread only if non blocking write is enabled*/
3925 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05303926 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003927 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05303928 } else if (-ENETRESET == ret) {
3929 ALOGE("copl %s: received sound card offline state on compress write", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303930 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru80659832014-06-04 18:17:56 +05303931 pthread_mutex_unlock(&out->lock);
Dhananjay Kumar1248dd82017-07-28 21:22:16 +05303932 out_on_error(&out->stream.common);
Naresh Tanniru80659832014-06-04 18:17:56 +05303933 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003934 }
Ashish Jain5106d362016-05-11 19:23:33 +05303935
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05303936 /* Call compr start only when non-zero bytes of data is there to be rendered */
3937 if (!out->playback_started && ret > 0) {
3938 int status = compress_start(out->compr);
3939 if (status < 0) {
3940 ret = status;
3941 ALOGE("%s: compr start failed with err %d", __func__, errno);
3942 goto exit;
3943 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07003944 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003945 out->playback_started = 1;
3946 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003947
3948 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3949 popcount(out->channel_mask),
3950 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003951 }
3952 pthread_mutex_unlock(&out->lock);
3953 return ret;
3954 } else {
3955 if (out->pcm) {
3956 if (out->muted)
3957 memset((void *)buffer, 0, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003958
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303959 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003960
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003961 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003962
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003963 if (out->config.rate)
3964 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
3965 out->config.rate;
3966
3967 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
3968
3969 request_out_focus(out, ns);
3970
3971 if (use_mmap)
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003972 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003973 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05303974 out->convert_buffer != NULL) {
3975
3976 memcpy_by_audio_format(out->convert_buffer,
3977 out->hal_op_format,
3978 buffer,
3979 out->hal_ip_format,
3980 out->config.period_size * out->config.channels);
3981
3982 ret = pcm_write(out->pcm, out->convert_buffer,
3983 (out->config.period_size *
3984 out->config.channels *
3985 format_to_bitwidth_table[out->hal_op_format]));
3986 } else {
Aditya Bavanarid4db8ee2017-05-29 21:08:03 +05303987 /*
3988 * To avoid underrun in DSP when the application is not pumping
3989 * data at required rate, check for the no. of bytes and ignore
3990 * pcm_write if it is less than actual buffer size.
3991 * It is a work around to a change in compress VOIP driver.
3992 */
3993 if ((out->flags & AUDIO_OUTPUT_FLAG_VOIP_RX) &&
3994 bytes < (out->config.period_size * out->config.channels *
3995 audio_bytes_per_sample(out->format))) {
3996 size_t voip_buf_size =
3997 out->config.period_size * out->config.channels *
3998 audio_bytes_per_sample(out->format);
3999 ALOGE("%s:VOIP underrun: bytes received %zu, required:%zu\n",
4000 __func__, bytes, voip_buf_size);
4001 usleep(((uint64_t)voip_buf_size - bytes) *
4002 1000000 / audio_stream_out_frame_size(stream) /
4003 out_get_sample_rate(&out->stream.common));
4004 ret = 0;
4005 } else
4006 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Ashish Jain83a6cc22016-06-28 14:34:17 +05304007 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004008
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004009 release_out_focus(out);
4010
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05304011 if (ret < 0)
4012 ret = -errno;
Zhou Songc9672822017-08-16 16:01:39 +08004013 else if (ret > 0)
Ashish Jain83a6cc22016-06-28 14:34:17 +05304014 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004015 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004016 }
4017
4018exit:
Zhou Songc9672822017-08-16 16:01:39 +08004019 update_frames_written(out, bytes);
Naresh Tanniru4c630392014-05-12 01:05:52 +05304020 if (-ENETRESET == ret) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304021 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304022 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004023 pthread_mutex_unlock(&out->lock);
4024
4025 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004026 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08004027 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05304028 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304029 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05304030 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304031 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304032 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05304033 out->standby = true;
4034 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304035 out_on_error(&out->stream.common);
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05304036 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
4037 usleep((uint64_t)bytes * 1000000 / audio_stream_out_frame_size(stream) /
4038 out_get_sample_rate(&out->stream.common));
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07004039
4040 if (audio_extn_passthru_is_passthrough_stream(out)) {
Garmond Leung317cbf12017-09-13 16:20:50 -07004041 ALOGE("%s: write error, ret = %ld", __func__, ret);
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07004042 return ret;
4043 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004044 }
4045 return bytes;
4046}
4047
4048static int out_get_render_position(const struct audio_stream_out *stream,
4049 uint32_t *dsp_frames)
4050{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004051 struct stream_out *out = (struct stream_out *)stream;
Zhou Song32a556e2015-05-05 10:46:56 +08004052
4053 if (dsp_frames == NULL)
4054 return -EINVAL;
4055
4056 *dsp_frames = 0;
4057 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08004058 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05304059
4060 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
4061 * this operation and adev_close_output_stream(where out gets reset).
4062 */
Dhananjay Kumarac341582017-02-23 23:42:25 +05304063 if (!out->non_blocking && !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05304064 *dsp_frames = get_actual_pcm_frames_rendered(out);
4065 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
4066 return 0;
4067 }
4068
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004069 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05304070 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05304071 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004072 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05304073 if (ret < 0)
4074 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004075 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05304076 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004077 }
Naresh Tanniru80659832014-06-04 18:17:56 +05304078 if (-ENETRESET == ret) {
4079 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304080 out->card_status = CARD_STATUS_OFFLINE;
4081 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05304082 } else if(ret < 0) {
4083 ALOGE(" ERROR: Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304084 ret = -EINVAL;
4085 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05304086 /*
4087 * Handle corner case where compress session is closed during SSR
4088 * and timestamp is queried
4089 */
4090 ALOGE(" ERROR: sound card not active, return error");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304091 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05304092 } else {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304093 ret = 0;
Naresh Tanniru80659832014-06-04 18:17:56 +05304094 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304095 pthread_mutex_unlock(&out->lock);
4096 return ret;
Zhou Song32a556e2015-05-05 10:46:56 +08004097 } else if (audio_is_linear_pcm(out->format)) {
4098 *dsp_frames = out->written;
4099 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004100 } else
4101 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004102}
4103
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004104static int out_add_audio_effect(const struct audio_stream *stream __unused,
4105 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004106{
4107 return 0;
4108}
4109
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004110static int out_remove_audio_effect(const struct audio_stream *stream __unused,
4111 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004112{
4113 return 0;
4114}
4115
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004116static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
4117 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004118{
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05304119 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004120}
4121
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004122static int out_get_presentation_position(const struct audio_stream_out *stream,
4123 uint64_t *frames, struct timespec *timestamp)
4124{
4125 struct stream_out *out = (struct stream_out *)stream;
4126 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07004127 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004128
Ashish Jain5106d362016-05-11 19:23:33 +05304129 /* below piece of code is not guarded against any lock because audioFliner serializes
4130 * this operation and adev_close_output_stream( where out gets reset).
4131 */
4132 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
Dhananjay Kumarac341582017-02-23 23:42:25 +05304133 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05304134 *frames = get_actual_pcm_frames_rendered(out);
4135 /* this is the best we can do */
4136 clock_gettime(CLOCK_MONOTONIC, timestamp);
4137 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
4138 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
4139 return 0;
4140 }
4141
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004142 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004143
Ashish Jain5106d362016-05-11 19:23:33 +05304144 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
4145 ret = compress_get_tstamp(out->compr, &dsp_frames,
4146 &out->sample_rate);
yidongh0515e042017-07-06 15:00:34 +08004147 // Adjustment accounts for A2dp encoder latency with offload usecases
4148 // Note: Encoder latency is returned in ms.
4149 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
4150 unsigned long offset =
4151 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
4152 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
4153 }
Ashish Jain5106d362016-05-11 19:23:33 +05304154 ALOGVV("%s rendered frames %ld sample_rate %d",
4155 __func__, dsp_frames, out->sample_rate);
4156 *frames = dsp_frames;
4157 if (ret < 0)
4158 ret = -errno;
4159 if (-ENETRESET == ret) {
4160 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304161 out->card_status = CARD_STATUS_OFFLINE;
Ashish Jain5106d362016-05-11 19:23:33 +05304162 ret = -EINVAL;
4163 } else
4164 ret = 0;
4165 /* this is the best we can do */
4166 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07004167 } else {
4168 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004169 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07004170 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
4171 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07004172 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07004173 // This adjustment accounts for buffering after app processor.
4174 // It is based on estimated DSP latency per use case, rather than exact.
4175 signed_frames -=
4176 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
4177
Aniket Kumar Lataff613152017-07-18 18:19:21 -07004178 // Adjustment accounts for A2dp encoder latency with non offload usecases
4179 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
4180 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
4181 signed_frames -=
4182 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
4183 }
4184
Eric Laurent949a0892013-09-20 09:20:13 -07004185 // It would be unusual for this value to be negative, but check just in case ...
4186 if (signed_frames >= 0) {
4187 *frames = signed_frames;
4188 ret = 0;
4189 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004190 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304191 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Ashish Jainbbce4322016-02-16 13:25:27 +05304192 *frames = out->written;
4193 clock_gettime(CLOCK_MONOTONIC, timestamp);
4194 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004195 }
4196 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004197 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004198 return ret;
4199}
4200
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004201static int out_set_callback(struct audio_stream_out *stream,
4202 stream_callback_t callback, void *cookie)
4203{
4204 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08004205 int ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004206
4207 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004208 lock_output_stream(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08004209 out->client_callback = callback;
4210 out->client_cookie = cookie;
4211 if (out->adsp_hdlr_stream_handle) {
4212 ret = audio_extn_adsp_hdlr_stream_set_callback(
4213 out->adsp_hdlr_stream_handle,
4214 callback,
4215 cookie);
4216 if (ret)
4217 ALOGW("%s:adsp hdlr callback registration failed %d",
4218 __func__, ret);
4219 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004220 pthread_mutex_unlock(&out->lock);
4221 return 0;
4222}
4223
4224static int out_pause(struct audio_stream_out* stream)
4225{
4226 struct stream_out *out = (struct stream_out *)stream;
4227 int status = -ENOSYS;
4228 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004229 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004230 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004231 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004232 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304233 if (out->card_status != CARD_STATUS_OFFLINE)
Naresh Tanniru80659832014-06-04 18:17:56 +05304234 status = compress_pause(out->compr);
4235
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004236 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004237
Mingming Yin21854652016-04-13 11:54:02 -07004238 if (audio_extn_passthru_is_active()) {
4239 ALOGV("offload use case, pause passthru");
4240 audio_extn_passthru_on_pause(out);
4241 }
4242
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05304243 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004244 audio_extn_dts_notify_playback_state(out->usecase, 0,
4245 out->sample_rate, popcount(out->channel_mask),
4246 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004247 }
4248 pthread_mutex_unlock(&out->lock);
4249 }
4250 return status;
4251}
4252
4253static int out_resume(struct audio_stream_out* stream)
4254{
4255 struct stream_out *out = (struct stream_out *)stream;
4256 int status = -ENOSYS;
4257 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004258 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004259 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004260 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004261 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004262 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304263 if (out->card_status != CARD_STATUS_OFFLINE) {
Naresh Tanniru80659832014-06-04 18:17:56 +05304264 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07004265 }
4266 if (!status) {
4267 out->offload_state = OFFLOAD_STATE_PLAYING;
4268 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05304269 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004270 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4271 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004272 }
4273 pthread_mutex_unlock(&out->lock);
4274 }
4275 return status;
4276}
4277
4278static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
4279{
4280 struct stream_out *out = (struct stream_out *)stream;
4281 int status = -ENOSYS;
4282 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004283 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004284 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004285 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
4286 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
4287 else
4288 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
4289 pthread_mutex_unlock(&out->lock);
4290 }
4291 return status;
4292}
4293
4294static int out_flush(struct audio_stream_out* stream)
4295{
4296 struct stream_out *out = (struct stream_out *)stream;
4297 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004298 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004299 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004300 lock_output_stream(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07004301 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
4302 stop_compressed_output_l(out);
4303 out->written = 0;
4304 } else {
4305 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
4306 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004307 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004308 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004309 return 0;
4310 }
4311 return -ENOSYS;
4312}
4313
Haynes Mathew George16081042017-05-31 17:16:49 -07004314static int out_stop(const struct audio_stream_out* stream)
4315{
4316 struct stream_out *out = (struct stream_out *)stream;
4317 struct audio_device *adev = out->dev;
4318 int ret = -ENOSYS;
4319
4320 ALOGV("%s", __func__);
4321 pthread_mutex_lock(&adev->lock);
4322 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
4323 out->playback_started && out->pcm != NULL) {
4324 pcm_stop(out->pcm);
4325 ret = stop_output_stream(out);
4326 out->playback_started = false;
4327 }
4328 pthread_mutex_unlock(&adev->lock);
4329 return ret;
4330}
4331
4332static int out_start(const struct audio_stream_out* stream)
4333{
4334 struct stream_out *out = (struct stream_out *)stream;
4335 struct audio_device *adev = out->dev;
4336 int ret = -ENOSYS;
4337
4338 ALOGV("%s", __func__);
4339 pthread_mutex_lock(&adev->lock);
4340 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
4341 !out->playback_started && out->pcm != NULL) {
4342 ret = start_output_stream(out);
4343 if (ret == 0) {
4344 out->playback_started = true;
4345 }
4346 }
4347 pthread_mutex_unlock(&adev->lock);
4348 return ret;
4349}
4350
4351/*
4352 * Modify config->period_count based on min_size_frames
4353 */
4354static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
4355{
4356 int periodCountRequested = (min_size_frames + config->period_size - 1)
4357 / config->period_size;
4358 int periodCount = MMAP_PERIOD_COUNT_MIN;
4359
4360 ALOGV("%s original config.period_size = %d config.period_count = %d",
4361 __func__, config->period_size, config->period_count);
4362
4363 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
4364 periodCount *= 2;
4365 }
4366 config->period_count = periodCount;
4367
4368 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
4369}
4370
4371static int out_create_mmap_buffer(const struct audio_stream_out *stream,
4372 int32_t min_size_frames,
4373 struct audio_mmap_buffer_info *info)
4374{
4375 struct stream_out *out = (struct stream_out *)stream;
4376 struct audio_device *adev = out->dev;
4377 int ret = 0;
4378 unsigned int offset1;
4379 unsigned int frames1;
4380 const char *step = "";
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07004381 uint32_t mmap_size;
Haynes Mathew George16081042017-05-31 17:16:49 -07004382
4383 ALOGV("%s", __func__);
4384 pthread_mutex_lock(&adev->lock);
4385
4386 if (info == NULL || min_size_frames == 0) {
4387 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
4388 ret = -EINVAL;
4389 goto exit;
4390 }
4391 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
4392 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
4393 ret = -ENOSYS;
4394 goto exit;
4395 }
4396 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
4397 if (out->pcm_device_id < 0) {
4398 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
4399 __func__, out->pcm_device_id, out->usecase);
4400 ret = -EINVAL;
4401 goto exit;
4402 }
4403
4404 adjust_mmap_period_count(&out->config, min_size_frames);
4405
4406 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
4407 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
4408 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
4409 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
4410 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
4411 step = "open";
4412 ret = -ENODEV;
4413 goto exit;
4414 }
4415 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
4416 if (ret < 0) {
4417 step = "begin";
4418 goto exit;
4419 }
4420 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
4421 info->burst_size_frames = out->config.period_size;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07004422 ret = platform_get_mmap_data_fd(adev->platform,
4423 out->pcm_device_id, 0 /*playback*/,
4424 &info->shared_memory_fd,
4425 &mmap_size);
4426 if (ret < 0) {
4427 step = "get_mmap_fd";
4428 goto exit;
4429 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004430 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(out->pcm,
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07004431 info->buffer_size_frames));
Haynes Mathew George16081042017-05-31 17:16:49 -07004432
4433 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
4434 if (ret < 0) {
4435 step = "commit";
4436 goto exit;
4437 }
4438
4439 out->standby = false;
4440 ret = 0;
4441
4442 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
4443 __func__, info->shared_memory_address, info->buffer_size_frames);
4444
4445exit:
4446 if (ret != 0) {
4447 if (out->pcm == NULL) {
4448 ALOGE("%s: %s - %d", __func__, step, ret);
4449 } else {
4450 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
4451 pcm_close(out->pcm);
4452 out->pcm = NULL;
4453 }
4454 }
4455 pthread_mutex_unlock(&adev->lock);
4456 return ret;
4457}
4458
4459static int out_get_mmap_position(const struct audio_stream_out *stream,
4460 struct audio_mmap_position *position)
4461{
4462 struct stream_out *out = (struct stream_out *)stream;
4463 ALOGVV("%s", __func__);
4464 if (position == NULL) {
4465 return -EINVAL;
4466 }
4467 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
4468 return -ENOSYS;
4469 }
4470 if (out->pcm == NULL) {
4471 return -ENOSYS;
4472 }
4473
4474 struct timespec ts = { 0, 0 };
4475 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
4476 if (ret < 0) {
4477 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
4478 return ret;
4479 }
4480 position->time_nanoseconds = ts.tv_sec*1000000000L + ts.tv_nsec;
4481 return 0;
4482}
4483
4484
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004485/** audio_stream_in implementation **/
4486static uint32_t in_get_sample_rate(const struct audio_stream *stream)
4487{
4488 struct stream_in *in = (struct stream_in *)stream;
4489
4490 return in->config.rate;
4491}
4492
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004493static int in_set_sample_rate(struct audio_stream *stream __unused,
4494 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004495{
4496 return -ENOSYS;
4497}
4498
4499static size_t in_get_buffer_size(const struct audio_stream *stream)
4500{
4501 struct stream_in *in = (struct stream_in *)stream;
4502
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004503 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
4504 return voice_extn_compress_voip_in_get_buffer_size(in);
Vikram Panduranga93f080e2017-06-07 18:16:14 -07004505 else if(in->usecase == USECASE_AUDIO_RECORD_VOIP)
4506 return VOIP_IO_BUF_SIZE(in->config.rate, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE);
Mingming Yine62d7842013-10-25 16:26:03 -07004507 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
4508 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304509 else if(audio_extn_cin_attached_usecase(in->usecase))
4510 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004511
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004512 return in->config.period_size * in->af_period_multiplier *
4513 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004514}
4515
4516static uint32_t in_get_channels(const struct audio_stream *stream)
4517{
4518 struct stream_in *in = (struct stream_in *)stream;
4519
4520 return in->channel_mask;
4521}
4522
4523static audio_format_t in_get_format(const struct audio_stream *stream)
4524{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004525 struct stream_in *in = (struct stream_in *)stream;
4526
4527 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004528}
4529
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004530static int in_set_format(struct audio_stream *stream __unused,
4531 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004532{
4533 return -ENOSYS;
4534}
4535
4536static int in_standby(struct audio_stream *stream)
4537{
4538 struct stream_in *in = (struct stream_in *)stream;
4539 struct audio_device *adev = in->dev;
4540 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304541 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4542 stream, in->usecase, use_case_table[in->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07004543 bool do_stop = true;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304544
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004545 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004546 if (!in->standby && in->is_st_session) {
4547 ALOGD("%s: sound trigger pcm stop lab", __func__);
4548 audio_extn_sound_trigger_stop_lab(in);
4549 in->standby = 1;
4550 }
4551
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004552 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004553 if (adev->adm_deregister_stream)
4554 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
4555
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08004556 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004557 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08004558 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
kunleizbecba2d2017-09-07 13:37:16 +08004559 do_stop = false;
Zhou Songa8895042016-07-05 17:54:22 +08004560 voice_extn_compress_voip_close_input_stream(stream);
4561 ALOGD("VOIP input entered standby");
Haynes Mathew George16081042017-05-31 17:16:49 -07004562 } else if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
4563 do_stop = in->capture_started;
4564 in->capture_started = false;
Zhou Songa8895042016-07-05 17:54:22 +08004565 } else {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304566 if (audio_extn_cin_attached_usecase(in->usecase))
4567 audio_extn_cin_stop_input_stream(in);
kunleizbecba2d2017-09-07 13:37:16 +08004568 }
4569
4570 if (do_stop) {
Zhou Songa8895042016-07-05 17:54:22 +08004571 if (in->pcm) {
4572 pcm_close(in->pcm);
4573 in->pcm = NULL;
4574 }
4575 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004576 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08004577 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004578 }
4579 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07004580 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004581 return status;
4582}
4583
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004584static int in_dump(const struct audio_stream *stream __unused,
4585 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004586{
4587 return 0;
4588}
4589
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304590static void in_snd_mon_cb(void * stream, struct str_parms * parms)
4591{
4592 if (!stream || !parms)
4593 return;
4594
4595 struct stream_in *in = (struct stream_in *)stream;
4596 struct audio_device *adev = in->dev;
4597
4598 card_status_t status;
4599 int card;
4600 if (parse_snd_card_status(parms, &card, &status) < 0)
4601 return;
4602
4603 pthread_mutex_lock(&adev->lock);
4604 bool valid_cb = (card == adev->snd_card);
4605 pthread_mutex_unlock(&adev->lock);
4606
4607 if (!valid_cb)
4608 return;
4609
4610 lock_input_stream(in);
4611 if (in->card_status != status)
4612 in->card_status = status;
4613 pthread_mutex_unlock(&in->lock);
4614
4615 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
4616 use_case_table[in->usecase],
4617 status == CARD_STATUS_OFFLINE ? "offline" : "online");
4618
4619 // a better solution would be to report error back to AF and let
4620 // it put the stream to standby
4621 if (status == CARD_STATUS_OFFLINE)
4622 in_standby(&in->stream.common);
4623
4624 return;
4625}
4626
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004627static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
4628{
4629 struct stream_in *in = (struct stream_in *)stream;
4630 struct audio_device *adev = in->dev;
4631 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004632 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004633 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004634
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304635 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004636 parms = str_parms_create_str(kvpairs);
4637
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304638 if (!parms)
4639 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004640 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004641 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004642
4643 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
4644 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004645 val = atoi(value);
4646 /* no audio source uses val == 0 */
4647 if ((in->source != val) && (val != 0)) {
4648 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08004649 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
4650 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
4651 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08004652 (in->config.rate == 8000 || in->config.rate == 16000 ||
4653 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004654 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08004655 err = voice_extn_compress_voip_open_input_stream(in);
4656 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08004657 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08004658 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08004659 }
4660 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004661 }
4662 }
4663
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004664 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
4665 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004666 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004667 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004668 in->device = val;
4669 /* If recording is in progress, change the tx device to new device */
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004670 if (!in->standby && !in->is_st_session) {
4671 ALOGV("update input routing change");
Haynes Mathew George822b5492016-07-01 16:57:24 -07004672 if (adev->adm_on_routing_change)
4673 adev->adm_on_routing_change(adev->adm_data,
4674 in->capture_handle);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004675 ret = select_devices(adev, in->usecase);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004676 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004677 }
4678 }
4679
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304680 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
4681 if (err >= 0) {
4682 strlcpy(in->profile, value, sizeof(in->profile));
4683 ALOGV("updating stream profile with value '%s'", in->profile);
4684 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
4685 &adev->streams_input_cfg_list,
4686 in->device, in->flags, in->format,
4687 in->sample_rate, in->bit_width,
4688 in->profile, &in->app_type_cfg);
4689 }
4690
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004691 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004692 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004693
4694 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304695error:
Eric Laurent994a6932013-07-17 11:51:42 -07004696 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004697 return ret;
4698}
4699
4700static char* in_get_parameters(const struct audio_stream *stream,
4701 const char *keys)
4702{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004703 struct stream_in *in = (struct stream_in *)stream;
4704 struct str_parms *query = str_parms_create_str(keys);
4705 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004706 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004707
4708 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004709 if (reply) {
4710 str_parms_destroy(reply);
4711 }
4712 if (query) {
4713 str_parms_destroy(query);
4714 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004715 ALOGE("in_get_parameters: failed to create query or reply");
4716 return NULL;
4717 }
4718
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004719 ALOGV("%s: enter: keys - %s", __func__, keys);
4720
4721 voice_extn_in_get_parameters(in, query, reply);
4722
4723 str = str_parms_to_str(reply);
4724 str_parms_destroy(query);
4725 str_parms_destroy(reply);
4726
4727 ALOGV("%s: exit: returns - %s", __func__, str);
4728 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004729}
4730
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004731static int in_set_gain(struct audio_stream_in *stream __unused,
4732 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004733{
4734 return 0;
4735}
4736
4737static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
4738 size_t bytes)
4739{
4740 struct stream_in *in = (struct stream_in *)stream;
4741 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05304742 int ret = -1;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304743 size_t bytes_read = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004744
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004745 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05304746
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07004747 if (in->is_st_session) {
4748 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
4749 /* Read from sound trigger HAL */
4750 audio_extn_sound_trigger_read(in, buffer, bytes);
4751 pthread_mutex_unlock(&in->lock);
4752 return bytes;
4753 }
4754
Haynes Mathew George16081042017-05-31 17:16:49 -07004755 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
4756 ret = -ENOSYS;
4757 goto exit;
4758 }
4759
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004760 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07004761 pthread_mutex_lock(&adev->lock);
4762 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
4763 ret = voice_extn_compress_voip_start_input_stream(in);
4764 else
4765 ret = start_input_stream(in);
4766 pthread_mutex_unlock(&adev->lock);
4767 if (ret != 0) {
4768 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004769 }
4770 in->standby = 0;
4771 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004772
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004773 // what's the duration requested by the client?
4774 long ns = 0;
4775
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304776 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004777 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
4778 in->config.rate;
4779
4780 request_in_focus(in, ns);
4781 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004782
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304783 if (audio_extn_cin_attached_usecase(in->usecase)) {
4784 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
4785 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304786 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004787 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304788 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07004789 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004790 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004791 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Garmond Leunge2433c32017-09-28 21:51:22 -07004792 } else if (audio_extn_ffv_get_stream() == in) {
4793 ret = audio_extn_ffv_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304794 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004795 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304796 /* data from DSP comes in 24_8 format, convert it to 8_24 */
4797 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
4798 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
4799 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304800 ret = -EINVAL;
4801 goto exit;
4802 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304803 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304804 ret = -errno;
4805 }
4806 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304807 /* bytes read is always set to bytes for non compress usecases */
4808 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004809 }
4810
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004811 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004812
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004813 /*
4814 * Instead of writing zeroes here, we could trust the hardware
4815 * to always provide zeroes when muted.
4816 */
Pavan Chikkala63964842014-12-04 10:48:28 +05304817 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
4818 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004819 memset(buffer, 0, bytes);
4820
4821exit:
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07004822 if (-ENETRESET == ret)
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304823 in->card_status = CARD_STATUS_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004824 pthread_mutex_unlock(&in->lock);
4825
4826 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05304827 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304828 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05304829 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304830 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05304831 in->standby = true;
4832 }
Sharad Sangled17c9122017-03-20 15:58:52 +05304833 if (!audio_extn_cin_attached_usecase(in->usecase)) {
4834 bytes_read = bytes;
4835 memset(buffer, 0, bytes);
4836 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004837 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004838 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05304839 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05304840 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004841 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304842 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004843}
4844
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004845static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004846{
4847 return 0;
4848}
4849
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004850static int add_remove_audio_effect(const struct audio_stream *stream,
4851 effect_handle_t effect,
4852 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004853{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004854 struct stream_in *in = (struct stream_in *)stream;
4855 int status = 0;
4856 effect_descriptor_t desc;
4857
4858 status = (*effect)->get_descriptor(effect, &desc);
4859 if (status != 0)
4860 return status;
4861
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004862 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004863 pthread_mutex_lock(&in->dev->lock);
4864 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
4865 in->enable_aec != enable &&
4866 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
4867 in->enable_aec = enable;
4868 if (!in->standby)
4869 select_devices(in->dev, in->usecase);
4870 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08004871 if (in->enable_ns != enable &&
4872 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
4873 in->enable_ns = enable;
4874 if (!in->standby)
4875 select_devices(in->dev, in->usecase);
4876 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004877 pthread_mutex_unlock(&in->dev->lock);
4878 pthread_mutex_unlock(&in->lock);
4879
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004880 return 0;
4881}
4882
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004883static int in_add_audio_effect(const struct audio_stream *stream,
4884 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004885{
Eric Laurent994a6932013-07-17 11:51:42 -07004886 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004887 return add_remove_audio_effect(stream, effect, true);
4888}
4889
4890static int in_remove_audio_effect(const struct audio_stream *stream,
4891 effect_handle_t effect)
4892{
Eric Laurent994a6932013-07-17 11:51:42 -07004893 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004894 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004895}
4896
Haynes Mathew George16081042017-05-31 17:16:49 -07004897static int in_stop(const struct audio_stream_in* stream)
4898{
4899 struct stream_in *in = (struct stream_in *)stream;
4900 struct audio_device *adev = in->dev;
4901
4902 int ret = -ENOSYS;
4903 ALOGV("%s", __func__);
4904 pthread_mutex_lock(&adev->lock);
4905 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
4906 in->capture_started && in->pcm != NULL) {
4907 pcm_stop(in->pcm);
4908 ret = stop_input_stream(in);
4909 in->capture_started = false;
4910 }
4911 pthread_mutex_unlock(&adev->lock);
4912 return ret;
4913}
4914
4915static int in_start(const struct audio_stream_in* stream)
4916{
4917 struct stream_in *in = (struct stream_in *)stream;
4918 struct audio_device *adev = in->dev;
4919 int ret = -ENOSYS;
4920
4921 ALOGV("%s in %p", __func__, in);
4922 pthread_mutex_lock(&adev->lock);
4923 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
4924 !in->capture_started && in->pcm != NULL) {
4925 if (!in->capture_started) {
4926 ret = start_input_stream(in);
4927 if (ret == 0) {
4928 in->capture_started = true;
4929 }
4930 }
4931 }
4932 pthread_mutex_unlock(&adev->lock);
4933 return ret;
4934}
4935
4936static int in_create_mmap_buffer(const struct audio_stream_in *stream,
4937 int32_t min_size_frames,
4938 struct audio_mmap_buffer_info *info)
4939{
4940 struct stream_in *in = (struct stream_in *)stream;
4941 struct audio_device *adev = in->dev;
4942 int ret = 0;
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07004943 unsigned int offset1 = 0;
4944 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07004945 const char *step = "";
4946
4947 pthread_mutex_lock(&adev->lock);
4948 ALOGV("%s in %p", __func__, in);
4949
4950 if (info == NULL || min_size_frames == 0) {
4951 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
4952 ret = -EINVAL;
4953 goto exit;
4954 }
4955 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
4956 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
4957 ALOGV("%s in %p", __func__, in);
4958 ret = -ENOSYS;
4959 goto exit;
4960 }
4961 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
4962 if (in->pcm_device_id < 0) {
4963 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
4964 __func__, in->pcm_device_id, in->usecase);
4965 ret = -EINVAL;
4966 goto exit;
4967 }
4968
4969 adjust_mmap_period_count(&in->config, min_size_frames);
4970
4971 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
4972 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
4973 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
4974 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
4975 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
4976 step = "open";
4977 ret = -ENODEV;
4978 goto exit;
4979 }
4980
4981 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
4982 if (ret < 0) {
4983 step = "begin";
4984 goto exit;
4985 }
4986 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
4987 info->burst_size_frames = in->config.period_size;
4988 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
4989
4990 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(in->pcm,
4991 info->buffer_size_frames));
4992
4993 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
4994 if (ret < 0) {
4995 step = "commit";
4996 goto exit;
4997 }
4998
4999 in->standby = false;
5000 ret = 0;
5001
5002 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
5003 __func__, info->shared_memory_address, info->buffer_size_frames);
5004
5005exit:
5006 if (ret != 0) {
5007 if (in->pcm == NULL) {
5008 ALOGE("%s: %s - %d", __func__, step, ret);
5009 } else {
5010 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
5011 pcm_close(in->pcm);
5012 in->pcm = NULL;
5013 }
5014 }
5015 pthread_mutex_unlock(&adev->lock);
5016 return ret;
5017}
5018
5019static int in_get_mmap_position(const struct audio_stream_in *stream,
5020 struct audio_mmap_position *position)
5021{
5022 struct stream_in *in = (struct stream_in *)stream;
5023 ALOGVV("%s", __func__);
5024 if (position == NULL) {
5025 return -EINVAL;
5026 }
5027 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
5028 return -ENOSYS;
5029 }
5030 if (in->pcm == NULL) {
5031 return -ENOSYS;
5032 }
5033 struct timespec ts = { 0, 0 };
5034 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
5035 if (ret < 0) {
5036 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
5037 return ret;
5038 }
5039 position->time_nanoseconds = ts.tv_sec*1000000000L + ts.tv_nsec;
5040 return 0;
5041}
5042
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305043int adev_open_output_stream(struct audio_hw_device *dev,
Haynes Mathew George16081042017-05-31 17:16:49 -07005044 audio_io_handle_t handle,
5045 audio_devices_t devices,
5046 audio_output_flags_t flags,
5047 struct audio_config *config,
5048 struct audio_stream_out **stream_out,
5049 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005050{
5051 struct audio_device *adev = (struct audio_device *)dev;
5052 struct stream_out *out;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05305053 int ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07005054 audio_format_t format;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005055 struct adsp_hdlr_stream_cfg hdlr_stream_cfg;
Manish Dewangan21a850a2017-08-14 12:03:55 +05305056 bool is_direct_passthough = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005057
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005058 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05305059
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005060 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
5061
Mingming Yin3a941d42016-02-17 18:08:05 -08005062 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
5063 stream_handle(%p)", __func__, config->format, config->sample_rate, config->channel_mask,
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305064 devices, flags, &out->stream);
5065
5066
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08005067 if (!out) {
5068 return -ENOMEM;
5069 }
5070
Haynes Mathew George204045b2015-02-25 20:32:03 -08005071 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005072 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305073 pthread_mutex_init(&out->compr_mute_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08005074 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
5075
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005076 if (devices == AUDIO_DEVICE_NONE)
5077 devices = AUDIO_DEVICE_OUT_SPEAKER;
5078
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005079 out->flags = flags;
5080 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07005081 out->dev = adev;
Aalique Grahame65780b52017-09-27 14:59:56 -07005082 out->hal_op_format = out->hal_ip_format = format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005083 out->sample_rate = config->sample_rate;
Sachin Mohan Gadag3d09acd2017-06-19 12:43:44 +05305084 out->channel_mask = config->channel_mask;
Ramjee Singh5857aeb2017-08-03 19:18:50 +05305085 if (out->channel_mask == AUDIO_CHANNEL_NONE)
5086 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
5087 else
5088 out->supported_channel_masks[0] = out->channel_mask;
Eric Laurentc4aef752013-09-12 17:45:53 -07005089 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07005090 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08005091 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05305092 out->convert_buffer = NULL;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305093 out->started = 0;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305094 out->a2dp_compress_mute = false;
Alexy Joseph98988832017-01-13 14:56:59 -08005095 out->dynamic_pm_qos_enabled = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005096
Nikhil Laturkar26b690b2017-07-25 11:06:14 +05305097 if ((flags & AUDIO_OUTPUT_FLAG_BD) &&
Ben Romberger6c4d3812017-06-13 17:46:45 -07005098 (property_get_bool("audio.matrix.limiter.enable", false)))
5099 platform_set_device_params(out, DEVICE_PARAM_LIMITER_ID, 1);
5100
Mingming Yin3a941d42016-02-17 18:08:05 -08005101 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
5102 (flags & AUDIO_OUTPUT_FLAG_DIRECT)) {
5103 pthread_mutex_lock(&adev->lock);
5104 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
5105 ret = read_hdmi_sink_caps(out);
5106 pthread_mutex_unlock(&adev->lock);
5107 if (ret != 0) {
5108 if (ret == -ENOSYS) {
5109 /* ignore and go with default */
5110 ret = 0;
5111 } else {
5112 ALOGE("error reading hdmi sink caps");
5113 goto error_open;
5114 }
5115 }
5116 }
5117
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005118 /* Init use case and pcm_config */
Nikhil Latukar2e6f6242017-08-15 13:37:07 +05305119#ifndef COMPRES_ENABLED
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005120 if (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX) &&
5121 (out->sample_rate == 8000 || out->sample_rate == 16000 ||
5122 out->sample_rate == 32000 || out->sample_rate == 48000)) {
5123 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_MONO;
5124 out->channel_mask = AUDIO_CHANNEL_OUT_MONO;
5125 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
5126
5127 out->config = default_pcm_config_voip_copp;
5128 out->config.period_size = VOIP_IO_BUF_SIZE(out->sample_rate, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
5129 out->config.rate = out->sample_rate;
5130
5131#else
Nikhil Latukar2e6f6242017-08-15 13:37:07 +05305132 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION || voice_extn_compress_voip_is_active(out->dev)) &&
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005133 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08005134 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005135 ret = voice_extn_compress_voip_open_output_stream(out);
5136 if (ret != 0) {
5137 ALOGE("%s: Compress voip output cannot be opened, error:%d",
5138 __func__, ret);
5139 goto error_open;
5140 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005141#endif
vivek mehta0ea887a2015-08-26 14:01:20 -07005142 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05305143 (out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305144 pthread_mutex_lock(&adev->lock);
5145 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
5146 pthread_mutex_unlock(&adev->lock);
5147
5148 // reject offload during card offline to allow
5149 // fallback to s/w paths
5150 if (offline) {
5151 ret = -ENODEV;
5152 goto error_open;
5153 }
vivek mehta0ea887a2015-08-26 14:01:20 -07005154
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005155 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
5156 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
5157 ALOGE("%s: Unsupported Offload information", __func__);
5158 ret = -EINVAL;
5159 goto error_open;
5160 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005161
Mingming Yin3a941d42016-02-17 18:08:05 -08005162 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005163 if(config->offload_info.format == 0)
5164 config->offload_info.format = out->supported_formats[0];
Mingming Yin3a941d42016-02-17 18:08:05 -08005165 if (config->offload_info.sample_rate == 0)
5166 config->offload_info.sample_rate = out->supported_sample_rates[0];
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005167 }
5168
Mingming Yin90310102013-11-13 16:57:00 -08005169 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305170 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07005171 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005172 ret = -EINVAL;
5173 goto error_open;
5174 }
5175
Ben Romberger0f8c87b2017-05-24 17:41:11 -07005176 /* TrueHD only supported for 48k multiples (48k, 96k, 192k) */
5177 if ((config->offload_info.format == AUDIO_FORMAT_DOLBY_TRUEHD) &&
5178 (audio_extn_passthru_is_passthrough_stream(out)) &&
5179 !((config->sample_rate == 48000) ||
5180 (config->sample_rate == 96000) ||
5181 (config->sample_rate == 192000))) {
5182 ALOGE("%s: Unsupported sample rate %d for audio format %x",
5183 __func__, config->sample_rate, config->offload_info.format);
5184 ret = -EINVAL;
5185 goto error_open;
5186 }
5187
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005188 out->compr_config.codec = (struct snd_codec *)
5189 calloc(1, sizeof(struct snd_codec));
5190
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005191 if (!out->compr_config.codec) {
5192 ret = -ENOMEM;
5193 goto error_open;
5194 }
5195
Dhananjay Kumarac341582017-02-23 23:42:25 +05305196 out->stream.pause = out_pause;
5197 out->stream.resume = out_resume;
5198 out->stream.flush = out_flush;
5199 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Mingming Yin21d60472015-09-30 13:56:25 -07005200 out->stream.set_callback = out_set_callback;
Mingming Yin21d60472015-09-30 13:56:25 -07005201 out->stream.drain = out_drain;
Dhananjay Kumarac341582017-02-23 23:42:25 +05305202 out->usecase = get_offload_usecase(adev, true /* is_compress */);
vivek mehta446c3962015-09-14 10:57:35 -07005203 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
Dhananjay Kumarac341582017-02-23 23:42:25 +05305204 } else {
5205 out->usecase = get_offload_usecase(adev, false /* is_compress */);
5206 ALOGV("non-offload DIRECT_usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07005207 }
vivek mehta446c3962015-09-14 10:57:35 -07005208
5209 if (out->usecase == USECASE_INVALID) {
Mingming Yin3a941d42016-02-17 18:08:05 -08005210 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
5211 config->format == 0 && config->sample_rate == 0 &&
5212 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07005213 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08005214 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
5215 } else {
5216 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
5217 ret = -EEXIST;
5218 goto error_open;
5219 }
vivek mehta446c3962015-09-14 10:57:35 -07005220 }
5221
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005222 if (config->offload_info.channel_mask)
5223 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08005224 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005225 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08005226 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07005227 } else {
Dhananjay Kumarac341582017-02-23 23:42:25 +05305228 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT usecase");
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07005229 ret = -EINVAL;
5230 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08005231 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07005232
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07005233 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005234 out->sample_rate = config->offload_info.sample_rate;
5235
Mingming Yin3ee55c62014-08-04 14:23:35 -07005236 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005237
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305238 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305239 if (audio_extn_utils_is_dolby_format(config->offload_info.format)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305240 audio_extn_dolby_send_ddp_endp_params(adev);
5241 audio_extn_dolby_set_dmid(adev);
5242 }
vivek mehta0ea887a2015-08-26 14:01:20 -07005243
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005244 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08005245 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005246 out->compr_config.codec->bit_rate =
5247 config->offload_info.bit_rate;
5248 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05305249 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005250 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05305251 /* Update bit width only for non passthrough usecases.
5252 * For passthrough usecases, the output will always be opened @16 bit
5253 */
5254 if (!audio_extn_passthru_is_passthrough_stream(out))
5255 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Naresh Tanniruee3499a2017-01-05 14:05:35 +05305256
5257 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
5258 out->compr_config.codec->flags |= COMPRESSED_TIMESTAMP_FLAG;
5259 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->flags);
5260
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005261 /*TODO: Do we need to change it for passthrough */
5262 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005263
Manish Dewangana6fc5442015-08-24 20:30:31 +05305264 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
5265 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05305266 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05305267 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05305268 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
5269 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05305270
5271 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
5272 AUDIO_FORMAT_PCM) {
5273
5274 /*Based on platform support, configure appropriate alsa format for corresponding
5275 *hal input format.
5276 */
5277 out->compr_config.codec->format = hal_format_to_alsa(
5278 config->offload_info.format);
5279
Ashish Jain83a6cc22016-06-28 14:34:17 +05305280 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05305281 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05305282 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05305283
Dhananjay Kumarac341582017-02-23 23:42:25 +05305284 /*for direct non-compress playback populate bit_width based on selected alsa format as
Ashish Jainf1eaa582016-05-23 20:54:24 +05305285 *hal input format and alsa format might differ based on platform support.
5286 */
5287 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05305288 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05305289
5290 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
5291
5292 /* Check if alsa session is configured with the same format as HAL input format,
5293 * if not then derive correct fragment size needed to accomodate the
5294 * conversion of HAL input format to alsa format.
5295 */
5296 audio_extn_utils_update_direct_pcm_fragment_size(out);
5297
5298 /*if hal input and output fragment size is different this indicates HAL input format is
5299 *not same as the alsa format
5300 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05305301 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05305302 /*Allocate a buffer to convert input data to the alsa configured format.
5303 *size of convert buffer is equal to the size required to hold one fragment size
5304 *worth of pcm data, this is because flinger does not write more than fragment_size
5305 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05305306 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
5307 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05305308 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
5309 ret = -ENOMEM;
5310 goto error_open;
5311 }
5312 }
5313 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
5314 out->compr_config.fragment_size =
5315 audio_extn_passthru_get_buffer_size(&config->offload_info);
5316 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
5317 } else {
5318 out->compr_config.fragment_size =
5319 platform_get_compress_offload_buffer_size(&config->offload_info);
5320 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
5321 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07005322
Naresh Tanniruee3499a2017-01-05 14:05:35 +05305323 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
5324 out->compr_config.fragment_size += sizeof(struct snd_codec_metadata);
5325 }
Amit Shekhar6f461b12014-08-01 14:52:58 -07005326 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05305327 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07005328
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05305329 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
5330 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
5331 }
5332
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005333 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
5334 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005335
Manish Dewangan69426c82017-01-30 17:35:36 +05305336 if ((flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) &&
5337 (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) {
5338 out->render_mode = RENDER_MODE_AUDIO_STC_MASTER;
5339 } else if(flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
5340 out->render_mode = RENDER_MODE_AUDIO_MASTER;
5341 } else {
5342 out->render_mode = RENDER_MODE_AUDIO_NO_TIMESTAMP;
5343 }
Alexy Josephaa54c872014-12-03 02:46:47 -08005344
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05305345 memset(&out->channel_map_param, 0,
5346 sizeof(struct audio_out_channel_map_param));
5347
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005348 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305349 out->send_next_track_params = false;
5350 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08005351 out->offload_state = OFFLOAD_STATE_IDLE;
5352 out->playback_started = 0;
5353
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005354 audio_extn_dts_create_state_notifier_node(out->usecase);
5355
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005356 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
5357 __func__, config->offload_info.version,
5358 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05305359
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305360 /* Check if DSD audio format is supported in codec
5361 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305362 */
5363
5364 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305365 (!platform_check_codec_dsd_support(adev->platform) ||
5366 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305367 ret = -EINVAL;
5368 goto error_open;
5369 }
5370
Ashish Jain5106d362016-05-11 19:23:33 +05305371 /* Disable gapless if any of the following is true
5372 * passthrough playback
5373 * AV playback
Dhananjay Kumarac341582017-02-23 23:42:25 +05305374 * non compressed Direct playback
Ashish Jain5106d362016-05-11 19:23:33 +05305375 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305376 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305377 (config->format == AUDIO_FORMAT_DSD) ||
Naresh Tanniru928f0862017-04-07 16:44:23 -07005378 (config->format == AUDIO_FORMAT_IEC61937) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305379 config->offload_info.has_video ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05305380 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05305381 check_and_set_gapless_mode(adev, false);
5382 } else
5383 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07005384
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305385 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07005386 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
5387 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305388 if (config->format == AUDIO_FORMAT_DSD) {
5389 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
5390 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
5391 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07005392
5393 create_offload_callback_thread(out);
5394
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07005395 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05305396 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07005397 if (ret != 0) {
5398 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
5399 __func__, ret);
5400 goto error_open;
5401 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005402 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
5403 if (config->sample_rate == 0)
5404 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
5405 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
5406 config->sample_rate != 8000) {
5407 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
5408 ret = -EINVAL;
5409 goto error_open;
5410 }
5411 out->sample_rate = config->sample_rate;
5412 out->config.rate = config->sample_rate;
5413 if (config->format == AUDIO_FORMAT_DEFAULT)
5414 config->format = AUDIO_FORMAT_PCM_16_BIT;
5415 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
5416 config->format = AUDIO_FORMAT_PCM_16_BIT;
5417 ret = -EINVAL;
5418 goto error_open;
5419 }
5420 out->format = config->format;
5421 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
5422 out->config = pcm_config_afe_proxy_playback;
5423 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07005424 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05305425 unsigned int channels = 0;
5426 /*Update config params to default if not set by the caller*/
5427 if (config->sample_rate == 0)
5428 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
5429 if (config->channel_mask == AUDIO_CHANNEL_NONE)
5430 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
5431 if (config->format == AUDIO_FORMAT_DEFAULT)
5432 config->format = AUDIO_FORMAT_PCM_16_BIT;
5433
5434 channels = audio_channel_count_from_out_mask(out->channel_mask);
5435
Varun Balaraje49253e2017-07-06 19:48:56 +05305436 if (out->flags & AUDIO_OUTPUT_FLAG_INTERACTIVE) {
5437 out->usecase = get_interactive_usecase(adev);
5438 out->config = pcm_config_low_latency;
5439 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
Ashish Jain83a6cc22016-06-28 14:34:17 +05305440 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005441 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
5442 out->flags);
5443 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Haynes Mathew George16081042017-05-31 17:16:49 -07005444 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
5445 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
5446 out->config = pcm_config_mmap_playback;
5447 out->stream.start = out_start;
5448 out->stream.stop = out_stop;
5449 out->stream.create_mmap_buffer = out_create_mmap_buffer;
5450 out->stream.get_mmap_position = out_get_mmap_position;
Ashish Jain83a6cc22016-06-28 14:34:17 +05305451 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
5452 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
Alexy Joseph98988832017-01-13 14:56:59 -08005453 out->dynamic_pm_qos_enabled = property_get_bool("vendor.audio.dynamic.qos.enable", false);
5454 if (!out->dynamic_pm_qos_enabled) {
5455 ALOGI("%s: dynamic qos voting not enabled for platform", __func__);
5456 } else {
5457 ALOGI("%s: dynamic qos voting enabled for platform", __func__);
5458 //the mixer path will be a string similar to "low-latency-playback resume"
5459 strlcpy(out->pm_qos_mixer_path, use_case_table[out->usecase], MAX_MIXER_PATH_LEN);
5460 strlcat(out->pm_qos_mixer_path,
5461 " resume", MAX_MIXER_PATH_LEN);
5462 ALOGI("%s: created %s pm_qos_mixer_path" , __func__,
5463 out->pm_qos_mixer_path);
5464 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05305465 out->config = pcm_config_low_latency;
5466 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
5467 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
5468 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05305469 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
5470 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
5471 if (out->config.period_size <= 0) {
5472 ALOGE("Invalid configuration period size is not valid");
5473 ret = -EINVAL;
5474 goto error_open;
5475 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05305476 } else {
5477 /* primary path is the default path selected if no other outputs are available/suitable */
5478 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
5479 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
5480 }
5481 out->hal_ip_format = format = out->format;
5482 out->config.format = hal_format_to_pcm(out->hal_ip_format);
5483 out->hal_op_format = pcm_format_to_hal(out->config.format);
5484 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
5485 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07005486 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05305487 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05305488 if (out->hal_ip_format != out->hal_op_format) {
5489 uint32_t buffer_size = out->config.period_size *
5490 format_to_bitwidth_table[out->hal_op_format] *
5491 out->config.channels;
5492 out->convert_buffer = calloc(1, buffer_size);
5493 if (out->convert_buffer == NULL){
5494 ALOGE("Allocation failed for convert buffer for size %d",
5495 out->compr_config.fragment_size);
5496 ret = -ENOMEM;
5497 goto error_open;
5498 }
5499 ALOGD("Convert buffer allocated of size %d", buffer_size);
5500 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005501 }
5502
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08005503 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
5504 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05305505
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005506 /* TODO remove this hardcoding and check why width is zero*/
5507 if (out->bit_width == 0)
5508 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05305509 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07005510 &adev->streams_output_cfg_list,
Aalique Grahame65780b52017-09-27 14:59:56 -07005511 devices, out->flags, out->hal_op_format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305512 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05305513 &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08005514 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
5515 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
5516 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08005517 if(adev->primary_output == NULL)
5518 adev->primary_output = out;
5519 else {
5520 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005521 ret = -EEXIST;
5522 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08005523 }
5524 }
5525
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005526 /* Check if this usecase is already existing */
5527 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07005528 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
5529 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005530 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005531 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005532 ret = -EEXIST;
5533 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005534 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08005535
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005536 pthread_mutex_unlock(&adev->lock);
5537
5538 out->stream.common.get_sample_rate = out_get_sample_rate;
5539 out->stream.common.set_sample_rate = out_set_sample_rate;
5540 out->stream.common.get_buffer_size = out_get_buffer_size;
5541 out->stream.common.get_channels = out_get_channels;
5542 out->stream.common.get_format = out_get_format;
5543 out->stream.common.set_format = out_set_format;
5544 out->stream.common.standby = out_standby;
5545 out->stream.common.dump = out_dump;
5546 out->stream.common.set_parameters = out_set_parameters;
5547 out->stream.common.get_parameters = out_get_parameters;
5548 out->stream.common.add_audio_effect = out_add_audio_effect;
5549 out->stream.common.remove_audio_effect = out_remove_audio_effect;
5550 out->stream.get_latency = out_get_latency;
5551 out->stream.set_volume = out_set_volume;
5552 out->stream.write = out_write;
5553 out->stream.get_render_position = out_get_render_position;
5554 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005555 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005556
Haynes Mathew George16081042017-05-31 17:16:49 -07005557 if (out->realtime)
5558 out->af_period_multiplier = af_period_multiplier;
5559 else
5560 out->af_period_multiplier = 1;
5561
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005562 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07005563 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005564 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005565
5566 config->format = out->stream.common.get_format(&out->stream.common);
5567 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
5568 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
5569
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305570 /*
5571 By locking output stream before registering, we allow the callback
5572 to update stream's state only after stream's initial state is set to
5573 adev state.
5574 */
5575 lock_output_stream(out);
5576 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
5577 pthread_mutex_lock(&adev->lock);
5578 out->card_status = adev->card_status;
5579 pthread_mutex_unlock(&adev->lock);
5580 pthread_mutex_unlock(&out->lock);
5581
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005582 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305583 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07005584 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005585
5586 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
5587 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
5588 popcount(out->channel_mask), out->playback_started);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005589 /* setup a channel for client <--> adsp communication for stream events */
Manish Dewangan21a850a2017-08-14 12:03:55 +05305590 is_direct_passthough = audio_extn_passthru_is_direct_passthrough(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005591 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Naresh Tanniru85819452017-05-04 18:55:45 -07005592 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) ||
Manish Dewangan21a850a2017-08-14 12:03:55 +05305593 (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false))) {
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005594 hdlr_stream_cfg.pcm_device_id = platform_get_pcm_device_id(
5595 out->usecase, PCM_PLAYBACK);
5596 hdlr_stream_cfg.flags = out->flags;
5597 hdlr_stream_cfg.type = PCM_PLAYBACK;
5598 ret = audio_extn_adsp_hdlr_stream_open(&out->adsp_hdlr_stream_handle,
5599 &hdlr_stream_cfg);
5600 if (ret) {
5601 ALOGE("%s: adsp_hdlr_stream_open failed %d",__func__, ret);
5602 out->adsp_hdlr_stream_handle = NULL;
5603 }
5604 }
Manish Dewangan21a850a2017-08-14 12:03:55 +05305605 if (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false)) {
Vidyakumar Athota2062f912017-06-27 14:46:15 -07005606 ret = audio_extn_ip_hdlr_intf_init(&out->ip_hdlr_handle, NULL, NULL, adev, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07005607 if (ret < 0) {
5608 ALOGE("%s: audio_extn_ip_hdlr_intf_init failed %d",__func__, ret);
5609 out->ip_hdlr_handle = NULL;
5610 }
5611 }
Eric Laurent994a6932013-07-17 11:51:42 -07005612 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005613 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005614
5615error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05305616 if (out->convert_buffer)
5617 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005618 free(out);
5619 *stream_out = NULL;
5620 ALOGD("%s: exit: ret %d", __func__, ret);
5621 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005622}
5623
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305624void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005625 struct audio_stream_out *stream)
5626{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005627 struct stream_out *out = (struct stream_out *)stream;
5628 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005629 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005630
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305631 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
5632
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305633 // must deregister from sndmonitor first to prevent races
5634 // between the callback and close_stream
5635 audio_extn_snd_mon_unregister_listener(out);
5636
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005637 /* close adsp hdrl session before standby */
5638 if (out->adsp_hdlr_stream_handle) {
5639 ret = audio_extn_adsp_hdlr_stream_close(out->adsp_hdlr_stream_handle);
5640 if (ret)
5641 ALOGE("%s: adsp_hdlr_stream_close failed %d",__func__, ret);
5642 out->adsp_hdlr_stream_handle = NULL;
5643 }
5644
Manish Dewangan21a850a2017-08-14 12:03:55 +05305645 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07005646 audio_extn_ip_hdlr_intf_deinit(out->ip_hdlr_handle);
5647 out->ip_hdlr_handle = NULL;
5648 }
5649
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005650 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305651 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005652 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305653 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305654 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005655 if(ret != 0)
5656 ALOGE("%s: Compress voip output cannot be closed, error:%d",
5657 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005658 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005659 out_standby(&stream->common);
5660
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005661 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005662 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005663 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005664 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005665 if (out->compr_config.codec != NULL)
5666 free(out->compr_config.codec);
5667 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005668
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305669 out->a2dp_compress_mute = false;
5670
Varun Balaraje49253e2017-07-06 19:48:56 +05305671 if (is_interactive_usecase(out->usecase))
5672 free_interactive_usecase(adev, out->usecase);
5673
Ashish Jain83a6cc22016-06-28 14:34:17 +05305674 if (out->convert_buffer != NULL) {
5675 free(out->convert_buffer);
5676 out->convert_buffer = NULL;
5677 }
5678
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005679 if (adev->voice_tx_output == out)
5680 adev->voice_tx_output = NULL;
5681
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05305682 if (adev->primary_output == out)
5683 adev->primary_output = NULL;
5684
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005685 pthread_cond_destroy(&out->cond);
5686 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005687 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07005688 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005689}
5690
5691static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
5692{
5693 struct audio_device *adev = (struct audio_device *)dev;
5694 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005695 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005696 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005697 int ret;
5698 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005699
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08005700 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005701 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005702
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305703 if (!parms)
5704 goto error;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305705
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305706 ret = str_parms_get_str(parms, "BT_SCO", value, sizeof(value));
5707 if (ret >= 0) {
5708 /* When set to false, HAL should disable EC and NS */
5709 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
5710 adev->bt_sco_on = true;
5711 else
5712 adev->bt_sco_on = false;
5713 }
5714
Naresh Tanniru4c630392014-05-12 01:05:52 +05305715 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005716 status = voice_set_parameters(adev, parms);
5717 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08005718 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005719
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005720 status = platform_set_parameters(adev->platform, parms);
5721 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08005722 goto done;
5723
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005724 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
5725 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07005726 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005727 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
5728 adev->bluetooth_nrec = true;
5729 else
5730 adev->bluetooth_nrec = false;
5731 }
5732
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005733 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
5734 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005735 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
5736 adev->screen_off = false;
5737 else
5738 adev->screen_off = true;
5739 }
5740
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005741 ret = str_parms_get_int(parms, "rotation", &val);
5742 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005743 bool reverse_speakers = false;
5744 switch(val) {
5745 // FIXME: note that the code below assumes that the speakers are in the correct placement
5746 // relative to the user when the device is rotated 90deg from its default rotation. This
5747 // assumption is device-specific, not platform-specific like this code.
5748 case 270:
5749 reverse_speakers = true;
5750 break;
5751 case 0:
5752 case 90:
5753 case 180:
5754 break;
5755 default:
5756 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005757 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005758 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005759 if (status == 0) {
5760 if (adev->speaker_lr_swap != reverse_speakers) {
5761 adev->speaker_lr_swap = reverse_speakers;
5762 // only update the selected device if there is active pcm playback
5763 struct audio_usecase *usecase;
5764 struct listnode *node;
5765 list_for_each(node, &adev->usecase_list) {
5766 usecase = node_to_item(node, struct audio_usecase, list);
5767 if (usecase->type == PCM_PLAYBACK) {
5768 select_devices(adev, usecase->id);
5769 break;
5770 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005771 }
5772 }
5773 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005774 }
5775
Mingming Yin514a8bc2014-07-29 15:22:21 -07005776 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
5777 if (ret >= 0) {
5778 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
5779 adev->bt_wb_speech_enabled = true;
5780 else
5781 adev->bt_wb_speech_enabled = false;
5782 }
5783
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07005784 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
5785 if (ret >= 0) {
5786 val = atoi(value);
5787 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07005788 ALOGV("cache new ext disp type and edid");
5789 ret = platform_get_ext_disp_type(adev->platform);
5790 if (ret < 0) {
5791 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Weiyin Jiangf50ce4e2016-10-13 14:22:03 +08005792 status = ret;
5793 goto done;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07005794 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07005795 platform_cache_edid(adev->platform);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08005796 } else if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
yidongh86ca17d2016-08-30 18:28:01 +08005797 !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
vivek mehta344576a2016-04-12 18:56:03 -07005798 /*
5799 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
5800 * Per AudioPolicyManager, USB device is higher priority than WFD.
5801 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
5802 * If WFD use case occupies AFE proxy, it may result unintended behavior while
5803 * starting voice call on USB
5804 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08005805 ret = str_parms_get_str(parms, "card", value, sizeof(value));
5806 if (ret >= 0) {
Kuirong Wang27152a12016-11-11 10:20:30 -08005807 audio_extn_usb_add_device(AUDIO_DEVICE_OUT_USB_DEVICE, atoi(value));
5808 audio_extn_usb_add_device(AUDIO_DEVICE_IN_USB_DEVICE, atoi(value));
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08005809 }
vivek mehta344576a2016-04-12 18:56:03 -07005810 ALOGV("detected USB connect .. disable proxy");
5811 adev->allow_afe_proxy_usage = false;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07005812 }
5813 }
5814
5815 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
5816 if (ret >= 0) {
5817 val = atoi(value);
Garmond Leunge3b6d482016-10-25 16:48:01 -07005818 /*
5819 * The HDMI / Displayport disconnect handling has been moved to
5820 * audio extension to ensure that its parameters are not
5821 * invalidated prior to updating sysfs of the disconnect event
5822 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
5823 */
5824 if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
yidongh86ca17d2016-08-30 18:28:01 +08005825 !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08005826 ret = str_parms_get_str(parms, "card", value, sizeof(value));
5827 if (ret >= 0) {
Ashish Jain3e37a702016-11-25 12:27:15 +05305828 audio_extn_usb_remove_device(AUDIO_DEVICE_OUT_USB_DEVICE, atoi(value));
5829 audio_extn_usb_remove_device(AUDIO_DEVICE_IN_USB_DEVICE, atoi(value));
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08005830 }
vivek mehta344576a2016-04-12 18:56:03 -07005831 ALOGV("detected USB disconnect .. enable proxy");
5832 adev->allow_afe_proxy_usage = true;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07005833 }
5834 }
5835
Naresh Tanniru9d027a62015-03-13 01:32:10 +05305836 ret = str_parms_get_str(parms,"reconfigA2dp", value, sizeof(value));
5837 if (ret >= 0) {
5838 struct audio_usecase *usecase;
5839 struct listnode *node;
5840 list_for_each(node, &adev->usecase_list) {
5841 usecase = node_to_item(node, struct audio_usecase, list);
5842 if ((usecase->type == PCM_PLAYBACK) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07005843 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP)){
Naresh Tanniru9d027a62015-03-13 01:32:10 +05305844 ALOGD("reconfigure a2dp... forcing device switch");
Weiyin Jiang425180d2017-06-05 16:40:23 +08005845
5846 pthread_mutex_unlock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05305847 lock_output_stream(usecase->stream.out);
Weiyin Jiang425180d2017-06-05 16:40:23 +08005848 pthread_mutex_lock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05305849 audio_extn_a2dp_set_handoff_mode(true);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05305850 //force device switch to re configure encoder
5851 select_devices(adev, usecase->id);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05305852 audio_extn_a2dp_set_handoff_mode(false);
5853 pthread_mutex_unlock(&usecase->stream.out->lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05305854 break;
5855 }
5856 }
5857 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08005858
5859 //handle vr audio setparam
5860 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
5861 value, sizeof(value));
5862 if (ret >= 0) {
5863 ALOGI("Setting vr mode to be %s", value);
5864 if (!strncmp(value, "true", 4)) {
5865 adev->vr_audio_mode_enabled = true;
5866 ALOGI("Setting vr mode to true");
5867 } else if (!strncmp(value, "false", 5)) {
5868 adev->vr_audio_mode_enabled = false;
5869 ALOGI("Setting vr mode to false");
5870 } else {
5871 ALOGI("wrong vr mode set");
5872 }
5873 }
5874
Naresh Tannirucd2353e2016-08-19 00:37:25 +05305875 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08005876done:
5877 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08005878 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305879error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005880 ALOGV("%s: exit with code(%d)", __func__, status);
5881 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005882}
5883
5884static char* adev_get_parameters(const struct audio_hw_device *dev,
5885 const char *keys)
5886{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07005887 struct audio_device *adev = (struct audio_device *)dev;
5888 struct str_parms *reply = str_parms_create();
5889 struct str_parms *query = str_parms_create_str(keys);
5890 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05305891 char value[256] = {0};
5892 int ret = 0;
5893
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005894 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005895 if (reply) {
5896 str_parms_destroy(reply);
5897 }
5898 if (query) {
5899 str_parms_destroy(query);
5900 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005901 ALOGE("adev_get_parameters: failed to create query or reply");
5902 return NULL;
5903 }
5904
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08005905 //handle vr audio getparam
5906
5907 ret = str_parms_get_str(query,
5908 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
5909 value, sizeof(value));
5910
5911 if (ret >= 0) {
5912 bool vr_audio_enabled = false;
5913 pthread_mutex_lock(&adev->lock);
5914 vr_audio_enabled = adev->vr_audio_mode_enabled;
5915 pthread_mutex_unlock(&adev->lock);
5916
5917 ALOGI("getting vr mode to %d", vr_audio_enabled);
5918
5919 if (vr_audio_enabled) {
5920 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
5921 "true");
5922 goto exit;
5923 } else {
5924 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
5925 "false");
5926 goto exit;
5927 }
5928 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07005929
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08005930 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07005931 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08005932 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07005933 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05305934 pthread_mutex_unlock(&adev->lock);
5935
Naresh Tannirud7205b62014-06-20 02:54:48 +05305936exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07005937 str = str_parms_to_str(reply);
5938 str_parms_destroy(query);
5939 str_parms_destroy(reply);
5940
5941 ALOGV("%s: exit: returns - %s", __func__, str);
5942 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005943}
5944
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005945static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005946{
5947 return 0;
5948}
5949
5950static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
5951{
Haynes Mathew George5191a852013-09-11 14:19:36 -07005952 int ret;
5953 struct audio_device *adev = (struct audio_device *)dev;
5954 pthread_mutex_lock(&adev->lock);
5955 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07005956 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07005957 pthread_mutex_unlock(&adev->lock);
5958 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005959}
5960
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005961static int adev_set_master_volume(struct audio_hw_device *dev __unused,
5962 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005963{
5964 return -ENOSYS;
5965}
5966
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005967static int adev_get_master_volume(struct audio_hw_device *dev __unused,
5968 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005969{
5970 return -ENOSYS;
5971}
5972
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005973static int adev_set_master_mute(struct audio_hw_device *dev __unused,
5974 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005975{
5976 return -ENOSYS;
5977}
5978
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005979static int adev_get_master_mute(struct audio_hw_device *dev __unused,
5980 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005981{
5982 return -ENOSYS;
5983}
5984
5985static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
5986{
5987 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005988
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005989 pthread_mutex_lock(&adev->lock);
5990 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005991 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005992 adev->mode = mode;
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08005993 if ((mode == AUDIO_MODE_NORMAL) && voice_is_in_call(adev)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005994 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07005995 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005996 adev->current_call_output = NULL;
5997 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005998 }
5999 pthread_mutex_unlock(&adev->lock);
6000 return 0;
6001}
6002
6003static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
6004{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08006005 int ret;
6006
6007 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08006008 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08006009 ret = voice_set_mic_mute((struct audio_device *)dev, state);
6010 pthread_mutex_unlock(&adev->lock);
6011
6012 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006013}
6014
6015static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
6016{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07006017 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006018 return 0;
6019}
6020
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006021static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006022 const struct audio_config *config)
6023{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006024 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006025
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07006026 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
6027 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006028}
6029
6030static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006031 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006032 audio_devices_t devices,
6033 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006034 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306035 audio_input_flags_t flags,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006036 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07006037 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006038{
6039 struct audio_device *adev = (struct audio_device *)dev;
6040 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08006041 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006042 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07006043 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05306044 bool channel_mask_updated = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306045
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006046 *stream_in = NULL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05306047 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0) {
6048 ALOGE("%s: invalid input parameters", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006049 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05306050 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006051
6052 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006053
6054 if (!in) {
6055 ALOGE("failed to allocate input stream");
6056 return -ENOMEM;
6057 }
6058
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306059 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306060 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
6061 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07006062 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006063 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07006064
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006065 in->stream.common.get_sample_rate = in_get_sample_rate;
6066 in->stream.common.set_sample_rate = in_set_sample_rate;
6067 in->stream.common.get_buffer_size = in_get_buffer_size;
6068 in->stream.common.get_channels = in_get_channels;
6069 in->stream.common.get_format = in_get_format;
6070 in->stream.common.set_format = in_set_format;
6071 in->stream.common.standby = in_standby;
6072 in->stream.common.dump = in_dump;
6073 in->stream.common.set_parameters = in_set_parameters;
6074 in->stream.common.get_parameters = in_get_parameters;
6075 in->stream.common.add_audio_effect = in_add_audio_effect;
6076 in->stream.common.remove_audio_effect = in_remove_audio_effect;
6077 in->stream.set_gain = in_set_gain;
6078 in->stream.read = in_read;
6079 in->stream.get_input_frames_lost = in_get_input_frames_lost;
6080
6081 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07006082 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006083 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006084 in->standby = 1;
6085 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006086 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006087 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006088
Dhananjay Kumar973fc362017-01-09 18:48:15 +05306089 in->usecase = USECASE_AUDIO_RECORD;
6090 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Haynes Mathew George16081042017-05-31 17:16:49 -07006091 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
Dhananjay Kumar973fc362017-01-09 18:48:15 +05306092 is_low_latency = true;
6093#if LOW_LATENCY_CAPTURE_USE_CASE
6094 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
6095#endif
6096 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
6097 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006098 in->format = config->format;
Haynes Mathew George16081042017-05-31 17:16:49 -07006099 if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
6100 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
6101 in->realtime = 0;
6102 in->usecase = USECASE_AUDIO_RECORD_MMAP;
6103 in->config = pcm_config_mmap_capture;
6104 in->stream.start = in_start;
6105 in->stream.stop = in_stop;
6106 in->stream.create_mmap_buffer = in_create_mmap_buffer;
6107 in->stream.get_mmap_position = in_get_mmap_position;
6108 in->af_period_multiplier = 1;
6109 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
6110 } else if (in->realtime) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006111 in->config = pcm_config_audio_capture_rt;
6112 in->sample_rate = in->config.rate;
6113 in->af_period_multiplier = af_period_multiplier;
6114 } else {
6115 in->config = pcm_config_audio_capture;
6116 in->config.rate = config->sample_rate;
6117 in->sample_rate = config->sample_rate;
6118 in->af_period_multiplier = 1;
6119 }
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306120 in->bit_width = 16;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006121
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306122 /* restrict 24 bit capture for unprocessed source only
6123 * for other sources if 24 bit requested reject 24 and set 16 bit capture only
6124 */
6125 if (config->format == AUDIO_FORMAT_DEFAULT) {
6126 config->format = AUDIO_FORMAT_PCM_16_BIT;
6127 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
6128 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
6129 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
6130 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
6131 bool ret_error = false;
6132 in->bit_width = 24;
6133 /* 24 bit is restricted to UNPROCESSED source only,also format supported
6134 from HAL is 24_packed and 8_24
6135 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
6136 24_packed return error indicating supported format is 24_packed
6137 *> In case of any other source requesting 24 bit or float return error
6138 indicating format supported is 16 bit only.
6139
6140 on error flinger will retry with supported format passed
6141 */
6142 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
6143 (source != AUDIO_SOURCE_CAMCORDER)) {
6144 config->format = AUDIO_FORMAT_PCM_16_BIT;
6145 if (config->sample_rate > 48000)
6146 config->sample_rate = 48000;
6147 ret_error = true;
6148 } else if (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) {
6149 in->config.format = PCM_FORMAT_S24_3LE;
6150 } else if (config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
6151 in->config.format = PCM_FORMAT_S24_LE;
6152 } else {
6153 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
6154 ret_error = true;
6155 }
6156
6157 if (ret_error) {
6158 ret = -EINVAL;
6159 goto err_open;
6160 }
6161 }
6162
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05306163 /* Update config params with the requested sample rate and channels */
Dhanalakshmi Siddani0b1488e2016-09-06 12:58:42 +05306164 if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) &&
6165 (adev->mode != AUDIO_MODE_IN_CALL)) {
6166 ret = -EINVAL;
6167 goto err_open;
6168 }
6169
6170 if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) ||
6171 (in->device == AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006172 if (config->sample_rate == 0)
6173 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
6174 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
6175 config->sample_rate != 8000) {
6176 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
6177 ret = -EINVAL;
6178 goto err_open;
6179 }
6180 if (config->format == AUDIO_FORMAT_DEFAULT)
6181 config->format = AUDIO_FORMAT_PCM_16_BIT;
6182 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
6183 config->format = AUDIO_FORMAT_PCM_16_BIT;
6184 ret = -EINVAL;
6185 goto err_open;
6186 }
6187
6188 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
6189 in->config = pcm_config_afe_proxy_record;
6190 in->config.channels = channel_count;
6191 in->config.rate = config->sample_rate;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306192 in->sample_rate = config->sample_rate;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05306193 } else if (!audio_extn_check_and_set_multichannel_usecase(adev,
6194 in, config, &channel_mask_updated)) {
6195 if (channel_mask_updated == true) {
6196 ALOGD("%s: return error to retry with updated channel mask (%#x)",
6197 __func__, config->channel_mask);
6198 ret = -EINVAL;
6199 goto err_open;
6200 }
Garmond Leunge2433c32017-09-28 21:51:22 -07006201 ALOGD("%s: created multi-channel session succesfully",__func__);
Mingming Yine62d7842013-10-25 16:26:03 -07006202 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08006203 audio_extn_compr_cap_format_supported(config->format) &&
6204 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006205 audio_extn_compr_cap_init(in);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306206 } else if (audio_extn_cin_applicable_stream(in)) {
6207 ret = audio_extn_cin_configure_input_stream(in);
6208 if (ret)
6209 goto err_open;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07006210 } else {
6211 in->config.channels = channel_count;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006212 if (!in->realtime) {
6213 in->format = config->format;
6214 frame_size = audio_stream_in_frame_size(&in->stream);
6215 buffer_size = get_input_buffer_size(config->sample_rate,
6216 config->format,
6217 channel_count,
6218 is_low_latency);
6219 in->config.period_size = buffer_size / frame_size;
6220 }
6221
Vikram Panduranga93f080e2017-06-07 18:16:14 -07006222#ifndef COMPRESS_VOIP_ENABLED
6223 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
6224 (in->config.rate == 8000 || in->config.rate == 16000 ||
6225 in->config.rate == 32000 || in->config.rate == 48000) &&
6226 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
6227
6228 in->usecase = USECASE_AUDIO_RECORD_VOIP;
6229 in->config = default_pcm_config_voip_copp;
6230 in->config.period_size = VOIP_IO_BUF_SIZE(in->sample_rate, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
6231 in->config.rate = in->sample_rate;
6232#else
Vidyakumar Athota5c398212015-03-31 21:53:21 -07006233 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
Haynes Mathew George16081042017-05-31 17:16:49 -07006234 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
6235 voice_extn_compress_voip_is_active(in->dev)) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07006236 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08006237 (in->config.rate == 8000 || in->config.rate == 16000 ||
6238 in->config.rate == 32000 || in->config.rate == 48000) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07006239 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
6240 voice_extn_compress_voip_open_input_stream(in);
Vikram Panduranga93f080e2017-06-07 18:16:14 -07006241#endif
Vidyakumar Athota5c398212015-03-31 21:53:21 -07006242 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07006243 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006244
Dhananjay Kumard6d32152016-10-13 16:11:03 +05306245 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
6246 &adev->streams_input_cfg_list,
6247 devices, flags, in->format, in->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05306248 in->bit_width, in->profile, &in->app_type_cfg);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05306249
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006250 /* This stream could be for sound trigger lab,
6251 get sound trigger pcm if present */
6252 audio_extn_sound_trigger_check_and_get_session(in);
6253
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306254 lock_input_stream(in);
6255 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
6256 pthread_mutex_lock(&adev->lock);
6257 in->card_status = adev->card_status;
6258 pthread_mutex_unlock(&adev->lock);
6259 pthread_mutex_unlock(&in->lock);
6260
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006261 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07006262 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08006263 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006264
6265err_open:
6266 free(in);
6267 *stream_in = NULL;
6268 return ret;
6269}
6270
6271static void adev_close_input_stream(struct audio_hw_device *dev,
6272 struct audio_stream_in *stream)
6273{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006274 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07006275 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006276 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306277
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306278 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08006279
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306280 // must deregister from sndmonitor first to prevent races
6281 // between the callback and close_stream
6282 audio_extn_snd_mon_unregister_listener(stream);
6283
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05306284 /* Disable echo reference while closing input stream */
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07006285 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05306286
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006287 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306288 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006289 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306290 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006291 if (ret != 0)
6292 ALOGE("%s: Compress voip input cannot be closed, error:%d",
6293 __func__, ret);
6294 } else
6295 in_standby(&stream->common);
6296
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07006297 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07006298 audio_extn_ssr_deinit();
6299 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006300
Garmond Leunge2433c32017-09-28 21:51:22 -07006301 if (audio_extn_ffv_get_stream() == in) {
6302 audio_extn_ffv_stream_deinit();
6303 }
6304
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306305 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07006306 audio_extn_compr_cap_format_supported(in->config.format))
6307 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05306308
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306309 if (audio_extn_cin_attached_usecase(in->usecase))
6310 audio_extn_cin_close_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006311
Mingming Yinfd7607b2016-01-22 12:48:44 -08006312 if (in->is_st_session) {
6313 ALOGV("%s: sound trigger pcm stop lab", __func__);
6314 audio_extn_sound_trigger_stop_lab(in);
6315 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006316 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006317 return;
6318}
6319
Siddartha Shaik31b530e2017-05-19 15:26:33 +05306320int adev_create_audio_patch(struct audio_hw_device *dev,
6321 unsigned int num_sources,
6322 const struct audio_port_config *sources,
6323 unsigned int num_sinks,
6324 const struct audio_port_config *sinks,
6325 audio_patch_handle_t *handle)
6326{
6327
6328
6329 return audio_extn_hw_loopback_create_audio_patch(dev,
6330 num_sources,
6331 sources,
6332 num_sinks,
6333 sinks,
6334 handle);
6335
6336}
6337
6338int adev_release_audio_patch(struct audio_hw_device *dev,
6339 audio_patch_handle_t handle)
6340{
6341 return audio_extn_hw_loopback_release_audio_patch(dev, handle);
6342}
6343
6344int adev_get_audio_port(struct audio_hw_device *dev, struct audio_port *config)
6345{
6346 return audio_extn_hw_loopback_get_audio_port(dev, config);
6347}
6348
6349int adev_set_audio_port_config(struct audio_hw_device *dev,
6350 const struct audio_port_config *config)
6351{
6352 return audio_extn_hw_loopback_set_audio_port_config(dev, config);
6353}
6354
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006355static int adev_dump(const audio_hw_device_t *device __unused,
6356 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006357{
6358 return 0;
6359}
6360
6361static int adev_close(hw_device_t *device)
6362{
6363 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07006364
6365 if (!adev)
6366 return 0;
6367
6368 pthread_mutex_lock(&adev_init_lock);
6369
6370 if ((--audio_device_ref_count) == 0) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306371 audio_extn_snd_mon_unregister_listener(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006372 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08006373 audio_extn_listen_deinit(adev);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05306374 audio_extn_utils_release_streams_cfg_lists(
6375 &adev->streams_output_cfg_list,
6376 &adev->streams_input_cfg_list);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05306377 if (audio_extn_qaf_is_enabled())
6378 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07006379 audio_route_free(adev->audio_route);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08006380 audio_extn_gef_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07006381 free(adev->snd_dev_ref_cnt);
6382 platform_deinit(adev->platform);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006383 if (adev->adm_deinit)
6384 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306385 qahwi_deinit(device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006386 audio_extn_adsp_hdlr_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306387 audio_extn_snd_mon_deinit();
Siddartha Shaik44dd7702017-06-14 12:13:25 +05306388 audio_extn_hw_loopback_deinit(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -07006389 audio_extn_ffv_deinit();
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +05306390 if (adev->device_cfg_params) {
6391 free(adev->device_cfg_params);
6392 adev->device_cfg_params = NULL;
6393 }
Kiran Kandi910e1862013-10-29 13:29:42 -07006394 free(device);
6395 adev = NULL;
6396 }
6397 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006398
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006399 return 0;
6400}
6401
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07006402/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
6403 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
6404 * just that it _might_ work.
6405 */
6406static int period_size_is_plausible_for_low_latency(int period_size)
6407{
6408 switch (period_size) {
6409 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07006410 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07006411 case 240:
6412 case 320:
6413 case 480:
6414 return 1;
6415 default:
6416 return 0;
6417 }
6418}
6419
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306420static void adev_snd_mon_cb(void *cookie, struct str_parms *parms)
6421{
6422 bool is_snd_card_status = false;
6423 bool is_ext_device_status = false;
6424 char value[32];
6425 int card = -1;
6426 card_status_t status;
6427
6428 if (cookie != adev || !parms)
6429 return;
6430
6431 if (!parse_snd_card_status(parms, &card, &status)) {
6432 is_snd_card_status = true;
6433 } else if (0 < str_parms_get_str(parms, "ext_audio_device", value, sizeof(value))) {
6434 is_ext_device_status = true;
6435 } else {
6436 // not a valid event
6437 return;
6438 }
6439
6440 pthread_mutex_lock(&adev->lock);
6441 if (card == adev->snd_card || is_ext_device_status) {
6442 if (is_snd_card_status && adev->card_status != status) {
6443 adev->card_status = status;
6444 platform_snd_card_update(adev->platform, status);
6445 audio_extn_fm_set_parameters(adev, parms);
6446 } else if (is_ext_device_status) {
6447 platform_set_parameters(adev->platform, parms);
6448 }
6449 }
6450 pthread_mutex_unlock(&adev->lock);
6451 return;
6452}
6453
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05306454/* out and adev lock held */
6455static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
6456{
6457 struct audio_usecase *uc_info;
6458 float left_p;
6459 float right_p;
6460 audio_devices_t devices;
6461
6462 uc_info = get_usecase_from_list(adev, out->usecase);
6463 if (uc_info == NULL) {
6464 ALOGE("%s: Could not find the usecase (%d) in the list",
6465 __func__, out->usecase);
6466 return -EINVAL;
6467 }
6468
6469 ALOGD("%s: enter: usecase(%d: %s)", __func__,
6470 out->usecase, use_case_table[out->usecase]);
6471
6472 if (restore) {
6473 // restore A2DP device for active usecases and unmute if required
6474 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
6475 (uc_info->out_snd_device != SND_DEVICE_OUT_BT_A2DP)) {
6476 ALOGD("%s: restoring A2dp and unmuting stream", __func__);
6477 select_devices(adev, uc_info->id);
6478 pthread_mutex_lock(&out->compr_mute_lock);
6479 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
6480 (out->a2dp_compress_mute)) {
6481 out->a2dp_compress_mute = false;
6482 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
6483 }
6484 pthread_mutex_unlock(&out->compr_mute_lock);
6485 }
6486 } else {
6487 // mute compress stream if suspended
6488 pthread_mutex_lock(&out->compr_mute_lock);
6489 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
6490 (!out->a2dp_compress_mute)) {
6491 if (!out->standby) {
6492 ALOGD("%s: selecting speaker and muting stream", __func__);
6493 devices = out->devices;
6494 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
6495 left_p = out->volume_l;
6496 right_p = out->volume_r;
6497 if (out->offload_state == OFFLOAD_STATE_PLAYING)
6498 compress_pause(out->compr);
6499 out_set_compr_volume(&out->stream, (float)0, (float)0);
6500 out->a2dp_compress_mute = true;
6501 select_devices(adev, out->usecase);
6502 if (out->offload_state == OFFLOAD_STATE_PLAYING)
6503 compress_resume(out->compr);
6504 out->devices = devices;
6505 out->volume_l = left_p;
6506 out->volume_r = right_p;
6507 }
6508 }
6509 pthread_mutex_unlock(&out->compr_mute_lock);
6510 }
6511 ALOGV("%s: exit", __func__);
6512 return 0;
6513}
6514
6515int check_a2dp_restore(struct audio_device *adev, struct stream_out *out, bool restore)
6516{
6517 int ret = 0;
6518
6519 lock_output_stream(out);
6520 pthread_mutex_lock(&adev->lock);
6521
6522 ret = check_a2dp_restore_l(adev, out, restore);
6523
6524 pthread_mutex_unlock(&adev->lock);
6525 pthread_mutex_unlock(&out->lock);
6526 return ret;
6527}
6528
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006529static int adev_open(const hw_module_t *module, const char *name,
6530 hw_device_t **device)
6531{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05306532 int ret;
6533
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08006534 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006535 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
6536
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07006537 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07006538 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07006539 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07006540 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07006541 ALOGD("%s: returning existing instance of adev", __func__);
6542 ALOGD("%s: exit", __func__);
6543 pthread_mutex_unlock(&adev_init_lock);
6544 return 0;
6545 }
6546
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006547 adev = calloc(1, sizeof(struct audio_device));
6548
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006549 if (!adev) {
6550 pthread_mutex_unlock(&adev_init_lock);
6551 return -ENOMEM;
6552 }
6553
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07006554 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
6555
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +05306556#ifdef DYNAMIC_LOG_ENABLED
6557 register_for_dynamic_logging("hal");
6558#endif
6559
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006560 adev->device.common.tag = HARDWARE_DEVICE_TAG;
6561 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
6562 adev->device.common.module = (struct hw_module_t *)module;
6563 adev->device.common.close = adev_close;
6564
6565 adev->device.init_check = adev_init_check;
6566 adev->device.set_voice_volume = adev_set_voice_volume;
6567 adev->device.set_master_volume = adev_set_master_volume;
6568 adev->device.get_master_volume = adev_get_master_volume;
6569 adev->device.set_master_mute = adev_set_master_mute;
6570 adev->device.get_master_mute = adev_get_master_mute;
6571 adev->device.set_mode = adev_set_mode;
6572 adev->device.set_mic_mute = adev_set_mic_mute;
6573 adev->device.get_mic_mute = adev_get_mic_mute;
6574 adev->device.set_parameters = adev_set_parameters;
6575 adev->device.get_parameters = adev_get_parameters;
6576 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
6577 adev->device.open_output_stream = adev_open_output_stream;
6578 adev->device.close_output_stream = adev_close_output_stream;
6579 adev->device.open_input_stream = adev_open_input_stream;
6580 adev->device.close_input_stream = adev_close_input_stream;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05306581 adev->device.create_audio_patch = adev_create_audio_patch;
6582 adev->device.release_audio_patch = adev_release_audio_patch;
6583 adev->device.get_audio_port = adev_get_audio_port;
6584 adev->device.set_audio_port_config = adev_set_audio_port_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006585 adev->device.dump = adev_dump;
6586
6587 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006588 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08006589 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08006590 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006591 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006592 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08006593 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -07006594 adev->allow_afe_proxy_usage = true;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306595 adev->bt_sco_on = false;
Eric Laurent07eeafd2013-10-06 12:52:49 -07006596 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07006597 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07006598 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08006599 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08006600 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006601 adev->offload_usecases_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05306602 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05306603 adev->perf_lock_opts[0] = 0x101;
6604 adev->perf_lock_opts[1] = 0x20E;
6605 adev->perf_lock_opts_size = 2;
Xiaojun Sang785b5da2017-08-03 15:52:29 +08006606 adev->dsp_bit_width_enforce_mode = 0;
Naresh Tanniru4c630392014-05-12 01:05:52 +05306607
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006608 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07006609 adev->platform = platform_init(adev);
6610 if (!adev->platform) {
6611 free(adev->snd_dev_ref_cnt);
6612 free(adev);
6613 ALOGE("%s: Failed to init platform data, aborting.", __func__);
6614 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08006615 pthread_mutex_unlock(&adev_init_lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05306616 pthread_mutex_destroy(&adev->lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07006617 return -EINVAL;
6618 }
Eric Laurentc4aef752013-09-12 17:45:53 -07006619
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05306620 if (audio_extn_qaf_is_enabled()) {
6621 ret = audio_extn_qaf_init(adev);
6622 if (ret < 0) {
6623 free(adev);
6624 ALOGE("%s: Failed to init platform data, aborting.", __func__);
6625 *device = NULL;
6626 pthread_mutex_unlock(&adev_init_lock);
6627 pthread_mutex_destroy(&adev->lock);
6628 return ret;
6629 }
6630
6631 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
6632 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
6633 }
6634
Eric Laurentc4aef752013-09-12 17:45:53 -07006635 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
6636 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
6637 if (adev->visualizer_lib == NULL) {
6638 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
6639 } else {
6640 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
6641 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08006642 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07006643 "visualizer_hal_start_output");
6644 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08006645 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07006646 "visualizer_hal_stop_output");
6647 }
6648 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +05306649 audio_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08006650 audio_extn_listen_init(adev, adev->snd_card);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08006651 audio_extn_gef_init(adev);
Siddartha Shaik44dd7702017-06-14 12:13:25 +05306652 audio_extn_hw_loopback_init(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -07006653 audio_extn_ffv_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07006654
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08006655 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
6656 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
6657 if (adev->offload_effects_lib == NULL) {
6658 ALOGE("%s: DLOPEN failed for %s", __func__,
6659 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
6660 } else {
6661 ALOGV("%s: DLOPEN successful for %s", __func__,
6662 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
6663 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +05306664 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08006665 "offload_effects_bundle_hal_start_output");
6666 adev->offload_effects_stop_output =
6667 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
6668 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006669 adev->offload_effects_set_hpx_state =
6670 (int (*)(bool))dlsym(adev->offload_effects_lib,
6671 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05306672 adev->offload_effects_get_parameters =
6673 (void (*)(struct str_parms *, struct str_parms *))
6674 dlsym(adev->offload_effects_lib,
6675 "offload_effects_bundle_get_parameters");
6676 adev->offload_effects_set_parameters =
6677 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
6678 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08006679 }
6680 }
6681
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006682 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
6683 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
6684 if (adev->adm_lib == NULL) {
6685 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
6686 } else {
6687 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
6688 adev->adm_init = (adm_init_t)
6689 dlsym(adev->adm_lib, "adm_init");
6690 adev->adm_deinit = (adm_deinit_t)
6691 dlsym(adev->adm_lib, "adm_deinit");
6692 adev->adm_register_input_stream = (adm_register_input_stream_t)
6693 dlsym(adev->adm_lib, "adm_register_input_stream");
6694 adev->adm_register_output_stream = (adm_register_output_stream_t)
6695 dlsym(adev->adm_lib, "adm_register_output_stream");
6696 adev->adm_deregister_stream = (adm_deregister_stream_t)
6697 dlsym(adev->adm_lib, "adm_deregister_stream");
6698 adev->adm_request_focus = (adm_request_focus_t)
6699 dlsym(adev->adm_lib, "adm_request_focus");
6700 adev->adm_abandon_focus = (adm_abandon_focus_t)
6701 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006702 adev->adm_set_config = (adm_set_config_t)
6703 dlsym(adev->adm_lib, "adm_set_config");
6704 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
6705 dlsym(adev->adm_lib, "adm_request_focus_v2");
6706 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
6707 dlsym(adev->adm_lib, "adm_is_noirq_avail");
6708 adev->adm_on_routing_change = (adm_on_routing_change_t)
6709 dlsym(adev->adm_lib, "adm_on_routing_change");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006710 }
6711 }
6712
Mingming Yin514a8bc2014-07-29 15:22:21 -07006713 adev->bt_wb_speech_enabled = false;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08006714 //initialize this to false for now,
6715 //this will be set to true through set param
6716 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -07006717
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07006718 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006719 *device = &adev->device.common;
Xiaojun Sang785b5da2017-08-03 15:52:29 +08006720 adev->dsp_bit_width_enforce_mode =
6721 adev_init_dsp_bit_width_enforce_mode(adev->mixer);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006722
Dhananjay Kumard6d32152016-10-13 16:11:03 +05306723 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
6724 &adev->streams_output_cfg_list,
6725 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07006726
Kiran Kandi910e1862013-10-29 13:29:42 -07006727 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07006728
6729 char value[PROPERTY_VALUE_MAX];
6730 int trial;
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07006731 if (property_get("vendor.audio_hal.period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07006732 trial = atoi(value);
6733 if (period_size_is_plausible_for_low_latency(trial)) {
6734 pcm_config_low_latency.period_size = trial;
6735 pcm_config_low_latency.start_threshold = trial / 4;
6736 pcm_config_low_latency.avail_min = trial / 4;
6737 configured_low_latency_capture_period_size = trial;
6738 }
6739 }
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07006740 if (property_get("vendor.audio_hal.in_period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07006741 trial = atoi(value);
6742 if (period_size_is_plausible_for_low_latency(trial)) {
6743 configured_low_latency_capture_period_size = trial;
6744 }
6745 }
6746
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07006747 if (property_get("vendor.audio_hal.period_multiplier", value, NULL) > 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006748 af_period_multiplier = atoi(value);
6749 if (af_period_multiplier < 0)
6750 af_period_multiplier = 2;
6751 else if (af_period_multiplier > 4)
6752 af_period_multiplier = 4;
6753
6754 ALOGV("new period_multiplier = %d", af_period_multiplier);
6755 }
6756
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07006757 adev->multi_offload_enable = property_get_bool("vendor.audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07006758 pthread_mutex_unlock(&adev_init_lock);
6759
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006760 if (adev->adm_init)
6761 adev->adm_data = adev->adm_init();
6762
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306763 qahwi_init(*device);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05306764 audio_extn_perf_lock_init();
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006765 audio_extn_adsp_hdlr_init(adev->mixer);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306766
6767 audio_extn_snd_mon_init();
6768 pthread_mutex_lock(&adev->lock);
6769 audio_extn_snd_mon_register_listener(adev, adev_snd_mon_cb);
6770 adev->card_status = CARD_STATUS_ONLINE;
6771 pthread_mutex_unlock(&adev->lock);
6772 audio_extn_sound_trigger_init(adev); /* dependent on snd_mon_init() */
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +05306773 /* Allocate memory for Device config params */
6774 adev->device_cfg_params = (struct audio_device_config_param*)
6775 calloc(platform_get_max_codec_backend(),
6776 sizeof(struct audio_device_config_param));
6777 if (adev->device_cfg_params == NULL)
6778 ALOGE("%s: Memory allocation failed for Device config params", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306779
Eric Laurent994a6932013-07-17 11:51:42 -07006780 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006781 return 0;
6782}
6783
6784static struct hw_module_methods_t hal_module_methods = {
6785 .open = adev_open,
6786};
6787
6788struct audio_module HAL_MODULE_INFO_SYM = {
6789 .common = {
6790 .tag = HARDWARE_MODULE_TAG,
6791 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
6792 .hal_api_version = HARDWARE_HAL_API_VERSION,
6793 .id = AUDIO_HARDWARE_MODULE_ID,
6794 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08006795 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006796 .methods = &hal_module_methods,
6797 },
6798};