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

Commit 4e022540 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "hal: add audio notification acknowledge feature" into av-userspace.lnx.1.0-dev.1.0

parents db421ad1 00611c3c
Loading
Loading
Loading
Loading
+120 −0
Original line number Diff line number Diff line
@@ -42,6 +42,7 @@
#include <stdlib.h>
#include <errno.h>
#include <dlfcn.h>
#include <fcntl.h>
#include <cutils/properties.h>
#include <cutils/log.h>

@@ -82,6 +83,124 @@ static struct audio_extn_module aextnmod = {
#define AUDIO_PARAMETER_OFFLOAD_NUM_ACTIVE "offload_num_active"
#define AUDIO_PARAMETER_HPX            "HPX"

/*
* update sysfs node hdmi_audio_cb to enable notification acknowledge feature
* bit(5) set to 1 to enable this feature
* bit(4) set to 1 to enable acknowledgement
* this is done only once at the first connect event
*
* bit(0) set to 1 when HDMI cable is connected
* bit(0) set to 0 when HDMI cable is disconnected
* this is done when device switch happens by setting audioparamter
*/

#define HDMI_PLUG_STATUS_NOTIFY_ENABLE 0x30

static ssize_t update_sysfs_node(const char *path, const char *data, size_t len)
{
    ssize_t err = 0;
    int fd = -1;

    err = access(path, W_OK);
    if (!err) {
        fd = open(path, O_WRONLY);
        errno = 0;
        err = write(fd, data, len);
        if (err < 0) {
            err = -errno;
        }
        close(fd);
    } else {
        ALOGE("%s: Failed to access path: %s error: %s",
                __FUNCTION__, path, strerror(errno));
        err = -errno;
    }

    return err;
}

static int get_hdmi_sysfs_node_index()
{
    static int node_index = -1;
    char fbvalue[80] = {0};
    char fbpath[80] = {0};
    int i = 0;
    FILE *hdmi_fp = NULL;

    if(node_index >= 0) {
        //hdmi sysfs node will not change so we just need to get the index once.
        ALOGV("HDMI sysfs node is at fb%d", node_index);
        return node_index;
    }

    for(i = 0; i < 3; i++) {
        snprintf(fbpath, sizeof(fbpath),
                  "/sys/class/graphics/fb%d/msm_fb_type", i);
        hdmi_fp = fopen(fbpath, "r");
        if(hdmi_fp) {
            fread(fbvalue, sizeof(char), 80, hdmi_fp);
            if(strncmp(fbvalue, "dtv panel", strlen("dtv panel")) == 0) {
                node_index = i;
                ALOGV("HDMI is at fb%d",i);
                fclose(hdmi_fp);
                return node_index;
            }
            fclose(hdmi_fp);
        } else {
            ALOGE("Failed to open fb node %d",i);
        }
    }

    return -1;
}

static int update_hdmi_sysfs_node(int node_value)
{
    char hdmi_ack_path[80] = {0};
    char hdmi_ack_value[3] = {0};
    int index, ret = -1;

    index = get_hdmi_sysfs_node_index();

    if (index >= 0) {
        snprintf(hdmi_ack_value, sizeof(hdmi_ack_value), "%d", node_value);
        snprintf(hdmi_ack_path, sizeof(hdmi_ack_path),
                  "/sys/class/graphics/fb%d/hdmi_audio_cb", index);

        ret = update_sysfs_node(hdmi_ack_path, hdmi_ack_value,
                sizeof(hdmi_ack_value));

        ALOGI("update hdmi_audio_cb at fb[%d] to:[%d] %s",
            index, node_value, (ret >= 0) ? "success":"fail");
    }

    return ret;
}

static void check_and_set_hdmi_connection_status(struct str_parms *parms)
{
    char value[32] = {0};
    static bool is_hdmi_sysfs_node_init = false;

    if (str_parms_get_str(parms, "connect", value, sizeof(value)) >= 0
            && (atoi(value) & AUDIO_DEVICE_OUT_HDMI)) {
        //params = "connect=1024" for HDMI connection.
        if (is_hdmi_sysfs_node_init == false) {
            is_hdmi_sysfs_node_init = true;
            update_hdmi_sysfs_node(HDMI_PLUG_STATUS_NOTIFY_ENABLE);
        }
        update_hdmi_sysfs_node(1);
    } else if(str_parms_get_str(parms, "disconnect", value, sizeof(value)) >= 0
            && (atoi(value) & AUDIO_DEVICE_OUT_HDMI)){
        //params = "disconnect=1024" for HDMI disconnection.
        update_hdmi_sysfs_node(0);
    } else {
        // handle hdmi devices only
        return;
    }
}


#ifndef FM_POWER_OPT
#define audio_extn_fm_set_parameters(adev, parms) (0)
#else
@@ -574,6 +693,7 @@ void audio_extn_set_parameters(struct audio_device *adev,
   audio_extn_hpx_set_parameters(adev, parms);
   audio_extn_pm_set_parameters(parms);
   audio_extn_source_track_set_parameters(adev, parms);
   check_and_set_hdmi_connection_status(parms);
   if (adev->offload_effects_set_parameters != NULL)
       adev->offload_effects_set_parameters(parms);
}