summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNishanth Menon2014-11-11 17:28:38 -0600
committerNishanth Menon2014-11-11 17:28:38 -0600
commit88fc70c0850794fb0bce52f63dfcc0d8f3d5062e (patch)
treebd2acd9a43827c481dfcca8049f0206c2f7979ef /audio/multizone
downloaddevice-ti-x15-88fc70c0850794fb0bce52f63dfcc0d8f3d5062e.tar.gz
device-ti-x15-88fc70c0850794fb0bce52f63dfcc0d8f3d5062e.tar.xz
device-ti-x15-88fc70c0850794fb0bce52f63dfcc0d8f3d5062e.zip
initial baseline from TI's code
Signed-off-by: Nishanth Menon <nm@ti.com>
Diffstat (limited to 'audio/multizone')
-rw-r--r--audio/multizone/Android.mk53
-rw-r--r--audio/multizone/AudioHw.cpp1276
-rw-r--r--audio/multizone/AudioHw.h251
-rw-r--r--audio/multizone/audio_hw.cpp562
-rw-r--r--audio/multizone/audio_policy.conf116
5 files changed, 2258 insertions, 0 deletions
diff --git a/audio/multizone/Android.mk b/audio/multizone/Android.mk
new file mode 100644
index 0000000..bf1c4d7
--- /dev/null
+++ b/audio/multizone/Android.mk
@@ -0,0 +1,53 @@
1# Copyright (C) 2013 Texas Instruments
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14
15LOCAL_PATH := $(call my-dir)
16
17include $(CLEAR_VARS)
18LOCAL_MODULE := audio_policy.conf
19LOCAL_MODULE_TAGS := optional
20LOCAL_MODULE_CLASS := ETC
21LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)
22LOCAL_SRC_FILES := $(LOCAL_MODULE)
23include $(BUILD_PREBUILT)
24
25include $(CLEAR_VARS)
26
27LOCAL_MODULE := audio.primary.$(TARGET_BOARD_PLATFORM)
28
29LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
30
31LOCAL_SRC_FILES := \
32 AudioHw.cpp \
33 audio_hw.cpp
34
35LOCAL_C_INCLUDES += \
36 system/media/audio_utils/include \
37 system/media/audio_effects/include \
38 device/ti/common-open/audio/utils/include
39
40LOCAL_SHARED_LIBRARIES := \
41 liblog \
42 libtiaudioutils \
43 libcutils \
44 libutils
45
46LOCAL_SHARED_LIBRARIES += libstlport
47include external/stlport/libstlport.mk
48
49LOCAL_STATIC_LIBRARIES := libmedia_helper
50
51LOCAL_MODULE_TAGS := optional
52
53include $(BUILD_SHARED_LIBRARY)
diff --git a/audio/multizone/AudioHw.cpp b/audio/multizone/AudioHw.cpp
new file mode 100644
index 0000000..38d06ed
--- /dev/null
+++ b/audio/multizone/AudioHw.cpp
@@ -0,0 +1,1276 @@
1/*
2 * Copyright (C) 2013 Texas Instruments
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 "AudioHw"
18// #define LOG_NDEBUG 0
19// #define VERY_VERBOSE_LOGGING
20#ifdef VERY_VERBOSE_LOGGING
21#define ALOGVV ALOGV
22#else
23#define ALOGVV(...) do { } while(0)
24#endif
25
26#include <cutils/log.h>
27#include <cutils/properties.h>
28#include <media/AudioParameter.h>
29
30#include <AudioHw.h>
31
32namespace android {
33
34AudioStreamOut::AudioStreamOut(AudioHwDevice *hwDev,
35 PcmWriter *writer,
36 const PcmParams &params,
37 const SlotMap &map,
38 audio_devices_t devices)
39 : mHwDev(hwDev), mNullWriter(&mNullPort, params), mWriter(writer),
40 mParams(params), mDevices(devices), mStandby(true), mUsedForVoiceCall(false)
41{
42 if (mWriter)
43 mStream = new AdaptedOutStream(params, map);
44}
45
46int AudioStreamOut::initCheck() const
47{
48 int ret = 0;
49
50 if (!mHwDev) {
51 ALOGE("AudioStreamOut: initCheck() invalid AudioHwDevice");
52 ret = -ENODEV;
53 }
54 else if (!mWriter || !mWriter->initCheck()) {
55 ALOGE("AudioStreamOut: initCheck() invalid PCM writer");
56 ret = -ENODEV;
57 }
58 else if (mStream == NULL || !mStream->initCheck()) {
59 ALOGE("AudioStreamOut: initCheck() invalid Out Stream");
60 ret = -ENODEV;
61 }
62
63 ALOGV("AudioStreamOut: init check %d", ret);
64
65 return ret;
66}
67
68uint32_t AudioStreamOut::getSampleRate() const
69{
70 uint32_t rate = mParams.sampleRate;
71
72 ALOGVV("AudioStreamOut: getSampleRate() %u Hz", rate);
73
74 return rate;
75}
76
77int AudioStreamOut::setSampleRate(uint32_t rate)
78{
79 ALOGV("AudioStreamOut: setSampleRate() %u Hz", rate);
80
81 return 0;
82}
83
84size_t AudioStreamOut::getBufferSize() const
85{
86 size_t size;
87
88 /* Take resampling ratio into account and align to the nearest
89 * 16 frames as required by the AudioFlinger */
90 size = (mParams.frameCount * mParams.sampleRate) / mWriter->getParams().sampleRate;
91 size = ((size + 15) & ~15) * mParams.frameSize();
92
93 ALOGVV("AudioStreamOut: getBufferSize() %u bytes", size);
94
95 return size;
96}
97
98audio_channel_mask_t AudioStreamOut::getChannels() const
99{
100 uint32_t channels = mParams.channels;
101
102 ALOGVV("AudioStreamOut: getChannels() %u channels", channels);
103
104 return audio_channel_out_mask_from_count(channels);
105}
106
107audio_format_t AudioStreamOut::getFormat() const
108{
109 uint32_t sampleBits = mParams.sampleBits;
110
111 ALOGVV("AudioStreamOut: getFormat() %u bits/sample", sampleBits);
112
113 switch (sampleBits) {
114 case 8:
115 return AUDIO_FORMAT_PCM_8_BIT;
116 case 24:
117 return AUDIO_FORMAT_PCM_8_24_BIT;
118 case 32:
119 return AUDIO_FORMAT_PCM_32_BIT;
120 case 16:
121 default:
122 return AUDIO_FORMAT_PCM_16_BIT;
123 }
124}
125
126int AudioStreamOut::setFormat(audio_format_t format)
127{
128 ALOGV("AudioStreamOut: setFormat() %u bits/sample",
129 audio_bytes_per_sample(format) * 8);
130
131 return 0;
132}
133
134/* must be called with mLock */
135int AudioStreamOut::resume()
136{
137 ALOGV("AudioStreamOut: resume using %s writer",
138 mUsedForVoiceCall ? "null" : "regular");
139
140 /*
141 * Switching PCM writers is done under the assumption that the non-null
142 * writer (mWriter) is always open (but possibly in standby), which is
143 * achieved by using the primary output for voice calls.
144 */
145 PcmWriter *writer;
146 if (mUsedForVoiceCall)
147 writer = &mNullWriter;
148 else
149 writer = mWriter;
150
151 int ret = writer->registerStream(mStream);
152 if (ret) {
153 ALOGE("AudioStreamOut: failed to register stream %d", ret);
154 return ret;
155 }
156
157 ret = mStream->start();
158 if (ret) {
159 ALOGE("AudioStreamOut: failed to start stream %d", ret);
160 writer->unregisterStream(mStream);
161 }
162
163 return ret;
164}
165
166/* must be called with mLock */
167void AudioStreamOut::idle()
168{
169 ALOGV("AudioStreamOut: idle using %s writer",
170 mUsedForVoiceCall ? "null" : "regular");
171
172 PcmWriter *writer;
173 if (mUsedForVoiceCall)
174 writer = &mNullWriter;
175 else
176 writer = mWriter;
177
178 mStream->stop();
179 writer->unregisterStream(mStream);
180}
181
182int AudioStreamOut::standby()
183{
184 ALOGV("AudioStreamOut: standby()");
185
186 AutoMutex lock(mLock);
187
188 if (!mStandby) {
189 idle();
190 mStandby = true;
191 }
192
193 return 0;
194}
195
196void AudioStreamOut::setVoiceCall(bool on)
197{
198 ALOGV("AudioStreamOut: setVoiceCall() %s", on ? "enter" : "leave");
199
200 AutoMutex lock(mLock);
201
202 /*
203 * Voice call reuses one of the PCM writers that is otherwise used
204 * for media. Media has to be re-routed to a null writer (that only
205 * consumes the data but doesn't write it to the hardware) when the
206 * voice call starts and routed back to the actual writer when the
207 * voice call stops.
208 * Temporarily entering standby helps transitioning to the null writer
209 * the next time that data is written to the stream if the voice call
210 * occurs at mid-stream.
211 */
212 if (mUsedForVoiceCall != on) {
213 if (!mStandby) {
214 idle();
215 mStandby = true;
216 }
217 mUsedForVoiceCall = on;
218 }
219}
220
221int AudioStreamOut::dump(int fd) const
222{
223 ALOGV("AudioStreamOut: dump()");
224 return 0;
225}
226
227audio_devices_t AudioStreamOut::getDevice() const
228{
229 ALOGV("AudioStreamOut: getDevice()");
230 return mDevices;
231}
232
233int AudioStreamOut::setParameters(const char *kv_pairs)
234{
235 ALOGV("AudioStreamOut: setParameters() '%s'", kv_pairs ? kv_pairs : "");
236
237 int ret;
238
239 AudioParameter parms = AudioParameter(String8(kv_pairs));
240 String8 key = String8(AudioParameter::keyRouting);
241 int device;
242
243 if ((ret = parms.getInt(key, device)) == NO_ERROR) {
244 if ((mDevices & AUDIO_DEVICE_OUT_ALL) != (unsigned int)device) {
245 standby();
246 }
247 if (device & ~(mHwDev->getSupportedDevices())) {
248 ALOGW("AudioStreamOut: setParameters() device(s) not supported, "
249 "will use default devices");
250 }
251 else
252 mDevices = device;
253 }
254
255 return ret;
256}
257
258char *AudioStreamOut::getParameters(const char *keys) const
259{
260 ALOGV("AudioStreamOut::getParameters()");
261 return NULL;
262}
263
264int AudioStreamOut::addAudioEffect(effect_handle_t effect) const
265{
266 ALOGV("AudioStreamOut: addAudioEffects()");
267 return 0;
268}
269
270int AudioStreamOut::removeAudioEffect(effect_handle_t effect) const
271{
272 ALOGV("AudioStreamOut: removeAudioEffects()");
273 return 0;
274}
275
276uint32_t AudioStreamOut::getLatency() const
277{
278 uint32_t latency = (1000 * getBufferSize()) / mWriter->getParams().sampleRate;
279
280 ALOGVV("AudioStreamOut: getLatency() %u ms", latency);
281
282 return latency;
283}
284
285int AudioStreamOut::setVolume(float left, float right)
286{
287 ALOGV("AudioStreamOut: setVolume() left=%.4f right=%.4f", left, right);
288 return -ENOSYS;
289}
290
291ssize_t AudioStreamOut::write(const void* buffer, size_t bytes)
292{
293 uint32_t frames = mParams.bytesToFrames(bytes);
294 int ret = 0;
295 uint32_t usecs = (frames * 1000000) / mParams.sampleRate;
296
297 ALOGVV("AudioStreamOut: write %u frames (%u bytes) buffer %p",
298 frames, bytes, buffer);
299
300 AutoMutex lock(mLock);
301
302 if (mStandby) {
303 ret = resume();
304 if (ret) {
305 ALOGE("AudioStreamOut: failed to resume stream %d", ret);
306 usleep(usecs); /* limits the rate of error messages */
307 return ret;
308 }
309 mStandby = false;
310 }
311
312 ret = mStream->write(buffer, frames);
313 if (ret < 0) {
314 ALOGE("AudioStreamOut: failed to write data %d", ret);
315 usleep(usecs);
316 } else {
317 ALOGW_IF(ret != (int)frames,
318 "AudioStreamOut: wrote only %d out of %d requested frames",
319 ret, frames);
320 bytes = mParams.framesToBytes(ret);
321 }
322
323 return bytes;
324}
325
326int AudioStreamOut::getRenderPosition(uint32_t *dsp_frames) const
327{
328 ALOGV("AudioStreamOut: getRenderPosition()");
329
330 return -EINVAL;
331}
332
333int AudioStreamOut::getNextWriteTimestamp(int64_t *timestamp) const
334{
335 ALOGVV("AudioStreamOut: getNextWriteTimestamp()");
336
337 return -EINVAL;
338}
339
340/* ---------------------------------------------------------------------------------------- */
341
342AudioStreamIn::AudioStreamIn(AudioHwDevice *hwDev,
343 PcmReader *reader,
344 const PcmParams &params,
345 const SlotMap &map,
346 audio_devices_t devices)
347 : mHwDev(hwDev), mReader(reader), mParams(params), mDevices(devices),
348 mSource(AUDIO_SOURCE_DEFAULT), mStandby(true)
349{
350 if (mReader)
351 mStream = new AdaptedInStream(params, map);
352}
353
354int AudioStreamIn::initCheck() const
355{
356 int ret = 0;
357
358 if (!mHwDev) {
359 ALOGE("AudioStreamIn: initCheck() invalid AudioHwDevice");
360 ret = -ENODEV;
361 }
362 else if (!mReader || !mReader->initCheck()) {
363 ALOGE("AudioStreamIn: initCheck() invalid PCM reader");
364 ret = -ENODEV;
365 }
366 else if (mStream == NULL || !mStream->initCheck()) {
367 ALOGE("AudioStreamIn: initCheck() invalid In Stream");
368 ret = -ENODEV;
369 }
370
371 ALOGV("AudioStreamIn: init check %d", ret);
372
373 return ret;
374}
375
376uint32_t AudioStreamIn::getSampleRate() const
377{
378 ALOGV("AudioStreamIn: getSampleRate()");
379
380 uint32_t rate = mParams.sampleRate;
381
382 return rate;
383}
384
385int AudioStreamIn::setSampleRate(uint32_t rate)
386{
387 ALOGV("AudioStreamIn: setSampleRate() %u Hz", rate);
388
389 return 0;
390}
391
392size_t AudioStreamIn::getBufferSize() const
393{
394 size_t size;
395
396 /* Take resampling ratio into account */
397 size = (mParams.frameCount * mParams.sampleRate) / mReader->getParams().sampleRate;
398 size = size * mParams.frameSize();
399
400 ALOGVV("AudioStreamIn: getBufferSize() %u bytes", size);
401
402 return size;
403}
404
405audio_channel_mask_t AudioStreamIn::getChannels() const
406{
407 ALOGV("AudioStreamIn: getChannels()");
408
409 return audio_channel_in_mask_from_count(mParams.channels);
410}
411
412audio_format_t AudioStreamIn::getFormat() const
413{
414 ALOGV("AudioStreamIn: getFormat()");
415
416 return AUDIO_FORMAT_PCM_16_BIT;
417}
418
419int AudioStreamIn::setFormat(audio_format_t format)
420{
421 ALOGV("AudioStreamIn: setFormat()");
422
423 return 0;
424}
425
426/* must be called with mLock */
427int AudioStreamIn::resume()
428{
429 int ret = mReader->registerStream(mStream);
430 if (ret) {
431 ALOGE("AudioStreamIn: failed to register Dest %d", ret);
432 return ret;
433 }
434
435 ret = mStream->start();
436 if (ret) {
437 ALOGE("AudioStreamIn: failed to start stream %d", ret);
438 mReader->unregisterStream(mStream);
439 }
440
441 return ret;
442}
443
444/* must be called with mLock */
445void AudioStreamIn::idle()
446{
447 mStream->stop();
448 mReader->unregisterStream(mStream);
449}
450
451int AudioStreamIn::standby()
452{
453 ALOGV("AudioStreamIn: standby()");
454
455 AutoMutex lock(mLock);
456
457 if (!mStandby) {
458 idle();
459 mStandby = true;
460 }
461
462 return 0;
463}
464
465int AudioStreamIn::dump(int fd) const
466{
467 ALOGV("AudioStreamIn: dump()");
468
469 return 0;
470}
471
472audio_devices_t AudioStreamIn::getDevice() const
473{
474 ALOGV("AudioStreamIn: getDevice()");
475
476 return mDevices;
477}
478
479int AudioStreamIn::setParameters(const char *kv_pairs)
480{
481 ALOGV("AudioStreamIn: setParameters() '%s'", kv_pairs ? kv_pairs : "");
482
483 int ret;
484
485 AudioParameter parms = AudioParameter(String8(kv_pairs));
486 String8 source_key = String8(AudioParameter::keyInputSource);
487 String8 device_key = String8(AudioParameter::keyRouting);
488 int source, device;
489
490 if ((ret = parms.getInt(source_key, source)) == NO_ERROR) {
491 /* no audio source uses 0 */
492 if ((mSource != (unsigned int)source) &&
493 (source != 0) &&
494 (source < AUDIO_SOURCE_CNT)) {
495 ALOGV("AudioStreamIn: setParameters() source changed [%d]->[%d]",
496 mSource, source);
497 mSource = (audio_source_t)source;
498 /* Nothing to do for AUDIO_PARAMETER_STREAM_INPUT_SOURCE, so only
499 * record the source and continue */
500 }
501 }
502
503 if ((ret = parms.getInt(device_key, device)) == NO_ERROR) {
504 if ((mDevices & AUDIO_DEVICE_IN_ALL) != (unsigned int)device) {
505 standby();
506 }
507 if (device & ~(mHwDev->getSupportedDevices())) {
508 ALOGW("AudioStreamIn: setParameters() device(s) not supported, "
509 "will use default devices");
510 }
511 else {
512 mDevices = device;
513 ALOGV("AudioStreamIn: setParameters() device set to [0x%x]",
514 mDevices);
515 }
516 }
517
518 return 0;
519}
520
521char *AudioStreamIn::getParameters(const char *keys) const
522{
523 ALOGV("AudioStreamIn: getParameters()");
524
525 return NULL;
526}
527
528int AudioStreamIn::addAudioEffect(effect_handle_t effect) const
529{
530 ALOGV("AudioStreamIn: addAudioEffect()");
531
532 return 0;
533}
534
535int AudioStreamIn::removeAudioEffect(effect_handle_t effect) const
536{
537 ALOGV("AudioStreamIn: removeAudioEffect()");
538
539 return 0;
540}
541
542int AudioStreamIn::setGain(float gain)
543{
544 ALOGV("AudioStreamIn: setGain()");
545
546 return 0;
547}
548
549ssize_t AudioStreamIn::read(void* buffer, size_t bytes)
550{
551 uint32_t frames = mParams.bytesToFrames(bytes);
552 int ret = 0;
553 uint32_t usecs = (frames * 1000000) / mParams.sampleRate;
554
555 ALOGVV("AudioStreamIn: read %u frames (%u bytes) buffer %p",
556 frames, bytes, buffer);
557
558 AutoMutex lock(mLock);
559
560 if (mStandby) {
561 ret = resume();
562 if (ret) {
563 ALOGE("AudioStreamIn: failed to resume stream %d", ret);
564 usleep(usecs); /* limits the rate of error messages */
565 return ret;
566 }
567 mStandby = false;
568 }
569
570 ret = mStream->read(buffer, frames);
571 if (ret < 0) {
572 ALOGE("AudioStreamIn: failed to read data %d", ret);
573 usleep(usecs);
574 bytes = ret;
575 } else {
576 ALOGW_IF(ret != (int)frames,
577 "AudioStreamIn: read only %d out of %d requested frames",
578 ret, frames);
579 bytes = mParams.framesToBytes(ret);
580 if (mHwDev->mMicMute)
581 memset(buffer, 0, bytes);
582 }
583
584 return bytes;
585}
586
587uint32_t AudioStreamIn::getInputFramesLost()
588{
589 ALOGVV("AudioStreamIn: getInputFrameLost()");
590
591 return 0;
592}
593
594/* ---------------------------------------------------------------------------------------- */
595
596const char *AudioHwDevice::kCabinVolumeHP = "HP DAC Playback Volume";
597const char *AudioHwDevice::kCabinVolumeLine = "Line DAC Playback Volume";
598const char *AudioHwDevice::kBTMode = "Bluetooth Mode";
599
600AudioHwDevice::AudioHwDevice(uint32_t card)
601 : mCardId(card), mMixer(mCardId), mMicMute(false), mMode(AUDIO_MODE_NORMAL)
602{
603 /*
604 * "multizone_audio.use_jamr" property is used to indicate if JAMR3
605 * board is available in the system:
606 * - Present
607 * o Cabin : port 1, slots 0 & 1
608 * o Mic : port 1, slot 2
609 * o Back Mic: port 1, slot 3
610 * - Not present
611 * o Cabin : port 0, slots 0 & 1
612 * o Mic : port 0, slots 0 & 1
613 */
614 char value[PROPERTY_VALUE_MAX];
615 if ((property_get("persist.audio.use_jamr", value, NULL) == 0) ||
616 !strcmp(value, "1") || !strcasecmp(value, "true")) {
617 mMediaPortId = kJAMR3PortId;
618 } else {
619 mMediaPortId = kCPUPortId;
620 }
621
622 ALOGI("AudioHwDevice: create hw device for card hw:%u Jacinto6 EVM %s",
623 card, usesJAMR3() ? "+ JAMR3" : "");
624
625 /* Mixer for dra7evm and input/output ports for JAMR3 PCM device */
626 for (uint32_t i = 0; i < kNumPorts; i++) {
627 ALSAInPort *inPort = new ALSAInPort(mCardId, i);
628 mInPorts.push_back(inPort);
629
630 ALSAOutPort *outPort = new ALSAOutPort(mCardId, i);
631 mOutPorts.push_back(outPort);
632 }
633
634 /* PCM parameters for the port associated with on-board audio:
635 * 2 channels, 16-bits/sample, 44.1kHz, buffer of 882 frames (capture) */
636 PcmParams params0(kCPUNumChannels, kSampleSize, kSampleRate, kCaptureFrameCount);
637 PcmReader *reader = new PcmReader(mInPorts[kCPUPortId], params0);
638 mReaders.push_back(reader);
639 /* 2 channels, 16-bits/sample, 44.1kHz, buffer of 1024 frames (playback) */
640 params0.frameCount = kPlaybackFrameCount;
641 PcmWriter *writer = new PcmWriter(mOutPorts[kCPUPortId], params0);
642 mWriters.push_back(writer);
643
644 /* PCM parameters for the port associated with JAMR3 audio:
645 * 8 channels, 16-bits/sample, 44.1kHz, buffer of 882 frames (capture) */
646 PcmParams params1(kJAMR3NumChannels, kSampleSize, kSampleRate, kCaptureFrameCount);
647 reader = new PcmReader(mInPorts[kJAMR3PortId], params1);
648 mReaders.push_back(reader);
649 /* 8 channels, 16-bits/sample, 44.1kHz, buffer of 1024 frames (playback) */
650 params1.frameCount = kPlaybackFrameCount;
651 writer = new PcmWriter(mOutPorts[kJAMR3PortId], params1);
652 mWriters.push_back(writer);
653
654 /* Voice call */
655 PcmParams paramsBT(kBTNumChannels, kSampleSize, kBTSampleRate, kBTFrameCount);
656 writer = new PcmWriter(mOutPorts[kBTPortId], paramsBT);
657 mWriters.push_back(writer);
658 reader = new PcmReader(mInPorts[kBTPortId], paramsBT);
659 mReaders.push_back(reader);
660
661 /* BT is configured as stereo but only the left channel carries data */
662 SlotMap slots;
663 slots[0] = 0;
664 slots[1] = 0;
665
666 /* Microphone slots are different in JAMR3 and CPU board */
667 SlotMap micSlots;
668 if (usesJAMR3()) {
669 micSlots[0] = 2;
670 micSlots[1] = 2;
671 } else {
672 micSlots[0] = 0;
673 micSlots[1] = 0;
674 }
675
676 /* Voice call uplink */
677 mULPipe = new tiaudioutils::MonoPipe(paramsBT,
678 (kVoiceCallPipeMs * paramsBT.sampleRate) / 1000);
679 mULPipeWriter = new PipeWriter(mULPipe);
680 mULPipeReader = new PipeReader(mULPipe);
681 mVoiceULInStream = new InStream(paramsBT, micSlots, mULPipeWriter);
682 mVoiceULOutStream = new OutStream(paramsBT, slots, mULPipeReader);
683
684 /* Voice call downlink */
685 mDLPipe = new tiaudioutils::MonoPipe(paramsBT,
686 (kVoiceCallPipeMs * params0.sampleRate) / 1000);
687 mDLPipeWriter = new PipeWriter(mDLPipe);
688 mDLPipeReader = new PipeReader(mDLPipe);
689 mVoiceDLInStream = new InStream(paramsBT, slots, mDLPipeWriter);
690 mVoiceDLOutStream = new OutStream(paramsBT, slots, mDLPipeReader);
691
692 mMixer.initRoutes();
693}
694
695AudioHwDevice::~AudioHwDevice()
696{
697 ALOGI("AudioHwDevice: destroy hw device for card hw:%u", mCardId);
698
699 if (mDLPipeWriter)
700 delete mDLPipeWriter;
701
702 if (mDLPipeReader)
703 delete mDLPipeReader;
704
705 if (mDLPipe)
706 delete mDLPipe;
707
708 if (mULPipeWriter)
709 delete mULPipeWriter;
710
711 if (mULPipeReader)
712 delete mULPipeReader;
713
714 if (mULPipe)
715 delete mULPipe;
716
717 for (WriterVect::const_iterator i = mWriters.begin(); i != mWriters.end(); ++i) {
718 delete (*i);
719 }
720 for (ReaderVect::const_iterator i = mReaders.begin(); i != mReaders.end(); ++i) {
721 delete (*i);
722 }
723 for (OutPortVect::iterator i = mOutPorts.begin(); i != mOutPorts.end(); ++i) {
724 delete (*i);
725 }
726 for (InPortVect::iterator i = mInPorts.begin(); i != mInPorts.end(); ++i) {
727 delete (*i);
728 }
729}
730
731uint32_t AudioHwDevice::getSupportedDevices() const
732{
733 uint32_t devices;
734
735 devices = AUDIO_DEVICE_IN_BUILTIN_MIC |
736 AUDIO_DEVICE_IN_BACK_MIC |
737 AUDIO_DEVICE_IN_VOICE_CALL |
738 AUDIO_DEVICE_IN_ANLG_DOCK_HEADSET |
739 AUDIO_DEVICE_OUT_SPEAKER |
740 AUDIO_DEVICE_OUT_WIRED_HEADPHONE |
741 AUDIO_DEVICE_OUT_WIRED_HEADSET |
742 AUDIO_DEVICE_OUT_WIRED_HEADPHONE2;
743 ALOGV("AudioHwDevice: supported devices 0x%08x", devices);
744
745 return devices;
746}
747
748int AudioHwDevice::initCheck() const
749{
750 if (!mMixer.initCheck()) {
751 ALOGE("AudioHwDevice: ALSA mixer init failed");
752 return -ENODEV;
753 }
754
755 for (ReaderVect::const_iterator i = mReaders.begin(); i != mReaders.end(); ++i) {
756 if (!((*i)->initCheck())) {
757 ALOGE("AudioHwDevice: PCM reader initCheck failed");
758 return -ENODEV;
759 }
760 }
761 for (WriterVect::const_iterator i = mWriters.begin(); i != mWriters.end(); ++i) {
762 if (!((*i)->initCheck())) {
763 ALOGE("AudioHwDevice: PCM writer init failed");
764 return -ENODEV;
765 }
766 }
767
768 if ((mULPipe == NULL) || !mULPipe->initCheck() ||
769 (mULPipeReader == NULL) || !mULPipeReader->initCheck() ||
770 (mULPipeWriter == NULL) || !mULPipeWriter->initCheck()) {
771 ALOGE("AudioHwDevice: voice call uplink init check failed");
772 return -ENODEV;
773 }
774
775 if ((mDLPipe == NULL) || !mDLPipe->initCheck() ||
776 (mDLPipeReader == NULL) || !mDLPipeReader->initCheck() ||
777 (mDLPipeWriter == NULL) || !mDLPipeWriter->initCheck()) {
778 ALOGE("AudioHwDevice: voice call downlink init check failed");
779 return -ENODEV;
780 }
781
782 if ((mVoiceULInStream == NULL) || !mVoiceULInStream->initCheck() ||
783 (mVoiceULOutStream == NULL) || !mVoiceULOutStream->initCheck()) {
784 ALOGE("AudioHwDevice: voice call uplink streams init check failed");
785 return -ENODEV;
786 }
787
788 if ((mVoiceDLInStream == NULL) || !mVoiceDLInStream->initCheck() ||
789 (mVoiceDLOutStream == NULL) || !mVoiceDLOutStream->initCheck()) {
790 ALOGE("AudioHwDevice: voice call downlink streams init check failed");
791 return -ENODEV;
792 }
793
794 return 0;
795}
796
797int AudioHwDevice::setVoiceVolume(float volume)
798{
799 /* Linear interpolation between voice dB limits */
800 float dB = (kVoiceDBMax - kVoiceDBMin) * volume + kVoiceDBMin;
801
802 /* Output stage gain (-59.0dB, 0dB) with steps of 0.5dB */
803 int val = 2 * (dB + 59.0f);
804
805 ALOGV("AudioHwDevice: setVoiceVolume() vol=%.4f dB=%.4f", volume, dB, val);
806
807 mMixer.set(ALSAControl(kCabinVolumeHP, val), true);
808 mMixer.set(ALSAControl(kCabinVolumeLine, val), true);
809
810 return 0;
811}
812
813int AudioHwDevice::setMasterVolume(float volume)
814{
815 ALOGV("AudioHwDevice: setMasterVolume() vol=%.4f", volume);
816 return -ENOSYS;
817}
818
819const char *AudioHwDevice::getModeName(audio_mode_t mode) const
820{
821 switch (mode) {
822 case AUDIO_MODE_CURRENT:
823 return "CURRENT";
824 case AUDIO_MODE_NORMAL:
825 return "NORMAL";
826 case AUDIO_MODE_RINGTONE:
827 return "RINGTONE";
828 case AUDIO_MODE_IN_CALL:
829 return "IN_CALL";
830 case AUDIO_MODE_IN_COMMUNICATION:
831 return "COMMUNICATION";
832 default:
833 return "INVALID";
834 }
835}
836
837int AudioHwDevice::setMode(audio_mode_t mode)
838{
839 ALOGV("AudioHwDevice: setMode() %s", getModeName(mode));
840
841 AutoMutex lock(mLock);
842 if (mMode == mode) {
843 ALOGW("AudioHwDevice: already in mode %s", getModeName(mode));
844 return 0;
845 }
846
847 int ret = 0;
848 if (mode == AUDIO_MODE_IN_CALL) {
849 ret = enterVoiceCall();
850 ALOGE_IF(ret, "AudioHwDevice: failed to enter voice call %d", ret);
851 } else {
852 leaveVoiceCall();
853 }
854
855 if (!ret)
856 mMode = mode;
857
858 return ret;
859}
860
861int AudioHwDevice::enableVoiceCall()
862{
863 ALOGV("AudioHwDevice: enable voice call paths");
864
865 sp<AudioStreamOut> outStream = mPrimaryStreamOut.promote();
866 if (outStream == NULL) {
867 ALOGE("AudioHwDevice: primary output stream is not valid");
868 return -ENODEV;
869 }
870
871 /* Playback stream will free the writer and switch to a null writer */
872 outStream->setVoiceCall(true);
873
874 /* Uplink input stream: Mic -> Pipe */
875 int ret = mReaders[mMediaPortId]->registerStream(mVoiceULInStream);
876 if (ret) {
877 ALOGE("AudioHwDevice: failed to register uplink in stream %d", ret);
878 return ret;
879 }
880
881 /* Uplink output stream: Pipe -> Bluetooth */
882 ret = mWriters[kBTPortId]->registerStream(mVoiceULOutStream);
883 if (ret) {
884 ALOGE("AudioHwDevice: failed to register uplink out stream %d", ret);
885 return ret;
886 }
887
888 /* Downlink input stream: Bluetooth -> Pipe */
889 ret = mReaders[kBTPortId]->registerStream(mVoiceDLInStream);
890 if (ret) {
891 ALOGE("AudioHwDevice: failed to register downlink in stream %d", ret);
892 return ret;
893 }
894
895 /* Downlink output stream: Pipe -> Speaker */
896 ret = outStream->mWriter->registerStream(mVoiceDLOutStream);
897 if (ret) {
898 ALOGE("AudioHwDevice: failed to register downlink out stream %d", ret);
899 }
900
901 return ret;
902}
903
904void AudioHwDevice::disableVoiceCall()
905{
906 ALOGV("AudioHwDevice: disable voice call paths");
907
908 sp<AudioStreamOut> outStream = mPrimaryStreamOut.promote();
909 if (outStream != NULL) {
910 if (outStream->mWriter->isStreamRegistered(mVoiceDLOutStream))
911 outStream->mWriter->unregisterStream(mVoiceDLOutStream);
912 outStream->setVoiceCall(false);
913 } else {
914 ALOGE("AudioHwDevice: primary output stream is not valid");
915 }
916
917 if (mReaders[kBTPortId]->isStreamRegistered(mVoiceDLInStream))
918 mReaders[kBTPortId]->unregisterStream(mVoiceDLInStream);
919
920 if (mWriters[kBTPortId]->isStreamRegistered(mVoiceULOutStream))
921 mWriters[kBTPortId]->unregisterStream(mVoiceULOutStream);
922
923 if (mReaders[mMediaPortId]->isStreamRegistered(mVoiceULInStream))
924 mReaders[mMediaPortId]->unregisterStream(mVoiceULInStream);
925}
926
927int AudioHwDevice::enterVoiceCall()
928{
929 ALOGI("AudioHwDevice: enter voice call");
930
931 /* Setup uplink and downlink pipes */
932 int ret = enableVoiceCall();
933 if (ret) {
934 ALOGE("AudioHwDevice: failed to enable voice call path %d", ret);
935 return ret;
936 }
937
938 /* Bluetooth is master, provides BCLK and FSYNC */
939 mMixer.set(ALSAControl(kBTMode, "Master"), true);
940
941 mULPipe->shutdown(false);
942 mDLPipe->shutdown(false);
943
944 /* Uplink input stream: Mic -> Pipe */
945 ret = mVoiceULInStream->start();
946 if (ret) {
947 ALOGE("AudioHwDevice: failed to start uplink in stream %d", ret);
948 return ret;
949 }
950
951 /* Downlink input stream: Bluetooth -> Pipe */
952 ret = mVoiceDLInStream->start();
953 if (ret) {
954 ALOGE("AudioHwDevice: failed to start downlink in stream %d", ret);
955 return ret;
956 }
957
958 /*
959 * Wait till pipe is half full to give a head start to the output streams.
960 * The time to wait consists of the actual pipe size, the ADC settle time
961 * used in the kernel and the time needed to produce a BT audio buffer.
962 * Only the pipe size related time contributes to the steady state latency.
963 */
964 usleep((kVoiceCallPipeMs * 5000) + (kADCSettleMs * 1000) +
965 (kBTFrameCount * 1000) / kBTSampleRate);
966
967 /* Downlink output stream: Pipe -> Speaker */
968 ret = mVoiceDLOutStream->start();
969 if (ret) {
970 ALOGE("AudioHwDevice: failed to start downlink out stream %d", ret);
971 }
972
973 /* Uplink output stream: Pipe -> Bluetooth */
974 ret = mVoiceULOutStream->start();
975 if (ret) {
976 ALOGE("AudioHwDevice: failed to start uplink out stream %d", ret);
977 return ret;
978 }
979
980 return ret;
981}
982
983void AudioHwDevice::leaveVoiceCall()
984{
985 ALOGI("AudioHwDevice: leave voice call");
986
987 /*
988 * The PCM ports used for Bluetooth are slaves and they can lose the
989 * BCLK and FSYNC while still active. That leads to blocking read() and
990 * write() calls, which is prevented by switching the clock source to
991 * an internal one and explicitly stopping both ports for the new source
992 * to take effect at kernel level
993 */
994 mMixer.set(ALSAControl(kBTMode, "Slave"), true);
995
996 mULPipe->shutdown(true);
997 mDLPipe->shutdown(true);
998
999 /* Uplink input stream: Mic -> Pipe */
1000 if (mVoiceULInStream->isStarted())
1001 mVoiceULInStream->stop();
1002
1003 /* Downlink input stream: Bluetooth -> Pipe */
1004 mInPorts[kBTPortId]->stop();
1005 if (mVoiceDLInStream->isStarted())
1006 mVoiceDLInStream->stop();
1007
1008 /* Downlink output stream: Pipe -> Speaker */
1009 if (mVoiceDLOutStream->isStarted())
1010 mVoiceDLOutStream->stop();
1011
1012 /* Uplink output stream: Pipe -> Bluetooth */
1013 mOutPorts[kBTPortId]->stop();
1014 if (mVoiceULOutStream->isStarted())
1015 mVoiceULOutStream->stop();
1016
1017 mULPipe->flush();
1018 mDLPipe->flush();
1019
1020 disableVoiceCall();
1021
1022 /* Reset the cabin volume for media */
1023 setVoiceVolume(1.0f);
1024}
1025
1026int AudioHwDevice::setMicMute(bool state)
1027{
1028 ALOGV("AudioHwDevice: setMicMute() %s", state ? "mute" : "unmute");
1029
1030 mMicMute = state;
1031
1032 return 0;
1033}
1034
1035int AudioHwDevice::getMicMute(bool *state) const
1036{
1037 ALOGV("AudioHwDevice: getMicMute()");
1038
1039 *state = mMicMute;
1040
1041 return 0;
1042}
1043
1044int AudioHwDevice::setParameters(const char *kv_pairs)
1045{
1046 ALOGV("AudioHwDevice: setParameters() '%s'", kv_pairs ? kv_pairs : "");
1047
1048 return 0;
1049}
1050
1051char *AudioHwDevice::getParameters(const char *keys) const
1052{
1053 ALOGV("AudioHwDevice: getParameters()");
1054
1055 return NULL;
1056}
1057
1058size_t AudioHwDevice::getInputBufferSize(const struct audio_config *config) const
1059{
1060 ALOGV("AudioHwDevice: getInputBufferSize()");
1061
1062 AutoMutex lock(mLock);
1063 size_t size;
1064
1065 /* Take resampling ratio into account */
1066 /* Use port 0 for the calculation, since values for both ports are the same */
1067 uint32_t frames = mReaders[kCPUPortId]->getParams().frameCount;
1068 uint32_t rate = mReaders[kCPUPortId]->getParams().sampleRate;
1069
1070 size = (frames * config->sample_rate) / rate;
1071 size = size * mReaders[kCPUPortId]->getParams().frameSize();
1072
1073 ALOGV("AudioHwDevice: getInputBufferSize() %d bytes", size);
1074
1075 return size;
1076}
1077
1078int AudioHwDevice::dump(int fd) const
1079{
1080 ALOGV("AudioHwDevice: dump()");
1081
1082 return 0;
1083}
1084
1085int AudioHwDevice::setMasterMute(bool mute)
1086{
1087 ALOGV("AudioHwDevice: setMasterMute() %s", mute ? "mute" : "unmute");
1088 return -ENOSYS;
1089}
1090
1091AudioStreamIn* AudioHwDevice::openInputStream(audio_io_handle_t handle,
1092 audio_devices_t devices,
1093 struct audio_config *config)
1094{
1095 uint32_t port = mMediaPortId;
1096 uint32_t srcSlot0, srcSlot1;
1097 uint32_t channels = popcount(config->channel_mask);
1098
1099 ALOGV("AudioHwDevice: openInputStream()");
1100
1101 switch (devices) {
1102 case AUDIO_DEVICE_IN_BUILTIN_MIC:
1103 case AUDIO_DEVICE_IN_VOICE_CALL:
1104 if (usesJAMR3()) {
1105 srcSlot0 = 2;
1106 srcSlot1 = 2;
1107 } else {
1108 srcSlot0 = 0;
1109 srcSlot1 = 1;
1110 }
1111 break;
1112 case AUDIO_DEVICE_IN_BACK_MIC:
1113 if (usesJAMR3()) {
1114 srcSlot0 = 3;
1115 srcSlot1 = 3;
1116 } else {
1117 srcSlot0 = 0;
1118 srcSlot1 = 1;
1119 }
1120 break;
1121 case AUDIO_DEVICE_IN_ANLG_DOCK_HEADSET:
1122 if (!usesJAMR3()) {
1123 ALOGE("AudioHwDevice: device 0x%08x requires JAMR3", devices);
1124 return NULL;
1125 }
1126 srcSlot0 = 0;
1127 srcSlot1 = 1;
1128 break;
1129 default:
1130 ALOGE("AudioHwDevice: device 0x%08x is not supported", devices);
1131 return NULL;
1132 }
1133
1134 SlotMap slotMap;
1135 if (channels >= 1)
1136 slotMap[0] = srcSlot0;
1137 if (channels == 2)
1138 slotMap[1] = srcSlot1;
1139 if (channels > 2) {
1140 ALOGE("AudioHwDevice: %u channels are not supported", channels);
1141 return NULL;
1142 }
1143
1144 if (!slotMap.isValid()) {
1145 ALOGE("AudioHwDevice: failed to create slot map");
1146 return NULL;
1147 }
1148
1149 AutoMutex lock(mLock);
1150
1151 /* Set the parameters for the internal input stream. Don't change the
1152 * parameters for capture. The resampler is used if needed. */
1153 PcmParams params(*config, mReaders[port]->getParams().frameCount);
1154
1155 sp<AudioStreamIn> in = new AudioStreamIn(this, mReaders[port], params,
1156 slotMap, devices);
1157 if ((in == NULL) || in->initCheck()) {
1158 ALOGE("AudioHwDevice: failed to open input stream on port hw:%u,%u",
1159 mCardId, port);
1160 return NULL;
1161 }
1162
1163 mInStreams.insert(in);
1164
1165 return in.get();
1166}
1167
1168void AudioHwDevice::closeInputStream(AudioStreamIn *in)
1169{
1170 ALOGV("AudioHwDevice: closeInputStream()");
1171
1172 AutoMutex lock(mLock);
1173
1174 if (mInStreams.find(in) == mInStreams.end()) {
1175 ALOGW("AudioHwDevice: input stream %p is not open", in);
1176 return;
1177 }
1178
1179 mInStreams.erase(in);
1180
1181 in = NULL;
1182}
1183
1184AudioStreamOut* AudioHwDevice::openOutputStream(audio_io_handle_t handle,
1185 audio_devices_t devices,
1186 audio_output_flags_t flags,
1187 struct audio_config *config)
1188{
1189 uint32_t port = 0;
1190 PcmParams params;
1191
1192 ALOGV("AudioHwDevice: openOutputStream()");
1193
1194 uint32_t destMask;
1195 switch (devices) {
1196 case AUDIO_DEVICE_OUT_SPEAKER:
1197 port = mMediaPortId;
1198 destMask = 0x03;
1199 break;
1200 case AUDIO_DEVICE_OUT_WIRED_HEADPHONE:
1201 case AUDIO_DEVICE_OUT_WIRED_HEADSET:
1202 port = kJAMR3PortId;
1203 destMask = 0x0c;
1204 break;
1205 case AUDIO_DEVICE_OUT_WIRED_HEADPHONE2:
1206 port = kJAMR3PortId;
1207 destMask = 0x30;
1208 break;
1209 default:
1210 ALOGE("AudioHwDevice: device 0x%08x is not supported", devices);
1211 return NULL;
1212 }
1213
1214 SlotMap slotMap(0x03, destMask);
1215 if (!slotMap.isValid()) {
1216 ALOGE("AudioHwDevice: failed to create slot map");
1217 return NULL;
1218 }
1219
1220 AutoMutex lock(mLock);
1221
1222 /* Set the parameters for the internal output stream */
1223 params.frameCount = mWriters[port]->getParams().frameCount;
1224 params.sampleRate = config->sample_rate; /* Use stream's resampler if needed */
1225 params.sampleBits = 16; /* 16-bits/sample */
1226 params.channels = 2; /* Listening zones are stereo */
1227
1228 /* Update audio config with granted parameters */
1229 if (popcount(config->channel_mask) != (int)params.channels) {
1230 ALOGV("AudioHwDevice: updating audio config channel mask [0x%x]->[0x%x]",
1231 config->channel_mask,
1232 audio_channel_out_mask_from_count(params.channels));
1233 }
1234 config->channel_mask = audio_channel_out_mask_from_count(params.channels);
1235 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
1236 ALOGV("AudioHwDevice: updating audio config format [0x%x]->[0x%x]",
1237 config->format, AUDIO_FORMAT_PCM_16_BIT);
1238 }
1239 config->format = AUDIO_FORMAT_PCM_16_BIT;
1240
1241 sp<AudioStreamOut> out = new AudioStreamOut(this, mWriters[port], params,
1242 slotMap, devices);
1243 if ((out == NULL) || out->initCheck()) {
1244 ALOGE("AudioHwDevice: failed to open output stream on port hw:%u,%u",
1245 mCardId, port);
1246 return NULL;
1247 }
1248
1249 if (flags & AUDIO_OUTPUT_FLAG_PRIMARY)
1250 mPrimaryStreamOut = out;
1251
1252 mOutStreams.insert(out);
1253
1254 return out.get();
1255}
1256
1257void AudioHwDevice::closeOutputStream(AudioStreamOut *out)
1258{
1259 ALOGV("AudioHwDevice: closeOutputStream()");
1260
1261 AutoMutex lock(mLock);
1262
1263 if (mOutStreams.find(out) == mOutStreams.end()) {
1264 ALOGW("AudioHwDevice: output stream %p is not open", out);
1265 return;
1266 }
1267
1268 if (mPrimaryStreamOut == out)
1269 mPrimaryStreamOut = NULL;
1270
1271 mOutStreams.erase(out);
1272
1273 out = NULL;
1274}
1275
1276}; /* namespace android */
diff --git a/audio/multizone/AudioHw.h b/audio/multizone/AudioHw.h
new file mode 100644
index 0000000..0d475da
--- /dev/null
+++ b/audio/multizone/AudioHw.h
@@ -0,0 +1,251 @@
1/*
2 * Copyright (C) 2013 Texas Instruments
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#ifndef _AUDIO_HW_H_
18#define _AUDIO_HW_H_
19
20#include <vector>
21
22#include <system/audio.h>
23#include <hardware/audio_effect.h>
24
25#include <tiaudioutils/Pcm.h>
26#include <tiaudioutils/NullPcm.h>
27#include <tiaudioutils/ALSAPcm.h>
28#include <tiaudioutils/ALSAMixer.h>
29#include <tiaudioutils/MumStream.h>
30#include <tiaudioutils/Stream.h>
31#include <tiaudioutils/Base.h>
32
33namespace android {
34
35using namespace tiaudioutils;
36using std::vector;
37
38class AudioHwDevice;
39
40class AudioStream {
41 public:
42 virtual ~AudioStream() {}
43 virtual uint32_t getSampleRate() const = 0;
44 virtual int setSampleRate(uint32_t rate) = 0;
45 virtual size_t getBufferSize() const = 0;
46 virtual audio_channel_mask_t getChannels() const = 0;
47 virtual audio_format_t getFormat() const = 0;
48 virtual int setFormat(audio_format_t format) = 0;
49 virtual int standby() = 0;
50 virtual int dump(int fd) const = 0;
51 virtual audio_devices_t getDevice() const = 0;
52 virtual int setDevice(audio_devices_t device) { return 0; } /* unused */
53 virtual int setParameters(const char *kv_pairs) = 0;
54 virtual char *getParameters(const char *keys) const = 0;
55 virtual int addAudioEffect(effect_handle_t effect) const = 0;
56 virtual int removeAudioEffect(effect_handle_t effect) const = 0;
57};
58
59class AudioStreamOut : public RefBase, public AudioStream {
60 public:
61 AudioStreamOut(AudioHwDevice *hwDev,
62 PcmWriter *writer,
63 const PcmParams &params,
64 const SlotMap &map,
65 audio_devices_t devices);
66 virtual ~AudioStreamOut() {};
67 int initCheck() const;
68
69 /* From AudioStream */
70 virtual uint32_t getSampleRate() const;
71 virtual int setSampleRate(uint32_t rate);
72 virtual size_t getBufferSize() const;
73 virtual audio_channel_mask_t getChannels() const;
74 virtual audio_format_t getFormat() const;
75 virtual int setFormat(audio_format_t format);
76 virtual int standby();
77 virtual int dump(int fd) const;
78 virtual audio_devices_t getDevice() const;
79 virtual int setParameters(const char *kv_pairs);
80 virtual char *getParameters(const char *keys) const;
81 virtual int addAudioEffect(effect_handle_t effect) const;
82 virtual int removeAudioEffect(effect_handle_t effect) const;
83
84 /* AudioStreamOut specific */
85 uint32_t getLatency() const;
86 int setVolume(float left, float right);
87 ssize_t write(const void* buffer, size_t bytes);
88 int getRenderPosition(uint32_t *dsp_frames) const;
89 int getNextWriteTimestamp(int64_t *timestamp) const;
90
91 void setVoiceCall(bool on);
92
93 friend AudioHwDevice;
94
95 protected:
96 int resume();
97 void idle();
98
99 AudioHwDevice *mHwDev;
100 NullOutPort mNullPort;
101 PcmWriter mNullWriter;
102 PcmWriter *mWriter;
103 PcmParams mParams;
104 audio_devices_t mDevices;
105 sp<OutStream> mStream;
106 bool mStandby;
107 bool mUsedForVoiceCall;
108 Mutex mLock;
109};
110
111class AudioStreamIn : public RefBase, public AudioStream {
112 public:
113 AudioStreamIn(AudioHwDevice *hwDev,
114 PcmReader *reader,
115 const PcmParams &params,
116 const SlotMap &map,
117 audio_devices_t devices);
118 virtual ~AudioStreamIn() {};
119 int initCheck() const;
120
121 /* From AudioStream */
122 virtual uint32_t getSampleRate() const;
123 virtual int setSampleRate(uint32_t rate);
124 virtual size_t getBufferSize() const;
125 virtual audio_channel_mask_t getChannels() const;
126 virtual audio_format_t getFormat() const;
127 virtual int setFormat(audio_format_t format);
128 virtual int standby();
129 virtual int dump(int fd) const;
130 virtual audio_devices_t getDevice() const;
131 virtual int setParameters(const char *kv_pairs);
132 virtual char *getParameters(const char *keys) const;
133 virtual int addAudioEffect(effect_handle_t effect) const;
134 virtual int removeAudioEffect(effect_handle_t effect) const;
135
136 /* AudioStreamIn specific */
137 int setGain(float gain);
138 ssize_t read(void* buffer, size_t bytes);
139 uint32_t getInputFramesLost();
140
141 protected:
142 int resume();
143 void idle();
144
145 AudioHwDevice *mHwDev;
146 PcmReader *mReader;
147 PcmParams mParams;
148 audio_devices_t mDevices;
149 audio_source_t mSource;
150 sp<InStream> mStream;
151 bool mStandby;
152 Mutex mLock;
153};
154
155class AudioHwDevice {
156 public:
157 AudioHwDevice(uint32_t card);
158 virtual ~AudioHwDevice();
159
160 uint32_t getSupportedDevices() const;
161 int initCheck() const;
162 int setVoiceVolume(float volume);
163 int setMasterVolume(float volume);
164 int setMode(audio_mode_t mode);
165 int setMicMute(bool state);
166 int getMicMute(bool *state) const;
167 int setParameters(const char *kv_pairs);
168 char *getParameters(const char *keys) const;
169 size_t getInputBufferSize(const struct audio_config *config) const;
170 int dump(int fd) const;
171 int setMasterMute(bool mute);
172 AudioStreamIn* openInputStream(audio_io_handle_t handle,
173 audio_devices_t devices,
174 struct audio_config *config);
175 void closeInputStream(AudioStreamIn *in);
176 AudioStreamOut* openOutputStream(audio_io_handle_t handle,
177 audio_devices_t devices,
178 audio_output_flags_t flags,
179 struct audio_config *config);
180 void closeOutputStream(AudioStreamOut *out);
181
182 friend class AudioStreamIn;
183 friend class AudioStreamOut;
184
185 static const uint32_t kNumPorts = 3;
186 static const uint32_t kCPUPortId = 0;
187 static const uint32_t kJAMR3PortId = 1;
188 static const uint32_t kBTPortId = 2;
189 static const uint32_t kCPUNumChannels = 2;
190 static const uint32_t kJAMR3NumChannels = 8;
191 static const uint32_t kBTNumChannels = 2;
192
193 static const uint32_t kSampleRate = 44100;
194 static const uint32_t kBTSampleRate = 8000;
195 static const uint32_t kSampleSize = 16;
196 static const uint32_t kCaptureFrameCount = 882;
197 static const uint32_t kPlaybackFrameCount = 1024;
198 static const uint32_t kBTFrameCount = 160;
199
200 static const uint32_t kADCSettleMs = 80;
201 static const uint32_t kVoiceCallPipeMs = 100;
202
203 static const float kVoiceDBMax = 0.0f;
204 static const float kVoiceDBMin = -24.0f;
205 static const char *kCabinVolumeHP;
206 static const char *kCabinVolumeLine;
207 static const char *kBTMode;
208
209 protected:
210 typedef set< sp<AudioStreamIn> > StreamInSet;
211 typedef set< sp<AudioStreamOut> > StreamOutSet;
212 typedef vector<ALSAInPort*> InPortVect;
213 typedef vector<ALSAOutPort*> OutPortVect;
214 typedef vector<PcmReader*> ReaderVect;
215 typedef vector<PcmWriter*> WriterVect;
216
217 bool usesJAMR3() const { return mMediaPortId == kJAMR3PortId; }
218 const char *getModeName(audio_mode_t mode) const;
219 int enterVoiceCall();
220 void leaveVoiceCall();
221 int enableVoiceCall();
222 void disableVoiceCall();
223
224 uint32_t mCardId;
225 ALSAMixer mMixer;
226 InPortVect mInPorts;
227 OutPortVect mOutPorts;
228 ReaderVect mReaders;
229 WriterVect mWriters;
230 StreamInSet mInStreams;
231 StreamOutSet mOutStreams;
232 bool mMicMute;
233 audio_mode_t mMode;
234 uint32_t mMediaPortId;
235 wp<AudioStreamOut> mPrimaryStreamOut;
236 tiaudioutils::MonoPipe *mULPipe;
237 tiaudioutils::MonoPipe *mDLPipe;
238 PipeWriter *mULPipeWriter;
239 PipeWriter *mDLPipeWriter;
240 PipeReader *mULPipeReader;
241 PipeReader *mDLPipeReader;
242 sp<InStream> mVoiceULInStream;
243 sp<InStream> mVoiceDLInStream;
244 sp<OutStream> mVoiceULOutStream;
245 sp<OutStream> mVoiceDLOutStream;
246 mutable Mutex mLock;
247};
248
249}; // namespace android
250
251#endif /* _AUDIO_HW_H_ */
diff --git a/audio/multizone/audio_hw.cpp b/audio/multizone/audio_hw.cpp
new file mode 100644
index 0000000..3e429c4
--- /dev/null
+++ b/audio/multizone/audio_hw.cpp
@@ -0,0 +1,562 @@
1/*
2 * Copyright (C) 2013 Texas Instruments
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 <stdint.h>
22#include <stdlib.h>
23#include <sys/time.h>
24
25#include <cutils/log.h>
26#include <cutils/str_parms.h>
27#include <cutils/properties.h>
28
29#include <system/audio.h>
30#include <hardware/hardware.h>
31#include <hardware/audio.h>
32#include <hardware/audio_effect.h>
33
34#include <AudioHw.h>
35
36extern "C" {
37
38namespace android {
39
40struct mz_audio_device {
41 struct audio_hw_device device;
42 AudioHwDevice *hwDev;
43};
44
45struct mz_stream_in {
46 struct audio_stream_in stream;
47 AudioStreamIn *streamIn;
48};
49
50struct mz_stream_out {
51 struct audio_stream_out stream;
52 AudioStreamOut *streamOut;
53};
54
55static inline AudioHwDevice *toAudioHwDev(struct audio_hw_device *dev)
56{
57 return reinterpret_cast<struct mz_audio_device *>(dev)->hwDev;
58}
59
60static inline const AudioHwDevice *tocAudioHwDev(const struct audio_hw_device *dev)
61{
62 return reinterpret_cast<const struct mz_audio_device *>(dev)->hwDev;
63}
64
65static inline AudioStreamIn *toStreamIn(struct audio_stream_in *in)
66{
67 return reinterpret_cast<struct mz_stream_in *>(in)->streamIn;
68}
69
70static inline const AudioStreamIn *tocStreamIn(const struct audio_stream_in *in)
71{
72 return reinterpret_cast<const struct mz_stream_in *>(in)->streamIn;
73}
74
75static inline AudioStreamOut *toStreamOut(struct audio_stream_out *out)
76{
77 return reinterpret_cast<struct mz_stream_out *>(out)->streamOut;
78}
79
80static inline const AudioStreamOut *tocStreamOut(const struct audio_stream_out *out)
81{
82 return reinterpret_cast<const struct mz_stream_out *>(out)->streamOut;
83}
84
85/* audio HAL functions */
86
87/* audio_stream_out implementation */
88
89static uint32_t out_get_sample_rate(const struct audio_stream *stream)
90{
91 const AudioStreamOut *out = tocStreamOut((audio_stream_out *)stream);
92 return out->getSampleRate();
93}
94
95static int out_set_sample_rate(struct audio_stream *stream, uint32_t rate)
96{
97 AudioStreamOut *out = toStreamOut((audio_stream_out *)stream);
98 return out->setSampleRate(rate);
99}
100
101static size_t out_get_buffer_size(const struct audio_stream *stream)
102{
103 const AudioStreamOut *out = tocStreamOut((audio_stream_out *)stream);
104 return out->getBufferSize();
105}
106
107static audio_channel_mask_t out_get_channels(const struct audio_stream *stream)
108{
109 const AudioStreamOut *out = tocStreamOut((audio_stream_out *)stream);
110 return out->getChannels();
111}
112
113static audio_format_t out_get_format(const struct audio_stream *stream)
114{
115 const AudioStreamOut *out = tocStreamOut((audio_stream_out *)stream);
116 return out->getFormat();
117}
118
119static int out_set_format(struct audio_stream *stream, audio_format_t format)
120{
121 AudioStreamOut *out = toStreamOut((audio_stream_out *)stream);
122 return out->setFormat(format);
123}
124
125static int out_standby(struct audio_stream *stream)
126{
127 AudioStreamOut *out = toStreamOut((audio_stream_out *)stream);
128 return out->standby();
129}
130
131static int out_dump(const struct audio_stream *stream, int fd)
132{
133 const AudioStreamOut *out = tocStreamOut((audio_stream_out *)stream);
134 return out->dump(fd);
135}
136
137static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
138{
139 AudioStreamOut *out = toStreamOut((audio_stream_out *)stream);
140 return out->setParameters(kvpairs);
141}
142
143static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
144{
145 const AudioStreamOut *out = tocStreamOut((audio_stream_out *)stream);
146 return out->getParameters(keys);
147}
148
149static uint32_t out_get_latency(const struct audio_stream_out *stream)
150{
151 const AudioStreamOut *out = tocStreamOut((audio_stream_out *)stream);
152 return out->getLatency();
153}
154
155static int out_set_volume(struct audio_stream_out *stream, float left,
156 float right)
157{
158 AudioStreamOut *out = toStreamOut((audio_stream_out *)stream);
159 return out->setVolume(left, right);
160}
161
162static ssize_t out_write(struct audio_stream_out *stream, const void* buffer,
163 size_t bytes)
164{
165 AudioStreamOut *out = toStreamOut((audio_stream_out *)stream);
166 return out->write(buffer, bytes);
167}
168
169static int out_get_render_position(const struct audio_stream_out *stream,
170 uint32_t *dsp_frames)
171{
172 const AudioStreamOut *out = tocStreamOut((audio_stream_out *)stream);
173 return out->getRenderPosition(dsp_frames);
174}
175
176static int out_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
177{
178 const AudioStreamOut *out = tocStreamOut((audio_stream_out *)stream);
179 return out->addAudioEffect(effect);
180}
181
182static int out_remove_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
183{
184 const AudioStreamOut *out = tocStreamOut((audio_stream_out *)stream);
185 return out->removeAudioEffect(effect);
186}
187
188static int out_get_next_write_timestamp(const struct audio_stream_out *stream,
189 int64_t *timestamp)
190{
191 const AudioStreamOut *out = tocStreamOut((audio_stream_out *)stream);
192 return out->getNextWriteTimestamp(timestamp);
193}
194
195/* audio_stream_in implementation */
196
197static uint32_t in_get_sample_rate(const struct audio_stream *stream)
198{
199 const AudioStreamIn *in = tocStreamIn((audio_stream_in *)stream);
200 return in->getSampleRate();
201}
202
203static int in_set_sample_rate(struct audio_stream *stream, uint32_t rate)
204{
205 AudioStreamIn *in = toStreamIn((audio_stream_in *)stream);
206 return in->setSampleRate(rate);
207}
208
209static size_t in_get_buffer_size(const struct audio_stream *stream)
210{
211 const AudioStreamIn *in = tocStreamIn((audio_stream_in *)stream);
212 return in->getBufferSize();
213}
214
215static audio_channel_mask_t in_get_channels(const struct audio_stream *stream)
216{
217 const AudioStreamIn *in = tocStreamIn((audio_stream_in *)stream);
218 return in->getChannels();
219}
220
221static audio_format_t in_get_format(const struct audio_stream *stream)
222{
223 const AudioStreamIn *in = tocStreamIn((audio_stream_in *)stream);
224 return in->getFormat();
225}
226
227static int in_set_format(struct audio_stream *stream, audio_format_t format)
228{
229 AudioStreamIn *in = toStreamIn((audio_stream_in *)stream);
230 return in->setFormat(format);
231}
232
233static int in_standby(struct audio_stream *stream)
234{
235 AudioStreamIn *in = toStreamIn((audio_stream_in *)stream);
236 return in->standby();
237}
238
239static int in_dump(const struct audio_stream *stream, int fd)
240{
241 const AudioStreamIn *in = tocStreamIn((audio_stream_in *)stream);
242 return in->dump(fd);
243}
244
245static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
246{
247 AudioStreamIn *in = toStreamIn((audio_stream_in *)stream);
248 return in->setParameters(kvpairs);
249}
250
251static char * in_get_parameters(const struct audio_stream *stream,
252 const char *keys)
253{
254 const AudioStreamIn *in = tocStreamIn((audio_stream_in *)stream);
255 return in->getParameters(keys);
256}
257
258static int in_set_gain(struct audio_stream_in *stream, float gain)
259{
260 AudioStreamIn *in = toStreamIn(stream);
261 return in->setGain(gain);
262}
263
264static ssize_t in_read(struct audio_stream_in *stream, void* buffer, size_t bytes)
265{
266 AudioStreamIn *in = toStreamIn(stream);
267 return in->read(buffer, bytes);
268}
269
270static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream)
271{
272 AudioStreamIn *in = toStreamIn(stream);
273 return in->getInputFramesLost();
274}
275
276static int in_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
277{
278 const AudioStreamIn *in = tocStreamIn((audio_stream_in *)stream);
279 return in->addAudioEffect(effect);
280}
281
282static int in_remove_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
283{
284 const AudioStreamIn *in = tocStreamIn((audio_stream_in *)stream);
285 return in->removeAudioEffect(effect);
286}
287
288/* audio_hw_device implementation */
289
290static int adev_open_output_stream(struct audio_hw_device *dev,
291 audio_io_handle_t handle,
292 audio_devices_t devices,
293 audio_output_flags_t flags,
294 struct audio_config *config,
295 struct audio_stream_out **stream_out)
296{
297 AudioHwDevice *hwDev = toAudioHwDev(dev);
298 struct mz_stream_out *out;
299
300 out = (struct mz_stream_out *)malloc(sizeof(*out));
301 if (!out)
302 return -ENOMEM;
303
304 ALOGV("adev_open_output_stream() stream %p, %u Hz, %u channels, "
305 "%u bits/sample, flags 0x%08x",
306 out, config->sample_rate, popcount(config->channel_mask),
307 audio_bytes_per_sample(config->format) * 8, flags);
308
309 out->stream.common.get_sample_rate = out_get_sample_rate;
310 out->stream.common.set_sample_rate = out_set_sample_rate;
311 out->stream.common.get_buffer_size = out_get_buffer_size;
312 out->stream.common.get_channels = out_get_channels;
313 out->stream.common.get_format = out_get_format;
314 out->stream.common.set_format = out_set_format;
315 out->stream.common.standby = out_standby;
316 out->stream.common.dump = out_dump;
317 out->stream.common.set_parameters = out_set_parameters;
318 out->stream.common.get_parameters = out_get_parameters;
319 out->stream.common.add_audio_effect = out_add_audio_effect;
320 out->stream.common.remove_audio_effect = out_remove_audio_effect;
321 out->stream.get_latency = out_get_latency;
322 out->stream.set_volume = out_set_volume;
323 out->stream.write = out_write;
324 out->stream.get_render_position = out_get_render_position;
325 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
326
327 out->streamOut = hwDev->openOutputStream(handle, devices, flags, config);
328 if (!out->streamOut) {
329 ALOGE("adev_open_output_stream() failed to open stream");
330 free(out);
331 return -ENODEV;
332 }
333
334 *stream_out = &out->stream;
335
336 return 0;
337}
338
339static void adev_close_output_stream(struct audio_hw_device *dev,
340 struct audio_stream_out *stream)
341{
342 AudioHwDevice *hwDev = toAudioHwDev(dev);
343 AudioStreamOut *out = toStreamOut(stream);
344
345 ALOGV("adev_close_output_stream() stream %p", stream);
346
347 out_standby(&stream->common);
348
349 /* closeOutputStream() also deletes the out object */
350 hwDev->closeOutputStream(out);
351
352 free(stream);
353}
354
355static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
356{
357 AudioHwDevice *hwDev = toAudioHwDev(dev);
358 return hwDev->setParameters(kvpairs);
359}
360
361static char *adev_get_parameters(const struct audio_hw_device *dev,
362 const char *keys)
363{
364 const AudioHwDevice *hwDev = tocAudioHwDev(dev);
365 return hwDev->getParameters(keys);
366}
367
368static int adev_init_check(const struct audio_hw_device *dev)
369{
370 const AudioHwDevice *hwDev = tocAudioHwDev(dev);
371 return hwDev->initCheck();
372}
373
374static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
375{
376 AudioHwDevice *hwDev = toAudioHwDev(dev);
377 return hwDev->setVoiceVolume(volume);
378}
379
380static int adev_set_master_volume(struct audio_hw_device *dev, float volume)
381{
382 AudioHwDevice *hwDev = toAudioHwDev(dev);
383 return hwDev->setMasterVolume(volume);
384}
385
386static int adev_set_master_mute(struct audio_hw_device *dev, bool muted)
387{
388 AudioHwDevice *hwDev = toAudioHwDev(dev);
389 return hwDev->setMasterMute(muted);
390}
391
392static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
393{
394 AudioHwDevice *hwDev = toAudioHwDev(dev);
395 return hwDev->setMode(mode);
396}
397
398static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
399{
400 AudioHwDevice *hwDev = toAudioHwDev(dev);
401 return hwDev->setMicMute(state);
402}
403
404static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
405{
406 const AudioHwDevice *hwDev = tocAudioHwDev(dev);
407 return hwDev->getMicMute(state);
408}
409
410static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev,
411 const struct audio_config *config)
412{
413 const AudioHwDevice *hwDev = tocAudioHwDev(dev);
414 return hwDev->getInputBufferSize(config);
415}
416
417static int adev_open_input_stream(struct audio_hw_device *dev,
418 audio_io_handle_t handle,
419 audio_devices_t devices,
420 struct audio_config *config,
421 struct audio_stream_in **stream_in)
422{
423 AudioHwDevice *hwDev = toAudioHwDev(dev);
424 struct mz_stream_in *in;
425 int ret;
426
427 in = (struct mz_stream_in *)malloc(sizeof(*in));
428 if (!in)
429 return -ENOMEM;
430
431 ALOGV("adev_open_input_stream() stream %p, %u Hz, %u channels, "
432 "%u bits/sample",
433 in, config->sample_rate, popcount(config->channel_mask),
434 audio_bytes_per_sample(config->format) * 8);
435
436 in->stream.common.get_sample_rate = in_get_sample_rate;
437 in->stream.common.set_sample_rate = in_set_sample_rate;
438 in->stream.common.get_buffer_size = in_get_buffer_size;
439 in->stream.common.get_channels = in_get_channels;
440 in->stream.common.get_format = in_get_format;
441 in->stream.common.set_format = in_set_format;
442 in->stream.common.standby = in_standby;
443 in->stream.common.dump = in_dump;
444 in->stream.common.set_parameters = in_set_parameters;
445 in->stream.common.get_parameters = in_get_parameters;
446 in->stream.common.add_audio_effect = in_add_audio_effect;
447 in->stream.common.remove_audio_effect = in_remove_audio_effect;
448 in->stream.set_gain = in_set_gain;
449 in->stream.read = in_read;
450 in->stream.get_input_frames_lost = in_get_input_frames_lost;
451
452 in->streamIn = hwDev->openInputStream(handle, devices, config);
453 if (!in->streamIn) {
454 ALOGE("adev_open_input_stream() failed to open stream");
455 free(in);
456 return -ENODEV;
457 }
458
459 *stream_in = &in->stream;
460
461 return 0;
462}
463
464static void adev_close_input_stream(struct audio_hw_device *dev,
465 struct audio_stream_in *stream)
466{
467 AudioHwDevice *hwDev = toAudioHwDev(dev);
468 AudioStreamIn *in = toStreamIn(stream);
469
470 ALOGV("adev_close_input_stream() stream %p", stream);
471
472 in_standby(&stream->common);
473
474 /* closeInputStream() also deletes the in object */
475 hwDev->closeInputStream(in);
476
477 free(stream);
478}
479
480static int adev_dump(const audio_hw_device_t *device, int fd)
481{
482 return 0;
483}
484
485static uint32_t adev_get_supported_devices(const struct audio_hw_device *dev)
486{
487 const AudioHwDevice *hwDev = tocAudioHwDev(dev);
488 return hwDev->getSupportedDevices();
489}
490
491static int adev_close(hw_device_t *device)
492{
493 ALOGI("adev_close()");
494
495 free(device);
496
497 return 0;
498}
499
500static int adev_open(const hw_module_t* module, const char* name, hw_device_t** device)
501{
502 struct mz_audio_device *adev;
503
504 ALOGI("adev_open() %s", name);
505
506 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0)
507 return -EINVAL;
508
509 adev = (struct mz_audio_device*)calloc(1, sizeof(*adev));
510 if (!adev)
511 return -ENOMEM;
512
513 adev->device.common.tag = HARDWARE_DEVICE_TAG;
514 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
515 adev->device.common.module = (struct hw_module_t *) module;
516 adev->device.common.close = adev_close;
517
518 adev->device.get_supported_devices = adev_get_supported_devices;
519 adev->device.init_check = adev_init_check;
520 adev->device.set_voice_volume = adev_set_voice_volume;
521 adev->device.set_master_volume = adev_set_master_volume;
522 adev->device.set_master_mute = adev_set_master_mute;
523 adev->device.set_mode = adev_set_mode;
524 adev->device.set_mic_mute = adev_set_mic_mute;
525 adev->device.get_mic_mute = adev_get_mic_mute;
526 adev->device.set_parameters = adev_set_parameters;
527 adev->device.get_parameters = adev_get_parameters;
528 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
529 adev->device.open_output_stream = adev_open_output_stream;
530 adev->device.close_output_stream = adev_close_output_stream;
531 adev->device.open_input_stream = adev_open_input_stream;
532 adev->device.close_input_stream = adev_close_input_stream;
533 adev->device.dump = adev_dump;
534
535 adev->hwDev = new AudioHwDevice(0);
536
537 *device = &adev->device.common;
538
539 return 0;
540}
541
542static struct hw_module_methods_t hal_module_methods = {
543 /* open */ adev_open,
544};
545
546struct audio_module HAL_MODULE_INFO_SYM = {
547 /* common */ {
548 /* tag*/ HARDWARE_MODULE_TAG,
549 /* module_api_version */AUDIO_MODULE_API_VERSION_0_1,
550 /* hal_api_version */ HARDWARE_HAL_API_VERSION,
551 /* id */ AUDIO_HARDWARE_MODULE_ID,
552 /* name */ "Jacinto6 Multizone Audio HAL",
553 /* author */ "Texas Instruments Inc.",
554 /* methods */ &hal_module_methods,
555 /* dso */ NULL,
556 /* reserved */ {0},
557 },
558};
559
560} /* namespace android */
561
562} /* extern "C" */
diff --git a/audio/multizone/audio_policy.conf b/audio/multizone/audio_policy.conf
new file mode 100644
index 0000000..473409c
--- /dev/null
+++ b/audio/multizone/audio_policy.conf
@@ -0,0 +1,116 @@
1# Global configuration section: lists input and output devices always present on the device
2# as well as the output device selected by default.
3# Devices are designated by a string that corresponds to the enum in audio.h
4
5global_configuration {
6 attached_output_devices AUDIO_DEVICE_OUT_SPEAKER|AUDIO_DEVICE_OUT_WIRED_HEADPHONE|AUDIO_DEVICE_OUT_WIRED_HEADPHONE2
7 default_output_device AUDIO_DEVICE_OUT_SPEAKER
8 attached_input_devices AUDIO_DEVICE_IN_BUILTIN_MIC|AUDIO_DEVICE_IN_ANLG_DOCK_HEADSET
9}
10
11# Zone affinity section: lists the output devices allowed per listening zone. Devices are
12# designated by a string that corresponds to the enum in audio.h. Multiple devices can be
13# concatenated by use of "|" without space or "\n".
14
15zone_affinity {
16 CABIN AUDIO_DEVICE_OUT_SPEAKER|AUDIO_DEVICE_OUT_AUX_DIGITAL|AUDIO_DEVICE_OUT_ALL_A2DP|AUDIO_DEVICE_IN_REMOTE_SUBMIX
17 BACKSEAT1 AUDIO_DEVICE_OUT_WIRED_HEADSET|AUDIO_DEVICE_OUT_WIRED_HEADPHONE|AUDIO_DEVICE_OUT_ALL_A2DP|AUDIO_DEVICE_IN_REMOTE_SUBMIX
18 BACKSEAT2 AUDIO_DEVICE_OUT_WIRED_HEADPHONE2|AUDIO_DEVICE_OUT_ALL_A2DP|AUDIO_DEVICE_IN_REMOTE_SUBMIX
19}
20
21# audio hardware module section: contains descriptors for all audio hw modules present on the
22# device. Each hw module node is named after the corresponding hw module library base name.
23# For instance, "primary" corresponds to audio.primary.<device>.so.
24# The "primary" module is mandatory and must include at least one output with
25# AUDIO_OUTPUT_FLAG_PRIMARY flag.
26# Each module descriptor contains one or more output profile descriptors and zero or more
27# input profile descriptors. Each profile lists all the parameters supported by a given output
28# or input stream category.
29# The "channel_masks", "formats", "devices" and "flags" are specified using strings corresponding
30# to enums in audio.h and audio_policy.h. They are concatenated by use of "|" without space or "\n".
31
32audio_hw_modules {
33 primary {
34 outputs {
35 primary {
36 sampling_rates 44100
37 channel_masks AUDIO_CHANNEL_OUT_STEREO
38 formats AUDIO_FORMAT_PCM_16_BIT
39 devices AUDIO_DEVICE_OUT_SPEAKER
40 flags AUDIO_OUTPUT_FLAG_PRIMARY
41 }
42 hp1 {
43 sampling_rates 44100
44 channel_masks AUDIO_CHANNEL_OUT_STEREO
45 formats AUDIO_FORMAT_PCM_16_BIT
46 devices AUDIO_DEVICE_OUT_WIRED_HEADSET|AUDIO_DEVICE_OUT_WIRED_HEADPHONE
47 }
48 hp2 {
49 sampling_rates 44100
50 channel_masks AUDIO_CHANNEL_OUT_STEREO
51 formats AUDIO_FORMAT_PCM_16_BIT
52 devices AUDIO_DEVICE_OUT_WIRED_HEADPHONE2
53 }
54 }
55 inputs {
56 primary {
57 sampling_rates 8000|11025|16000|22050|32000|44100|48000
58 channel_masks AUDIO_CHANNEL_IN_MONO|AUDIO_CHANNEL_IN_STEREO
59 formats AUDIO_FORMAT_PCM_16_BIT
60 devices AUDIO_DEVICE_IN_BUILTIN_MIC|AUDIO_DEVICE_IN_BACK_MIC|AUDIO_DEVICE_IN_VOICE_CALL|AUDIO_DEVICE_IN_ANLG_DOCK_HEADSET
61 }
62 }
63 }
64 hdmi {
65 outputs {
66 stereo {
67 sampling_rates 44100|48000
68 channel_masks AUDIO_CHANNEL_OUT_STEREO
69 formats AUDIO_FORMAT_PCM_16_BIT
70 devices AUDIO_DEVICE_OUT_AUX_DIGITAL
71 }
72 multichannel {
73 sampling_rates 44100|48000
74 channel_masks dynamic
75 formats AUDIO_FORMAT_PCM_16_BIT
76 devices AUDIO_DEVICE_OUT_AUX_DIGITAL
77 flags AUDIO_OUTPUT_FLAG_DIRECT
78 }
79 }
80 }
81 a2dp {
82 outputs {
83 a2dp {
84 sampling_rates 44100
85 channel_masks AUDIO_CHANNEL_OUT_STEREO
86 formats AUDIO_FORMAT_PCM_16_BIT
87 devices AUDIO_DEVICE_OUT_ALL_A2DP
88 }
89 }
90 }
91 r_submix {
92 outputs {
93 r_submix {
94 sampling_rates 44100|48000
95 channel_masks AUDIO_CHANNEL_OUT_STEREO
96 formats AUDIO_FORMAT_PCM_16_BIT
97 devices AUDIO_DEVICE_OUT_REMOTE_SUBMIX
98 }
99 multichannel {
100 sampling_rates 44100|48000
101 channel_masks AUDIO_CHANNEL_OUT_5POINT1
102 formats AUDIO_FORMAT_PCM_16_BIT
103 devices AUDIO_DEVICE_OUT_REMOTE_SUBMIX
104 flags AUDIO_OUTPUT_FLAG_DIRECT
105 }
106 }
107 inputs {
108 r_submix {
109 sampling_rates 44100|48000
110 channel_masks AUDIO_CHANNEL_IN_MONO|AUDIO_CHANNEL_IN_STEREO|AUDIO_CHANNEL_IN_5POINT1EMUL
111 formats AUDIO_FORMAT_PCM_16_BIT
112 devices AUDIO_DEVICE_IN_REMOTE_SUBMIX
113 }
114 }
115 }
116}