blob: ba85282afbd5ab7d361143f5f798b985b9fb6e05 [file] [log] [blame]
Simon Wilson15f60a82012-04-24 20:56:32 -07001/*
2 * Copyright (C) 2012 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "audio_hw_primary"
18/*#define LOG_NDEBUG 0*/
19
20#include <errno.h>
21#include <pthread.h>
22#include <stdint.h>
23#include <stdlib.h>
24#include <sys/time.h>
Eric Laurent688880c2012-09-07 16:46:00 -070025#include <fcntl.h>
Simon Wilson15f60a82012-04-24 20:56:32 -070026
27#include <cutils/log.h>
28#include <cutils/properties.h>
29#include <cutils/str_parms.h>
30
31#include <hardware/audio.h>
32#include <hardware/hardware.h>
33
Christopher Ferrisf4d123f2013-12-04 16:22:55 -080034#include <linux/videodev2.h>
Simon Wilsonf051bcf2012-09-26 14:10:07 -070035#include <videodev2_exynos_media.h>
36
Simon Wilson15f60a82012-04-24 20:56:32 -070037#include <system/audio.h>
38
39#include <tinyalsa/asoundlib.h>
40
41#include <audio_utils/resampler.h>
Simon Wilson759c6f02013-01-15 16:38:56 -080042#include <audio_route/audio_route.h>
Simon Wilson15f60a82012-04-24 20:56:32 -070043
Eric Laurenta989ebf2012-10-15 15:14:44 -070044#include <BubbleLevel.h>
45
Jean-Michel Trivie04f7c92012-09-30 16:01:41 -070046#include <eS305VoiceProcessing.h>
47
Simon Wilson15f60a82012-04-24 20:56:32 -070048#define PCM_CARD 0
Simon Wilson56d84e22012-08-17 13:55:27 -070049#define PCM_CARD_SPDIF 1
50#define PCM_TOTAL 2
51
Simon Wilson15f60a82012-04-24 20:56:32 -070052#define PCM_DEVICE 0
Glenn Kastene0aa8f32012-08-17 09:26:58 -070053#define PCM_DEVICE_DEEP 1
Simon Wilsona282d2f2012-09-12 16:14:24 -070054#define PCM_DEVICE_VOICE 2
55#define PCM_DEVICE_SCO 3
Simon Wilson15f60a82012-04-24 20:56:32 -070056
Simon Wilson759c6f02013-01-15 16:38:56 -080057#define MIXER_CARD 0
58
Eric Laurent1a0c0a72012-08-24 11:29:04 -070059/* duration in ms of volume ramp applied when starting capture to remove plop */
60#define CAPTURE_START_RAMP_MS 100
61
Eric Laurentb2c0b4f2012-09-21 11:42:48 -070062/* default sampling for HDMI multichannel output */
63#define HDMI_MULTI_DEFAULT_SAMPLING_RATE 44100
64/* maximum number of channel mask configurations supported. Currently the primary
65 * output only supports 1 (stereo) and the multi channel HDMI output 2 (5.1 and 7.1) */
66#define MAX_SUPPORTED_CHANNEL_MASKS 2
67
68#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
69
Simon Wilson15f60a82012-04-24 20:56:32 -070070struct pcm_config pcm_config = {
71 .channels = 2,
72 .rate = 44100,
Glenn Kasten22db1772012-09-04 09:26:50 -070073 .period_size = 256,
Glenn Kastenb9366272012-07-18 14:06:12 -070074 .period_count = 2,
Simon Wilson15f60a82012-04-24 20:56:32 -070075 .format = PCM_FORMAT_S16_LE,
76};
77
Glenn Kasten7ecf6232012-09-28 12:01:31 -070078struct pcm_config pcm_config_in = {
79 .channels = 2,
80 .rate = 44100,
Glenn Kastena83d9a12014-07-15 10:28:31 -070081 .period_size = 512,
82 .period_count = 2,
83 .format = PCM_FORMAT_S16_LE,
84};
85
86struct pcm_config pcm_config_in_low_latency = {
87 .channels = 2,
88 .rate = 44100,
Glenn Kasten344070a2014-05-12 14:41:05 -070089 .period_size = 256,
Glenn Kasten7ecf6232012-09-28 12:01:31 -070090 .period_count = 2,
91 .format = PCM_FORMAT_S16_LE,
92};
93
Simon Wilsona282d2f2012-09-12 16:14:24 -070094struct pcm_config pcm_config_sco = {
95 .channels = 1,
96 .rate = 8000,
97 .period_size = 128,
98 .period_count = 2,
99 .format = PCM_FORMAT_S16_LE,
100};
101
Glenn Kastene0aa8f32012-08-17 09:26:58 -0700102struct pcm_config pcm_config_deep = {
103 .channels = 2,
104 .rate = 44100,
105 /* FIXME This is an arbitrary number, may change.
106 * Dynamic configuration based on screen on/off is not implemented;
107 * let's see what power consumption is first to see if necessary.
108 */
109 .period_size = 8192,
110 .period_count = 2,
111 .format = PCM_FORMAT_S16_LE,
112};
113
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700114struct pcm_config pcm_config_hdmi_multi = {
115 .channels = 6, /* changed when the stream is opened */
116 .rate = HDMI_MULTI_DEFAULT_SAMPLING_RATE,
117 .period_size = 1024,
118 .period_count = 4,
119 .format = PCM_FORMAT_S16_LE,
120};
121
Glenn Kastene0aa8f32012-08-17 09:26:58 -0700122enum output_type {
123 OUTPUT_DEEP_BUF, // deep PCM buffers output stream
124 OUTPUT_LOW_LATENCY, // low latency output stream
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700125 OUTPUT_HDMI, // HDMI multi channel
Glenn Kastene0aa8f32012-08-17 09:26:58 -0700126 OUTPUT_TOTAL
127};
128
Simon Wilson15f60a82012-04-24 20:56:32 -0700129struct audio_device {
130 struct audio_hw_device hw_device;
131
132 pthread_mutex_t lock; /* see note below on mutex acquisition order */
Glenn Kastene0aa8f32012-08-17 09:26:58 -0700133 audio_devices_t out_device; /* "or" of stream_out.device for all active output streams */
Eric Laurent42531fa2012-10-03 09:06:14 -0700134 audio_devices_t in_device;
Simon Wilson15f60a82012-04-24 20:56:32 -0700135 bool mic_mute;
136 struct audio_route *ar;
Eric Laurent87532032012-07-16 13:53:20 -0700137 audio_source_t input_source;
138 int cur_route_id; /* current route ID: combination of input source
139 * and output device IDs */
Simon Wilsona282d2f2012-09-12 16:14:24 -0700140 struct pcm *pcm_voice_out;
141 struct pcm *pcm_sco_out;
142 struct pcm *pcm_voice_in;
143 struct pcm *pcm_sco_in;
Eric Laurent688880c2012-09-07 16:46:00 -0700144 int es305_preset;
Eric Laurenta989ebf2012-10-15 15:14:44 -0700145 int es305_new_mode;
Eric Laurent688880c2012-09-07 16:46:00 -0700146 int es305_mode;
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700147 int hdmi_drv_fd;
Eric Laurenta989ebf2012-10-15 15:14:44 -0700148 struct bubble_level *bubble_level;
Eric Laurentb52afc82013-01-18 15:12:57 -0800149 audio_channel_mask_t in_channel_mask;
Eric Laurent4f1aece2013-04-19 17:10:25 -0700150 unsigned int sco_on_count;
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700151
Glenn Kastene0aa8f32012-08-17 09:26:58 -0700152 struct stream_out *outputs[OUTPUT_TOTAL];
Simon Wilson15f60a82012-04-24 20:56:32 -0700153};
154
155struct stream_out {
156 struct audio_stream_out stream;
157
158 pthread_mutex_t lock; /* see note below on mutex acquisition order */
Simon Wilson56d84e22012-08-17 13:55:27 -0700159 struct pcm *pcm[PCM_TOTAL];
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700160 struct pcm_config config;
Glenn Kastene0aa8f32012-08-17 09:26:58 -0700161 unsigned int pcm_device;
Simon Wilson56d84e22012-08-17 13:55:27 -0700162 bool standby; /* true if all PCMs are inactive */
Eric Laurent42531fa2012-10-03 09:06:14 -0700163 audio_devices_t device;
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700164 /* FIXME: when HDMI multichannel output is active, other outputs must be disabled as
165 * HDMI and WM1811 share the same I2S. This means that notifications and other sounds are
166 * silent when watching a 5.1 movie. */
167 bool disabled;
168 audio_channel_mask_t channel_mask;
169 /* Array of supported channel mask configurations. +1 so that the last entry is always 0 */
170 audio_channel_mask_t supported_channel_masks[MAX_SUPPORTED_CHANNEL_MASKS + 1];
Eric Laurent3948fda2013-04-04 09:24:22 -0700171 bool muted;
Glenn Kasten21169cb2013-08-20 15:36:18 -0700172 uint64_t written; /* total frames written, not cleared when entering standby */
Simon Wilson15f60a82012-04-24 20:56:32 -0700173
174 struct audio_device *dev;
175};
176
177struct stream_in {
178 struct audio_stream_in stream;
179
180 pthread_mutex_t lock; /* see note below on mutex acquisition order */
181 struct pcm *pcm;
182 bool standby;
183
184 unsigned int requested_rate;
185 struct resampler_itfe *resampler;
186 struct resampler_buffer_provider buf_provider;
187 int16_t *buffer;
188 size_t frames_in;
189 int read_status;
Eric Laurent87532032012-07-16 13:53:20 -0700190 audio_source_t input_source;
Jean-Michel Trivie04f7c92012-09-30 16:01:41 -0700191 audio_io_handle_t io_handle;
Eric Laurent42531fa2012-10-03 09:06:14 -0700192 audio_devices_t device;
Eric Laurent1a0c0a72012-08-24 11:29:04 -0700193 uint16_t ramp_vol;
194 uint16_t ramp_step;
195 size_t ramp_frames;
Eric Laurentb52afc82013-01-18 15:12:57 -0800196 audio_channel_mask_t channel_mask;
Glenn Kastena83d9a12014-07-15 10:28:31 -0700197 audio_input_flags_t flags;
198 struct pcm_config *config;
Simon Wilson15f60a82012-04-24 20:56:32 -0700199
200 struct audio_device *dev;
201};
202
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700203#define STRING_TO_ENUM(string) { #string, string }
204
205struct string_to_enum {
206 const char *name;
207 uint32_t value;
208};
209
210const struct string_to_enum out_channels_name_to_enum_table[] = {
211 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
212 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
213 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
214};
215
Eric Laurent87532032012-07-16 13:53:20 -0700216enum {
217 OUT_DEVICE_SPEAKER,
218 OUT_DEVICE_HEADSET,
219 OUT_DEVICE_HEADPHONES,
220 OUT_DEVICE_BT_SCO,
221 OUT_DEVICE_SPEAKER_AND_HEADSET,
222 OUT_DEVICE_TAB_SIZE, /* number of rows in route_configs[][] */
223 OUT_DEVICE_NONE,
Eric Laurent87532032012-07-16 13:53:20 -0700224 OUT_DEVICE_CNT
225};
226
227enum {
228 IN_SOURCE_MIC,
229 IN_SOURCE_CAMCORDER,
230 IN_SOURCE_VOICE_RECOGNITION,
231 IN_SOURCE_VOICE_COMMUNICATION,
232 IN_SOURCE_TAB_SIZE, /* number of lines in route_configs[][] */
233 IN_SOURCE_NONE,
Eric Laurent87532032012-07-16 13:53:20 -0700234 IN_SOURCE_CNT
235};
236
Eric Laurent688880c2012-09-07 16:46:00 -0700237enum {
Eric Laurent688880c2012-09-07 16:46:00 -0700238 ES305_MODE_DEFAULT,
Eric Laurenta989ebf2012-10-15 15:14:44 -0700239 ES305_MODE_LEVEL,
Eric Laurent688880c2012-09-07 16:46:00 -0700240 ES305_NUM_MODES,
241};
242
Eric Laurent42531fa2012-10-03 09:06:14 -0700243int get_output_device_id(audio_devices_t device)
Eric Laurent87532032012-07-16 13:53:20 -0700244{
Eric Laurent6a466d72012-08-28 12:13:38 -0700245 if (device == AUDIO_DEVICE_NONE)
Eric Laurent87532032012-07-16 13:53:20 -0700246 return OUT_DEVICE_NONE;
247
248 if (popcount(device) == 2) {
249 if ((device == (AUDIO_DEVICE_OUT_SPEAKER |
250 AUDIO_DEVICE_OUT_WIRED_HEADSET)) ||
251 (device == (AUDIO_DEVICE_OUT_SPEAKER |
252 AUDIO_DEVICE_OUT_WIRED_HEADPHONE)))
253 return OUT_DEVICE_SPEAKER_AND_HEADSET;
254 else
Simon Wilsona6b94122012-09-12 12:52:24 -0700255 return OUT_DEVICE_NONE;
Eric Laurent87532032012-07-16 13:53:20 -0700256 }
257
258 if (popcount(device) != 1)
Simon Wilsona6b94122012-09-12 12:52:24 -0700259 return OUT_DEVICE_NONE;
Eric Laurent87532032012-07-16 13:53:20 -0700260
261 switch (device) {
262 case AUDIO_DEVICE_OUT_SPEAKER:
263 return OUT_DEVICE_SPEAKER;
264 case AUDIO_DEVICE_OUT_WIRED_HEADSET:
265 return OUT_DEVICE_HEADSET;
266 case AUDIO_DEVICE_OUT_WIRED_HEADPHONE:
267 return OUT_DEVICE_HEADPHONES;
268 case AUDIO_DEVICE_OUT_BLUETOOTH_SCO:
269 case AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET:
270 case AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT:
271 return OUT_DEVICE_BT_SCO;
272 default:
Simon Wilsona6b94122012-09-12 12:52:24 -0700273 return OUT_DEVICE_NONE;
Eric Laurent87532032012-07-16 13:53:20 -0700274 }
275}
276
277int get_input_source_id(audio_source_t source)
278{
279 switch (source) {
280 case AUDIO_SOURCE_DEFAULT:
281 return IN_SOURCE_NONE;
282 case AUDIO_SOURCE_MIC:
283 return IN_SOURCE_MIC;
284 case AUDIO_SOURCE_CAMCORDER:
285 return IN_SOURCE_CAMCORDER;
286 case AUDIO_SOURCE_VOICE_RECOGNITION:
287 return IN_SOURCE_VOICE_RECOGNITION;
288 case AUDIO_SOURCE_VOICE_COMMUNICATION:
289 return IN_SOURCE_VOICE_COMMUNICATION;
290 default:
Simon Wilsona6b94122012-09-12 12:52:24 -0700291 return IN_SOURCE_NONE;
Eric Laurent87532032012-07-16 13:53:20 -0700292 }
293}
294
295struct route_config {
296 const char * const output_route;
297 const char * const input_route;
Eric Laurent688880c2012-09-07 16:46:00 -0700298 int es305_preset[ES305_NUM_MODES]; // es305 preset for this route.
299 // -1 means es305 bypass
Eric Laurent87532032012-07-16 13:53:20 -0700300};
301
302const struct route_config media_speaker = {
303 "media-speaker",
Eric Laurent688880c2012-09-07 16:46:00 -0700304 "media-main-mic",
305 { ES305_PRESET_OFF,
306 ES305_PRESET_OFF }
Eric Laurent87532032012-07-16 13:53:20 -0700307};
308
309const struct route_config media_headphones = {
310 "media-headphones",
Eric Laurent688880c2012-09-07 16:46:00 -0700311 "media-main-mic",
312 { ES305_PRESET_OFF,
313 ES305_PRESET_OFF }
Eric Laurent87532032012-07-16 13:53:20 -0700314};
315
316const struct route_config media_headset = {
317 "media-headphones",
Eric Laurent688880c2012-09-07 16:46:00 -0700318 "media-headset-mic",
319 { ES305_PRESET_OFF,
320 ES305_PRESET_OFF }
Eric Laurent87532032012-07-16 13:53:20 -0700321};
322
323const struct route_config camcorder_speaker = {
324 "media-speaker",
Eric Laurent688880c2012-09-07 16:46:00 -0700325 "media-second-mic",
Jean-Michel Trivi48277c52012-10-08 10:22:59 -0700326 { ES305_PRESET_CAMCORDER,
327 ES305_PRESET_CAMCORDER }
Eric Laurent87532032012-07-16 13:53:20 -0700328};
329
330const struct route_config camcorder_headphones = {
331 "media-headphones",
Eric Laurent688880c2012-09-07 16:46:00 -0700332 "media-second-mic",
Jean-Michel Trivi48277c52012-10-08 10:22:59 -0700333 { ES305_PRESET_CAMCORDER,
334 ES305_PRESET_CAMCORDER }
Eric Laurent87532032012-07-16 13:53:20 -0700335};
336
337const struct route_config voice_rec_speaker = {
338 "voice-rec-speaker",
Eric Laurent688880c2012-09-07 16:46:00 -0700339 "voice-rec-main-mic",
Jean-Michel Trivie04f7c92012-09-30 16:01:41 -0700340 { ES305_PRESET_ASRA_HANDHELD,
341 ES305_PRESET_ASRA_DESKTOP }
Eric Laurent87532032012-07-16 13:53:20 -0700342};
343
344const struct route_config voice_rec_headphones = {
345 "voice-rec-headphones",
Eric Laurent688880c2012-09-07 16:46:00 -0700346 "voice-rec-main-mic",
Jean-Michel Trivie04f7c92012-09-30 16:01:41 -0700347 { ES305_PRESET_ASRA_HANDHELD,
348 ES305_PRESET_ASRA_DESKTOP }
Eric Laurent87532032012-07-16 13:53:20 -0700349};
350
351const struct route_config voice_rec_headset = {
352 "voice-rec-headphones",
Eric Laurent688880c2012-09-07 16:46:00 -0700353 "voice-rec-headset-mic",
Jean-Michel Trivie04f7c92012-09-30 16:01:41 -0700354 { ES305_PRESET_ASRA_HEADSET,
355 ES305_PRESET_ASRA_HEADSET }
Eric Laurent87532032012-07-16 13:53:20 -0700356};
357
358const struct route_config communication_speaker = {
359 "communication-speaker",
Eric Laurent688880c2012-09-07 16:46:00 -0700360 "communication-main-mic",
361 { ES305_PRESET_VOIP_HANDHELD,
362 ES305_PRESET_VOIP_DESKTOP }
Eric Laurent87532032012-07-16 13:53:20 -0700363};
364
365const struct route_config communication_headphones = {
366 "communication-headphones",
Eric Laurent688880c2012-09-07 16:46:00 -0700367 "communication-main-mic",
368 { ES305_PRESET_VOIP_HEADPHONES,
369 ES305_PRESET_VOIP_HP_DESKTOP}
Eric Laurent87532032012-07-16 13:53:20 -0700370};
371
372const struct route_config communication_headset = {
373 "communication-headphones",
Eric Laurent688880c2012-09-07 16:46:00 -0700374 "communication-headset-mic",
375 { ES305_PRESET_VOIP_HEADSET,
376 ES305_PRESET_VOIP_HEADSET }
Eric Laurent87532032012-07-16 13:53:20 -0700377};
378
379const struct route_config speaker_and_headphones = {
380 "speaker-and-headphones",
Eric Laurent688880c2012-09-07 16:46:00 -0700381 "main-mic",
382 { ES305_PRESET_CURRENT,
383 ES305_PRESET_CURRENT }
Eric Laurent87532032012-07-16 13:53:20 -0700384};
385
386const struct route_config bluetooth_sco = {
387 "bt-sco-headset",
Eric Laurent688880c2012-09-07 16:46:00 -0700388 "bt-sco-mic",
389 { ES305_PRESET_OFF,
390 ES305_PRESET_OFF }
Eric Laurent87532032012-07-16 13:53:20 -0700391};
392
393const struct route_config * const route_configs[IN_SOURCE_TAB_SIZE]
394 [OUT_DEVICE_TAB_SIZE] = {
395 { /* IN_SOURCE_MIC */
396 &media_speaker, /* OUT_DEVICE_SPEAKER */
397 &media_headset, /* OUT_DEVICE_HEADSET */
398 &media_headphones, /* OUT_DEVICE_HEADPHONES */
399 &bluetooth_sco, /* OUT_DEVICE_BT_SCO */
400 &speaker_and_headphones /* OUT_DEVICE_SPEAKER_AND_HEADSET */
401 },
402 { /* IN_SOURCE_CAMCORDER */
403 &camcorder_speaker, /* OUT_DEVICE_SPEAKER */
404 &camcorder_headphones, /* OUT_DEVICE_HEADSET */
405 &camcorder_headphones, /* OUT_DEVICE_HEADPHONES */
406 &bluetooth_sco, /* OUT_DEVICE_BT_SCO */
407 &speaker_and_headphones /* OUT_DEVICE_SPEAKER_AND_HEADSET */
408 },
409 { /* IN_SOURCE_VOICE_RECOGNITION */
410 &voice_rec_speaker, /* OUT_DEVICE_SPEAKER */
411 &voice_rec_headset, /* OUT_DEVICE_HEADSET */
412 &voice_rec_headphones, /* OUT_DEVICE_HEADPHONES */
413 &bluetooth_sco, /* OUT_DEVICE_BT_SCO */
414 &speaker_and_headphones /* OUT_DEVICE_SPEAKER_AND_HEADSET */
415 },
416 { /* IN_SOURCE_VOICE_COMMUNICATION */
417 &communication_speaker, /* OUT_DEVICE_SPEAKER */
418 &communication_headset, /* OUT_DEVICE_HEADSET */
419 &communication_headphones, /* OUT_DEVICE_HEADPHONES */
420 &bluetooth_sco, /* OUT_DEVICE_BT_SCO */
421 &speaker_and_headphones /* OUT_DEVICE_SPEAKER_AND_HEADSET */
422 }
423};
424
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700425static int do_out_standby(struct stream_out *out);
426
Simon Wilson15f60a82012-04-24 20:56:32 -0700427/**
428 * NOTE: when multiple mutexes have to be acquired, always respect the
429 * following order: hw device > in stream > out stream
430 */
431
432/* Helper functions */
433
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700434static int open_hdmi_driver(struct audio_device *adev)
Simon Wilsonf051bcf2012-09-26 14:10:07 -0700435{
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700436 if (adev->hdmi_drv_fd < 0) {
437 adev->hdmi_drv_fd = open("/dev/video16", O_RDWR);
438 if (adev->hdmi_drv_fd < 0)
439 ALOGE("%s cannot open video16 (%d)", __func__, adev->hdmi_drv_fd);
440 }
441 return adev->hdmi_drv_fd;
442}
443
444/* must be called with hw device mutex locked */
445static int enable_hdmi_audio(struct audio_device *adev, int enable)
446{
Simon Wilsonf051bcf2012-09-26 14:10:07 -0700447 int ret;
448 struct v4l2_control ctrl;
449
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700450 ret = open_hdmi_driver(adev);
451 if (ret < 0)
452 return ret;
Simon Wilsonf051bcf2012-09-26 14:10:07 -0700453
454 ctrl.id = V4L2_CID_TV_ENABLE_HDMI_AUDIO;
455 ctrl.value = !!enable;
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700456 ret = ioctl(adev->hdmi_drv_fd, VIDIOC_S_CTRL, &ctrl);
Simon Wilsonf051bcf2012-09-26 14:10:07 -0700457
458 if (ret < 0)
459 ALOGE("V4L2_CID_TV_ENABLE_HDMI_AUDIO ioctl error (%d)", errno);
460
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700461 return ret;
462}
463
464/* must be called with hw device mutex locked */
465static int read_hdmi_channel_masks(struct audio_device *adev, struct stream_out *out) {
466 int ret;
467 struct v4l2_control ctrl;
468
469 ret = open_hdmi_driver(adev);
470 if (ret < 0)
471 return ret;
472
473 ctrl.id = V4L2_CID_TV_MAX_AUDIO_CHANNELS;
474 ret = ioctl(adev->hdmi_drv_fd, VIDIOC_G_CTRL, &ctrl);
475 if (ret < 0) {
476 ALOGE("V4L2_CID_TV_MAX_AUDIO_CHANNELS ioctl error (%d)", errno);
477 return ret;
478 }
479
480 ALOGV("%s ioctl %d got %d max channels", __func__, ret, ctrl.value);
481
482 if (ctrl.value != 6 && ctrl.value != 8)
483 return -ENOSYS;
484
485 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
486 if (ctrl.value == 8)
487 out->supported_channel_masks[1] = AUDIO_CHANNEL_OUT_7POINT1;
488
489 return ret;
490}
491
492/* must be called with hw device mutex locked */
493static int set_hdmi_channels(struct audio_device *adev, int channels) {
494 int ret;
495 struct v4l2_control ctrl;
496
497 ret = open_hdmi_driver(adev);
498 if (ret < 0)
499 return ret;
500
501 ctrl.id = V4L2_CID_TV_SET_NUM_CHANNELS;
502 ctrl.value = channels;
503 ret = ioctl(adev->hdmi_drv_fd, VIDIOC_S_CTRL, &ctrl);
504 if (ret < 0)
505 ALOGE("V4L2_CID_TV_SET_NUM_CHANNELS ioctl error (%d)", errno);
Simon Wilsonf051bcf2012-09-26 14:10:07 -0700506
507 return ret;
508}
509
Simon Wilson15f60a82012-04-24 20:56:32 -0700510static void select_devices(struct audio_device *adev)
511{
Eric Laurent6a466d72012-08-28 12:13:38 -0700512 int output_device_id = get_output_device_id(adev->out_device);
Eric Laurent87532032012-07-16 13:53:20 -0700513 int input_source_id = get_input_source_id(adev->input_source);
Simon Wilsonc4006be2012-08-17 11:23:38 -0700514 const char *output_route = NULL;
515 const char *input_route = NULL;
Eric Laurent87532032012-07-16 13:53:20 -0700516 int new_route_id;
Eric Laurent688880c2012-09-07 16:46:00 -0700517 int new_es305_preset = -1;
Simon Wilson15f60a82012-04-24 20:56:32 -0700518
Simon Wilson759c6f02013-01-15 16:38:56 -0800519 audio_route_reset(adev->ar);
Simon Wilsonc4006be2012-08-17 11:23:38 -0700520
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700521 enable_hdmi_audio(adev, adev->out_device & AUDIO_DEVICE_OUT_AUX_DIGITAL);
Simon Wilsonab5dda62012-10-01 17:44:38 -0700522
Eric Laurent87532032012-07-16 13:53:20 -0700523 new_route_id = (1 << (input_source_id + OUT_DEVICE_CNT)) + (1 << output_device_id);
Eric Laurenta989ebf2012-10-15 15:14:44 -0700524 if ((new_route_id == adev->cur_route_id) && (adev->es305_mode == adev->es305_new_mode))
Eric Laurent87532032012-07-16 13:53:20 -0700525 return;
526 adev->cur_route_id = new_route_id;
Eric Laurenta989ebf2012-10-15 15:14:44 -0700527 adev->es305_mode = adev->es305_new_mode;
Simon Wilson15f60a82012-04-24 20:56:32 -0700528
Eric Laurent87532032012-07-16 13:53:20 -0700529 if (input_source_id != IN_SOURCE_NONE) {
530 if (output_device_id != OUT_DEVICE_NONE) {
531 input_route =
532 route_configs[input_source_id][output_device_id]->input_route;
533 output_route =
534 route_configs[input_source_id][output_device_id]->output_route;
Eric Laurent688880c2012-09-07 16:46:00 -0700535 new_es305_preset =
536 route_configs[input_source_id][output_device_id]->es305_preset[adev->es305_mode];
Eric Laurent87532032012-07-16 13:53:20 -0700537 } else {
Eric Laurent42531fa2012-10-03 09:06:14 -0700538 switch (adev->in_device) {
Eric Laurent4f1aece2013-04-19 17:10:25 -0700539 case AUDIO_DEVICE_IN_WIRED_HEADSET & ~AUDIO_DEVICE_BIT_IN:
Eric Laurent42531fa2012-10-03 09:06:14 -0700540 output_device_id = OUT_DEVICE_HEADSET;
541 break;
Eric Laurent4f1aece2013-04-19 17:10:25 -0700542 case AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET & ~AUDIO_DEVICE_BIT_IN:
Eric Laurent42531fa2012-10-03 09:06:14 -0700543 output_device_id = OUT_DEVICE_BT_SCO;
544 break;
545 default:
546 output_device_id = OUT_DEVICE_SPEAKER;
547 break;
548 }
Eric Laurent87532032012-07-16 13:53:20 -0700549 input_route =
Eric Laurent42531fa2012-10-03 09:06:14 -0700550 route_configs[input_source_id][output_device_id]->input_route;
Eric Laurent688880c2012-09-07 16:46:00 -0700551 new_es305_preset =
Eric Laurent42531fa2012-10-03 09:06:14 -0700552 route_configs[input_source_id][output_device_id]->es305_preset[adev->es305_mode];
Eric Laurent87532032012-07-16 13:53:20 -0700553 }
Eric Laurentb52afc82013-01-18 15:12:57 -0800554 // disable noise suppression when capturing front and back mic for voice recognition
555 if ((adev->input_source == AUDIO_SOURCE_VOICE_RECOGNITION) &&
Jean-Michel Trivi3f467de2013-06-06 15:26:01 -0700556 (adev->in_channel_mask == AUDIO_CHANNEL_IN_FRONT_BACK))
Eric Laurentb52afc82013-01-18 15:12:57 -0800557 new_es305_preset = -1;
Eric Laurent87532032012-07-16 13:53:20 -0700558 } else {
559 if (output_device_id != OUT_DEVICE_NONE) {
560 output_route =
561 route_configs[IN_SOURCE_MIC][output_device_id]->output_route;
562 }
563 }
564
565 ALOGV("select_devices() devices %#x input src %d output route %s input route %s",
Eric Laurent6a466d72012-08-28 12:13:38 -0700566 adev->out_device, adev->input_source,
Simon Wilsonc4006be2012-08-17 11:23:38 -0700567 output_route ? output_route : "none",
568 input_route ? input_route : "none");
Eric Laurent87532032012-07-16 13:53:20 -0700569
Simon Wilsonc4006be2012-08-17 11:23:38 -0700570 if (output_route)
571 audio_route_apply_path(adev->ar, output_route);
572 if (input_route)
573 audio_route_apply_path(adev->ar, input_route);
Simon Wilson15f60a82012-04-24 20:56:32 -0700574
Eric Laurent688880c2012-09-07 16:46:00 -0700575 if ((new_es305_preset != ES305_PRESET_CURRENT) &&
576 (new_es305_preset != adev->es305_preset)) {
Jean-Michel Trivie04f7c92012-09-30 16:01:41 -0700577 ALOGV(" select_devices() changing es305 preset from %d to %d",
578 adev->es305_preset, new_es305_preset);
579 if (eS305_UsePreset(new_es305_preset) == 0) {
Eric Laurent688880c2012-09-07 16:46:00 -0700580 adev->es305_preset = new_es305_preset;
Jean-Michel Trivie04f7c92012-09-30 16:01:41 -0700581 }
Eric Laurent688880c2012-09-07 16:46:00 -0700582 }
583
Simon Wilson759c6f02013-01-15 16:38:56 -0800584 audio_route_update_mixer(adev->ar);
Simon Wilson15f60a82012-04-24 20:56:32 -0700585}
586
Eric Laurenta989ebf2012-10-15 15:14:44 -0700587void bubblelevel_callback(bool is_level, void *user_data)
588{
589 struct audio_device *adev = (struct audio_device *)user_data;
590 int es305_mode;
591
592 if (is_level)
593 es305_mode = ES305_MODE_LEVEL;
594 else
595 es305_mode = ES305_MODE_DEFAULT;
596
597 pthread_mutex_lock(&adev->lock);
598 if (es305_mode != adev->es305_mode) {
599 adev->es305_new_mode = es305_mode;
600 select_devices(adev);
601 ALOGV("bubblelevel_callback is_level %d es305_mode %d", is_level, es305_mode);
602 }
603 pthread_mutex_unlock(&adev->lock);
604}
605
Eric Laurent429f24d2012-11-02 14:37:38 -0700606/* must be called with hw device mutex locked */
607bool get_bubblelevel(struct audio_device *adev)
608{
609 if (!adev->bubble_level) {
610 adev->bubble_level = bubble_level_create();
611 if (adev->bubble_level)
612 adev->bubble_level->set_callback(adev->bubble_level, bubblelevel_callback, adev);
613 }
614 return (adev->bubble_level != NULL);
615}
616
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700617static void force_non_hdmi_out_standby(struct audio_device *adev)
618{
619 enum output_type type;
620 struct stream_out *out;
621
622 for (type = 0; type < OUTPUT_TOTAL; ++type) {
623 out = adev->outputs[type];
624 if (type == OUTPUT_HDMI || !out)
625 continue;
626 pthread_mutex_lock(&out->lock);
627 do_out_standby(out);
628 pthread_mutex_unlock(&out->lock);
629 }
630}
631
Eric Laurent4f1aece2013-04-19 17:10:25 -0700632/* must be called with the hw device mutex locked, OK to hold other mutexes */
633static void start_bt_sco(struct audio_device *adev) {
634 if (adev->sco_on_count++ > 0)
635 return;
636
Glenn Kasten21169cb2013-08-20 15:36:18 -0700637 adev->pcm_voice_out = pcm_open(PCM_CARD, PCM_DEVICE_VOICE, PCM_OUT | PCM_MONOTONIC,
Eric Laurent4f1aece2013-04-19 17:10:25 -0700638 &pcm_config_sco);
639 if (adev->pcm_voice_out && !pcm_is_ready(adev->pcm_voice_out)) {
640 ALOGE("pcm_open(VOICE_OUT) failed: %s", pcm_get_error(adev->pcm_voice_out));
641 goto err_voice_out;
642 }
Glenn Kasten21169cb2013-08-20 15:36:18 -0700643 adev->pcm_sco_out = pcm_open(PCM_CARD, PCM_DEVICE_SCO, PCM_OUT | PCM_MONOTONIC,
Eric Laurent4f1aece2013-04-19 17:10:25 -0700644 &pcm_config_sco);
645 if (adev->pcm_sco_out && !pcm_is_ready(adev->pcm_sco_out)) {
646 ALOGE("pcm_open(SCO_OUT) failed: %s", pcm_get_error(adev->pcm_sco_out));
647 goto err_sco_out;
648 }
649 adev->pcm_voice_in = pcm_open(PCM_CARD, PCM_DEVICE_VOICE, PCM_IN,
650 &pcm_config_sco);
651 if (adev->pcm_voice_in && !pcm_is_ready(adev->pcm_voice_in)) {
652 ALOGE("pcm_open(VOICE_IN) failed: %s", pcm_get_error(adev->pcm_voice_in));
653 goto err_voice_in;
654 }
655 adev->pcm_sco_in = pcm_open(PCM_CARD, PCM_DEVICE_SCO, PCM_IN,
656 &pcm_config_sco);
657 if (adev->pcm_sco_in && !pcm_is_ready(adev->pcm_sco_in)) {
658 ALOGE("pcm_open(SCO_IN) failed: %s", pcm_get_error(adev->pcm_sco_in));
659 goto err_sco_in;
660 }
661
662 pcm_start(adev->pcm_voice_out);
663 pcm_start(adev->pcm_sco_out);
664 pcm_start(adev->pcm_voice_in);
665 pcm_start(adev->pcm_sco_in);
666
667 return;
668
669err_sco_in:
670 pcm_close(adev->pcm_sco_in);
671err_voice_in:
672 pcm_close(adev->pcm_voice_in);
673err_sco_out:
674 pcm_close(adev->pcm_sco_out);
675err_voice_out:
676 pcm_close(adev->pcm_voice_out);
677}
678
679/* must be called with the hw device mutex locked, OK to hold other mutexes */
680static void stop_bt_sco(struct audio_device *adev) {
681 if (adev->sco_on_count == 0 || --adev->sco_on_count > 0)
682 return;
683
684 pcm_stop(adev->pcm_voice_out);
685 pcm_stop(adev->pcm_sco_out);
686 pcm_stop(adev->pcm_voice_in);
687 pcm_stop(adev->pcm_sco_in);
688
689 pcm_close(adev->pcm_voice_out);
690 pcm_close(adev->pcm_sco_out);
691 pcm_close(adev->pcm_voice_in);
692 pcm_close(adev->pcm_sco_in);
693}
694
Simon Wilson15f60a82012-04-24 20:56:32 -0700695/* must be called with hw device and output stream mutexes locked */
696static int start_output_stream(struct stream_out *out)
697{
698 struct audio_device *adev = out->dev;
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700699 int type;
700
701 if (out == adev->outputs[OUTPUT_HDMI]) {
702 force_non_hdmi_out_standby(adev);
703 } else if (adev->outputs[OUTPUT_HDMI] && !adev->outputs[OUTPUT_HDMI]->standby) {
704 out->disabled = true;
705 return 0;
706 }
707
708 out->disabled = false;
Simon Wilson15f60a82012-04-24 20:56:32 -0700709
Simon Wilson56d84e22012-08-17 13:55:27 -0700710 if (out->device & (AUDIO_DEVICE_OUT_SPEAKER |
711 AUDIO_DEVICE_OUT_WIRED_HEADSET |
712 AUDIO_DEVICE_OUT_WIRED_HEADPHONE |
Simon Wilsona282d2f2012-09-12 16:14:24 -0700713 AUDIO_DEVICE_OUT_AUX_DIGITAL |
714 AUDIO_DEVICE_OUT_ALL_SCO)) {
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700715
Glenn Kastene0aa8f32012-08-17 09:26:58 -0700716 out->pcm[PCM_CARD] = pcm_open(PCM_CARD, out->pcm_device,
Glenn Kasten21169cb2013-08-20 15:36:18 -0700717 PCM_OUT | PCM_MONOTONIC, &out->config);
Simon Wilson15f60a82012-04-24 20:56:32 -0700718
Simon Wilson56d84e22012-08-17 13:55:27 -0700719 if (out->pcm[PCM_CARD] && !pcm_is_ready(out->pcm[PCM_CARD])) {
720 ALOGE("pcm_open(PCM_CARD) failed: %s",
721 pcm_get_error(out->pcm[PCM_CARD]));
722 pcm_close(out->pcm[PCM_CARD]);
723 return -ENOMEM;
724 }
725 }
726
727 if (out->device & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET) {
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700728 out->pcm[PCM_CARD_SPDIF] = pcm_open(PCM_CARD_SPDIF, out->pcm_device,
Glenn Kasten21169cb2013-08-20 15:36:18 -0700729 PCM_OUT | PCM_MONOTONIC, &out->config);
Simon Wilson56d84e22012-08-17 13:55:27 -0700730
731 if (out->pcm[PCM_CARD_SPDIF] &&
732 !pcm_is_ready(out->pcm[PCM_CARD_SPDIF])) {
733 ALOGE("pcm_open(PCM_CARD_SPDIF) failed: %s",
734 pcm_get_error(out->pcm[PCM_CARD_SPDIF]));
735 pcm_close(out->pcm[PCM_CARD_SPDIF]);
736 return -ENOMEM;
737 }
Simon Wilson15f60a82012-04-24 20:56:32 -0700738 }
739
Glenn Kastene0aa8f32012-08-17 09:26:58 -0700740 adev->out_device |= out->device;
Eric Laurent87532032012-07-16 13:53:20 -0700741 select_devices(adev);
742
Eric Laurent4f1aece2013-04-19 17:10:25 -0700743 if (out->device & AUDIO_DEVICE_OUT_ALL_SCO)
744 start_bt_sco(adev);
745
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700746 if (out->device & AUDIO_DEVICE_OUT_AUX_DIGITAL)
747 set_hdmi_channels(adev, out->config.channels);
748
Eric Laurenta989ebf2012-10-15 15:14:44 -0700749 /* anticipate level measurement in case we start capture later */
Eric Laurent429f24d2012-11-02 14:37:38 -0700750 if (get_bubblelevel(adev))
751 adev->bubble_level->poll_once(adev->bubble_level);
Eric Laurenta989ebf2012-10-15 15:14:44 -0700752
Simon Wilson15f60a82012-04-24 20:56:32 -0700753 return 0;
754}
755
756/* must be called with hw device and input stream mutexes locked */
757static int start_input_stream(struct stream_in *in)
758{
759 struct audio_device *adev = in->dev;
760
Glenn Kastena83d9a12014-07-15 10:28:31 -0700761 in->pcm = pcm_open(PCM_CARD, PCM_DEVICE, PCM_IN, in->config);
Simon Wilson15f60a82012-04-24 20:56:32 -0700762
763 if (in->pcm && !pcm_is_ready(in->pcm)) {
764 ALOGE("pcm_open() failed: %s", pcm_get_error(in->pcm));
765 pcm_close(in->pcm);
766 return -ENOMEM;
767 }
768
769 /* if no supported sample rate is available, use the resampler */
770 if (in->resampler)
771 in->resampler->reset(in->resampler);
772
Eric Laurentf4231822012-08-22 16:06:38 -0700773 in->frames_in = 0;
Eric Laurent87532032012-07-16 13:53:20 -0700774 adev->input_source = in->input_source;
Eric Laurent42531fa2012-10-03 09:06:14 -0700775 adev->in_device = in->device;
Jean-Michel Trivi3f467de2013-06-06 15:26:01 -0700776 adev->in_channel_mask = in->channel_mask;
Jean-Michel Trivie04f7c92012-09-30 16:01:41 -0700777
778 eS305_SetActiveIoHandle(in->io_handle);
Eric Laurent87532032012-07-16 13:53:20 -0700779 select_devices(adev);
780
Eric Laurent4f1aece2013-04-19 17:10:25 -0700781 if (in->device & AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET)
782 start_bt_sco(adev);
783
Eric Laurent1a0c0a72012-08-24 11:29:04 -0700784 /* initialize volume ramp */
785 in->ramp_frames = (CAPTURE_START_RAMP_MS * in->requested_rate) / 1000;
786 in->ramp_step = (uint16_t)(USHRT_MAX / in->ramp_frames);
787 in->ramp_vol = 0;;
788
Eric Laurent429f24d2012-11-02 14:37:38 -0700789 if (get_bubblelevel(adev)) {
790 adev->bubble_level->set_poll_interval(adev->bubble_level, BL_POLL_INTERVAL_MIN_SEC);
791 adev->bubble_level->start_polling(adev->bubble_level);
792 }
Eric Laurenta989ebf2012-10-15 15:14:44 -0700793
Simon Wilson15f60a82012-04-24 20:56:32 -0700794 return 0;
795}
796
797static size_t get_input_buffer_size(unsigned int sample_rate,
798 audio_format_t format,
Glenn Kastena83d9a12014-07-15 10:28:31 -0700799 unsigned int channel_count,
800 bool is_low_latency)
Simon Wilson15f60a82012-04-24 20:56:32 -0700801{
Glenn Kastena83d9a12014-07-15 10:28:31 -0700802 const struct pcm_config *config = is_low_latency ?
803 &pcm_config_in_low_latency : &pcm_config_in;
Simon Wilson15f60a82012-04-24 20:56:32 -0700804 size_t size;
805
806 /*
807 * take resampling into account and return the closest majoring
808 * multiple of 16 frames, as audioflinger expects audio buffers to
809 * be a multiple of 16 frames
810 */
Glenn Kastena83d9a12014-07-15 10:28:31 -0700811 size = (config->period_size * sample_rate) / config->rate;
Simon Wilson15f60a82012-04-24 20:56:32 -0700812 size = ((size + 15) / 16) * 16;
813
814 return size * channel_count * audio_bytes_per_sample(format);
815}
816
817static int get_next_buffer(struct resampler_buffer_provider *buffer_provider,
818 struct resampler_buffer* buffer)
819{
820 struct stream_in *in;
Eric Laurentd7abdd02012-07-27 14:54:41 -0700821 size_t i;
Simon Wilson15f60a82012-04-24 20:56:32 -0700822
823 if (buffer_provider == NULL || buffer == NULL)
824 return -EINVAL;
825
826 in = (struct stream_in *)((char *)buffer_provider -
827 offsetof(struct stream_in, buf_provider));
828
829 if (in->pcm == NULL) {
830 buffer->raw = NULL;
831 buffer->frame_count = 0;
832 in->read_status = -ENODEV;
833 return -ENODEV;
834 }
835
836 if (in->frames_in == 0) {
837 in->read_status = pcm_read(in->pcm,
838 (void*)in->buffer,
Glenn Kastena83d9a12014-07-15 10:28:31 -0700839 pcm_frames_to_bytes(in->pcm, in->config->period_size));
Simon Wilson15f60a82012-04-24 20:56:32 -0700840 if (in->read_status != 0) {
841 ALOGE("get_next_buffer() pcm_read error %d", in->read_status);
842 buffer->raw = NULL;
843 buffer->frame_count = 0;
844 return in->read_status;
845 }
Eric Laurentd7abdd02012-07-27 14:54:41 -0700846
Glenn Kastena83d9a12014-07-15 10:28:31 -0700847 in->frames_in = in->config->period_size;
Eric Laurentd7abdd02012-07-27 14:54:41 -0700848
849 /* Do stereo to mono conversion in place by discarding right channel */
Eric Laurentb52afc82013-01-18 15:12:57 -0800850 if (in->channel_mask == AUDIO_CHANNEL_IN_MONO)
851 for (i = 1; i < in->frames_in; i++)
852 in->buffer[i] = in->buffer[i * 2];
Simon Wilson15f60a82012-04-24 20:56:32 -0700853 }
854
855 buffer->frame_count = (buffer->frame_count > in->frames_in) ?
856 in->frames_in : buffer->frame_count;
Eric Laurentb52afc82013-01-18 15:12:57 -0800857 buffer->i16 = in->buffer +
Glenn Kastena83d9a12014-07-15 10:28:31 -0700858 (in->config->period_size - in->frames_in) *
Eric Laurent1e7184b2014-07-01 20:29:10 -0700859 audio_channel_count_from_in_mask(in->channel_mask);
Simon Wilson15f60a82012-04-24 20:56:32 -0700860
861 return in->read_status;
862
863}
864
865static void release_buffer(struct resampler_buffer_provider *buffer_provider,
866 struct resampler_buffer* buffer)
867{
868 struct stream_in *in;
869
870 if (buffer_provider == NULL || buffer == NULL)
871 return;
872
873 in = (struct stream_in *)((char *)buffer_provider -
874 offsetof(struct stream_in, buf_provider));
875
876 in->frames_in -= buffer->frame_count;
877}
878
879/* read_frames() reads frames from kernel driver, down samples to capture rate
880 * if necessary and output the number of frames requested to the buffer specified */
881static ssize_t read_frames(struct stream_in *in, void *buffer, ssize_t frames)
882{
883 ssize_t frames_wr = 0;
Eric Laurent84c33732014-07-03 16:35:46 -0700884 size_t frame_size = audio_stream_in_frame_size(&in->stream);
Simon Wilson15f60a82012-04-24 20:56:32 -0700885
886 while (frames_wr < frames) {
887 size_t frames_rd = frames - frames_wr;
888 if (in->resampler != NULL) {
889 in->resampler->resample_from_provider(in->resampler,
890 (int16_t *)((char *)buffer +
Eric Laurentd7abdd02012-07-27 14:54:41 -0700891 frames_wr * frame_size),
Simon Wilson15f60a82012-04-24 20:56:32 -0700892 &frames_rd);
893 } else {
894 struct resampler_buffer buf = {
895 { raw : NULL, },
896 frame_count : frames_rd,
897 };
898 get_next_buffer(&in->buf_provider, &buf);
899 if (buf.raw != NULL) {
900 memcpy((char *)buffer +
Eric Laurentd7abdd02012-07-27 14:54:41 -0700901 frames_wr * frame_size,
Simon Wilson15f60a82012-04-24 20:56:32 -0700902 buf.raw,
Eric Laurentd7abdd02012-07-27 14:54:41 -0700903 buf.frame_count * frame_size);
Simon Wilson15f60a82012-04-24 20:56:32 -0700904 frames_rd = buf.frame_count;
905 }
906 release_buffer(&in->buf_provider, &buf);
907 }
908 /* in->read_status is updated by getNextBuffer() also called by
909 * in->resampler->resample_from_provider() */
910 if (in->read_status != 0)
911 return in->read_status;
912
913 frames_wr += frames_rd;
914 }
915 return frames_wr;
916}
917
918/* API functions */
919
920static uint32_t out_get_sample_rate(const struct audio_stream *stream)
921{
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700922 struct stream_out *out = (struct stream_out *)stream;
923
924 return out->config.rate;
Simon Wilson15f60a82012-04-24 20:56:32 -0700925}
926
927static int out_set_sample_rate(struct audio_stream *stream, uint32_t rate)
928{
929 return -ENOSYS;
930}
931
932static size_t out_get_buffer_size(const struct audio_stream *stream)
933{
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700934 struct stream_out *out = (struct stream_out *)stream;
Glenn Kastene0aa8f32012-08-17 09:26:58 -0700935
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700936 return out->config.period_size *
Eric Laurent84c33732014-07-03 16:35:46 -0700937 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Simon Wilson15f60a82012-04-24 20:56:32 -0700938}
939
Glenn Kastenca1414b2012-06-25 10:38:47 -0700940static audio_channel_mask_t out_get_channels(const struct audio_stream *stream)
Simon Wilson15f60a82012-04-24 20:56:32 -0700941{
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700942 struct stream_out *out = (struct stream_out *)stream;
943
944 return out->channel_mask;
Simon Wilson15f60a82012-04-24 20:56:32 -0700945}
946
947static audio_format_t out_get_format(const struct audio_stream *stream)
948{
949 return AUDIO_FORMAT_PCM_16_BIT;
950}
951
952static int out_set_format(struct audio_stream *stream, audio_format_t format)
953{
954 return -ENOSYS;
955}
956
Glenn Kasten068b84e2012-09-26 12:34:51 -0700957/* Return the set of output devices associated with active streams
958 * other than out. Assumes out is non-NULL and out->dev is locked.
959 */
960static audio_devices_t output_devices(struct stream_out *out)
961{
962 struct audio_device *dev = out->dev;
963 enum output_type type;
964 audio_devices_t devices = AUDIO_DEVICE_NONE;
965
966 for (type = 0; type < OUTPUT_TOTAL; ++type) {
967 struct stream_out *other = dev->outputs[type];
968 if (other && (other != out) && !other->standby) {
969 /* safe to access other stream without a mutex,
970 * because we hold the dev lock,
971 * which prevents the other stream from being closed
972 */
973 devices |= other->device;
974 }
975 }
976
977 return devices;
978}
979
Simon Wilson459d5bd2012-08-21 12:18:07 -0700980static int do_out_standby(struct stream_out *out)
Simon Wilson15f60a82012-04-24 20:56:32 -0700981{
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700982 struct audio_device *adev = out->dev;
Simon Wilson56d84e22012-08-17 13:55:27 -0700983 int i;
Simon Wilson15f60a82012-04-24 20:56:32 -0700984
Simon Wilson15f60a82012-04-24 20:56:32 -0700985 if (!out->standby) {
Simon Wilson56d84e22012-08-17 13:55:27 -0700986 for (i = 0; i < PCM_TOTAL; i++) {
987 if (out->pcm[i]) {
988 pcm_close(out->pcm[i]);
989 out->pcm[i] = NULL;
990 }
991 }
Simon Wilson15f60a82012-04-24 20:56:32 -0700992 out->standby = true;
Glenn Kastene0aa8f32012-08-17 09:26:58 -0700993
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700994 if (out == adev->outputs[OUTPUT_HDMI]) {
995 /* force standby on low latency output stream so that it can reuse HDMI driver if
996 * necessary when restarted */
997 force_non_hdmi_out_standby(adev);
998 }
Glenn Kastene0aa8f32012-08-17 09:26:58 -0700999
Eric Laurent4f1aece2013-04-19 17:10:25 -07001000 if (out->device & AUDIO_DEVICE_OUT_ALL_SCO)
1001 stop_bt_sco(adev);
1002
Eric Laurentb2c0b4f2012-09-21 11:42:48 -07001003 /* re-calculate the set of active devices from other streams */
1004 adev->out_device = output_devices(out);
Simon Wilson79a2e012012-10-19 14:20:33 -07001005
1006 /* Skip resetting the mixer if no output device is active */
1007 if (adev->out_device)
1008 select_devices(adev);
Simon Wilson15f60a82012-04-24 20:56:32 -07001009 }
1010
Simon Wilson459d5bd2012-08-21 12:18:07 -07001011 return 0;
1012}
1013
1014static int out_standby(struct audio_stream *stream)
1015{
1016 struct stream_out *out = (struct stream_out *)stream;
1017 int ret;
1018
1019 pthread_mutex_lock(&out->dev->lock);
1020 pthread_mutex_lock(&out->lock);
1021
1022 ret = do_out_standby(out);
1023
Simon Wilson15f60a82012-04-24 20:56:32 -07001024 pthread_mutex_unlock(&out->lock);
1025 pthread_mutex_unlock(&out->dev->lock);
1026
Simon Wilson459d5bd2012-08-21 12:18:07 -07001027 return ret;
Simon Wilson15f60a82012-04-24 20:56:32 -07001028}
1029
1030static int out_dump(const struct audio_stream *stream, int fd)
1031{
1032 return 0;
1033}
1034
1035static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
1036{
1037 struct stream_out *out = (struct stream_out *)stream;
1038 struct audio_device *adev = out->dev;
1039 struct str_parms *parms;
1040 char value[32];
1041 int ret;
1042 unsigned int val;
1043
1044 parms = str_parms_create_str(kvpairs);
1045
1046 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING,
1047 value, sizeof(value));
1048 pthread_mutex_lock(&adev->lock);
Eric Laurent87532032012-07-16 13:53:20 -07001049 pthread_mutex_lock(&out->lock);
Simon Wilson15f60a82012-04-24 20:56:32 -07001050 if (ret >= 0) {
1051 val = atoi(value);
Eric Laurent87532032012-07-16 13:53:20 -07001052 if ((out->device != val) && (val != 0)) {
Simon Wilson459d5bd2012-08-21 12:18:07 -07001053 /* Force standby if moving to/from SPDIF or if the output
1054 * device changes when in SPDIF mode */
1055 if (((val & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET) ^
Eric Laurent6a466d72012-08-28 12:13:38 -07001056 (adev->out_device & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET)) ||
1057 (adev->out_device & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET)) {
Simon Wilson459d5bd2012-08-21 12:18:07 -07001058 do_out_standby(out);
1059 }
1060
Eric Laurent4f1aece2013-04-19 17:10:25 -07001061 /* force output standby to start or stop SCO pcm stream if needed */
Simon Wilsona282d2f2012-09-12 16:14:24 -07001062 if ((val & AUDIO_DEVICE_OUT_ALL_SCO) ^
Eric Laurent4f1aece2013-04-19 17:10:25 -07001063 (out->device & AUDIO_DEVICE_OUT_ALL_SCO)) {
1064 do_out_standby(out);
Simon Wilsona282d2f2012-09-12 16:14:24 -07001065 }
1066
Eric Laurentb2c0b4f2012-09-21 11:42:48 -07001067 if (!out->standby && (out == adev->outputs[OUTPUT_HDMI] ||
1068 !adev->outputs[OUTPUT_HDMI] ||
1069 adev->outputs[OUTPUT_HDMI]->standby)) {
1070 adev->out_device = output_devices(out) | val;
Eric Laurent87532032012-07-16 13:53:20 -07001071 select_devices(adev);
1072 }
Eric Laurentb2c0b4f2012-09-21 11:42:48 -07001073 out->device = val;
Simon Wilson15f60a82012-04-24 20:56:32 -07001074 }
1075 }
Eric Laurent87532032012-07-16 13:53:20 -07001076 pthread_mutex_unlock(&out->lock);
Simon Wilson15f60a82012-04-24 20:56:32 -07001077 pthread_mutex_unlock(&adev->lock);
1078
1079 str_parms_destroy(parms);
1080 return ret;
1081}
1082
1083static char * out_get_parameters(const struct audio_stream *stream, const char *keys)
1084{
Eric Laurentb2c0b4f2012-09-21 11:42:48 -07001085 struct stream_out *out = (struct stream_out *)stream;
1086 struct str_parms *query = str_parms_create_str(keys);
1087 char *str;
1088 char value[256];
1089 struct str_parms *reply = str_parms_create();
1090 size_t i, j;
1091 int ret;
1092 bool first = true;
1093
1094 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
1095 if (ret >= 0) {
1096 value[0] = '\0';
1097 i = 0;
1098 /* the last entry in supported_channel_masks[] is always 0 */
1099 while (out->supported_channel_masks[i] != 0) {
1100 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
1101 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
1102 if (!first) {
1103 strcat(value, "|");
1104 }
1105 strcat(value, out_channels_name_to_enum_table[j].name);
1106 first = false;
1107 break;
1108 }
1109 }
1110 i++;
1111 }
1112 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
1113 str = str_parms_to_str(reply);
1114 } else {
1115 str = strdup(keys);
1116 }
1117
1118 str_parms_destroy(query);
1119 str_parms_destroy(reply);
1120 return str;
Simon Wilson15f60a82012-04-24 20:56:32 -07001121}
1122
1123static uint32_t out_get_latency(const struct audio_stream_out *stream)
1124{
Eric Laurentb2c0b4f2012-09-21 11:42:48 -07001125 struct stream_out *out = (struct stream_out *)stream;
Glenn Kastene0aa8f32012-08-17 09:26:58 -07001126
Eric Laurentb2c0b4f2012-09-21 11:42:48 -07001127 return (out->config.period_size * out->config.period_count * 1000) /
1128 out->config.rate;
Simon Wilson15f60a82012-04-24 20:56:32 -07001129}
1130
1131static int out_set_volume(struct audio_stream_out *stream, float left,
1132 float right)
1133{
Eric Laurent3948fda2013-04-04 09:24:22 -07001134 struct stream_out *out = (struct stream_out *)stream;
1135 struct audio_device *adev = out->dev;
1136
1137 if (out == adev->outputs[OUTPUT_HDMI]) {
1138 /* only take left channel into account: the API is for stereo anyway */
1139 out->muted = (left == 0.0f);
1140 return 0;
1141 }
Simon Wilson15f60a82012-04-24 20:56:32 -07001142 return -ENOSYS;
1143}
1144
1145static ssize_t out_write(struct audio_stream_out *stream, const void* buffer,
1146 size_t bytes)
1147{
Glenn Kastenf2d98022013-08-30 16:20:49 -07001148 int ret = 0;
Simon Wilson15f60a82012-04-24 20:56:32 -07001149 struct stream_out *out = (struct stream_out *)stream;
1150 struct audio_device *adev = out->dev;
Simon Wilson56d84e22012-08-17 13:55:27 -07001151 int i;
Simon Wilson15f60a82012-04-24 20:56:32 -07001152
1153 /*
1154 * acquiring hw device mutex systematically is useful if a low
1155 * priority thread is waiting on the output stream mutex - e.g.
1156 * executing out_set_parameters() while holding the hw device
1157 * mutex
1158 */
1159 pthread_mutex_lock(&adev->lock);
1160 pthread_mutex_lock(&out->lock);
1161 if (out->standby) {
1162 ret = start_output_stream(out);
1163 if (ret != 0) {
1164 pthread_mutex_unlock(&adev->lock);
1165 goto exit;
1166 }
1167 out->standby = false;
1168 }
1169 pthread_mutex_unlock(&adev->lock);
1170
Eric Laurentb2c0b4f2012-09-21 11:42:48 -07001171 if (out->disabled) {
1172 ret = -EPIPE;
1173 goto exit;
1174 }
1175
Eric Laurent3948fda2013-04-04 09:24:22 -07001176 if (out->muted)
1177 memset((void *)buffer, 0, bytes);
1178
Simon Wilson56d84e22012-08-17 13:55:27 -07001179 /* Write to all active PCMs */
1180 for (i = 0; i < PCM_TOTAL; i++)
Glenn Kasten21169cb2013-08-20 15:36:18 -07001181 if (out->pcm[i]) {
1182 ret = pcm_write(out->pcm[i], (void *)buffer, bytes);
1183 if (ret != 0)
1184 break;
1185 }
1186 if (ret == 0)
1187 out->written += bytes / (out->config.channels * sizeof(short));
Eric Laurentb2c0b4f2012-09-21 11:42:48 -07001188
Simon Wilson15f60a82012-04-24 20:56:32 -07001189exit:
1190 pthread_mutex_unlock(&out->lock);
1191
1192 if (ret != 0) {
Eric Laurent84c33732014-07-03 16:35:46 -07001193 usleep(bytes * 1000000 / audio_stream_out_frame_size(stream) /
Simon Wilson15f60a82012-04-24 20:56:32 -07001194 out_get_sample_rate(&stream->common));
1195 }
1196
1197 return bytes;
1198}
1199
1200static int out_get_render_position(const struct audio_stream_out *stream,
1201 uint32_t *dsp_frames)
1202{
1203 return -EINVAL;
1204}
1205
1206static int out_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
1207{
1208 return 0;
1209}
1210
1211static int out_remove_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
1212{
1213 return 0;
1214}
1215
1216static int out_get_next_write_timestamp(const struct audio_stream_out *stream,
1217 int64_t *timestamp)
1218{
1219 return -EINVAL;
1220}
1221
Glenn Kasten21169cb2013-08-20 15:36:18 -07001222static int out_get_presentation_position(const struct audio_stream_out *stream,
1223 uint64_t *frames, struct timespec *timestamp)
1224{
1225 struct stream_out *out = (struct stream_out *)stream;
1226 int ret = -1;
1227
1228 pthread_mutex_lock(&out->lock);
1229
1230 int i;
1231 // There is a question how to implement this correctly when there is more than one PCM stream.
1232 // We are just interested in the frames pending for playback in the kernel buffer here,
1233 // not the total played since start. The current behavior should be safe because the
1234 // cases where both cards are active are marginal.
1235 for (i = 0; i < PCM_TOTAL; i++)
1236 if (out->pcm[i]) {
1237 size_t avail;
1238 if (pcm_get_htimestamp(out->pcm[i], &avail, timestamp) == 0) {
1239 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
1240 // FIXME This calculation is incorrect if there is buffering after app processor
1241 int64_t signed_frames = out->written - kernel_buffer_size + avail;
1242 // It would be unusual for this value to be negative, but check just in case ...
1243 if (signed_frames >= 0) {
1244 *frames = signed_frames;
1245 ret = 0;
1246 }
1247 break;
1248 }
1249 }
1250
1251 pthread_mutex_unlock(&out->lock);
1252
1253 return ret;
1254}
1255
Simon Wilson15f60a82012-04-24 20:56:32 -07001256/** audio_stream_in implementation **/
1257static uint32_t in_get_sample_rate(const struct audio_stream *stream)
1258{
1259 struct stream_in *in = (struct stream_in *)stream;
1260
1261 return in->requested_rate;
1262}
1263
1264static int in_set_sample_rate(struct audio_stream *stream, uint32_t rate)
1265{
1266 return 0;
1267}
1268
Eric Laurentd7abdd02012-07-27 14:54:41 -07001269static audio_channel_mask_t in_get_channels(const struct audio_stream *stream)
1270{
Eric Laurentb52afc82013-01-18 15:12:57 -08001271 struct stream_in *in = (struct stream_in *)stream;
1272
1273 return in->channel_mask;
Eric Laurentd7abdd02012-07-27 14:54:41 -07001274}
1275
1276
Simon Wilson15f60a82012-04-24 20:56:32 -07001277static size_t in_get_buffer_size(const struct audio_stream *stream)
1278{
1279 struct stream_in *in = (struct stream_in *)stream;
1280
1281 return get_input_buffer_size(in->requested_rate,
1282 AUDIO_FORMAT_PCM_16_BIT,
Glenn Kastena83d9a12014-07-15 10:28:31 -07001283 audio_channel_count_from_in_mask(in_get_channels(stream)),
1284 (in->flags & AUDIO_INPUT_FLAG_FAST) != 0);
Simon Wilson15f60a82012-04-24 20:56:32 -07001285}
1286
1287static audio_format_t in_get_format(const struct audio_stream *stream)
1288{
1289 return AUDIO_FORMAT_PCM_16_BIT;
1290}
1291
1292static int in_set_format(struct audio_stream *stream, audio_format_t format)
1293{
1294 return -ENOSYS;
1295}
1296
Eric Laurent4f1aece2013-04-19 17:10:25 -07001297static int do_in_standby(struct stream_in *in)
Simon Wilson15f60a82012-04-24 20:56:32 -07001298{
Eric Laurent4f1aece2013-04-19 17:10:25 -07001299 struct audio_device *adev = in->dev;
Simon Wilson15f60a82012-04-24 20:56:32 -07001300
1301 if (!in->standby) {
1302 pcm_close(in->pcm);
1303 in->pcm = NULL;
Eric Laurent4f1aece2013-04-19 17:10:25 -07001304
1305 if (in->device & AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET)
1306 stop_bt_sco(adev);
1307
Eric Laurent87532032012-07-16 13:53:20 -07001308 in->dev->input_source = AUDIO_SOURCE_DEFAULT;
Eric Laurent42531fa2012-10-03 09:06:14 -07001309 in->dev->in_device = AUDIO_DEVICE_NONE;
Jean-Michel Trivi3f467de2013-06-06 15:26:01 -07001310 in->dev->in_channel_mask = 0;
Eric Laurent4f1aece2013-04-19 17:10:25 -07001311 select_devices(adev);
Simon Wilson15f60a82012-04-24 20:56:32 -07001312 in->standby = true;
Eric Laurenta989ebf2012-10-15 15:14:44 -07001313
Eric Laurent4f1aece2013-04-19 17:10:25 -07001314 if (get_bubblelevel(adev))
1315 in->dev->bubble_level->stop_polling(adev->bubble_level);
Simon Wilson15f60a82012-04-24 20:56:32 -07001316 }
1317
Jean-Michel Trivie04f7c92012-09-30 16:01:41 -07001318 eS305_SetActiveIoHandle(ES305_IO_HANDLE_NONE);
Eric Laurent4f1aece2013-04-19 17:10:25 -07001319 return 0;
1320}
1321
1322static int in_standby(struct audio_stream *stream)
1323{
1324 struct stream_in *in = (struct stream_in *)stream;
1325 int ret;
1326
1327 pthread_mutex_lock(&in->dev->lock);
1328 pthread_mutex_lock(&in->lock);
1329
1330 ret = do_in_standby(in);
Jean-Michel Trivie04f7c92012-09-30 16:01:41 -07001331
Simon Wilson15f60a82012-04-24 20:56:32 -07001332 pthread_mutex_unlock(&in->lock);
1333 pthread_mutex_unlock(&in->dev->lock);
1334
Eric Laurent4f1aece2013-04-19 17:10:25 -07001335 return ret;
Simon Wilson15f60a82012-04-24 20:56:32 -07001336}
1337
1338static int in_dump(const struct audio_stream *stream, int fd)
1339{
1340 return 0;
1341}
1342
1343static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
1344{
1345 struct stream_in *in = (struct stream_in *)stream;
1346 struct audio_device *adev = in->dev;
1347 struct str_parms *parms;
1348 char value[32];
1349 int ret;
1350 unsigned int val;
Eric Laurent87532032012-07-16 13:53:20 -07001351 bool apply_now = false;
Simon Wilson15f60a82012-04-24 20:56:32 -07001352
1353 parms = str_parms_create_str(kvpairs);
1354
Simon Wilson15f60a82012-04-24 20:56:32 -07001355 pthread_mutex_lock(&adev->lock);
Eric Laurent87532032012-07-16 13:53:20 -07001356 pthread_mutex_lock(&in->lock);
Eric Laurent42531fa2012-10-03 09:06:14 -07001357 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE,
1358 value, sizeof(value));
Simon Wilson15f60a82012-04-24 20:56:32 -07001359 if (ret >= 0) {
1360 val = atoi(value);
Eric Laurent87532032012-07-16 13:53:20 -07001361 /* no audio source uses val == 0 */
1362 if ((in->input_source != val) && (val != 0)) {
1363 in->input_source = val;
1364 apply_now = !in->standby;
Simon Wilson15f60a82012-04-24 20:56:32 -07001365 }
1366 }
Eric Laurent87532032012-07-16 13:53:20 -07001367
Eric Laurent42531fa2012-10-03 09:06:14 -07001368 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING,
1369 value, sizeof(value));
1370 if (ret >= 0) {
Eric Laurent4f1aece2013-04-19 17:10:25 -07001371 /* strip AUDIO_DEVICE_BIT_IN to allow bitwise comparisons */
1372 val = atoi(value) & ~AUDIO_DEVICE_BIT_IN;
Eric Laurent42531fa2012-10-03 09:06:14 -07001373 /* no audio device uses val == 0 */
1374 if ((in->device != val) && (val != 0)) {
Eric Laurent4f1aece2013-04-19 17:10:25 -07001375 /* force output standby to start or stop SCO pcm stream if needed */
1376 if ((val & AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET) ^
1377 (in->device & AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET)) {
1378 do_in_standby(in);
1379 }
Eric Laurent42531fa2012-10-03 09:06:14 -07001380 in->device = val;
1381 apply_now = !in->standby;
1382 }
1383 }
1384
Eric Laurent87532032012-07-16 13:53:20 -07001385 if (apply_now) {
Eric Laurent87532032012-07-16 13:53:20 -07001386 adev->input_source = in->input_source;
Eric Laurent42531fa2012-10-03 09:06:14 -07001387 adev->in_device = in->device;
Eric Laurent87532032012-07-16 13:53:20 -07001388 select_devices(adev);
1389 }
1390
1391 pthread_mutex_unlock(&in->lock);
Simon Wilson15f60a82012-04-24 20:56:32 -07001392 pthread_mutex_unlock(&adev->lock);
1393
1394 str_parms_destroy(parms);
1395 return ret;
1396}
1397
1398static char * in_get_parameters(const struct audio_stream *stream,
1399 const char *keys)
1400{
1401 return strdup("");
1402}
1403
1404static int in_set_gain(struct audio_stream_in *stream, float gain)
1405{
1406 return 0;
1407}
1408
Eric Laurent1a0c0a72012-08-24 11:29:04 -07001409static void in_apply_ramp(struct stream_in *in, int16_t *buffer, size_t frames)
1410{
1411 size_t i;
1412 uint16_t vol = in->ramp_vol;
1413 uint16_t step = in->ramp_step;
1414
1415 frames = (frames < in->ramp_frames) ? frames : in->ramp_frames;
1416
Eric Laurentb52afc82013-01-18 15:12:57 -08001417 if (in->channel_mask == AUDIO_CHANNEL_IN_MONO)
1418 for (i = 0; i < frames; i++)
1419 {
1420 buffer[i] = (int16_t)((buffer[i] * vol) >> 16);
1421 vol += step;
1422 }
1423 else
1424 for (i = 0; i < frames; i++)
1425 {
1426 buffer[2*i] = (int16_t)((buffer[2*i] * vol) >> 16);
1427 buffer[2*i + 1] = (int16_t)((buffer[2*i + 1] * vol) >> 16);
1428 vol += step;
1429 }
1430
Eric Laurent1a0c0a72012-08-24 11:29:04 -07001431
1432 in->ramp_vol = vol;
1433 in->ramp_frames -= frames;
1434}
1435
Simon Wilson15f60a82012-04-24 20:56:32 -07001436static ssize_t in_read(struct audio_stream_in *stream, void* buffer,
1437 size_t bytes)
1438{
1439 int ret = 0;
1440 struct stream_in *in = (struct stream_in *)stream;
1441 struct audio_device *adev = in->dev;
Eric Laurent84c33732014-07-03 16:35:46 -07001442 size_t frames_rq = bytes / audio_stream_in_frame_size(stream);
Simon Wilson15f60a82012-04-24 20:56:32 -07001443
1444 /*
1445 * acquiring hw device mutex systematically is useful if a low
1446 * priority thread is waiting on the input stream mutex - e.g.
1447 * executing in_set_parameters() while holding the hw device
1448 * mutex
1449 */
1450 pthread_mutex_lock(&adev->lock);
1451 pthread_mutex_lock(&in->lock);
1452 if (in->standby) {
1453 ret = start_input_stream(in);
1454 if (ret == 0)
1455 in->standby = 0;
1456 }
1457 pthread_mutex_unlock(&adev->lock);
1458
1459 if (ret < 0)
1460 goto exit;
1461
1462 /*if (in->num_preprocessors != 0)
1463 ret = process_frames(in, buffer, frames_rq);
Eric Laurentd7abdd02012-07-27 14:54:41 -07001464 else */
1465 ret = read_frames(in, buffer, frames_rq);
Simon Wilson15f60a82012-04-24 20:56:32 -07001466
1467 if (ret > 0)
1468 ret = 0;
1469
Eric Laurent1a0c0a72012-08-24 11:29:04 -07001470 if (in->ramp_frames > 0)
1471 in_apply_ramp(in, buffer, frames_rq);
1472
Simon Wilson15f60a82012-04-24 20:56:32 -07001473 /*
1474 * Instead of writing zeroes here, we could trust the hardware
1475 * to always provide zeroes when muted.
1476 */
1477 if (ret == 0 && adev->mic_mute)
1478 memset(buffer, 0, bytes);
1479
1480exit:
1481 if (ret < 0)
Eric Laurent84c33732014-07-03 16:35:46 -07001482 usleep(bytes * 1000000 / audio_stream_in_frame_size(stream) /
Simon Wilson15f60a82012-04-24 20:56:32 -07001483 in_get_sample_rate(&stream->common));
1484
1485 pthread_mutex_unlock(&in->lock);
1486 return bytes;
1487}
1488
1489static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream)
1490{
1491 return 0;
1492}
1493
1494static int in_add_audio_effect(const struct audio_stream *stream,
1495 effect_handle_t effect)
1496{
Jean-Michel Trivie04f7c92012-09-30 16:01:41 -07001497 struct stream_in *in = (struct stream_in *)stream;
1498 effect_descriptor_t descr;
1499 if ((*effect)->get_descriptor(effect, &descr) == 0) {
1500
1501 pthread_mutex_lock(&in->dev->lock);
1502 pthread_mutex_lock(&in->lock);
1503
1504 eS305_AddEffect(&descr, in->io_handle);
1505
1506 pthread_mutex_unlock(&in->lock);
1507 pthread_mutex_unlock(&in->dev->lock);
1508 }
1509
Simon Wilson15f60a82012-04-24 20:56:32 -07001510 return 0;
1511}
1512
1513static int in_remove_audio_effect(const struct audio_stream *stream,
1514 effect_handle_t effect)
1515{
Jean-Michel Trivie04f7c92012-09-30 16:01:41 -07001516 struct stream_in *in = (struct stream_in *)stream;
1517 effect_descriptor_t descr;
1518 if ((*effect)->get_descriptor(effect, &descr) == 0) {
1519
1520 pthread_mutex_lock(&in->dev->lock);
1521 pthread_mutex_lock(&in->lock);
1522
1523 eS305_RemoveEffect(&descr, in->io_handle);
1524
1525 pthread_mutex_unlock(&in->lock);
1526 pthread_mutex_unlock(&in->dev->lock);
1527 }
1528
Simon Wilson15f60a82012-04-24 20:56:32 -07001529 return 0;
1530}
1531
Simon Wilson15f60a82012-04-24 20:56:32 -07001532static int adev_open_output_stream(struct audio_hw_device *dev,
1533 audio_io_handle_t handle,
1534 audio_devices_t devices,
1535 audio_output_flags_t flags,
1536 struct audio_config *config,
Eric Laurent2f4b8092014-07-27 17:23:22 -07001537 struct audio_stream_out **stream_out,
1538 const char *address __unused)
Simon Wilson15f60a82012-04-24 20:56:32 -07001539{
1540 struct audio_device *adev = (struct audio_device *)dev;
1541 struct stream_out *out;
1542 int ret;
Glenn Kastene0aa8f32012-08-17 09:26:58 -07001543 enum output_type type;
Simon Wilson15f60a82012-04-24 20:56:32 -07001544
1545 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
1546 if (!out)
1547 return -ENOMEM;
1548
Eric Laurentb2c0b4f2012-09-21 11:42:48 -07001549 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
1550 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
1551 if (devices == AUDIO_DEVICE_NONE)
1552 devices = AUDIO_DEVICE_OUT_SPEAKER;
1553 out->device = devices;
1554
1555 if (flags & AUDIO_OUTPUT_FLAG_DIRECT &&
1556 devices == AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1557 pthread_mutex_lock(&adev->lock);
1558 ret = read_hdmi_channel_masks(adev, out);
1559 pthread_mutex_unlock(&adev->lock);
1560 if (ret != 0)
1561 goto err_open;
1562 if (config->sample_rate == 0)
1563 config->sample_rate = HDMI_MULTI_DEFAULT_SAMPLING_RATE;
1564 if (config->channel_mask == 0)
1565 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
1566 out->channel_mask = config->channel_mask;
1567 out->config = pcm_config_hdmi_multi;
1568 out->config.rate = config->sample_rate;
Eric Laurent1e7184b2014-07-01 20:29:10 -07001569 out->config.channels = audio_channel_count_from_out_mask(config->channel_mask);
Eric Laurentb2c0b4f2012-09-21 11:42:48 -07001570 out->pcm_device = PCM_DEVICE;
1571 type = OUTPUT_HDMI;
1572 } else if (flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
1573 out->config = pcm_config_deep;
1574 out->pcm_device = PCM_DEVICE_DEEP;
1575 type = OUTPUT_DEEP_BUF;
1576 } else {
1577 out->config = pcm_config;
1578 out->pcm_device = PCM_DEVICE;
1579 type = OUTPUT_LOW_LATENCY;
1580 }
1581
Simon Wilson15f60a82012-04-24 20:56:32 -07001582 out->stream.common.get_sample_rate = out_get_sample_rate;
1583 out->stream.common.set_sample_rate = out_set_sample_rate;
1584 out->stream.common.get_buffer_size = out_get_buffer_size;
1585 out->stream.common.get_channels = out_get_channels;
1586 out->stream.common.get_format = out_get_format;
1587 out->stream.common.set_format = out_set_format;
1588 out->stream.common.standby = out_standby;
1589 out->stream.common.dump = out_dump;
1590 out->stream.common.set_parameters = out_set_parameters;
1591 out->stream.common.get_parameters = out_get_parameters;
1592 out->stream.common.add_audio_effect = out_add_audio_effect;
1593 out->stream.common.remove_audio_effect = out_remove_audio_effect;
1594 out->stream.get_latency = out_get_latency;
1595 out->stream.set_volume = out_set_volume;
1596 out->stream.write = out_write;
1597 out->stream.get_render_position = out_get_render_position;
1598 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten21169cb2013-08-20 15:36:18 -07001599 out->stream.get_presentation_position = out_get_presentation_position;
Simon Wilson15f60a82012-04-24 20:56:32 -07001600
1601 out->dev = adev;
1602
1603 config->format = out_get_format(&out->stream.common);
1604 config->channel_mask = out_get_channels(&out->stream.common);
1605 config->sample_rate = out_get_sample_rate(&out->stream.common);
1606
1607 out->standby = true;
Eric Laurent3948fda2013-04-04 09:24:22 -07001608 /* out->muted = false; by calloc() */
Glenn Kasten21169cb2013-08-20 15:36:18 -07001609 /* out->written = 0; by calloc() */
Simon Wilson15f60a82012-04-24 20:56:32 -07001610
Glenn Kastene0aa8f32012-08-17 09:26:58 -07001611 pthread_mutex_lock(&adev->lock);
1612 if (adev->outputs[type]) {
1613 pthread_mutex_unlock(&adev->lock);
1614 ret = -EBUSY;
1615 goto err_open;
1616 }
1617 adev->outputs[type] = out;
1618 pthread_mutex_unlock(&adev->lock);
1619
Simon Wilson15f60a82012-04-24 20:56:32 -07001620 *stream_out = &out->stream;
Eric Laurentb2c0b4f2012-09-21 11:42:48 -07001621
Simon Wilson15f60a82012-04-24 20:56:32 -07001622 return 0;
1623
1624err_open:
1625 free(out);
1626 *stream_out = NULL;
1627 return ret;
1628}
1629
1630static void adev_close_output_stream(struct audio_hw_device *dev,
1631 struct audio_stream_out *stream)
1632{
Glenn Kastene0aa8f32012-08-17 09:26:58 -07001633 struct audio_device *adev;
1634 enum output_type type;
1635
Simon Wilson15f60a82012-04-24 20:56:32 -07001636 out_standby(&stream->common);
Glenn Kastene0aa8f32012-08-17 09:26:58 -07001637 adev = (struct audio_device *)dev;
1638 pthread_mutex_lock(&adev->lock);
1639 for (type = 0; type < OUTPUT_TOTAL; ++type) {
1640 if (adev->outputs[type] == (struct stream_out *) stream) {
1641 adev->outputs[type] = NULL;
Eric Laurentb2c0b4f2012-09-21 11:42:48 -07001642 break;
Glenn Kastene0aa8f32012-08-17 09:26:58 -07001643 }
1644 }
1645 pthread_mutex_unlock(&adev->lock);
Simon Wilson15f60a82012-04-24 20:56:32 -07001646 free(stream);
1647}
1648
1649static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
1650{
Eric Laurenta989ebf2012-10-15 15:14:44 -07001651 return 0;
Simon Wilson15f60a82012-04-24 20:56:32 -07001652}
1653
1654static char * adev_get_parameters(const struct audio_hw_device *dev,
1655 const char *keys)
1656{
Eric Laurent688880c2012-09-07 16:46:00 -07001657 struct audio_device *adev = (struct audio_device *)dev;
1658 struct str_parms *parms = str_parms_create_str(keys);
1659 char value[32];
1660 int ret = str_parms_get_str(parms, "ec_supported", value, sizeof(value));
1661 char *str;
1662
1663 str_parms_destroy(parms);
1664 if (ret >= 0) {
Jean-Michel Trivie04f7c92012-09-30 16:01:41 -07001665 parms = str_parms_create_str("ec_supported=yes");
Eric Laurent688880c2012-09-07 16:46:00 -07001666 str = str_parms_to_str(parms);
1667 str_parms_destroy(parms);
1668 return str;
1669 }
Simon Wilson15f60a82012-04-24 20:56:32 -07001670 return strdup("");
1671}
1672
1673static int adev_init_check(const struct audio_hw_device *dev)
1674{
1675 return 0;
1676}
1677
1678static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
1679{
1680 return -ENOSYS;
1681}
1682
1683static int adev_set_master_volume(struct audio_hw_device *dev, float volume)
1684{
1685 return -ENOSYS;
1686}
1687
1688static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
1689{
1690 return 0;
1691}
1692
1693static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
1694{
1695 struct audio_device *adev = (struct audio_device *)dev;
1696
1697 adev->mic_mute = state;
1698
1699 return 0;
1700}
1701
1702static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
1703{
1704 struct audio_device *adev = (struct audio_device *)dev;
1705
1706 *state = adev->mic_mute;
1707
1708 return 0;
1709}
1710
1711static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev,
1712 const struct audio_config *config)
1713{
1714
1715 return get_input_buffer_size(config->sample_rate, config->format,
Glenn Kastena83d9a12014-07-15 10:28:31 -07001716 audio_channel_count_from_in_mask(config->channel_mask),
1717 false /* is_low_latency: since we don't know, be conservative */);
Simon Wilson15f60a82012-04-24 20:56:32 -07001718}
1719
1720static int adev_open_input_stream(struct audio_hw_device *dev,
1721 audio_io_handle_t handle,
1722 audio_devices_t devices,
1723 struct audio_config *config,
Glenn Kastena83d9a12014-07-15 10:28:31 -07001724 struct audio_stream_in **stream_in,
Eric Laurent2f4b8092014-07-27 17:23:22 -07001725 audio_input_flags_t flags,
1726 const char *address __unused,
1727 audio_source_t source __unused)
Simon Wilson15f60a82012-04-24 20:56:32 -07001728{
1729 struct audio_device *adev = (struct audio_device *)dev;
1730 struct stream_in *in;
1731 int ret;
1732
1733 *stream_in = NULL;
1734
Eric Laurentd7abdd02012-07-27 14:54:41 -07001735 /* Respond with a request for mono if a different format is given. */
Eric Laurentb52afc82013-01-18 15:12:57 -08001736 if (config->channel_mask != AUDIO_CHANNEL_IN_MONO &&
1737 config->channel_mask != AUDIO_CHANNEL_IN_FRONT_BACK) {
Eric Laurentd7abdd02012-07-27 14:54:41 -07001738 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
Simon Wilson15f60a82012-04-24 20:56:32 -07001739 return -EINVAL;
1740 }
1741
1742 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
1743 if (!in)
1744 return -ENOMEM;
1745
1746 in->stream.common.get_sample_rate = in_get_sample_rate;
1747 in->stream.common.set_sample_rate = in_set_sample_rate;
1748 in->stream.common.get_buffer_size = in_get_buffer_size;
1749 in->stream.common.get_channels = in_get_channels;
1750 in->stream.common.get_format = in_get_format;
1751 in->stream.common.set_format = in_set_format;
1752 in->stream.common.standby = in_standby;
1753 in->stream.common.dump = in_dump;
1754 in->stream.common.set_parameters = in_set_parameters;
1755 in->stream.common.get_parameters = in_get_parameters;
1756 in->stream.common.add_audio_effect = in_add_audio_effect;
1757 in->stream.common.remove_audio_effect = in_remove_audio_effect;
1758 in->stream.set_gain = in_set_gain;
1759 in->stream.read = in_read;
1760 in->stream.get_input_frames_lost = in_get_input_frames_lost;
1761
1762 in->dev = adev;
1763 in->standby = true;
1764 in->requested_rate = config->sample_rate;
Eric Laurent87532032012-07-16 13:53:20 -07001765 in->input_source = AUDIO_SOURCE_DEFAULT;
Eric Laurent4f1aece2013-04-19 17:10:25 -07001766 /* strip AUDIO_DEVICE_BIT_IN to allow bitwise comparisons */
1767 in->device = devices & ~AUDIO_DEVICE_BIT_IN;
Jean-Michel Trivie04f7c92012-09-30 16:01:41 -07001768 in->io_handle = handle;
Eric Laurentb52afc82013-01-18 15:12:57 -08001769 in->channel_mask = config->channel_mask;
Glenn Kastena83d9a12014-07-15 10:28:31 -07001770 in->flags = flags;
1771 struct pcm_config *pcm_config = flags & AUDIO_INPUT_FLAG_FAST ?
1772 &pcm_config_in_low_latency : &pcm_config_in;
1773 in->config = pcm_config;
Simon Wilson15f60a82012-04-24 20:56:32 -07001774
Glenn Kastena83d9a12014-07-15 10:28:31 -07001775 in->buffer = malloc(pcm_config->period_size * pcm_config->channels
Eric Laurent84c33732014-07-03 16:35:46 -07001776 * audio_stream_in_frame_size(&in->stream));
Eric Laurentd7abdd02012-07-27 14:54:41 -07001777
Simon Wilson15f60a82012-04-24 20:56:32 -07001778 if (!in->buffer) {
1779 ret = -ENOMEM;
1780 goto err_malloc;
1781 }
1782
Glenn Kastena83d9a12014-07-15 10:28:31 -07001783 if (in->requested_rate != pcm_config->rate) {
Simon Wilson15f60a82012-04-24 20:56:32 -07001784 in->buf_provider.get_next_buffer = get_next_buffer;
1785 in->buf_provider.release_buffer = release_buffer;
1786
Glenn Kastena83d9a12014-07-15 10:28:31 -07001787 ret = create_resampler(pcm_config->rate,
Simon Wilson15f60a82012-04-24 20:56:32 -07001788 in->requested_rate,
Eric Laurent1e7184b2014-07-01 20:29:10 -07001789 audio_channel_count_from_in_mask(in->channel_mask),
Simon Wilson15f60a82012-04-24 20:56:32 -07001790 RESAMPLER_QUALITY_DEFAULT,
1791 &in->buf_provider,
1792 &in->resampler);
1793 if (ret != 0) {
1794 ret = -EINVAL;
1795 goto err_resampler;
1796 }
1797 }
1798
1799 *stream_in = &in->stream;
1800 return 0;
1801
1802err_resampler:
1803 free(in->buffer);
1804err_malloc:
1805 free(in);
1806 return ret;
1807}
1808
1809static void adev_close_input_stream(struct audio_hw_device *dev,
1810 struct audio_stream_in *stream)
1811{
1812 struct stream_in *in = (struct stream_in *)stream;
1813
1814 in_standby(&stream->common);
1815 if (in->resampler) {
1816 release_resampler(in->resampler);
1817 in->resampler = NULL;
1818 }
1819 free(in->buffer);
1820 free(stream);
1821}
1822
1823static int adev_dump(const audio_hw_device_t *device, int fd)
1824{
1825 return 0;
1826}
1827
1828static int adev_close(hw_device_t *device)
1829{
1830 struct audio_device *adev = (struct audio_device *)device;
1831
1832 audio_route_free(adev->ar);
1833
Jean-Michel Trivie04f7c92012-09-30 16:01:41 -07001834 eS305_Release();
1835
Eric Laurentb2c0b4f2012-09-21 11:42:48 -07001836 if (adev->hdmi_drv_fd >= 0)
1837 close(adev->hdmi_drv_fd);
Eric Laurent688880c2012-09-07 16:46:00 -07001838
Eric Laurent429f24d2012-11-02 14:37:38 -07001839 if (adev->bubble_level)
1840 bubble_level_release(adev->bubble_level);
Eric Laurenta989ebf2012-10-15 15:14:44 -07001841
Simon Wilson15f60a82012-04-24 20:56:32 -07001842 free(device);
1843 return 0;
1844}
1845
Simon Wilson15f60a82012-04-24 20:56:32 -07001846static int adev_open(const hw_module_t* module, const char* name,
1847 hw_device_t** device)
1848{
1849 struct audio_device *adev;
1850 int ret;
1851
1852 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0)
1853 return -EINVAL;
1854
1855 adev = calloc(1, sizeof(struct audio_device));
1856 if (!adev)
1857 return -ENOMEM;
1858
1859 adev->hw_device.common.tag = HARDWARE_DEVICE_TAG;
Eric Laurent6a466d72012-08-28 12:13:38 -07001860 adev->hw_device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
Simon Wilson15f60a82012-04-24 20:56:32 -07001861 adev->hw_device.common.module = (struct hw_module_t *) module;
1862 adev->hw_device.common.close = adev_close;
1863
Simon Wilson15f60a82012-04-24 20:56:32 -07001864 adev->hw_device.init_check = adev_init_check;
1865 adev->hw_device.set_voice_volume = adev_set_voice_volume;
1866 adev->hw_device.set_master_volume = adev_set_master_volume;
1867 adev->hw_device.set_mode = adev_set_mode;
1868 adev->hw_device.set_mic_mute = adev_set_mic_mute;
1869 adev->hw_device.get_mic_mute = adev_get_mic_mute;
1870 adev->hw_device.set_parameters = adev_set_parameters;
1871 adev->hw_device.get_parameters = adev_get_parameters;
1872 adev->hw_device.get_input_buffer_size = adev_get_input_buffer_size;
1873 adev->hw_device.open_output_stream = adev_open_output_stream;
1874 adev->hw_device.close_output_stream = adev_close_output_stream;
1875 adev->hw_device.open_input_stream = adev_open_input_stream;
1876 adev->hw_device.close_input_stream = adev_close_input_stream;
1877 adev->hw_device.dump = adev_dump;
1878
Simon Wilson759c6f02013-01-15 16:38:56 -08001879 adev->ar = audio_route_init(MIXER_CARD, NULL);
Eric Laurent87532032012-07-16 13:53:20 -07001880 adev->input_source = AUDIO_SOURCE_DEFAULT;
1881 /* adev->cur_route_id initial value is 0 and such that first device
1882 * selection is always applied by select_devices() */
Simon Wilson15f60a82012-04-24 20:56:32 -07001883
Eric Laurent688880c2012-09-07 16:46:00 -07001884 adev->es305_preset = ES305_PRESET_INIT;
Eric Laurenta989ebf2012-10-15 15:14:44 -07001885 adev->es305_new_mode = ES305_MODE_LEVEL;
1886 adev->es305_mode = ES305_MODE_LEVEL;
Eric Laurentb2c0b4f2012-09-21 11:42:48 -07001887 adev->hdmi_drv_fd = -1;
Eric Laurent4f1aece2013-04-19 17:10:25 -07001888
Simon Wilson15f60a82012-04-24 20:56:32 -07001889 *device = &adev->hw_device.common;
1890
Glenn Kasten6e11d0a2014-05-12 14:41:05 -07001891 char value[PROPERTY_VALUE_MAX];
1892 if (property_get("audio_hal.period_size", value, NULL) > 0) {
1893 pcm_config.period_size = atoi(value);
1894 pcm_config_in.period_size = pcm_config.period_size;
1895 }
1896 if (property_get("audio_hal.in_period_size", value, NULL) > 0)
1897 pcm_config_in.period_size = atoi(value);
1898
Simon Wilson15f60a82012-04-24 20:56:32 -07001899 return 0;
1900}
1901
1902static struct hw_module_methods_t hal_module_methods = {
1903 .open = adev_open,
1904};
1905
1906struct audio_module HAL_MODULE_INFO_SYM = {
1907 .common = {
1908 .tag = HARDWARE_MODULE_TAG,
1909 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
1910 .hal_api_version = HARDWARE_HAL_API_VERSION,
1911 .id = AUDIO_HARDWARE_MODULE_ID,
1912 .name = "Manta audio HW HAL",
1913 .author = "The Android Open Source Project",
1914 .methods = &hal_module_methods,
1915 },
1916};