blob: 66c50e8aa5772f37f4a5b1aa9ee5d42634aa4853 [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002 * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003 * Not a Contribution.
4 *
Shiv Maliyappanahalli8911f282014-01-10 15:56:19 -08005 * Copyright (C) 2013 The Android Open Source Project
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 */
19
20#define LOG_TAG "audio_hw_primary"
21/*#define LOG_NDEBUG 0*/
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070022/*#define VERY_VERY_VERBOSE_LOGGING*/
23#ifdef VERY_VERY_VERBOSE_LOGGING
24#define ALOGVV ALOGV
25#else
26#define ALOGVV(a...) do { } while(0)
27#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080028
29#include <errno.h>
30#include <pthread.h>
31#include <stdint.h>
32#include <sys/time.h>
33#include <stdlib.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080034#include <math.h>
Eric Laurentc4aef752013-09-12 17:45:53 -070035#include <dlfcn.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070036#include <sys/resource.h>
37#include <sys/prctl.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080038
39#include <cutils/log.h>
40#include <cutils/str_parms.h>
41#include <cutils/properties.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070042#include <cutils/atomic.h>
43#include <cutils/sched_policy.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080044
Eric Laurentb23d5282013-05-14 15:27:20 -070045#include <hardware/audio_effect.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070046#include <system/thread_defs.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070047#include <audio_effects/effect_aec.h>
48#include <audio_effects/effect_ns.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080049#include "audio_hw.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070050#include "platform_api.h"
51#include <platform.h>
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -070052#include "audio_extn.h"
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080053#include "voice_extn.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080054
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070055#include "sound/compress_params.h"
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080056#include "sound/asound.h"
ApurupaPattapu2e084df2013-12-18 15:47:59 -080057
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070058#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 4
59/* ToDo: Check and update a proper value in msec */
60#define COMPRESS_OFFLOAD_PLAYBACK_LATENCY 96
61#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
62
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080063
Haynes Mathew Georgebf143712013-12-03 13:02:53 -080064#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_DEEP_BUFFER
65
Eric Laurentb23d5282013-05-14 15:27:20 -070066struct pcm_config pcm_config_deep_buffer = {
67 .channels = 2,
68 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
69 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
70 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
71 .format = PCM_FORMAT_S16_LE,
72 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
73 .stop_threshold = INT_MAX,
74 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
75};
76
77struct pcm_config pcm_config_low_latency = {
78 .channels = 2,
79 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
80 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
81 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
82 .format = PCM_FORMAT_S16_LE,
83 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
84 .stop_threshold = INT_MAX,
85 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
86};
87
88struct pcm_config pcm_config_hdmi_multi = {
89 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
90 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
91 .period_size = HDMI_MULTI_PERIOD_SIZE,
92 .period_count = HDMI_MULTI_PERIOD_COUNT,
93 .format = PCM_FORMAT_S16_LE,
94 .start_threshold = 0,
95 .stop_threshold = INT_MAX,
96 .avail_min = 0,
97};
98
99struct pcm_config pcm_config_audio_capture = {
100 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -0700101 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
102 .format = PCM_FORMAT_S16_LE,
103};
104
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800105const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700106 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
107 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
108 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700109 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700110#ifdef MULTIPLE_OFFLOAD_ENABLED
111 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
112 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
113 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
114 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
115 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
116 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
117 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
118 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
119#endif
Eric Laurentb23d5282013-05-14 15:27:20 -0700120 [USECASE_AUDIO_RECORD] = "audio-record",
Mingming Yine62d7842013-10-25 16:26:03 -0700121 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Eric Laurentb23d5282013-05-14 15:27:20 -0700122 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700123 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700124 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800125 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800126 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700127 [USECASE_VOICE_CALL] = "voice-call",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700128
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700129 [USECASE_VOICE2_CALL] = "voice2-call",
130 [USECASE_VOLTE_CALL] = "volte-call",
131 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800132 [USECASE_VOWLAN_CALL] = "vowlan-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800133 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700134 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
135 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
136 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800137 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
138 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
139 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
140
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700141 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
142 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700143 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
144 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Eric Laurentb23d5282013-05-14 15:27:20 -0700145};
146
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700147static const audio_usecase_t offload_usecases[] = {
148 USECASE_AUDIO_PLAYBACK_OFFLOAD,
149#ifdef MULTIPLE_OFFLOAD_ENABLED
150 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
151 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
152 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
153 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
154 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
155 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
156 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
157 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
158#endif
159};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800160
161#define STRING_TO_ENUM(string) { #string, string }
162
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800163struct string_to_enum {
164 const char *name;
165 uint32_t value;
166};
167
168static const struct string_to_enum out_channels_name_to_enum_table[] = {
169 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
170 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
171 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
172};
173
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700174static struct audio_device *adev = NULL;
175static pthread_mutex_t adev_init_lock;
Kiran Kandi910e1862013-10-29 13:29:42 -0700176static unsigned int audio_device_ref_count;
177
Haynes Mathew George5191a852013-09-11 14:19:36 -0700178static int set_voice_volume_l(struct audio_device *adev, float volume);
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800179
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800180static int check_and_set_gapless_mode(struct audio_device *adev) {
181
182
183 char value[PROPERTY_VALUE_MAX] = {0};
184 bool gapless_enabled = false;
185 const char *mixer_ctl_name = "Compress Gapless Playback";
186 struct mixer_ctl *ctl;
187
188 ALOGV("%s:", __func__);
189 property_get("audio.offload.gapless.enabled", value, NULL);
190 gapless_enabled = atoi(value) || !strncmp("true", value, 4);
191
192 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
193 if (!ctl) {
194 ALOGE("%s: Could not get ctl for mixer cmd - %s",
195 __func__, mixer_ctl_name);
196 return -EINVAL;
197 }
198
199 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
200 ALOGE("%s: Could not set gapless mode %d",
201 __func__, gapless_enabled);
202 return -EINVAL;
203 }
204 return 0;
205}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700206
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700207static bool is_supported_format(audio_format_t format)
208{
Eric Laurent86e17132013-09-12 17:49:30 -0700209 if (format == AUDIO_FORMAT_MP3 ||
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800210 format == AUDIO_FORMAT_AAC ||
211 format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD ||
Mingming Yin3ee55c62014-08-04 14:23:35 -0700212 format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD ||
213 format == AUDIO_FORMAT_FLAC)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800214 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700215
216 return false;
217}
218
219static int get_snd_codec_id(audio_format_t format)
220{
221 int id = 0;
222
223 switch (format) {
224 case AUDIO_FORMAT_MP3:
225 id = SND_AUDIOCODEC_MP3;
226 break;
227 case AUDIO_FORMAT_AAC:
228 id = SND_AUDIOCODEC_AAC;
229 break;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800230 case AUDIO_FORMAT_PCM_16_BIT_OFFLOAD:
231 case AUDIO_FORMAT_PCM_24_BIT_OFFLOAD:
232 id = SND_AUDIOCODEC_PCM;
233 break;
Mingming Yin3ee55c62014-08-04 14:23:35 -0700234 case AUDIO_FORMAT_FLAC:
235 id = SND_AUDIOCODEC_FLAC;
236 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700237 default:
Mingming Yin90310102013-11-13 16:57:00 -0800238 ALOGE("%s: Unsupported audio format :%x", __func__, format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700239 }
240
241 return id;
242}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800243
Venkata Narendra Kumar Guttaed0f94f2014-07-09 16:29:28 +0530244int get_snd_card_state(struct audio_device *adev)
Naresh Tanniru80659832014-06-04 18:17:56 +0530245{
246 int snd_scard_state;
247
248 if (!adev)
249 return SND_CARD_STATE_OFFLINE;
250
251 pthread_mutex_lock(&adev->snd_card_status.lock);
252 snd_scard_state = adev->snd_card_status.state;
253 pthread_mutex_unlock(&adev->snd_card_status.lock);
254
255 return snd_scard_state;
256}
257
258static int set_snd_card_state(struct audio_device *adev, int snd_scard_state)
259{
260 if (!adev)
261 return -ENOSYS;
262
263 pthread_mutex_lock(&adev->snd_card_status.lock);
264 adev->snd_card_status.state = snd_scard_state;
265 pthread_mutex_unlock(&adev->snd_card_status.lock);
266
267 return 0;
268}
269
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700270int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700271 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800272{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700273 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700274 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800275
276 if (usecase == NULL)
277 return -EINVAL;
278
279 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
280
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800281 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700282 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800283 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700284 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800285
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -0800286#ifdef DS1_DOLBY_DAP_ENABLED
287 audio_extn_dolby_set_dmid(adev);
288 audio_extn_dolby_set_endpoint(adev);
289#endif
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530290 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700291 audio_extn_utils_send_audio_calibration(adev, usecase);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700292 audio_extn_utils_send_app_type_cfg(usecase);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800293 strcpy(mixer_path, use_case_table[usecase->id]);
Eric Laurentb23d5282013-05-14 15:27:20 -0700294 platform_add_backend_name(mixer_path, snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700295 ALOGV("%s: apply mixer and update path: %s", __func__, mixer_path);
296 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800297 ALOGV("%s: exit", __func__);
298 return 0;
299}
300
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700301int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700302 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800303{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700304 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700305 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800306
307 if (usecase == NULL)
308 return -EINVAL;
309
310 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700311 if (usecase->type == PCM_CAPTURE)
312 snd_device = usecase->in_snd_device;
313 else
314 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800315 strcpy(mixer_path, use_case_table[usecase->id]);
Eric Laurentb23d5282013-05-14 15:27:20 -0700316 platform_add_backend_name(mixer_path, snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700317 ALOGV("%s: reset and update mixer path: %s", __func__, mixer_path);
318 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530319 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800320 ALOGV("%s: exit", __func__);
321 return 0;
322}
323
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700324int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700325 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800326{
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700327 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
328
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800329 if (snd_device < SND_DEVICE_MIN ||
330 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800331 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800332 return -EINVAL;
333 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700334
335 adev->snd_dev_ref_cnt[snd_device]++;
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700336
337 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
338 ALOGE("%s: Invalid sound device returned", __func__);
339 return -EINVAL;
340 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700341 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700342 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700343 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700344 return 0;
345 }
346
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -0700347 if (audio_extn_spkr_prot_is_enabled())
348 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700349 /* start usb playback thread */
350 if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
351 SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
352 audio_extn_usb_start_playback(adev);
353
354 /* start usb capture thread */
355 if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
356 audio_extn_usb_start_capture(adev);
357
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800358 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
359 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700360 audio_extn_spkr_prot_is_enabled()) {
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700361 if (audio_extn_spkr_prot_get_acdb_id(snd_device) < 0) {
362 adev->snd_dev_ref_cnt[snd_device]--;
363 return -EINVAL;
364 }
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800365 if (audio_extn_spkr_prot_start_processing(snd_device)) {
366 ALOGE("%s: spkr_start_processing failed", __func__);
367 return -EINVAL;
368 }
369 } else {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700370 ALOGV("%s: snd_device(%d: %s)", __func__,
371 snd_device, device_name);
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -0700372 /* due to the possibility of calibration overwrite between listen
373 and audio, notify listen hal before audio calibration is sent */
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530374 audio_extn_listen_update_device_status(snd_device,
375 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700376 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700377 adev->snd_dev_ref_cnt[snd_device]--;
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530378 audio_extn_listen_update_device_status(snd_device,
379 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700380 return -EINVAL;
381 }
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700382 audio_route_apply_and_update_path(adev->audio_route, device_name);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800383 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800384 return 0;
385}
386
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700387int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700388 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800389{
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700390 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
391
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800392 if (snd_device < SND_DEVICE_MIN ||
393 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800394 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800395 return -EINVAL;
396 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700397 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
398 ALOGE("%s: device ref cnt is already 0", __func__);
399 return -EINVAL;
400 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700401
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700402 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700403
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700404 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
405 ALOGE("%s: Invalid sound device returned", __func__);
406 return -EINVAL;
407 }
408
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700409 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Eric Laurent994a6932013-07-17 11:51:42 -0700410 ALOGV("%s: snd_device(%d: %s)", __func__,
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700411 snd_device, device_name);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -0800412 /* exit usb play back thread */
413 if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
414 SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
415 audio_extn_usb_stop_playback();
416
417 /* exit usb capture thread */
418 if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -0700419 audio_extn_usb_stop_capture();
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -0800420
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800421 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
422 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700423 audio_extn_spkr_prot_is_enabled()) {
424 audio_extn_spkr_prot_stop_processing();
425 } else
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700426 audio_route_reset_and_update_path(adev->audio_route, device_name);
Kiran Kandide144c82013-11-20 15:58:32 -0800427
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530428 audio_extn_listen_update_device_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -0800429 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700430 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700431
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800432 return 0;
433}
434
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700435static void check_usecases_codec_backend(struct audio_device *adev,
436 struct audio_usecase *uc_info,
437 snd_device_t snd_device)
438{
439 struct listnode *node;
440 struct audio_usecase *usecase;
441 bool switch_device[AUDIO_USECASE_MAX];
442 int i, num_uc_to_switch = 0;
443
444 /*
445 * This function is to make sure that all the usecases that are active on
446 * the hardware codec backend are always routed to any one device that is
447 * handled by the hardware codec.
448 * For example, if low-latency and deep-buffer usecases are currently active
449 * on speaker and out_set_parameters(headset) is received on low-latency
450 * output, then we have to make sure deep-buffer is also switched to headset,
451 * because of the limitation that both the devices cannot be enabled
452 * at the same time as they share the same backend.
453 */
Mingming Yin3ee55c62014-08-04 14:23:35 -0700454 /*
455 * This call is to check if we need to force routing for a particular stream
456 * If there is a backend configuration change for the device when a
457 * new stream starts, then ADM needs to be closed and re-opened with the new
458 * configuraion. This call check if we need to re-route all the streams
459 * associated with the backend. Touch tone + 24 bit playback.
460 */
461 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info);
462
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700463 /* Disable all the usecases on the shared backend other than the
464 specified usecase */
465 for (i = 0; i < AUDIO_USECASE_MAX; i++)
466 switch_device[i] = false;
467
468 list_for_each(node, &adev->usecase_list) {
469 usecase = node_to_item(node, struct audio_usecase, list);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800470 if (usecase->type != PCM_CAPTURE &&
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700471 usecase != uc_info &&
Mingming Yin3ee55c62014-08-04 14:23:35 -0700472 (usecase->out_snd_device != snd_device || force_routing) &&
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700473 usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
474 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
475 __func__, use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700476 platform_get_snd_device_name(usecase->out_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700477 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700478 switch_device[usecase->id] = true;
479 num_uc_to_switch++;
480 }
481 }
482
483 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700484 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700485
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530486 /* Make sure the previous devices to be disabled first and then enable the
487 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700488 list_for_each(node, &adev->usecase_list) {
489 usecase = node_to_item(node, struct audio_usecase, list);
490 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700491 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700492 }
493 }
494
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700495 list_for_each(node, &adev->usecase_list) {
496 usecase = node_to_item(node, struct audio_usecase, list);
497 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700498 enable_snd_device(adev, snd_device);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700499 }
500 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700501
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700502 /* Re-route all the usecases on the shared backend other than the
503 specified usecase to new snd devices */
504 list_for_each(node, &adev->usecase_list) {
505 usecase = node_to_item(node, struct audio_usecase, list);
506 /* Update the out_snd_device only before enabling the audio route */
507 if (switch_device[usecase->id] ) {
508 usecase->out_snd_device = snd_device;
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700509 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700510 }
511 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700512 }
513}
514
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700515static void check_and_route_capture_usecases(struct audio_device *adev,
516 struct audio_usecase *uc_info,
517 snd_device_t snd_device)
518{
519 struct listnode *node;
520 struct audio_usecase *usecase;
521 bool switch_device[AUDIO_USECASE_MAX];
522 int i, num_uc_to_switch = 0;
523
524 /*
525 * This function is to make sure that all the active capture usecases
526 * are always routed to the same input sound device.
527 * For example, if audio-record and voice-call usecases are currently
528 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
529 * is received for voice call then we have to make sure that audio-record
530 * usecase is also switched to earpiece i.e. voice-dmic-ef,
531 * because of the limitation that two devices cannot be enabled
532 * at the same time if they share the same backend.
533 */
534 for (i = 0; i < AUDIO_USECASE_MAX; i++)
535 switch_device[i] = false;
536
537 list_for_each(node, &adev->usecase_list) {
538 usecase = node_to_item(node, struct audio_usecase, list);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800539 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700540 usecase != uc_info &&
541 usecase->in_snd_device != snd_device) {
542 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
543 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700544 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700545 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700546 switch_device[usecase->id] = true;
547 num_uc_to_switch++;
548 }
549 }
550
551 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700552 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700553
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530554 /* Make sure the previous devices to be disabled first and then enable the
555 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700556 list_for_each(node, &adev->usecase_list) {
557 usecase = node_to_item(node, struct audio_usecase, list);
558 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700559 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800560 }
561 }
562
563 list_for_each(node, &adev->usecase_list) {
564 usecase = node_to_item(node, struct audio_usecase, list);
565 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700566 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700567 }
568 }
569
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700570 /* Re-route all the usecases on the shared backend other than the
571 specified usecase to new snd devices */
572 list_for_each(node, &adev->usecase_list) {
573 usecase = node_to_item(node, struct audio_usecase, list);
574 /* Update the in_snd_device only before enabling the audio route */
575 if (switch_device[usecase->id] ) {
576 usecase->in_snd_device = snd_device;
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700577 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700578 }
579 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700580 }
581}
582
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800583/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700584static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800585{
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700586 int ret = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700587 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800588
589 switch (channels) {
590 /*
591 * Do not handle stereo output in Multi-channel cases
592 * Stereo case is handled in normal playback path
593 */
594 case 6:
595 ALOGV("%s: HDMI supports 5.1", __func__);
596 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
597 break;
598 case 8:
599 ALOGV("%s: HDMI supports 5.1 and 7.1 channels", __func__);
600 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
601 out->supported_channel_masks[1] = AUDIO_CHANNEL_OUT_7POINT1;
602 break;
603 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700604 ALOGE("HDMI does not support multi channel playback");
605 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800606 break;
607 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700608 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800609}
610
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700611static audio_usecase_t get_voice_usecase_id_from_list(struct audio_device *adev)
612{
613 struct audio_usecase *usecase;
614 struct listnode *node;
615
616 list_for_each(node, &adev->usecase_list) {
617 usecase = node_to_item(node, struct audio_usecase, list);
618 if (usecase->type == VOICE_CALL) {
619 ALOGV("%s: usecase id %d", __func__, usecase->id);
620 return usecase->id;
621 }
622 }
623 return USECASE_INVALID;
624}
625
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700626struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700627 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700628{
629 struct audio_usecase *usecase;
630 struct listnode *node;
631
632 list_for_each(node, &adev->usecase_list) {
633 usecase = node_to_item(node, struct audio_usecase, list);
634 if (usecase->id == uc_id)
635 return usecase;
636 }
637 return NULL;
638}
639
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700640int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800641{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800642 snd_device_t out_snd_device = SND_DEVICE_NONE;
643 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700644 struct audio_usecase *usecase = NULL;
645 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800646 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800647 struct audio_usecase *hfp_usecase = NULL;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -0800648 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800649 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700650 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800651
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700652 usecase = get_usecase_from_list(adev, uc_id);
653 if (usecase == NULL) {
654 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
655 return -EINVAL;
656 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800657
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800658 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800659 (usecase->type == VOIP_CALL) ||
660 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700661 out_snd_device = platform_get_output_snd_device(adev->platform,
662 usecase->stream.out->devices);
663 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700664 usecase->devices = usecase->stream.out->devices;
665 } else {
666 /*
667 * If the voice call is active, use the sound devices of voice call usecase
668 * so that it would not result any device switch. All the usecases will
669 * be switched to new device when select_devices() is called for voice call
670 * usecase. This is to avoid switching devices for voice call when
671 * check_usecases_codec_backend() is called below.
672 */
Vidyakumar Athotaad34d572014-08-05 18:20:42 -0700673 if (adev->voice.in_call && adev->mode == AUDIO_MODE_IN_CALL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700674 vc_usecase = get_usecase_from_list(adev,
675 get_voice_usecase_id_from_list(adev));
Helen Zeng067b96b2013-11-26 12:10:29 -0800676 if ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
677 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL)) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700678 in_snd_device = vc_usecase->in_snd_device;
679 out_snd_device = vc_usecase->out_snd_device;
680 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800681 } else if (voice_extn_compress_voip_is_active(adev)) {
682 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
Narsinga Rao Chellac17cab62014-04-11 17:20:46 -0700683 if ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Avinash Vaish4d6167d2014-06-25 12:20:37 +0530684 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
685 (voip_usecase->stream.out != adev->primary_output)) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800686 in_snd_device = voip_usecase->in_snd_device;
687 out_snd_device = voip_usecase->out_snd_device;
688 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800689 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -0800690 hfp_ucid = audio_extn_hfp_get_usecase();
691 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800692 if (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
693 in_snd_device = hfp_usecase->in_snd_device;
694 out_snd_device = hfp_usecase->out_snd_device;
695 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700696 }
697 if (usecase->type == PCM_PLAYBACK) {
698 usecase->devices = usecase->stream.out->devices;
699 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700700 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700701 out_snd_device = platform_get_output_snd_device(adev->platform,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700702 usecase->stream.out->devices);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700703 if (usecase->stream.out == adev->primary_output &&
704 adev->active_input &&
705 adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
706 select_devices(adev, adev->active_input->usecase);
707 }
708 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700709 } else if (usecase->type == PCM_CAPTURE) {
710 usecase->devices = usecase->stream.in->device;
711 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700712 if (in_snd_device == SND_DEVICE_NONE) {
713 if (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
714 adev->primary_output && !adev->primary_output->standby) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700715 in_snd_device = platform_get_input_snd_device(adev->platform,
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700716 adev->primary_output->devices);
717 } else {
Eric Laurentb23d5282013-05-14 15:27:20 -0700718 in_snd_device = platform_get_input_snd_device(adev->platform,
719 AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700720 }
721 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700722 }
723 }
724
725 if (out_snd_device == usecase->out_snd_device &&
726 in_snd_device == usecase->in_snd_device) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800727 return 0;
728 }
729
sangwoobc677242013-08-08 16:53:43 +0900730 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -0700731 out_snd_device, platform_get_snd_device_name(out_snd_device),
732 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800733
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800734 /*
735 * Limitation: While in call, to do a device switch we need to disable
736 * and enable both RX and TX devices though one of them is same as current
737 * device.
738 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700739 if ((usecase->type == VOICE_CALL) &&
740 (usecase->in_snd_device != SND_DEVICE_NONE) &&
741 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700742 status = platform_switch_voice_call_device_pre(adev->platform);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800743 }
744
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700745 /* Disable current sound devices */
746 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700747 disable_audio_route(adev, usecase);
748 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800749 }
750
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700751 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700752 disable_audio_route(adev, usecase);
753 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800754 }
755
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800756 /* Applicable only on the targets that has external modem.
757 * New device information should be sent to modem before enabling
758 * the devices to reduce in-call device switch time.
759 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700760 if ((usecase->type == VOICE_CALL) &&
761 (usecase->in_snd_device != SND_DEVICE_NONE) &&
762 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800763 status = platform_switch_voice_call_enable_device_config(adev->platform,
764 out_snd_device,
765 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700766 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800767
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700768 /* Enable new sound devices */
769 if (out_snd_device != SND_DEVICE_NONE) {
770 if (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)
771 check_usecases_codec_backend(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700772 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800773 }
774
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700775 if (in_snd_device != SND_DEVICE_NONE) {
776 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700777 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700778 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700779
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800780 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL)
Eric Laurentb23d5282013-05-14 15:27:20 -0700781 status = platform_switch_voice_call_device_post(adev->platform,
782 out_snd_device,
783 in_snd_device);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800784
sangwoo170731f2013-06-08 15:36:36 +0900785 usecase->in_snd_device = in_snd_device;
786 usecase->out_snd_device = out_snd_device;
787
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700788 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +0900789
Vidyakumar Athota1fd21792013-11-15 14:50:57 -0800790 /* Applicable only on the targets that has external modem.
791 * Enable device command should be sent to modem only after
792 * enabling voice call mixer controls
793 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -0700794 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -0800795 status = platform_switch_voice_call_usecase_route_post(adev->platform,
796 out_snd_device,
797 in_snd_device);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +0530798 ALOGD("%s: done",__func__);
799
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800800 return status;
801}
802
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800803static int stop_input_stream(struct stream_in *in)
804{
805 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800806 struct audio_usecase *uc_info;
807 struct audio_device *adev = in->dev;
808
Eric Laurentc8400632013-02-14 19:04:54 -0800809 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800810
Eric Laurent994a6932013-07-17 11:51:42 -0700811 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700812 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800813 uc_info = get_usecase_from_list(adev, in->usecase);
814 if (uc_info == NULL) {
815 ALOGE("%s: Could not find the usecase (%d) in the list",
816 __func__, in->usecase);
817 return -EINVAL;
818 }
819
Vidyakumar Athota2850d532013-11-19 16:02:12 -0800820 /* Close in-call recording streams */
821 voice_check_and_stop_incall_rec_usecase(adev, in);
822
Eric Laurent150dbfe2013-02-27 14:31:02 -0800823 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700824 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700825
826 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700827 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800828
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800829 list_remove(&uc_info->list);
830 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800831
Eric Laurent994a6932013-07-17 11:51:42 -0700832 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800833 return ret;
834}
835
836int start_input_stream(struct stream_in *in)
837{
838 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -0800839 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800840 struct audio_usecase *uc_info;
841 struct audio_device *adev = in->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +0530842 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800843
Mingming Yine62d7842013-10-25 16:26:03 -0700844 in->usecase = platform_update_usecase_from_source(in->source,in->usecase);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +0530845 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
846 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700847
Naresh Tanniru80659832014-06-04 18:17:56 +0530848
849 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +0530850 ALOGE("%s: sound card is not active/SSR returning error", __func__);
851 ret = -ENETRESET;
Naresh Tanniru4c630392014-05-12 01:05:52 +0530852 goto error_config;
853 }
Naresh Tanniru4c630392014-05-12 01:05:52 +0530854
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700855 /* Check if source matches incall recording usecase criteria */
856 ret = voice_check_and_set_incall_rec_usecase(adev, in);
857 if (ret)
858 goto error_config;
859 else
860 ALOGV("%s: usecase(%d)", __func__, in->usecase);
861
Eric Laurentb23d5282013-05-14 15:27:20 -0700862 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800863 if (in->pcm_device_id < 0) {
864 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
865 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -0800866 ret = -EINVAL;
867 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800868 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700869
870 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800871 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -0700872
873 if (!uc_info) {
874 ret = -ENOMEM;
875 goto error_config;
876 }
877
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800878 uc_info->id = in->usecase;
879 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800880 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700881 uc_info->devices = in->device;
882 uc_info->in_snd_device = SND_DEVICE_NONE;
883 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800884
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800885 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700886 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800887
Eric Laurentc8400632013-02-14 19:04:54 -0800888 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -0800889 __func__, adev->snd_card,
890 in->pcm_device_id, in->config.channels);
891 in->pcm = pcm_open(adev->snd_card,
892 in->pcm_device_id, PCM_IN, &in->config);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800893 if (in->pcm && !pcm_is_ready(in->pcm)) {
894 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
895 pcm_close(in->pcm);
896 in->pcm = NULL;
Eric Laurentc8400632013-02-14 19:04:54 -0800897 ret = -EIO;
898 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800899 }
Naresh Tanniru4c630392014-05-12 01:05:52 +0530900
Eric Laurent994a6932013-07-17 11:51:42 -0700901 ALOGV("%s: exit", __func__);
Eric Laurentc8400632013-02-14 19:04:54 -0800902 return ret;
903
904error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800905 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -0800906
907error_config:
908 adev->active_input = NULL;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700909 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -0800910
911 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800912}
913
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700914/* must be called with out->lock locked */
915static int send_offload_cmd_l(struct stream_out* out, int command)
916{
917 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
918
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -0700919 if (!cmd) {
920 ALOGE("failed to allocate mem for command 0x%x", command);
921 return -ENOMEM;
922 }
923
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700924 ALOGVV("%s %d", __func__, command);
925
926 cmd->cmd = command;
927 list_add_tail(&out->offload_cmd_list, &cmd->node);
928 pthread_cond_signal(&out->offload_cond);
929 return 0;
930}
931
932/* must be called iwth out->lock locked */
933static void stop_compressed_output_l(struct stream_out *out)
934{
935 out->offload_state = OFFLOAD_STATE_IDLE;
936 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -0700937 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700938 if (out->compr != NULL) {
939 compress_stop(out->compr);
940 while (out->offload_thread_blocked) {
941 pthread_cond_wait(&out->cond, &out->lock);
942 }
943 }
944}
945
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700946bool is_offload_usecase(audio_usecase_t uc_id)
947{
948 unsigned int i;
949 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
950 if (uc_id == offload_usecases[i])
951 return true;
952 }
953 return false;
954}
955
956static audio_usecase_t get_offload_usecase(struct audio_device *adev)
957{
958 audio_usecase_t ret = USECASE_AUDIO_PLAYBACK_OFFLOAD;
959 unsigned int i, num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
960 char value[PROPERTY_VALUE_MAX] = {0};
961
962 property_get("audio.offload.multiple.enabled", value, NULL);
963 if (!(atoi(value) || !strncmp("true", value, 4)))
964 num_usecase = 1; /* If prop is not set, limit the num of offload usecases to 1 */
965
966 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
967 for (i = 0; i < num_usecase; i++) {
968 if (!(adev->offload_usecases_state & (0x1<<i))) {
969 adev->offload_usecases_state |= 0x1 << i;
970 ret = offload_usecases[i];
971 break;
972 }
973 }
974 ALOGV("%s: offload usecase is %d", __func__, ret);
975 return ret;
976}
977
978static void free_offload_usecase(struct audio_device *adev,
979 audio_usecase_t uc_id)
980{
981 unsigned int i;
982 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
983 if (offload_usecases[i] == uc_id) {
984 adev->offload_usecases_state &= ~(0x1<<i);
985 break;
986 }
987 }
988 ALOGV("%s: free offload usecase %d", __func__, uc_id);
989}
990
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700991static void *offload_thread_loop(void *context)
992{
993 struct stream_out *out = (struct stream_out *) context;
994 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -0800995 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700996
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700997 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
998 set_sched_policy(0, SP_FOREGROUND);
999 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1000
1001 ALOGV("%s", __func__);
1002 pthread_mutex_lock(&out->lock);
1003 for (;;) {
1004 struct offload_cmd *cmd = NULL;
1005 stream_callback_event_t event;
1006 bool send_callback = false;
1007
1008 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1009 __func__, list_empty(&out->offload_cmd_list),
1010 out->offload_state);
1011 if (list_empty(&out->offload_cmd_list)) {
1012 ALOGV("%s SLEEPING", __func__);
1013 pthread_cond_wait(&out->offload_cond, &out->lock);
1014 ALOGV("%s RUNNING", __func__);
1015 continue;
1016 }
1017
1018 item = list_head(&out->offload_cmd_list);
1019 cmd = node_to_item(item, struct offload_cmd, node);
1020 list_remove(item);
1021
1022 ALOGVV("%s STATE %d CMD %d out->compr %p",
1023 __func__, out->offload_state, cmd->cmd, out->compr);
1024
1025 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1026 free(cmd);
1027 break;
1028 }
1029
1030 if (out->compr == NULL) {
1031 ALOGE("%s: Compress handle is NULL", __func__);
1032 pthread_cond_signal(&out->cond);
1033 continue;
1034 }
1035 out->offload_thread_blocked = true;
1036 pthread_mutex_unlock(&out->lock);
1037 send_callback = false;
1038 switch(cmd->cmd) {
1039 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001040 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001041 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001042 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001043 send_callback = true;
1044 event = STREAM_CBK_EVENT_WRITE_READY;
1045 break;
1046 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001047 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05301048 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001049 ALOGD("copl(%p):calling compress_partial_drain", out);
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001050 compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001051 ALOGD("copl(%p):out of compress_partial_drain", out);
Sidipotu Ashok55820562014-02-10 16:16:38 +05301052 }
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001053 else if(ret == -ETIMEDOUT)
1054 compress_drain(out->compr);
1055 else
1056 ALOGE("%s: Next track returned error %d",__func__, ret);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001057 send_callback = true;
1058 event = STREAM_CBK_EVENT_DRAIN_READY;
1059 break;
1060 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001061 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001062 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001063 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001064 send_callback = true;
1065 event = STREAM_CBK_EVENT_DRAIN_READY;
1066 break;
1067 default:
1068 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1069 break;
1070 }
1071 pthread_mutex_lock(&out->lock);
1072 out->offload_thread_blocked = false;
1073 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001074 if (send_callback) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001075 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001076 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001077 free(cmd);
1078 }
1079
1080 pthread_cond_signal(&out->cond);
1081 while (!list_empty(&out->offload_cmd_list)) {
1082 item = list_head(&out->offload_cmd_list);
1083 list_remove(item);
1084 free(node_to_item(item, struct offload_cmd, node));
1085 }
1086 pthread_mutex_unlock(&out->lock);
1087
1088 return NULL;
1089}
1090
1091static int create_offload_callback_thread(struct stream_out *out)
1092{
1093 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1094 list_init(&out->offload_cmd_list);
1095 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1096 offload_thread_loop, out);
1097 return 0;
1098}
1099
1100static int destroy_offload_callback_thread(struct stream_out *out)
1101{
1102 pthread_mutex_lock(&out->lock);
1103 stop_compressed_output_l(out);
1104 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1105
1106 pthread_mutex_unlock(&out->lock);
1107 pthread_join(out->offload_thread, (void **) NULL);
1108 pthread_cond_destroy(&out->offload_cond);
1109
1110 return 0;
1111}
1112
Eric Laurent07eeafd2013-10-06 12:52:49 -07001113static bool allow_hdmi_channel_config(struct audio_device *adev)
1114{
1115 struct listnode *node;
1116 struct audio_usecase *usecase;
1117 bool ret = true;
1118
1119 list_for_each(node, &adev->usecase_list) {
1120 usecase = node_to_item(node, struct audio_usecase, list);
1121 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1122 /*
1123 * If voice call is already existing, do not proceed further to avoid
1124 * disabling/enabling both RX and TX devices, CSD calls, etc.
1125 * Once the voice call done, the HDMI channels can be configured to
1126 * max channels of remaining use cases.
1127 */
1128 if (usecase->id == USECASE_VOICE_CALL) {
1129 ALOGD("%s: voice call is active, no change in HDMI channels",
1130 __func__);
1131 ret = false;
1132 break;
1133 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
1134 ALOGD("%s: multi channel playback is active, "
1135 "no change in HDMI channels", __func__);
1136 ret = false;
1137 break;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001138 } else if (is_offload_usecase(usecase->id) &&
Mingming Yin139f1072014-02-24 17:56:01 -08001139 popcount(usecase->stream.out->channel_mask) > 2) {
1140 ALOGD("%s: multi-channel(%x) compress offload playback is active, "
1141 "no change in HDMI channels", __func__, usecase->stream.out->channel_mask);
1142 ret = false;
1143 break;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001144 }
1145 }
1146 }
1147 return ret;
1148}
1149
1150static int check_and_set_hdmi_channels(struct audio_device *adev,
1151 unsigned int channels)
1152{
1153 struct listnode *node;
1154 struct audio_usecase *usecase;
1155
1156 /* Check if change in HDMI channel config is allowed */
1157 if (!allow_hdmi_channel_config(adev))
1158 return 0;
1159
1160 if (channels == adev->cur_hdmi_channels) {
Mingming Yin10fef6a2013-11-26 17:17:01 -08001161 ALOGD("%s: Requested channels are same as current channels(%d)", __func__, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001162 return 0;
1163 }
1164
1165 platform_set_hdmi_channels(adev->platform, channels);
1166 adev->cur_hdmi_channels = channels;
1167
1168 /*
1169 * Deroute all the playback streams routed to HDMI so that
1170 * the back end is deactivated. Note that backend will not
1171 * be deactivated if any one stream is connected to it.
1172 */
1173 list_for_each(node, &adev->usecase_list) {
1174 usecase = node_to_item(node, struct audio_usecase, list);
1175 if (usecase->type == PCM_PLAYBACK &&
1176 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001177 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001178 }
1179 }
1180
1181 /*
1182 * Enable all the streams disabled above. Now the HDMI backend
1183 * will be activated with new channel configuration
1184 */
1185 list_for_each(node, &adev->usecase_list) {
1186 usecase = node_to_item(node, struct audio_usecase, list);
1187 if (usecase->type == PCM_PLAYBACK &&
1188 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001189 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001190 }
1191 }
1192
1193 return 0;
1194}
1195
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001196static int stop_output_stream(struct stream_out *out)
1197{
1198 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001199 struct audio_usecase *uc_info;
1200 struct audio_device *adev = out->dev;
1201
Eric Laurent994a6932013-07-17 11:51:42 -07001202 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001203 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001204 uc_info = get_usecase_from_list(adev, out->usecase);
1205 if (uc_info == NULL) {
1206 ALOGE("%s: Could not find the usecase (%d) in the list",
1207 __func__, out->usecase);
1208 return -EINVAL;
1209 }
1210
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001211 if (is_offload_usecase(out->usecase)) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001212 if (adev->visualizer_stop_output != NULL)
1213 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
1214 if (adev->offload_effects_stop_output != NULL)
1215 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1216 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001217
Eric Laurent150dbfe2013-02-27 14:31:02 -08001218 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001219 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001220
1221 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001222 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001223
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001224 list_remove(&uc_info->list);
1225 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001226
Eric Laurent07eeafd2013-10-06 12:52:49 -07001227 /* Must be called after removing the usecase from list */
1228 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1229 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
1230
Eric Laurent994a6932013-07-17 11:51:42 -07001231 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001232 return ret;
1233}
1234
1235int start_output_stream(struct stream_out *out)
1236{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001237 int ret = 0;
Mingming Yin9c041392014-05-01 15:37:31 -07001238 int sink_channels = 0;
1239 char prop_value[PROPERTY_VALUE_MAX] = {0};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001240 struct audio_usecase *uc_info;
1241 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301242 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001243
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001244 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
1245 ret = -EINVAL;
1246 goto error_config;
1247 }
1248
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301249 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
1250 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
1251 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05301252
Naresh Tanniru80659832014-06-04 18:17:56 +05301253 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301254 ALOGE("%s: sound card is not active/SSR returning error", __func__);
1255 ret = -ENETRESET;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301256 goto error_config;
1257 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301258
Eric Laurentb23d5282013-05-14 15:27:20 -07001259 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001260 if (out->pcm_device_id < 0) {
1261 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1262 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001263 ret = -EINVAL;
1264 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001265 }
1266
1267 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001268
1269 if (!uc_info) {
1270 ret = -ENOMEM;
1271 goto error_config;
1272 }
1273
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001274 uc_info->id = out->usecase;
1275 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001276 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001277 uc_info->devices = out->devices;
1278 uc_info->in_snd_device = SND_DEVICE_NONE;
1279 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001280
Eric Laurent07eeafd2013-10-06 12:52:49 -07001281 /* This must be called before adding this usecase to the list */
Mingming Yin10fef6a2013-11-26 17:17:01 -08001282 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Mingming Yin9c041392014-05-01 15:37:31 -07001283 property_get("audio.use.hdmi.sink.cap", prop_value, NULL);
1284 if (!strncmp("true", prop_value, 4)) {
1285 sink_channels = platform_edid_get_max_channels(out->dev->platform);
1286 ALOGD("%s: set HDMI channel count[%d] based on sink capability", __func__, sink_channels);
1287 check_and_set_hdmi_channels(adev, sink_channels);
1288 } else {
1289 if (is_offload_usecase(out->usecase))
1290 check_and_set_hdmi_channels(adev, out->compr_config.codec->ch_in);
1291 else
1292 check_and_set_hdmi_channels(adev, out->config.channels);
1293 }
Mingming Yin10fef6a2013-11-26 17:17:01 -08001294 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001295
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001296 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001297
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001298 select_devices(adev, out->usecase);
1299
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001300 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d)",
1301 __func__, 0, out->pcm_device_id);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001302 if (!is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08001303 out->pcm = pcm_open(adev->snd_card,
1304 out->pcm_device_id,
1305 PCM_OUT | PCM_MONOTONIC, &out->config);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001306 if (out->pcm && !pcm_is_ready(out->pcm)) {
1307 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1308 pcm_close(out->pcm);
1309 out->pcm = NULL;
1310 ret = -EIO;
1311 goto error_open;
1312 }
1313 } else {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001314 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08001315 out->compr = compress_open(adev->snd_card,
1316 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001317 COMPRESS_IN, &out->compr_config);
1318 if (out->compr && !is_compress_ready(out->compr)) {
1319 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1320 compress_close(out->compr);
1321 out->compr = NULL;
1322 ret = -EIO;
1323 goto error_open;
1324 }
1325 if (out->offload_callback)
1326 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07001327
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001328#ifdef DS1_DOLBY_DDP_ENABLED
1329 if (audio_extn_is_dolby_format(out->format))
1330 audio_extn_dolby_send_ddp_endp_params(adev);
1331#endif
1332
Eric Laurentc4aef752013-09-12 17:45:53 -07001333 if (adev->visualizer_start_output != NULL)
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001334 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1335 if (adev->offload_effects_start_output != NULL)
1336 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001337 }
Eric Laurent994a6932013-07-17 11:51:42 -07001338 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001339 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001340error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001341 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001342error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001343 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001344}
1345
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001346static int check_input_parameters(uint32_t sample_rate,
1347 audio_format_t format,
1348 int channel_count)
1349{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001350 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001351
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001352 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
Mingming Yine62d7842013-10-25 16:26:03 -07001353 !voice_extn_compress_voip_is_format_supported(format) &&
1354 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001355
1356 switch (channel_count) {
1357 case 1:
1358 case 2:
1359 case 6:
1360 break;
1361 default:
1362 ret = -EINVAL;
1363 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001364
1365 switch (sample_rate) {
1366 case 8000:
1367 case 11025:
1368 case 12000:
1369 case 16000:
1370 case 22050:
1371 case 24000:
1372 case 32000:
1373 case 44100:
1374 case 48000:
1375 break;
1376 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001377 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001378 }
1379
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001380 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001381}
1382
1383static size_t get_input_buffer_size(uint32_t sample_rate,
1384 audio_format_t format,
1385 int channel_count)
1386{
1387 size_t size = 0;
1388
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001389 if (check_input_parameters(sample_rate, format, channel_count) != 0)
1390 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001391
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001392 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
1393 /* ToDo: should use frame_size computed based on the format and
1394 channel_count here. */
1395 size *= sizeof(short) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001396
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001397 /* make sure the size is multiple of 64 */
1398 size += 0x3f;
1399 size &= ~0x3f;
1400
1401 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001402}
1403
1404static uint32_t out_get_sample_rate(const struct audio_stream *stream)
1405{
1406 struct stream_out *out = (struct stream_out *)stream;
1407
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001408 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001409}
1410
1411static int out_set_sample_rate(struct audio_stream *stream, uint32_t rate)
1412{
1413 return -ENOSYS;
1414}
1415
1416static size_t out_get_buffer_size(const struct audio_stream *stream)
1417{
1418 struct stream_out *out = (struct stream_out *)stream;
1419
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001420 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001421 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001422 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
1423 return voice_extn_compress_voip_out_get_buffer_size(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001424
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001425 return out->config.period_size * audio_stream_frame_size(stream);
1426}
1427
1428static uint32_t out_get_channels(const struct audio_stream *stream)
1429{
1430 struct stream_out *out = (struct stream_out *)stream;
1431
1432 return out->channel_mask;
1433}
1434
1435static audio_format_t out_get_format(const struct audio_stream *stream)
1436{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001437 struct stream_out *out = (struct stream_out *)stream;
1438
1439 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001440}
1441
1442static int out_set_format(struct audio_stream *stream, audio_format_t format)
1443{
1444 return -ENOSYS;
1445}
1446
1447static int out_standby(struct audio_stream *stream)
1448{
1449 struct stream_out *out = (struct stream_out *)stream;
1450 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001451
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301452 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
1453 stream, out->usecase, use_case_table[out->usecase]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001454 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
1455 /* Ignore standby in case of voip call because the voip output
1456 * stream is closed in adev_close_output_stream()
1457 */
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301458 ALOGD("%s: Ignore Standby in VOIP call", __func__);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001459 return 0;
1460 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001461
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001462 pthread_mutex_lock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001463 if (!out->standby) {
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08001464 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001465 out->standby = true;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001466 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001467 if (out->pcm) {
1468 pcm_close(out->pcm);
1469 out->pcm = NULL;
1470 }
1471 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001472 ALOGD("copl(%p):standby", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001473 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001474 out->gapless_mdata.encoder_delay = 0;
1475 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001476 if (out->compr != NULL) {
1477 compress_close(out->compr);
1478 out->compr = NULL;
1479 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08001480 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001481 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001482 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001483 }
1484 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07001485 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001486 return 0;
1487}
1488
1489static int out_dump(const struct audio_stream *stream, int fd)
1490{
1491 return 0;
1492}
1493
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001494static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
1495{
1496 int ret = 0;
1497 char value[32];
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001498 bool is_meta_data_params = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001499 struct compr_gapless_mdata tmp_mdata;
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001500 tmp_mdata.encoder_delay = 0;
1501 tmp_mdata.encoder_padding = 0;
ApurupaPattapu2e084df2013-12-18 15:47:59 -08001502
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001503 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001504 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001505 return -EINVAL;
1506 }
1507
ApurupaPattapu2e084df2013-12-18 15:47:59 -08001508 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FORMAT, value, sizeof(value));
1509 if (ret >= 0) {
1510 if (atoi(value) == SND_AUDIOSTREAMFORMAT_MP4ADTS) {
1511 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
1512 ALOGV("ADTS format is set in offload mode");
1513 }
1514 out->send_new_metadata = 1;
1515 }
1516
Mingming Yin3ee55c62014-08-04 14:23:35 -07001517 if (out->format == AUDIO_FORMAT_FLAC) {
1518 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FLAC_MIN_BLK_SIZE, value, sizeof(value));
1519 if (ret >= 0) {
1520 out->compr_config.codec->options.flac_dec.min_blk_size = atoi(value);
1521 out->send_new_metadata = 1;
1522 }
1523 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FLAC_MAX_BLK_SIZE, value, sizeof(value));
1524 if (ret >= 0) {
1525 out->compr_config.codec->options.flac_dec.max_blk_size = atoi(value);
1526 out->send_new_metadata = 1;
1527 }
1528 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FLAC_MIN_FRAME_SIZE, value, sizeof(value));
1529 if (ret >= 0) {
1530 out->compr_config.codec->options.flac_dec.min_frame_size = atoi(value);
1531 out->send_new_metadata = 1;
1532 }
1533 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FLAC_MAX_FRAME_SIZE, value, sizeof(value));
1534 if (ret >= 0) {
1535 out->compr_config.codec->options.flac_dec.max_frame_size = atoi(value);
1536 out->send_new_metadata = 1;
1537 }
1538 }
1539
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001540 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_SAMPLE_RATE, value, sizeof(value));
1541 if(ret >= 0)
1542 is_meta_data_params = true;
1543 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_NUM_CHANNEL, value, sizeof(value));
1544 if(ret >= 0 )
1545 is_meta_data_params = true;
1546 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_AVG_BIT_RATE, value, sizeof(value));
1547 if(ret >= 0 )
1548 is_meta_data_params = true;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001549 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
1550 if (ret >= 0) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001551 is_meta_data_params = true;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001552 tmp_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001553 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001554 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
1555 if (ret >= 0) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001556 is_meta_data_params = true;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001557 tmp_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001558 }
1559
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001560 if(!is_meta_data_params) {
1561 ALOGV("%s: Not gapless meta data params", __func__);
1562 return 0;
1563 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001564 out->gapless_mdata = tmp_mdata;
1565 out->send_new_metadata = 1;
1566 ALOGV("%s new encoder delay %u and padding %u", __func__,
1567 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
1568
1569 return 0;
1570}
1571
1572
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001573static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
1574{
1575 struct stream_out *out = (struct stream_out *)stream;
1576 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001577 struct audio_usecase *usecase;
1578 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001579 struct str_parms *parms;
1580 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001581 int ret = 0, val = 0, err;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001582 bool select_new_device = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001583
sangwoobc677242013-08-08 16:53:43 +09001584 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001585 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001586 parms = str_parms_create_str(kvpairs);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001587 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
1588 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001589 val = atoi(value);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001590 pthread_mutex_lock(&out->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001591 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001592
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001593 /*
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05301594 * When HDMI cable is unplugged/usb hs is disconnected the
1595 * music playback is paused and the policy manager sends routing=0
1596 * But the audioflingercontinues to write data until standby time
1597 * (3sec). As the HDMI core is turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001598 * Avoid this by routing audio to speaker until standby.
1599 */
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05301600 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL ||
1601 out->devices == AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET) &&
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001602 val == AUDIO_DEVICE_NONE) {
1603 val = AUDIO_DEVICE_OUT_SPEAKER;
1604 }
1605
1606 /*
1607 * select_devices() call below switches all the usecases on the same
1608 * backend to the new device. Refer to check_usecases_codec_backend() in
1609 * the select_devices(). But how do we undo this?
1610 *
1611 * For example, music playback is active on headset (deep-buffer usecase)
1612 * and if we go to ringtones and select a ringtone, low-latency usecase
1613 * will be started on headset+speaker. As we can't enable headset+speaker
1614 * and headset devices at the same time, select_devices() switches the music
1615 * playback to headset+speaker while starting low-lateny usecase for ringtone.
1616 * So when the ringtone playback is completed, how do we undo the same?
1617 *
1618 * We are relying on the out_set_parameters() call on deep-buffer output,
1619 * once the ringtone playback is ended.
1620 * NOTE: We should not check if the current devices are same as new devices.
1621 * Because select_devices() must be called to switch back the music
1622 * playback to headset.
1623 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001624 if (val != 0) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001625 out->devices = val;
1626
1627 if (!out->standby)
1628 select_devices(adev, out->usecase);
1629
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001630 if ((adev->mode == AUDIO_MODE_IN_CALL) &&
Vidyakumar Athotaad34d572014-08-05 18:20:42 -07001631 !adev->voice.in_call &&
1632 (out == adev->primary_output)) {
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001633 ret = voice_start_call(adev);
Vidyakumar Athotaad34d572014-08-05 18:20:42 -07001634 } else if ((adev->mode == AUDIO_MODE_IN_CALL) &&
1635 adev->voice.in_call &&
1636 (out == adev->primary_output)) {
Narsinga Rao Chella22d8d7a2014-02-06 14:05:14 -08001637 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001638 }
1639 }
1640
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001641 if ((adev->mode == AUDIO_MODE_NORMAL) &&
Vidyakumar Athotaad34d572014-08-05 18:20:42 -07001642 adev->voice.in_call &&
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001643 (out == adev->primary_output)) {
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001644 ret = voice_stop_call(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001645 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001646
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001647 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001648 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001649 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001650
1651 if (out == adev->primary_output) {
1652 pthread_mutex_lock(&adev->lock);
1653 audio_extn_set_parameters(adev, parms);
1654 pthread_mutex_unlock(&adev->lock);
1655 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001656 if (is_offload_usecase(out->usecase)) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001657 pthread_mutex_lock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001658 parse_compress_metadata(out, parms);
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001659 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001660 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001661
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001662 str_parms_destroy(parms);
Eric Laurent994a6932013-07-17 11:51:42 -07001663 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001664 return ret;
1665}
1666
1667static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
1668{
1669 struct stream_out *out = (struct stream_out *)stream;
1670 struct str_parms *query = str_parms_create_str(keys);
1671 char *str;
1672 char value[256];
1673 struct str_parms *reply = str_parms_create();
1674 size_t i, j;
1675 int ret;
1676 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001677
1678 if (!query || !reply) {
1679 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
1680 return NULL;
1681 }
1682
Eric Laurent994a6932013-07-17 11:51:42 -07001683 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001684 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
1685 if (ret >= 0) {
1686 value[0] = '\0';
1687 i = 0;
1688 while (out->supported_channel_masks[i] != 0) {
1689 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
1690 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
1691 if (!first) {
1692 strcat(value, "|");
1693 }
1694 strcat(value, out_channels_name_to_enum_table[j].name);
1695 first = false;
1696 break;
1697 }
1698 }
1699 i++;
1700 }
1701 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
1702 str = str_parms_to_str(reply);
1703 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001704 voice_extn_out_get_parameters(out, query, reply);
1705 str = str_parms_to_str(reply);
1706 if (!strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08001707 free(str);
1708 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001709 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001710 }
1711 str_parms_destroy(query);
1712 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07001713 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001714 return str;
1715}
1716
1717static uint32_t out_get_latency(const struct audio_stream_out *stream)
1718{
1719 struct stream_out *out = (struct stream_out *)stream;
1720
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001721 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001722 return COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
1723
1724 return (out->config.period_count * out->config.period_size * 1000) /
1725 (out->config.rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001726}
1727
1728static int out_set_volume(struct audio_stream_out *stream, float left,
1729 float right)
1730{
Eric Laurenta9024de2013-04-04 09:19:12 -07001731 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001732 int volume[2];
1733
Eric Laurenta9024de2013-04-04 09:19:12 -07001734 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
1735 /* only take left channel into account: the API is for stereo anyway */
1736 out->muted = (left == 0.0f);
1737 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001738 } else if (is_offload_usecase(out->usecase)) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001739 char mixer_ctl_name[128];
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001740 struct audio_device *adev = out->dev;
1741 struct mixer_ctl *ctl;
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001742 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
1743 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001744
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001745 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
1746 "Compress Playback %d Volume", pcm_device_id);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001747 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
1748 if (!ctl) {
1749 ALOGE("%s: Could not get ctl for mixer cmd - %s",
1750 __func__, mixer_ctl_name);
1751 return -EINVAL;
1752 }
1753 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
1754 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
1755 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
1756 return 0;
Eric Laurenta9024de2013-04-04 09:19:12 -07001757 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001758
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001759 return -ENOSYS;
1760}
1761
1762static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
1763 size_t bytes)
1764{
1765 struct stream_out *out = (struct stream_out *)stream;
1766 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301767 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07001768 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001769
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001770 pthread_mutex_lock(&out->lock);
Naresh Tanniru4c630392014-05-12 01:05:52 +05301771
Naresh Tanniru80659832014-06-04 18:17:56 +05301772 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
1773 if (out->pcm) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301774 ALOGD(" %s: sound card is not active/SSR state", __func__);
1775 ret= -ENETRESET;
1776 goto exit;
Naresh Tanniru80659832014-06-04 18:17:56 +05301777 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1778 //during SSR for compress usecase we should return error to flinger
1779 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
1780 pthread_mutex_unlock(&out->lock);
1781 return -ENETRESET;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301782 }
1783 }
1784
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001785 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001786 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08001787 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001788 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
1789 ret = voice_extn_compress_voip_start_output_stream(out);
1790 else
1791 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001792 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001793 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001794 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001795 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001796 goto exit;
1797 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001798 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001799
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001800 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001801 ALOGD("copl(%p): writing buffer (%d bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001802 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001803 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001804 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
1805 out->send_new_metadata = 0;
1806 }
1807
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001808 ret = compress_write(out->compr, buffer, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001809 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %d", __func__, bytes, ret);
Eric Laurent6e895242013-09-05 16:10:57 -07001810 if (ret >= 0 && ret < (ssize_t)bytes) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05301811 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001812 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05301813 } else if (-ENETRESET == ret) {
1814 ALOGE("copl %s: received sound card offline state on compress write", __func__);
1815 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
1816 pthread_mutex_unlock(&out->lock);
1817 out_standby(&out->stream.common);
1818 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001819 }
Naresh Tanniru80659832014-06-04 18:17:56 +05301820 if (!out->playback_started && ret >= 0) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001821 compress_start(out->compr);
1822 out->playback_started = 1;
1823 out->offload_state = OFFLOAD_STATE_PLAYING;
1824 }
1825 pthread_mutex_unlock(&out->lock);
1826 return ret;
1827 } else {
1828 if (out->pcm) {
1829 if (out->muted)
1830 memset((void *)buffer, 0, bytes);
1831 ALOGVV("%s: writing buffer (%d bytes) to pcm device", __func__, bytes);
1832 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07001833 if (ret == 0)
1834 out->written += bytes / (out->config.channels * sizeof(short));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001835 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001836 }
1837
1838exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05301839 /* ToDo: There may be a corner case when SSR happens back to back during
1840 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05301841 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05301842 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05301843 }
1844
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001845 pthread_mutex_unlock(&out->lock);
1846
1847 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001848 if (out->pcm)
1849 ALOGE("%s: error %d - %s", __func__, ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05301850 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
1851 voice_extn_compress_voip_close_output_stream(&out->stream.common);
1852 out->standby = true;
1853 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001854 out_standby(&out->stream.common);
1855 usleep(bytes * 1000000 / audio_stream_frame_size(&out->stream.common) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05301856 out_get_sample_rate(&out->stream.common));
1857
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001858 }
1859 return bytes;
1860}
1861
1862static int out_get_render_position(const struct audio_stream_out *stream,
1863 uint32_t *dsp_frames)
1864{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001865 struct stream_out *out = (struct stream_out *)stream;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001866 if (is_offload_usecase(out->usecase) && (dsp_frames != NULL)) {
Naresh Tanniru80659832014-06-04 18:17:56 +05301867 ssize_t ret = -EINVAL;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001868 *dsp_frames = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001869 pthread_mutex_lock(&out->lock);
1870 if (out->compr != NULL) {
Naresh Tanniru80659832014-06-04 18:17:56 +05301871 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001872 &out->sample_rate);
1873 ALOGVV("%s rendered frames %d sample_rate %d",
1874 __func__, *dsp_frames, out->sample_rate);
1875 }
1876 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05301877 if (-ENETRESET == ret) {
1878 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
1879 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
1880 return -EINVAL;
1881 } else if(ret < 0) {
1882 ALOGE(" ERROR: Unable to get time stamp from compress driver");
1883 return -EINVAL;
1884 } else {
1885 return 0;
1886 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001887 } else
1888 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001889}
1890
1891static int out_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
1892{
1893 return 0;
1894}
1895
1896static int out_remove_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
1897{
1898 return 0;
1899}
1900
1901static int out_get_next_write_timestamp(const struct audio_stream_out *stream,
1902 int64_t *timestamp)
1903{
1904 return -EINVAL;
1905}
1906
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07001907static int out_get_presentation_position(const struct audio_stream_out *stream,
1908 uint64_t *frames, struct timespec *timestamp)
1909{
1910 struct stream_out *out = (struct stream_out *)stream;
1911 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07001912 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07001913
1914 pthread_mutex_lock(&out->lock);
1915
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001916 if (is_offload_usecase(out->usecase)) {
Eric Laurent949a0892013-09-20 09:20:13 -07001917 if (out->compr != NULL) {
1918 compress_get_tstamp(out->compr, &dsp_frames,
1919 &out->sample_rate);
1920 ALOGVV("%s rendered frames %ld sample_rate %d",
1921 __func__, dsp_frames, out->sample_rate);
1922 *frames = dsp_frames;
1923 ret = 0;
1924 /* this is the best we can do */
1925 clock_gettime(CLOCK_MONOTONIC, timestamp);
1926 }
1927 } else {
1928 if (out->pcm) {
1929 size_t avail;
1930 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
1931 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07001932 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07001933 // This adjustment accounts for buffering after app processor.
1934 // It is based on estimated DSP latency per use case, rather than exact.
1935 signed_frames -=
1936 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
1937
Eric Laurent949a0892013-09-20 09:20:13 -07001938 // It would be unusual for this value to be negative, but check just in case ...
1939 if (signed_frames >= 0) {
1940 *frames = signed_frames;
1941 ret = 0;
1942 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07001943 }
1944 }
1945 }
1946
1947 pthread_mutex_unlock(&out->lock);
1948
1949 return ret;
1950}
1951
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001952static int out_set_callback(struct audio_stream_out *stream,
1953 stream_callback_t callback, void *cookie)
1954{
1955 struct stream_out *out = (struct stream_out *)stream;
1956
1957 ALOGV("%s", __func__);
1958 pthread_mutex_lock(&out->lock);
1959 out->offload_callback = callback;
1960 out->offload_cookie = cookie;
1961 pthread_mutex_unlock(&out->lock);
1962 return 0;
1963}
1964
1965static int out_pause(struct audio_stream_out* stream)
1966{
1967 struct stream_out *out = (struct stream_out *)stream;
1968 int status = -ENOSYS;
1969 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001970 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001971 ALOGD("copl(%p):pause compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001972 pthread_mutex_lock(&out->lock);
1973 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05301974 struct audio_device *adev = out->dev;
1975 int snd_scard_state = get_snd_card_state(adev);
1976
1977 if (SND_CARD_STATE_ONLINE == snd_scard_state)
1978 status = compress_pause(out->compr);
1979
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001980 out->offload_state = OFFLOAD_STATE_PAUSED;
1981 }
1982 pthread_mutex_unlock(&out->lock);
1983 }
1984 return status;
1985}
1986
1987static int out_resume(struct audio_stream_out* stream)
1988{
1989 struct stream_out *out = (struct stream_out *)stream;
1990 int status = -ENOSYS;
1991 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001992 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001993 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001994 status = 0;
1995 pthread_mutex_lock(&out->lock);
1996 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05301997 struct audio_device *adev = out->dev;
1998 int snd_scard_state = get_snd_card_state(adev);
1999
2000 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2001 status = compress_resume(out->compr);
2002
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002003 out->offload_state = OFFLOAD_STATE_PLAYING;
2004 }
2005 pthread_mutex_unlock(&out->lock);
2006 }
2007 return status;
2008}
2009
2010static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2011{
2012 struct stream_out *out = (struct stream_out *)stream;
2013 int status = -ENOSYS;
2014 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002015 if (is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002016 pthread_mutex_lock(&out->lock);
2017 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2018 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2019 else
2020 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2021 pthread_mutex_unlock(&out->lock);
2022 }
2023 return status;
2024}
2025
2026static int out_flush(struct audio_stream_out* stream)
2027{
2028 struct stream_out *out = (struct stream_out *)stream;
2029 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002030 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002031 ALOGD("copl(%p):calling compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002032 pthread_mutex_lock(&out->lock);
2033 stop_compressed_output_l(out);
2034 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002035 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002036 return 0;
2037 }
2038 return -ENOSYS;
2039}
2040
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002041/** audio_stream_in implementation **/
2042static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2043{
2044 struct stream_in *in = (struct stream_in *)stream;
2045
2046 return in->config.rate;
2047}
2048
2049static int in_set_sample_rate(struct audio_stream *stream, uint32_t rate)
2050{
2051 return -ENOSYS;
2052}
2053
2054static size_t in_get_buffer_size(const struct audio_stream *stream)
2055{
2056 struct stream_in *in = (struct stream_in *)stream;
2057
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002058 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
2059 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07002060 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
2061 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002062
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002063 return in->config.period_size * audio_stream_frame_size(stream);
2064}
2065
2066static uint32_t in_get_channels(const struct audio_stream *stream)
2067{
2068 struct stream_in *in = (struct stream_in *)stream;
2069
2070 return in->channel_mask;
2071}
2072
2073static audio_format_t in_get_format(const struct audio_stream *stream)
2074{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002075 struct stream_in *in = (struct stream_in *)stream;
2076
2077 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002078}
2079
2080static int in_set_format(struct audio_stream *stream, audio_format_t format)
2081{
2082 return -ENOSYS;
2083}
2084
2085static int in_standby(struct audio_stream *stream)
2086{
2087 struct stream_in *in = (struct stream_in *)stream;
2088 struct audio_device *adev = in->dev;
2089 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302090 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2091 stream, in->usecase, use_case_table[in->usecase]);
2092
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002093
2094 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
2095 /* Ignore standby in case of voip call because the voip input
2096 * stream is closed in adev_close_input_stream()
2097 */
2098 ALOGV("%s: Ignore Standby in VOIP call", __func__);
2099 return status;
2100 }
2101
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002102 pthread_mutex_lock(&in->lock);
2103 if (!in->standby) {
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002104 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002105 in->standby = true;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002106 if (in->pcm) {
2107 pcm_close(in->pcm);
2108 in->pcm = NULL;
2109 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002110 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002111 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002112 }
2113 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002114 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002115 return status;
2116}
2117
2118static int in_dump(const struct audio_stream *stream, int fd)
2119{
2120 return 0;
2121}
2122
2123static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
2124{
2125 struct stream_in *in = (struct stream_in *)stream;
2126 struct audio_device *adev = in->dev;
2127 struct str_parms *parms;
2128 char *str;
2129 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002130 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002131
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302132 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002133 parms = str_parms_create_str(kvpairs);
2134
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002135 pthread_mutex_lock(&in->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002136 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002137
2138 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
2139 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002140 val = atoi(value);
2141 /* no audio source uses val == 0 */
2142 if ((in->source != val) && (val != 0)) {
2143 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002144 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2145 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2146 (voice_extn_compress_voip_is_format_supported(in->format)) &&
2147 (in->config.rate == 8000 || in->config.rate == 16000) &&
2148 (popcount(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002149 err = voice_extn_compress_voip_open_input_stream(in);
2150 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002151 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002152 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002153 }
2154 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002155 }
2156 }
2157
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002158 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2159 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002160 val = atoi(value);
2161 if ((in->device != val) && (val != 0)) {
2162 in->device = val;
2163 /* If recording is in progress, change the tx device to new device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002164 if (!in->standby)
2165 ret = select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002166 }
2167 }
2168
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002169done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002170 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002171 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002172
2173 str_parms_destroy(parms);
Eric Laurent994a6932013-07-17 11:51:42 -07002174 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002175 return ret;
2176}
2177
2178static char* in_get_parameters(const struct audio_stream *stream,
2179 const char *keys)
2180{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002181 struct stream_in *in = (struct stream_in *)stream;
2182 struct str_parms *query = str_parms_create_str(keys);
2183 char *str;
2184 char value[256];
2185 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002186
2187 if (!query || !reply) {
2188 ALOGE("in_get_parameters: failed to create query or reply");
2189 return NULL;
2190 }
2191
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002192 ALOGV("%s: enter: keys - %s", __func__, keys);
2193
2194 voice_extn_in_get_parameters(in, query, reply);
2195
2196 str = str_parms_to_str(reply);
2197 str_parms_destroy(query);
2198 str_parms_destroy(reply);
2199
2200 ALOGV("%s: exit: returns - %s", __func__, str);
2201 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002202}
2203
2204static int in_set_gain(struct audio_stream_in *stream, float gain)
2205{
2206 return 0;
2207}
2208
2209static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
2210 size_t bytes)
2211{
2212 struct stream_in *in = (struct stream_in *)stream;
2213 struct audio_device *adev = in->dev;
2214 int i, ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05302215 int snd_scard_state = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002216
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002217 pthread_mutex_lock(&in->lock);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302218
2219 if (in->pcm) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302220 if(SND_CARD_STATE_OFFLINE == snd_scard_state) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05302221 ALOGD(" %s: sound card is not active/SSR state", __func__);
2222 ret= -ENETRESET;
2223 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302224 }
2225 }
2226
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002227 if (in->standby) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002228 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002229 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
2230 ret = voice_extn_compress_voip_start_input_stream(in);
2231 else
2232 ret = start_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002233 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002234 if (ret != 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002235 goto exit;
2236 }
2237 in->standby = 0;
2238 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002239
2240 if (in->pcm) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002241 if (audio_extn_ssr_get_enabled() && popcount(in->channel_mask) == 6)
2242 ret = audio_extn_ssr_read(stream, buffer, bytes);
Mingming Yine62d7842013-10-25 16:26:03 -07002243 else if (audio_extn_compr_cap_usecase_supported(in->usecase))
2244 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002245 else
2246 ret = pcm_read(in->pcm, buffer, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002247 }
2248
2249 /*
2250 * Instead of writing zeroes here, we could trust the hardware
2251 * to always provide zeroes when muted.
2252 */
kunleizc5a639b2014-04-24 18:46:22 +08002253 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in))
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002254 memset(buffer, 0, bytes);
2255
2256exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302257 /* ToDo: There may be a corner case when SSR happens back to back during
2258 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05302259 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302260 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302261 memset(buffer, 0, bytes);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302262 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002263 pthread_mutex_unlock(&in->lock);
2264
2265 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302266 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
2267 voice_extn_compress_voip_close_input_stream(&in->stream.common);
2268 in->standby = true;
2269 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002270 in_standby(&in->stream.common);
2271 ALOGV("%s: read failed - sleeping for buffer duration", __func__);
2272 usleep(bytes * 1000000 / audio_stream_frame_size(&in->stream.common) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302273 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002274 }
2275 return bytes;
2276}
2277
2278static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream)
2279{
2280 return 0;
2281}
2282
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002283static int add_remove_audio_effect(const struct audio_stream *stream,
2284 effect_handle_t effect,
2285 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002286{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002287 struct stream_in *in = (struct stream_in *)stream;
2288 int status = 0;
2289 effect_descriptor_t desc;
2290
2291 status = (*effect)->get_descriptor(effect, &desc);
2292 if (status != 0)
2293 return status;
2294
2295 pthread_mutex_lock(&in->lock);
2296 pthread_mutex_lock(&in->dev->lock);
2297 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2298 in->enable_aec != enable &&
2299 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
2300 in->enable_aec = enable;
2301 if (!in->standby)
2302 select_devices(in->dev, in->usecase);
2303 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08002304 if (in->enable_ns != enable &&
2305 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
2306 in->enable_ns = enable;
2307 if (!in->standby)
2308 select_devices(in->dev, in->usecase);
2309 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002310 pthread_mutex_unlock(&in->dev->lock);
2311 pthread_mutex_unlock(&in->lock);
2312
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002313 return 0;
2314}
2315
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002316static int in_add_audio_effect(const struct audio_stream *stream,
2317 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002318{
Eric Laurent994a6932013-07-17 11:51:42 -07002319 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002320 return add_remove_audio_effect(stream, effect, true);
2321}
2322
2323static int in_remove_audio_effect(const struct audio_stream *stream,
2324 effect_handle_t effect)
2325{
Eric Laurent994a6932013-07-17 11:51:42 -07002326 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002327 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002328}
2329
2330static int adev_open_output_stream(struct audio_hw_device *dev,
2331 audio_io_handle_t handle,
2332 audio_devices_t devices,
2333 audio_output_flags_t flags,
2334 struct audio_config *config,
2335 struct audio_stream_out **stream_out)
2336{
2337 struct audio_device *adev = (struct audio_device *)dev;
2338 struct stream_out *out;
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08002339 int i, ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002340 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002341
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002342 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302343
2344 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2345 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
2346 ALOGE(" sound card is not active rejecting compress output open request");
2347 return -EINVAL;
2348 }
2349
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002350 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
2351
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302352 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
2353 stream_handle(%p)",__func__, config->sample_rate, config->channel_mask,
2354 devices, flags, &out->stream);
2355
2356
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08002357 if (!out) {
2358 return -ENOMEM;
2359 }
2360
2361 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
2362 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
2363
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002364 if (devices == AUDIO_DEVICE_NONE)
2365 devices = AUDIO_DEVICE_OUT_SPEAKER;
2366
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002367 out->flags = flags;
2368 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07002369 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002370 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002371 out->sample_rate = config->sample_rate;
2372 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
2373 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07002374 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002375 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002376
2377 /* Init use case and pcm_config */
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002378 if ((out->flags == AUDIO_OUTPUT_FLAG_DIRECT) &&
2379 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
2380 out->devices & AUDIO_DEVICE_OUT_PROXY)) {
2381
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002382 pthread_mutex_lock(&adev->lock);
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002383 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
2384 ret = read_hdmi_channel_masks(out);
2385
2386 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
2387 ret = audio_extn_read_afe_proxy_channel_masks(out);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002388 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002389 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002390 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002391
2392 if (config->sample_rate == 0)
2393 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2394 if (config->channel_mask == 0)
2395 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
2396
2397 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002398 out->sample_rate = config->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002399 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
2400 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002401 out->config.rate = config->sample_rate;
2402 out->config.channels = popcount(out->channel_mask);
2403 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002404 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2405 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08002406 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002407 ret = voice_extn_compress_voip_open_output_stream(out);
2408 if (ret != 0) {
2409 ALOGE("%s: Compress voip output cannot be opened, error:%d",
2410 __func__, ret);
2411 goto error_open;
2412 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002413 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
2414 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
2415 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
2416 ALOGE("%s: Unsupported Offload information", __func__);
2417 ret = -EINVAL;
2418 goto error_open;
2419 }
Mingming Yin90310102013-11-13 16:57:00 -08002420 if (!is_supported_format(config->offload_info.format) &&
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002421 !audio_extn_is_dolby_format(config->offload_info.format)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002422 ALOGE("%s: Unsupported audio format", __func__);
2423 ret = -EINVAL;
2424 goto error_open;
2425 }
2426
2427 out->compr_config.codec = (struct snd_codec *)
2428 calloc(1, sizeof(struct snd_codec));
2429
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002430 if (!out->compr_config.codec) {
2431 ret = -ENOMEM;
2432 goto error_open;
2433 }
2434
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002435 out->usecase = get_offload_usecase(adev);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002436 if (config->offload_info.channel_mask)
2437 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002438 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002439 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002440 config->offload_info.channel_mask = config->channel_mask;
2441 }
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002442 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002443 out->sample_rate = config->offload_info.sample_rate;
2444
2445 out->stream.set_callback = out_set_callback;
2446 out->stream.pause = out_pause;
2447 out->stream.resume = out_resume;
2448 out->stream.drain = out_drain;
2449 out->stream.flush = out_flush;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002450 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002451
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002452 if (audio_extn_is_dolby_format(config->offload_info.format))
Mingming Yin90310102013-11-13 16:57:00 -08002453 out->compr_config.codec->id =
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002454 audio_extn_dolby_get_snd_codec_id(adev, out,
2455 config->offload_info.format);
Mingming Yin90310102013-11-13 16:57:00 -08002456 else
2457 out->compr_config.codec->id =
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002458 get_snd_codec_id(config->offload_info.format);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002459 if (audio_is_offload_pcm(config->offload_info.format)) {
2460 out->compr_config.fragment_size =
2461 platform_get_pcm_offload_buffer_size(&config->offload_info);
2462 } else {
2463 out->compr_config.fragment_size =
2464 platform_get_compress_offload_buffer_size(&config->offload_info);
2465 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002466 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
2467 out->compr_config.codec->sample_rate =
2468 compress_get_alsa_rate(config->offload_info.sample_rate);
2469 out->compr_config.codec->bit_rate =
2470 config->offload_info.bit_rate;
2471 out->compr_config.codec->ch_in =
2472 popcount(config->channel_mask);
2473 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002474 out->bit_width = PCM_OUTPUT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002475
Mingming Yin3ee55c62014-08-04 14:23:35 -07002476 if (config->offload_info.format == AUDIO_FORMAT_AAC)
2477 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002478 if (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD)
2479 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002480 if(config->offload_info.format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002481 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
2482
Mingming Yin3ee55c62014-08-04 14:23:35 -07002483 if (out->bit_width == 24) {
2484 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
2485 }
2486
2487 if (out->bit_width == 24 && !platform_check_24_bit_support()) {
2488 ALOGW("24 bit support is not enabled, using 16 bit backend");
2489 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
2490 }
2491
2492 out->compr_config.codec->options.flac_dec.sample_size = out->bit_width;
2493
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002494 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
2495 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002496
2497 out->send_new_metadata = 1;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08002498 out->offload_state = OFFLOAD_STATE_IDLE;
2499 out->playback_started = 0;
2500
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002501 create_offload_callback_thread(out);
2502 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
2503 __func__, config->offload_info.version,
2504 config->offload_info.bit_rate);
Krishnankutty Kolathappillyb165a8a2014-01-07 11:25:51 -08002505 //Decide if we need to use gapless mode by default
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -08002506 check_and_set_gapless_mode(adev);
Krishnankutty Kolathappillyb165a8a2014-01-07 11:25:51 -08002507
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07002508 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
2509 ret = voice_check_and_set_incall_music_usecase(adev, out);
2510 if (ret != 0) {
2511 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
2512 __func__, ret);
2513 goto error_open;
2514 }
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07002515 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002516 format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002517 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
2518 out->config = pcm_config_low_latency;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002519 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07002520 } else {
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08002521 /* primary path is the default path selected if no other outputs are available/suitable */
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002522 format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08002523 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07002524 out->config = pcm_config_deep_buffer;
2525 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002526 }
2527
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002528 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
2529 &adev->streams_output_cfg_list,
2530 flags, format, &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08002531 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
2532 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
2533 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002534 if(adev->primary_output == NULL)
2535 adev->primary_output = out;
2536 else {
2537 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002538 ret = -EEXIST;
2539 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002540 }
2541 }
2542
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002543 /* Check if this usecase is already existing */
2544 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07002545 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
2546 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002547 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002548 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002549 ret = -EEXIST;
2550 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002551 }
2552 pthread_mutex_unlock(&adev->lock);
2553
2554 out->stream.common.get_sample_rate = out_get_sample_rate;
2555 out->stream.common.set_sample_rate = out_set_sample_rate;
2556 out->stream.common.get_buffer_size = out_get_buffer_size;
2557 out->stream.common.get_channels = out_get_channels;
2558 out->stream.common.get_format = out_get_format;
2559 out->stream.common.set_format = out_set_format;
2560 out->stream.common.standby = out_standby;
2561 out->stream.common.dump = out_dump;
2562 out->stream.common.set_parameters = out_set_parameters;
2563 out->stream.common.get_parameters = out_get_parameters;
2564 out->stream.common.add_audio_effect = out_add_audio_effect;
2565 out->stream.common.remove_audio_effect = out_remove_audio_effect;
2566 out->stream.get_latency = out_get_latency;
2567 out->stream.set_volume = out_set_volume;
2568 out->stream.write = out_write;
2569 out->stream.get_render_position = out_get_render_position;
2570 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002571 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002572
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002573 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07002574 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002575 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002576
2577 config->format = out->stream.common.get_format(&out->stream.common);
2578 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
2579 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
2580
2581 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302582 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
2583 use_case_table[out->usecase]);
Eric Laurent994a6932013-07-17 11:51:42 -07002584 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002585 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002586
2587error_open:
2588 free(out);
2589 *stream_out = NULL;
2590 ALOGD("%s: exit: ret %d", __func__, ret);
2591 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002592}
2593
2594static void adev_close_output_stream(struct audio_hw_device *dev,
2595 struct audio_stream_out *stream)
2596{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002597 struct stream_out *out = (struct stream_out *)stream;
2598 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002599 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002600
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302601 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
2602
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002603 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
2604 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
2605 if(ret != 0)
2606 ALOGE("%s: Compress voip output cannot be closed, error:%d",
2607 __func__, ret);
2608 }
2609 else
2610 out_standby(&stream->common);
2611
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002612 if (is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002613 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002614 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002615 if (out->compr_config.codec != NULL)
2616 free(out->compr_config.codec);
2617 }
2618 pthread_cond_destroy(&out->cond);
2619 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002620 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07002621 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002622}
2623
2624static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
2625{
2626 struct audio_device *adev = (struct audio_device *)dev;
2627 struct str_parms *parms;
2628 char *str;
2629 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07002630 int val;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002631 int ret = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002632
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08002633 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002634 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002635
Naresh Tanniru4c630392014-05-12 01:05:52 +05302636 err = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
2637 if (err >= 0) {
2638 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302639 if (strstr(snd_card_status, "OFFLINE")) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302640 struct listnode *node;
2641 struct audio_usecase *usecase;
2642
Naresh Tanniru4c630392014-05-12 01:05:52 +05302643 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05302644 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2645
2646 pthread_mutex_lock(&adev->lock);
2647 //close compress session on OFFLINE status
2648 usecase = get_usecase_from_list(adev,USECASE_AUDIO_PLAYBACK_OFFLOAD);
2649 if (usecase && usecase->stream.out) {
2650 ALOGD(" %s closing compress session on OFFLINE state", __func__);
2651
2652 struct stream_out *out = usecase->stream.out;
2653
2654 pthread_mutex_unlock(&adev->lock);
2655 out_standby(&out->stream.common);
2656 } else
2657 pthread_mutex_unlock(&adev->lock);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302658 } else if (strstr(snd_card_status, "ONLINE")) {
2659 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05302660 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302661 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05302662 }
2663
2664 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002665 ret = voice_set_parameters(adev, parms);
2666 if (ret != 0)
2667 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002668
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002669 ret = platform_set_parameters(adev->platform, parms);
2670 if (ret != 0)
2671 goto done;
2672
2673 err = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
2674 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002675 /* When set to false, HAL should disable EC and NS
2676 * But it is currently not supported.
2677 */
2678 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
2679 adev->bluetooth_nrec = true;
2680 else
2681 adev->bluetooth_nrec = false;
2682 }
2683
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002684 err = str_parms_get_str(parms, "screen_state", value, sizeof(value));
2685 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002686 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
2687 adev->screen_off = false;
2688 else
2689 adev->screen_off = true;
2690 }
2691
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002692 err = str_parms_get_int(parms, "rotation", &val);
2693 if (err >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07002694 bool reverse_speakers = false;
2695 switch(val) {
2696 // FIXME: note that the code below assumes that the speakers are in the correct placement
2697 // relative to the user when the device is rotated 90deg from its default rotation. This
2698 // assumption is device-specific, not platform-specific like this code.
2699 case 270:
2700 reverse_speakers = true;
2701 break;
2702 case 0:
2703 case 90:
2704 case 180:
2705 break;
2706 default:
2707 ALOGE("%s: unexpected rotation of %d", __func__, val);
2708 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07002709 if (adev->speaker_lr_swap != reverse_speakers) {
2710 adev->speaker_lr_swap = reverse_speakers;
2711 // only update the selected device if there is active pcm playback
2712 struct audio_usecase *usecase;
2713 struct listnode *node;
2714 list_for_each(node, &adev->usecase_list) {
2715 usecase = node_to_item(node, struct audio_usecase, list);
2716 if (usecase->type == PCM_PLAYBACK) {
2717 select_devices(adev, usecase->id);
2718 break;
2719 }
2720 }
2721 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07002722 }
2723
Mingming Yin514a8bc2014-07-29 15:22:21 -07002724 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
2725 if (ret >= 0) {
2726 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
2727 adev->bt_wb_speech_enabled = true;
2728 else
2729 adev->bt_wb_speech_enabled = false;
2730 }
2731
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07002732 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08002733
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002734done:
2735 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08002736 pthread_mutex_unlock(&adev->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002737 ALOGV("%s: exit with code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002738 return ret;
2739}
2740
2741static char* adev_get_parameters(const struct audio_hw_device *dev,
2742 const char *keys)
2743{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002744 struct audio_device *adev = (struct audio_device *)dev;
2745 struct str_parms *reply = str_parms_create();
2746 struct str_parms *query = str_parms_create_str(keys);
2747 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05302748 char value[256] = {0};
2749 int ret = 0;
2750
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002751 if (!query || !reply) {
2752 ALOGE("adev_get_parameters: failed to create query or reply");
2753 return NULL;
2754 }
2755
Naresh Tannirud7205b62014-06-20 02:54:48 +05302756 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
2757 sizeof(value));
2758 if (ret >=0) {
2759 int val = 1;
2760 pthread_mutex_lock(&adev->snd_card_status.lock);
2761 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
2762 val = 0;
2763 pthread_mutex_unlock(&adev->snd_card_status.lock);
2764 str_parms_add_int(reply, "SND_CARD_STATUS", val);
2765 goto exit;
2766 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002767
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08002768 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002769 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08002770 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002771 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05302772 pthread_mutex_unlock(&adev->lock);
2773
Naresh Tannirud7205b62014-06-20 02:54:48 +05302774exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002775 str = str_parms_to_str(reply);
2776 str_parms_destroy(query);
2777 str_parms_destroy(reply);
2778
2779 ALOGV("%s: exit: returns - %s", __func__, str);
2780 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002781}
2782
2783static int adev_init_check(const struct audio_hw_device *dev)
2784{
2785 return 0;
2786}
2787
2788static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
2789{
Haynes Mathew George5191a852013-09-11 14:19:36 -07002790 int ret;
2791 struct audio_device *adev = (struct audio_device *)dev;
2792 pthread_mutex_lock(&adev->lock);
2793 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07002794 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07002795 pthread_mutex_unlock(&adev->lock);
2796 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002797}
2798
2799static int adev_set_master_volume(struct audio_hw_device *dev, float volume)
2800{
2801 return -ENOSYS;
2802}
2803
2804static int adev_get_master_volume(struct audio_hw_device *dev,
2805 float *volume)
2806{
2807 return -ENOSYS;
2808}
2809
2810static int adev_set_master_mute(struct audio_hw_device *dev, bool muted)
2811{
2812 return -ENOSYS;
2813}
2814
2815static int adev_get_master_mute(struct audio_hw_device *dev, bool *muted)
2816{
2817 return -ENOSYS;
2818}
2819
2820static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
2821{
2822 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002823 pthread_mutex_lock(&adev->lock);
2824 if (adev->mode != mode) {
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07002825 ALOGD("%s mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002826 adev->mode = mode;
2827 }
2828 pthread_mutex_unlock(&adev->lock);
2829 return 0;
2830}
2831
2832static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
2833{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08002834 int ret;
2835
2836 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08002837 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08002838 ret = voice_set_mic_mute((struct audio_device *)dev, state);
2839 pthread_mutex_unlock(&adev->lock);
2840
2841 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002842}
2843
2844static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
2845{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002846 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002847 return 0;
2848}
2849
2850static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev,
2851 const struct audio_config *config)
2852{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002853 int channel_count = popcount(config->channel_mask);
2854
2855 return get_input_buffer_size(config->sample_rate, config->format, channel_count);
2856}
2857
2858static int adev_open_input_stream(struct audio_hw_device *dev,
2859 audio_io_handle_t handle,
2860 audio_devices_t devices,
2861 struct audio_config *config,
2862 struct audio_stream_in **stream_in)
2863{
2864 struct audio_device *adev = (struct audio_device *)dev;
2865 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002866 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002867 int channel_count = popcount(config->channel_mask);
2868
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302869
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002870 *stream_in = NULL;
2871 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
2872 return -EINVAL;
2873
2874 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002875
2876 if (!in) {
2877 ALOGE("failed to allocate input stream");
2878 return -ENOMEM;
2879 }
2880
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302881 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
2882 stream_handle(%p)",__func__, config->sample_rate, config->channel_mask,
2883 devices, &in->stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002884
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07002885 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
2886
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002887 in->stream.common.get_sample_rate = in_get_sample_rate;
2888 in->stream.common.set_sample_rate = in_set_sample_rate;
2889 in->stream.common.get_buffer_size = in_get_buffer_size;
2890 in->stream.common.get_channels = in_get_channels;
2891 in->stream.common.get_format = in_get_format;
2892 in->stream.common.set_format = in_set_format;
2893 in->stream.common.standby = in_standby;
2894 in->stream.common.dump = in_dump;
2895 in->stream.common.set_parameters = in_set_parameters;
2896 in->stream.common.get_parameters = in_get_parameters;
2897 in->stream.common.add_audio_effect = in_add_audio_effect;
2898 in->stream.common.remove_audio_effect = in_remove_audio_effect;
2899 in->stream.set_gain = in_set_gain;
2900 in->stream.read = in_read;
2901 in->stream.get_input_frames_lost = in_get_input_frames_lost;
2902
2903 in->device = devices;
2904 in->source = AUDIO_SOURCE_DEFAULT;
2905 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002906 in->standby = 1;
2907 in->channel_mask = config->channel_mask;
2908
2909 /* Update config params with the requested sample rate and channels */
2910 in->usecase = USECASE_AUDIO_RECORD;
2911 in->config = pcm_config_audio_capture;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002912 in->config.rate = config->sample_rate;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002913 in->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002914
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002915 if (channel_count == 6) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002916 if(audio_extn_ssr_get_enabled()) {
2917 if(audio_extn_ssr_init(adev, in)) {
2918 ALOGE("%s: audio_extn_ssr_init failed", __func__);
2919 ret = -EINVAL;
2920 goto err_open;
2921 }
2922 } else {
2923 ret = -EINVAL;
2924 goto err_open;
2925 }
Mingming Yine62d7842013-10-25 16:26:03 -07002926 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002927 audio_extn_compr_cap_format_supported(config->format) &&
2928 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Mingming Yine62d7842013-10-25 16:26:03 -07002929 audio_extn_compr_cap_init(adev, in);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002930 } else {
2931 in->config.channels = channel_count;
2932 frame_size = audio_stream_frame_size((struct audio_stream *)in);
2933 buffer_size = get_input_buffer_size(config->sample_rate,
2934 config->format,
2935 channel_count);
2936 in->config.period_size = buffer_size / frame_size;
2937 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002938
2939 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07002940 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002941 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002942
2943err_open:
2944 free(in);
2945 *stream_in = NULL;
2946 return ret;
2947}
2948
2949static void adev_close_input_stream(struct audio_hw_device *dev,
2950 struct audio_stream_in *stream)
2951{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002952 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002953 struct stream_in *in = (struct stream_in *)stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302954 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002955
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002956 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
2957 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
2958 if (ret != 0)
2959 ALOGE("%s: Compress voip input cannot be closed, error:%d",
2960 __func__, ret);
2961 } else
2962 in_standby(&stream->common);
2963
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002964 if (audio_extn_ssr_get_enabled() && (popcount(in->channel_mask) == 6)) {
2965 audio_extn_ssr_deinit();
2966 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002967 free(stream);
2968
Mingming Yine62d7842013-10-25 16:26:03 -07002969 if(audio_extn_compr_cap_enabled() &&
2970 audio_extn_compr_cap_format_supported(in->config.format))
2971 audio_extn_compr_cap_deinit();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002972 return;
2973}
2974
2975static int adev_dump(const audio_hw_device_t *device, int fd)
2976{
2977 return 0;
2978}
2979
2980static int adev_close(hw_device_t *device)
2981{
2982 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07002983
2984 if (!adev)
2985 return 0;
2986
2987 pthread_mutex_lock(&adev_init_lock);
2988
2989 if ((--audio_device_ref_count) == 0) {
Kiran Kandide144c82013-11-20 15:58:32 -08002990 audio_extn_listen_deinit(adev);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002991 audio_extn_utils_release_streams_output_cfg_list(&adev->streams_output_cfg_list);
Kiran Kandi910e1862013-10-29 13:29:42 -07002992 audio_route_free(adev->audio_route);
2993 free(adev->snd_dev_ref_cnt);
2994 platform_deinit(adev->platform);
Kiran Kandi910e1862013-10-29 13:29:42 -07002995 free(device);
2996 adev = NULL;
2997 }
2998 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002999 return 0;
3000}
3001
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003002static int adev_open(const hw_module_t *module, const char *name,
3003 hw_device_t **device)
3004{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003005 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003006
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003007 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003008 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
3009
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003010 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07003011 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003012 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07003013 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003014 ALOGD("%s: returning existing instance of adev", __func__);
3015 ALOGD("%s: exit", __func__);
3016 pthread_mutex_unlock(&adev_init_lock);
3017 return 0;
3018 }
3019
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003020 adev = calloc(1, sizeof(struct audio_device));
3021
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003022 if (!adev) {
3023 pthread_mutex_unlock(&adev_init_lock);
3024 return -ENOMEM;
3025 }
3026
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003027 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
3028
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003029 adev->device.common.tag = HARDWARE_DEVICE_TAG;
3030 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
3031 adev->device.common.module = (struct hw_module_t *)module;
3032 adev->device.common.close = adev_close;
3033
3034 adev->device.init_check = adev_init_check;
3035 adev->device.set_voice_volume = adev_set_voice_volume;
3036 adev->device.set_master_volume = adev_set_master_volume;
3037 adev->device.get_master_volume = adev_get_master_volume;
3038 adev->device.set_master_mute = adev_set_master_mute;
3039 adev->device.get_master_mute = adev_get_master_mute;
3040 adev->device.set_mode = adev_set_mode;
3041 adev->device.set_mic_mute = adev_set_mic_mute;
3042 adev->device.get_mic_mute = adev_get_mic_mute;
3043 adev->device.set_parameters = adev_set_parameters;
3044 adev->device.get_parameters = adev_get_parameters;
3045 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
3046 adev->device.open_output_stream = adev_open_output_stream;
3047 adev->device.close_output_stream = adev_close_output_stream;
3048 adev->device.open_input_stream = adev_open_input_stream;
3049 adev->device.close_input_stream = adev_close_input_stream;
3050 adev->device.dump = adev_dump;
3051
3052 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003053 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08003054 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003055 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003056 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003057 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08003058 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07003059 /* adev->cur_hdmi_channels = 0; by calloc() */
Mingming Yin3ee55c62014-08-04 14:23:35 -07003060 adev->cur_codec_backend_samplerate = CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
3061 adev->cur_codec_backend_bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Eric Laurentb23d5282013-05-14 15:27:20 -07003062 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003063 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003064 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08003065 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003066 adev->offload_usecases_state = 0;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303067
3068 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
3069 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003070 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07003071 adev->platform = platform_init(adev);
3072 if (!adev->platform) {
3073 free(adev->snd_dev_ref_cnt);
3074 free(adev);
3075 ALOGE("%s: Failed to init platform data, aborting.", __func__);
3076 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08003077 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07003078 return -EINVAL;
3079 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003080
Naresh Tanniru4c630392014-05-12 01:05:52 +05303081 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
3082
Eric Laurentc4aef752013-09-12 17:45:53 -07003083 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
3084 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
3085 if (adev->visualizer_lib == NULL) {
3086 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
3087 } else {
3088 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
3089 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003090 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003091 "visualizer_hal_start_output");
3092 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003093 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003094 "visualizer_hal_stop_output");
3095 }
3096 }
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08003097 audio_extn_listen_init(adev, adev->snd_card);
Eric Laurentc4aef752013-09-12 17:45:53 -07003098
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003099 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
3100 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
3101 if (adev->offload_effects_lib == NULL) {
3102 ALOGE("%s: DLOPEN failed for %s", __func__,
3103 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3104 } else {
3105 ALOGV("%s: DLOPEN successful for %s", __func__,
3106 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3107 adev->offload_effects_start_output =
3108 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3109 "offload_effects_bundle_hal_start_output");
3110 adev->offload_effects_stop_output =
3111 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3112 "offload_effects_bundle_hal_stop_output");
3113 }
3114 }
3115
Mingming Yin514a8bc2014-07-29 15:22:21 -07003116 adev->bt_wb_speech_enabled = false;
3117
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003118 *device = &adev->device.common;
3119
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003120 audio_extn_utils_update_streams_output_cfg_list(adev->platform, adev->mixer,
3121 &adev->streams_output_cfg_list);
3122
Kiran Kandi910e1862013-10-29 13:29:42 -07003123 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003124 pthread_mutex_unlock(&adev_init_lock);
3125
Eric Laurent994a6932013-07-17 11:51:42 -07003126 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003127 return 0;
3128}
3129
Mingming Yin07972cc2014-06-06 17:11:23 -07003130int pcm_ioctl(struct pcm *pcm, int request, ...)
3131{
3132 va_list ap;
3133 void * arg;
3134 int pcm_fd = *(int*)pcm;
3135
3136 va_start(ap, request);
3137 arg = va_arg(ap, void *);
3138 va_end(ap);
3139
3140 return ioctl(pcm_fd, request, arg);
3141}
3142
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003143static struct hw_module_methods_t hal_module_methods = {
3144 .open = adev_open,
3145};
3146
3147struct audio_module HAL_MODULE_INFO_SYM = {
3148 .common = {
3149 .tag = HARDWARE_MODULE_TAG,
3150 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
3151 .hal_api_version = HARDWARE_HAL_API_VERSION,
3152 .id = AUDIO_HARDWARE_MODULE_ID,
3153 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08003154 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003155 .methods = &hal_module_methods,
3156 },
3157};