blob: e9c3b56b98b8566e26078d6c2d6df299d786cc9d [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07002 * Copyright (c) 2013, The Linux Foundation. All rights reserved.
3 * Not a Contribution.
4 *
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005 * Copyright (C) 2013 The Android Open Source Project
6 *
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"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080053
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070054#include "sound/compress_params.h"
55
56#define COMPRESS_OFFLOAD_FRAGMENT_SIZE (32 * 1024)
57#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 4
58/* ToDo: Check and update a proper value in msec */
59#define COMPRESS_OFFLOAD_PLAYBACK_LATENCY 96
60#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
61
Eric Laurentb23d5282013-05-14 15:27:20 -070062struct pcm_config pcm_config_deep_buffer = {
63 .channels = 2,
64 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
65 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
66 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
67 .format = PCM_FORMAT_S16_LE,
68 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
69 .stop_threshold = INT_MAX,
70 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
71};
72
73struct pcm_config pcm_config_low_latency = {
74 .channels = 2,
75 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
76 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
77 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
78 .format = PCM_FORMAT_S16_LE,
79 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
80 .stop_threshold = INT_MAX,
81 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
82};
83
84struct pcm_config pcm_config_hdmi_multi = {
85 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
86 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
87 .period_size = HDMI_MULTI_PERIOD_SIZE,
88 .period_count = HDMI_MULTI_PERIOD_COUNT,
89 .format = PCM_FORMAT_S16_LE,
90 .start_threshold = 0,
91 .stop_threshold = INT_MAX,
92 .avail_min = 0,
93};
94
95struct pcm_config pcm_config_audio_capture = {
96 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -070097 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
98 .format = PCM_FORMAT_S16_LE,
99};
100
Eric Laurentb23d5282013-05-14 15:27:20 -0700101static const char * const use_case_table[AUDIO_USECASE_MAX] = {
102 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
103 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
104 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700105 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
Eric Laurentb23d5282013-05-14 15:27:20 -0700106 [USECASE_AUDIO_RECORD] = "audio-record",
107 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700108 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700109 [USECASE_VOICE_CALL] = "voice-call",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700110
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700111 [USECASE_VOICE2_CALL] = "voice2-call",
112 [USECASE_VOLTE_CALL] = "volte-call",
113 [USECASE_QCHAT_CALL] = "qchat-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700114 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
115 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
116 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700117 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
118 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Eric Laurentb23d5282013-05-14 15:27:20 -0700119};
120
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800121
122#define STRING_TO_ENUM(string) { #string, string }
123
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800124struct string_to_enum {
125 const char *name;
126 uint32_t value;
127};
128
129static const struct string_to_enum out_channels_name_to_enum_table[] = {
130 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
131 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
132 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
133};
134
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700135static struct audio_device *adev = NULL;
136static pthread_mutex_t adev_init_lock;
137static bool is_adev_initialised = false;
Haynes Mathew George5191a852013-09-11 14:19:36 -0700138static int set_voice_volume_l(struct audio_device *adev, float volume);
139
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700140static bool is_supported_format(audio_format_t format)
141{
Eric Laurent86e17132013-09-12 17:49:30 -0700142 if (format == AUDIO_FORMAT_MP3 ||
143 format == AUDIO_FORMAT_AAC)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700144 return true;
145
146 return false;
147}
148
149static int get_snd_codec_id(audio_format_t format)
150{
151 int id = 0;
152
153 switch (format) {
154 case AUDIO_FORMAT_MP3:
155 id = SND_AUDIOCODEC_MP3;
156 break;
157 case AUDIO_FORMAT_AAC:
158 id = SND_AUDIOCODEC_AAC;
159 break;
160 default:
161 ALOGE("%s: Unsupported audio format", __func__);
162 }
163
164 return id;
165}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800166
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700167static int enable_audio_route(struct audio_device *adev,
168 struct audio_usecase *usecase,
169 bool update_mixer)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800170{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700171 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700172 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800173
174 if (usecase == NULL)
175 return -EINVAL;
176
177 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
178
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800179 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700180 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800181 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700182 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800183
184 strcpy(mixer_path, use_case_table[usecase->id]);
Eric Laurentb23d5282013-05-14 15:27:20 -0700185 platform_add_backend_name(mixer_path, snd_device);
Eric Laurent994a6932013-07-17 11:51:42 -0700186 ALOGV("%s: apply mixer path: %s", __func__, mixer_path);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700187 audio_route_apply_path(adev->audio_route, mixer_path);
188 if (update_mixer)
189 audio_route_update_mixer(adev->audio_route);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800190
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800191 ALOGV("%s: exit", __func__);
192 return 0;
193}
194
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700195int disable_audio_route(struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700196 struct audio_usecase *usecase,
197 bool update_mixer)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800198{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700199 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700200 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800201
202 if (usecase == NULL)
203 return -EINVAL;
204
205 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700206 if (usecase->type == PCM_CAPTURE)
207 snd_device = usecase->in_snd_device;
208 else
209 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800210 strcpy(mixer_path, use_case_table[usecase->id]);
Eric Laurentb23d5282013-05-14 15:27:20 -0700211 platform_add_backend_name(mixer_path, snd_device);
Eric Laurent994a6932013-07-17 11:51:42 -0700212 ALOGV("%s: reset mixer path: %s", __func__, mixer_path);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700213 audio_route_reset_path(adev->audio_route, mixer_path);
214 if (update_mixer)
215 audio_route_update_mixer(adev->audio_route);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800216
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800217 ALOGV("%s: exit", __func__);
218 return 0;
219}
220
221static int enable_snd_device(struct audio_device *adev,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700222 snd_device_t snd_device,
223 bool update_mixer)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800224{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800225 if (snd_device < SND_DEVICE_MIN ||
226 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800227 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800228 return -EINVAL;
229 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700230
231 adev->snd_dev_ref_cnt[snd_device]++;
232 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700233 ALOGV("%s: snd_device(%d: %s) is already active",
Eric Laurentb23d5282013-05-14 15:27:20 -0700234 __func__, snd_device, platform_get_snd_device_name(snd_device));
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700235 return 0;
236 }
237
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700238 /* start usb playback thread */
239 if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
240 SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
241 audio_extn_usb_start_playback(adev);
242
243 /* start usb capture thread */
244 if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
245 audio_extn_usb_start_capture(adev);
246
Eric Laurentb23d5282013-05-14 15:27:20 -0700247 if (platform_send_audio_calibration(adev->platform, snd_device) < 0) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700248 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800249 return -EINVAL;
250 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800251
Eric Laurent994a6932013-07-17 11:51:42 -0700252 ALOGV("%s: snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -0700253 snd_device, platform_get_snd_device_name(snd_device));
254 audio_route_apply_path(adev->audio_route, platform_get_snd_device_name(snd_device));
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700255 if (update_mixer)
256 audio_route_update_mixer(adev->audio_route);
257
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800258 return 0;
259}
260
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700261int disable_snd_device(struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700262 snd_device_t snd_device,
263 bool update_mixer)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800264{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800265 if (snd_device < SND_DEVICE_MIN ||
266 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800267 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800268 return -EINVAL;
269 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700270 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
271 ALOGE("%s: device ref cnt is already 0", __func__);
272 return -EINVAL;
273 }
274 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700275
276 /* exit usb play back thread */
277 if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
278 SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
279 audio_extn_usb_stop_playback();
280
281 /* exit usb capture thread */
282 if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
283 audio_extn_usb_stop_capture(adev);
284
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700285 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Eric Laurent994a6932013-07-17 11:51:42 -0700286 ALOGV("%s: snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -0700287 snd_device, platform_get_snd_device_name(snd_device));
288 audio_route_reset_path(adev->audio_route, platform_get_snd_device_name(snd_device));
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700289 if (update_mixer)
290 audio_route_update_mixer(adev->audio_route);
291 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800292 return 0;
293}
294
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700295static void check_usecases_codec_backend(struct audio_device *adev,
296 struct audio_usecase *uc_info,
297 snd_device_t snd_device)
298{
299 struct listnode *node;
300 struct audio_usecase *usecase;
301 bool switch_device[AUDIO_USECASE_MAX];
302 int i, num_uc_to_switch = 0;
303
304 /*
305 * This function is to make sure that all the usecases that are active on
306 * the hardware codec backend are always routed to any one device that is
307 * handled by the hardware codec.
308 * For example, if low-latency and deep-buffer usecases are currently active
309 * on speaker and out_set_parameters(headset) is received on low-latency
310 * output, then we have to make sure deep-buffer is also switched to headset,
311 * because of the limitation that both the devices cannot be enabled
312 * at the same time as they share the same backend.
313 */
314 /* Disable all the usecases on the shared backend other than the
315 specified usecase */
316 for (i = 0; i < AUDIO_USECASE_MAX; i++)
317 switch_device[i] = false;
318
319 list_for_each(node, &adev->usecase_list) {
320 usecase = node_to_item(node, struct audio_usecase, list);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700321 if (usecase->type == PCM_PLAYBACK &&
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700322 usecase != uc_info &&
323 usecase->out_snd_device != snd_device &&
324 usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
325 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
326 __func__, use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700327 platform_get_snd_device_name(usecase->out_snd_device));
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700328 disable_audio_route(adev, usecase, false);
329 switch_device[usecase->id] = true;
330 num_uc_to_switch++;
331 }
332 }
333
334 if (num_uc_to_switch) {
335 /* Make sure all the streams are de-routed before disabling the device */
336 audio_route_update_mixer(adev->audio_route);
337
338 list_for_each(node, &adev->usecase_list) {
339 usecase = node_to_item(node, struct audio_usecase, list);
340 if (switch_device[usecase->id]) {
341 disable_snd_device(adev, usecase->out_snd_device, false);
342 enable_snd_device(adev, snd_device, false);
343 }
344 }
345
346 /* Make sure new snd device is enabled before re-routing the streams */
347 audio_route_update_mixer(adev->audio_route);
348
349 /* Re-route all the usecases on the shared backend other than the
350 specified usecase to new snd devices */
351 list_for_each(node, &adev->usecase_list) {
352 usecase = node_to_item(node, struct audio_usecase, list);
353 /* Update the out_snd_device only before enabling the audio route */
354 if (switch_device[usecase->id] ) {
355 usecase->out_snd_device = snd_device;
356 enable_audio_route(adev, usecase, false);
357 }
358 }
359
360 audio_route_update_mixer(adev->audio_route);
361 }
362}
363
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700364static void check_and_route_capture_usecases(struct audio_device *adev,
365 struct audio_usecase *uc_info,
366 snd_device_t snd_device)
367{
368 struct listnode *node;
369 struct audio_usecase *usecase;
370 bool switch_device[AUDIO_USECASE_MAX];
371 int i, num_uc_to_switch = 0;
372
373 /*
374 * This function is to make sure that all the active capture usecases
375 * are always routed to the same input sound device.
376 * For example, if audio-record and voice-call usecases are currently
377 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
378 * is received for voice call then we have to make sure that audio-record
379 * usecase is also switched to earpiece i.e. voice-dmic-ef,
380 * because of the limitation that two devices cannot be enabled
381 * at the same time if they share the same backend.
382 */
383 for (i = 0; i < AUDIO_USECASE_MAX; i++)
384 switch_device[i] = false;
385
386 list_for_each(node, &adev->usecase_list) {
387 usecase = node_to_item(node, struct audio_usecase, list);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700388 if (usecase->type == PCM_CAPTURE &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700389 usecase != uc_info &&
390 usecase->in_snd_device != snd_device) {
391 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
392 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700393 platform_get_snd_device_name(usecase->in_snd_device));
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700394 disable_audio_route(adev, usecase, false);
395 switch_device[usecase->id] = true;
396 num_uc_to_switch++;
397 }
398 }
399
400 if (num_uc_to_switch) {
401 /* Make sure all the streams are de-routed before disabling the device */
402 audio_route_update_mixer(adev->audio_route);
403
404 list_for_each(node, &adev->usecase_list) {
405 usecase = node_to_item(node, struct audio_usecase, list);
406 if (switch_device[usecase->id]) {
407 disable_snd_device(adev, usecase->in_snd_device, false);
408 enable_snd_device(adev, snd_device, false);
409 }
410 }
411
412 /* Make sure new snd device is enabled before re-routing the streams */
413 audio_route_update_mixer(adev->audio_route);
414
415 /* Re-route all the usecases on the shared backend other than the
416 specified usecase to new snd devices */
417 list_for_each(node, &adev->usecase_list) {
418 usecase = node_to_item(node, struct audio_usecase, list);
419 /* Update the in_snd_device only before enabling the audio route */
420 if (switch_device[usecase->id] ) {
421 usecase->in_snd_device = snd_device;
422 enable_audio_route(adev, usecase, false);
423 }
424 }
425
426 audio_route_update_mixer(adev->audio_route);
427 }
428}
429
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700430static int disable_all_usecases_of_type(struct audio_device *adev,
431 usecase_type_t usecase_type,
432 bool update_mixer)
433{
434 struct audio_usecase *usecase;
435 struct listnode *node;
436 int ret = 0;
437
438 list_for_each(node, &adev->usecase_list) {
439 usecase = node_to_item(node, struct audio_usecase, list);
440 if (usecase->type == usecase_type) {
441 ALOGV("%s: usecase id %d", __func__, usecase->id);
442 ret = disable_audio_route(adev, usecase, update_mixer);
443 if (ret) {
444 ALOGE("%s: Failed to disable usecase id %d",
445 __func__, usecase->id);
446 }
447 }
448 }
449
450 return ret;
451}
452
453static int enable_all_usecases_of_type(struct audio_device *adev,
454 usecase_type_t usecase_type,
455 bool update_mixer)
456{
457 struct audio_usecase *usecase;
458 struct listnode *node;
459 int ret = 0;
460
461 list_for_each(node, &adev->usecase_list) {
462 usecase = node_to_item(node, struct audio_usecase, list);
463 if (usecase->type == usecase_type) {
464 ALOGV("%s: usecase id %d", __func__, usecase->id);
465 ret = enable_audio_route(adev, usecase, update_mixer);
466 if (ret) {
467 ALOGE("%s: Failed to enable usecase id %d",
468 __func__, usecase->id);
469 }
470 }
471 }
472
473 return ret;
474}
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800475
476/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700477static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800478{
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700479 int ret = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700480 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800481
482 switch (channels) {
483 /*
484 * Do not handle stereo output in Multi-channel cases
485 * Stereo case is handled in normal playback path
486 */
487 case 6:
488 ALOGV("%s: HDMI supports 5.1", __func__);
489 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
490 break;
491 case 8:
492 ALOGV("%s: HDMI supports 5.1 and 7.1 channels", __func__);
493 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
494 out->supported_channel_masks[1] = AUDIO_CHANNEL_OUT_7POINT1;
495 break;
496 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700497 ALOGE("HDMI does not support multi channel playback");
498 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800499 break;
500 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700501 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800502}
503
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700504static audio_usecase_t get_voice_usecase_id_from_list(struct audio_device *adev)
505{
506 struct audio_usecase *usecase;
507 struct listnode *node;
508
509 list_for_each(node, &adev->usecase_list) {
510 usecase = node_to_item(node, struct audio_usecase, list);
511 if (usecase->type == VOICE_CALL) {
512 ALOGV("%s: usecase id %d", __func__, usecase->id);
513 return usecase->id;
514 }
515 }
516 return USECASE_INVALID;
517}
518
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700519struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700520 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700521{
522 struct audio_usecase *usecase;
523 struct listnode *node;
524
525 list_for_each(node, &adev->usecase_list) {
526 usecase = node_to_item(node, struct audio_usecase, list);
527 if (usecase->id == uc_id)
528 return usecase;
529 }
530 return NULL;
531}
532
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700533int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800534{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800535 snd_device_t out_snd_device = SND_DEVICE_NONE;
536 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700537 struct audio_usecase *usecase = NULL;
538 struct audio_usecase *vc_usecase = NULL;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800539 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700540 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800541
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700542 usecase = get_usecase_from_list(adev, uc_id);
543 if (usecase == NULL) {
544 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
545 return -EINVAL;
546 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800547
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700548 if (usecase->type == VOICE_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700549 out_snd_device = platform_get_output_snd_device(adev->platform,
550 usecase->stream.out->devices);
551 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700552 usecase->devices = usecase->stream.out->devices;
553 } else {
554 /*
555 * If the voice call is active, use the sound devices of voice call usecase
556 * so that it would not result any device switch. All the usecases will
557 * be switched to new device when select_devices() is called for voice call
558 * usecase. This is to avoid switching devices for voice call when
559 * check_usecases_codec_backend() is called below.
560 */
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700561 if (voice_is_in_call(adev)) {
562 vc_usecase = get_usecase_from_list(adev,
563 get_voice_usecase_id_from_list(adev));
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700564 if (vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
565 in_snd_device = vc_usecase->in_snd_device;
566 out_snd_device = vc_usecase->out_snd_device;
567 }
568 }
569 if (usecase->type == PCM_PLAYBACK) {
570 usecase->devices = usecase->stream.out->devices;
571 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700572 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700573 out_snd_device = platform_get_output_snd_device(adev->platform,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700574 usecase->stream.out->devices);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700575 if (usecase->stream.out == adev->primary_output &&
576 adev->active_input &&
577 adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
578 select_devices(adev, adev->active_input->usecase);
579 }
580 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700581 } else if (usecase->type == PCM_CAPTURE) {
582 usecase->devices = usecase->stream.in->device;
583 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700584 if (in_snd_device == SND_DEVICE_NONE) {
585 if (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
586 adev->primary_output && !adev->primary_output->standby) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700587 in_snd_device = platform_get_input_snd_device(adev->platform,
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700588 adev->primary_output->devices);
589 } else {
Eric Laurentb23d5282013-05-14 15:27:20 -0700590 in_snd_device = platform_get_input_snd_device(adev->platform,
591 AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700592 }
593 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700594 }
595 }
596
597 if (out_snd_device == usecase->out_snd_device &&
598 in_snd_device == usecase->in_snd_device) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800599 return 0;
600 }
601
sangwoobc677242013-08-08 16:53:43 +0900602 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -0700603 out_snd_device, platform_get_snd_device_name(out_snd_device),
604 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800605
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800606 /*
607 * Limitation: While in call, to do a device switch we need to disable
608 * and enable both RX and TX devices though one of them is same as current
609 * device.
610 */
Eric Laurentb23d5282013-05-14 15:27:20 -0700611 if (usecase->type == VOICE_CALL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700612 disable_all_usecases_of_type(adev, VOICE_CALL, true);
Eric Laurentb23d5282013-05-14 15:27:20 -0700613 status = platform_switch_voice_call_device_pre(adev->platform);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800614 }
615
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700616 /* Disable current sound devices */
617 if (usecase->out_snd_device != SND_DEVICE_NONE) {
618 disable_audio_route(adev, usecase, true);
619 disable_snd_device(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800620 }
621
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700622 if (usecase->in_snd_device != SND_DEVICE_NONE) {
623 disable_audio_route(adev, usecase, true);
624 disable_snd_device(adev, usecase->in_snd_device, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800625 }
626
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700627 /* Enable new sound devices */
628 if (out_snd_device != SND_DEVICE_NONE) {
629 if (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)
630 check_usecases_codec_backend(adev, usecase, out_snd_device);
631 enable_snd_device(adev, out_snd_device, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800632 }
633
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700634 if (in_snd_device != SND_DEVICE_NONE) {
635 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700636 enable_snd_device(adev, in_snd_device, false);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700637 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700638
Eric Laurentb23d5282013-05-14 15:27:20 -0700639 if (usecase->type == VOICE_CALL)
640 status = platform_switch_voice_call_device_post(adev->platform,
641 out_snd_device,
642 in_snd_device);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800643
sangwoo170731f2013-06-08 15:36:36 +0900644 audio_route_update_mixer(adev->audio_route);
645
646 usecase->in_snd_device = in_snd_device;
647 usecase->out_snd_device = out_snd_device;
648
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700649 if (usecase->type == VOICE_CALL)
650 enable_all_usecases_of_type(adev, VOICE_CALL, true);
651 else
652 enable_audio_route(adev, usecase, true);
sangwoo170731f2013-06-08 15:36:36 +0900653
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800654 return status;
655}
656
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800657static int stop_input_stream(struct stream_in *in)
658{
659 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800660 struct audio_usecase *uc_info;
661 struct audio_device *adev = in->dev;
662
Eric Laurentc8400632013-02-14 19:04:54 -0800663 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800664
Eric Laurent994a6932013-07-17 11:51:42 -0700665 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700666 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800667 uc_info = get_usecase_from_list(adev, in->usecase);
668 if (uc_info == NULL) {
669 ALOGE("%s: Could not find the usecase (%d) in the list",
670 __func__, in->usecase);
671 return -EINVAL;
672 }
673
Eric Laurent150dbfe2013-02-27 14:31:02 -0800674 /* 1. Disable stream specific mixer controls */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700675 disable_audio_route(adev, uc_info, true);
676
677 /* 2. Disable the tx device */
678 disable_snd_device(adev, uc_info->in_snd_device, true);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800679
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800680 list_remove(&uc_info->list);
681 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800682
Eric Laurent994a6932013-07-17 11:51:42 -0700683 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800684 return ret;
685}
686
687int start_input_stream(struct stream_in *in)
688{
689 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -0800690 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800691 struct audio_usecase *uc_info;
692 struct audio_device *adev = in->dev;
693
Eric Laurent994a6932013-07-17 11:51:42 -0700694 ALOGV("%s: enter: usecase(%d)", __func__, in->usecase);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700695
696 /* Check if source matches incall recording usecase criteria */
697 ret = voice_check_and_set_incall_rec_usecase(adev, in);
698 if (ret)
699 goto error_config;
700 else
701 ALOGV("%s: usecase(%d)", __func__, in->usecase);
702
Eric Laurentb23d5282013-05-14 15:27:20 -0700703 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800704 if (in->pcm_device_id < 0) {
705 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
706 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -0800707 ret = -EINVAL;
708 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800709 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700710
711 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800712 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
713 uc_info->id = in->usecase;
714 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800715 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700716 uc_info->devices = in->device;
717 uc_info->in_snd_device = SND_DEVICE_NONE;
718 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800719
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800720 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700721 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800722
Eric Laurentc8400632013-02-14 19:04:54 -0800723 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
724 __func__, SOUND_CARD, in->pcm_device_id, in->config.channels);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800725 in->pcm = pcm_open(SOUND_CARD, in->pcm_device_id,
726 PCM_IN, &in->config);
727 if (in->pcm && !pcm_is_ready(in->pcm)) {
728 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
729 pcm_close(in->pcm);
730 in->pcm = NULL;
Eric Laurentc8400632013-02-14 19:04:54 -0800731 ret = -EIO;
732 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800733 }
Eric Laurent994a6932013-07-17 11:51:42 -0700734 ALOGV("%s: exit", __func__);
Eric Laurentc8400632013-02-14 19:04:54 -0800735 return ret;
736
737error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800738 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -0800739
740error_config:
741 adev->active_input = NULL;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700742 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -0800743
744 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800745}
746
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700747/* must be called with out->lock locked */
748static int send_offload_cmd_l(struct stream_out* out, int command)
749{
750 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
751
752 ALOGVV("%s %d", __func__, command);
753
754 cmd->cmd = command;
755 list_add_tail(&out->offload_cmd_list, &cmd->node);
756 pthread_cond_signal(&out->offload_cond);
757 return 0;
758}
759
760/* must be called iwth out->lock locked */
761static void stop_compressed_output_l(struct stream_out *out)
762{
763 out->offload_state = OFFLOAD_STATE_IDLE;
764 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -0700765 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700766 if (out->compr != NULL) {
767 compress_stop(out->compr);
768 while (out->offload_thread_blocked) {
769 pthread_cond_wait(&out->cond, &out->lock);
770 }
771 }
772}
773
774static void *offload_thread_loop(void *context)
775{
776 struct stream_out *out = (struct stream_out *) context;
777 struct listnode *item;
778
779 out->offload_state = OFFLOAD_STATE_IDLE;
780 out->playback_started = 0;
781
782 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
783 set_sched_policy(0, SP_FOREGROUND);
784 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
785
786 ALOGV("%s", __func__);
787 pthread_mutex_lock(&out->lock);
788 for (;;) {
789 struct offload_cmd *cmd = NULL;
790 stream_callback_event_t event;
791 bool send_callback = false;
792
793 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
794 __func__, list_empty(&out->offload_cmd_list),
795 out->offload_state);
796 if (list_empty(&out->offload_cmd_list)) {
797 ALOGV("%s SLEEPING", __func__);
798 pthread_cond_wait(&out->offload_cond, &out->lock);
799 ALOGV("%s RUNNING", __func__);
800 continue;
801 }
802
803 item = list_head(&out->offload_cmd_list);
804 cmd = node_to_item(item, struct offload_cmd, node);
805 list_remove(item);
806
807 ALOGVV("%s STATE %d CMD %d out->compr %p",
808 __func__, out->offload_state, cmd->cmd, out->compr);
809
810 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
811 free(cmd);
812 break;
813 }
814
815 if (out->compr == NULL) {
816 ALOGE("%s: Compress handle is NULL", __func__);
817 pthread_cond_signal(&out->cond);
818 continue;
819 }
820 out->offload_thread_blocked = true;
821 pthread_mutex_unlock(&out->lock);
822 send_callback = false;
823 switch(cmd->cmd) {
824 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
825 compress_wait(out->compr, -1);
826 send_callback = true;
827 event = STREAM_CBK_EVENT_WRITE_READY;
828 break;
829 case OFFLOAD_CMD_PARTIAL_DRAIN:
Haynes Mathew George352f27b2013-07-26 00:00:15 -0700830 compress_next_track(out->compr);
831 compress_partial_drain(out->compr);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700832 send_callback = true;
833 event = STREAM_CBK_EVENT_DRAIN_READY;
834 break;
835 case OFFLOAD_CMD_DRAIN:
836 compress_drain(out->compr);
837 send_callback = true;
838 event = STREAM_CBK_EVENT_DRAIN_READY;
839 break;
840 default:
841 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
842 break;
843 }
844 pthread_mutex_lock(&out->lock);
845 out->offload_thread_blocked = false;
846 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -0700847 if (send_callback) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700848 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -0700849 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700850 free(cmd);
851 }
852
853 pthread_cond_signal(&out->cond);
854 while (!list_empty(&out->offload_cmd_list)) {
855 item = list_head(&out->offload_cmd_list);
856 list_remove(item);
857 free(node_to_item(item, struct offload_cmd, node));
858 }
859 pthread_mutex_unlock(&out->lock);
860
861 return NULL;
862}
863
864static int create_offload_callback_thread(struct stream_out *out)
865{
866 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
867 list_init(&out->offload_cmd_list);
868 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
869 offload_thread_loop, out);
870 return 0;
871}
872
873static int destroy_offload_callback_thread(struct stream_out *out)
874{
875 pthread_mutex_lock(&out->lock);
876 stop_compressed_output_l(out);
877 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
878
879 pthread_mutex_unlock(&out->lock);
880 pthread_join(out->offload_thread, (void **) NULL);
881 pthread_cond_destroy(&out->offload_cond);
882
883 return 0;
884}
885
Eric Laurent07eeafd2013-10-06 12:52:49 -0700886static bool allow_hdmi_channel_config(struct audio_device *adev)
887{
888 struct listnode *node;
889 struct audio_usecase *usecase;
890 bool ret = true;
891
892 list_for_each(node, &adev->usecase_list) {
893 usecase = node_to_item(node, struct audio_usecase, list);
894 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
895 /*
896 * If voice call is already existing, do not proceed further to avoid
897 * disabling/enabling both RX and TX devices, CSD calls, etc.
898 * Once the voice call done, the HDMI channels can be configured to
899 * max channels of remaining use cases.
900 */
901 if (usecase->id == USECASE_VOICE_CALL) {
902 ALOGD("%s: voice call is active, no change in HDMI channels",
903 __func__);
904 ret = false;
905 break;
906 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
907 ALOGD("%s: multi channel playback is active, "
908 "no change in HDMI channels", __func__);
909 ret = false;
910 break;
911 }
912 }
913 }
914 return ret;
915}
916
917static int check_and_set_hdmi_channels(struct audio_device *adev,
918 unsigned int channels)
919{
920 struct listnode *node;
921 struct audio_usecase *usecase;
922
923 /* Check if change in HDMI channel config is allowed */
924 if (!allow_hdmi_channel_config(adev))
925 return 0;
926
927 if (channels == adev->cur_hdmi_channels) {
928 ALOGD("%s: Requested channels are same as current", __func__);
929 return 0;
930 }
931
932 platform_set_hdmi_channels(adev->platform, channels);
933 adev->cur_hdmi_channels = channels;
934
935 /*
936 * Deroute all the playback streams routed to HDMI so that
937 * the back end is deactivated. Note that backend will not
938 * be deactivated if any one stream is connected to it.
939 */
940 list_for_each(node, &adev->usecase_list) {
941 usecase = node_to_item(node, struct audio_usecase, list);
942 if (usecase->type == PCM_PLAYBACK &&
943 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
944 disable_audio_route(adev, usecase, true);
945 }
946 }
947
948 /*
949 * Enable all the streams disabled above. Now the HDMI backend
950 * will be activated with new channel configuration
951 */
952 list_for_each(node, &adev->usecase_list) {
953 usecase = node_to_item(node, struct audio_usecase, list);
954 if (usecase->type == PCM_PLAYBACK &&
955 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
956 enable_audio_route(adev, usecase, true);
957 }
958 }
959
960 return 0;
961}
962
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800963static int stop_output_stream(struct stream_out *out)
964{
965 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800966 struct audio_usecase *uc_info;
967 struct audio_device *adev = out->dev;
968
Eric Laurent994a6932013-07-17 11:51:42 -0700969 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700970 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800971 uc_info = get_usecase_from_list(adev, out->usecase);
972 if (uc_info == NULL) {
973 ALOGE("%s: Could not find the usecase (%d) in the list",
974 __func__, out->usecase);
975 return -EINVAL;
976 }
977
Eric Laurentc4aef752013-09-12 17:45:53 -0700978 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD &&
979 adev->visualizer_stop_output != NULL)
980 adev->visualizer_stop_output(out->handle);
981
Eric Laurent150dbfe2013-02-27 14:31:02 -0800982 /* 1. Get and set stream specific mixer controls */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700983 disable_audio_route(adev, uc_info, true);
984
985 /* 2. Disable the rx device */
986 disable_snd_device(adev, uc_info->out_snd_device, true);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800987
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800988 list_remove(&uc_info->list);
989 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800990
Eric Laurent07eeafd2013-10-06 12:52:49 -0700991 /* Must be called after removing the usecase from list */
992 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
993 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
994
Eric Laurent994a6932013-07-17 11:51:42 -0700995 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800996 return ret;
997}
998
999int start_output_stream(struct stream_out *out)
1000{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001001 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001002 struct audio_usecase *uc_info;
1003 struct audio_device *adev = out->dev;
1004
Eric Laurent994a6932013-07-17 11:51:42 -07001005 ALOGV("%s: enter: usecase(%d: %s) devices(%#x)",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001006 __func__, out->usecase, use_case_table[out->usecase], out->devices);
Eric Laurentb23d5282013-05-14 15:27:20 -07001007 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001008 if (out->pcm_device_id < 0) {
1009 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1010 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001011 ret = -EINVAL;
1012 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001013 }
1014
1015 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1016 uc_info->id = out->usecase;
1017 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001018 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001019 uc_info->devices = out->devices;
1020 uc_info->in_snd_device = SND_DEVICE_NONE;
1021 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001022
Eric Laurent07eeafd2013-10-06 12:52:49 -07001023 /* This must be called before adding this usecase to the list */
1024 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1025 check_and_set_hdmi_channels(adev, out->config.channels);
1026
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001027 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001028
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001029 select_devices(adev, out->usecase);
1030
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001031 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d)",
1032 __func__, 0, out->pcm_device_id);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001033 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1034 out->pcm = pcm_open(SOUND_CARD, out->pcm_device_id,
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07001035 PCM_OUT | PCM_MONOTONIC, &out->config);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001036 if (out->pcm && !pcm_is_ready(out->pcm)) {
1037 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1038 pcm_close(out->pcm);
1039 out->pcm = NULL;
1040 ret = -EIO;
1041 goto error_open;
1042 }
1043 } else {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001044 out->pcm = NULL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001045 out->compr = compress_open(SOUND_CARD, out->pcm_device_id,
1046 COMPRESS_IN, &out->compr_config);
1047 if (out->compr && !is_compress_ready(out->compr)) {
1048 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1049 compress_close(out->compr);
1050 out->compr = NULL;
1051 ret = -EIO;
1052 goto error_open;
1053 }
1054 if (out->offload_callback)
1055 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07001056
1057 if (adev->visualizer_start_output != NULL)
1058 adev->visualizer_start_output(out->handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001059 }
Eric Laurent994a6932013-07-17 11:51:42 -07001060 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001061 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001062error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001063 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001064error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001065 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001066}
1067
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001068static int check_input_parameters(uint32_t sample_rate,
1069 audio_format_t format,
1070 int channel_count)
1071{
1072 if (format != AUDIO_FORMAT_PCM_16_BIT) return -EINVAL;
1073
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07001074 if ((channel_count < 1) || (channel_count > 6)) return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001075
1076 switch (sample_rate) {
1077 case 8000:
1078 case 11025:
1079 case 12000:
1080 case 16000:
1081 case 22050:
1082 case 24000:
1083 case 32000:
1084 case 44100:
1085 case 48000:
1086 break;
1087 default:
1088 return -EINVAL;
1089 }
1090
1091 return 0;
1092}
1093
1094static size_t get_input_buffer_size(uint32_t sample_rate,
1095 audio_format_t format,
1096 int channel_count)
1097{
1098 size_t size = 0;
1099
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001100 if (check_input_parameters(sample_rate, format, channel_count) != 0)
1101 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001102
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001103 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
1104 /* ToDo: should use frame_size computed based on the format and
1105 channel_count here. */
1106 size *= sizeof(short) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001107
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001108 /* make sure the size is multiple of 64 */
1109 size += 0x3f;
1110 size &= ~0x3f;
1111
1112 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001113}
1114
1115static uint32_t out_get_sample_rate(const struct audio_stream *stream)
1116{
1117 struct stream_out *out = (struct stream_out *)stream;
1118
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001119 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001120}
1121
1122static int out_set_sample_rate(struct audio_stream *stream, uint32_t rate)
1123{
1124 return -ENOSYS;
1125}
1126
1127static size_t out_get_buffer_size(const struct audio_stream *stream)
1128{
1129 struct stream_out *out = (struct stream_out *)stream;
1130
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001131 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1132 return out->compr_config.fragment_size;
1133 }
1134
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001135 return out->config.period_size * audio_stream_frame_size(stream);
1136}
1137
1138static uint32_t out_get_channels(const struct audio_stream *stream)
1139{
1140 struct stream_out *out = (struct stream_out *)stream;
1141
1142 return out->channel_mask;
1143}
1144
1145static audio_format_t out_get_format(const struct audio_stream *stream)
1146{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001147 struct stream_out *out = (struct stream_out *)stream;
1148
1149 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001150}
1151
1152static int out_set_format(struct audio_stream *stream, audio_format_t format)
1153{
1154 return -ENOSYS;
1155}
1156
1157static int out_standby(struct audio_stream *stream)
1158{
1159 struct stream_out *out = (struct stream_out *)stream;
1160 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001161
Eric Laurent994a6932013-07-17 11:51:42 -07001162 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001163 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001164
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001165 pthread_mutex_lock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001166 if (!out->standby) {
1167 out->standby = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001168 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1169 if (out->pcm) {
1170 pcm_close(out->pcm);
1171 out->pcm = NULL;
1172 }
1173 } else {
1174 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001175 out->gapless_mdata.encoder_delay = 0;
1176 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001177 if (out->compr != NULL) {
1178 compress_close(out->compr);
1179 out->compr = NULL;
1180 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08001181 }
1182 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001183 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001184 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001185 }
1186 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07001187 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001188 return 0;
1189}
1190
1191static int out_dump(const struct audio_stream *stream, int fd)
1192{
1193 return 0;
1194}
1195
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001196static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
1197{
1198 int ret = 0;
1199 char value[32];
1200 struct compr_gapless_mdata tmp_mdata;
1201
1202 if (!out || !parms) {
1203 return -EINVAL;
1204 }
1205
1206 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
1207 if (ret >= 0) {
1208 tmp_mdata.encoder_delay = atoi(value); //whats a good limit check?
1209 } else {
1210 return -EINVAL;
1211 }
1212
1213 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
1214 if (ret >= 0) {
1215 tmp_mdata.encoder_padding = atoi(value);
1216 } else {
1217 return -EINVAL;
1218 }
1219
1220 out->gapless_mdata = tmp_mdata;
1221 out->send_new_metadata = 1;
1222 ALOGV("%s new encoder delay %u and padding %u", __func__,
1223 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
1224
1225 return 0;
1226}
1227
1228
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001229static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
1230{
1231 struct stream_out *out = (struct stream_out *)stream;
1232 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001233 struct audio_usecase *usecase;
1234 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001235 struct str_parms *parms;
1236 char value[32];
1237 int ret, val = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001238 bool select_new_device = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001239
sangwoobc677242013-08-08 16:53:43 +09001240 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001241 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001242 parms = str_parms_create_str(kvpairs);
1243 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
1244 if (ret >= 0) {
1245 val = atoi(value);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001246 pthread_mutex_lock(&out->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001247 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001248
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001249 /*
1250 * When HDMI cable is unplugged the music playback is paused and
1251 * the policy manager sends routing=0. But the audioflinger
1252 * continues to write data until standby time (3sec).
1253 * As the HDMI core is turned off, the write gets blocked.
1254 * Avoid this by routing audio to speaker until standby.
1255 */
1256 if (out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL &&
1257 val == AUDIO_DEVICE_NONE) {
1258 val = AUDIO_DEVICE_OUT_SPEAKER;
1259 }
1260
1261 /*
1262 * select_devices() call below switches all the usecases on the same
1263 * backend to the new device. Refer to check_usecases_codec_backend() in
1264 * the select_devices(). But how do we undo this?
1265 *
1266 * For example, music playback is active on headset (deep-buffer usecase)
1267 * and if we go to ringtones and select a ringtone, low-latency usecase
1268 * will be started on headset+speaker. As we can't enable headset+speaker
1269 * and headset devices at the same time, select_devices() switches the music
1270 * playback to headset+speaker while starting low-lateny usecase for ringtone.
1271 * So when the ringtone playback is completed, how do we undo the same?
1272 *
1273 * We are relying on the out_set_parameters() call on deep-buffer output,
1274 * once the ringtone playback is ended.
1275 * NOTE: We should not check if the current devices are same as new devices.
1276 * Because select_devices() must be called to switch back the music
1277 * playback to headset.
1278 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001279 if (val != 0) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001280 out->devices = val;
1281
1282 if (!out->standby)
1283 select_devices(adev, out->usecase);
1284
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001285 if ((adev->mode == AUDIO_MODE_IN_CALL) &&
1286 !voice_is_in_call(adev) &&
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001287 (out == adev->primary_output)) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001288 voice_start_call(adev);
1289 } else if ((adev->mode == AUDIO_MODE_IN_CALL) &&
1290 voice_is_in_call(adev) &&
1291 (out == adev->primary_output)) {
1292 select_devices(adev, get_voice_usecase_id_from_list(adev));
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001293 }
1294 }
1295
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001296 if ((adev->mode == AUDIO_MODE_NORMAL) &&
1297 voice_is_in_call(adev) &&
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001298 (out == adev->primary_output)) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001299 voice_stop_call(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001300 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001301
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001302 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001303 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001304 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001305
1306 if (out == adev->primary_output) {
1307 pthread_mutex_lock(&adev->lock);
1308 audio_extn_set_parameters(adev, parms);
1309 pthread_mutex_unlock(&adev->lock);
1310 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001311 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1312 parse_compress_metadata(out, parms);
1313 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001314
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001315 str_parms_destroy(parms);
Eric Laurent994a6932013-07-17 11:51:42 -07001316 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001317 return ret;
1318}
1319
1320static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
1321{
1322 struct stream_out *out = (struct stream_out *)stream;
1323 struct str_parms *query = str_parms_create_str(keys);
1324 char *str;
1325 char value[256];
1326 struct str_parms *reply = str_parms_create();
1327 size_t i, j;
1328 int ret;
1329 bool first = true;
Eric Laurent994a6932013-07-17 11:51:42 -07001330 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001331 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
1332 if (ret >= 0) {
1333 value[0] = '\0';
1334 i = 0;
1335 while (out->supported_channel_masks[i] != 0) {
1336 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
1337 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
1338 if (!first) {
1339 strcat(value, "|");
1340 }
1341 strcat(value, out_channels_name_to_enum_table[j].name);
1342 first = false;
1343 break;
1344 }
1345 }
1346 i++;
1347 }
1348 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
1349 str = str_parms_to_str(reply);
1350 } else {
1351 str = strdup(keys);
1352 }
1353 str_parms_destroy(query);
1354 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07001355 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001356 return str;
1357}
1358
1359static uint32_t out_get_latency(const struct audio_stream_out *stream)
1360{
1361 struct stream_out *out = (struct stream_out *)stream;
1362
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001363 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
1364 return COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
1365
1366 return (out->config.period_count * out->config.period_size * 1000) /
1367 (out->config.rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001368}
1369
1370static int out_set_volume(struct audio_stream_out *stream, float left,
1371 float right)
1372{
Eric Laurenta9024de2013-04-04 09:19:12 -07001373 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001374 int volume[2];
1375
Eric Laurenta9024de2013-04-04 09:19:12 -07001376 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
1377 /* only take left channel into account: the API is for stereo anyway */
1378 out->muted = (left == 0.0f);
1379 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001380 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1381 const char *mixer_ctl_name = "Compress Playback Volume";
1382 struct audio_device *adev = out->dev;
1383 struct mixer_ctl *ctl;
1384
1385 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
1386 if (!ctl) {
1387 ALOGE("%s: Could not get ctl for mixer cmd - %s",
1388 __func__, mixer_ctl_name);
1389 return -EINVAL;
1390 }
1391 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
1392 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
1393 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
1394 return 0;
Eric Laurenta9024de2013-04-04 09:19:12 -07001395 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001396
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001397 return -ENOSYS;
1398}
1399
1400static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
1401 size_t bytes)
1402{
1403 struct stream_out *out = (struct stream_out *)stream;
1404 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07001405 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001406
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001407 pthread_mutex_lock(&out->lock);
1408 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001409 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08001410 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001411 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001412 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001413 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001414 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001415 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001416 goto exit;
1417 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001418 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001419
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001420 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001421 ALOGVV("%s: writing buffer (%d bytes) to compress device", __func__, bytes);
1422 if (out->send_new_metadata) {
1423 ALOGVV("send new gapless metadata");
1424 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
1425 out->send_new_metadata = 0;
1426 }
1427
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001428 ret = compress_write(out->compr, buffer, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001429 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %d", __func__, bytes, ret);
Eric Laurent6e895242013-09-05 16:10:57 -07001430 if (ret >= 0 && ret < (ssize_t)bytes) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001431 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
1432 }
1433 if (!out->playback_started) {
1434 compress_start(out->compr);
1435 out->playback_started = 1;
1436 out->offload_state = OFFLOAD_STATE_PLAYING;
1437 }
1438 pthread_mutex_unlock(&out->lock);
1439 return ret;
1440 } else {
1441 if (out->pcm) {
1442 if (out->muted)
1443 memset((void *)buffer, 0, bytes);
1444 ALOGVV("%s: writing buffer (%d bytes) to pcm device", __func__, bytes);
1445 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07001446 if (ret == 0)
1447 out->written += bytes / (out->config.channels * sizeof(short));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001448 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001449 }
1450
1451exit:
1452 pthread_mutex_unlock(&out->lock);
1453
1454 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001455 if (out->pcm)
1456 ALOGE("%s: error %d - %s", __func__, ret, pcm_get_error(out->pcm));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001457 out_standby(&out->stream.common);
1458 usleep(bytes * 1000000 / audio_stream_frame_size(&out->stream.common) /
1459 out_get_sample_rate(&out->stream.common));
1460 }
1461 return bytes;
1462}
1463
1464static int out_get_render_position(const struct audio_stream_out *stream,
1465 uint32_t *dsp_frames)
1466{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001467 struct stream_out *out = (struct stream_out *)stream;
1468 *dsp_frames = 0;
1469 if ((out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) && (dsp_frames != NULL)) {
1470 pthread_mutex_lock(&out->lock);
1471 if (out->compr != NULL) {
1472 compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
1473 &out->sample_rate);
1474 ALOGVV("%s rendered frames %d sample_rate %d",
1475 __func__, *dsp_frames, out->sample_rate);
1476 }
1477 pthread_mutex_unlock(&out->lock);
1478 return 0;
1479 } else
1480 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001481}
1482
1483static int out_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
1484{
1485 return 0;
1486}
1487
1488static int out_remove_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
1489{
1490 return 0;
1491}
1492
1493static int out_get_next_write_timestamp(const struct audio_stream_out *stream,
1494 int64_t *timestamp)
1495{
1496 return -EINVAL;
1497}
1498
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07001499static int out_get_presentation_position(const struct audio_stream_out *stream,
1500 uint64_t *frames, struct timespec *timestamp)
1501{
1502 struct stream_out *out = (struct stream_out *)stream;
1503 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07001504 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07001505
1506 pthread_mutex_lock(&out->lock);
1507
Eric Laurent949a0892013-09-20 09:20:13 -07001508 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1509 if (out->compr != NULL) {
1510 compress_get_tstamp(out->compr, &dsp_frames,
1511 &out->sample_rate);
1512 ALOGVV("%s rendered frames %ld sample_rate %d",
1513 __func__, dsp_frames, out->sample_rate);
1514 *frames = dsp_frames;
1515 ret = 0;
1516 /* this is the best we can do */
1517 clock_gettime(CLOCK_MONOTONIC, timestamp);
1518 }
1519 } else {
1520 if (out->pcm) {
1521 size_t avail;
1522 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
1523 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07001524 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07001525 // This adjustment accounts for buffering after app processor.
1526 // It is based on estimated DSP latency per use case, rather than exact.
1527 signed_frames -=
1528 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
1529
Eric Laurent949a0892013-09-20 09:20:13 -07001530 // It would be unusual for this value to be negative, but check just in case ...
1531 if (signed_frames >= 0) {
1532 *frames = signed_frames;
1533 ret = 0;
1534 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07001535 }
1536 }
1537 }
1538
1539 pthread_mutex_unlock(&out->lock);
1540
1541 return ret;
1542}
1543
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001544static int out_set_callback(struct audio_stream_out *stream,
1545 stream_callback_t callback, void *cookie)
1546{
1547 struct stream_out *out = (struct stream_out *)stream;
1548
1549 ALOGV("%s", __func__);
1550 pthread_mutex_lock(&out->lock);
1551 out->offload_callback = callback;
1552 out->offload_cookie = cookie;
1553 pthread_mutex_unlock(&out->lock);
1554 return 0;
1555}
1556
1557static int out_pause(struct audio_stream_out* stream)
1558{
1559 struct stream_out *out = (struct stream_out *)stream;
1560 int status = -ENOSYS;
1561 ALOGV("%s", __func__);
1562 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1563 pthread_mutex_lock(&out->lock);
1564 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
1565 status = compress_pause(out->compr);
1566 out->offload_state = OFFLOAD_STATE_PAUSED;
1567 }
1568 pthread_mutex_unlock(&out->lock);
1569 }
1570 return status;
1571}
1572
1573static int out_resume(struct audio_stream_out* stream)
1574{
1575 struct stream_out *out = (struct stream_out *)stream;
1576 int status = -ENOSYS;
1577 ALOGV("%s", __func__);
1578 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1579 status = 0;
1580 pthread_mutex_lock(&out->lock);
1581 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
1582 status = compress_resume(out->compr);
1583 out->offload_state = OFFLOAD_STATE_PLAYING;
1584 }
1585 pthread_mutex_unlock(&out->lock);
1586 }
1587 return status;
1588}
1589
1590static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
1591{
1592 struct stream_out *out = (struct stream_out *)stream;
1593 int status = -ENOSYS;
1594 ALOGV("%s", __func__);
1595 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1596 pthread_mutex_lock(&out->lock);
1597 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
1598 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
1599 else
1600 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
1601 pthread_mutex_unlock(&out->lock);
1602 }
1603 return status;
1604}
1605
1606static int out_flush(struct audio_stream_out* stream)
1607{
1608 struct stream_out *out = (struct stream_out *)stream;
1609 ALOGV("%s", __func__);
1610 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1611 pthread_mutex_lock(&out->lock);
1612 stop_compressed_output_l(out);
1613 pthread_mutex_unlock(&out->lock);
1614 return 0;
1615 }
1616 return -ENOSYS;
1617}
1618
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001619/** audio_stream_in implementation **/
1620static uint32_t in_get_sample_rate(const struct audio_stream *stream)
1621{
1622 struct stream_in *in = (struct stream_in *)stream;
1623
1624 return in->config.rate;
1625}
1626
1627static int in_set_sample_rate(struct audio_stream *stream, uint32_t rate)
1628{
1629 return -ENOSYS;
1630}
1631
1632static size_t in_get_buffer_size(const struct audio_stream *stream)
1633{
1634 struct stream_in *in = (struct stream_in *)stream;
1635
1636 return in->config.period_size * audio_stream_frame_size(stream);
1637}
1638
1639static uint32_t in_get_channels(const struct audio_stream *stream)
1640{
1641 struct stream_in *in = (struct stream_in *)stream;
1642
1643 return in->channel_mask;
1644}
1645
1646static audio_format_t in_get_format(const struct audio_stream *stream)
1647{
1648 return AUDIO_FORMAT_PCM_16_BIT;
1649}
1650
1651static int in_set_format(struct audio_stream *stream, audio_format_t format)
1652{
1653 return -ENOSYS;
1654}
1655
1656static int in_standby(struct audio_stream *stream)
1657{
1658 struct stream_in *in = (struct stream_in *)stream;
1659 struct audio_device *adev = in->dev;
1660 int status = 0;
Eric Laurent994a6932013-07-17 11:51:42 -07001661 ALOGV("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001662 pthread_mutex_lock(&in->lock);
1663 if (!in->standby) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001664 in->standby = true;
Eric Laurent150dbfe2013-02-27 14:31:02 -08001665 if (in->pcm) {
1666 pcm_close(in->pcm);
1667 in->pcm = NULL;
1668 }
1669 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001670 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001671 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001672 }
1673 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07001674 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001675 return status;
1676}
1677
1678static int in_dump(const struct audio_stream *stream, int fd)
1679{
1680 return 0;
1681}
1682
1683static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
1684{
1685 struct stream_in *in = (struct stream_in *)stream;
1686 struct audio_device *adev = in->dev;
1687 struct str_parms *parms;
1688 char *str;
1689 char value[32];
1690 int ret, val = 0;
1691
Eric Laurent994a6932013-07-17 11:51:42 -07001692 ALOGV("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001693 parms = str_parms_create_str(kvpairs);
1694
1695 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
1696
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001697 pthread_mutex_lock(&in->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001698 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001699 if (ret >= 0) {
1700 val = atoi(value);
1701 /* no audio source uses val == 0 */
1702 if ((in->source != val) && (val != 0)) {
1703 in->source = val;
1704 }
1705 }
1706
1707 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
1708 if (ret >= 0) {
1709 val = atoi(value);
1710 if ((in->device != val) && (val != 0)) {
1711 in->device = val;
1712 /* If recording is in progress, change the tx device to new device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001713 if (!in->standby)
1714 ret = select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001715 }
1716 }
1717
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001718 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001719 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001720
1721 str_parms_destroy(parms);
Eric Laurent994a6932013-07-17 11:51:42 -07001722 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001723 return ret;
1724}
1725
1726static char* in_get_parameters(const struct audio_stream *stream,
1727 const char *keys)
1728{
1729 return strdup("");
1730}
1731
1732static int in_set_gain(struct audio_stream_in *stream, float gain)
1733{
1734 return 0;
1735}
1736
1737static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
1738 size_t bytes)
1739{
1740 struct stream_in *in = (struct stream_in *)stream;
1741 struct audio_device *adev = in->dev;
1742 int i, ret = -1;
1743
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001744 pthread_mutex_lock(&in->lock);
1745 if (in->standby) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001746 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001747 ret = start_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001748 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001749 if (ret != 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001750 goto exit;
1751 }
1752 in->standby = 0;
1753 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001754
1755 if (in->pcm) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07001756 if (audio_extn_ssr_get_enabled() && popcount(in->channel_mask) == 6)
1757 ret = audio_extn_ssr_read(stream, buffer, bytes);
1758 else
1759 ret = pcm_read(in->pcm, buffer, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001760 }
1761
1762 /*
1763 * Instead of writing zeroes here, we could trust the hardware
1764 * to always provide zeroes when muted.
1765 */
Helen Zenge0b186f2013-10-23 14:00:59 -07001766 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call(adev))
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001767 memset(buffer, 0, bytes);
1768
1769exit:
1770 pthread_mutex_unlock(&in->lock);
1771
1772 if (ret != 0) {
1773 in_standby(&in->stream.common);
1774 ALOGV("%s: read failed - sleeping for buffer duration", __func__);
1775 usleep(bytes * 1000000 / audio_stream_frame_size(&in->stream.common) /
1776 in_get_sample_rate(&in->stream.common));
1777 }
1778 return bytes;
1779}
1780
1781static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream)
1782{
1783 return 0;
1784}
1785
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07001786static int add_remove_audio_effect(const struct audio_stream *stream,
1787 effect_handle_t effect,
1788 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001789{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07001790 struct stream_in *in = (struct stream_in *)stream;
1791 int status = 0;
1792 effect_descriptor_t desc;
1793
1794 status = (*effect)->get_descriptor(effect, &desc);
1795 if (status != 0)
1796 return status;
1797
1798 pthread_mutex_lock(&in->lock);
1799 pthread_mutex_lock(&in->dev->lock);
1800 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
1801 in->enable_aec != enable &&
1802 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
1803 in->enable_aec = enable;
1804 if (!in->standby)
1805 select_devices(in->dev, in->usecase);
1806 }
1807 pthread_mutex_unlock(&in->dev->lock);
1808 pthread_mutex_unlock(&in->lock);
1809
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001810 return 0;
1811}
1812
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07001813static int in_add_audio_effect(const struct audio_stream *stream,
1814 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001815{
Eric Laurent994a6932013-07-17 11:51:42 -07001816 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07001817 return add_remove_audio_effect(stream, effect, true);
1818}
1819
1820static int in_remove_audio_effect(const struct audio_stream *stream,
1821 effect_handle_t effect)
1822{
Eric Laurent994a6932013-07-17 11:51:42 -07001823 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07001824 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001825}
1826
1827static int adev_open_output_stream(struct audio_hw_device *dev,
1828 audio_io_handle_t handle,
1829 audio_devices_t devices,
1830 audio_output_flags_t flags,
1831 struct audio_config *config,
1832 struct audio_stream_out **stream_out)
1833{
1834 struct audio_device *adev = (struct audio_device *)dev;
1835 struct stream_out *out;
1836 int i, ret;
1837
Eric Laurent994a6932013-07-17 11:51:42 -07001838 ALOGV("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001839 __func__, config->sample_rate, config->channel_mask, devices, flags);
1840 *stream_out = NULL;
1841 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
1842
1843 if (devices == AUDIO_DEVICE_NONE)
1844 devices = AUDIO_DEVICE_OUT_SPEAKER;
1845
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001846 out->flags = flags;
1847 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001848 out->dev = adev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001849 out->format = config->format;
1850 out->sample_rate = config->sample_rate;
1851 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
1852 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07001853 out->handle = handle;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001854
1855 /* Init use case and pcm_config */
1856 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
1857 out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001858 pthread_mutex_lock(&adev->lock);
1859 ret = read_hdmi_channel_masks(out);
1860 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001861 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001862 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001863
1864 if (config->sample_rate == 0)
1865 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
1866 if (config->channel_mask == 0)
1867 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
1868
1869 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001870 out->sample_rate = config->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001871 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
1872 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001873 out->config.rate = config->sample_rate;
1874 out->config.channels = popcount(out->channel_mask);
1875 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001876 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
1877 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
1878 out->config = pcm_config_deep_buffer;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001879 out->sample_rate = out->config.rate;
1880 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
1881 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
1882 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
1883 ALOGE("%s: Unsupported Offload information", __func__);
1884 ret = -EINVAL;
1885 goto error_open;
1886 }
1887 if (!is_supported_format(config->offload_info.format)) {
1888 ALOGE("%s: Unsupported audio format", __func__);
1889 ret = -EINVAL;
1890 goto error_open;
1891 }
1892
1893 out->compr_config.codec = (struct snd_codec *)
1894 calloc(1, sizeof(struct snd_codec));
1895
1896 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
1897 if (config->offload_info.channel_mask)
1898 out->channel_mask = config->offload_info.channel_mask;
1899 else if (config->channel_mask)
1900 out->channel_mask = config->channel_mask;
1901 out->format = config->offload_info.format;
1902 out->sample_rate = config->offload_info.sample_rate;
1903
1904 out->stream.set_callback = out_set_callback;
1905 out->stream.pause = out_pause;
1906 out->stream.resume = out_resume;
1907 out->stream.drain = out_drain;
1908 out->stream.flush = out_flush;
1909
1910 out->compr_config.codec->id =
1911 get_snd_codec_id(config->offload_info.format);
1912 out->compr_config.fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
1913 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
1914 out->compr_config.codec->sample_rate =
1915 compress_get_alsa_rate(config->offload_info.sample_rate);
1916 out->compr_config.codec->bit_rate =
1917 config->offload_info.bit_rate;
1918 out->compr_config.codec->ch_in =
1919 popcount(config->channel_mask);
1920 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
1921
1922 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
1923 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001924
1925 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001926 create_offload_callback_thread(out);
1927 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
1928 __func__, config->offload_info.version,
1929 config->offload_info.bit_rate);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07001930 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
1931 ret = voice_check_and_set_incall_music_usecase(adev, out);
1932 if (ret != 0) {
1933 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
1934 __func__, ret);
1935 goto error_open;
1936 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001937 } else {
1938 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
1939 out->config = pcm_config_low_latency;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001940 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001941 }
1942
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001943 if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
1944 if(adev->primary_output == NULL)
1945 adev->primary_output = out;
1946 else {
1947 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001948 ret = -EEXIST;
1949 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001950 }
1951 }
1952
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001953 /* Check if this usecase is already existing */
1954 pthread_mutex_lock(&adev->lock);
1955 if (get_usecase_from_list(adev, out->usecase) != NULL) {
1956 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001957 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001958 ret = -EEXIST;
1959 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001960 }
1961 pthread_mutex_unlock(&adev->lock);
1962
1963 out->stream.common.get_sample_rate = out_get_sample_rate;
1964 out->stream.common.set_sample_rate = out_set_sample_rate;
1965 out->stream.common.get_buffer_size = out_get_buffer_size;
1966 out->stream.common.get_channels = out_get_channels;
1967 out->stream.common.get_format = out_get_format;
1968 out->stream.common.set_format = out_set_format;
1969 out->stream.common.standby = out_standby;
1970 out->stream.common.dump = out_dump;
1971 out->stream.common.set_parameters = out_set_parameters;
1972 out->stream.common.get_parameters = out_get_parameters;
1973 out->stream.common.add_audio_effect = out_add_audio_effect;
1974 out->stream.common.remove_audio_effect = out_remove_audio_effect;
1975 out->stream.get_latency = out_get_latency;
1976 out->stream.set_volume = out_set_volume;
1977 out->stream.write = out_write;
1978 out->stream.get_render_position = out_get_render_position;
1979 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07001980 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001981
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001982 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07001983 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07001984 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001985
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001986 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
1987 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001988
1989 config->format = out->stream.common.get_format(&out->stream.common);
1990 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
1991 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
1992
1993 *stream_out = &out->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07001994 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001995 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001996
1997error_open:
1998 free(out);
1999 *stream_out = NULL;
2000 ALOGD("%s: exit: ret %d", __func__, ret);
2001 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002002}
2003
2004static void adev_close_output_stream(struct audio_hw_device *dev,
2005 struct audio_stream_out *stream)
2006{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002007 struct stream_out *out = (struct stream_out *)stream;
2008 struct audio_device *adev = out->dev;
2009
Eric Laurent994a6932013-07-17 11:51:42 -07002010 ALOGV("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002011 out_standby(&stream->common);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002012 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2013 destroy_offload_callback_thread(out);
2014
2015 if (out->compr_config.codec != NULL)
2016 free(out->compr_config.codec);
2017 }
2018 pthread_cond_destroy(&out->cond);
2019 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002020 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07002021 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002022}
2023
2024static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
2025{
2026 struct audio_device *adev = (struct audio_device *)dev;
2027 struct str_parms *parms;
2028 char *str;
2029 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07002030 int val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002031 int ret;
2032
Eric Laurent994a6932013-07-17 11:51:42 -07002033 ALOGV("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002034 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002035
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002036 voice_set_parameters(adev, parms);
2037 platform_set_parameters(adev->platform, parms);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002038
2039 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
2040 if (ret >= 0) {
2041 /* When set to false, HAL should disable EC and NS
2042 * But it is currently not supported.
2043 */
2044 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
2045 adev->bluetooth_nrec = true;
2046 else
2047 adev->bluetooth_nrec = false;
2048 }
2049
2050 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
2051 if (ret >= 0) {
2052 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
2053 adev->screen_off = false;
2054 else
2055 adev->screen_off = true;
2056 }
2057
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07002058 ret = str_parms_get_int(parms, "rotation", &val);
2059 if (ret >= 0) {
2060 bool reverse_speakers = false;
2061 switch(val) {
2062 // FIXME: note that the code below assumes that the speakers are in the correct placement
2063 // relative to the user when the device is rotated 90deg from its default rotation. This
2064 // assumption is device-specific, not platform-specific like this code.
2065 case 270:
2066 reverse_speakers = true;
2067 break;
2068 case 0:
2069 case 90:
2070 case 180:
2071 break;
2072 default:
2073 ALOGE("%s: unexpected rotation of %d", __func__, val);
2074 }
2075 pthread_mutex_lock(&adev->lock);
2076 if (adev->speaker_lr_swap != reverse_speakers) {
2077 adev->speaker_lr_swap = reverse_speakers;
2078 // only update the selected device if there is active pcm playback
2079 struct audio_usecase *usecase;
2080 struct listnode *node;
2081 list_for_each(node, &adev->usecase_list) {
2082 usecase = node_to_item(node, struct audio_usecase, list);
2083 if (usecase->type == PCM_PLAYBACK) {
2084 select_devices(adev, usecase->id);
2085 break;
2086 }
2087 }
2088 }
2089 pthread_mutex_unlock(&adev->lock);
2090 }
2091
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07002092 audio_extn_set_parameters(adev, parms);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002093 str_parms_destroy(parms);
Eric Laurent994a6932013-07-17 11:51:42 -07002094 ALOGV("%s: exit with code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002095 return ret;
2096}
2097
2098static char* adev_get_parameters(const struct audio_hw_device *dev,
2099 const char *keys)
2100{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002101 struct audio_device *adev = (struct audio_device *)dev;
2102 struct str_parms *reply = str_parms_create();
2103 struct str_parms *query = str_parms_create_str(keys);
2104 char *str;
2105
2106 audio_extn_get_parameters(adev, query, reply);
2107 platform_get_parameters(adev->platform, query, reply);
2108 str = str_parms_to_str(reply);
2109 str_parms_destroy(query);
2110 str_parms_destroy(reply);
2111
2112 ALOGV("%s: exit: returns - %s", __func__, str);
2113 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002114}
2115
2116static int adev_init_check(const struct audio_hw_device *dev)
2117{
2118 return 0;
2119}
2120
2121static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
2122{
Haynes Mathew George5191a852013-09-11 14:19:36 -07002123 int ret;
2124 struct audio_device *adev = (struct audio_device *)dev;
2125 pthread_mutex_lock(&adev->lock);
2126 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07002127 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07002128 pthread_mutex_unlock(&adev->lock);
2129 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002130}
2131
2132static int adev_set_master_volume(struct audio_hw_device *dev, float volume)
2133{
2134 return -ENOSYS;
2135}
2136
2137static int adev_get_master_volume(struct audio_hw_device *dev,
2138 float *volume)
2139{
2140 return -ENOSYS;
2141}
2142
2143static int adev_set_master_mute(struct audio_hw_device *dev, bool muted)
2144{
2145 return -ENOSYS;
2146}
2147
2148static int adev_get_master_mute(struct audio_hw_device *dev, bool *muted)
2149{
2150 return -ENOSYS;
2151}
2152
2153static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
2154{
2155 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002156 pthread_mutex_lock(&adev->lock);
2157 if (adev->mode != mode) {
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07002158 ALOGD("%s mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002159 adev->mode = mode;
2160 }
2161 pthread_mutex_unlock(&adev->lock);
2162 return 0;
2163}
2164
2165static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
2166{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002167 return voice_set_mic_mute((struct audio_device *)dev, state);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002168}
2169
2170static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
2171{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002172 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002173 return 0;
2174}
2175
2176static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev,
2177 const struct audio_config *config)
2178{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002179 int channel_count = popcount(config->channel_mask);
2180
2181 return get_input_buffer_size(config->sample_rate, config->format, channel_count);
2182}
2183
2184static int adev_open_input_stream(struct audio_hw_device *dev,
2185 audio_io_handle_t handle,
2186 audio_devices_t devices,
2187 struct audio_config *config,
2188 struct audio_stream_in **stream_in)
2189{
2190 struct audio_device *adev = (struct audio_device *)dev;
2191 struct stream_in *in;
2192 int ret, buffer_size, frame_size;
2193 int channel_count = popcount(config->channel_mask);
2194
Eric Laurent994a6932013-07-17 11:51:42 -07002195 ALOGV("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002196 *stream_in = NULL;
2197 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
2198 return -EINVAL;
2199
2200 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
2201
2202 in->stream.common.get_sample_rate = in_get_sample_rate;
2203 in->stream.common.set_sample_rate = in_set_sample_rate;
2204 in->stream.common.get_buffer_size = in_get_buffer_size;
2205 in->stream.common.get_channels = in_get_channels;
2206 in->stream.common.get_format = in_get_format;
2207 in->stream.common.set_format = in_set_format;
2208 in->stream.common.standby = in_standby;
2209 in->stream.common.dump = in_dump;
2210 in->stream.common.set_parameters = in_set_parameters;
2211 in->stream.common.get_parameters = in_get_parameters;
2212 in->stream.common.add_audio_effect = in_add_audio_effect;
2213 in->stream.common.remove_audio_effect = in_remove_audio_effect;
2214 in->stream.set_gain = in_set_gain;
2215 in->stream.read = in_read;
2216 in->stream.get_input_frames_lost = in_get_input_frames_lost;
2217
2218 in->device = devices;
2219 in->source = AUDIO_SOURCE_DEFAULT;
2220 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002221 in->standby = 1;
2222 in->channel_mask = config->channel_mask;
2223
2224 /* Update config params with the requested sample rate and channels */
2225 in->usecase = USECASE_AUDIO_RECORD;
2226 in->config = pcm_config_audio_capture;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002227 in->config.rate = config->sample_rate;
2228
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002229 if (audio_extn_ssr_get_enabled()&& channel_count == 6) {
2230 if(audio_extn_ssr_init(adev, in))
2231 ALOGE("%s: audio_extn_ssr_init failed", __func__);
2232 } else {
2233 in->config.channels = channel_count;
2234 frame_size = audio_stream_frame_size((struct audio_stream *)in);
2235 buffer_size = get_input_buffer_size(config->sample_rate,
2236 config->format,
2237 channel_count);
2238 in->config.period_size = buffer_size / frame_size;
2239 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002240
2241 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07002242 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002243 return 0;
2244
2245err_open:
2246 free(in);
2247 *stream_in = NULL;
2248 return ret;
2249}
2250
2251static void adev_close_input_stream(struct audio_hw_device *dev,
2252 struct audio_stream_in *stream)
2253{
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002254 struct stream_in *in = (struct stream_in *)stream;
Eric Laurent994a6932013-07-17 11:51:42 -07002255 ALOGV("%s", __func__);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002256
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002257 in_standby(&stream->common);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002258 if (audio_extn_ssr_get_enabled() && (popcount(in->channel_mask) == 6)) {
2259 audio_extn_ssr_deinit();
2260 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002261 free(stream);
2262
2263 return;
2264}
2265
2266static int adev_dump(const audio_hw_device_t *device, int fd)
2267{
2268 return 0;
2269}
2270
2271static int adev_close(hw_device_t *device)
2272{
2273 struct audio_device *adev = (struct audio_device *)device;
2274 audio_route_free(adev->audio_route);
Eric Laurentb23d5282013-05-14 15:27:20 -07002275 free(adev->snd_dev_ref_cnt);
2276 platform_deinit(adev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002277 free(device);
2278 return 0;
2279}
2280
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002281static int adev_open(const hw_module_t *module, const char *name,
2282 hw_device_t **device)
2283{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002284 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002285
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002286 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002287 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
2288
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002289 pthread_mutex_lock(&adev_init_lock);
2290 if (is_adev_initialised == true){
2291 *device = &adev->device.common;
2292 ALOGD("%s: returning existing instance of adev", __func__);
2293 ALOGD("%s: exit", __func__);
2294 pthread_mutex_unlock(&adev_init_lock);
2295 return 0;
2296 }
2297
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002298 adev = calloc(1, sizeof(struct audio_device));
2299
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002300 adev->device.common.tag = HARDWARE_DEVICE_TAG;
2301 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
2302 adev->device.common.module = (struct hw_module_t *)module;
2303 adev->device.common.close = adev_close;
2304
2305 adev->device.init_check = adev_init_check;
2306 adev->device.set_voice_volume = adev_set_voice_volume;
2307 adev->device.set_master_volume = adev_set_master_volume;
2308 adev->device.get_master_volume = adev_get_master_volume;
2309 adev->device.set_master_mute = adev_set_master_mute;
2310 adev->device.get_master_mute = adev_get_master_mute;
2311 adev->device.set_mode = adev_set_mode;
2312 adev->device.set_mic_mute = adev_set_mic_mute;
2313 adev->device.get_mic_mute = adev_get_mic_mute;
2314 adev->device.set_parameters = adev_set_parameters;
2315 adev->device.get_parameters = adev_get_parameters;
2316 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
2317 adev->device.open_output_stream = adev_open_output_stream;
2318 adev->device.close_output_stream = adev_close_output_stream;
2319 adev->device.open_input_stream = adev_open_input_stream;
2320 adev->device.close_input_stream = adev_close_input_stream;
2321 adev->device.dump = adev_dump;
2322
2323 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002324 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08002325 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002326 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002327 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002328 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08002329 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07002330 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07002331 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002332 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002333 list_init(&adev->usecase_list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002334
2335 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07002336 adev->platform = platform_init(adev);
2337 if (!adev->platform) {
2338 free(adev->snd_dev_ref_cnt);
2339 free(adev);
2340 ALOGE("%s: Failed to init platform data, aborting.", __func__);
2341 *device = NULL;
2342 return -EINVAL;
2343 }
Eric Laurentc4aef752013-09-12 17:45:53 -07002344
2345 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
2346 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
2347 if (adev->visualizer_lib == NULL) {
2348 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
2349 } else {
2350 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
2351 adev->visualizer_start_output =
2352 (int (*)(audio_io_handle_t))dlsym(adev->visualizer_lib,
2353 "visualizer_hal_start_output");
2354 adev->visualizer_stop_output =
2355 (int (*)(audio_io_handle_t))dlsym(adev->visualizer_lib,
2356 "visualizer_hal_stop_output");
2357 }
2358 }
2359
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002360 *device = &adev->device.common;
2361
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002362 /* update init flag*/
2363 is_adev_initialised = true;
2364 pthread_mutex_unlock(&adev_init_lock);
2365
Eric Laurent994a6932013-07-17 11:51:42 -07002366 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002367 return 0;
2368}
2369
2370static struct hw_module_methods_t hal_module_methods = {
2371 .open = adev_open,
2372};
2373
2374struct audio_module HAL_MODULE_INFO_SYM = {
2375 .common = {
2376 .tag = HARDWARE_MODULE_TAG,
2377 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
2378 .hal_api_version = HARDWARE_HAL_API_VERSION,
2379 .id = AUDIO_HARDWARE_MODULE_ID,
2380 .name = "QCOM Audio HAL",
2381 .author = "Code Aurora Forum",
2382 .methods = &hal_module_methods,
2383 },
2384};