audio_hw_hal.cpp revision 4765c439491ddda3de658e62cc4a64d10e726b34
1/*
2 * Copyright (C) 2011 The Android Open Source Project
3 * Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 *      http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18#define LOG_TAG "qcom_audio_hw_hal"
19//#define LOG_NDEBUG 0
20
21#include <stdint.h>
22
23#include <hardware/hardware.h>
24#include <system/audio.h>
25#include <hardware/audio.h>
26
27#include <hardware_legacy/AudioHardwareInterface.h>
28#include <hardware_legacy/AudioSystemLegacy.h>
29
30namespace android_audio_legacy {
31
32extern "C" {
33
34struct qcom_audio_module {
35    struct audio_module module;
36};
37
38struct qcom_audio_device {
39    struct audio_hw_device device;
40
41    struct AudioHardwareInterface *hwif;
42};
43
44struct qcom_stream_out {
45    struct audio_stream_out stream;
46
47    AudioStreamOut *qcom_out;
48};
49
50struct qcom_stream_in {
51    struct audio_stream_in stream;
52
53    AudioStreamIn *qcom_in;
54};
55
56/** audio_stream_out implementation **/
57static uint32_t out_get_sample_rate(const struct audio_stream *stream)
58{
59    const struct qcom_stream_out *out =
60        reinterpret_cast<const struct qcom_stream_out *>(stream);
61    return out->qcom_out->sampleRate();
62}
63
64static int out_set_sample_rate(struct audio_stream *stream, uint32_t rate)
65{
66    struct qcom_stream_out *out =
67        reinterpret_cast<struct qcom_stream_out *>(stream);
68
69    LOGE("(%s:%d) %s: Implement me!", __FILE__, __LINE__, __func__);
70    /* TODO: implement this */
71    return 0;
72}
73
74static size_t out_get_buffer_size(const struct audio_stream *stream)
75{
76    const struct qcom_stream_out *out =
77        reinterpret_cast<const struct qcom_stream_out *>(stream);
78    return out->qcom_out->bufferSize();
79}
80
81static audio_channel_mask_t out_get_channels(const struct audio_stream *stream)
82{
83    const struct qcom_stream_out *out =
84        reinterpret_cast<const struct qcom_stream_out *>(stream);
85    return out->qcom_out->channels();
86}
87
88static audio_format_t out_get_format(const struct audio_stream *stream)
89{
90    const struct qcom_stream_out *out =
91        reinterpret_cast<const struct qcom_stream_out *>(stream);
92    return out->qcom_out->format();
93}
94
95static int out_set_format(struct audio_stream *stream, audio_format_t format)
96{
97    struct qcom_stream_out *out =
98        reinterpret_cast<struct qcom_stream_out *>(stream);
99    LOGE("(%s:%d) %s: Implement me!", __FILE__, __LINE__, __func__);
100    /* TODO: implement me */
101    return 0;
102}
103
104static int out_standby(struct audio_stream *stream)
105{
106    struct qcom_stream_out *out =
107        reinterpret_cast<struct qcom_stream_out *>(stream);
108    return out->qcom_out->standby();
109}
110
111static int out_dump(const struct audio_stream *stream, int fd)
112{
113    const struct qcom_stream_out *out =
114        reinterpret_cast<const struct qcom_stream_out *>(stream);
115    Vector<String16> args;
116    return out->qcom_out->dump(fd, args);
117}
118
119static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
120{
121    struct qcom_stream_out *out =
122        reinterpret_cast<struct qcom_stream_out *>(stream);
123    return out->qcom_out->setParameters(String8(kvpairs));
124}
125
126static char * out_get_parameters(const struct audio_stream *stream, const char *keys)
127{
128    const struct qcom_stream_out *out =
129        reinterpret_cast<const struct qcom_stream_out *>(stream);
130    String8 s8;
131    s8 = out->qcom_out->getParameters(String8(keys));
132    return strdup(s8.string());
133}
134
135static uint32_t out_get_latency(const struct audio_stream_out *stream)
136{
137    const struct qcom_stream_out *out =
138        reinterpret_cast<const struct qcom_stream_out *>(stream);
139    return out->qcom_out->latency();
140}
141
142static int out_set_volume(struct audio_stream_out *stream, float left,
143                          float right)
144{
145    struct qcom_stream_out *out =
146        reinterpret_cast<struct qcom_stream_out *>(stream);
147    return out->qcom_out->setVolume(left, right);
148}
149
150static ssize_t out_write(struct audio_stream_out *stream, const void* buffer,
151                         size_t bytes)
152{
153    struct qcom_stream_out *out =
154        reinterpret_cast<struct qcom_stream_out *>(stream);
155    return out->qcom_out->write(buffer, bytes);
156}
157
158static int out_get_render_position(const struct audio_stream_out *stream,
159                                   uint32_t *dsp_frames)
160{
161    const struct qcom_stream_out *out =
162        reinterpret_cast<const struct qcom_stream_out *>(stream);
163    return out->qcom_out->getRenderPosition(dsp_frames);
164}
165
166static int out_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
167{
168    return 0;
169}
170
171static int out_remove_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
172{
173    return 0;
174}
175
176static int out_get_next_write_timestamp(const struct audio_stream_out *stream,
177                                        int64_t *timestamp)
178{
179    return -EINVAL;
180}
181
182/** audio_stream_in implementation **/
183static uint32_t in_get_sample_rate(const struct audio_stream *stream)
184{
185    const struct qcom_stream_in *in =
186        reinterpret_cast<const struct qcom_stream_in *>(stream);
187    return in->qcom_in->sampleRate();
188}
189
190static int in_set_sample_rate(struct audio_stream *stream, uint32_t rate)
191{
192    struct qcom_stream_in *in =
193        reinterpret_cast<struct qcom_stream_in *>(stream);
194
195    LOGE("(%s:%d) %s: Implement me!", __FILE__, __LINE__, __func__);
196    /* TODO: implement this */
197    return 0;
198}
199
200static size_t in_get_buffer_size(const struct audio_stream *stream)
201{
202    const struct qcom_stream_in *in =
203        reinterpret_cast<const struct qcom_stream_in *>(stream);
204    return in->qcom_in->bufferSize();
205}
206
207static audio_channel_mask_t in_get_channels(const struct audio_stream *stream)
208{
209    const struct qcom_stream_in *in =
210        reinterpret_cast<const struct qcom_stream_in *>(stream);
211    return in->qcom_in->channels();
212}
213
214static audio_format_t in_get_format(const struct audio_stream *stream)
215{
216    const struct qcom_stream_in *in =
217        reinterpret_cast<const struct qcom_stream_in *>(stream);
218    return in->qcom_in->format();
219}
220
221static int in_set_format(struct audio_stream *stream, audio_format_t format)
222{
223    struct qcom_stream_in *in =
224        reinterpret_cast<struct qcom_stream_in *>(stream);
225    LOGE("(%s:%d) %s: Implement me!", __FILE__, __LINE__, __func__);
226    /* TODO: implement me */
227    return 0;
228}
229
230static int in_standby(struct audio_stream *stream)
231{
232    struct qcom_stream_in *in = reinterpret_cast<struct qcom_stream_in *>(stream);
233    return in->qcom_in->standby();
234}
235
236static int in_dump(const struct audio_stream *stream, int fd)
237{
238    const struct qcom_stream_in *in =
239        reinterpret_cast<const struct qcom_stream_in *>(stream);
240    Vector<String16> args;
241    return in->qcom_in->dump(fd, args);
242}
243
244static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
245{
246    struct qcom_stream_in *in =
247        reinterpret_cast<struct qcom_stream_in *>(stream);
248    return in->qcom_in->setParameters(String8(kvpairs));
249}
250
251static char * in_get_parameters(const struct audio_stream *stream,
252                                const char *keys)
253{
254    const struct qcom_stream_in *in =
255        reinterpret_cast<const struct qcom_stream_in *>(stream);
256    String8 s8;
257    s8 = in->qcom_in->getParameters(String8(keys));
258    return strdup(s8.string());
259}
260
261static int in_set_gain(struct audio_stream_in *stream, float gain)
262{
263    struct qcom_stream_in *in =
264        reinterpret_cast<struct qcom_stream_in *>(stream);
265    return in->qcom_in->setGain(gain);
266}
267
268static ssize_t in_read(struct audio_stream_in *stream, void* buffer,
269                       size_t bytes)
270{
271    struct qcom_stream_in *in =
272        reinterpret_cast<struct qcom_stream_in *>(stream);
273    return in->qcom_in->read(buffer, bytes);
274}
275
276static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream)
277{
278    struct qcom_stream_in *in =
279        reinterpret_cast<struct qcom_stream_in *>(stream);
280    return in->qcom_in->getInputFramesLost();
281}
282
283static int in_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
284{
285    const struct qcom_stream_in *in =
286        reinterpret_cast<const struct qcom_stream_in *>(stream);
287    return in->qcom_in->addAudioEffect(effect);
288}
289
290static int in_remove_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
291{
292    const struct qcom_stream_in *in =
293        reinterpret_cast<const struct qcom_stream_in *>(stream);
294    return in->qcom_in->removeAudioEffect(effect);
295}
296
297/** audio_hw_device implementation **/
298static inline struct qcom_audio_device * to_ladev(struct audio_hw_device *dev)
299{
300    return reinterpret_cast<struct qcom_audio_device *>(dev);
301}
302
303static inline const struct qcom_audio_device * to_cladev(const struct audio_hw_device *dev)
304{
305    return reinterpret_cast<const struct qcom_audio_device *>(dev);
306}
307
308static uint32_t adev_get_supported_devices(const struct audio_hw_device *dev)
309{
310    /* XXX: The old AudioHardwareInterface interface is not smart enough to
311     * tell us this, so we'll lie and basically tell AF that we support the
312     * below input/output devices and cross our fingers. To do things properly,
313     * audio hardware interfaces that need advanced features (like this) should
314     * convert to the new HAL interface and not use this wrapper. */
315    return (/* OUT */
316            AUDIO_DEVICE_OUT_EARPIECE |
317            AUDIO_DEVICE_OUT_SPEAKER |
318            AUDIO_DEVICE_OUT_WIRED_HEADSET |
319            AUDIO_DEVICE_OUT_WIRED_HEADPHONE |
320            AUDIO_DEVICE_OUT_AUX_DIGITAL |
321            AUDIO_DEVICE_OUT_ALL_SCO |
322            AUDIO_DEVICE_OUT_ANC_HEADSET |
323            AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET |
324            AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET |
325            AUDIO_DEVICE_OUT_ANC_HEADPHONE |
326            AUDIO_DEVICE_OUT_FM |
327            AUDIO_DEVICE_OUT_FM_TX |
328            AUDIO_DEVICE_OUT_DIRECTOUTPUT |
329            AUDIO_DEVICE_OUT_PROXY |
330            AUDIO_DEVICE_OUT_DEFAULT |
331            /* IN */
332            AUDIO_DEVICE_IN_VOICE_CALL |
333            AUDIO_DEVICE_IN_COMMUNICATION |
334            AUDIO_DEVICE_IN_AMBIENT |
335            AUDIO_DEVICE_IN_BUILTIN_MIC |
336            AUDIO_DEVICE_IN_WIRED_HEADSET |
337            AUDIO_DEVICE_IN_AUX_DIGITAL |
338            AUDIO_DEVICE_IN_BACK_MIC |
339            AUDIO_DEVICE_IN_ALL_SCO |
340            AUDIO_DEVICE_IN_ANC_HEADSET |
341            AUDIO_DEVICE_IN_FM_RX |
342            AUDIO_DEVICE_IN_FM_RX_A2DP |
343            AUDIO_DEVICE_IN_DEFAULT);
344}
345
346static int adev_init_check(const struct audio_hw_device *dev)
347{
348    const struct qcom_audio_device *qadev = to_cladev(dev);
349
350    return qadev->hwif->initCheck();
351}
352
353static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
354{
355    struct qcom_audio_device *qadev = to_ladev(dev);
356    return qadev->hwif->setVoiceVolume(volume);
357}
358
359static int adev_set_master_volume(struct audio_hw_device *dev, float volume)
360{
361    struct qcom_audio_device *qadev = to_ladev(dev);
362    return qadev->hwif->setMasterVolume(volume);
363}
364
365static int adev_get_master_volume(struct audio_hw_device *dev, float *volume) {
366
367    return -ENOSYS;
368}
369#ifdef QUALCOMM_FEATURES_ENABLED
370static int adev_set_fm_volume(struct audio_hw_device *dev, float volume)
371{
372    struct qcom_audio_device *qadev = to_ladev(dev);
373    return qadev->hwif->setFmVolume(volume);
374}
375#endif
376
377static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
378{
379    struct qcom_audio_device *qadev = to_ladev(dev);
380    return qadev->hwif->setMode(mode);
381}
382
383static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
384{
385    struct qcom_audio_device *qadev = to_ladev(dev);
386    return qadev->hwif->setMicMute(state);
387}
388
389static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
390{
391    const struct qcom_audio_device *qadev = to_cladev(dev);
392    return qadev->hwif->getMicMute(state);
393}
394
395static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
396{
397    struct qcom_audio_device *qadev = to_ladev(dev);
398    return qadev->hwif->setParameters(String8(kvpairs));
399}
400
401static char * adev_get_parameters(const struct audio_hw_device *dev,
402                                  const char *keys)
403{
404    const struct qcom_audio_device *qadev = to_cladev(dev);
405    String8 s8;
406
407    s8 = qadev->hwif->getParameters(String8(keys));
408    return strdup(s8.string());
409}
410
411static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev,
412                                         const struct audio_config *config)
413{
414    const struct qcom_audio_device *qadev = to_cladev(dev);
415    return qadev->hwif->getInputBufferSize(sample_rate, format, channel_count);
416}
417
418#ifdef QUALCOMM_FEATURES_ENABLED
419static int adev_open_output_session(struct audio_hw_device *dev,
420                                   uint32_t devices,
421                                   int *format,
422                                   int sessionId,
423                                   uint32_t samplingRate,
424                                   uint32_t channels,
425                                   struct audio_stream_out **stream_out)
426{
427    struct qcom_audio_device *qadev = to_ladev(dev);
428    status_t status;
429    struct qcom_stream_out *out;
430    int ret;
431
432    out = (struct qcom_stream_out *)calloc(1, sizeof(*out));
433    if (!out)
434        return -ENOMEM;
435
436    out->qcom_out = qadev->hwif->openOutputSession(devices, format,&status,sessionId,samplingRate,channels);
437    if (!out->qcom_out) {
438        ret = status;
439        goto err_open;
440    }
441
442    out->stream.common.standby = out_standby;
443    out->stream.common.set_parameters = out_set_parameters;
444    out->stream.set_volume = out_set_volume;
445
446    *stream_out = &out->stream;
447    return 0;
448
449err_open:
450    free(out);
451    *stream_out = NULL;
452    return ret;
453}
454#endif
455
456static int adev_open_output_stream(struct audio_hw_device *dev,
457                                   audio_io_handle_t handle,
458                                   audio_devices_t devices,
459                                   audio_output_flags_t flags,
460                                   struct audio_config *config,
461                                   struct audio_stream_out **stream_out)
462{
463    struct qcom_audio_device *qadev = to_ladev(dev);
464    status_t status;
465    struct qcom_stream_out *out;
466    int ret;
467
468    out = (struct qcom_stream_out *)calloc(1, sizeof(*out));
469    if (!out)
470        return -ENOMEM;
471
472    out->qcom_out = qadev->hwif->openOutputStream(devices, config->format, config->channels_mask,
473                                                    config->sample_rate, &status);
474    if (!out->qcom_out) {
475        ret = status;
476        goto err_open;
477    }
478
479    out->stream.common.get_sample_rate = out_get_sample_rate;
480    out->stream.common.set_sample_rate = out_set_sample_rate;
481    out->stream.common.get_buffer_size = out_get_buffer_size;
482    out->stream.common.get_channels = out_get_channels;
483    out->stream.common.get_format = out_get_format;
484    out->stream.common.set_format = out_set_format;
485    out->stream.common.standby = out_standby;
486    out->stream.common.dump = out_dump;
487    out->stream.common.set_parameters = out_set_parameters;
488    out->stream.common.get_parameters = out_get_parameters;
489    out->stream.common.add_audio_effect = out_add_audio_effect;
490    out->stream.common.remove_audio_effect = out_remove_audio_effect;
491    out->stream.get_latency = out_get_latency;
492    out->stream.set_volume = out_set_volume;
493    out->stream.write = out_write;
494    out->stream.get_render_position = out_get_render_position;
495    out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
496
497    *stream_out = &out->stream;
498    return 0;
499
500err_open:
501    free(out);
502    *stream_out = NULL;
503    return ret;
504}
505
506static void adev_close_output_stream(struct audio_hw_device *dev,
507                                     struct audio_stream_out* stream)
508{
509    struct qcom_audio_device *qadev = to_ladev(dev);
510    struct qcom_stream_out *out = reinterpret_cast<struct qcom_stream_out *>(stream);
511
512    qadev->hwif->closeOutputStream(out->qcom_out);
513    free(out);
514}
515
516/** This method creates and opens the audio hardware input stream */
517static int adev_open_input_stream(struct audio_hw_device *dev,
518                                  audio_io_handle_t handle,
519                                  audio_devices_t devices,
520                                  audio_config *config,
521                                  audio_stream_in **stream_in)
522{
523    struct qcom_audio_device *qadev = to_ladev(dev);
524    status_t status;
525    struct qcom_stream_in *in;
526    int ret;
527
528    in = (struct qcom_stream_in *)calloc(1, sizeof(*in));
529    if (!in)
530        return -ENOMEM;
531
532    in->qcom_in = qadev->hwif->openInputStream(devices, config->format, config->channels_mask,
533                                    config->sample_rate, &status,
534                                    (AudioSystem::audio_in_acoustics)acoustics);
535    if (!in->qcom_in) {
536        ret = status;
537        goto err_open;
538    }
539
540    in->stream.common.get_sample_rate = in_get_sample_rate;
541    in->stream.common.set_sample_rate = in_set_sample_rate;
542    in->stream.common.get_buffer_size = in_get_buffer_size;
543    in->stream.common.get_channels = in_get_channels;
544    in->stream.common.get_format = in_get_format;
545    in->stream.common.set_format = in_set_format;
546    in->stream.common.standby = in_standby;
547    in->stream.common.dump = in_dump;
548    in->stream.common.set_parameters = in_set_parameters;
549    in->stream.common.get_parameters = in_get_parameters;
550    in->stream.common.add_audio_effect = in_add_audio_effect;
551    in->stream.common.remove_audio_effect = in_remove_audio_effect;
552    in->stream.set_gain = in_set_gain;
553    in->stream.read = in_read;
554    in->stream.get_input_frames_lost = in_get_input_frames_lost;
555
556    *stream_in = &in->stream;
557    return 0;
558
559err_open:
560    free(in);
561    *stream_in = NULL;
562    return ret;
563}
564
565static void adev_close_input_stream(struct audio_hw_device *dev,
566                               struct audio_stream_in *stream)
567{
568    struct qcom_audio_device *qadev = to_ladev(dev);
569    struct qcom_stream_in *in =
570        reinterpret_cast<struct qcom_stream_in *>(stream);
571
572    qadev->hwif->closeInputStream(in->qcom_in);
573    free(in);
574}
575
576static int adev_dump(const struct audio_hw_device *dev, int fd)
577{
578    const struct qcom_audio_device *qadev = to_cladev(dev);
579    Vector<String16> args;
580
581    return qadev->hwif->dumpState(fd, args);
582}
583
584static int qcom_adev_close(hw_device_t* device)
585{
586    struct audio_hw_device *hwdev =
587                        reinterpret_cast<struct audio_hw_device *>(device);
588    struct qcom_audio_device *qadev = to_ladev(hwdev);
589
590    if (!qadev)
591        return 0;
592
593    if (qadev->hwif)
594        delete qadev->hwif;
595
596    free(qadev);
597    return 0;
598}
599
600static int qcom_adev_open(const hw_module_t* module, const char* name,
601                            hw_device_t** device)
602{
603    struct qcom_audio_device *qadev;
604    int ret;
605
606    if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0)
607        return -EINVAL;
608
609    qadev = (struct qcom_audio_device *)calloc(1, sizeof(*qadev));
610    if (!qadev)
611        return -ENOMEM;
612
613    qadev->device.common.tag = HARDWARE_DEVICE_TAG;
614    qadev->device.common.version = AUDIO_DEVICE_API_VERSION_1_0;
615    qadev->device.common.module = const_cast<hw_module_t*>(module);
616    qadev->device.common.close = qcom_adev_close;
617
618    qadev->device.get_supported_devices = adev_get_supported_devices;
619    qadev->device.init_check = adev_init_check;
620    qadev->device.set_voice_volume = adev_set_voice_volume;
621    qadev->device.set_master_volume = adev_set_master_volume;
622    qadev->device.get_master_volume = adev_get_master_volume;
623#ifdef QUALCOMM_FEATURES_ENABLED
624    qadev->device.set_fm_volume = adev_set_fm_volume;
625#endif
626    qadev->device.set_mode = adev_set_mode;
627    qadev->device.set_mic_mute = adev_set_mic_mute;
628    qadev->device.get_mic_mute = adev_get_mic_mute;
629    qadev->device.set_parameters = adev_set_parameters;
630    qadev->device.get_parameters = adev_get_parameters;
631    qadev->device.get_input_buffer_size = adev_get_input_buffer_size;
632    qadev->device.open_output_stream = adev_open_output_stream;
633#ifdef QUALCOMM_FEATURES_ENABLED
634    qadev->device.open_output_session = adev_open_output_session;
635#endif
636    qadev->device.close_output_stream = adev_close_output_stream;
637    qadev->device.open_input_stream = adev_open_input_stream;
638    qadev->device.close_input_stream = adev_close_input_stream;
639    qadev->device.dump = adev_dump;
640
641    qadev->hwif = createAudioHardware();
642    if (!qadev->hwif) {
643        ret = -EIO;
644        goto err_create_audio_hw;
645    }
646
647    *device = &qadev->device.common;
648
649    return 0;
650
651err_create_audio_hw:
652    free(qadev);
653    return ret;
654}
655
656static struct hw_module_methods_t qcom_audio_module_methods = {
657        open: qcom_adev_open
658};
659
660struct qcom_audio_module HAL_MODULE_INFO_SYM = {
661    module: {
662        common: {
663            tag: HARDWARE_MODULE_TAG,
664            version_major: 1,
665            version_minor: 0,
666            id: AUDIO_HARDWARE_MODULE_ID,
667            name: "QCOM Audio HW HAL",
668            author: "Code Aurora Forum",
669            methods: &qcom_audio_module_methods,
670            dso : NULL,
671            reserved : {0},
672        },
673    },
674};
675
676}; // extern "C"
677
678}; // namespace android_audio_legacy
679