1ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON/*
2ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON * Copyright (C) 2012 The Android Open Source Project
3ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON *
4ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON * Licensed under the Apache License, Version 2.0 (the "License");
5ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON * you may not use this file except in compliance with the License.
6ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON * You may obtain a copy of the License at
7ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON *
8ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON *      http://www.apache.org/licenses/LICENSE-2.0/
9ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON * Copyright (C) 2012 The Android Open Source Project
10ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON *
11ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON * Licensed under the Apache License, Version 2.0 (the "License");
12ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON * you may not use this file except in compliance with the License.
13ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON * You may obtain a copy of the License at
14ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON *
15ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON *      http://www.apache.org/licenses/LICENSE-2.0
16ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON *
17ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON * Unless required by applicable law or agreed to in writing, software
18ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON * distributed under the License is distributed on an "AS IS" BASIS,
19ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON * See the License for the specific language governing permissions and
21ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON * limitations under the License.
22ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON */
23ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
24ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON/*
25ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON * This code has modified by Intel Corporation
26ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON */
27ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
28ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON/*
29ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON * Copyright (c) 2014, Intel Corporation
30ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON *
31ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON * Licensed under the Apache License, Version 2.0 (the "License");
32ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON * you may not use this file except in compliance with the License.
33ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON * You may obtain a copy of the License at
34ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON *
35ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON * http://www.apache.org/licenses/LICENSE-2.0
36ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON *
37ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
38ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
39ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
40ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
41ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
42ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
43ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
44ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
45ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
46ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
47ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON */
48ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
49ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON#define LOG_TAG "tiny_hdmi_audio_hw"
50ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON//#define LOG_NDEBUG 0
51ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
52ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON#include <errno.h>
53ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON#include <pthread.h>
54ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON#include <stdint.h>
55ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON#include <sys/time.h>
56ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON#include <stdlib.h>
57ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
58ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON#include <cutils/log.h>
59ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON#include <cutils/str_parms.h>
60ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON#include <cutils/properties.h>
61ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
62ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON#include <hardware/hardware.h>
63ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON#include <system/audio.h>
64ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON#include <hardware/audio.h>
65ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
66ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON#include <sound/asound.h>
67ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON#include <tinyalsa/asoundlib.h>
68ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
69ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON#define UNUSED_PARAMETER(x)        (void)(x)
70ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
71ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON#define DEFAULT_CARD               0
72ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON#define DEFAULT_DEVICE             0
73ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
74ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON/*this is used to avoid starvation*/
75ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON#define LATENCY_TO_BUFFER_SIZE_RATIO 2
76ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
77ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON/*Playback Channel Map*/
78ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON#define CHANNEL_MAP_REQUEST      2
79ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
80ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON/*global - keep track of the active device.
81ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTONThis is needed since we are supporting more
82ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTONthan one profile for HDMI. The Flinger
83ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTONassumes we can suport multiple streams
84ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTONat the same time. This makes sure only one stream
85ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTONis active at a time.*/
86ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTONstruct pcm * activePcm = NULL;
87ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON/*TODO - move active channel inside activepcm*/
88ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTONstatic unsigned int activeChannel;
89ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
90ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
91ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
92ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON#define STRING_TO_ENUM(string) { #string, string }
93ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
94ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTONstruct channel_list {
95ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    const char *name;
96ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    uint32_t value;
97ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON};
98ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
99ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTONconst struct channel_list channel_list_table[] = {
100ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
101ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
102ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
103ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON};
104ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
105ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTONstruct pcm_config pcm_config_default = {
106ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    .channels = 2,
107ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    .rate = 44100,
108ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    .period_size = 1024,
109ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    .period_count = 4,
110ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    .format = PCM_FORMAT_S24_LE,
111ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON};
112ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
113ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON#define CHANNEL_MASK_MAX 3
114ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTONstruct audio_device {
115ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    struct audio_hw_device hw_device;
116ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
117ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    pthread_mutex_t lock;
118ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    int card;
119ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    int device;
120ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    bool standby;
121ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    int sink_sup_channels;
122ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    audio_channel_mask_t sup_channel_masks[CHANNEL_MASK_MAX];
123ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON};
124ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
125ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTONstruct stream_out {
126ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    struct audio_stream_out stream;
127ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
128ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    pthread_mutex_t lock;
129ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    struct pcm *pcm;
130ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    bool standby;
131ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
132ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON/* PCM Stream Configurations */
133ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    struct pcm_config pcm_config;
134ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    uint32_t   channel_mask;
135ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
136ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON /* ALSA PCM Configurations */
137ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    uint32_t   sample_rate;
138ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    uint32_t   buffer_size;
139ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    uint32_t   channels;
140ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    uint32_t   latency;
141ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
142ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    struct audio_device *dev;
143ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON};
144ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
145ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON/**
146ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON * NOTE: when multiple mutexes have to be acquired, always respect the
147ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON * following order: hw device > out stream
148ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON */
149ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
150ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON/* Helper functions */
151ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
152ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON// This function return the card number associated with the card ID (name)
153ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON// passed as argument
154ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTONstatic int get_card_number_by_name(const char* name)
155ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON{
156ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    char id_filepath[PATH_MAX] = {0};
157ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    char number_filepath[PATH_MAX] = {0};
158ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    ssize_t written;
159ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
160ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    snprintf(id_filepath, sizeof(id_filepath), "/proc/asound/%s", name);
161ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
162ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    written = readlink(id_filepath, number_filepath, sizeof(number_filepath));
163ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    if (written < 0) {
164ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON        ALOGE("Sound card %s does not exist - setting default", name);
165ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON        return DEFAULT_CARD;
166ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    } else if (written >= (ssize_t)sizeof(id_filepath)) {
167ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON        ALOGE("Sound card %s name is too long - setting default", name);
168ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON        return DEFAULT_CARD;
169ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    }
170ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
171ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    // We are assured, because of the check in the previous elseif, that this
172ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    // buffer is null-terminated.  So this call is safe.
173ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    // 4 == strlen("card")
174ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    return atoi(number_filepath + 4);
175ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON}
176ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
177ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTONstatic enum pcm_format Get_SinkSupported_format()
178ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON{
179ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON   /*TODO : query sink supported formats*/
180ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON   return PCM_FORMAT_S24_LE;
181ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON}
182ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
183ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTONstatic int make_sinkcompliant_buffers(void* input, void *output, int ipbytes)
184ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON{
185ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON  int i = 0,outbytes = 0;
186ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON  enum pcm_format out_pcmformat;
187ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON  int *src = (int*)input;
188ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON  int *dst = (int*)output;
189ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
190ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON  /*by default android currently support only
191ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    16 bit signed PCM*/
192ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON  out_pcmformat = Get_SinkSupported_format();
193ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
194ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON  switch (out_pcmformat) {
195ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    default:
196ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    case PCM_FORMAT_S24_LE:
197ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    {
198ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON       ALOGV("convert 16 to 24 bits for %d",ipbytes);
199ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON       /*convert 16 bit input to 24 bit output
200ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON         in a 32 bit sample*/
201ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON       if(0 == ipbytes)
202ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON          break;
203ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
204ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON       for(i = 0; i < (ipbytes/4); i++){
205ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON          int x = (int)((int*)src)[i];
206ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON          dst[i*2] = ((int)( x & 0x0000FFFF)) << 8;
207ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON          // trying to sign exdent
208ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON          dst[i*2] = dst[i*2] << 8;
209ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON          dst[i*2] = dst[i*2] >> 8;
210ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON          //shift to middle
211ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON          dst[i*2 + 1] = (int)(( x & 0xFFFF0000) >> 8);
212ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON          dst[i*2 + 1] = dst[i*2 + 1] << 8;
213ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON          dst[i*2 + 1] = dst[i*2 + 1] >> 8;
214ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON        }
215ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON        outbytes=ipbytes * 2;
216ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
217ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    }//case
218ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON  };//switch
219ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
220ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON  return outbytes;
221ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON}
222ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
223ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON/* must be called with hw device and output stream mutexes locked */
224ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTONstatic int start_output_stream(struct stream_out *out)
225ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON{
226ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    struct audio_device *adev = out->dev;
227ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
228ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    ALOGV("%s enter",__func__);
229ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
230ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    if ((adev->card < 0) || (adev->device < 0)){
231ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON        /*this will be updated once the hot plug intent
232ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON          sends these information.*/
233ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON        adev->card = DEFAULT_CARD;
234ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON        adev->device = DEFAULT_DEVICE;
235ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON        ALOGV("%s : Setting default card/ device %d,%d",__func__,adev->card,adev->device);
236ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    }
237ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
238ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    ALOGV("%s enter %d,%d,%d,%d,%d",__func__,
239ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON          out->pcm_config.channels,
240ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON          out->pcm_config.rate,
241ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON          out->pcm_config.period_size,
242ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON          out->pcm_config.period_count,
243ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON          out->pcm_config.format);
244ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
245ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    out->pcm_config.start_threshold = 0;
246ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    out->pcm_config.stop_threshold = 0;
247ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    out->pcm_config.silence_threshold = 0;
248ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
249ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    if(activePcm){
250ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON      ALOGV("Closing already open tiny alsa stream running state %d",(int)(activePcm));
251ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON      pcm_close(activePcm);
252ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON      activePcm = NULL;
253ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    }
254ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
255ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    /*TODO - this needs to be updated once the device connect intent sends
256ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON      card, device id*/
257ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    adev->card = get_card_number_by_name("IntelHDMI");
258ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    ALOGD("%s: HDMI card number = %d, device = %d",__func__,adev->card,adev->device);
259ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
260ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    out->pcm = pcm_open(adev->card, adev->device, PCM_OUT, &out->pcm_config);
261ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
262ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    if (out->pcm && !pcm_is_ready(out->pcm)) {
263ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON        ALOGE("pcm_open() failed: %s", pcm_get_error(out->pcm));
264ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON        pcm_close(out->pcm);
265ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON        activePcm = NULL;
266ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON        return -ENOMEM;
267ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    }
268ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
269ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    activePcm = out->pcm;
270ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    activeChannel = out->pcm_config.channels;
271ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
272ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    ALOGV("Initialized PCM device for channels %d handle = %d",out->pcm_config.channels, (int)activePcm);
273ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    ALOGV("%s exit",__func__);
274ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    return 0;
275ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON}
276ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
277ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON/* API functions */
278ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
279ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTONstatic uint32_t out_get_sample_rate(const struct audio_stream *stream)
280ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON{
281ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    struct stream_out *out = (struct stream_out *)stream;
282ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    return out->pcm_config.rate;
283ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON}
284ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
285ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTONstatic int out_set_sample_rate(struct audio_stream *stream, uint32_t rate)
286ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON{
287ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    UNUSED_PARAMETER(stream);
288ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    UNUSED_PARAMETER(rate);
289ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
290ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    return 0;
291ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON}
292ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
293ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTONstatic size_t out_get_buffer_size(const struct audio_stream *stream)
294ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON{
295ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    struct stream_out *out = (struct stream_out *)stream;
296ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    size_t buf_size;
297ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
298ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    if(out->channel_mask > 2){
299ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON       buf_size = out->pcm_config.period_size *
3000ce92df294da2b05fd06c7da49ac5324e68c7a14Guilhem IMBERTON                  audio_stream_out_frame_size((struct audio_stream_out *)stream);
301ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    }
302ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    else{
303ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON       buf_size = out->pcm_config.period_size *
304ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON                  out->pcm_config.period_count *
3050ce92df294da2b05fd06c7da49ac5324e68c7a14Guilhem IMBERTON                  audio_stream_out_frame_size((struct audio_stream_out *)stream);
306ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
307ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON       /*latency of audio flinger is based on this
308ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON         buffer size. modifying the buffer size to avoid
309ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON         starvation*/
310ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON       buf_size/=LATENCY_TO_BUFFER_SIZE_RATIO;
311ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    }
312ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
313ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    ALOGV("%s : %d, period_size : %d, frame_size : %d",
314ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON        __func__,
315ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON        buf_size,
316ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON        out->pcm_config.period_size,
3170ce92df294da2b05fd06c7da49ac5324e68c7a14Guilhem IMBERTON        audio_stream_out_frame_size((struct audio_stream_out *)stream));
318ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
319ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    return buf_size;
320ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
321ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON}
322ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
323ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTONstatic uint32_t out_get_channels(const struct audio_stream *stream)
324ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON{
325ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    struct stream_out *out = (struct stream_out *)stream;
326ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    ALOGV("%s channel mask : %x",__func__,out->channel_mask);
327ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    return out->channel_mask;
328ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON}
329ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
330ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTONstatic audio_format_t out_get_format(const struct audio_stream *stream)
331ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON{
332ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    UNUSED_PARAMETER(stream);
333ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
334ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    return AUDIO_FORMAT_PCM_16_BIT;
335ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON}
336ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
337ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTONstatic int out_set_format(struct audio_stream *stream, audio_format_t format)
338ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON{
339ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    UNUSED_PARAMETER(stream);
340ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    UNUSED_PARAMETER(format);
341ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
342ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    return 0;
343ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON}
344ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
345ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTONstatic int out_standby(struct audio_stream *stream)
346ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON{
347ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    struct stream_out *out = (struct stream_out *)stream;
348ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
349ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    ALOGV("%s enter standby = %d",__func__,out->standby);
350ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
351ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    pthread_mutex_lock(&out->dev->lock);
352ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    pthread_mutex_lock(&out->lock);
353ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
354ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    if (!out->standby && activePcm) {
355ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON        pcm_close(activePcm);
356ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON        out->pcm = NULL;
357ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON        out->standby = true;
358ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON        activePcm = NULL;
359ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON        ALOGV("%s PCM device closed",__func__);
360ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    }
361ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
362ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    pthread_mutex_unlock(&out->lock);
363ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    pthread_mutex_unlock(&out->dev->lock);
364ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
365ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    ALOGV("%s exit",__func__);
366ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    return 0;
367ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON}
368ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
369ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTONstatic int out_dump(const struct audio_stream *stream, int fd)
370ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON{
371ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    UNUSED_PARAMETER(stream);
372ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    UNUSED_PARAMETER(fd);
373ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    return 0;
374ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON}
375ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
376ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTONstatic int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
377ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON{
378ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    struct stream_out *out = (struct stream_out *)stream;
379ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    struct audio_device *adev = out->dev;
380ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    struct str_parms *parms;
381ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    char value[32];
382ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    int ret;
383ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    ALOGV("%s enter",__func__);
384ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
385ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    parms = str_parms_create_str(kvpairs);
386ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
387ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    pthread_mutex_lock(&adev->lock);
388ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
389ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    if (parms == NULL) {
390ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON        ALOGE("couldn't extract string params from key value pairs");
391ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON        pthread_mutex_unlock(&adev->lock);
392ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON        return 0;
393ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    }
394ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
395ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    ret = str_parms_get_str(parms, "card", value, sizeof(value));
396ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    if (ret >= 0)
397ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON        adev->card = atoi(value);
398ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
399ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    ret = str_parms_get_str(parms, "device", value, sizeof(value));
400ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    if (ret >= 0)
401ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON        adev->device = atoi(value);
402ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
403ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    pthread_mutex_unlock(&adev->lock);
404ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    str_parms_destroy(parms);
405ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
406ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    ALOGV("%s exit",__func__);
407ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    return 0;
408ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON}
409ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
410ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTONstatic int parse_channel_map()
411ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON{
412ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    struct mixer *mixer;
413ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    int card = 0;
414ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    struct mixer_ctl *ctl;
415ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    enum mixer_ctl_type type;
416ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    unsigned int num_values;
417ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    unsigned int i,id;
418ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    int chcount=0, chmap=0;
419ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
420ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    card = get_card_number_by_name("IntelHDMI");
421ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    mixer = mixer_open(card);
422ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    if (!mixer) {
423ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON        ALOGE("[EDID] Failed to open mixer\n");
424ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON        goto chmap_error;
425ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    }
426ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
427ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    id = CHANNEL_MAP_REQUEST;
428ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    if (id >= mixer_get_num_ctls(mixer)) {
429ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON        ALOGE("[EDID] Invalid request for channel map %d",id);
430ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON        goto chmap_error;
431ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    }
432ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
433ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    ctl = mixer_get_ctl_by_name(mixer, "Playback Channel Map");
434ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
435ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    //ctl = mixer_get_ctl(mixer, id);
436ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
437ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    type = mixer_ctl_get_type(ctl);
438ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    num_values = mixer_ctl_get_num_values(ctl);
439ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
440ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    ALOGV("[EDID]id = %d",id);
441ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    ALOGV("[EDID]type = %d",type);
442ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    ALOGV("[EDID]count = %d",num_values);
443ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
444ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    for (i = 0; i < num_values; i++) {
445ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON      switch (type)
446ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON      {
447ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON       case MIXER_CTL_TYPE_INT:
448ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON            chmap = mixer_ctl_get_value(ctl, i);
449ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON            ALOGD("[EDID]chmap = %d", chmap);
450ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON            if(chmap > 0)  ++chcount;
451ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON            break;
452ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON       default:
453ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON            printf(" unknown");
454ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON            break;
455ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON      };
456ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    }//for
457ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
458ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    ALOGD("[EDID]valid number of channels supported by sink = %d",chcount);
459ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
460ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    mixer_close(mixer);
461ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
462ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    return chcount;
463ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
464ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTONchmap_error:
465ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    mixer_close(mixer);
466ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    return 2;//stereo by default
467ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
468ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON}
469ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
470ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTONstatic int out_read_edid(const struct stream_out *stream)
471ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON{
472ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    struct stream_out *out = (struct stream_out *)stream;
473ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    struct audio_device *adev = out->dev;
474ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
475ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    /**read the channel max param from the sink*/
476ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    adev->sink_sup_channels = parse_channel_map();
477ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
478ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    if(adev->sink_sup_channels == 8) {
479ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON      adev->sup_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
480ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON      adev->sup_channel_masks[1] = AUDIO_CHANNEL_OUT_7POINT1;
481ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    }
482ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    else if((adev->sink_sup_channels == 6) || (adev->sink_sup_channels > 2)) {
483ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON      adev->sup_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
484ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    }
485ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    else {
486ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON      adev->sup_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
487ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    }
488ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
489ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    ALOGV("%s sink supports 0x%x max channels", __func__,adev->sink_sup_channels);
490ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    return 0;
491ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON}
492ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
493ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTONstatic char * out_get_parameters(const struct audio_stream *stream, const char *keys)
494ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON{
495ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    struct stream_out *out = (struct stream_out *)stream;
496ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    struct audio_device *adev = out->dev;
497ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    struct str_parms *params_in = str_parms_create_str(keys);
498ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    char *str = NULL;
499ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    char value[256] = {0};
500ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    int ret;
501ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    size_t i, j;
502ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    bool append = false;
503ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
504ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    struct str_parms *params_out = str_parms_create();
505ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
506ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    ALOGV("%s Entered %s", __func__,keys);
507ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
508ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    if (params_in) {
509ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON        ret = str_parms_get_str(params_in, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
510ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON        if (ret >= 0) {
511ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON            /*read the channel support from sink*/
512ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON            out_read_edid(out);
513ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
514ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON            value[0] = '\0';
515ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON            for (i = 0; i < CHANNEL_MASK_MAX; i++) {
516ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON               for (j = 0; j < ARRAY_SIZE(channel_list_table); j++) {
517ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON                   if (channel_list_table[j].value == adev->sup_channel_masks[i]) {
518ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON                      if (append) {
519ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON                          strcat(value, "|");
520ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON                      }
521ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON                      strcat(value, channel_list_table[j].name);
522ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON                      append = true;
523ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON                      break;
524ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON                   }
525ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON               }
526ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON            }
527ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON        }
528ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    }
529ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    if (params_out) {
530ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON        str_parms_add_str(params_out, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
531ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON        str = str_parms_to_str(params_out);
532ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    } else {
533ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON        str = strdup(keys);
534ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    }
535ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
536ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    ALOGV("%s AUDIO_PARAMETER_STREAM_SUP_CHANNELS %s", __func__,str);
537ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    if (params_in) {
538ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON        str_parms_destroy(params_in);
539ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    }
540ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    if (params_out) {
541ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON        str_parms_destroy(params_out);
542ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    }
543ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
544ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    return str;
545ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON}
546ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
547ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTONstatic uint32_t out_get_latency(const struct audio_stream_out *stream)
548ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON{
549ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    struct stream_out *out = (struct stream_out *)stream;
550ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    return (out->pcm_config.period_size * out->pcm_config.period_count * 1000) /
551ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON            out_get_sample_rate(&stream->common);
552ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON}
553ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
554ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTONstatic int out_set_volume(struct audio_stream_out *stream, float left,
555ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON                          float right)
556ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON{
557ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    UNUSED_PARAMETER(stream);
558ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    UNUSED_PARAMETER(left);
559ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    UNUSED_PARAMETER(right);
560ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
561ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    return -ENOSYS;
562ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON}
563ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
564ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTONstatic ssize_t out_write(struct audio_stream_out *stream, const void* buffer,
565ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON                         size_t bytes)
566ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON{
567ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    int ret = 0;
568ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    struct stream_out *out = (struct stream_out *)stream;
569ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    int32_t* dstbuff = NULL;
570ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    int outbytes = 0;
571ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
572ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    ALOGV("%s enter for bytes = %d channels = %d",__func__,bytes, out->pcm_config.channels);
573ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
574ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    pthread_mutex_lock(&out->dev->lock);
575ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    pthread_mutex_lock(&out->lock);
576ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
577ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    if(activePcm == NULL) {
578ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON       ALOGV("%s: previous stream closed- open again",__func__);
579ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON       out->standby = true;
580ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    }
581ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
582ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    if (out->standby) {
583ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON        ret = start_output_stream(out);
584ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON        if (ret != 0) {
585ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON            goto err;
586ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON        }
587ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON        out->standby = false;
588ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    }
589ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
590ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    if((!out->pcm) || (activeChannel != out->pcm_config.channels)){
591ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON       ALOGD("%s: null handle to write - device already closed",__func__);
592ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON       goto err;
593ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    }
594ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
595ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    if(Get_SinkSupported_format() == out->pcm_config.format){
596ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
597ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON       /*16 bit data will be converted to 24 bit over 32 bit data type
598ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON       hence the multiplier 2*/
599ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON       dstbuff = (int32_t*)malloc(bytes* 2);
600ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON       if (!dstbuff) {
601ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON           pthread_mutex_unlock(&out->lock);
602ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON           pthread_mutex_unlock(&out->dev->lock);
603ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON           ALOGE("%s : memory allocation failed",__func__);
604ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON           return -ENOMEM;
605ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON       }
606ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
607ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON       memset(dstbuff,0,bytes * 2);
608ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
609ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON       outbytes = make_sinkcompliant_buffers((void*)buffer, (void*)dstbuff,bytes);
610ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON     } //if()for conversion
611ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
612ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    if(dstbuff){
613ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON      ret = pcm_write(out->pcm, (void *)dstbuff, outbytes);
614ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    }
615ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    else
616ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON      ret = pcm_write(out->pcm, (void *)buffer, bytes);
617ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
618ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    ALOGV("pcm_write: %s done for %d input bytes, output bytes = %d ", pcm_get_error(out->pcm),bytes,outbytes);
619ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
620ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    free(dstbuff);
621ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
622ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTONerr:
623ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    pthread_mutex_unlock(&out->lock);
624ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    pthread_mutex_unlock(&out->dev->lock);
625ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
626ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON   if(ret !=0){
627ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    uint64_t duration_ms = ((bytes * 1000)/
6280ce92df294da2b05fd06c7da49ac5324e68c7a14Guilhem IMBERTON                            (audio_stream_out_frame_size(stream)) /
629ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON                            (out_get_sample_rate(&stream->common)));
630ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    ALOGV("%s : silence written", __func__);
631ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    usleep(duration_ms * 1000);
632ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON   }
633ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
634ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    ALOGV("%s exit",__func__);
635ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    return bytes;
636ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON}
637ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
638ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTONstatic int out_get_render_position(const struct audio_stream_out *stream,
639ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON                                   uint32_t *dsp_frames)
640ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON{
641ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    UNUSED_PARAMETER(stream);
642ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    UNUSED_PARAMETER(dsp_frames);
643ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
644ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    return -EINVAL;
645ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON}
646ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
647ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTONstatic int out_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
648ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON{
649ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    UNUSED_PARAMETER(stream);
650ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    UNUSED_PARAMETER(effect);
651ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
652ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    return 0;
653ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON}
654ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
655ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTONstatic int out_remove_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
656ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON{
657ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    UNUSED_PARAMETER(stream);
658ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    UNUSED_PARAMETER(effect);
659ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
660ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    return 0;
661ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON}
662ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
663ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTONstatic int out_get_next_write_timestamp(const struct audio_stream_out *stream,
664ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON                                        int64_t *timestamp)
665ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON{
666ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    UNUSED_PARAMETER(stream);
667ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    UNUSED_PARAMETER(timestamp);
668ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
669ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    return -EINVAL;
670ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON}
671ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
672ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTONstatic int adev_open_output_stream(struct audio_hw_device *dev,
673ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON                                   audio_io_handle_t handle,
674ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON                                   audio_devices_t devices,
675ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON                                   audio_output_flags_t flags,
676ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON                                   struct audio_config *config,
6770ce92df294da2b05fd06c7da49ac5324e68c7a14Guilhem IMBERTON                                   struct audio_stream_out **stream_out,
6780ce92df294da2b05fd06c7da49ac5324e68c7a14Guilhem IMBERTON                                   const char *address)
679ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON{
680ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    UNUSED_PARAMETER(devices);
681ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    UNUSED_PARAMETER(handle);
6820ce92df294da2b05fd06c7da49ac5324e68c7a14Guilhem IMBERTON    UNUSED_PARAMETER(address);
683ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
684ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    struct audio_device *adev = (struct audio_device *)dev;
685ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    struct stream_out *out;
686ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    int ret;
687ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    ALOGV("%s enter",__func__);
688ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
689ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
690ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    if (!out)
691ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON        return -ENOMEM;
692ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
693ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
694ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    out->dev = adev;
695ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
696ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    adev->sup_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
697ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
698ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    if (flags & AUDIO_OUTPUT_FLAG_DIRECT) {
699ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON        ALOGV("%s: HDMI Multichannel",__func__);
700ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON        if (config->sample_rate == 0)
701ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON            config->sample_rate = pcm_config_default.rate;
702ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON        if (config->channel_mask == 0){
703ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON            /*read the channel support from sink*/
704ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON            out_read_edid(out);
705ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON            if(config->channel_mask == 0)
706ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON               config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
707ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON        }
708ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    } else {
709ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON        ALOGV("%s: HDMI Stereo",__func__);
710ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON        if (config->sample_rate == 0)
711ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON            config->sample_rate = pcm_config_default.rate;
712ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON        if (config->channel_mask == 0)
713ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON            config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
714ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    }
715ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
716ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    out->channel_mask                      = config->channel_mask;
717ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
718ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    out->pcm_config.channels               = popcount(config->channel_mask);
719ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    out->pcm_config.rate                   = config->sample_rate;
720ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    out->pcm_config.period_size            = pcm_config_default.period_size;
721ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    out->pcm_config.period_count           = pcm_config_default.period_count;
722ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    out->pcm_config.format                 = pcm_config_default.format;
723ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
724ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    out->stream.common.get_sample_rate     = out_get_sample_rate;
725ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    out->stream.common.set_sample_rate     = out_set_sample_rate;
726ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    out->stream.common.get_buffer_size     = out_get_buffer_size;
727ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    out->stream.common.get_channels        = out_get_channels;
728ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    out->stream.common.get_format          = out_get_format;
729ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    out->stream.common.set_format          = out_set_format;
730ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    out->stream.common.standby             = out_standby;
731ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    out->stream.common.dump                = out_dump;
732ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    out->stream.common.set_parameters      = out_set_parameters;
733ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    out->stream.common.get_parameters      = out_get_parameters;
734ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    out->stream.common.add_audio_effect    = out_add_audio_effect;
735ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    out->stream.common.remove_audio_effect = out_remove_audio_effect;
736ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    out->stream.get_latency                = out_get_latency;
737ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    out->stream.set_volume                 = out_set_volume;
738ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    out->stream.write                      = out_write;
739ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    out->stream.get_render_position        = out_get_render_position;
740ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    out->stream.get_next_write_timestamp   = out_get_next_write_timestamp;
741ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
742ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    config->format = out_get_format(&out->stream.common);
743ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    config->channel_mask = out_get_channels(&out->stream.common);
744ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    config->sample_rate = out_get_sample_rate(&out->stream.common);
745ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
746ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    out->standby = true;
747ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
748ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    adev->card = -1;
749ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    adev->device = -1;
750ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
751ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    pthread_mutex_lock(&out->dev->lock);
752ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    pthread_mutex_lock(&out->lock);
753ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
754ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    if(activePcm){
755ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON      ALOGV("Closing already open tiny alsa stream %d",(int)out->pcm);
756ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON      pcm_close(activePcm);
757ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON      activePcm = NULL;
758ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    }
759ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    ret = start_output_stream(out);
760ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    if (ret != 0) {
761ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON        ALOGV("%s: stream start failed", __func__);
762ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON        goto err_open;
763ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    }
764ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
765ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    out->standby = false;
766ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
767ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    *stream_out = &out->stream;
768ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
769ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    pthread_mutex_unlock(&out->lock);
770ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    pthread_mutex_unlock(&out->dev->lock);
771ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
772ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    ALOGV("%s exit",__func__);
773ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    return 0;
774ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
775ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTONerr_open:
776ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    ALOGE("%s exit with error",__func__);
777ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    pthread_mutex_unlock(&out->lock);
778ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    pthread_mutex_unlock(&out->dev->lock);
779ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    free(out);
780ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    *stream_out = NULL;
781ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    return ret;
782ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON}
783ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
784ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTONstatic void adev_close_output_stream(struct audio_hw_device *dev,
785ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON                                     struct audio_stream_out *stream)
786ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON{
787ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    UNUSED_PARAMETER(dev);
788ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
789ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    struct stream_out *out = (struct stream_out *)stream;
790ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
791ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    ALOGV("%s enter",__func__);
792ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    out->standby = false;
793ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    out_standby(&stream->common);
794ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    free(stream);
795ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    ALOGV("%s exit",__func__);
796ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON}
797ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
798ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTONstatic int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
799ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON{
800ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    UNUSED_PARAMETER(dev);
801ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    UNUSED_PARAMETER(kvpairs);
802ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
803ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    return 0;
804ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON}
805ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
806ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTONstatic char * adev_get_parameters(const struct audio_hw_device *dev,
807ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON                                  const char *keys)
808ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON{
809ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    UNUSED_PARAMETER(dev);
810ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    UNUSED_PARAMETER(keys);
811ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
812ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    return strdup("");
813ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON}
814ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
815ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTONstatic int adev_init_check(const struct audio_hw_device *dev)
816ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON{
817ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    UNUSED_PARAMETER(dev);
818ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
819ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    return 0;
820ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON}
821ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
822ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTONstatic int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
823ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON{
824ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    UNUSED_PARAMETER(dev);
825ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    UNUSED_PARAMETER(volume);
826ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
827ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    return -ENOSYS;
828ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON}
829ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
830ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTONstatic int adev_set_master_volume(struct audio_hw_device *dev, float volume)
831ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON{
832ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    UNUSED_PARAMETER(dev);
833ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    UNUSED_PARAMETER(volume);
834ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
835ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    return -ENOSYS;
836ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON}
837ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
838ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTONstatic int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
839ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON{
840ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    UNUSED_PARAMETER(dev);
841ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    UNUSED_PARAMETER(mode);
842ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
843ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    return 0;
844ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON}
845ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
846ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTONstatic int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
847ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON{
848ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    UNUSED_PARAMETER(dev);
849ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    UNUSED_PARAMETER(state);
850ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
851ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    return -ENOSYS;
852ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON}
853ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
854ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTONstatic int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
855ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON{
856ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    UNUSED_PARAMETER(dev);
857ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    UNUSED_PARAMETER(state);
858ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
859ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    return -ENOSYS;
860ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON}
861ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
862ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTONstatic size_t adev_get_input_buffer_size(const struct audio_hw_device *dev,
863ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON                                         const struct audio_config *config)
864ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON{
865ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    UNUSED_PARAMETER(dev);
866ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    UNUSED_PARAMETER(config);
867ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
868ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    return 0;
869ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON}
870ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
871ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTONstatic int adev_open_input_stream(struct audio_hw_device *dev,
872ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON                                  audio_io_handle_t handle,
873ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON                                  audio_devices_t devices,
874ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON                                  struct audio_config *config,
8750ce92df294da2b05fd06c7da49ac5324e68c7a14Guilhem IMBERTON                                  struct audio_stream_in **stream_in,
8760ce92df294da2b05fd06c7da49ac5324e68c7a14Guilhem IMBERTON                                  audio_input_flags_t flags,
8770ce92df294da2b05fd06c7da49ac5324e68c7a14Guilhem IMBERTON                                  const char *address,
8780ce92df294da2b05fd06c7da49ac5324e68c7a14Guilhem IMBERTON                                  audio_source_t source)
879ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON{
880ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    UNUSED_PARAMETER(dev);
881ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    UNUSED_PARAMETER(handle);
882ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    UNUSED_PARAMETER(devices);
883ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    UNUSED_PARAMETER(config);
884ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    UNUSED_PARAMETER(stream_in);
8850ce92df294da2b05fd06c7da49ac5324e68c7a14Guilhem IMBERTON    UNUSED_PARAMETER(flags);
8860ce92df294da2b05fd06c7da49ac5324e68c7a14Guilhem IMBERTON    UNUSED_PARAMETER(address);
8870ce92df294da2b05fd06c7da49ac5324e68c7a14Guilhem IMBERTON    UNUSED_PARAMETER(source);
888ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
889ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    return -ENOSYS;
890ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON}
891ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
892ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTONstatic void adev_close_input_stream(struct audio_hw_device *dev,
893ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON                                   struct audio_stream_in *stream)
894ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON{
895ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    UNUSED_PARAMETER(dev);
896ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    UNUSED_PARAMETER(stream);
897ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON}
898ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
899ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTONstatic int adev_dump(const audio_hw_device_t *device, int fd)
900ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON{
901ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    UNUSED_PARAMETER(device);
902ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    UNUSED_PARAMETER(fd);
903ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
904ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    return 0;
905ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON}
906ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
907ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTONstatic int adev_close(hw_device_t *device)
908ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON{
909ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    free(device);
910ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    return 0;
911ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON}
912ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
913ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTONstatic int adev_open(const hw_module_t* module, const char* name,
914ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON                     hw_device_t** device)
915ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON{
916ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    struct audio_device *adev;
917ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
918ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    ALOGV("%s enter",__func__);
919ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
920ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0)
921ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON        return -EINVAL;
922ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
923ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    adev = calloc(1, sizeof(struct audio_device));
924ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    if (!adev)
925ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON        return -ENOMEM;
926ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
927ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    adev->hw_device.common.tag = HARDWARE_DEVICE_TAG;
928ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    adev->hw_device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
929ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    adev->hw_device.common.module = (struct hw_module_t *) module;
930ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    adev->hw_device.common.close = adev_close;
931ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
932ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    adev->hw_device.init_check = adev_init_check;
933ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    adev->hw_device.set_voice_volume = adev_set_voice_volume;
934ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    adev->hw_device.set_master_volume = adev_set_master_volume;
935ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    adev->hw_device.set_mode = adev_set_mode;
936ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    adev->hw_device.set_mic_mute = adev_set_mic_mute;
937ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    adev->hw_device.get_mic_mute = adev_get_mic_mute;
938ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    adev->hw_device.set_parameters = adev_set_parameters;
939ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    adev->hw_device.get_parameters = adev_get_parameters;
940ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    adev->hw_device.get_input_buffer_size = adev_get_input_buffer_size;
941ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    adev->hw_device.open_output_stream = adev_open_output_stream;
942ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    adev->hw_device.close_output_stream = adev_close_output_stream;
943ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    adev->hw_device.open_input_stream = adev_open_input_stream;
944ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    adev->hw_device.close_input_stream = adev_close_input_stream;
945ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    adev->hw_device.dump = adev_dump;
946ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
947ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    *device = &adev->hw_device.common;
948ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
949ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    ALOGV("%s exit",__func__);
950ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
951ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    return 0;
952ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON}
953ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
954ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTONstatic struct hw_module_methods_t hal_module_methods = {
955ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    .open = adev_open,
956ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON};
957ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON
958ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTONstruct audio_module HAL_MODULE_INFO_SYM = {
959ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    .common = {
960ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON        .tag = HARDWARE_MODULE_TAG,
961ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON        .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
962ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON        .hal_api_version = HARDWARE_HAL_API_VERSION,
963ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON        .id = AUDIO_HARDWARE_MODULE_ID,
964ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON        .name = "tiny_hdmi audio HW HAL",
965ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON        .author = "The Android Open Source Project",
966ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON        .methods = &hal_module_methods,
967ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON    },
968ec31af53afbd9e6e1f9a6270c5046a8e9d14c093Guilhem IMBERTON};
969