Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5a97ddd8 authored by Ashish Jain's avatar Ashish Jain Committed by Gerrit - the friendly Code Review server
Browse files

audio: Enable External HDMI support

-For HDMI compliance, channel status bits
should be configured for the external HDMI chip.
-Hence HAL based on the output format i.e compressed
or LPCM populates the channel_status information
and passes it to the dai-driver which in turn
configures the external HDMI chip.

Change-Id: Ibf192492d259a722070a08f4764fde9498dd268d
parent 7a23789f
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -54,6 +54,7 @@ LOCAL_ADDITIONAL_DEPENDENCIES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr

ifeq ($(strip $(AUDIO_FEATURE_ENABLED_HDMI_EDID)),true)
    LOCAL_SRC_FILES += edid.c
    LOCAL_CFLAGS := -DHDMI_EDID_ENABLED
endif

ifeq ($(strip $(AUDIO_USE_LL_AS_PRIMARY_OUTPUT)),true)
@@ -251,6 +252,12 @@ ifeq ($(strip $(AUDIO_FEATURE_ENABLED_LISTEN)),true)
    LOCAL_SRC_FILES += audio_extn/listen.c
endif

ifeq ($(strip $(AUDIO_FEATURE_ENABLED_EXT_HDMI)),true)
    LOCAL_CFLAGS += -DAUDIO_EXTERNAL_HDMI_ENABLED
    LOCAL_C_INCLUDES += $(TARGET_OUT_HEADERS)/mm-audio/audio-parsers
    LOCAL_SHARED_LIBRARIES += libaudioparsers
endif

ifeq ($(strip $(BOARD_SUPPORTS_SOUND_TRIGGER)),true)
    LOCAL_CFLAGS += -DSOUND_TRIGGER_ENABLED
    LOCAL_CFLAGS += -DSOUND_TRIGGER_PLATFORM_NAME=$(TARGET_BOARD_PLATFORM)
+6 −0
Original line number Diff line number Diff line
@@ -480,4 +480,10 @@ int audio_extn_perf_lock_init(void);
void audio_extn_perf_lock_acquire(void);
void audio_extn_perf_lock_release(void);
#endif /* KPI_OPTIMIZE_ENABLED */

#ifndef AUDIO_EXTERNAL_HDMI_ENABLED
#define setChannelStatus(out, buffer, bytes) (0)
#else
void setChannelStatus(struct stream_out *out, char * buffer, size_t bytes);
#endif
#endif /* AUDIO_EXTN_H */
+146 −0
Original line number Diff line number Diff line
@@ -35,6 +35,10 @@
#include "audio_extn.h"
#include "voice.h"

#ifdef AUDIO_EXTERNAL_HDMI_ENABLED
#include "audio_parsers.h"
#endif

#define AUDIO_OUTPUT_POLICY_VENDOR_CONFIG_FILE "/vendor/etc/audio_output_policy.conf"

#define OUTPUTS_TAG "outputs"
@@ -52,6 +56,21 @@
#define BASE_TABLE_SIZE 64
#define MAX_BASEINDEX_LEN 256

#ifdef AUDIO_EXTERNAL_HDMI_ENABLED
#define PROFESSIONAL        (1<<0)	/* 0 = consumer, 1 = professional */
#define NON_LPCM	    (1<<1)	/* 0 = audio, 1 = non-audio */
#define SR_44100	    (0<<0)	/* 44.1kHz */
#define SR_NOTID	    (1<<0)	/* non indicated */
#define SR_48000	    (2<<0)	/* 48kHz */
#define SR_32000	    (3<<0)	/* 32kHz */
#define SR_22050	    (4<<0)	/* 22.05kHz */
#define SR_24000	    (6<<0)	/* 24kHz */
#define SR_88200	    (8<<0)	/* 88.2kHz */
#define SR_96000	    (10<<0)	/* 96kHz */
#define SR_176400	    (12<<0)	/* 176.4kHz */
#define SR_192000	    (14<<0)	/* 192kHz */

#endif
struct string_to_enum {
    const char *name;
    uint32_t value;
@@ -750,3 +769,130 @@ done:
    outp[k] = '\0';
    return k;
}

#ifdef AUDIO_EXTERNAL_HDMI_ENABLED

void get_default_compressed_channel_status(
                                  unsigned char *channel_status)
{
     int32_t status = 0;
     unsigned char bit_index;
     memset(channel_status,0,24);

     /* block start bit in preamble bit 3 */
     channel_status[0] |= PROFESSIONAL;
     //compre out
     channel_status[0] |= NON_LPCM;
     // sample rate; fixed 48K for default/transcode
     channel_status[3] |= SR_48000;
}

int32_t get_compressed_channel_status(void *audio_stream_data,
                                                   uint32_t audio_frame_size,
                                                   unsigned char *channel_status,
                                                   enum audio_parser_code_type codec_type)
                                                   // codec_type - AUDIO_PARSER_CODEC_AC3
                                                   //            - AUDIO_PARSER_CODEC_DTS
{
     unsigned char *streamPtr;
     int ret = 0;
     streamPtr = (unsigned char *)audio_stream_data;

     if (audio_stream_data == NULL || audio_frame_size == 0) {
         ALOGW("no buffer to get channel status, return default for compress");
         get_default_compressed_channel_status(channel_status);
         return ret;
     }

     memset(channel_status,0,24);
     if(init_audio_parser(streamPtr, audio_frame_size, codec_type) == -1)
     {
         ALOGE("init audio parser failed");
         return -1;
     }
     ret = get_channel_status(channel_status, codec_type);
     return ret;

}

void get_linearpcm_channel_status(uint32_t sampleRate,
                                                  unsigned char *channel_status)
{
     int32_t status = 0;
     unsigned char bit_index;
     memset(channel_status,0,24);
     /* block start bit in preamble bit 3 */
     channel_status[0] |= PROFESSIONAL;
     //LPCM OUT
     channel_status[0] &= ~NON_LPCM;

     switch (sampleRate) {
         case 8000:
         case 11025:
         case 12000:
         case 16000:
         case 22050:
             channel_status[3] |= SR_NOTID;
         case 24000:
             channel_status[3] |= SR_24000;
             break;
         case 32000:
             channel_status[3] |= SR_32000;
             break;
         case 44100:
             channel_status[3] |= SR_44100;
             break;
         case 48000:
             channel_status[3] |= SR_48000;
             break;
         case 88200:
             channel_status[3] |= SR_88200;
             break;
         case 96000:
             channel_status[3] |= SR_96000;
             break;
         case 176400:
             channel_status[3] |= SR_176400;
             break;
         case 192000:
            channel_status[3] |= SR_192000;
             break;
         default:
             ALOGV("Invalid sample_rate %u\n", sampleRate);
             status = -1;
             break;
     }
}

void setChannelStatus(struct stream_out *out, char * buffer, size_t bytes)
{
    unsigned char channel_status[24]={0};
    struct snd_aes_iec958 iec958;
    const char *mixer_ctl_name = "IEC958 Playback PCM Stream";
    struct mixer_ctl *ctl;
    int i=0;
    if (audio_extn_is_dolby_format(out->format) &&
        /*TODO:Extend code to support DTS passthrough*/
        /*set compressed channel status bits*/
        audio_extn_dolby_is_passthrough_stream(out->flags)){
        get_compressed_channel_status(buffer, bytes, channel_status, AUDIO_PARSER_CODEC_AC3);
    } else {
        /*set channel status bit for LPCM*/
        get_linearpcm_channel_status(out->sample_rate, channel_status);
    }

    memcpy(iec958.status, channel_status,sizeof(iec958.status));
    ctl = mixer_get_ctl_by_name(out->dev->mixer, mixer_ctl_name);
    if (!ctl) {
            ALOGE("%s: Could not get ctl for mixer cmd - %s",
                  __func__, mixer_ctl_name);
            return;
    }
    if (mixer_ctl_set_array(ctl, &iec958, sizeof(iec958)) < 0) {
        ALOGE("%s: Could not set channel status for ext HDMI ",
              __func__);
        return;
    }

}
#endif
+9 −1
Original line number Diff line number Diff line
@@ -564,6 +564,9 @@ int disable_snd_device(struct audio_device *adev,
            audio_route_reset_and_update_path(adev->audio_route, device_name);
        }

        if (snd_device == SND_DEVICE_OUT_HDMI)
            adev->mChannelStatusSet = false;

        audio_extn_dev_arbi_release(snd_device);
        audio_extn_sound_trigger_update_device_status(snd_device,
                                        ST_EVENT_SND_DEVICE_FREE);
@@ -2119,6 +2122,11 @@ static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
        }
    }

    if (adev->mChannelStatusSet == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
        setChannelStatus(out, buffer, bytes);
        adev->mChannelStatusSet = true;
    }

    if (is_offload_usecase(out->usecase)) {
        ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
        if (out->send_new_metadata) {
@@ -2775,7 +2783,6 @@ static int adev_open_output_stream(struct audio_hw_device *dev,
    out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
    out->non_blocking = 0;
    out->use_small_bufs = false;

    /* Init use case and pcm_config */
    if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT) &&
        !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
@@ -3657,6 +3664,7 @@ static int adev_open(const hw_module_t *module, const char *name,
    list_init(&adev->usecase_list);
    adev->cur_wfd_channels = 2;
    adev->offload_usecases_state = 0;
    adev->mChannelStatusSet = false;

    pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
    adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
+1 −0
Original line number Diff line number Diff line
@@ -311,6 +311,7 @@ struct audio_device {
    int snd_card;
    unsigned int cur_codec_backend_samplerate;
    unsigned int cur_codec_backend_bit_width;
    bool mChannelStatusSet;
    void *platform;
    unsigned int offload_usecases_state;
    void *visualizer_lib;
Loading