blob: 926a63fb8f5011730c93e5c76401f94d18ceeffb [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",
Eric Laurentb23d5282013-05-14 15:27:20 -0700330};
331
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700332static const audio_usecase_t offload_usecases[] = {
333 USECASE_AUDIO_PLAYBACK_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700334 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
335 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
336 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
337 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
338 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
339 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
340 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
341 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700342};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800343
Varun Balaraje49253e2017-07-06 19:48:56 +0530344static const audio_usecase_t interactive_usecases[] = {
345 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1,
346 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2,
347 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3,
348 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4,
349 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5,
350 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6,
351 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7,
352 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8,
353};
354
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800355#define STRING_TO_ENUM(string) { #string, string }
356
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800357struct string_to_enum {
358 const char *name;
359 uint32_t value;
360};
361
362static const struct string_to_enum out_channels_name_to_enum_table[] = {
363 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Mingming Yin3a941d42016-02-17 18:08:05 -0800364 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_2POINT1),
365 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),
366 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_SURROUND),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700367 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
Mingming Yin3a941d42016-02-17 18:08:05 -0800368 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
369 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_6POINT1),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800370 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
371};
372
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700373static const struct string_to_enum out_formats_name_to_enum_table[] = {
374 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
375 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
376 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
Ben Romberger1aaaf862017-04-06 17:49:46 -0700377 STRING_TO_ENUM(AUDIO_FORMAT_DOLBY_TRUEHD),
Mingming Yin3a941d42016-02-17 18:08:05 -0800378 STRING_TO_ENUM(AUDIO_FORMAT_DTS),
379 STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD),
Naresh Tanniru928f0862017-04-07 16:44:23 -0700380 STRING_TO_ENUM(AUDIO_FORMAT_IEC61937)
Mingming Yin3a941d42016-02-17 18:08:05 -0800381};
382
383//list of all supported sample rates by HDMI specification.
384static const int out_hdmi_sample_rates[] = {
385 32000, 44100, 48000, 88200, 96000, 176400, 192000,
386};
387
388static const struct string_to_enum out_hdmi_sample_rates_name_to_enum_table[] = {
389 STRING_TO_ENUM(32000),
390 STRING_TO_ENUM(44100),
391 STRING_TO_ENUM(48000),
392 STRING_TO_ENUM(88200),
393 STRING_TO_ENUM(96000),
394 STRING_TO_ENUM(176400),
395 STRING_TO_ENUM(192000),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700396};
397
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700398static struct audio_device *adev = NULL;
399static pthread_mutex_t adev_init_lock;
Kiran Kandi910e1862013-10-29 13:29:42 -0700400static unsigned int audio_device_ref_count;
vivek mehtab72d08d2016-04-29 03:16:47 -0700401//cache last MBDRC cal step level
402static int last_known_cal_step = -1 ;
Kiran Kandi910e1862013-10-29 13:29:42 -0700403
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530404static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore);
405static int out_set_compr_volume(struct audio_stream_out *stream, float left, float right);
406
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700407static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
408 int flags __unused)
409{
410 int dir = 0;
411 switch (uc_id) {
412 case USECASE_AUDIO_RECORD_LOW_LATENCY:
413 dir = 1;
414 case USECASE_AUDIO_PLAYBACK_ULL:
415 break;
416 default:
417 return false;
418 }
419
420 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
421 PCM_PLAYBACK : PCM_CAPTURE);
422 if (adev->adm_is_noirq_avail)
423 return adev->adm_is_noirq_avail(adev->adm_data,
424 adev->snd_card, dev_id, dir);
425 return false;
426}
427
428static void register_out_stream(struct stream_out *out)
429{
430 struct audio_device *adev = out->dev;
431 if (is_offload_usecase(out->usecase) ||
432 !adev->adm_register_output_stream)
433 return;
434
435 // register stream first for backward compatibility
436 adev->adm_register_output_stream(adev->adm_data,
437 out->handle,
438 out->flags);
439
440 if (!adev->adm_set_config)
441 return;
442
443 if (out->realtime)
444 adev->adm_set_config(adev->adm_data,
445 out->handle,
446 out->pcm, &out->config);
447}
448
449static void register_in_stream(struct stream_in *in)
450{
451 struct audio_device *adev = in->dev;
452 if (!adev->adm_register_input_stream)
453 return;
454
455 adev->adm_register_input_stream(adev->adm_data,
456 in->capture_handle,
457 in->flags);
458
459 if (!adev->adm_set_config)
460 return;
461
462 if (in->realtime)
463 adev->adm_set_config(adev->adm_data,
464 in->capture_handle,
465 in->pcm,
466 &in->config);
467}
468
469static void request_out_focus(struct stream_out *out, long ns)
470{
471 struct audio_device *adev = out->dev;
472
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700473 if (adev->adm_request_focus_v2)
474 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
475 else if (adev->adm_request_focus)
476 adev->adm_request_focus(adev->adm_data, out->handle);
477}
478
479static void request_in_focus(struct stream_in *in, long ns)
480{
481 struct audio_device *adev = in->dev;
482
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700483 if (adev->adm_request_focus_v2)
484 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
485 else if (adev->adm_request_focus)
486 adev->adm_request_focus(adev->adm_data, in->capture_handle);
487}
488
489static void release_out_focus(struct stream_out *out)
490{
491 struct audio_device *adev = out->dev;
492
493 if (adev->adm_abandon_focus)
494 adev->adm_abandon_focus(adev->adm_data, out->handle);
495}
496
497static void release_in_focus(struct stream_in *in)
498{
499 struct audio_device *adev = in->dev;
500 if (adev->adm_abandon_focus)
501 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
502}
503
Dhananjay Kumare6293dd2017-05-25 17:25:30 +0530504static int parse_snd_card_status(struct str_parms *parms, int *card,
505 card_status_t *status)
506{
507 char value[32]={0};
508 char state[32]={0};
509
510 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
511 if (ret < 0)
512 return -1;
513
514 // sscanf should be okay as value is of max length 32.
515 // same as sizeof state.
516 if (sscanf(value, "%d,%s", card, state) < 2)
517 return -1;
518
519 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
520 CARD_STATUS_OFFLINE;
521 return 0;
522}
523
vivek mehtaa76401a2015-04-24 14:12:15 -0700524__attribute__ ((visibility ("default")))
525bool audio_hw_send_gain_dep_calibration(int level) {
526 bool ret_val = false;
vivek mehtab72d08d2016-04-29 03:16:47 -0700527 ALOGV("%s: called ...", __func__);
vivek mehtaa76401a2015-04-24 14:12:15 -0700528
529 pthread_mutex_lock(&adev_init_lock);
530
531 if (adev != NULL && adev->platform != NULL) {
532 pthread_mutex_lock(&adev->lock);
533 ret_val = platform_send_gain_dep_cal(adev->platform, level);
vivek mehtab72d08d2016-04-29 03:16:47 -0700534
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +0530535 // cache level info for any of the use case which
536 // was not started.
537 last_known_cal_step = level;;
vivek mehtab72d08d2016-04-29 03:16:47 -0700538
vivek mehtaa76401a2015-04-24 14:12:15 -0700539 pthread_mutex_unlock(&adev->lock);
540 } else {
541 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
542 }
543
544 pthread_mutex_unlock(&adev_init_lock);
545
546 return ret_val;
547}
548
Ashish Jain5106d362016-05-11 19:23:33 +0530549static int check_and_set_gapless_mode(struct audio_device *adev, bool enable_gapless)
550{
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800551 bool gapless_enabled = false;
552 const char *mixer_ctl_name = "Compress Gapless Playback";
553 struct mixer_ctl *ctl;
554
555 ALOGV("%s:", __func__);
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -0700556 gapless_enabled = property_get_bool("vendor.audio.offload.gapless.enabled", false);
Ashish Jain5106d362016-05-11 19:23:33 +0530557
558 /*Disable gapless if its AV playback*/
559 gapless_enabled = gapless_enabled && enable_gapless;
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800560
561 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
562 if (!ctl) {
563 ALOGE("%s: Could not get ctl for mixer cmd - %s",
564 __func__, mixer_ctl_name);
565 return -EINVAL;
566 }
567
568 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
569 ALOGE("%s: Could not set gapless mode %d",
570 __func__, gapless_enabled);
571 return -EINVAL;
572 }
573 return 0;
574}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700575
Aniket Kumar Lataf56b6402016-10-27 12:03:18 -0700576__attribute__ ((visibility ("default")))
577int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
578 int table_size) {
579 int ret_val = 0;
580 ALOGV("%s: enter ... ", __func__);
581
582 pthread_mutex_lock(&adev_init_lock);
583 if (adev == NULL) {
584 ALOGW("%s: adev is NULL .... ", __func__);
585 goto done;
586 }
587
588 pthread_mutex_lock(&adev->lock);
589 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
590 pthread_mutex_unlock(&adev->lock);
591done:
592 pthread_mutex_unlock(&adev_init_lock);
593 ALOGV("%s: exit ... ", __func__);
594 return ret_val;
595}
596
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700597static bool is_supported_format(audio_format_t format)
598{
Eric Laurent86e17132013-09-12 17:49:30 -0700599 if (format == AUDIO_FORMAT_MP3 ||
Satish Babu Patakokila0c313922016-12-08 12:07:08 +0530600 format == AUDIO_FORMAT_MP2 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530601 format == AUDIO_FORMAT_AAC_LC ||
602 format == AUDIO_FORMAT_AAC_HE_V1 ||
603 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530604 format == AUDIO_FORMAT_AAC_ADTS_LC ||
605 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
606 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
Arun Kumar Dasari3b174182016-12-27 13:01:14 +0530607 format == AUDIO_FORMAT_AAC_LATM_LC ||
608 format == AUDIO_FORMAT_AAC_LATM_HE_V1 ||
609 format == AUDIO_FORMAT_AAC_LATM_HE_V2 ||
Ashish Jain5106d362016-05-11 19:23:33 +0530610 format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
611 format == AUDIO_FORMAT_PCM_8_24_BIT ||
Ashish Jainf1eaa582016-05-23 20:54:24 +0530612 format == AUDIO_FORMAT_PCM_FLOAT ||
613 format == AUDIO_FORMAT_PCM_32_BIT ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700614 format == AUDIO_FORMAT_PCM_16_BIT ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530615 format == AUDIO_FORMAT_AC3 ||
616 format == AUDIO_FORMAT_E_AC3 ||
Ben Romberger1aaaf862017-04-06 17:49:46 -0700617 format == AUDIO_FORMAT_DOLBY_TRUEHD ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530618 format == AUDIO_FORMAT_DTS ||
619 format == AUDIO_FORMAT_DTS_HD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800620 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530621 format == AUDIO_FORMAT_ALAC ||
622 format == AUDIO_FORMAT_APE ||
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530623 format == AUDIO_FORMAT_DSD ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530624 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800625 format == AUDIO_FORMAT_WMA ||
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +0530626 format == AUDIO_FORMAT_WMA_PRO ||
Naresh Tanniru928f0862017-04-07 16:44:23 -0700627 format == AUDIO_FORMAT_APTX ||
628 format == AUDIO_FORMAT_IEC61937)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800629 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700630
631 return false;
632}
633
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700634static inline bool is_mmap_usecase(audio_usecase_t uc_id)
635{
636 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
637 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
638}
639
Avinash Vaish71a8b972014-07-24 15:36:33 +0530640static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
641 struct audio_usecase *uc_info)
642{
643 struct listnode *node;
644 struct audio_usecase *usecase;
645
646 if (uc_info == NULL)
647 return -EINVAL;
648
649 /* Re-route all voice usecases on the shared backend other than the
650 specified usecase to new snd devices */
651 list_for_each(node, &adev->usecase_list) {
652 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800653 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530654 enable_audio_route(adev, usecase);
655 }
656 return 0;
657}
658
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530659static void enable_asrc_mode(struct audio_device *adev)
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530660{
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530661 ALOGV("%s", __func__);
662 audio_route_apply_and_update_path(adev->audio_route,
663 "asrc-mode");
664 adev->asrc_mode_enabled = true;
665}
666
667static void disable_asrc_mode(struct audio_device *adev)
668{
669 ALOGV("%s", __func__);
670 audio_route_reset_and_update_path(adev->audio_route,
671 "asrc-mode");
672 adev->asrc_mode_enabled = false;
673}
674
675/*
676 * - Enable ASRC mode for incoming mix path use case(Headphone backend)if Headphone
677 * 44.1 or Native DSD backends are enabled for any of current use case.
678 * e.g. 48-> + (Naitve DSD or Headphone 44.1)
679 * - Disable current mix path use case(Headphone backend) and re-enable it with
680 * ASRC mode for incoming Headphone 44.1 or Native DSD use case.
681 * e.g. Naitve DSD or Headphone 44.1 -> + 48
682 */
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530683static void check_and_set_asrc_mode(struct audio_device *adev,
684 struct audio_usecase *uc_info,
685 snd_device_t snd_device)
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530686{
687 ALOGV("%s snd device %d", __func__, snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530688 int i, num_new_devices = 0;
689 snd_device_t split_new_snd_devices[SND_DEVICE_OUT_END];
690 /*
691 *Split snd device for new combo use case
692 *e.g. Headphopne 44.1-> + Ringtone (Headphone + Speaker)
693 */
694 if (platform_split_snd_device(adev->platform,
695 snd_device,
696 &num_new_devices,
697 split_new_snd_devices) == 0) {
698 for (i = 0; i < num_new_devices; i++)
699 check_and_set_asrc_mode(adev, uc_info, split_new_snd_devices[i]);
700 } else {
701 int new_backend_idx = platform_get_backend_index(snd_device);
702 if (((new_backend_idx == HEADPHONE_BACKEND) ||
703 (new_backend_idx == HEADPHONE_44_1_BACKEND) ||
704 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
705 !adev->asrc_mode_enabled) {
706 struct listnode *node = NULL;
707 struct audio_usecase *uc = NULL;
708 struct stream_out *curr_out = NULL;
709 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
710 int i, num_devices, ret = 0;
711 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530712
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530713 list_for_each(node, &adev->usecase_list) {
714 uc = node_to_item(node, struct audio_usecase, list);
715 curr_out = (struct stream_out*) uc->stream.out;
716 if (curr_out && PCM_PLAYBACK == uc->type && uc != uc_info) {
717 /*
718 *Split snd device for existing combo use case
719 *e.g. Ringtone (Headphone + Speaker) + Headphopne 44.1
720 */
721 ret = platform_split_snd_device(adev->platform,
722 uc->out_snd_device,
723 &num_devices,
724 split_snd_devices);
725 if (ret < 0 || num_devices == 0) {
726 ALOGV("%s: Unable to split uc->out_snd_device: %d",__func__, uc->out_snd_device);
727 split_snd_devices[0] = uc->out_snd_device;
728 num_devices = 1;
Garmond Leung50058f62017-02-08 09:49:30 -0800729 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530730 for (i = 0; i < num_devices; i++) {
731 usecase_backend_idx = platform_get_backend_index(split_snd_devices[i]);
732 ALOGD("%s:snd_dev %d usecase_backend_idx %d",__func__, split_snd_devices[i],usecase_backend_idx);
733 if((new_backend_idx == HEADPHONE_BACKEND) &&
734 ((usecase_backend_idx == HEADPHONE_44_1_BACKEND) ||
735 (usecase_backend_idx == DSD_NATIVE_BACKEND))) {
736 ALOGD("%s:DSD or native stream detected enabling asrcmode in hardware",
737 __func__);
738 enable_asrc_mode(adev);
739 break;
740 } else if(((new_backend_idx == HEADPHONE_44_1_BACKEND) ||
741 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
742 (usecase_backend_idx == HEADPHONE_BACKEND)) {
743 ALOGD("%s:48K stream detected, disabling and enabling it with asrcmode in hardware",
744 __func__);
745 disable_audio_route(adev, uc);
746 disable_snd_device(adev, uc->out_snd_device);
747 // Apply true-high-quality-mode if DSD or > 44.1KHz or >=24-bit
748 if (new_backend_idx == DSD_NATIVE_BACKEND)
749 audio_route_apply_and_update_path(adev->audio_route,
750 "hph-true-highquality-mode");
751 else if ((new_backend_idx == HEADPHONE_44_1_BACKEND) &&
752 (curr_out->bit_width >= 24))
753 audio_route_apply_and_update_path(adev->audio_route,
754 "hph-highquality-mode");
755 enable_asrc_mode(adev);
756 enable_snd_device(adev, uc->out_snd_device);
757 enable_audio_route(adev, uc);
758 break;
759 }
760 }
761 // reset split devices count
762 num_devices = 0;
Garmond Leung50058f62017-02-08 09:49:30 -0800763 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530764 if (adev->asrc_mode_enabled)
765 break;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530766 }
767 }
768 }
769}
770
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700771int pcm_ioctl(struct pcm *pcm, int request, ...)
772{
773 va_list ap;
774 void * arg;
775 int pcm_fd = *(int*)pcm;
776
777 va_start(ap, request);
778 arg = va_arg(ap, void *);
779 va_end(ap);
780
781 return ioctl(pcm_fd, request, arg);
782}
783
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700784int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700785 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800786{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700787 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700788 char mixer_path[MIXER_PATH_MAX_LENGTH];
Manish Dewangan58229382017-02-02 15:48:41 +0530789 struct stream_out *out = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800790
791 if (usecase == NULL)
792 return -EINVAL;
793
794 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
795
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800796 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700797 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800798 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700799 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800800
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -0800801#ifdef DS1_DOLBY_DAP_ENABLED
802 audio_extn_dolby_set_dmid(adev);
803 audio_extn_dolby_set_endpoint(adev);
804#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700805 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700806 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530807 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -0700808 audio_extn_utils_send_app_type_cfg(adev, usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +0530809 audio_extn_utils_send_audio_calibration(adev, usecase);
Manish Dewangan58229382017-02-02 15:48:41 +0530810 if ((usecase->type == PCM_PLAYBACK) && is_offload_usecase(usecase->id)) {
811 out = usecase->stream.out;
812 if (out && out->compr)
813 audio_extn_utils_compress_set_clk_rec_mode(usecase);
814 }
815
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800816 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700817 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700818 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700819 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800820 ALOGV("%s: exit", __func__);
821 return 0;
822}
823
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700824int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700825 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800826{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700827 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700828 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800829
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +0530830 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800831 return -EINVAL;
832
833 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700834 if (usecase->type == PCM_CAPTURE)
835 snd_device = usecase->in_snd_device;
836 else
837 snd_device = usecase->out_snd_device;
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800838 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700839 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700840 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700841 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700842 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530843 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800844 ALOGV("%s: exit", __func__);
845 return 0;
846}
847
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700848int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700849 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800850{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530851 int i, num_devices = 0;
852 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700853 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
854
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800855 if (snd_device < SND_DEVICE_MIN ||
856 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800857 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800858 return -EINVAL;
859 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700860
861 adev->snd_dev_ref_cnt[snd_device]++;
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700862
863 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
864 ALOGE("%s: Invalid sound device returned", __func__);
865 return -EINVAL;
866 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700867 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700868 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700869 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700870 return 0;
871 }
872
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530873
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -0700874 if (audio_extn_spkr_prot_is_enabled())
875 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700876
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800877 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
878 audio_extn_spkr_prot_is_enabled()) {
879 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700880 adev->snd_dev_ref_cnt[snd_device]--;
881 return -EINVAL;
882 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200883 audio_extn_dev_arbi_acquire(snd_device);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800884 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800885 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200886 audio_extn_dev_arbi_release(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800887 return -EINVAL;
888 }
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -0700889 } else if (platform_split_snd_device(adev->platform,
890 snd_device,
891 &num_devices,
892 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530893 for (i = 0; i < num_devices; i++) {
894 enable_snd_device(adev, new_snd_devices[i]);
895 }
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800896 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700897 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530898
Preetam Singh Ranawatf1d417c2017-01-10 17:00:32 +0530899
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530900 if ((SND_DEVICE_OUT_BT_A2DP == snd_device) &&
901 (audio_extn_a2dp_start_playback() < 0)) {
902 ALOGE(" fail to configure A2dp control path ");
903 return -EINVAL;
904 }
905
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -0700906 /* due to the possibility of calibration overwrite between listen
907 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700908 audio_extn_sound_trigger_update_device_status(snd_device,
909 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530910 audio_extn_listen_update_device_status(snd_device,
911 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700912 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700913 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700914 audio_extn_sound_trigger_update_device_status(snd_device,
915 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530916 audio_extn_listen_update_device_status(snd_device,
917 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700918 return -EINVAL;
919 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300920 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700921 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530922
923 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
924 !adev->native_playback_enabled &&
925 audio_is_true_native_stream_active(adev)) {
926 ALOGD("%s: %d: napb: enabling native mode in hardware",
927 __func__, __LINE__);
928 audio_route_apply_and_update_path(adev->audio_route,
929 "true-native-mode");
930 adev->native_playback_enabled = true;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530931 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800932 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800933 return 0;
934}
935
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700936int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700937 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800938{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530939 int i, num_devices = 0;
940 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700941 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
942
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800943 if (snd_device < SND_DEVICE_MIN ||
944 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800945 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800946 return -EINVAL;
947 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700948 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
949 ALOGE("%s: device ref cnt is already 0", __func__);
950 return -EINVAL;
951 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700952
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700953 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700954
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700955 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
956 ALOGE("%s: Invalid sound device returned", __func__);
957 return -EINVAL;
958 }
959
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700960 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700961 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530962
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800963 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
964 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -0700965 audio_extn_spkr_prot_stop_processing(snd_device);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -0700966 } else if (platform_split_snd_device(adev->platform,
967 snd_device,
968 &num_devices,
969 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530970 for (i = 0; i < num_devices; i++) {
971 disable_snd_device(adev, new_snd_devices[i]);
972 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300973 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700974 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300975 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700976
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530977 if (SND_DEVICE_OUT_BT_A2DP == snd_device)
978 audio_extn_a2dp_stop_playback();
979
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -0700980 if (snd_device == SND_DEVICE_OUT_HDMI || snd_device == SND_DEVICE_OUT_DISPLAY_PORT)
Ashish Jain81eb2a82015-05-13 10:52:34 +0530981 adev->is_channel_status_set = false;
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530982 else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
983 adev->native_playback_enabled) {
984 ALOGD("%s: %d: napb: disabling native mode in hardware",
985 __func__, __LINE__);
986 audio_route_reset_and_update_path(adev->audio_route,
987 "true-native-mode");
988 adev->native_playback_enabled = false;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530989 } else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
990 adev->asrc_mode_enabled) {
991 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530992 disable_asrc_mode(adev);
993 audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530994 }
Ashish Jain81eb2a82015-05-13 10:52:34 +0530995
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200996 audio_extn_dev_arbi_release(snd_device);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700997 audio_extn_sound_trigger_update_device_status(snd_device,
998 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530999 audio_extn_listen_update_device_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -08001000 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001001 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001002
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001003 return 0;
1004}
1005
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001006/*
1007 legend:
1008 uc - existing usecase
1009 new_uc - new usecase
1010 d1, d11, d2 - SND_DEVICE enums
1011 a1, a2 - corresponding ANDROID device enums
1012 B1, B2 - backend strings
1013
1014case 1
1015 uc->dev d1 (a1) B1
1016 new_uc->dev d1 (a1), d2 (a2) B1, B2
1017
1018 resolution: disable and enable uc->dev on d1
1019
1020case 2
1021 uc->dev d1 (a1) B1
1022 new_uc->dev d11 (a1) B1
1023
1024 resolution: need to switch uc since d1 and d11 are related
1025 (e.g. speaker and voice-speaker)
1026 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
1027
1028case 3
1029 uc->dev d1 (a1) B1
1030 new_uc->dev d2 (a2) B2
1031
1032 resolution: no need to switch uc
1033
1034case 4
1035 uc->dev d1 (a1) B1
1036 new_uc->dev d2 (a2) B1
1037
1038 resolution: disable enable uc-dev on d2 since backends match
1039 we cannot enable two streams on two different devices if they
1040 share the same backend. e.g. if offload is on speaker device using
1041 QUAD_MI2S backend and a low-latency stream is started on voice-handset
1042 using the same backend, offload must also be switched to voice-handset.
1043
1044case 5
1045 uc->dev d1 (a1) B1
1046 new_uc->dev d1 (a1), d2 (a2) B1
1047
1048 resolution: disable enable uc-dev on d2 since backends match
1049 we cannot enable two streams on two different devices if they
1050 share the same backend.
1051
1052case 6
1053 uc->dev d1 (a1) B1
1054 new_uc->dev d2 (a1) B2
1055
1056 resolution: no need to switch
1057
1058case 7
1059 uc->dev d1 (a1), d2 (a2) B1, B2
1060 new_uc->dev d1 (a1) B1
1061
1062 resolution: no need to switch
1063
1064*/
1065static snd_device_t derive_playback_snd_device(void * platform,
1066 struct audio_usecase *uc,
1067 struct audio_usecase *new_uc,
1068 snd_device_t new_snd_device)
1069{
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301070 audio_devices_t a1, a2;
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001071
1072 snd_device_t d1 = uc->out_snd_device;
1073 snd_device_t d2 = new_snd_device;
1074
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301075 switch (uc->type) {
1076 case TRANSCODE_LOOPBACK :
1077 a1 = uc->stream.inout->out_config.devices;
1078 a2 = new_uc->stream.inout->out_config.devices;
1079 break;
1080 default :
1081 a1 = uc->stream.out->devices;
1082 a2 = new_uc->stream.out->devices;
1083 break;
1084 }
1085
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001086 // Treat as a special case when a1 and a2 are not disjoint
1087 if ((a1 != a2) && (a1 & a2)) {
1088 snd_device_t d3[2];
1089 int num_devices = 0;
1090 int ret = platform_split_snd_device(platform,
1091 popcount(a1) > 1 ? d1 : d2,
1092 &num_devices,
1093 d3);
1094 if (ret < 0) {
1095 if (ret != -ENOSYS) {
1096 ALOGW("%s failed to split snd_device %d",
1097 __func__,
1098 popcount(a1) > 1 ? d1 : d2);
1099 }
1100 goto end;
1101 }
1102
1103 // NB: case 7 is hypothetical and isn't a practical usecase yet.
1104 // But if it does happen, we need to give priority to d2 if
1105 // the combo devices active on the existing usecase share a backend.
1106 // This is because we cannot have a usecase active on a combo device
1107 // and a new usecase requests one device in this combo pair.
1108 if (platform_check_backends_match(d3[0], d3[1])) {
1109 return d2; // case 5
1110 } else {
1111 return d1; // case 1
1112 }
1113 } else {
1114 if (platform_check_backends_match(d1, d2)) {
1115 return d2; // case 2, 4
1116 } else {
1117 return d1; // case 6, 3
1118 }
1119 }
1120
1121end:
1122 return d2; // return whatever was calculated before.
1123}
1124
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001125static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301126 struct audio_usecase *uc_info,
1127 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001128{
1129 struct listnode *node;
1130 struct audio_usecase *usecase;
1131 bool switch_device[AUDIO_USECASE_MAX];
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301132 snd_device_t uc_derive_snd_device;
1133 snd_device_t derive_snd_device[AUDIO_USECASE_MAX];
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001134 int i, num_uc_to_switch = 0;
kunleiz5cd52b82016-11-07 17:22:52 +08001135 int status = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301136 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001137 /*
1138 * This function is to make sure that all the usecases that are active on
1139 * the hardware codec backend are always routed to any one device that is
1140 * handled by the hardware codec.
1141 * For example, if low-latency and deep-buffer usecases are currently active
1142 * on speaker and out_set_parameters(headset) is received on low-latency
1143 * output, then we have to make sure deep-buffer is also switched to headset,
1144 * because of the limitation that both the devices cannot be enabled
1145 * at the same time as they share the same backend.
1146 */
Mingming Yin3ee55c62014-08-04 14:23:35 -07001147 /*
1148 * This call is to check if we need to force routing for a particular stream
1149 * If there is a backend configuration change for the device when a
1150 * new stream starts, then ADM needs to be closed and re-opened with the new
1151 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001152 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -07001153 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001154 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
1155 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301156 /* For a2dp device reconfigure all active sessions
1157 * with new AFE encoder format based on a2dp state
1158 */
1159 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
1160 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device) &&
1161 audio_extn_a2dp_is_force_device_switch()) {
1162 force_routing = true;
1163 force_restart_session = true;
1164 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301165 ALOGD("%s:becf: force routing %d", __func__, force_routing);
1166
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001167 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001168 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001169 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001170 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1171 switch_device[i] = false;
1172
1173 list_for_each(node, &adev->usecase_list) {
1174 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001175
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301176 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
1177 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301178 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301179 platform_get_snd_device_name(usecase->out_snd_device),
1180 platform_check_backends_match(snd_device, usecase->out_snd_device));
Ashish Jain6a65b352017-03-21 17:24:40 +05301181 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info)) {
1182 uc_derive_snd_device = derive_playback_snd_device(adev->platform,
1183 usecase, uc_info, snd_device);
1184 if (((uc_derive_snd_device != usecase->out_snd_device) || force_routing) &&
1185 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1186 (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
1187 (usecase->devices & AUDIO_DEVICE_OUT_USB_DEVICE) ||
1188 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP) ||
1189 (usecase->devices & AUDIO_DEVICE_OUT_ALL_SCO)) &&
1190 ((force_restart_session) ||
1191 (platform_check_backends_match(snd_device, usecase->out_snd_device)))) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301192 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
1193 __func__, use_case_table[usecase->id],
1194 platform_get_snd_device_name(usecase->out_snd_device));
1195 disable_audio_route(adev, usecase);
1196 switch_device[usecase->id] = true;
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301197 /* Enable existing usecase on derived playback device */
1198 derive_snd_device[usecase->id] = uc_derive_snd_device;
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301199 num_uc_to_switch++;
Ashish Jain6a65b352017-03-21 17:24:40 +05301200 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001201 }
1202 }
1203
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301204 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
1205 num_uc_to_switch);
1206
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001207 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001208 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001209
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301210 /* Make sure the previous devices to be disabled first and then enable the
1211 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001212 list_for_each(node, &adev->usecase_list) {
1213 usecase = node_to_item(node, struct audio_usecase, list);
1214 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001215 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001216 }
1217 }
1218
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001219 list_for_each(node, &adev->usecase_list) {
1220 usecase = node_to_item(node, struct audio_usecase, list);
1221 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301222 enable_snd_device(adev, derive_snd_device[usecase->id]);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001223 }
1224 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001225
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001226 /* Re-route all the usecases on the shared backend other than the
1227 specified usecase to new snd devices */
1228 list_for_each(node, &adev->usecase_list) {
1229 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301230 /* Update the out_snd_device only before enabling the audio route */
1231 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301232 usecase->out_snd_device = derive_snd_device[usecase->id];
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301233 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301234 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301235 use_case_table[usecase->id],
1236 platform_get_snd_device_name(usecase->out_snd_device));
kunleiz5cd52b82016-11-07 17:22:52 +08001237 /* Update voc calibration before enabling VoIP route */
1238 if (usecase->type == VOIP_CALL)
1239 status = platform_switch_voice_call_device_post(adev->platform,
1240 usecase->out_snd_device,
kunleizab514ca2017-01-09 14:59:50 +08001241 platform_get_input_snd_device(adev->platform, uc_info->devices));
Avinash Vaish71a8b972014-07-24 15:36:33 +05301242 enable_audio_route(adev, usecase);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301243 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001244 }
1245 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001246 }
1247}
1248
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301249static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001250 struct audio_usecase *uc_info,
1251 snd_device_t snd_device)
1252{
1253 struct listnode *node;
1254 struct audio_usecase *usecase;
1255 bool switch_device[AUDIO_USECASE_MAX];
1256 int i, num_uc_to_switch = 0;
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301257 int backend_check_cond = AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND;
kunleiz5cd52b82016-11-07 17:22:52 +08001258 int status = 0;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001259
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301260 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1261 snd_device);
1262 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301263
1264 /*
1265 * Make sure out devices is checked against out codec backend device and
1266 * also in devices against in codec backend. Checking out device against in
1267 * codec backend or vice versa causes issues.
1268 */
1269 if (uc_info->type == PCM_CAPTURE)
1270 backend_check_cond = AUDIO_DEVICE_IN_ALL_CODEC_BACKEND;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001271 /*
1272 * This function is to make sure that all the active capture usecases
1273 * are always routed to the same input sound device.
1274 * For example, if audio-record and voice-call usecases are currently
1275 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1276 * is received for voice call then we have to make sure that audio-record
1277 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1278 * because of the limitation that two devices cannot be enabled
1279 * at the same time if they share the same backend.
1280 */
1281 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1282 switch_device[i] = false;
1283
1284 list_for_each(node, &adev->usecase_list) {
1285 usecase = node_to_item(node, struct audio_usecase, list);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301286 /*
1287 * TODO: Enhance below condition to handle BT sco/USB multi recording
1288 */
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001289 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001290 usecase != uc_info &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301291 (usecase->in_snd_device != snd_device || force_routing) &&
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301292 ((uc_info->devices & backend_check_cond) &&
Karthik Reddy Katta0d471762015-08-20 13:36:07 +05301293 (((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND) ||
Satya Krishna Pindiproli458b5a72017-03-13 15:14:24 +05301294 (usecase->type == VOIP_CALL))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07001295 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001296 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1297 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001298 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001299 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001300 switch_device[usecase->id] = true;
1301 num_uc_to_switch++;
1302 }
1303 }
1304
1305 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001306 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001307
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301308 /* Make sure the previous devices to be disabled first and then enable the
1309 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001310 list_for_each(node, &adev->usecase_list) {
1311 usecase = node_to_item(node, struct audio_usecase, list);
1312 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001313 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001314 }
1315 }
1316
1317 list_for_each(node, &adev->usecase_list) {
1318 usecase = node_to_item(node, struct audio_usecase, list);
1319 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001320 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001321 }
1322 }
1323
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001324 /* Re-route all the usecases on the shared backend other than the
1325 specified usecase to new snd devices */
1326 list_for_each(node, &adev->usecase_list) {
1327 usecase = node_to_item(node, struct audio_usecase, list);
1328 /* Update the in_snd_device only before enabling the audio route */
1329 if (switch_device[usecase->id] ) {
1330 usecase->in_snd_device = snd_device;
kunleiz5cd52b82016-11-07 17:22:52 +08001331 if (usecase->type != VOICE_CALL) {
1332 /* Update voc calibration before enabling VoIP route */
1333 if (usecase->type == VOIP_CALL)
1334 status = platform_switch_voice_call_device_post(adev->platform,
Zhou Song557e7282017-05-05 17:18:18 +08001335 platform_get_output_snd_device(adev->platform, uc_info->stream.out),
kunleiz5cd52b82016-11-07 17:22:52 +08001336 usecase->in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301337 enable_audio_route(adev, usecase);
kunleiz5cd52b82016-11-07 17:22:52 +08001338 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001339 }
1340 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001341 }
1342}
1343
Mingming Yin3a941d42016-02-17 18:08:05 -08001344static void reset_hdmi_sink_caps(struct stream_out *out) {
1345 int i = 0;
1346
1347 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
1348 out->supported_channel_masks[i] = 0;
1349 }
1350 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
1351 out->supported_formats[i] = 0;
1352 }
1353 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
1354 out->supported_sample_rates[i] = 0;
1355 }
1356}
1357
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001358/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08001359static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001360{
Mingming Yin3a941d42016-02-17 18:08:05 -08001361 int ret = 0, i = 0, j = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001362 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001363
Mingming Yin3a941d42016-02-17 18:08:05 -08001364 reset_hdmi_sink_caps(out);
1365
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001366 /* Cache ext disp type */
Garmond Leung37850ab2016-10-06 11:42:18 -07001367 if (platform_get_ext_disp_type(adev->platform) <= 0) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001368 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07001369 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001370 }
1371
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001372 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001373 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08001374 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001375 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08001376 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
1377 case 6:
1378 ALOGV("%s: HDMI supports 5.1 channels", __func__);
1379 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
1380 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
1381 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
1382 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
1383 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001384 break;
1385 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08001386 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001387 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001388 break;
1389 }
Mingming Yin3a941d42016-02-17 18:08:05 -08001390
1391 // check channel format caps
1392 i = 0;
1393 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_AC3)) {
1394 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
1395 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
1396 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
1397 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
1398 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
1399 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
1400 }
1401
Ben Romberger1aaaf862017-04-06 17:49:46 -07001402 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DOLBY_TRUEHD)) {
1403 ALOGV(":%s HDMI supports TRUE HD format", __func__);
1404 out->supported_formats[i++] = AUDIO_FORMAT_DOLBY_TRUEHD;
1405 }
1406
Mingming Yin3a941d42016-02-17 18:08:05 -08001407 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS)) {
1408 ALOGV(":%s HDMI supports DTS format", __func__);
1409 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
1410 }
1411
1412 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS_HD)) {
1413 ALOGV(":%s HDMI supports DTS HD format", __func__);
1414 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
1415 }
1416
Naresh Tanniru928f0862017-04-07 16:44:23 -07001417 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_IEC61937)) {
1418 ALOGV(":%s HDMI supports IEC61937 format", __func__);
1419 out->supported_formats[i++] = AUDIO_FORMAT_IEC61937;
1420 }
1421
Mingming Yin3a941d42016-02-17 18:08:05 -08001422
1423 // check sample rate caps
1424 i = 0;
1425 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
1426 if (platform_is_edid_supported_sample_rate(out->dev->platform, out_hdmi_sample_rates[j])) {
1427 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
1428 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
1429 }
1430 }
1431
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001432 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001433}
1434
Alexy Josephb1379942016-01-29 15:49:38 -08001435audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001436 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001437{
1438 struct audio_usecase *usecase;
1439 struct listnode *node;
1440
1441 list_for_each(node, &adev->usecase_list) {
1442 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001443 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001444 ALOGV("%s: usecase id %d", __func__, usecase->id);
1445 return usecase->id;
1446 }
1447 }
1448 return USECASE_INVALID;
1449}
1450
Alexy Josephb1379942016-01-29 15:49:38 -08001451struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001452 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001453{
1454 struct audio_usecase *usecase;
1455 struct listnode *node;
1456
1457 list_for_each(node, &adev->usecase_list) {
1458 usecase = node_to_item(node, struct audio_usecase, list);
1459 if (usecase->id == uc_id)
1460 return usecase;
1461 }
1462 return NULL;
1463}
1464
Dhananjay Kumard4833242016-10-06 22:09:12 +05301465struct stream_in *get_next_active_input(const struct audio_device *adev)
1466{
1467 struct audio_usecase *usecase;
1468 struct listnode *node;
1469
1470 list_for_each_reverse(node, &adev->usecase_list) {
1471 usecase = node_to_item(node, struct audio_usecase, list);
1472 if (usecase->type == PCM_CAPTURE)
1473 return usecase->stream.in;
1474 }
1475 return NULL;
1476}
1477
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301478/*
1479 * is a true native playback active
1480 */
1481bool audio_is_true_native_stream_active(struct audio_device *adev)
1482{
1483 bool active = false;
1484 int i = 0;
1485 struct listnode *node;
1486
1487 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
1488 ALOGV("%s:napb: not in true mode or non hdphones device",
1489 __func__);
1490 active = false;
1491 goto exit;
1492 }
1493
1494 list_for_each(node, &adev->usecase_list) {
1495 struct audio_usecase *uc;
1496 uc = node_to_item(node, struct audio_usecase, list);
1497 struct stream_out *curr_out =
1498 (struct stream_out*) uc->stream.out;
1499
1500 if (curr_out && PCM_PLAYBACK == uc->type) {
1501 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
1502 "(%d) device %s", __func__, i++, use_case_table[uc->id],
1503 uc->id, curr_out->sample_rate,
1504 curr_out->bit_width,
1505 platform_get_snd_device_name(uc->out_snd_device));
1506
1507 if (is_offload_usecase(uc->id) &&
1508 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
1509 active = true;
1510 ALOGD("%s:napb:native stream detected", __func__);
1511 }
1512 }
1513 }
1514exit:
1515 return active;
1516}
1517
Xiaojun Sang785b5da2017-08-03 15:52:29 +08001518uint32_t adev_get_dsp_bit_width_enforce_mode()
1519{
1520 if (adev == NULL) {
1521 ALOGE("%s: adev is null. Disable DSP bit width enforce mode.\n", __func__);
1522 return 0;
1523 }
1524 return adev->dsp_bit_width_enforce_mode;
1525}
1526
1527static uint32_t adev_init_dsp_bit_width_enforce_mode(struct mixer *mixer)
1528{
1529 char value[PROPERTY_VALUE_MAX];
1530 int trial;
1531 uint32_t dsp_bit_width_enforce_mode = 0;
1532
1533 if (!mixer) {
1534 ALOGE("%s: adev mixer is null. cannot update DSP bitwidth.\n",
1535 __func__);
1536 return 0;
1537 }
1538
1539 if (property_get("persist.vendor.audio_hal.dsp_bit_width_enforce_mode",
1540 value, NULL) > 0) {
1541 trial = atoi(value);
1542 switch (trial) {
1543 case 16:
1544 dsp_bit_width_enforce_mode = 16;
1545 break;
1546 case 24:
1547 dsp_bit_width_enforce_mode = 24;
1548 break;
1549 case 32:
1550 dsp_bit_width_enforce_mode = 32;
1551 break;
1552 default:
1553 dsp_bit_width_enforce_mode = 0;
1554 ALOGD("%s Dynamic DSP bitwidth config is disabled.", __func__);
1555 break;
1556 }
1557 }
1558
1559 return dsp_bit_width_enforce_mode;
1560}
1561
1562static void audio_enable_asm_bit_width_enforce_mode(struct mixer *mixer,
1563 uint32_t enforce_mode,
1564 bool enable)
1565{
1566 struct mixer_ctl *ctl = NULL;
1567 const char *mixer_ctl_name = "ASM Bit Width";
1568 uint32_t asm_bit_width_mode = 0;
1569
1570 if (enforce_mode == 0) {
1571 ALOGD("%s: DSP bitwidth feature is disabled.", __func__);
1572 return;
1573 }
1574
1575 ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
1576 if (!ctl) {
1577 ALOGE("%s: Could not get ctl for mixer cmd - %s",
1578 __func__, mixer_ctl_name);
1579 return;
1580 }
1581
1582 if (enable)
1583 asm_bit_width_mode = enforce_mode;
1584 else
1585 asm_bit_width_mode = 0;
1586
1587 ALOGV("%s DSP bit width feature status is %d width=%d",
1588 __func__, enable, asm_bit_width_mode);
1589 if (mixer_ctl_set_value(ctl, 0, asm_bit_width_mode) < 0)
1590 ALOGE("%s: Could not set ASM biwidth %d", __func__,
1591 asm_bit_width_mode);
1592
1593 return;
1594}
1595
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301596/*
1597 * if native DSD playback active
1598 */
1599bool audio_is_dsd_native_stream_active(struct audio_device *adev)
1600{
1601 bool active = false;
1602 struct listnode *node = NULL;
1603 struct audio_usecase *uc = NULL;
1604 struct stream_out *curr_out = NULL;
1605
1606 list_for_each(node, &adev->usecase_list) {
1607 uc = node_to_item(node, struct audio_usecase, list);
1608 curr_out = (struct stream_out*) uc->stream.out;
1609
1610 if (curr_out && PCM_PLAYBACK == uc->type &&
1611 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
1612 active = true;
1613 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05301614 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301615 }
1616 }
1617 return active;
1618}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301619
1620static bool force_device_switch(struct audio_usecase *usecase)
1621{
1622 bool ret = false;
1623 bool is_it_true_mode = false;
1624
1625 if (is_offload_usecase(usecase->id) &&
1626 (usecase->stream.out) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08001627 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
1628 (usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADSET ||
1629 usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADPHONE)) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301630 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
1631 if ((is_it_true_mode && !adev->native_playback_enabled) ||
1632 (!is_it_true_mode && adev->native_playback_enabled)){
1633 ret = true;
1634 ALOGD("napb: time to toggle native mode");
1635 }
1636 }
1637
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301638 // Force all a2dp output devices to reconfigure for proper AFE encode format
Ashish Jainc597d102016-12-12 10:31:34 +05301639 //Also handle a case where in earlier a2dp start failed as A2DP stream was
1640 //in suspended state, hence try to trigger a retry when we again get a routing request.
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301641 if((usecase->stream.out) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07001642 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Ashish Jainc597d102016-12-12 10:31:34 +05301643 audio_extn_a2dp_is_force_device_switch()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301644 ALOGD("Force a2dp device switch to update new encoder config");
1645 ret = true;
1646 }
1647
Manish Dewangan671a4202017-08-18 17:30:46 +05301648 if (usecase->stream.out->stream_config_changed) {
1649 ALOGD("Force stream_config_changed to update iec61937 transmission config");
1650 return true;
1651 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301652 return ret;
1653}
1654
Ashish Jain1b9b30c2017-05-18 20:57:40 +05301655bool is_btsco_device(snd_device_t out_snd_device, snd_device_t in_snd_device)
1656{
1657 bool ret=false;
1658 if ((out_snd_device == SND_DEVICE_OUT_BT_SCO ||
1659 out_snd_device == SND_DEVICE_OUT_BT_SCO_WB) ||
1660 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB_NREC ||
1661 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB ||
1662 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_NREC ||
1663 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC)
1664 ret = true;
1665
1666 return ret;
1667}
1668
1669bool is_a2dp_device(snd_device_t out_snd_device)
1670{
1671 bool ret=false;
1672 if (out_snd_device == SND_DEVICE_OUT_BT_A2DP)
1673 ret = true;
1674
1675 return ret;
1676}
1677
1678bool is_bt_soc_on(struct audio_device *adev)
1679{
1680 struct mixer_ctl *ctl;
1681 char *mixer_ctl_name = "BT SOC status";
1682 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
1683 bool bt_soc_status = true;
1684 if (!ctl) {
1685 ALOGE("%s: Could not get ctl for mixer cmd - %s",
1686 __func__, mixer_ctl_name);
1687 /*This is to ensure we dont break targets which dont have the kernel change*/
1688 return true;
1689 }
1690 bt_soc_status = mixer_ctl_get_value(ctl, 0);
1691 ALOGD("BT SOC status: %d",bt_soc_status);
1692 return bt_soc_status;
1693}
1694
1695int out_standby_l(struct audio_stream *stream);
1696
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001697int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001698{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001699 snd_device_t out_snd_device = SND_DEVICE_NONE;
1700 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001701 struct audio_usecase *usecase = NULL;
1702 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001703 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001704 struct audio_usecase *hfp_usecase = NULL;
Siddartha Shaik44dd7702017-06-14 12:13:25 +05301705 struct stream_out stream_out;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001706 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001707 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001708
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301709 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
1710
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001711 usecase = get_usecase_from_list(adev, uc_id);
1712 if (usecase == NULL) {
1713 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1714 return -EINVAL;
1715 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001716
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001717 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08001718 (usecase->type == VOIP_CALL) ||
1719 (usecase->type == PCM_HFP_CALL)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301720 if(usecase->stream.out == NULL) {
1721 ALOGE("%s: stream.out is NULL", __func__);
1722 return -EINVAL;
1723 }
Eric Laurentb23d5282013-05-14 15:27:20 -07001724 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001725 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -07001726 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001727 usecase->devices = usecase->stream.out->devices;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301728 } else if (usecase->type == TRANSCODE_LOOPBACK ) {
1729 if (usecase->stream.inout == NULL) {
1730 ALOGE("%s: stream.inout is NULL", __func__);
1731 return -EINVAL;
1732 }
Siddartha Shaik44dd7702017-06-14 12:13:25 +05301733 stream_out.devices = usecase->stream.inout->out_config.devices;
1734 stream_out.sample_rate = usecase->stream.inout->out_config.sample_rate;
1735 stream_out.format = usecase->stream.inout->out_config.format;
1736 stream_out.channel_mask = usecase->stream.inout->out_config.channel_mask;
1737 out_snd_device = platform_get_output_snd_device(adev->platform,
1738 &stream_out);
1739 in_snd_device = platform_get_input_snd_device(adev->platform, AUDIO_DEVICE_NONE);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301740 usecase->devices = (out_snd_device | in_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001741 } else {
1742 /*
1743 * If the voice call is active, use the sound devices of voice call usecase
1744 * so that it would not result any device switch. All the usecases will
1745 * be switched to new device when select_devices() is called for voice call
1746 * usecase. This is to avoid switching devices for voice call when
1747 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07001748 * choose voice call device only if the use case device is
1749 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001750 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08001751 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001752 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001753 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Alexy Josephdbcddf22016-05-16 17:54:09 -07001754 if ((vc_usecase) && (((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1755 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) ||
Preetam Singh Ranawat097cb1f2016-07-19 13:49:04 +05301756 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1757 (usecase->devices & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) ||
Alexy Josephdbcddf22016-05-16 17:54:09 -07001758 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001759 in_snd_device = vc_usecase->in_snd_device;
1760 out_snd_device = vc_usecase->out_snd_device;
1761 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001762 } else if (voice_extn_compress_voip_is_active(adev)) {
yidongh02ef86f2017-04-21 15:36:04 +08001763 bool out_snd_device_backend_match = true;
yidongh47785a82017-05-08 19:29:29 +08001764 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
yidongh6261d8e2017-05-15 17:04:02 +08001765 if ((voip_usecase != NULL) &&
1766 (usecase->type == PCM_PLAYBACK) &&
1767 (usecase->stream.out != NULL)) {
yidongh02ef86f2017-04-21 15:36:04 +08001768 out_snd_device_backend_match = platform_check_backends_match(
1769 voip_usecase->out_snd_device,
1770 platform_get_output_snd_device(
1771 adev->platform,
1772 usecase->stream.out));
1773 }
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001774 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Zhou Song0154bf12016-08-04 10:48:16 +08001775 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1776 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
yidongh02ef86f2017-04-21 15:36:04 +08001777 out_snd_device_backend_match &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001778 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001779 in_snd_device = voip_usecase->in_snd_device;
1780 out_snd_device = voip_usecase->out_snd_device;
1781 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001782 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001783 hfp_ucid = audio_extn_hfp_get_usecase();
1784 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001785 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001786 in_snd_device = hfp_usecase->in_snd_device;
1787 out_snd_device = hfp_usecase->out_snd_device;
1788 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001789 }
1790 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301791 if (usecase->stream.out == NULL) {
1792 ALOGE("%s: stream.out is NULL", __func__);
1793 return -EINVAL;
1794 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001795 usecase->devices = usecase->stream.out->devices;
1796 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001797 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001798 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001799 usecase->stream.out);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001800 if (usecase->stream.out == adev->primary_output &&
1801 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -08001802 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001803 select_devices(adev, adev->active_input->usecase);
1804 }
1805 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001806 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301807 if (usecase->stream.in == NULL) {
1808 ALOGE("%s: stream.in is NULL", __func__);
1809 return -EINVAL;
1810 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001811 usecase->devices = usecase->stream.in->device;
1812 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001813 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001814 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08001815 if (adev->active_input &&
1816 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +05301817 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
1818 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
1819 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001820 out_device = adev->primary_output->devices;
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07001821 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001822 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1823 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001824 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001825 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001826 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001827 }
1828 }
1829
1830 if (out_snd_device == usecase->out_snd_device &&
1831 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301832
1833 if (!force_device_switch(usecase))
1834 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001835 }
1836
Ashish Jain1b9b30c2017-05-18 20:57:40 +05301837 if ((is_btsco_device(out_snd_device,in_snd_device) && !adev->bt_sco_on) ||
1838 (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_is_ready())) {
1839 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
1840 return 0;
1841 }
1842
sangwoobc677242013-08-08 16:53:43 +09001843 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -07001844 out_snd_device, platform_get_snd_device_name(out_snd_device),
1845 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001846
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001847 /*
1848 * Limitation: While in call, to do a device switch we need to disable
1849 * and enable both RX and TX devices though one of them is same as current
1850 * device.
1851 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001852 if ((usecase->type == VOICE_CALL) &&
1853 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1854 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001855 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07001856 }
1857
1858 if (((usecase->type == VOICE_CALL) ||
1859 (usecase->type == VOIP_CALL)) &&
1860 (usecase->out_snd_device != SND_DEVICE_NONE)) {
1861 /* Disable sidetone only if voice/voip call already exists */
1862 if (voice_is_call_state_active(adev) ||
1863 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07001864 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07001865
1866 /* Disable aanc only if voice call exists */
1867 if (voice_is_call_state_active(adev))
1868 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001869 }
1870
Zhou Songc66eb7e2017-08-08 18:29:07 +08001871 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP) &&
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05301872 (!audio_extn_a2dp_is_ready())) {
1873 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
Zhou Songc66eb7e2017-08-08 18:29:07 +08001874 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05301875 }
1876
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001877 /* Disable current sound devices */
1878 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001879 disable_audio_route(adev, usecase);
1880 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001881 }
1882
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001883 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001884 disable_audio_route(adev, usecase);
1885 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001886 }
1887
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001888 /* Applicable only on the targets that has external modem.
1889 * New device information should be sent to modem before enabling
1890 * the devices to reduce in-call device switch time.
1891 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001892 if ((usecase->type == VOICE_CALL) &&
1893 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1894 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001895 status = platform_switch_voice_call_enable_device_config(adev->platform,
1896 out_snd_device,
1897 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001898 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001899
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001900 /* Enable new sound devices */
1901 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001902 check_usecases_codec_backend(adev, usecase, out_snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301903 if (platform_check_codec_asrc_support(adev->platform))
1904 check_and_set_asrc_mode(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001905 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001906 }
1907
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001908 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301909 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001910 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001911 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001912
Avinash Vaish71a8b972014-07-24 15:36:33 +05301913 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001914 status = platform_switch_voice_call_device_post(adev->platform,
1915 out_snd_device,
1916 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301917 enable_audio_route_for_voice_usecases(adev, usecase);
1918 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001919
sangwoo170731f2013-06-08 15:36:36 +09001920 usecase->in_snd_device = in_snd_device;
1921 usecase->out_snd_device = out_snd_device;
1922
Dhananjay Kumard6d32152016-10-13 16:11:03 +05301923 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
1924 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301925 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001926 if ((24 == usecase->stream.out->bit_width) &&
1927 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
1928 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
1929 } else if ((out_snd_device == SND_DEVICE_OUT_HDMI ||
1930 out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
1931 out_snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
1932 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
1933 /*
1934 * To best utlize DSP, check if the stream sample rate is supported/multiple of
1935 * configured device sample rate, if not update the COPP rate to be equal to the
1936 * device sample rate, else open COPP at stream sample rate
1937 */
1938 platform_check_and_update_copp_sample_rate(adev->platform, out_snd_device,
1939 usecase->stream.out->sample_rate,
1940 &usecase->stream.out->app_type_cfg.sample_rate);
Ashish Jain4826f6c2017-02-06 13:33:20 +05301941 } else if (((out_snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
1942 !audio_is_true_native_stream_active(adev)) &&
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001943 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
1944 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
1945 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
1946 }
1947
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001948 /* Notify device change info to effect clients registered */
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001949 pthread_mutex_unlock(&adev->lock);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001950 audio_extn_gef_notify_device_config(
1951 usecase->stream.out->devices,
1952 usecase->stream.out->channel_mask,
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001953 usecase->stream.out->app_type_cfg.sample_rate,
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001954 platform_get_snd_device_acdb_id(usecase->out_snd_device));
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001955 pthread_mutex_lock(&adev->lock);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301956 }
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001957 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001958
Vidyakumar Athota493f2892016-08-14 11:56:55 -07001959 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07001960 /* Enable aanc only if voice call exists */
1961 if (voice_is_call_state_active(adev))
1962 voice_check_and_update_aanc_path(adev, out_snd_device, true);
1963
Vidyakumar Athota493f2892016-08-14 11:56:55 -07001964 /* Enable sidetone only if other voice/voip call already exists */
1965 if (voice_is_call_state_active(adev) ||
1966 voice_extn_compress_voip_is_started(adev))
1967 voice_set_sidetone(adev, out_snd_device, true);
1968 }
1969
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001970 /* Applicable only on the targets that has external modem.
1971 * Enable device command should be sent to modem only after
1972 * enabling voice call mixer controls
1973 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07001974 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001975 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1976 out_snd_device,
1977 in_snd_device);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05301978
1979 if (is_btsco_device(out_snd_device, in_snd_device) || is_a2dp_device(out_snd_device)) {
1980
1981 if (usecase->type == VOIP_CALL) {
1982 if (adev->active_input != NULL &&
1983 !adev->active_input->standby) {
1984 if (is_bt_soc_on(adev) == false){
1985 ALOGD("BT SCO MIC disconnected while in connection");
1986 if (adev->active_input->pcm != NULL)
1987 pcm_stop(adev->active_input->pcm);
1988 }
1989 }
1990 if ((usecase->stream.out != NULL) && (usecase->stream.out != adev->primary_output)
1991 && usecase->stream.out->started) {
1992 if (is_bt_soc_on(adev) == false) {
1993 ALOGD("BT SCO/A2DP disconnected while in connection");
1994 out_standby_l(&usecase->stream.out->stream.common);
1995 }
1996 }
1997 } else if ((usecase->stream.out != NULL) &&
1998 !(usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
1999 usecase->stream.out->started) {
2000 if (is_bt_soc_on(adev) == false) {
2001 ALOGD("BT SCO/A2dp disconnected while in connection");
2002 out_standby_l(&usecase->stream.out->stream.common);
2003 }
2004 }
2005 }
2006
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302007 ALOGD("%s: done",__func__);
2008
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002009 return status;
2010}
2011
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002012static int stop_input_stream(struct stream_in *in)
2013{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302014 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002015 struct audio_usecase *uc_info;
2016 struct audio_device *adev = in->dev;
2017
Eric Laurent994a6932013-07-17 11:51:42 -07002018 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002019 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002020 uc_info = get_usecase_from_list(adev, in->usecase);
2021 if (uc_info == NULL) {
2022 ALOGE("%s: Could not find the usecase (%d) in the list",
2023 __func__, in->usecase);
2024 return -EINVAL;
2025 }
2026
Vidyakumar Athota2850d532013-11-19 16:02:12 -08002027 /* Close in-call recording streams */
2028 voice_check_and_stop_incall_rec_usecase(adev, in);
2029
Eric Laurent150dbfe2013-02-27 14:31:02 -08002030 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002031 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002032
2033 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002034 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002035
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002036 list_remove(&uc_info->list);
2037 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002038
Aalique Grahame2e9b2e42016-12-07 12:43:48 -08002039 adev->active_input = get_next_active_input(adev);
2040
Eric Laurent994a6932013-07-17 11:51:42 -07002041 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002042 return ret;
2043}
2044
2045int start_input_stream(struct stream_in *in)
2046{
2047 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08002048 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002049 struct audio_usecase *uc_info;
2050 struct audio_device *adev = in->dev;
2051
Mingming Yin2664a5b2015-09-03 10:53:11 -07002052 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
2053 if (get_usecase_from_list(adev, usecase) == NULL)
2054 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302055 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
2056 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002057
Naresh Tanniru80659832014-06-04 18:17:56 +05302058
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302059 if (CARD_STATUS_OFFLINE == in->card_status||
2060 CARD_STATUS_OFFLINE == adev->card_status) {
2061 ALOGW("in->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302062 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302063 goto error_config;
2064 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05302065
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302066 if (audio_is_bluetooth_sco_device(in->device)) {
2067 if (!adev->bt_sco_on) {
2068 ALOGE("%s: SCO profile is not ready, return error", __func__);
2069 ret = -EIO;
2070 goto error_config;
2071 }
2072 }
2073
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002074 /* Check if source matches incall recording usecase criteria */
2075 ret = voice_check_and_set_incall_rec_usecase(adev, in);
2076 if (ret)
2077 goto error_config;
2078 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07002079 ALOGV("%s: usecase(%d)", __func__, in->usecase);
2080
2081 if (get_usecase_from_list(adev, in->usecase) != NULL) {
2082 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
2083 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08002084 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07002085 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002086
Eric Laurentb23d5282013-05-14 15:27:20 -07002087 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002088 if (in->pcm_device_id < 0) {
2089 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
2090 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08002091 ret = -EINVAL;
2092 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002093 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002094
2095 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002096 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002097
2098 if (!uc_info) {
2099 ret = -ENOMEM;
2100 goto error_config;
2101 }
2102
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002103 uc_info->id = in->usecase;
2104 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002105 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002106 uc_info->devices = in->device;
2107 uc_info->in_snd_device = SND_DEVICE_NONE;
2108 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002109
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002110 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302111 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2112 adev->perf_lock_opts,
2113 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002114 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002115
Haynes Mathew George16081042017-05-31 17:16:49 -07002116 if (audio_extn_cin_attached_usecase(in->usecase)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05302117 ret = audio_extn_cin_start_input_stream(in);
2118 if (ret)
2119 goto error_open;
2120 else
2121 goto done_open;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002122 }
2123
Haynes Mathew George16081042017-05-31 17:16:49 -07002124 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002125 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07002126 ALOGE("%s: pcm stream not ready", __func__);
2127 goto error_open;
2128 }
2129 ret = pcm_start(in->pcm);
2130 if (ret < 0) {
2131 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
2132 goto error_open;
2133 }
2134 } else {
2135 unsigned int flags = PCM_IN | PCM_MONOTONIC;
2136 unsigned int pcm_open_retry_count = 0;
2137
2138 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
2139 flags |= PCM_MMAP | PCM_NOIRQ;
2140 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
2141 } else if (in->realtime) {
2142 flags |= PCM_MMAP | PCM_NOIRQ;
2143 }
2144
2145 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
2146 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
2147
2148 while (1) {
2149 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
2150 flags, &in->config);
2151 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
2152 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
2153 if (in->pcm != NULL) {
2154 pcm_close(in->pcm);
2155 in->pcm = NULL;
2156 }
2157 if (pcm_open_retry_count-- == 0) {
2158 ret = -EIO;
2159 goto error_open;
2160 }
2161 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2162 continue;
2163 }
2164 break;
2165 }
2166
2167 ALOGV("%s: pcm_prepare", __func__);
2168 ret = pcm_prepare(in->pcm);
2169 if (ret < 0) {
2170 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2171 pcm_close(in->pcm);
2172 in->pcm = NULL;
2173 goto error_open;
2174 }
2175 register_in_stream(in);
2176 if (in->realtime) {
2177 ret = pcm_start(in->pcm);
2178 if (ret < 0) {
2179 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002180 pcm_close(in->pcm);
2181 in->pcm = NULL;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002182 goto error_open;
2183 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002184 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002185 }
2186
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05302187done_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302188 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002189 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002190
Eric Laurentc8400632013-02-14 19:04:54 -08002191 return ret;
2192
2193error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302194 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002195 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -08002196error_config:
Dhananjay Kumard4833242016-10-06 22:09:12 +05302197 adev->active_input = get_next_active_input(adev);
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05302198 /*
2199 * sleep 50ms to allow sufficient time for kernel
2200 * drivers to recover incases like SSR.
2201 */
2202 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002203 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08002204
2205 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002206}
2207
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002208void lock_input_stream(struct stream_in *in)
2209{
2210 pthread_mutex_lock(&in->pre_lock);
2211 pthread_mutex_lock(&in->lock);
2212 pthread_mutex_unlock(&in->pre_lock);
2213}
2214
2215void lock_output_stream(struct stream_out *out)
2216{
2217 pthread_mutex_lock(&out->pre_lock);
2218 pthread_mutex_lock(&out->lock);
2219 pthread_mutex_unlock(&out->pre_lock);
2220}
2221
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002222/* must be called with out->lock locked */
2223static int send_offload_cmd_l(struct stream_out* out, int command)
2224{
2225 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
2226
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002227 if (!cmd) {
2228 ALOGE("failed to allocate mem for command 0x%x", command);
2229 return -ENOMEM;
2230 }
2231
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002232 ALOGVV("%s %d", __func__, command);
2233
2234 cmd->cmd = command;
2235 list_add_tail(&out->offload_cmd_list, &cmd->node);
2236 pthread_cond_signal(&out->offload_cond);
2237 return 0;
2238}
2239
2240/* must be called iwth out->lock locked */
2241static void stop_compressed_output_l(struct stream_out *out)
2242{
2243 out->offload_state = OFFLOAD_STATE_IDLE;
2244 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002245 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002246 if (out->compr != NULL) {
2247 compress_stop(out->compr);
2248 while (out->offload_thread_blocked) {
2249 pthread_cond_wait(&out->cond, &out->lock);
2250 }
2251 }
2252}
2253
Varun Balaraje49253e2017-07-06 19:48:56 +05302254bool is_interactive_usecase(audio_usecase_t uc_id)
2255{
2256 unsigned int i;
2257 for (i = 0; i < sizeof(interactive_usecases)/sizeof(interactive_usecases[0]); i++) {
2258 if (uc_id == interactive_usecases[i])
2259 return true;
2260 }
2261 return false;
2262}
2263
2264static audio_usecase_t get_interactive_usecase(struct audio_device *adev)
2265{
2266 audio_usecase_t ret_uc = USECASE_INVALID;
2267 unsigned int intract_uc_index;
2268 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
2269
2270 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
2271 for (intract_uc_index = 0; intract_uc_index < num_usecase; intract_uc_index++) {
2272 if (!(adev->interactive_usecase_state & (0x1 << intract_uc_index))) {
2273 adev->interactive_usecase_state |= 0x1 << intract_uc_index;
2274 ret_uc = interactive_usecases[intract_uc_index];
2275 break;
2276 }
2277 }
2278
2279 ALOGV("%s: Interactive usecase is %d", __func__, ret_uc);
2280 return ret_uc;
2281}
2282
2283static void free_interactive_usecase(struct audio_device *adev,
2284 audio_usecase_t uc_id)
2285{
2286 unsigned int interact_uc_index;
2287 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
2288
2289 for (interact_uc_index = 0; interact_uc_index < num_usecase; interact_uc_index++) {
2290 if (interactive_usecases[interact_uc_index] == uc_id) {
2291 adev->interactive_usecase_state &= ~(0x1 << interact_uc_index);
2292 break;
2293 }
2294 }
2295 ALOGV("%s: free Interactive usecase %d", __func__, uc_id);
2296}
2297
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002298bool is_offload_usecase(audio_usecase_t uc_id)
2299{
2300 unsigned int i;
2301 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
2302 if (uc_id == offload_usecases[i])
2303 return true;
2304 }
2305 return false;
2306}
2307
Dhananjay Kumarac341582017-02-23 23:42:25 +05302308static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_compress)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002309{
vivek mehta446c3962015-09-14 10:57:35 -07002310 audio_usecase_t ret_uc = USECASE_INVALID;
2311 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08002312 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07002313 if (!adev->multi_offload_enable) {
Dhananjay Kumarac341582017-02-23 23:42:25 +05302314 if (!is_compress)
vivek mehta446c3962015-09-14 10:57:35 -07002315 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
2316 else
2317 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002318
vivek mehta446c3962015-09-14 10:57:35 -07002319 pthread_mutex_lock(&adev->lock);
2320 if (get_usecase_from_list(adev, ret_uc) != NULL)
2321 ret_uc = USECASE_INVALID;
2322 pthread_mutex_unlock(&adev->lock);
2323
2324 return ret_uc;
2325 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002326
2327 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07002328 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
2329 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
2330 adev->offload_usecases_state |= 0x1 << offload_uc_index;
2331 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002332 break;
2333 }
2334 }
vivek mehta446c3962015-09-14 10:57:35 -07002335
2336 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
2337 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002338}
2339
2340static void free_offload_usecase(struct audio_device *adev,
2341 audio_usecase_t uc_id)
2342{
vivek mehta446c3962015-09-14 10:57:35 -07002343 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08002344 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07002345
2346 if (!adev->multi_offload_enable)
2347 return;
2348
2349 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
2350 if (offload_usecases[offload_uc_index] == uc_id) {
2351 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002352 break;
2353 }
2354 }
2355 ALOGV("%s: free offload usecase %d", __func__, uc_id);
2356}
2357
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002358static void *offload_thread_loop(void *context)
2359{
2360 struct stream_out *out = (struct stream_out *) context;
2361 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002362 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002363
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002364 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
2365 set_sched_policy(0, SP_FOREGROUND);
2366 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
2367
2368 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002369 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002370 for (;;) {
2371 struct offload_cmd *cmd = NULL;
2372 stream_callback_event_t event;
2373 bool send_callback = false;
2374
2375 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
2376 __func__, list_empty(&out->offload_cmd_list),
2377 out->offload_state);
2378 if (list_empty(&out->offload_cmd_list)) {
2379 ALOGV("%s SLEEPING", __func__);
2380 pthread_cond_wait(&out->offload_cond, &out->lock);
2381 ALOGV("%s RUNNING", __func__);
2382 continue;
2383 }
2384
2385 item = list_head(&out->offload_cmd_list);
2386 cmd = node_to_item(item, struct offload_cmd, node);
2387 list_remove(item);
2388
2389 ALOGVV("%s STATE %d CMD %d out->compr %p",
2390 __func__, out->offload_state, cmd->cmd, out->compr);
2391
2392 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
2393 free(cmd);
2394 break;
2395 }
2396
2397 if (out->compr == NULL) {
2398 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07002399 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002400 pthread_cond_signal(&out->cond);
2401 continue;
2402 }
2403 out->offload_thread_blocked = true;
2404 pthread_mutex_unlock(&out->lock);
2405 send_callback = false;
2406 switch(cmd->cmd) {
2407 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002408 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002409 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002410 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002411 send_callback = true;
2412 event = STREAM_CBK_EVENT_WRITE_READY;
2413 break;
2414 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002415 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05302416 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002417 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302418 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002419 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302420 if (ret < 0)
2421 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05302422 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302423 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002424 compress_drain(out->compr);
2425 else
2426 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302427 if (ret != -ENETRESET) {
2428 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302429 pthread_mutex_lock(&out->lock);
2430 out->send_new_metadata = 1;
2431 out->send_next_track_params = true;
2432 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302433 event = STREAM_CBK_EVENT_DRAIN_READY;
2434 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
2435 } else
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302436 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002437 break;
2438 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002439 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002440 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002441 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002442 send_callback = true;
2443 event = STREAM_CBK_EVENT_DRAIN_READY;
2444 break;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302445 case OFFLOAD_CMD_ERROR:
2446 ALOGD("copl(%p): sending error callback to AF", out);
2447 send_callback = true;
2448 event = STREAM_CBK_EVENT_ERROR;
2449 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002450 default:
2451 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
2452 break;
2453 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002454 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002455 out->offload_thread_blocked = false;
2456 pthread_cond_signal(&out->cond);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08002457 if (send_callback && out->client_callback) {
2458 ALOGVV("%s: sending client_callback event %d", __func__, event);
2459 out->client_callback(event, NULL, out->client_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07002460 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002461 free(cmd);
2462 }
2463
2464 pthread_cond_signal(&out->cond);
2465 while (!list_empty(&out->offload_cmd_list)) {
2466 item = list_head(&out->offload_cmd_list);
2467 list_remove(item);
2468 free(node_to_item(item, struct offload_cmd, node));
2469 }
2470 pthread_mutex_unlock(&out->lock);
2471
2472 return NULL;
2473}
2474
2475static int create_offload_callback_thread(struct stream_out *out)
2476{
2477 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
2478 list_init(&out->offload_cmd_list);
2479 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
2480 offload_thread_loop, out);
2481 return 0;
2482}
2483
2484static int destroy_offload_callback_thread(struct stream_out *out)
2485{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002486 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002487 stop_compressed_output_l(out);
2488 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
2489
2490 pthread_mutex_unlock(&out->lock);
2491 pthread_join(out->offload_thread, (void **) NULL);
2492 pthread_cond_destroy(&out->offload_cond);
2493
2494 return 0;
2495}
2496
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002497static int stop_output_stream(struct stream_out *out)
2498{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302499 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002500 struct audio_usecase *uc_info;
2501 struct audio_device *adev = out->dev;
2502
Eric Laurent994a6932013-07-17 11:51:42 -07002503 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002504 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002505 uc_info = get_usecase_from_list(adev, out->usecase);
2506 if (uc_info == NULL) {
2507 ALOGE("%s: Could not find the usecase (%d) in the list",
2508 __func__, out->usecase);
2509 return -EINVAL;
2510 }
2511
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002512 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302513 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002514 if (adev->visualizer_stop_output != NULL)
2515 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002516
2517 audio_extn_dts_remove_state_notifier_node(out->usecase);
2518
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002519 if (adev->offload_effects_stop_output != NULL)
2520 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
2521 }
Eric Laurentc4aef752013-09-12 17:45:53 -07002522
Eric Laurent150dbfe2013-02-27 14:31:02 -08002523 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002524 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002525
2526 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002527 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002528
Xiaojun Sang785b5da2017-08-03 15:52:29 +08002529 if (is_offload_usecase(out->usecase)) {
2530 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
2531 adev->dsp_bit_width_enforce_mode,
2532 false);
2533 }
2534
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002535 list_remove(&uc_info->list);
2536 free(uc_info);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302537 out->started = 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002538 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302539 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002540 ALOGV("Disable passthrough , reset mixer to pcm");
2541 /* NO_PASSTHROUGH */
2542 out->compr_config.codec->compr_passthr = 0;
Mingming Yin21854652016-04-13 11:54:02 -07002543 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002544 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
2545 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07002546
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302547 /* Must be called after removing the usecase from list */
2548 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302549 audio_extn_keep_alive_start();
2550
Manish Dewangan21a850a2017-08-14 12:03:55 +05302551 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07002552 ret = audio_extn_ip_hdlr_intf_close(out->ip_hdlr_handle, true, out);
2553 if (ret < 0)
2554 ALOGE("%s: audio_extn_ip_hdlr_intf_close failed %d",__func__, ret);
2555 }
2556
Eric Laurent994a6932013-07-17 11:51:42 -07002557 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002558 return ret;
2559}
2560
2561int start_output_stream(struct stream_out *out)
2562{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002563 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002564 struct audio_usecase *uc_info;
2565 struct audio_device *adev = out->dev;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08002566 char mixer_ctl_name[128];
2567 struct mixer_ctl *ctl = NULL;
2568 char* perf_mode[] = {"ULL", "ULL_PP", "LL"};
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302569 bool a2dp_combo = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002570
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002571 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
2572 ret = -EINVAL;
2573 goto error_config;
2574 }
2575
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302576 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
2577 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
2578 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302579
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302580 if (CARD_STATUS_OFFLINE == out->card_status ||
2581 CARD_STATUS_OFFLINE == adev->card_status) {
2582 ALOGW("out->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302583 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302584 goto error_config;
2585 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05302586
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05302587 if (out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) {
2588 if (!audio_extn_a2dp_is_ready()) {
2589 if (out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302590 a2dp_combo = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05302591 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302592 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
2593 ALOGE("%s: A2DP profile is not ready, return error", __func__);
2594 ret = -EAGAIN;
2595 goto error_config;
2596 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05302597 }
2598 }
2599 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302600 if (out->devices & AUDIO_DEVICE_OUT_ALL_SCO) {
2601 if (!adev->bt_sco_on) {
2602 if (out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
2603 //combo usecase just by pass a2dp
2604 ALOGW("%s: SCO is not connected, route it to speaker", __func__);
2605 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
2606 } else {
2607 ALOGE("%s: SCO profile is not ready, return error", __func__);
2608 ret = -EAGAIN;
2609 goto error_config;
2610 }
2611 }
2612 }
2613
Eric Laurentb23d5282013-05-14 15:27:20 -07002614 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002615 if (out->pcm_device_id < 0) {
2616 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
2617 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002618 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002619 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002620 }
2621
2622 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002623
2624 if (!uc_info) {
2625 ret = -ENOMEM;
2626 goto error_config;
2627 }
2628
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002629 uc_info->id = out->usecase;
2630 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002631 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002632 uc_info->devices = out->devices;
2633 uc_info->in_snd_device = SND_DEVICE_NONE;
2634 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002635 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002636
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302637 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2638 adev->perf_lock_opts,
2639 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302640
2641 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
2642 audio_extn_keep_alive_stop();
2643 if (audio_extn_passthru_is_enabled() &&
2644 audio_extn_passthru_is_passthrough_stream(out)) {
2645 audio_extn_passthru_on_start(out);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302646 }
2647 }
2648
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302649 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
2650 (!audio_extn_a2dp_is_ready())) {
2651 if (!a2dp_combo) {
2652 check_a2dp_restore_l(adev, out, false);
2653 } else {
2654 audio_devices_t dev = out->devices;
2655 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
2656 select_devices(adev, out->usecase);
2657 out->devices = dev;
2658 }
2659 } else {
2660 select_devices(adev, out->usecase);
2661 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002662
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002663 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
2664 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Haynes Mathew George16081042017-05-31 17:16:49 -07002665
2666 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2667 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2668 ALOGE("%s: pcm stream not ready", __func__);
2669 goto error_open;
2670 }
2671 ret = pcm_start(out->pcm);
2672 if (ret < 0) {
2673 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
2674 goto error_open;
2675 }
2676 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002677 unsigned int flags = PCM_OUT;
2678 unsigned int pcm_open_retry_count = 0;
2679 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
2680 flags |= PCM_MMAP | PCM_NOIRQ;
2681 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002682 } else if (out->realtime) {
2683 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002684 } else
2685 flags |= PCM_MONOTONIC;
2686
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08002687 if ((adev->vr_audio_mode_enabled) &&
2688 (out->flags & AUDIO_OUTPUT_FLAG_RAW)) {
2689 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2690 "PCM_Dev %d Topology", out->pcm_device_id);
2691 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2692 if (!ctl) {
2693 ALOGI("%s: Could not get ctl for mixer cmd might be ULL - %s",
2694 __func__, mixer_ctl_name);
2695 } else {
2696 //if success use ULLPP
2697 ALOGI("%s: mixer ctrl %s succeeded setting up ULL for %d",
2698 __func__, mixer_ctl_name, out->pcm_device_id);
2699 //There is a still a possibility that some sessions
2700 // that request for FAST|RAW when 3D audio is active
2701 //can go through ULLPP. Ideally we expects apps to
2702 //listen to audio focus and stop concurrent playback
2703 //Also, we will look for mode flag (voice_in_communication)
2704 //before enabling the realtime flag.
2705 mixer_ctl_set_enum_by_string(ctl, perf_mode[1]);
2706 }
2707 }
2708
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002709 while (1) {
2710 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
2711 flags, &out->config);
2712 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2713 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
2714 if (out->pcm != NULL) {
2715 pcm_close(out->pcm);
2716 out->pcm = NULL;
2717 }
2718 if (pcm_open_retry_count-- == 0) {
2719 ret = -EIO;
2720 goto error_open;
2721 }
2722 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2723 continue;
2724 }
2725 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002726 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002727
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002728 ALOGV("%s: pcm_prepare", __func__);
2729 if (pcm_is_ready(out->pcm)) {
2730 ret = pcm_prepare(out->pcm);
2731 if (ret < 0) {
2732 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2733 pcm_close(out->pcm);
2734 out->pcm = NULL;
2735 goto error_open;
2736 }
2737 }
Divya Narayanan Poojary2c429012017-04-20 16:37:20 +05302738 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05302739 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
2740
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002741 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002742 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05302743 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Xiaojun Sang785b5da2017-08-03 15:52:29 +08002744 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
2745 adev->dsp_bit_width_enforce_mode,
2746 true);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002747 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08002748 out->compr = compress_open(adev->snd_card,
2749 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002750 COMPRESS_IN, &out->compr_config);
2751 if (out->compr && !is_compress_ready(out->compr)) {
2752 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
2753 compress_close(out->compr);
2754 out->compr = NULL;
2755 ret = -EIO;
2756 goto error_open;
2757 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302758 /* compress_open sends params of the track, so reset the flag here */
2759 out->is_compr_metadata_avail = false;
2760
Ben Rombergerd771a7c2017-02-22 18:05:17 -08002761 if (out->client_callback)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002762 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07002763
Fred Oh3f43e742015-03-04 18:42:34 -08002764 /* Since small bufs uses blocking writes, a write will be blocked
2765 for the default max poll time (20s) in the event of an SSR.
2766 Reduce the poll time to observe and deal with SSR faster.
2767 */
Ashish Jain5106d362016-05-11 19:23:33 +05302768 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08002769 compress_set_max_poll_wait(out->compr, 1000);
2770 }
2771
Manish Dewangan69426c82017-01-30 17:35:36 +05302772 audio_extn_utils_compress_set_render_mode(out);
Manish Dewangan58229382017-02-02 15:48:41 +05302773 audio_extn_utils_compress_set_clk_rec_mode(uc_info);
Manish Dewangan69426c82017-01-30 17:35:36 +05302774
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002775 audio_extn_dts_create_state_notifier_node(out->usecase);
2776 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2777 popcount(out->channel_mask),
2778 out->playback_started);
2779
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002780#ifdef DS1_DOLBY_DDP_ENABLED
2781 if (audio_extn_is_dolby_format(out->format))
2782 audio_extn_dolby_send_ddp_endp_params(adev);
2783#endif
Preetam Singh Ranawatd18d8832017-02-08 17:34:54 +05302784 if (!(audio_extn_passthru_is_passthrough_stream(out)) &&
2785 (out->sample_rate != 176400 && out->sample_rate <= 192000)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002786 if (adev->visualizer_start_output != NULL)
2787 adev->visualizer_start_output(out->handle, out->pcm_device_id);
2788 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05302789 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002790 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002791 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002792 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002793
2794 if (ret == 0) {
2795 register_out_stream(out);
2796 if (out->realtime) {
2797 ret = pcm_start(out->pcm);
2798 if (ret < 0)
2799 goto error_open;
2800 }
2801 }
2802
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302803 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002804 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002805
Manish Dewangan21a850a2017-08-14 12:03:55 +05302806 if (out->ip_hdlr_handle) {
Vidyakumar Athota6d655882017-05-22 18:26:24 -07002807 ret = audio_extn_ip_hdlr_intf_open(out->ip_hdlr_handle, true, out, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07002808 if (ret < 0)
2809 ALOGE("%s: audio_extn_ip_hdlr_intf_open failed %d",__func__, ret);
2810 }
2811
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002812 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002813error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302814 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002815 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002816error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05302817 /*
2818 * sleep 50ms to allow sufficient time for kernel
2819 * drivers to recover incases like SSR.
2820 */
2821 usleep(50000);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002822 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002823}
2824
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002825static int check_input_parameters(uint32_t sample_rate,
2826 audio_format_t format,
2827 int channel_count)
2828{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002829 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002830
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302831 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
2832 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
2833 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07002834 !voice_extn_compress_voip_is_format_supported(format) &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302835 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002836
2837 switch (channel_count) {
2838 case 1:
2839 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05302840 case 3:
2841 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002842 case 6:
2843 break;
2844 default:
2845 ret = -EINVAL;
2846 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002847
2848 switch (sample_rate) {
2849 case 8000:
2850 case 11025:
2851 case 12000:
2852 case 16000:
2853 case 22050:
2854 case 24000:
2855 case 32000:
2856 case 44100:
2857 case 48000:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302858 case 96000:
2859 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002860 break;
2861 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002862 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002863 }
2864
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002865 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002866}
2867
2868static size_t get_input_buffer_size(uint32_t sample_rate,
2869 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002870 int channel_count,
2871 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002872{
2873 size_t size = 0;
2874
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002875 if (check_input_parameters(sample_rate, format, channel_count) != 0)
2876 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002877
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002878 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002879 if (is_low_latency)
2880 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302881
2882 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002883
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002884 /* make sure the size is multiple of 32 bytes
2885 * At 48 kHz mono 16-bit PCM:
2886 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2887 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2888 */
2889 size += 0x1f;
2890 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002891
2892 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002893}
2894
Ashish Jain058165c2016-09-28 23:18:48 +05302895static size_t get_output_period_size(uint32_t sample_rate,
2896 audio_format_t format,
2897 int channel_count,
2898 int duration /*in millisecs*/)
2899{
2900 size_t size = 0;
2901 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
2902
2903 if ((duration == 0) || (sample_rate == 0) ||
2904 (bytes_per_sample == 0) || (channel_count == 0)) {
2905 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
2906 bytes_per_sample, channel_count);
2907 return -EINVAL;
2908 }
2909
2910 size = (sample_rate *
2911 duration *
2912 bytes_per_sample *
2913 channel_count) / 1000;
2914 /*
2915 * To have same PCM samples for all channels, the buffer size requires to
2916 * be multiple of (number of channels * bytes per sample)
2917 * For writes to succeed, the buffer must be written at address which is multiple of 32
2918 */
2919 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
2920
2921 return (size/(channel_count * bytes_per_sample));
2922}
2923
Ashish Jain5106d362016-05-11 19:23:33 +05302924static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out)
2925{
2926 uint64_t actual_frames_rendered = 0;
2927 size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
2928
2929 /* This adjustment accounts for buffering after app processor.
2930 * It is based on estimated DSP latency per use case, rather than exact.
2931 */
2932 int64_t platform_latency = platform_render_latency(out->usecase) *
2933 out->sample_rate / 1000000LL;
2934
2935 /* not querying actual state of buffering in kernel as it would involve an ioctl call
2936 * which then needs protection, this causes delay in TS query for pcm_offload usecase
2937 * hence only estimate.
2938 */
2939 int64_t signed_frames = out->written - kernel_buffer_size;
2940
2941 signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask)) - platform_latency;
2942
2943 if (signed_frames > 0)
2944 actual_frames_rendered = signed_frames;
2945
2946 ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
2947 "bytes/sample %zu channel count %d", __func__,(long long int)signed_frames,
2948 (long long int)out->written, (int)kernel_buffer_size,
2949 audio_bytes_per_sample(out->compr_config.codec->format),
2950 popcount(out->channel_mask));
2951
2952 return actual_frames_rendered;
2953}
2954
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002955static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2956{
2957 struct stream_out *out = (struct stream_out *)stream;
2958
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002959 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002960}
2961
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002962static int out_set_sample_rate(struct audio_stream *stream __unused,
2963 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002964{
2965 return -ENOSYS;
2966}
2967
2968static size_t out_get_buffer_size(const struct audio_stream *stream)
2969{
2970 struct stream_out *out = (struct stream_out *)stream;
2971
Varun Balaraje49253e2017-07-06 19:48:56 +05302972 if (is_interactive_usecase(out->usecase)) {
Sri Karri27279e12017-08-07 16:05:20 +05302973 return out->config.period_size * out->config.period_count;
Varun Balaraje49253e2017-07-06 19:48:56 +05302974 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Naresh Tanniruee3499a2017-01-05 14:05:35 +05302975 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
2976 return out->compr_config.fragment_size - sizeof(struct snd_codec_metadata);
2977 else
2978 return out->compr_config.fragment_size;
2979 } else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002980 return voice_extn_compress_voip_out_get_buffer_size(out);
Vikram Panduranga93f080e2017-06-07 18:16:14 -07002981 else if(out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
2982 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 +05302983 else if (is_offload_usecase(out->usecase) &&
2984 out->flags == AUDIO_OUTPUT_FLAG_DIRECT)
Ashish Jain83a6cc22016-06-28 14:34:17 +05302985 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002986
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002987 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002988 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002989}
2990
2991static uint32_t out_get_channels(const struct audio_stream *stream)
2992{
2993 struct stream_out *out = (struct stream_out *)stream;
2994
2995 return out->channel_mask;
2996}
2997
2998static audio_format_t out_get_format(const struct audio_stream *stream)
2999{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003000 struct stream_out *out = (struct stream_out *)stream;
3001
3002 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003003}
3004
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003005static int out_set_format(struct audio_stream *stream __unused,
3006 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003007{
3008 return -ENOSYS;
3009}
3010
3011static int out_standby(struct audio_stream *stream)
3012{
3013 struct stream_out *out = (struct stream_out *)stream;
3014 struct audio_device *adev = out->dev;
kunleiza9d11682017-08-04 14:14:09 +08003015 struct audio_usecase *uc_info;
3016 struct listnode *node;
Haynes Mathew George16081042017-05-31 17:16:49 -07003017 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003018
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303019 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3020 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003021
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003022 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003023 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003024 if (adev->adm_deregister_stream)
3025 adev->adm_deregister_stream(adev->adm_data, out->handle);
3026
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07003027 if (is_offload_usecase(out->usecase))
3028 stop_compressed_output_l(out);
3029
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003030 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003031 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08003032 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
3033 voice_extn_compress_voip_close_output_stream(stream);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303034 out->started = 0;
Zhou Songa8895042016-07-05 17:54:22 +08003035 pthread_mutex_unlock(&adev->lock);
3036 pthread_mutex_unlock(&out->lock);
3037 ALOGD("VOIP output entered standby");
3038 return 0;
3039 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003040 if (out->pcm) {
3041 pcm_close(out->pcm);
3042 out->pcm = NULL;
3043 }
Haynes Mathew George16081042017-05-31 17:16:49 -07003044 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3045 do_stop = out->playback_started;
3046 out->playback_started = false;
3047 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003048 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003049 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303050 out->send_next_track_params = false;
3051 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003052 out->gapless_mdata.encoder_delay = 0;
3053 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003054 if (out->compr != NULL) {
3055 compress_close(out->compr);
3056 out->compr = NULL;
3057 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003058 }
Haynes Mathew George16081042017-05-31 17:16:49 -07003059 if (do_stop) {
3060 stop_output_stream(out);
3061 }
kunleiza9d11682017-08-04 14:14:09 +08003062 //restore output device for active usecase when current snd device and output device mismatch
3063 list_for_each(node, &adev->usecase_list) {
3064 uc_info = node_to_item(node, struct audio_usecase, list);
3065 if ((uc_info->type == PCM_PLAYBACK) &&
3066 (uc_info->out_snd_device != platform_get_output_snd_device(adev->platform, uc_info->stream.out)))
3067 select_devices(adev, uc_info->id);
3068 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003069 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003070 }
3071 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05303072 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003073 return 0;
3074}
3075
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303076static int out_on_error(struct audio_stream *stream)
3077{
3078 struct stream_out *out = (struct stream_out *)stream;
3079 bool do_standby = false;
3080
3081 lock_output_stream(out);
3082 if (!out->standby) {
3083 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
3084 stop_compressed_output_l(out);
3085 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
3086 } else
3087 do_standby = true;
3088 }
3089 pthread_mutex_unlock(&out->lock);
3090
3091 if (do_standby)
3092 return out_standby(&out->stream.common);
3093
3094 return 0;
3095}
3096
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303097/*
3098 *standby implementation without locks, assumes that the callee already
3099 *has taken adev and out lock.
3100 */
3101int out_standby_l(struct audio_stream *stream)
3102{
3103 struct stream_out *out = (struct stream_out *)stream;
3104 struct audio_device *adev = out->dev;
3105
3106 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3107 stream, out->usecase, use_case_table[out->usecase]);
3108
3109 if (!out->standby) {
3110 if (adev->adm_deregister_stream)
3111 adev->adm_deregister_stream(adev->adm_data, out->handle);
3112
3113 if (is_offload_usecase(out->usecase))
3114 stop_compressed_output_l(out);
3115
3116 out->standby = true;
3117 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
3118 voice_extn_compress_voip_close_output_stream(stream);
3119 out->started = 0;
3120 ALOGD("VOIP output entered standby");
3121 return 0;
3122 } else if (!is_offload_usecase(out->usecase)) {
3123 if (out->pcm) {
3124 pcm_close(out->pcm);
3125 out->pcm = NULL;
3126 }
3127 } else {
3128 ALOGD("copl(%p):standby", out);
3129 out->send_next_track_params = false;
3130 out->is_compr_metadata_avail = false;
3131 out->gapless_mdata.encoder_delay = 0;
3132 out->gapless_mdata.encoder_padding = 0;
3133 if (out->compr != NULL) {
3134 compress_close(out->compr);
3135 out->compr = NULL;
3136 }
3137 }
3138 stop_output_stream(out);
3139 }
3140 ALOGD("%s: exit", __func__);
3141 return 0;
3142}
3143
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003144static int out_dump(const struct audio_stream *stream __unused,
3145 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003146{
3147 return 0;
3148}
3149
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003150static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
3151{
3152 int ret = 0;
3153 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08003154
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003155 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08003156 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003157 return -EINVAL;
3158 }
3159
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05303160 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08003161
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003162 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
3163 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05303164 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003165 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003166 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
3167 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05303168 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003169 }
3170
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003171 ALOGV("%s new encoder delay %u and padding %u", __func__,
3172 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
3173
3174 return 0;
3175}
3176
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003177static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
3178{
3179 return out == adev->primary_output || out == adev->voice_tx_output;
3180}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003181
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303182// note: this call is safe only if the stream_cb is
3183// removed first in close_output_stream (as is done now).
3184static void out_snd_mon_cb(void * stream, struct str_parms * parms)
3185{
3186 if (!stream || !parms)
3187 return;
3188
3189 struct stream_out *out = (struct stream_out *)stream;
3190 struct audio_device *adev = out->dev;
3191
3192 card_status_t status;
3193 int card;
3194 if (parse_snd_card_status(parms, &card, &status) < 0)
3195 return;
3196
3197 pthread_mutex_lock(&adev->lock);
3198 bool valid_cb = (card == adev->snd_card);
3199 pthread_mutex_unlock(&adev->lock);
3200
3201 if (!valid_cb)
3202 return;
3203
3204 lock_output_stream(out);
3205 if (out->card_status != status)
3206 out->card_status = status;
3207 pthread_mutex_unlock(&out->lock);
3208
3209 ALOGI("out_snd_mon_cb for card %d usecase %s, status %s", card,
3210 use_case_table[out->usecase],
3211 status == CARD_STATUS_OFFLINE ? "offline" : "online");
3212
3213 if (status == CARD_STATUS_OFFLINE)
3214 out_on_error(stream);
3215
3216 return;
3217}
3218
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003219static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
3220{
3221 struct stream_out *out = (struct stream_out *)stream;
3222 struct audio_device *adev = out->dev;
3223 struct str_parms *parms;
3224 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003225 int ret = 0, val = 0, err;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303226 bool bypass_a2dp = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003227
sangwoobc677242013-08-08 16:53:43 +09003228 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003229 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003230 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303231 if (!parms)
3232 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003233 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
3234 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003235 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003236 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003237 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003238
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003239 /*
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08003240 * When HDMI cable is unplugged the music playback is paused and
3241 * the policy manager sends routing=0. But the audioflinger continues
3242 * to write data until standby time (3sec). As the HDMI core is
3243 * turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003244 * Avoid this by routing audio to speaker until standby.
3245 */
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08003246 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
3247 (val == AUDIO_DEVICE_NONE) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303248 !audio_extn_passthru_is_passthrough_stream(out) &&
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08003249 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
3250 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003251 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05303252 /*
3253 * When A2DP is disconnected the
3254 * music playback is paused and the policy manager sends routing=0
3255 * But the audioflingercontinues to write data until standby time
3256 * (3sec). As BT is turned off, the write gets blocked.
3257 * Avoid this by routing audio to speaker until standby.
3258 */
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07003259 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Naresh Tanniru9d027a62015-03-13 01:32:10 +05303260 (val == AUDIO_DEVICE_NONE)) {
3261 val = AUDIO_DEVICE_OUT_SPEAKER;
3262 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303263 /* To avoid a2dp to sco overlapping / BT device improper state
3264 * check with BT lib about a2dp streaming support before routing
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05303265 */
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303266 if (val & AUDIO_DEVICE_OUT_ALL_A2DP) {
3267 if (!audio_extn_a2dp_is_ready()) {
3268 if (val & AUDIO_DEVICE_OUT_SPEAKER) {
3269 //combo usecase just by pass a2dp
3270 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303271 bypass_a2dp = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303272 } else {
3273 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
3274 /* update device to a2dp and don't route as BT returned error
3275 * However it is still possible a2dp routing called because
3276 * of current active device disconnection (like wired headset)
3277 */
3278 out->devices = val;
3279 pthread_mutex_unlock(&out->lock);
3280 pthread_mutex_unlock(&adev->lock);
3281 goto error;
3282 }
3283 }
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05303284 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003285 /*
3286 * select_devices() call below switches all the usecases on the same
3287 * backend to the new device. Refer to check_usecases_codec_backend() in
3288 * the select_devices(). But how do we undo this?
3289 *
3290 * For example, music playback is active on headset (deep-buffer usecase)
3291 * and if we go to ringtones and select a ringtone, low-latency usecase
3292 * will be started on headset+speaker. As we can't enable headset+speaker
3293 * and headset devices at the same time, select_devices() switches the music
3294 * playback to headset+speaker while starting low-lateny usecase for ringtone.
3295 * So when the ringtone playback is completed, how do we undo the same?
3296 *
3297 * We are relying on the out_set_parameters() call on deep-buffer output,
3298 * once the ringtone playback is ended.
3299 * NOTE: We should not check if the current devices are same as new devices.
3300 * Because select_devices() must be called to switch back the music
3301 * playback to headset.
3302 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003303 if (val != 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003304 audio_devices_t new_dev = val;
3305 bool same_dev = out->devices == new_dev;
3306 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003307
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07003308 if (output_drives_call(adev, out)) {
3309 if(!voice_is_in_call(adev)) {
3310 if (adev->mode == AUDIO_MODE_IN_CALL) {
3311 adev->current_call_output = out;
3312 ret = voice_start_call(adev);
3313 }
3314 } else {
3315 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003316 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07003317 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003318 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08003319
3320 if (!out->standby) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003321 if (!same_dev) {
3322 ALOGV("update routing change");
Sudheer Papothi80266982016-08-16 02:36:18 +05303323 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3324 adev->perf_lock_opts,
3325 adev->perf_lock_opts_size);
Haynes Mathew George822b5492016-07-01 16:57:24 -07003326 if (adev->adm_on_routing_change)
3327 adev->adm_on_routing_change(adev->adm_data,
3328 out->handle);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003329 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303330 if (!bypass_a2dp) {
3331 select_devices(adev, out->usecase);
3332 } else {
3333 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
3334 select_devices(adev, out->usecase);
3335 out->devices = new_dev;
3336 }
Sudheer Papothi80266982016-08-16 02:36:18 +05303337 if (!same_dev)
3338 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303339 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
3340 out->a2dp_compress_mute &&
Zhou Songc66eb7e2017-08-08 18:29:07 +08003341 (!(out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) || audio_extn_a2dp_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303342 pthread_mutex_lock(&out->compr_mute_lock);
3343 out->a2dp_compress_mute = false;
3344 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
3345 pthread_mutex_unlock(&out->compr_mute_lock);
3346 }
3347
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08003348 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003349 }
3350
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003351 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003352 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003353 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003354
3355 if (out == adev->primary_output) {
3356 pthread_mutex_lock(&adev->lock);
3357 audio_extn_set_parameters(adev, parms);
3358 pthread_mutex_unlock(&adev->lock);
3359 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003360 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003361 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003362 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003363
3364 audio_extn_dts_create_state_notifier_node(out->usecase);
3365 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3366 popcount(out->channel_mask),
3367 out->playback_started);
3368
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08003369 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003370 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003371
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05303372 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
3373 if (err >= 0) {
3374 strlcpy(out->profile, value, sizeof(out->profile));
3375 ALOGV("updating stream profile with value '%s'", out->profile);
3376 lock_output_stream(out);
3377 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
3378 &adev->streams_output_cfg_list,
3379 out->devices, out->flags, out->format,
3380 out->sample_rate, out->bit_width,
3381 out->channel_mask, out->profile,
3382 &out->app_type_cfg);
3383 pthread_mutex_unlock(&out->lock);
3384 }
3385
Alexy Joseph98988832017-01-13 14:56:59 -08003386 //suspend, resume handling block
3387 if (out->dynamic_pm_qos_enabled) {
3388 //check suspend parameter only for low latency and if the property
3389 //is enabled
3390 if (str_parms_get_str(parms, "suspend_playback", value, sizeof(value)) >= 0) {
3391 ALOGI("%s: got suspend_playback %s", __func__, value);
3392 lock_output_stream(out);
3393 if (!strncmp(value, "false", 5)) {
3394 //suspend_playback=false is supposed to set QOS value back to 75%
3395 //the mixer control sent with value Enable will achieve that
3396 ret = audio_route_apply_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
3397 } else if (!strncmp (value, "true", 4)) {
3398 //suspend_playback=true is supposed to remove QOS value
3399 //resetting the mixer control will set the default value
3400 //for the mixer control which is Disable and this removes the QOS vote
3401 ret = audio_route_reset_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
3402 } else {
3403 ALOGE("%s: Wrong value sent for suspend_playback, expected true/false,"
3404 " got %s", __func__, value);
3405 ret = -1;
3406 }
3407
3408 if (ret != 0) {
3409 ALOGE("%s: %s mixer ctl failed with %d, ignore suspend/resume setparams",
3410 __func__, out->pm_qos_mixer_path, ret);
3411 }
3412
3413 pthread_mutex_unlock(&out->lock);
3414 }
3415 }
3416 //end suspend, resume handling block
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003417 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303418error:
Eric Laurent994a6932013-07-17 11:51:42 -07003419 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003420 return ret;
3421}
3422
3423static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
3424{
3425 struct stream_out *out = (struct stream_out *)stream;
3426 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003427 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003428 char value[256];
3429 struct str_parms *reply = str_parms_create();
3430 size_t i, j;
3431 int ret;
3432 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003433
3434 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003435 if (reply) {
3436 str_parms_destroy(reply);
3437 }
3438 if (query) {
3439 str_parms_destroy(query);
3440 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003441 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
3442 return NULL;
3443 }
3444
Eric Laurent994a6932013-07-17 11:51:42 -07003445 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003446 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
3447 if (ret >= 0) {
3448 value[0] = '\0';
3449 i = 0;
3450 while (out->supported_channel_masks[i] != 0) {
3451 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
3452 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
3453 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08003454 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003455 }
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08003456 strlcat(value, out_channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003457 first = false;
3458 break;
3459 }
3460 }
3461 i++;
3462 }
3463 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
3464 str = str_parms_to_str(reply);
3465 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003466 voice_extn_out_get_parameters(out, query, reply);
3467 str = str_parms_to_str(reply);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003468 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003469
Alexy Joseph62142aa2015-11-16 15:10:34 -08003470
3471 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
3472 if (ret >= 0) {
3473 value[0] = '\0';
Dhananjay Kumarac341582017-02-23 23:42:25 +05303474 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
3475 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Alexy Joseph62142aa2015-11-16 15:10:34 -08003476 ALOGV("in direct_pcm");
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05303477 strlcat(value, "true", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08003478 } else {
3479 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05303480 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08003481 }
3482 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003483 if (str)
3484 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08003485 str = str_parms_to_str(reply);
3486 }
3487
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003488 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
3489 if (ret >= 0) {
3490 value[0] = '\0';
3491 i = 0;
3492 first = true;
3493 while (out->supported_formats[i] != 0) {
3494 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
3495 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
3496 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08003497 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003498 }
3499 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
3500 first = false;
3501 break;
3502 }
3503 }
3504 i++;
3505 }
3506 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003507 if (str)
3508 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003509 str = str_parms_to_str(reply);
3510 }
Mingming Yin3a941d42016-02-17 18:08:05 -08003511
3512 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
3513 if (ret >= 0) {
3514 value[0] = '\0';
3515 i = 0;
3516 first = true;
3517 while (out->supported_sample_rates[i] != 0) {
3518 for (j = 0; j < ARRAY_SIZE(out_hdmi_sample_rates_name_to_enum_table); j++) {
3519 if (out_hdmi_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
3520 if (!first) {
3521 strlcat(value, "|", sizeof(value));
3522 }
3523 strlcat(value, out_hdmi_sample_rates_name_to_enum_table[j].name, sizeof(value));
3524 first = false;
3525 break;
3526 }
3527 }
3528 i++;
3529 }
3530 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
3531 if (str)
3532 free(str);
3533 str = str_parms_to_str(reply);
3534 }
3535
Alexy Joseph98988832017-01-13 14:56:59 -08003536 if (str_parms_get_str(query, "supports_hw_suspend", value, sizeof(value)) >= 0) {
3537 //only low latency track supports suspend_resume
3538 str_parms_add_int(reply, "supports_hw_suspend",
3539 (out->dynamic_pm_qos_enabled));
3540 if (str)
3541 free(str);
3542 str = str_parms_to_str(reply);
3543 }
3544
3545
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003546 str_parms_destroy(query);
3547 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07003548 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003549 return str;
3550}
3551
3552static uint32_t out_get_latency(const struct audio_stream_out *stream)
3553{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003554 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003555 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08003556 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003557
Alexy Josephaa54c872014-12-03 02:46:47 -08003558 if (is_offload_usecase(out->usecase)) {
Manish Dewangan07de2142017-02-27 19:27:20 +05303559 lock_output_stream(out);
3560 latency = audio_extn_utils_compress_get_dsp_latency(out);
3561 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07003562 } else if ((out->realtime) ||
3563 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003564 // since the buffer won't be filled up faster than realtime,
3565 // return a smaller number
3566 if (out->config.rate)
3567 period_ms = (out->af_period_multiplier * out->config.period_size *
3568 1000) / (out->config.rate);
3569 else
3570 period_ms = 0;
3571 latency = period_ms + platform_render_latency(out->usecase)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08003572 } else {
3573 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003574 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08003575 }
3576
yidongh0515e042017-07-06 15:00:34 +08003577 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices)
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -08003578 latency += audio_extn_a2dp_get_encoder_latency();
3579
Anish Kumar50ebcbf2014-12-09 04:01:39 +05303580 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08003581 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003582}
3583
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303584static float AmpToDb(float amplification)
3585{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05303586 float db = DSD_VOLUME_MIN_DB;
3587 if (amplification > 0) {
3588 db = 20 * log10(amplification);
3589 if(db < DSD_VOLUME_MIN_DB)
3590 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303591 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05303592 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303593}
3594
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303595static int out_set_compr_volume(struct audio_stream_out *stream, float left,
3596 float right)
3597{
3598 struct stream_out *out = (struct stream_out *)stream;
3599 int volume[2];
3600 char mixer_ctl_name[128];
3601 struct audio_device *adev = out->dev;
3602 struct mixer_ctl *ctl;
3603 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
3604 PCM_PLAYBACK);
3605
3606 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
3607 "Compress Playback %d Volume", pcm_device_id);
3608 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3609 if (!ctl) {
3610 ALOGE("%s: Could not get ctl for mixer cmd - %s",
3611 __func__, mixer_ctl_name);
3612 return -EINVAL;
3613 }
3614 ALOGE("%s:ctl for mixer cmd - %s, left %f, right %f",
3615 __func__, mixer_ctl_name, left, right);
3616 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
3617 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
3618 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
3619
3620 return 0;
3621}
3622
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003623static int out_set_volume(struct audio_stream_out *stream, float left,
3624 float right)
3625{
Eric Laurenta9024de2013-04-04 09:19:12 -07003626 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003627 int volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303628 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003629
Eric Laurenta9024de2013-04-04 09:19:12 -07003630 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
3631 /* only take left channel into account: the API is for stereo anyway */
3632 out->muted = (left == 0.0f);
3633 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003634 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303635 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003636 /*
3637 * Set mute or umute on HDMI passthrough stream.
3638 * Only take left channel into account.
3639 * Mute is 0 and unmute 1
3640 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303641 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303642 } else if (out->format == AUDIO_FORMAT_DSD){
3643 char mixer_ctl_name[128] = "DSD Volume";
3644 struct audio_device *adev = out->dev;
3645 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3646
3647 if (!ctl) {
3648 ALOGE("%s: Could not get ctl for mixer cmd - %s",
3649 __func__, mixer_ctl_name);
3650 return -EINVAL;
3651 }
3652 volume[0] = (int)(AmpToDb(left));
3653 volume[1] = (int)(AmpToDb(right));
3654 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
3655 return 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003656 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303657 pthread_mutex_lock(&out->compr_mute_lock);
3658 ALOGE("%s: compress mute %d", __func__, out->a2dp_compress_mute);
3659 if (!out->a2dp_compress_mute)
3660 ret = out_set_compr_volume(stream, left, right);
3661 out->volume_l = left;
3662 out->volume_r = right;
3663 pthread_mutex_unlock(&out->compr_mute_lock);
3664 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003665 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07003666 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
3667 char mixer_ctl_name[] = "App Type Gain";
3668 struct audio_device *adev = out->dev;
3669 struct mixer_ctl *ctl;
3670 uint32_t set_values[4];
3671
3672 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3673 if (!ctl) {
3674 ALOGE("%s: Could not get ctl for mixer cmd - %s",
3675 __func__, mixer_ctl_name);
3676 return -EINVAL;
3677 }
3678
3679 set_values[0] = 0; //0: Rx Session 1:Tx Session
3680 set_values[1] = out->app_type_cfg.app_type;
3681 set_values[2] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
3682 set_values[3] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
3683
3684 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
3685 return 0;
Eric Laurenta9024de2013-04-04 09:19:12 -07003686 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003687
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003688 return -ENOSYS;
3689}
3690
Zhou Songc9672822017-08-16 16:01:39 +08003691static void update_frames_written(struct stream_out *out, size_t bytes)
3692{
3693 size_t bpf = 0;
3694
3695 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
3696 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
3697 bpf = 1;
3698 else if (!is_offload_usecase(out->usecase))
3699 bpf = audio_bytes_per_sample(out->format) *
3700 audio_channel_count_from_out_mask(out->channel_mask);
3701 if (bpf != 0)
3702 out->written += bytes / bpf;
3703}
3704
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003705static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
3706 size_t bytes)
3707{
3708 struct stream_out *out = (struct stream_out *)stream;
3709 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07003710 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003711
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003712 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303713
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303714 if (CARD_STATUS_OFFLINE == out->card_status) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08003715
Dhananjay Kumarac341582017-02-23 23:42:25 +05303716 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Ashish Jainbbce4322016-02-16 13:25:27 +05303717 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05303718 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
3719 pthread_mutex_unlock(&out->lock);
3720 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05303721 } else {
Ashish Jainbbce4322016-02-16 13:25:27 +05303722 ALOGD(" %s: sound card is not active/SSR state", __func__);
3723 ret= -EIO;
3724 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303725 }
3726 }
3727
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303728 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303729 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303730 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303731 goto exit;
3732 }
3733
Haynes Mathew George16081042017-05-31 17:16:49 -07003734 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3735 ret = -EINVAL;
3736 goto exit;
3737 }
3738
Manish Dewangan37864bc2017-06-09 12:28:37 +05303739 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Manish Dewangan672001f2017-08-16 13:44:07 +05303740 if (audio_extn_passthru_is_enabled() &&
3741 !out->is_iec61937_info_available &&
3742 audio_extn_passthru_is_passthrough_stream(out)) {
Manish Dewangan37864bc2017-06-09 12:28:37 +05303743 audio_extn_passthru_update_stream_configuration(adev, out,
3744 buffer, bytes);
3745 out->is_iec61937_info_available = true;
Manish Dewangan671a4202017-08-18 17:30:46 +05303746
3747 if((out->format == AUDIO_FORMAT_DTS) ||
3748 (out->format == AUDIO_FORMAT_DTS_HD)) {
3749 ret = audio_extn_passthru_update_dts_stream_configuration(out,
3750 buffer, bytes);
3751 if (ret) {
3752 if (ret != -ENOSYS) {
3753 out->is_iec61937_info_available = false;
3754 ALOGD("iec61937 transmission info not yet updated retry");
3755 }
3756 } else {
3757 /* if stream has started and after that there is
3758 * stream config change (iec transmission config)
3759 * then trigger select_device to update backend configuration.
3760 */
3761 out->stream_config_changed = true;
3762 pthread_mutex_lock(&adev->lock);
3763 select_devices(adev, out->usecase);
3764 pthread_mutex_unlock(&adev->lock);
3765 out->stream_config_changed = false;
3766 out->is_iec61937_info_available = true;
3767 }
3768 }
Manish Dewangan37864bc2017-06-09 12:28:37 +05303769 }
3770 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303771
3772 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
3773 (audio_extn_a2dp_is_suspended())) {
3774 if (!(out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
3775 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303776 ret = -EIO;
3777 goto exit;
3778 }
3779 }
3780 }
3781
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003782 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003783 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08003784 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003785 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
3786 ret = voice_extn_compress_voip_start_output_stream(out);
3787 else
3788 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003789 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003790 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003791 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003792 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003793 goto exit;
3794 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303795 out->started = 1;
vivek mehtab72d08d2016-04-29 03:16:47 -07003796 if (last_known_cal_step != -1) {
3797 ALOGD("%s: retry previous failed cal level set", __func__);
3798 audio_hw_send_gain_dep_calibration(last_known_cal_step);
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +05303799 last_known_cal_step = -1;
vivek mehtab72d08d2016-04-29 03:16:47 -07003800 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003801 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003802
Ashish Jain81eb2a82015-05-13 10:52:34 +05303803 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08003804 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05303805 adev->is_channel_status_set = true;
3806 }
3807
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003808 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08003809 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003810 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003811 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003812 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
3813 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303814 if (out->send_next_track_params && out->is_compr_metadata_avail) {
3815 ALOGD("copl(%p):send next track params in gapless", out);
3816 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
3817 out->send_next_track_params = false;
3818 out->is_compr_metadata_avail = false;
3819 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003820 }
Dhananjay Kumarac341582017-02-23 23:42:25 +05303821 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05303822 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003823
Ashish Jain83a6cc22016-06-28 14:34:17 +05303824 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05303825 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05303826 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05303827 pthread_mutex_unlock(&out->lock);
3828 return -EINVAL;
3829 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05303830 audio_format_t dst_format = out->hal_op_format;
3831 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303832
3833 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
3834 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
3835
Ashish Jain83a6cc22016-06-28 14:34:17 +05303836 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05303837 dst_format,
3838 buffer,
3839 src_format,
3840 frames);
3841
Ashish Jain83a6cc22016-06-28 14:34:17 +05303842 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05303843 bytes_to_write);
3844
3845 /*Convert written bytes in audio flinger format*/
3846 if (ret > 0)
3847 ret = ((ret * format_to_bitwidth_table[out->format]) /
3848 format_to_bitwidth_table[dst_format]);
3849 }
3850 } else
3851 ret = compress_write(out->compr, buffer, bytes);
3852
Zhou Songc9672822017-08-16 16:01:39 +08003853 if ((ret < 0 || ret == (ssize_t)bytes) && !out->non_blocking)
3854 update_frames_written(out, bytes);
3855
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303856 if (ret < 0)
3857 ret = -errno;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303858 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %zd", __func__, bytes, ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05303859 /*msg to cb thread only if non blocking write is enabled*/
3860 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05303861 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003862 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05303863 } else if (-ENETRESET == ret) {
3864 ALOGE("copl %s: received sound card offline state on compress write", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303865 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru80659832014-06-04 18:17:56 +05303866 pthread_mutex_unlock(&out->lock);
Dhananjay Kumar1248dd82017-07-28 21:22:16 +05303867 out_on_error(&out->stream.common);
Naresh Tanniru80659832014-06-04 18:17:56 +05303868 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003869 }
Ashish Jain5106d362016-05-11 19:23:33 +05303870
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05303871 /* Call compr start only when non-zero bytes of data is there to be rendered */
3872 if (!out->playback_started && ret > 0) {
3873 int status = compress_start(out->compr);
3874 if (status < 0) {
3875 ret = status;
3876 ALOGE("%s: compr start failed with err %d", __func__, errno);
3877 goto exit;
3878 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07003879 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003880 out->playback_started = 1;
3881 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003882
3883 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3884 popcount(out->channel_mask),
3885 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003886 }
3887 pthread_mutex_unlock(&out->lock);
3888 return ret;
3889 } else {
3890 if (out->pcm) {
3891 if (out->muted)
3892 memset((void *)buffer, 0, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003893
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303894 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003895
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003896 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003897
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003898 if (out->config.rate)
3899 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
3900 out->config.rate;
3901
3902 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
3903
3904 request_out_focus(out, ns);
3905
3906 if (use_mmap)
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003907 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003908 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05303909 out->convert_buffer != NULL) {
3910
3911 memcpy_by_audio_format(out->convert_buffer,
3912 out->hal_op_format,
3913 buffer,
3914 out->hal_ip_format,
3915 out->config.period_size * out->config.channels);
3916
3917 ret = pcm_write(out->pcm, out->convert_buffer,
3918 (out->config.period_size *
3919 out->config.channels *
3920 format_to_bitwidth_table[out->hal_op_format]));
3921 } else {
Aditya Bavanarid4db8ee2017-05-29 21:08:03 +05303922 /*
3923 * To avoid underrun in DSP when the application is not pumping
3924 * data at required rate, check for the no. of bytes and ignore
3925 * pcm_write if it is less than actual buffer size.
3926 * It is a work around to a change in compress VOIP driver.
3927 */
3928 if ((out->flags & AUDIO_OUTPUT_FLAG_VOIP_RX) &&
3929 bytes < (out->config.period_size * out->config.channels *
3930 audio_bytes_per_sample(out->format))) {
3931 size_t voip_buf_size =
3932 out->config.period_size * out->config.channels *
3933 audio_bytes_per_sample(out->format);
3934 ALOGE("%s:VOIP underrun: bytes received %zu, required:%zu\n",
3935 __func__, bytes, voip_buf_size);
3936 usleep(((uint64_t)voip_buf_size - bytes) *
3937 1000000 / audio_stream_out_frame_size(stream) /
3938 out_get_sample_rate(&out->stream.common));
3939 ret = 0;
3940 } else
3941 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Ashish Jain83a6cc22016-06-28 14:34:17 +05303942 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003943
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003944 release_out_focus(out);
3945
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303946 if (ret < 0)
3947 ret = -errno;
Zhou Songc9672822017-08-16 16:01:39 +08003948 else if (ret > 0)
Ashish Jain83a6cc22016-06-28 14:34:17 +05303949 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003950 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003951 }
3952
3953exit:
Zhou Songc9672822017-08-16 16:01:39 +08003954 update_frames_written(out, bytes);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303955 if (-ENETRESET == ret) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303956 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303957 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003958 pthread_mutex_unlock(&out->lock);
3959
3960 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003961 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08003962 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303963 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303964 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303965 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303966 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303967 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303968 out->standby = true;
3969 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303970 out_on_error(&out->stream.common);
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05303971 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
3972 usleep((uint64_t)bytes * 1000000 / audio_stream_out_frame_size(stream) /
3973 out_get_sample_rate(&out->stream.common));
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07003974
3975 if (audio_extn_passthru_is_passthrough_stream(out)) {
3976 ALOGE("%s: write error, ret = %d", __func__, ret);
3977 return ret;
3978 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003979 }
3980 return bytes;
3981}
3982
3983static int out_get_render_position(const struct audio_stream_out *stream,
3984 uint32_t *dsp_frames)
3985{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003986 struct stream_out *out = (struct stream_out *)stream;
Zhou Song32a556e2015-05-05 10:46:56 +08003987
3988 if (dsp_frames == NULL)
3989 return -EINVAL;
3990
3991 *dsp_frames = 0;
3992 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08003993 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05303994
3995 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
3996 * this operation and adev_close_output_stream(where out gets reset).
3997 */
Dhananjay Kumarac341582017-02-23 23:42:25 +05303998 if (!out->non_blocking && !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05303999 *dsp_frames = get_actual_pcm_frames_rendered(out);
4000 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
4001 return 0;
4002 }
4003
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004004 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05304005 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05304006 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004007 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05304008 if (ret < 0)
4009 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004010 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05304011 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004012 }
Naresh Tanniru80659832014-06-04 18:17:56 +05304013 if (-ENETRESET == ret) {
4014 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304015 out->card_status = CARD_STATUS_OFFLINE;
4016 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05304017 } else if(ret < 0) {
4018 ALOGE(" ERROR: Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304019 ret = -EINVAL;
4020 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05304021 /*
4022 * Handle corner case where compress session is closed during SSR
4023 * and timestamp is queried
4024 */
4025 ALOGE(" ERROR: sound card not active, return error");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304026 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05304027 } else {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304028 ret = 0;
Naresh Tanniru80659832014-06-04 18:17:56 +05304029 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304030 pthread_mutex_unlock(&out->lock);
4031 return ret;
Zhou Song32a556e2015-05-05 10:46:56 +08004032 } else if (audio_is_linear_pcm(out->format)) {
4033 *dsp_frames = out->written;
4034 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004035 } else
4036 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004037}
4038
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004039static int out_add_audio_effect(const struct audio_stream *stream __unused,
4040 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004041{
4042 return 0;
4043}
4044
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004045static int out_remove_audio_effect(const struct audio_stream *stream __unused,
4046 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004047{
4048 return 0;
4049}
4050
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004051static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
4052 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004053{
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05304054 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004055}
4056
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004057static int out_get_presentation_position(const struct audio_stream_out *stream,
4058 uint64_t *frames, struct timespec *timestamp)
4059{
4060 struct stream_out *out = (struct stream_out *)stream;
4061 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07004062 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004063
Ashish Jain5106d362016-05-11 19:23:33 +05304064 /* below piece of code is not guarded against any lock because audioFliner serializes
4065 * this operation and adev_close_output_stream( where out gets reset).
4066 */
4067 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
Dhananjay Kumarac341582017-02-23 23:42:25 +05304068 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05304069 *frames = get_actual_pcm_frames_rendered(out);
4070 /* this is the best we can do */
4071 clock_gettime(CLOCK_MONOTONIC, timestamp);
4072 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
4073 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
4074 return 0;
4075 }
4076
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004077 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004078
Ashish Jain5106d362016-05-11 19:23:33 +05304079 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
4080 ret = compress_get_tstamp(out->compr, &dsp_frames,
4081 &out->sample_rate);
yidongh0515e042017-07-06 15:00:34 +08004082 // Adjustment accounts for A2dp encoder latency with offload usecases
4083 // Note: Encoder latency is returned in ms.
4084 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
4085 unsigned long offset =
4086 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
4087 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
4088 }
Ashish Jain5106d362016-05-11 19:23:33 +05304089 ALOGVV("%s rendered frames %ld sample_rate %d",
4090 __func__, dsp_frames, out->sample_rate);
4091 *frames = dsp_frames;
4092 if (ret < 0)
4093 ret = -errno;
4094 if (-ENETRESET == ret) {
4095 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304096 out->card_status = CARD_STATUS_OFFLINE;
Ashish Jain5106d362016-05-11 19:23:33 +05304097 ret = -EINVAL;
4098 } else
4099 ret = 0;
4100 /* this is the best we can do */
4101 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07004102 } else {
4103 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004104 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07004105 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
4106 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07004107 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07004108 // This adjustment accounts for buffering after app processor.
4109 // It is based on estimated DSP latency per use case, rather than exact.
4110 signed_frames -=
4111 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
4112
Aniket Kumar Lataff613152017-07-18 18:19:21 -07004113 // Adjustment accounts for A2dp encoder latency with non offload usecases
4114 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
4115 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
4116 signed_frames -=
4117 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
4118 }
4119
Eric Laurent949a0892013-09-20 09:20:13 -07004120 // It would be unusual for this value to be negative, but check just in case ...
4121 if (signed_frames >= 0) {
4122 *frames = signed_frames;
4123 ret = 0;
4124 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004125 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304126 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Ashish Jainbbce4322016-02-16 13:25:27 +05304127 *frames = out->written;
4128 clock_gettime(CLOCK_MONOTONIC, timestamp);
4129 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004130 }
4131 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004132 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004133 return ret;
4134}
4135
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004136static int out_set_callback(struct audio_stream_out *stream,
4137 stream_callback_t callback, void *cookie)
4138{
4139 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08004140 int ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004141
4142 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004143 lock_output_stream(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08004144 out->client_callback = callback;
4145 out->client_cookie = cookie;
4146 if (out->adsp_hdlr_stream_handle) {
4147 ret = audio_extn_adsp_hdlr_stream_set_callback(
4148 out->adsp_hdlr_stream_handle,
4149 callback,
4150 cookie);
4151 if (ret)
4152 ALOGW("%s:adsp hdlr callback registration failed %d",
4153 __func__, ret);
4154 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004155 pthread_mutex_unlock(&out->lock);
4156 return 0;
4157}
4158
4159static int out_pause(struct audio_stream_out* stream)
4160{
4161 struct stream_out *out = (struct stream_out *)stream;
4162 int status = -ENOSYS;
4163 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004164 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004165 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004166 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004167 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304168 if (out->card_status != CARD_STATUS_OFFLINE)
Naresh Tanniru80659832014-06-04 18:17:56 +05304169 status = compress_pause(out->compr);
4170
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004171 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004172
Mingming Yin21854652016-04-13 11:54:02 -07004173 if (audio_extn_passthru_is_active()) {
4174 ALOGV("offload use case, pause passthru");
4175 audio_extn_passthru_on_pause(out);
4176 }
4177
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05304178 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004179 audio_extn_dts_notify_playback_state(out->usecase, 0,
4180 out->sample_rate, popcount(out->channel_mask),
4181 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004182 }
4183 pthread_mutex_unlock(&out->lock);
4184 }
4185 return status;
4186}
4187
4188static int out_resume(struct audio_stream_out* stream)
4189{
4190 struct stream_out *out = (struct stream_out *)stream;
4191 int status = -ENOSYS;
4192 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004193 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004194 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004195 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004196 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004197 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304198 if (out->card_status != CARD_STATUS_OFFLINE) {
Naresh Tanniru80659832014-06-04 18:17:56 +05304199 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07004200 }
4201 if (!status) {
4202 out->offload_state = OFFLOAD_STATE_PLAYING;
4203 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05304204 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004205 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4206 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004207 }
4208 pthread_mutex_unlock(&out->lock);
4209 }
4210 return status;
4211}
4212
4213static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
4214{
4215 struct stream_out *out = (struct stream_out *)stream;
4216 int status = -ENOSYS;
4217 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004218 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004219 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004220 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
4221 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
4222 else
4223 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
4224 pthread_mutex_unlock(&out->lock);
4225 }
4226 return status;
4227}
4228
4229static int out_flush(struct audio_stream_out* stream)
4230{
4231 struct stream_out *out = (struct stream_out *)stream;
4232 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004233 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004234 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004235 lock_output_stream(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07004236 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
4237 stop_compressed_output_l(out);
4238 out->written = 0;
4239 } else {
4240 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
4241 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004242 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004243 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004244 return 0;
4245 }
4246 return -ENOSYS;
4247}
4248
Haynes Mathew George16081042017-05-31 17:16:49 -07004249static int out_stop(const struct audio_stream_out* stream)
4250{
4251 struct stream_out *out = (struct stream_out *)stream;
4252 struct audio_device *adev = out->dev;
4253 int ret = -ENOSYS;
4254
4255 ALOGV("%s", __func__);
4256 pthread_mutex_lock(&adev->lock);
4257 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
4258 out->playback_started && out->pcm != NULL) {
4259 pcm_stop(out->pcm);
4260 ret = stop_output_stream(out);
4261 out->playback_started = false;
4262 }
4263 pthread_mutex_unlock(&adev->lock);
4264 return ret;
4265}
4266
4267static int out_start(const struct audio_stream_out* stream)
4268{
4269 struct stream_out *out = (struct stream_out *)stream;
4270 struct audio_device *adev = out->dev;
4271 int ret = -ENOSYS;
4272
4273 ALOGV("%s", __func__);
4274 pthread_mutex_lock(&adev->lock);
4275 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
4276 !out->playback_started && out->pcm != NULL) {
4277 ret = start_output_stream(out);
4278 if (ret == 0) {
4279 out->playback_started = true;
4280 }
4281 }
4282 pthread_mutex_unlock(&adev->lock);
4283 return ret;
4284}
4285
4286/*
4287 * Modify config->period_count based on min_size_frames
4288 */
4289static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
4290{
4291 int periodCountRequested = (min_size_frames + config->period_size - 1)
4292 / config->period_size;
4293 int periodCount = MMAP_PERIOD_COUNT_MIN;
4294
4295 ALOGV("%s original config.period_size = %d config.period_count = %d",
4296 __func__, config->period_size, config->period_count);
4297
4298 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
4299 periodCount *= 2;
4300 }
4301 config->period_count = periodCount;
4302
4303 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
4304}
4305
4306static int out_create_mmap_buffer(const struct audio_stream_out *stream,
4307 int32_t min_size_frames,
4308 struct audio_mmap_buffer_info *info)
4309{
4310 struct stream_out *out = (struct stream_out *)stream;
4311 struct audio_device *adev = out->dev;
4312 int ret = 0;
4313 unsigned int offset1;
4314 unsigned int frames1;
4315 const char *step = "";
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07004316 uint32_t mmap_size;
Haynes Mathew George16081042017-05-31 17:16:49 -07004317
4318 ALOGV("%s", __func__);
4319 pthread_mutex_lock(&adev->lock);
4320
4321 if (info == NULL || min_size_frames == 0) {
4322 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
4323 ret = -EINVAL;
4324 goto exit;
4325 }
4326 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
4327 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
4328 ret = -ENOSYS;
4329 goto exit;
4330 }
4331 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
4332 if (out->pcm_device_id < 0) {
4333 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
4334 __func__, out->pcm_device_id, out->usecase);
4335 ret = -EINVAL;
4336 goto exit;
4337 }
4338
4339 adjust_mmap_period_count(&out->config, min_size_frames);
4340
4341 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
4342 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
4343 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
4344 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
4345 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
4346 step = "open";
4347 ret = -ENODEV;
4348 goto exit;
4349 }
4350 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
4351 if (ret < 0) {
4352 step = "begin";
4353 goto exit;
4354 }
4355 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
4356 info->burst_size_frames = out->config.period_size;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07004357 ret = platform_get_mmap_data_fd(adev->platform,
4358 out->pcm_device_id, 0 /*playback*/,
4359 &info->shared_memory_fd,
4360 &mmap_size);
4361 if (ret < 0) {
4362 step = "get_mmap_fd";
4363 goto exit;
4364 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004365 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(out->pcm,
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07004366 info->buffer_size_frames));
Haynes Mathew George16081042017-05-31 17:16:49 -07004367
4368 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
4369 if (ret < 0) {
4370 step = "commit";
4371 goto exit;
4372 }
4373
4374 out->standby = false;
4375 ret = 0;
4376
4377 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
4378 __func__, info->shared_memory_address, info->buffer_size_frames);
4379
4380exit:
4381 if (ret != 0) {
4382 if (out->pcm == NULL) {
4383 ALOGE("%s: %s - %d", __func__, step, ret);
4384 } else {
4385 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
4386 pcm_close(out->pcm);
4387 out->pcm = NULL;
4388 }
4389 }
4390 pthread_mutex_unlock(&adev->lock);
4391 return ret;
4392}
4393
4394static int out_get_mmap_position(const struct audio_stream_out *stream,
4395 struct audio_mmap_position *position)
4396{
4397 struct stream_out *out = (struct stream_out *)stream;
4398 ALOGVV("%s", __func__);
4399 if (position == NULL) {
4400 return -EINVAL;
4401 }
4402 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
4403 return -ENOSYS;
4404 }
4405 if (out->pcm == NULL) {
4406 return -ENOSYS;
4407 }
4408
4409 struct timespec ts = { 0, 0 };
4410 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
4411 if (ret < 0) {
4412 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
4413 return ret;
4414 }
4415 position->time_nanoseconds = ts.tv_sec*1000000000L + ts.tv_nsec;
4416 return 0;
4417}
4418
4419
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004420/** audio_stream_in implementation **/
4421static uint32_t in_get_sample_rate(const struct audio_stream *stream)
4422{
4423 struct stream_in *in = (struct stream_in *)stream;
4424
4425 return in->config.rate;
4426}
4427
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004428static int in_set_sample_rate(struct audio_stream *stream __unused,
4429 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004430{
4431 return -ENOSYS;
4432}
4433
4434static size_t in_get_buffer_size(const struct audio_stream *stream)
4435{
4436 struct stream_in *in = (struct stream_in *)stream;
4437
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004438 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
4439 return voice_extn_compress_voip_in_get_buffer_size(in);
Vikram Panduranga93f080e2017-06-07 18:16:14 -07004440 else if(in->usecase == USECASE_AUDIO_RECORD_VOIP)
4441 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 -07004442 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
4443 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304444 else if(audio_extn_cin_attached_usecase(in->usecase))
4445 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004446
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004447 return in->config.period_size * in->af_period_multiplier *
4448 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004449}
4450
4451static uint32_t in_get_channels(const struct audio_stream *stream)
4452{
4453 struct stream_in *in = (struct stream_in *)stream;
4454
4455 return in->channel_mask;
4456}
4457
4458static audio_format_t in_get_format(const struct audio_stream *stream)
4459{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004460 struct stream_in *in = (struct stream_in *)stream;
4461
4462 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004463}
4464
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004465static int in_set_format(struct audio_stream *stream __unused,
4466 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004467{
4468 return -ENOSYS;
4469}
4470
4471static int in_standby(struct audio_stream *stream)
4472{
4473 struct stream_in *in = (struct stream_in *)stream;
4474 struct audio_device *adev = in->dev;
4475 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304476 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4477 stream, in->usecase, use_case_table[in->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07004478 bool do_stop = true;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304479
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004480 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004481 if (!in->standby && in->is_st_session) {
4482 ALOGD("%s: sound trigger pcm stop lab", __func__);
4483 audio_extn_sound_trigger_stop_lab(in);
4484 in->standby = 1;
4485 }
4486
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004487 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004488 if (adev->adm_deregister_stream)
4489 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
4490
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08004491 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004492 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08004493 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
4494 voice_extn_compress_voip_close_input_stream(stream);
4495 ALOGD("VOIP input entered standby");
Haynes Mathew George16081042017-05-31 17:16:49 -07004496 } else if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
4497 do_stop = in->capture_started;
4498 in->capture_started = false;
Zhou Songa8895042016-07-05 17:54:22 +08004499 } else {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304500 if (audio_extn_cin_attached_usecase(in->usecase))
4501 audio_extn_cin_stop_input_stream(in);
Zhou Songa8895042016-07-05 17:54:22 +08004502 if (in->pcm) {
4503 pcm_close(in->pcm);
4504 in->pcm = NULL;
4505 }
4506 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004507 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004508 if (in->pcm) {
4509 pcm_close(in->pcm);
4510 in->pcm = NULL;
4511 }
4512
4513 if (do_stop) {
4514 status = stop_input_stream(in);
4515 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08004516 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004517 }
4518 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07004519 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004520 return status;
4521}
4522
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004523static int in_dump(const struct audio_stream *stream __unused,
4524 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004525{
4526 return 0;
4527}
4528
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304529static void in_snd_mon_cb(void * stream, struct str_parms * parms)
4530{
4531 if (!stream || !parms)
4532 return;
4533
4534 struct stream_in *in = (struct stream_in *)stream;
4535 struct audio_device *adev = in->dev;
4536
4537 card_status_t status;
4538 int card;
4539 if (parse_snd_card_status(parms, &card, &status) < 0)
4540 return;
4541
4542 pthread_mutex_lock(&adev->lock);
4543 bool valid_cb = (card == adev->snd_card);
4544 pthread_mutex_unlock(&adev->lock);
4545
4546 if (!valid_cb)
4547 return;
4548
4549 lock_input_stream(in);
4550 if (in->card_status != status)
4551 in->card_status = status;
4552 pthread_mutex_unlock(&in->lock);
4553
4554 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
4555 use_case_table[in->usecase],
4556 status == CARD_STATUS_OFFLINE ? "offline" : "online");
4557
4558 // a better solution would be to report error back to AF and let
4559 // it put the stream to standby
4560 if (status == CARD_STATUS_OFFLINE)
4561 in_standby(&in->stream.common);
4562
4563 return;
4564}
4565
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004566static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
4567{
4568 struct stream_in *in = (struct stream_in *)stream;
4569 struct audio_device *adev = in->dev;
4570 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004571 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004572 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004573
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304574 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004575 parms = str_parms_create_str(kvpairs);
4576
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304577 if (!parms)
4578 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004579 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004580 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004581
4582 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
4583 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004584 val = atoi(value);
4585 /* no audio source uses val == 0 */
4586 if ((in->source != val) && (val != 0)) {
4587 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08004588 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
4589 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
4590 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08004591 (in->config.rate == 8000 || in->config.rate == 16000 ||
4592 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004593 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08004594 err = voice_extn_compress_voip_open_input_stream(in);
4595 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08004596 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08004597 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08004598 }
4599 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004600 }
4601 }
4602
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004603 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
4604 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004605 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004606 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004607 in->device = val;
4608 /* If recording is in progress, change the tx device to new device */
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004609 if (!in->standby && !in->is_st_session) {
4610 ALOGV("update input routing change");
Haynes Mathew George822b5492016-07-01 16:57:24 -07004611 if (adev->adm_on_routing_change)
4612 adev->adm_on_routing_change(adev->adm_data,
4613 in->capture_handle);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004614 ret = select_devices(adev, in->usecase);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004615 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004616 }
4617 }
4618
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304619 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
4620 if (err >= 0) {
4621 strlcpy(in->profile, value, sizeof(in->profile));
4622 ALOGV("updating stream profile with value '%s'", in->profile);
4623 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
4624 &adev->streams_input_cfg_list,
4625 in->device, in->flags, in->format,
4626 in->sample_rate, in->bit_width,
4627 in->profile, &in->app_type_cfg);
4628 }
4629
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004630 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004631 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004632
4633 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304634error:
Eric Laurent994a6932013-07-17 11:51:42 -07004635 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004636 return ret;
4637}
4638
4639static char* in_get_parameters(const struct audio_stream *stream,
4640 const char *keys)
4641{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004642 struct stream_in *in = (struct stream_in *)stream;
4643 struct str_parms *query = str_parms_create_str(keys);
4644 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004645 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004646
4647 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004648 if (reply) {
4649 str_parms_destroy(reply);
4650 }
4651 if (query) {
4652 str_parms_destroy(query);
4653 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004654 ALOGE("in_get_parameters: failed to create query or reply");
4655 return NULL;
4656 }
4657
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004658 ALOGV("%s: enter: keys - %s", __func__, keys);
4659
4660 voice_extn_in_get_parameters(in, query, reply);
4661
4662 str = str_parms_to_str(reply);
4663 str_parms_destroy(query);
4664 str_parms_destroy(reply);
4665
4666 ALOGV("%s: exit: returns - %s", __func__, str);
4667 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004668}
4669
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004670static int in_set_gain(struct audio_stream_in *stream __unused,
4671 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004672{
4673 return 0;
4674}
4675
4676static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
4677 size_t bytes)
4678{
4679 struct stream_in *in = (struct stream_in *)stream;
4680 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05304681 int ret = -1;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304682 size_t bytes_read = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004683
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004684 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05304685
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07004686 if (in->is_st_session) {
4687 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
4688 /* Read from sound trigger HAL */
4689 audio_extn_sound_trigger_read(in, buffer, bytes);
4690 pthread_mutex_unlock(&in->lock);
4691 return bytes;
4692 }
4693
Haynes Mathew George16081042017-05-31 17:16:49 -07004694 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
4695 ret = -ENOSYS;
4696 goto exit;
4697 }
4698
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004699 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07004700 pthread_mutex_lock(&adev->lock);
4701 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
4702 ret = voice_extn_compress_voip_start_input_stream(in);
4703 else
4704 ret = start_input_stream(in);
4705 pthread_mutex_unlock(&adev->lock);
4706 if (ret != 0) {
4707 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004708 }
4709 in->standby = 0;
4710 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004711
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004712 // what's the duration requested by the client?
4713 long ns = 0;
4714
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304715 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004716 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
4717 in->config.rate;
4718
4719 request_in_focus(in, ns);
4720 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004721
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304722 if (audio_extn_cin_attached_usecase(in->usecase)) {
4723 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
4724 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304725 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004726 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304727 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07004728 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004729 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004730 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304731 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004732 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304733 /* data from DSP comes in 24_8 format, convert it to 8_24 */
4734 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
4735 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
4736 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304737 ret = -EINVAL;
4738 goto exit;
4739 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304740 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304741 ret = -errno;
4742 }
4743 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304744 /* bytes read is always set to bytes for non compress usecases */
4745 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004746 }
4747
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004748 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004749
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004750 /*
4751 * Instead of writing zeroes here, we could trust the hardware
4752 * to always provide zeroes when muted.
4753 */
Pavan Chikkala63964842014-12-04 10:48:28 +05304754 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
4755 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004756 memset(buffer, 0, bytes);
4757
4758exit:
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07004759 if (-ENETRESET == ret)
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304760 in->card_status = CARD_STATUS_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004761 pthread_mutex_unlock(&in->lock);
4762
4763 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05304764 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304765 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05304766 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304767 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05304768 in->standby = true;
4769 }
Sharad Sangled17c9122017-03-20 15:58:52 +05304770 if (!audio_extn_cin_attached_usecase(in->usecase)) {
4771 bytes_read = bytes;
4772 memset(buffer, 0, bytes);
4773 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004774 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004775 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05304776 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05304777 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004778 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304779 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004780}
4781
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004782static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004783{
4784 return 0;
4785}
4786
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004787static int add_remove_audio_effect(const struct audio_stream *stream,
4788 effect_handle_t effect,
4789 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004790{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004791 struct stream_in *in = (struct stream_in *)stream;
4792 int status = 0;
4793 effect_descriptor_t desc;
4794
4795 status = (*effect)->get_descriptor(effect, &desc);
4796 if (status != 0)
4797 return status;
4798
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004799 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004800 pthread_mutex_lock(&in->dev->lock);
4801 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
4802 in->enable_aec != enable &&
4803 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
4804 in->enable_aec = enable;
4805 if (!in->standby)
4806 select_devices(in->dev, in->usecase);
4807 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08004808 if (in->enable_ns != enable &&
4809 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
4810 in->enable_ns = enable;
4811 if (!in->standby)
4812 select_devices(in->dev, in->usecase);
4813 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004814 pthread_mutex_unlock(&in->dev->lock);
4815 pthread_mutex_unlock(&in->lock);
4816
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004817 return 0;
4818}
4819
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004820static int in_add_audio_effect(const struct audio_stream *stream,
4821 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004822{
Eric Laurent994a6932013-07-17 11:51:42 -07004823 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004824 return add_remove_audio_effect(stream, effect, true);
4825}
4826
4827static int in_remove_audio_effect(const struct audio_stream *stream,
4828 effect_handle_t effect)
4829{
Eric Laurent994a6932013-07-17 11:51:42 -07004830 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004831 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004832}
4833
Haynes Mathew George16081042017-05-31 17:16:49 -07004834static int in_stop(const struct audio_stream_in* stream)
4835{
4836 struct stream_in *in = (struct stream_in *)stream;
4837 struct audio_device *adev = in->dev;
4838
4839 int ret = -ENOSYS;
4840 ALOGV("%s", __func__);
4841 pthread_mutex_lock(&adev->lock);
4842 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
4843 in->capture_started && in->pcm != NULL) {
4844 pcm_stop(in->pcm);
4845 ret = stop_input_stream(in);
4846 in->capture_started = false;
4847 }
4848 pthread_mutex_unlock(&adev->lock);
4849 return ret;
4850}
4851
4852static int in_start(const struct audio_stream_in* stream)
4853{
4854 struct stream_in *in = (struct stream_in *)stream;
4855 struct audio_device *adev = in->dev;
4856 int ret = -ENOSYS;
4857
4858 ALOGV("%s in %p", __func__, in);
4859 pthread_mutex_lock(&adev->lock);
4860 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
4861 !in->capture_started && in->pcm != NULL) {
4862 if (!in->capture_started) {
4863 ret = start_input_stream(in);
4864 if (ret == 0) {
4865 in->capture_started = true;
4866 }
4867 }
4868 }
4869 pthread_mutex_unlock(&adev->lock);
4870 return ret;
4871}
4872
4873static int in_create_mmap_buffer(const struct audio_stream_in *stream,
4874 int32_t min_size_frames,
4875 struct audio_mmap_buffer_info *info)
4876{
4877 struct stream_in *in = (struct stream_in *)stream;
4878 struct audio_device *adev = in->dev;
4879 int ret = 0;
4880 unsigned int offset1;
4881 unsigned int frames1;
4882 const char *step = "";
4883
4884 pthread_mutex_lock(&adev->lock);
4885 ALOGV("%s in %p", __func__, in);
4886
4887 if (info == NULL || min_size_frames == 0) {
4888 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
4889 ret = -EINVAL;
4890 goto exit;
4891 }
4892 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
4893 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
4894 ALOGV("%s in %p", __func__, in);
4895 ret = -ENOSYS;
4896 goto exit;
4897 }
4898 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
4899 if (in->pcm_device_id < 0) {
4900 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
4901 __func__, in->pcm_device_id, in->usecase);
4902 ret = -EINVAL;
4903 goto exit;
4904 }
4905
4906 adjust_mmap_period_count(&in->config, min_size_frames);
4907
4908 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
4909 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
4910 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
4911 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
4912 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
4913 step = "open";
4914 ret = -ENODEV;
4915 goto exit;
4916 }
4917
4918 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
4919 if (ret < 0) {
4920 step = "begin";
4921 goto exit;
4922 }
4923 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
4924 info->burst_size_frames = in->config.period_size;
4925 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
4926
4927 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(in->pcm,
4928 info->buffer_size_frames));
4929
4930 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
4931 if (ret < 0) {
4932 step = "commit";
4933 goto exit;
4934 }
4935
4936 in->standby = false;
4937 ret = 0;
4938
4939 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
4940 __func__, info->shared_memory_address, info->buffer_size_frames);
4941
4942exit:
4943 if (ret != 0) {
4944 if (in->pcm == NULL) {
4945 ALOGE("%s: %s - %d", __func__, step, ret);
4946 } else {
4947 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
4948 pcm_close(in->pcm);
4949 in->pcm = NULL;
4950 }
4951 }
4952 pthread_mutex_unlock(&adev->lock);
4953 return ret;
4954}
4955
4956static int in_get_mmap_position(const struct audio_stream_in *stream,
4957 struct audio_mmap_position *position)
4958{
4959 struct stream_in *in = (struct stream_in *)stream;
4960 ALOGVV("%s", __func__);
4961 if (position == NULL) {
4962 return -EINVAL;
4963 }
4964 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
4965 return -ENOSYS;
4966 }
4967 if (in->pcm == NULL) {
4968 return -ENOSYS;
4969 }
4970 struct timespec ts = { 0, 0 };
4971 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
4972 if (ret < 0) {
4973 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
4974 return ret;
4975 }
4976 position->time_nanoseconds = ts.tv_sec*1000000000L + ts.tv_nsec;
4977 return 0;
4978}
4979
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304980int adev_open_output_stream(struct audio_hw_device *dev,
Haynes Mathew George16081042017-05-31 17:16:49 -07004981 audio_io_handle_t handle,
4982 audio_devices_t devices,
4983 audio_output_flags_t flags,
4984 struct audio_config *config,
4985 struct audio_stream_out **stream_out,
4986 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004987{
4988 struct audio_device *adev = (struct audio_device *)dev;
4989 struct stream_out *out;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05304990 int ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004991 audio_format_t format;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08004992 struct adsp_hdlr_stream_cfg hdlr_stream_cfg;
Manish Dewangan21a850a2017-08-14 12:03:55 +05304993 bool is_direct_passthough = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004994
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004995 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05304996
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004997 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
4998
Mingming Yin3a941d42016-02-17 18:08:05 -08004999 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
5000 stream_handle(%p)", __func__, config->format, config->sample_rate, config->channel_mask,
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305001 devices, flags, &out->stream);
5002
5003
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08005004 if (!out) {
5005 return -ENOMEM;
5006 }
5007
Haynes Mathew George204045b2015-02-25 20:32:03 -08005008 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005009 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305010 pthread_mutex_init(&out->compr_mute_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08005011 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
5012
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005013 if (devices == AUDIO_DEVICE_NONE)
5014 devices = AUDIO_DEVICE_OUT_SPEAKER;
5015
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005016 out->flags = flags;
5017 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07005018 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07005019 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005020 out->sample_rate = config->sample_rate;
Sachin Mohan Gadag3d09acd2017-06-19 12:43:44 +05305021 out->channel_mask = config->channel_mask;
Ramjee Singh5857aeb2017-08-03 19:18:50 +05305022 if (out->channel_mask == AUDIO_CHANNEL_NONE)
5023 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
5024 else
5025 out->supported_channel_masks[0] = out->channel_mask;
Eric Laurentc4aef752013-09-12 17:45:53 -07005026 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07005027 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08005028 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05305029 out->convert_buffer = NULL;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305030 out->started = 0;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305031 out->a2dp_compress_mute = false;
Alexy Joseph98988832017-01-13 14:56:59 -08005032 out->dynamic_pm_qos_enabled = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005033
Nikhil Laturkar26b690b2017-07-25 11:06:14 +05305034 if ((flags & AUDIO_OUTPUT_FLAG_BD) &&
Ben Romberger6c4d3812017-06-13 17:46:45 -07005035 (property_get_bool("audio.matrix.limiter.enable", false)))
5036 platform_set_device_params(out, DEVICE_PARAM_LIMITER_ID, 1);
5037
Mingming Yin3a941d42016-02-17 18:08:05 -08005038 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
5039 (flags & AUDIO_OUTPUT_FLAG_DIRECT)) {
5040 pthread_mutex_lock(&adev->lock);
5041 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
5042 ret = read_hdmi_sink_caps(out);
5043 pthread_mutex_unlock(&adev->lock);
5044 if (ret != 0) {
5045 if (ret == -ENOSYS) {
5046 /* ignore and go with default */
5047 ret = 0;
5048 } else {
5049 ALOGE("error reading hdmi sink caps");
5050 goto error_open;
5051 }
5052 }
5053 }
5054
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005055 /* Init use case and pcm_config */
Nikhil Latukar2e6f6242017-08-15 13:37:07 +05305056#ifndef COMPRES_ENABLED
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005057 if (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX) &&
5058 (out->sample_rate == 8000 || out->sample_rate == 16000 ||
5059 out->sample_rate == 32000 || out->sample_rate == 48000)) {
5060 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_MONO;
5061 out->channel_mask = AUDIO_CHANNEL_OUT_MONO;
5062 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
5063
5064 out->config = default_pcm_config_voip_copp;
5065 out->config.period_size = VOIP_IO_BUF_SIZE(out->sample_rate, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
5066 out->config.rate = out->sample_rate;
5067
5068#else
Nikhil Latukar2e6f6242017-08-15 13:37:07 +05305069 } 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 -08005070 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08005071 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005072 ret = voice_extn_compress_voip_open_output_stream(out);
5073 if (ret != 0) {
5074 ALOGE("%s: Compress voip output cannot be opened, error:%d",
5075 __func__, ret);
5076 goto error_open;
5077 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005078#endif
vivek mehta0ea887a2015-08-26 14:01:20 -07005079 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05305080 (out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305081 pthread_mutex_lock(&adev->lock);
5082 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
5083 pthread_mutex_unlock(&adev->lock);
5084
5085 // reject offload during card offline to allow
5086 // fallback to s/w paths
5087 if (offline) {
5088 ret = -ENODEV;
5089 goto error_open;
5090 }
vivek mehta0ea887a2015-08-26 14:01:20 -07005091
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005092 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
5093 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
5094 ALOGE("%s: Unsupported Offload information", __func__);
5095 ret = -EINVAL;
5096 goto error_open;
5097 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005098
Mingming Yin3a941d42016-02-17 18:08:05 -08005099 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005100 if(config->offload_info.format == 0)
5101 config->offload_info.format = out->supported_formats[0];
Mingming Yin3a941d42016-02-17 18:08:05 -08005102 if (config->offload_info.sample_rate == 0)
5103 config->offload_info.sample_rate = out->supported_sample_rates[0];
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005104 }
5105
Mingming Yin90310102013-11-13 16:57:00 -08005106 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305107 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07005108 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005109 ret = -EINVAL;
5110 goto error_open;
5111 }
5112
Ben Romberger0f8c87b2017-05-24 17:41:11 -07005113 /* TrueHD only supported for 48k multiples (48k, 96k, 192k) */
5114 if ((config->offload_info.format == AUDIO_FORMAT_DOLBY_TRUEHD) &&
5115 (audio_extn_passthru_is_passthrough_stream(out)) &&
5116 !((config->sample_rate == 48000) ||
5117 (config->sample_rate == 96000) ||
5118 (config->sample_rate == 192000))) {
5119 ALOGE("%s: Unsupported sample rate %d for audio format %x",
5120 __func__, config->sample_rate, config->offload_info.format);
5121 ret = -EINVAL;
5122 goto error_open;
5123 }
5124
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005125 out->compr_config.codec = (struct snd_codec *)
5126 calloc(1, sizeof(struct snd_codec));
5127
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005128 if (!out->compr_config.codec) {
5129 ret = -ENOMEM;
5130 goto error_open;
5131 }
5132
Dhananjay Kumarac341582017-02-23 23:42:25 +05305133 out->stream.pause = out_pause;
5134 out->stream.resume = out_resume;
5135 out->stream.flush = out_flush;
5136 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Mingming Yin21d60472015-09-30 13:56:25 -07005137 out->stream.set_callback = out_set_callback;
Mingming Yin21d60472015-09-30 13:56:25 -07005138 out->stream.drain = out_drain;
Dhananjay Kumarac341582017-02-23 23:42:25 +05305139 out->usecase = get_offload_usecase(adev, true /* is_compress */);
vivek mehta446c3962015-09-14 10:57:35 -07005140 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
Dhananjay Kumarac341582017-02-23 23:42:25 +05305141 } else {
5142 out->usecase = get_offload_usecase(adev, false /* is_compress */);
5143 ALOGV("non-offload DIRECT_usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07005144 }
vivek mehta446c3962015-09-14 10:57:35 -07005145
5146 if (out->usecase == USECASE_INVALID) {
Mingming Yin3a941d42016-02-17 18:08:05 -08005147 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
5148 config->format == 0 && config->sample_rate == 0 &&
5149 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07005150 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08005151 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
5152 } else {
5153 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
5154 ret = -EEXIST;
5155 goto error_open;
5156 }
vivek mehta446c3962015-09-14 10:57:35 -07005157 }
5158
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005159 if (config->offload_info.channel_mask)
5160 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08005161 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005162 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08005163 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07005164 } else {
Dhananjay Kumarac341582017-02-23 23:42:25 +05305165 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT usecase");
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07005166 ret = -EINVAL;
5167 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08005168 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07005169
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07005170 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005171 out->sample_rate = config->offload_info.sample_rate;
5172
Mingming Yin3ee55c62014-08-04 14:23:35 -07005173 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005174
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305175 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
5176 if (audio_extn_is_dolby_format(config->offload_info.format)) {
5177 audio_extn_dolby_send_ddp_endp_params(adev);
5178 audio_extn_dolby_set_dmid(adev);
5179 }
vivek mehta0ea887a2015-08-26 14:01:20 -07005180
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005181 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08005182 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005183 out->compr_config.codec->bit_rate =
5184 config->offload_info.bit_rate;
5185 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05305186 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005187 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05305188 /* Update bit width only for non passthrough usecases.
5189 * For passthrough usecases, the output will always be opened @16 bit
5190 */
5191 if (!audio_extn_passthru_is_passthrough_stream(out))
5192 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Naresh Tanniruee3499a2017-01-05 14:05:35 +05305193
5194 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
5195 out->compr_config.codec->flags |= COMPRESSED_TIMESTAMP_FLAG;
5196 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->flags);
5197
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005198 /*TODO: Do we need to change it for passthrough */
5199 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005200
Manish Dewangana6fc5442015-08-24 20:30:31 +05305201 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
5202 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05305203 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05305204 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05305205 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
5206 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05305207
5208 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
5209 AUDIO_FORMAT_PCM) {
5210
5211 /*Based on platform support, configure appropriate alsa format for corresponding
5212 *hal input format.
5213 */
5214 out->compr_config.codec->format = hal_format_to_alsa(
5215 config->offload_info.format);
5216
Ashish Jain83a6cc22016-06-28 14:34:17 +05305217 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05305218 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05305219 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05305220
Dhananjay Kumarac341582017-02-23 23:42:25 +05305221 /*for direct non-compress playback populate bit_width based on selected alsa format as
Ashish Jainf1eaa582016-05-23 20:54:24 +05305222 *hal input format and alsa format might differ based on platform support.
5223 */
5224 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05305225 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05305226
5227 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
5228
5229 /* Check if alsa session is configured with the same format as HAL input format,
5230 * if not then derive correct fragment size needed to accomodate the
5231 * conversion of HAL input format to alsa format.
5232 */
5233 audio_extn_utils_update_direct_pcm_fragment_size(out);
5234
5235 /*if hal input and output fragment size is different this indicates HAL input format is
5236 *not same as the alsa format
5237 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05305238 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05305239 /*Allocate a buffer to convert input data to the alsa configured format.
5240 *size of convert buffer is equal to the size required to hold one fragment size
5241 *worth of pcm data, this is because flinger does not write more than fragment_size
5242 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05305243 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
5244 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05305245 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
5246 ret = -ENOMEM;
5247 goto error_open;
5248 }
5249 }
5250 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
5251 out->compr_config.fragment_size =
5252 audio_extn_passthru_get_buffer_size(&config->offload_info);
5253 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
5254 } else {
5255 out->compr_config.fragment_size =
5256 platform_get_compress_offload_buffer_size(&config->offload_info);
5257 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
5258 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07005259
Naresh Tanniruee3499a2017-01-05 14:05:35 +05305260 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
5261 out->compr_config.fragment_size += sizeof(struct snd_codec_metadata);
5262 }
Amit Shekhar6f461b12014-08-01 14:52:58 -07005263 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05305264 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07005265
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05305266 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
5267 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
5268 }
5269
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005270 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
5271 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005272
Manish Dewangan69426c82017-01-30 17:35:36 +05305273 if ((flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) &&
5274 (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) {
5275 out->render_mode = RENDER_MODE_AUDIO_STC_MASTER;
5276 } else if(flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
5277 out->render_mode = RENDER_MODE_AUDIO_MASTER;
5278 } else {
5279 out->render_mode = RENDER_MODE_AUDIO_NO_TIMESTAMP;
5280 }
Alexy Josephaa54c872014-12-03 02:46:47 -08005281
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05305282 memset(&out->channel_map_param, 0,
5283 sizeof(struct audio_out_channel_map_param));
5284
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005285 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305286 out->send_next_track_params = false;
5287 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08005288 out->offload_state = OFFLOAD_STATE_IDLE;
5289 out->playback_started = 0;
5290
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005291 audio_extn_dts_create_state_notifier_node(out->usecase);
5292
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005293 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
5294 __func__, config->offload_info.version,
5295 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05305296
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305297 /* Check if DSD audio format is supported in codec
5298 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305299 */
5300
5301 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305302 (!platform_check_codec_dsd_support(adev->platform) ||
5303 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305304 ret = -EINVAL;
5305 goto error_open;
5306 }
5307
Ashish Jain5106d362016-05-11 19:23:33 +05305308 /* Disable gapless if any of the following is true
5309 * passthrough playback
5310 * AV playback
Dhananjay Kumarac341582017-02-23 23:42:25 +05305311 * non compressed Direct playback
Ashish Jain5106d362016-05-11 19:23:33 +05305312 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305313 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305314 (config->format == AUDIO_FORMAT_DSD) ||
Naresh Tanniru928f0862017-04-07 16:44:23 -07005315 (config->format == AUDIO_FORMAT_IEC61937) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305316 config->offload_info.has_video ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05305317 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05305318 check_and_set_gapless_mode(adev, false);
5319 } else
5320 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07005321
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305322 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07005323 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
5324 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305325 if (config->format == AUDIO_FORMAT_DSD) {
5326 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
5327 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
5328 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07005329
5330 create_offload_callback_thread(out);
5331
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07005332 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05305333 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07005334 if (ret != 0) {
5335 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
5336 __func__, ret);
5337 goto error_open;
5338 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005339 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
5340 if (config->sample_rate == 0)
5341 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
5342 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
5343 config->sample_rate != 8000) {
5344 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
5345 ret = -EINVAL;
5346 goto error_open;
5347 }
5348 out->sample_rate = config->sample_rate;
5349 out->config.rate = config->sample_rate;
5350 if (config->format == AUDIO_FORMAT_DEFAULT)
5351 config->format = AUDIO_FORMAT_PCM_16_BIT;
5352 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
5353 config->format = AUDIO_FORMAT_PCM_16_BIT;
5354 ret = -EINVAL;
5355 goto error_open;
5356 }
5357 out->format = config->format;
5358 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
5359 out->config = pcm_config_afe_proxy_playback;
5360 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07005361 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05305362 unsigned int channels = 0;
5363 /*Update config params to default if not set by the caller*/
5364 if (config->sample_rate == 0)
5365 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
5366 if (config->channel_mask == AUDIO_CHANNEL_NONE)
5367 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
5368 if (config->format == AUDIO_FORMAT_DEFAULT)
5369 config->format = AUDIO_FORMAT_PCM_16_BIT;
5370
5371 channels = audio_channel_count_from_out_mask(out->channel_mask);
5372
Varun Balaraje49253e2017-07-06 19:48:56 +05305373 if (out->flags & AUDIO_OUTPUT_FLAG_INTERACTIVE) {
5374 out->usecase = get_interactive_usecase(adev);
5375 out->config = pcm_config_low_latency;
5376 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
Ashish Jain83a6cc22016-06-28 14:34:17 +05305377 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005378 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
5379 out->flags);
5380 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Haynes Mathew George16081042017-05-31 17:16:49 -07005381 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
5382 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
5383 out->config = pcm_config_mmap_playback;
5384 out->stream.start = out_start;
5385 out->stream.stop = out_stop;
5386 out->stream.create_mmap_buffer = out_create_mmap_buffer;
5387 out->stream.get_mmap_position = out_get_mmap_position;
Ashish Jain83a6cc22016-06-28 14:34:17 +05305388 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
5389 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
Alexy Joseph98988832017-01-13 14:56:59 -08005390 out->dynamic_pm_qos_enabled = property_get_bool("vendor.audio.dynamic.qos.enable", false);
5391 if (!out->dynamic_pm_qos_enabled) {
5392 ALOGI("%s: dynamic qos voting not enabled for platform", __func__);
5393 } else {
5394 ALOGI("%s: dynamic qos voting enabled for platform", __func__);
5395 //the mixer path will be a string similar to "low-latency-playback resume"
5396 strlcpy(out->pm_qos_mixer_path, use_case_table[out->usecase], MAX_MIXER_PATH_LEN);
5397 strlcat(out->pm_qos_mixer_path,
5398 " resume", MAX_MIXER_PATH_LEN);
5399 ALOGI("%s: created %s pm_qos_mixer_path" , __func__,
5400 out->pm_qos_mixer_path);
5401 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05305402 out->config = pcm_config_low_latency;
5403 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
5404 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
5405 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05305406 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
5407 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
5408 if (out->config.period_size <= 0) {
5409 ALOGE("Invalid configuration period size is not valid");
5410 ret = -EINVAL;
5411 goto error_open;
5412 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05305413 } else {
5414 /* primary path is the default path selected if no other outputs are available/suitable */
5415 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
5416 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
5417 }
5418 out->hal_ip_format = format = out->format;
5419 out->config.format = hal_format_to_pcm(out->hal_ip_format);
5420 out->hal_op_format = pcm_format_to_hal(out->config.format);
5421 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
5422 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07005423 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05305424 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05305425 if (out->hal_ip_format != out->hal_op_format) {
5426 uint32_t buffer_size = out->config.period_size *
5427 format_to_bitwidth_table[out->hal_op_format] *
5428 out->config.channels;
5429 out->convert_buffer = calloc(1, buffer_size);
5430 if (out->convert_buffer == NULL){
5431 ALOGE("Allocation failed for convert buffer for size %d",
5432 out->compr_config.fragment_size);
5433 ret = -ENOMEM;
5434 goto error_open;
5435 }
5436 ALOGD("Convert buffer allocated of size %d", buffer_size);
5437 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005438 }
5439
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08005440 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
5441 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05305442
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005443 /* TODO remove this hardcoding and check why width is zero*/
5444 if (out->bit_width == 0)
5445 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05305446 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07005447 &adev->streams_output_cfg_list,
Preetam Singh Ranawat4277a5a2017-01-18 19:02:24 +05305448 devices, out->flags, format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305449 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05305450 &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08005451 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
5452 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
5453 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08005454 if(adev->primary_output == NULL)
5455 adev->primary_output = out;
5456 else {
5457 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005458 ret = -EEXIST;
5459 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08005460 }
5461 }
5462
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005463 /* Check if this usecase is already existing */
5464 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07005465 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
5466 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005467 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005468 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005469 ret = -EEXIST;
5470 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005471 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08005472
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005473 pthread_mutex_unlock(&adev->lock);
5474
5475 out->stream.common.get_sample_rate = out_get_sample_rate;
5476 out->stream.common.set_sample_rate = out_set_sample_rate;
5477 out->stream.common.get_buffer_size = out_get_buffer_size;
5478 out->stream.common.get_channels = out_get_channels;
5479 out->stream.common.get_format = out_get_format;
5480 out->stream.common.set_format = out_set_format;
5481 out->stream.common.standby = out_standby;
5482 out->stream.common.dump = out_dump;
5483 out->stream.common.set_parameters = out_set_parameters;
5484 out->stream.common.get_parameters = out_get_parameters;
5485 out->stream.common.add_audio_effect = out_add_audio_effect;
5486 out->stream.common.remove_audio_effect = out_remove_audio_effect;
5487 out->stream.get_latency = out_get_latency;
5488 out->stream.set_volume = out_set_volume;
5489 out->stream.write = out_write;
5490 out->stream.get_render_position = out_get_render_position;
5491 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005492 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005493
Haynes Mathew George16081042017-05-31 17:16:49 -07005494 if (out->realtime)
5495 out->af_period_multiplier = af_period_multiplier;
5496 else
5497 out->af_period_multiplier = 1;
5498
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005499 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07005500 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005501 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005502
5503 config->format = out->stream.common.get_format(&out->stream.common);
5504 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
5505 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
5506
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305507 /*
5508 By locking output stream before registering, we allow the callback
5509 to update stream's state only after stream's initial state is set to
5510 adev state.
5511 */
5512 lock_output_stream(out);
5513 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
5514 pthread_mutex_lock(&adev->lock);
5515 out->card_status = adev->card_status;
5516 pthread_mutex_unlock(&adev->lock);
5517 pthread_mutex_unlock(&out->lock);
5518
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005519 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305520 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07005521 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005522
5523 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
5524 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
5525 popcount(out->channel_mask), out->playback_started);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005526 /* setup a channel for client <--> adsp communication for stream events */
Manish Dewangan21a850a2017-08-14 12:03:55 +05305527 is_direct_passthough = audio_extn_passthru_is_direct_passthrough(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005528 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Naresh Tanniru85819452017-05-04 18:55:45 -07005529 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) ||
Manish Dewangan21a850a2017-08-14 12:03:55 +05305530 (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false))) {
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005531 hdlr_stream_cfg.pcm_device_id = platform_get_pcm_device_id(
5532 out->usecase, PCM_PLAYBACK);
5533 hdlr_stream_cfg.flags = out->flags;
5534 hdlr_stream_cfg.type = PCM_PLAYBACK;
5535 ret = audio_extn_adsp_hdlr_stream_open(&out->adsp_hdlr_stream_handle,
5536 &hdlr_stream_cfg);
5537 if (ret) {
5538 ALOGE("%s: adsp_hdlr_stream_open failed %d",__func__, ret);
5539 out->adsp_hdlr_stream_handle = NULL;
5540 }
5541 }
Manish Dewangan21a850a2017-08-14 12:03:55 +05305542 if (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false)) {
Vidyakumar Athota2062f912017-06-27 14:46:15 -07005543 ret = audio_extn_ip_hdlr_intf_init(&out->ip_hdlr_handle, NULL, NULL, adev, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07005544 if (ret < 0) {
5545 ALOGE("%s: audio_extn_ip_hdlr_intf_init failed %d",__func__, ret);
5546 out->ip_hdlr_handle = NULL;
5547 }
5548 }
Eric Laurent994a6932013-07-17 11:51:42 -07005549 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005550 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005551
5552error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05305553 if (out->convert_buffer)
5554 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005555 free(out);
5556 *stream_out = NULL;
5557 ALOGD("%s: exit: ret %d", __func__, ret);
5558 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005559}
5560
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305561void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005562 struct audio_stream_out *stream)
5563{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005564 struct stream_out *out = (struct stream_out *)stream;
5565 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005566 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005567
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305568 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
5569
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305570 // must deregister from sndmonitor first to prevent races
5571 // between the callback and close_stream
5572 audio_extn_snd_mon_unregister_listener(out);
5573
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005574 /* close adsp hdrl session before standby */
5575 if (out->adsp_hdlr_stream_handle) {
5576 ret = audio_extn_adsp_hdlr_stream_close(out->adsp_hdlr_stream_handle);
5577 if (ret)
5578 ALOGE("%s: adsp_hdlr_stream_close failed %d",__func__, ret);
5579 out->adsp_hdlr_stream_handle = NULL;
5580 }
5581
Manish Dewangan21a850a2017-08-14 12:03:55 +05305582 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07005583 audio_extn_ip_hdlr_intf_deinit(out->ip_hdlr_handle);
5584 out->ip_hdlr_handle = NULL;
5585 }
5586
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005587 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305588 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005589 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305590 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305591 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005592 if(ret != 0)
5593 ALOGE("%s: Compress voip output cannot be closed, error:%d",
5594 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005595 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005596 out_standby(&stream->common);
5597
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005598 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005599 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005600 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005601 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005602 if (out->compr_config.codec != NULL)
5603 free(out->compr_config.codec);
5604 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005605
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305606 out->a2dp_compress_mute = false;
5607
Varun Balaraje49253e2017-07-06 19:48:56 +05305608 if (is_interactive_usecase(out->usecase))
5609 free_interactive_usecase(adev, out->usecase);
5610
Ashish Jain83a6cc22016-06-28 14:34:17 +05305611 if (out->convert_buffer != NULL) {
5612 free(out->convert_buffer);
5613 out->convert_buffer = NULL;
5614 }
5615
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005616 if (adev->voice_tx_output == out)
5617 adev->voice_tx_output = NULL;
5618
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05305619 if (adev->primary_output == out)
5620 adev->primary_output = NULL;
5621
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005622 pthread_cond_destroy(&out->cond);
5623 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005624 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07005625 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005626}
5627
5628static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
5629{
5630 struct audio_device *adev = (struct audio_device *)dev;
5631 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005632 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005633 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005634 int ret;
5635 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005636
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08005637 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005638 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005639
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305640 if (!parms)
5641 goto error;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305642
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305643 ret = str_parms_get_str(parms, "BT_SCO", value, sizeof(value));
5644 if (ret >= 0) {
5645 /* When set to false, HAL should disable EC and NS */
5646 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
5647 adev->bt_sco_on = true;
5648 else
5649 adev->bt_sco_on = false;
5650 }
5651
Naresh Tanniru4c630392014-05-12 01:05:52 +05305652 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005653 status = voice_set_parameters(adev, parms);
5654 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08005655 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005656
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005657 status = platform_set_parameters(adev->platform, parms);
5658 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08005659 goto done;
5660
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005661 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
5662 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07005663 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005664 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
5665 adev->bluetooth_nrec = true;
5666 else
5667 adev->bluetooth_nrec = false;
5668 }
5669
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005670 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
5671 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005672 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
5673 adev->screen_off = false;
5674 else
5675 adev->screen_off = true;
5676 }
5677
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005678 ret = str_parms_get_int(parms, "rotation", &val);
5679 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005680 bool reverse_speakers = false;
5681 switch(val) {
5682 // FIXME: note that the code below assumes that the speakers are in the correct placement
5683 // relative to the user when the device is rotated 90deg from its default rotation. This
5684 // assumption is device-specific, not platform-specific like this code.
5685 case 270:
5686 reverse_speakers = true;
5687 break;
5688 case 0:
5689 case 90:
5690 case 180:
5691 break;
5692 default:
5693 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005694 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005695 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005696 if (status == 0) {
5697 if (adev->speaker_lr_swap != reverse_speakers) {
5698 adev->speaker_lr_swap = reverse_speakers;
5699 // only update the selected device if there is active pcm playback
5700 struct audio_usecase *usecase;
5701 struct listnode *node;
5702 list_for_each(node, &adev->usecase_list) {
5703 usecase = node_to_item(node, struct audio_usecase, list);
5704 if (usecase->type == PCM_PLAYBACK) {
5705 select_devices(adev, usecase->id);
5706 break;
5707 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005708 }
5709 }
5710 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005711 }
5712
Mingming Yin514a8bc2014-07-29 15:22:21 -07005713 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
5714 if (ret >= 0) {
5715 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
5716 adev->bt_wb_speech_enabled = true;
5717 else
5718 adev->bt_wb_speech_enabled = false;
5719 }
5720
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07005721 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
5722 if (ret >= 0) {
5723 val = atoi(value);
5724 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07005725 ALOGV("cache new ext disp type and edid");
5726 ret = platform_get_ext_disp_type(adev->platform);
5727 if (ret < 0) {
5728 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Weiyin Jiangf50ce4e2016-10-13 14:22:03 +08005729 status = ret;
5730 goto done;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07005731 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07005732 platform_cache_edid(adev->platform);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08005733 } else if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
yidongh86ca17d2016-08-30 18:28:01 +08005734 !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
vivek mehta344576a2016-04-12 18:56:03 -07005735 /*
5736 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
5737 * Per AudioPolicyManager, USB device is higher priority than WFD.
5738 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
5739 * If WFD use case occupies AFE proxy, it may result unintended behavior while
5740 * starting voice call on USB
5741 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08005742 ret = str_parms_get_str(parms, "card", value, sizeof(value));
5743 if (ret >= 0) {
Kuirong Wang27152a12016-11-11 10:20:30 -08005744 audio_extn_usb_add_device(AUDIO_DEVICE_OUT_USB_DEVICE, atoi(value));
5745 audio_extn_usb_add_device(AUDIO_DEVICE_IN_USB_DEVICE, atoi(value));
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08005746 }
vivek mehta344576a2016-04-12 18:56:03 -07005747 ALOGV("detected USB connect .. disable proxy");
5748 adev->allow_afe_proxy_usage = false;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07005749 }
5750 }
5751
5752 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
5753 if (ret >= 0) {
5754 val = atoi(value);
Garmond Leunge3b6d482016-10-25 16:48:01 -07005755 /*
5756 * The HDMI / Displayport disconnect handling has been moved to
5757 * audio extension to ensure that its parameters are not
5758 * invalidated prior to updating sysfs of the disconnect event
5759 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
5760 */
5761 if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
yidongh86ca17d2016-08-30 18:28:01 +08005762 !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08005763 ret = str_parms_get_str(parms, "card", value, sizeof(value));
5764 if (ret >= 0) {
Ashish Jain3e37a702016-11-25 12:27:15 +05305765 audio_extn_usb_remove_device(AUDIO_DEVICE_OUT_USB_DEVICE, atoi(value));
5766 audio_extn_usb_remove_device(AUDIO_DEVICE_IN_USB_DEVICE, atoi(value));
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08005767 }
vivek mehta344576a2016-04-12 18:56:03 -07005768 ALOGV("detected USB disconnect .. enable proxy");
5769 adev->allow_afe_proxy_usage = true;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07005770 }
5771 }
5772
Naresh Tanniru9d027a62015-03-13 01:32:10 +05305773 ret = str_parms_get_str(parms,"reconfigA2dp", value, sizeof(value));
5774 if (ret >= 0) {
5775 struct audio_usecase *usecase;
5776 struct listnode *node;
5777 list_for_each(node, &adev->usecase_list) {
5778 usecase = node_to_item(node, struct audio_usecase, list);
5779 if ((usecase->type == PCM_PLAYBACK) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07005780 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP)){
Naresh Tanniru9d027a62015-03-13 01:32:10 +05305781 ALOGD("reconfigure a2dp... forcing device switch");
Weiyin Jiang425180d2017-06-05 16:40:23 +08005782
5783 pthread_mutex_unlock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05305784 lock_output_stream(usecase->stream.out);
Weiyin Jiang425180d2017-06-05 16:40:23 +08005785 pthread_mutex_lock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05305786 audio_extn_a2dp_set_handoff_mode(true);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05305787 //force device switch to re configure encoder
5788 select_devices(adev, usecase->id);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05305789 audio_extn_a2dp_set_handoff_mode(false);
5790 pthread_mutex_unlock(&usecase->stream.out->lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05305791 break;
5792 }
5793 }
5794 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08005795
5796 //handle vr audio setparam
5797 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
5798 value, sizeof(value));
5799 if (ret >= 0) {
5800 ALOGI("Setting vr mode to be %s", value);
5801 if (!strncmp(value, "true", 4)) {
5802 adev->vr_audio_mode_enabled = true;
5803 ALOGI("Setting vr mode to true");
5804 } else if (!strncmp(value, "false", 5)) {
5805 adev->vr_audio_mode_enabled = false;
5806 ALOGI("Setting vr mode to false");
5807 } else {
5808 ALOGI("wrong vr mode set");
5809 }
5810 }
5811
Naresh Tannirucd2353e2016-08-19 00:37:25 +05305812 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08005813done:
5814 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08005815 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305816error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005817 ALOGV("%s: exit with code(%d)", __func__, status);
5818 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005819}
5820
5821static char* adev_get_parameters(const struct audio_hw_device *dev,
5822 const char *keys)
5823{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07005824 struct audio_device *adev = (struct audio_device *)dev;
5825 struct str_parms *reply = str_parms_create();
5826 struct str_parms *query = str_parms_create_str(keys);
5827 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05305828 char value[256] = {0};
5829 int ret = 0;
5830
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005831 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005832 if (reply) {
5833 str_parms_destroy(reply);
5834 }
5835 if (query) {
5836 str_parms_destroy(query);
5837 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005838 ALOGE("adev_get_parameters: failed to create query or reply");
5839 return NULL;
5840 }
5841
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08005842 //handle vr audio getparam
5843
5844 ret = str_parms_get_str(query,
5845 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
5846 value, sizeof(value));
5847
5848 if (ret >= 0) {
5849 bool vr_audio_enabled = false;
5850 pthread_mutex_lock(&adev->lock);
5851 vr_audio_enabled = adev->vr_audio_mode_enabled;
5852 pthread_mutex_unlock(&adev->lock);
5853
5854 ALOGI("getting vr mode to %d", vr_audio_enabled);
5855
5856 if (vr_audio_enabled) {
5857 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
5858 "true");
5859 goto exit;
5860 } else {
5861 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
5862 "false");
5863 goto exit;
5864 }
5865 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07005866
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08005867 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07005868 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08005869 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07005870 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05305871 pthread_mutex_unlock(&adev->lock);
5872
Naresh Tannirud7205b62014-06-20 02:54:48 +05305873exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07005874 str = str_parms_to_str(reply);
5875 str_parms_destroy(query);
5876 str_parms_destroy(reply);
5877
5878 ALOGV("%s: exit: returns - %s", __func__, str);
5879 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005880}
5881
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005882static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005883{
5884 return 0;
5885}
5886
5887static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
5888{
Haynes Mathew George5191a852013-09-11 14:19:36 -07005889 int ret;
5890 struct audio_device *adev = (struct audio_device *)dev;
5891 pthread_mutex_lock(&adev->lock);
5892 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07005893 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07005894 pthread_mutex_unlock(&adev->lock);
5895 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005896}
5897
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005898static int adev_set_master_volume(struct audio_hw_device *dev __unused,
5899 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005900{
5901 return -ENOSYS;
5902}
5903
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005904static int adev_get_master_volume(struct audio_hw_device *dev __unused,
5905 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005906{
5907 return -ENOSYS;
5908}
5909
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005910static int adev_set_master_mute(struct audio_hw_device *dev __unused,
5911 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005912{
5913 return -ENOSYS;
5914}
5915
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005916static int adev_get_master_mute(struct audio_hw_device *dev __unused,
5917 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005918{
5919 return -ENOSYS;
5920}
5921
5922static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
5923{
5924 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005925
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005926 pthread_mutex_lock(&adev->lock);
5927 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005928 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005929 adev->mode = mode;
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08005930 if ((mode == AUDIO_MODE_NORMAL) && voice_is_in_call(adev)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005931 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07005932 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005933 adev->current_call_output = NULL;
5934 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005935 }
5936 pthread_mutex_unlock(&adev->lock);
5937 return 0;
5938}
5939
5940static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
5941{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08005942 int ret;
5943
5944 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08005945 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08005946 ret = voice_set_mic_mute((struct audio_device *)dev, state);
5947 pthread_mutex_unlock(&adev->lock);
5948
5949 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005950}
5951
5952static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
5953{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07005954 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005955 return 0;
5956}
5957
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005958static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005959 const struct audio_config *config)
5960{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005961 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005962
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07005963 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
5964 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005965}
5966
5967static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07005968 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005969 audio_devices_t devices,
5970 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005971 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305972 audio_input_flags_t flags,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005973 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07005974 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005975{
5976 struct audio_device *adev = (struct audio_device *)dev;
5977 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08005978 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005979 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07005980 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05305981 bool channel_mask_updated = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305982
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005983 *stream_in = NULL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05305984 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0) {
5985 ALOGE("%s: invalid input parameters", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005986 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05305987 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005988
5989 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005990
5991 if (!in) {
5992 ALOGE("failed to allocate input stream");
5993 return -ENOMEM;
5994 }
5995
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305996 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305997 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
5998 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07005999 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006000 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07006001
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006002 in->stream.common.get_sample_rate = in_get_sample_rate;
6003 in->stream.common.set_sample_rate = in_set_sample_rate;
6004 in->stream.common.get_buffer_size = in_get_buffer_size;
6005 in->stream.common.get_channels = in_get_channels;
6006 in->stream.common.get_format = in_get_format;
6007 in->stream.common.set_format = in_set_format;
6008 in->stream.common.standby = in_standby;
6009 in->stream.common.dump = in_dump;
6010 in->stream.common.set_parameters = in_set_parameters;
6011 in->stream.common.get_parameters = in_get_parameters;
6012 in->stream.common.add_audio_effect = in_add_audio_effect;
6013 in->stream.common.remove_audio_effect = in_remove_audio_effect;
6014 in->stream.set_gain = in_set_gain;
6015 in->stream.read = in_read;
6016 in->stream.get_input_frames_lost = in_get_input_frames_lost;
6017
6018 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07006019 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006020 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006021 in->standby = 1;
6022 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006023 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006024 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006025
Dhananjay Kumar973fc362017-01-09 18:48:15 +05306026 in->usecase = USECASE_AUDIO_RECORD;
6027 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Haynes Mathew George16081042017-05-31 17:16:49 -07006028 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
Dhananjay Kumar973fc362017-01-09 18:48:15 +05306029 is_low_latency = true;
6030#if LOW_LATENCY_CAPTURE_USE_CASE
6031 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
6032#endif
6033 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
6034 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006035 in->format = config->format;
Haynes Mathew George16081042017-05-31 17:16:49 -07006036 if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
6037 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
6038 in->realtime = 0;
6039 in->usecase = USECASE_AUDIO_RECORD_MMAP;
6040 in->config = pcm_config_mmap_capture;
6041 in->stream.start = in_start;
6042 in->stream.stop = in_stop;
6043 in->stream.create_mmap_buffer = in_create_mmap_buffer;
6044 in->stream.get_mmap_position = in_get_mmap_position;
6045 in->af_period_multiplier = 1;
6046 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
6047 } else if (in->realtime) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006048 in->config = pcm_config_audio_capture_rt;
6049 in->sample_rate = in->config.rate;
6050 in->af_period_multiplier = af_period_multiplier;
6051 } else {
6052 in->config = pcm_config_audio_capture;
6053 in->config.rate = config->sample_rate;
6054 in->sample_rate = config->sample_rate;
6055 in->af_period_multiplier = 1;
6056 }
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306057 in->bit_width = 16;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006058
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306059 /* restrict 24 bit capture for unprocessed source only
6060 * for other sources if 24 bit requested reject 24 and set 16 bit capture only
6061 */
6062 if (config->format == AUDIO_FORMAT_DEFAULT) {
6063 config->format = AUDIO_FORMAT_PCM_16_BIT;
6064 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
6065 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
6066 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
6067 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
6068 bool ret_error = false;
6069 in->bit_width = 24;
6070 /* 24 bit is restricted to UNPROCESSED source only,also format supported
6071 from HAL is 24_packed and 8_24
6072 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
6073 24_packed return error indicating supported format is 24_packed
6074 *> In case of any other source requesting 24 bit or float return error
6075 indicating format supported is 16 bit only.
6076
6077 on error flinger will retry with supported format passed
6078 */
6079 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
6080 (source != AUDIO_SOURCE_CAMCORDER)) {
6081 config->format = AUDIO_FORMAT_PCM_16_BIT;
6082 if (config->sample_rate > 48000)
6083 config->sample_rate = 48000;
6084 ret_error = true;
6085 } else if (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) {
6086 in->config.format = PCM_FORMAT_S24_3LE;
6087 } else if (config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
6088 in->config.format = PCM_FORMAT_S24_LE;
6089 } else {
6090 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
6091 ret_error = true;
6092 }
6093
6094 if (ret_error) {
6095 ret = -EINVAL;
6096 goto err_open;
6097 }
6098 }
6099
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05306100 /* Update config params with the requested sample rate and channels */
Dhanalakshmi Siddani0b1488e2016-09-06 12:58:42 +05306101 if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) &&
6102 (adev->mode != AUDIO_MODE_IN_CALL)) {
6103 ret = -EINVAL;
6104 goto err_open;
6105 }
6106
6107 if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) ||
6108 (in->device == AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006109 if (config->sample_rate == 0)
6110 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
6111 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
6112 config->sample_rate != 8000) {
6113 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
6114 ret = -EINVAL;
6115 goto err_open;
6116 }
6117 if (config->format == AUDIO_FORMAT_DEFAULT)
6118 config->format = AUDIO_FORMAT_PCM_16_BIT;
6119 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
6120 config->format = AUDIO_FORMAT_PCM_16_BIT;
6121 ret = -EINVAL;
6122 goto err_open;
6123 }
6124
6125 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
6126 in->config = pcm_config_afe_proxy_record;
6127 in->config.channels = channel_count;
6128 in->config.rate = config->sample_rate;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306129 in->sample_rate = config->sample_rate;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05306130 } else if (!audio_extn_check_and_set_multichannel_usecase(adev,
6131 in, config, &channel_mask_updated)) {
6132 if (channel_mask_updated == true) {
6133 ALOGD("%s: return error to retry with updated channel mask (%#x)",
6134 __func__, config->channel_mask);
6135 ret = -EINVAL;
6136 goto err_open;
6137 }
Naresh Tanniruc9093982015-10-16 18:05:29 +05306138 ALOGD("%s: created surround sound session succesfully",__func__);
Mingming Yine62d7842013-10-25 16:26:03 -07006139 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08006140 audio_extn_compr_cap_format_supported(config->format) &&
6141 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006142 audio_extn_compr_cap_init(in);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306143 } else if (audio_extn_cin_applicable_stream(in)) {
6144 ret = audio_extn_cin_configure_input_stream(in);
6145 if (ret)
6146 goto err_open;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07006147 } else {
6148 in->config.channels = channel_count;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006149 if (!in->realtime) {
6150 in->format = config->format;
6151 frame_size = audio_stream_in_frame_size(&in->stream);
6152 buffer_size = get_input_buffer_size(config->sample_rate,
6153 config->format,
6154 channel_count,
6155 is_low_latency);
6156 in->config.period_size = buffer_size / frame_size;
6157 }
6158
Vikram Panduranga93f080e2017-06-07 18:16:14 -07006159#ifndef COMPRESS_VOIP_ENABLED
6160 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
6161 (in->config.rate == 8000 || in->config.rate == 16000 ||
6162 in->config.rate == 32000 || in->config.rate == 48000) &&
6163 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
6164
6165 in->usecase = USECASE_AUDIO_RECORD_VOIP;
6166 in->config = default_pcm_config_voip_copp;
6167 in->config.period_size = VOIP_IO_BUF_SIZE(in->sample_rate, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
6168 in->config.rate = in->sample_rate;
6169#else
Vidyakumar Athota5c398212015-03-31 21:53:21 -07006170 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
Haynes Mathew George16081042017-05-31 17:16:49 -07006171 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
6172 voice_extn_compress_voip_is_active(in->dev)) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07006173 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08006174 (in->config.rate == 8000 || in->config.rate == 16000 ||
6175 in->config.rate == 32000 || in->config.rate == 48000) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07006176 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
6177 voice_extn_compress_voip_open_input_stream(in);
Vikram Panduranga93f080e2017-06-07 18:16:14 -07006178#endif
Vidyakumar Athota5c398212015-03-31 21:53:21 -07006179 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07006180 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006181
Dhananjay Kumard6d32152016-10-13 16:11:03 +05306182 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
6183 &adev->streams_input_cfg_list,
6184 devices, flags, in->format, in->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05306185 in->bit_width, in->profile, &in->app_type_cfg);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05306186
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006187 /* This stream could be for sound trigger lab,
6188 get sound trigger pcm if present */
6189 audio_extn_sound_trigger_check_and_get_session(in);
6190
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306191 lock_input_stream(in);
6192 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
6193 pthread_mutex_lock(&adev->lock);
6194 in->card_status = adev->card_status;
6195 pthread_mutex_unlock(&adev->lock);
6196 pthread_mutex_unlock(&in->lock);
6197
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006198 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07006199 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08006200 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006201
6202err_open:
6203 free(in);
6204 *stream_in = NULL;
6205 return ret;
6206}
6207
6208static void adev_close_input_stream(struct audio_hw_device *dev,
6209 struct audio_stream_in *stream)
6210{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006211 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07006212 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006213 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306214
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306215 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08006216
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306217 // must deregister from sndmonitor first to prevent races
6218 // between the callback and close_stream
6219 audio_extn_snd_mon_unregister_listener(stream);
6220
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05306221 /* Disable echo reference while closing input stream */
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07006222 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05306223
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006224 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306225 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006226 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306227 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006228 if (ret != 0)
6229 ALOGE("%s: Compress voip input cannot be closed, error:%d",
6230 __func__, ret);
6231 } else
6232 in_standby(&stream->common);
6233
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07006234 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07006235 audio_extn_ssr_deinit();
6236 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006237
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306238 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07006239 audio_extn_compr_cap_format_supported(in->config.format))
6240 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05306241
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306242 if (audio_extn_cin_attached_usecase(in->usecase))
6243 audio_extn_cin_close_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006244
Mingming Yinfd7607b2016-01-22 12:48:44 -08006245 if (in->is_st_session) {
6246 ALOGV("%s: sound trigger pcm stop lab", __func__);
6247 audio_extn_sound_trigger_stop_lab(in);
6248 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006249 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006250 return;
6251}
6252
Siddartha Shaik31b530e2017-05-19 15:26:33 +05306253int adev_create_audio_patch(struct audio_hw_device *dev,
6254 unsigned int num_sources,
6255 const struct audio_port_config *sources,
6256 unsigned int num_sinks,
6257 const struct audio_port_config *sinks,
6258 audio_patch_handle_t *handle)
6259{
6260
6261
6262 return audio_extn_hw_loopback_create_audio_patch(dev,
6263 num_sources,
6264 sources,
6265 num_sinks,
6266 sinks,
6267 handle);
6268
6269}
6270
6271int adev_release_audio_patch(struct audio_hw_device *dev,
6272 audio_patch_handle_t handle)
6273{
6274 return audio_extn_hw_loopback_release_audio_patch(dev, handle);
6275}
6276
6277int adev_get_audio_port(struct audio_hw_device *dev, struct audio_port *config)
6278{
6279 return audio_extn_hw_loopback_get_audio_port(dev, config);
6280}
6281
6282int adev_set_audio_port_config(struct audio_hw_device *dev,
6283 const struct audio_port_config *config)
6284{
6285 return audio_extn_hw_loopback_set_audio_port_config(dev, config);
6286}
6287
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006288static int adev_dump(const audio_hw_device_t *device __unused,
6289 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006290{
6291 return 0;
6292}
6293
6294static int adev_close(hw_device_t *device)
6295{
6296 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07006297
6298 if (!adev)
6299 return 0;
6300
6301 pthread_mutex_lock(&adev_init_lock);
6302
6303 if ((--audio_device_ref_count) == 0) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306304 audio_extn_snd_mon_unregister_listener(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006305 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08006306 audio_extn_listen_deinit(adev);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05306307 audio_extn_utils_release_streams_cfg_lists(
6308 &adev->streams_output_cfg_list,
6309 &adev->streams_input_cfg_list);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05306310 if (audio_extn_qaf_is_enabled())
6311 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07006312 audio_route_free(adev->audio_route);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08006313 audio_extn_gef_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07006314 free(adev->snd_dev_ref_cnt);
6315 platform_deinit(adev->platform);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006316 if (adev->adm_deinit)
6317 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306318 qahwi_deinit(device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006319 audio_extn_adsp_hdlr_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306320 audio_extn_snd_mon_deinit();
Siddartha Shaik44dd7702017-06-14 12:13:25 +05306321 audio_extn_hw_loopback_deinit(adev);
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +05306322 if (adev->device_cfg_params) {
6323 free(adev->device_cfg_params);
6324 adev->device_cfg_params = NULL;
6325 }
Kiran Kandi910e1862013-10-29 13:29:42 -07006326 free(device);
6327 adev = NULL;
6328 }
6329 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006330
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006331 return 0;
6332}
6333
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07006334/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
6335 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
6336 * just that it _might_ work.
6337 */
6338static int period_size_is_plausible_for_low_latency(int period_size)
6339{
6340 switch (period_size) {
6341 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07006342 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07006343 case 240:
6344 case 320:
6345 case 480:
6346 return 1;
6347 default:
6348 return 0;
6349 }
6350}
6351
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306352static void adev_snd_mon_cb(void *cookie, struct str_parms *parms)
6353{
6354 bool is_snd_card_status = false;
6355 bool is_ext_device_status = false;
6356 char value[32];
6357 int card = -1;
6358 card_status_t status;
6359
6360 if (cookie != adev || !parms)
6361 return;
6362
6363 if (!parse_snd_card_status(parms, &card, &status)) {
6364 is_snd_card_status = true;
6365 } else if (0 < str_parms_get_str(parms, "ext_audio_device", value, sizeof(value))) {
6366 is_ext_device_status = true;
6367 } else {
6368 // not a valid event
6369 return;
6370 }
6371
6372 pthread_mutex_lock(&adev->lock);
6373 if (card == adev->snd_card || is_ext_device_status) {
6374 if (is_snd_card_status && adev->card_status != status) {
6375 adev->card_status = status;
6376 platform_snd_card_update(adev->platform, status);
6377 audio_extn_fm_set_parameters(adev, parms);
6378 } else if (is_ext_device_status) {
6379 platform_set_parameters(adev->platform, parms);
6380 }
6381 }
6382 pthread_mutex_unlock(&adev->lock);
6383 return;
6384}
6385
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05306386/* out and adev lock held */
6387static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
6388{
6389 struct audio_usecase *uc_info;
6390 float left_p;
6391 float right_p;
6392 audio_devices_t devices;
6393
6394 uc_info = get_usecase_from_list(adev, out->usecase);
6395 if (uc_info == NULL) {
6396 ALOGE("%s: Could not find the usecase (%d) in the list",
6397 __func__, out->usecase);
6398 return -EINVAL;
6399 }
6400
6401 ALOGD("%s: enter: usecase(%d: %s)", __func__,
6402 out->usecase, use_case_table[out->usecase]);
6403
6404 if (restore) {
6405 // restore A2DP device for active usecases and unmute if required
6406 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
6407 (uc_info->out_snd_device != SND_DEVICE_OUT_BT_A2DP)) {
6408 ALOGD("%s: restoring A2dp and unmuting stream", __func__);
6409 select_devices(adev, uc_info->id);
6410 pthread_mutex_lock(&out->compr_mute_lock);
6411 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
6412 (out->a2dp_compress_mute)) {
6413 out->a2dp_compress_mute = false;
6414 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
6415 }
6416 pthread_mutex_unlock(&out->compr_mute_lock);
6417 }
6418 } else {
6419 // mute compress stream if suspended
6420 pthread_mutex_lock(&out->compr_mute_lock);
6421 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
6422 (!out->a2dp_compress_mute)) {
6423 if (!out->standby) {
6424 ALOGD("%s: selecting speaker and muting stream", __func__);
6425 devices = out->devices;
6426 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
6427 left_p = out->volume_l;
6428 right_p = out->volume_r;
6429 if (out->offload_state == OFFLOAD_STATE_PLAYING)
6430 compress_pause(out->compr);
6431 out_set_compr_volume(&out->stream, (float)0, (float)0);
6432 out->a2dp_compress_mute = true;
6433 select_devices(adev, out->usecase);
6434 if (out->offload_state == OFFLOAD_STATE_PLAYING)
6435 compress_resume(out->compr);
6436 out->devices = devices;
6437 out->volume_l = left_p;
6438 out->volume_r = right_p;
6439 }
6440 }
6441 pthread_mutex_unlock(&out->compr_mute_lock);
6442 }
6443 ALOGV("%s: exit", __func__);
6444 return 0;
6445}
6446
6447int check_a2dp_restore(struct audio_device *adev, struct stream_out *out, bool restore)
6448{
6449 int ret = 0;
6450
6451 lock_output_stream(out);
6452 pthread_mutex_lock(&adev->lock);
6453
6454 ret = check_a2dp_restore_l(adev, out, restore);
6455
6456 pthread_mutex_unlock(&adev->lock);
6457 pthread_mutex_unlock(&out->lock);
6458 return ret;
6459}
6460
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006461static int adev_open(const hw_module_t *module, const char *name,
6462 hw_device_t **device)
6463{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05306464 int ret;
6465
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08006466 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006467 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
6468
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07006469 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07006470 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07006471 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07006472 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07006473 ALOGD("%s: returning existing instance of adev", __func__);
6474 ALOGD("%s: exit", __func__);
6475 pthread_mutex_unlock(&adev_init_lock);
6476 return 0;
6477 }
6478
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006479 adev = calloc(1, sizeof(struct audio_device));
6480
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006481 if (!adev) {
6482 pthread_mutex_unlock(&adev_init_lock);
6483 return -ENOMEM;
6484 }
6485
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07006486 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
6487
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +05306488#ifdef DYNAMIC_LOG_ENABLED
6489 register_for_dynamic_logging("hal");
6490#endif
6491
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006492 adev->device.common.tag = HARDWARE_DEVICE_TAG;
6493 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
6494 adev->device.common.module = (struct hw_module_t *)module;
6495 adev->device.common.close = adev_close;
6496
6497 adev->device.init_check = adev_init_check;
6498 adev->device.set_voice_volume = adev_set_voice_volume;
6499 adev->device.set_master_volume = adev_set_master_volume;
6500 adev->device.get_master_volume = adev_get_master_volume;
6501 adev->device.set_master_mute = adev_set_master_mute;
6502 adev->device.get_master_mute = adev_get_master_mute;
6503 adev->device.set_mode = adev_set_mode;
6504 adev->device.set_mic_mute = adev_set_mic_mute;
6505 adev->device.get_mic_mute = adev_get_mic_mute;
6506 adev->device.set_parameters = adev_set_parameters;
6507 adev->device.get_parameters = adev_get_parameters;
6508 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
6509 adev->device.open_output_stream = adev_open_output_stream;
6510 adev->device.close_output_stream = adev_close_output_stream;
6511 adev->device.open_input_stream = adev_open_input_stream;
6512 adev->device.close_input_stream = adev_close_input_stream;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05306513 adev->device.create_audio_patch = adev_create_audio_patch;
6514 adev->device.release_audio_patch = adev_release_audio_patch;
6515 adev->device.get_audio_port = adev_get_audio_port;
6516 adev->device.set_audio_port_config = adev_set_audio_port_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006517 adev->device.dump = adev_dump;
6518
6519 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006520 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08006521 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08006522 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006523 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006524 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08006525 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -07006526 adev->allow_afe_proxy_usage = true;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306527 adev->bt_sco_on = false;
Eric Laurent07eeafd2013-10-06 12:52:49 -07006528 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07006529 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07006530 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08006531 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08006532 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006533 adev->offload_usecases_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05306534 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05306535 adev->perf_lock_opts[0] = 0x101;
6536 adev->perf_lock_opts[1] = 0x20E;
6537 adev->perf_lock_opts_size = 2;
Xiaojun Sang785b5da2017-08-03 15:52:29 +08006538 adev->dsp_bit_width_enforce_mode = 0;
Naresh Tanniru4c630392014-05-12 01:05:52 +05306539
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006540 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07006541 adev->platform = platform_init(adev);
6542 if (!adev->platform) {
6543 free(adev->snd_dev_ref_cnt);
6544 free(adev);
6545 ALOGE("%s: Failed to init platform data, aborting.", __func__);
6546 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08006547 pthread_mutex_unlock(&adev_init_lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05306548 pthread_mutex_destroy(&adev->lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07006549 return -EINVAL;
6550 }
Eric Laurentc4aef752013-09-12 17:45:53 -07006551
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05306552 if (audio_extn_qaf_is_enabled()) {
6553 ret = audio_extn_qaf_init(adev);
6554 if (ret < 0) {
6555 free(adev);
6556 ALOGE("%s: Failed to init platform data, aborting.", __func__);
6557 *device = NULL;
6558 pthread_mutex_unlock(&adev_init_lock);
6559 pthread_mutex_destroy(&adev->lock);
6560 return ret;
6561 }
6562
6563 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
6564 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
6565 }
6566
Eric Laurentc4aef752013-09-12 17:45:53 -07006567 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
6568 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
6569 if (adev->visualizer_lib == NULL) {
6570 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
6571 } else {
6572 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
6573 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08006574 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07006575 "visualizer_hal_start_output");
6576 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08006577 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07006578 "visualizer_hal_stop_output");
6579 }
6580 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +05306581 audio_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08006582 audio_extn_listen_init(adev, adev->snd_card);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08006583 audio_extn_gef_init(adev);
Siddartha Shaik44dd7702017-06-14 12:13:25 +05306584 audio_extn_hw_loopback_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07006585
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08006586 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
6587 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
6588 if (adev->offload_effects_lib == NULL) {
6589 ALOGE("%s: DLOPEN failed for %s", __func__,
6590 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
6591 } else {
6592 ALOGV("%s: DLOPEN successful for %s", __func__,
6593 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
6594 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +05306595 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08006596 "offload_effects_bundle_hal_start_output");
6597 adev->offload_effects_stop_output =
6598 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
6599 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006600 adev->offload_effects_set_hpx_state =
6601 (int (*)(bool))dlsym(adev->offload_effects_lib,
6602 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05306603 adev->offload_effects_get_parameters =
6604 (void (*)(struct str_parms *, struct str_parms *))
6605 dlsym(adev->offload_effects_lib,
6606 "offload_effects_bundle_get_parameters");
6607 adev->offload_effects_set_parameters =
6608 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
6609 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08006610 }
6611 }
6612
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006613 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
6614 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
6615 if (adev->adm_lib == NULL) {
6616 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
6617 } else {
6618 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
6619 adev->adm_init = (adm_init_t)
6620 dlsym(adev->adm_lib, "adm_init");
6621 adev->adm_deinit = (adm_deinit_t)
6622 dlsym(adev->adm_lib, "adm_deinit");
6623 adev->adm_register_input_stream = (adm_register_input_stream_t)
6624 dlsym(adev->adm_lib, "adm_register_input_stream");
6625 adev->adm_register_output_stream = (adm_register_output_stream_t)
6626 dlsym(adev->adm_lib, "adm_register_output_stream");
6627 adev->adm_deregister_stream = (adm_deregister_stream_t)
6628 dlsym(adev->adm_lib, "adm_deregister_stream");
6629 adev->adm_request_focus = (adm_request_focus_t)
6630 dlsym(adev->adm_lib, "adm_request_focus");
6631 adev->adm_abandon_focus = (adm_abandon_focus_t)
6632 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006633 adev->adm_set_config = (adm_set_config_t)
6634 dlsym(adev->adm_lib, "adm_set_config");
6635 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
6636 dlsym(adev->adm_lib, "adm_request_focus_v2");
6637 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
6638 dlsym(adev->adm_lib, "adm_is_noirq_avail");
6639 adev->adm_on_routing_change = (adm_on_routing_change_t)
6640 dlsym(adev->adm_lib, "adm_on_routing_change");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006641 }
6642 }
6643
Mingming Yin514a8bc2014-07-29 15:22:21 -07006644 adev->bt_wb_speech_enabled = false;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08006645 //initialize this to false for now,
6646 //this will be set to true through set param
6647 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -07006648
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07006649 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006650 *device = &adev->device.common;
Xiaojun Sang785b5da2017-08-03 15:52:29 +08006651 adev->dsp_bit_width_enforce_mode =
6652 adev_init_dsp_bit_width_enforce_mode(adev->mixer);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006653
Dhananjay Kumard6d32152016-10-13 16:11:03 +05306654 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
6655 &adev->streams_output_cfg_list,
6656 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07006657
Kiran Kandi910e1862013-10-29 13:29:42 -07006658 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07006659
6660 char value[PROPERTY_VALUE_MAX];
6661 int trial;
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07006662 if (property_get("vendor.audio_hal.period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07006663 trial = atoi(value);
6664 if (period_size_is_plausible_for_low_latency(trial)) {
6665 pcm_config_low_latency.period_size = trial;
6666 pcm_config_low_latency.start_threshold = trial / 4;
6667 pcm_config_low_latency.avail_min = trial / 4;
6668 configured_low_latency_capture_period_size = trial;
6669 }
6670 }
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07006671 if (property_get("vendor.audio_hal.in_period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07006672 trial = atoi(value);
6673 if (period_size_is_plausible_for_low_latency(trial)) {
6674 configured_low_latency_capture_period_size = trial;
6675 }
6676 }
6677
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07006678 if (property_get("vendor.audio_hal.period_multiplier", value, NULL) > 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006679 af_period_multiplier = atoi(value);
6680 if (af_period_multiplier < 0)
6681 af_period_multiplier = 2;
6682 else if (af_period_multiplier > 4)
6683 af_period_multiplier = 4;
6684
6685 ALOGV("new period_multiplier = %d", af_period_multiplier);
6686 }
6687
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07006688 adev->multi_offload_enable = property_get_bool("vendor.audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07006689 pthread_mutex_unlock(&adev_init_lock);
6690
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006691 if (adev->adm_init)
6692 adev->adm_data = adev->adm_init();
6693
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306694 qahwi_init(*device);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05306695 audio_extn_perf_lock_init();
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006696 audio_extn_adsp_hdlr_init(adev->mixer);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306697
6698 audio_extn_snd_mon_init();
6699 pthread_mutex_lock(&adev->lock);
6700 audio_extn_snd_mon_register_listener(adev, adev_snd_mon_cb);
6701 adev->card_status = CARD_STATUS_ONLINE;
6702 pthread_mutex_unlock(&adev->lock);
6703 audio_extn_sound_trigger_init(adev); /* dependent on snd_mon_init() */
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +05306704 /* Allocate memory for Device config params */
6705 adev->device_cfg_params = (struct audio_device_config_param*)
6706 calloc(platform_get_max_codec_backend(),
6707 sizeof(struct audio_device_config_param));
6708 if (adev->device_cfg_params == NULL)
6709 ALOGE("%s: Memory allocation failed for Device config params", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306710
Eric Laurent994a6932013-07-17 11:51:42 -07006711 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006712 return 0;
6713}
6714
6715static struct hw_module_methods_t hal_module_methods = {
6716 .open = adev_open,
6717};
6718
6719struct audio_module HAL_MODULE_INFO_SYM = {
6720 .common = {
6721 .tag = HARDWARE_MODULE_TAG,
6722 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
6723 .hal_api_version = HARDWARE_HAL_API_VERSION,
6724 .id = AUDIO_HARDWARE_MODULE_ID,
6725 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08006726 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006727 .methods = &hal_module_methods,
6728 },
6729};