Android-x86
Fork
Spenden

  • R/O
  • HTTP
  • SSH
  • HTTPS

hardware-intel-audio_media: Commit

hardware/intel/audio_media


Commit MetaInfo

Revisionec31af53afbd9e6e1f9a6270c5046a8e9d14c093 (tree)
Zeit2014-08-02 04:22:44
AutorGuilhem IMBERTON <guilhem.imberton@inte...>
CommiterIon Alberdi

Log Message

Squashed commit for Google

BZ: 214804

Based on save/r44c_fugu_before_reset_bz214804

Change-Id: I9f38c7048bea5f554512519121d91927110cb6bc
Reviewed-on: https://android.intel.com/224231
Reviewed-by: Imberton, Guilhem <guilhem.imberton@intel.com>
Tested-by: Imberton, Guilhem <guilhem.imberton@intel.com>

Ändern Zusammenfassung

Diff

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