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

Commit 3190dc6a authored by Haynes Mathew George's avatar Haynes Mathew George Committed by Ethan Chen
Browse files

audio: extend platform parser

Extend platform parser with support for additional sections.
Supported sections now include acdb ids, pcm device ids and backend names.

Change-Id: Idfbc8a8bb490606686436c107db5b0c7d636ccbe
parent 07340b16
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -578,6 +578,15 @@ void audio_extn_spkr_prot_init(void *adev)
        handle.thermal_handle = NULL;
        handle.spkr_prot_enable = false;
    }

    if (handle.spkr_prot_enable) {
        char platform[PROPERTY_VALUE_MAX];
        property_get("ro.board.platform", platform, "");
        if (!strncmp("apq8084", platform, sizeof("apq8084"))) {
            platform_set_snd_device_backend(SND_DEVICE_OUT_VOICE_SPEAKER,
                                            "speaker-protected");
        }
    }
}

int audio_extn_spkr_prot_start_processing(snd_device_t snd_device)
+17 −0
Original line number Diff line number Diff line
@@ -924,3 +924,20 @@ bool platform_listen_update_status(snd_device_t snd_device __unused)
{
     return false;
}

int platform_get_usecase_index(const char * usecase __unused)
{
    return -ENOSYS;
}

int platform_set_usecase_pcm_id(audio_usecase_t usecase __unused, int32_t type __unused,
                                int32_t pcm_id __unused)
{
    return -ENOSYS;
}

int platform_set_snd_device_backend(snd_device_t snd_device __unused,
                                    const char * backend __unused)
{
    return -ENOSYS;
}
+136 −41
Original line number Diff line number Diff line
@@ -122,7 +122,7 @@ struct platform_data {
    struct csd_data *csd;
};

static const int pcm_device_table[AUDIO_USECASE_MAX][2] = {
static int pcm_device_table[AUDIO_USECASE_MAX][2] = {
    [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {DEEP_BUFFER_PCM_DEVICE,
                                            DEEP_BUFFER_PCM_DEVICE},
    [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {LOWLATENCY_PCM_DEVICE,
@@ -329,7 +329,7 @@ static int acdb_device_table[SND_DEVICE_MAX] = {
    [SND_DEVICE_IN_CAPTURE_VI_FEEDBACK] = 102,
};

struct snd_device_index {
struct name_to_index {
    char name[100];
    unsigned int index;
};
@@ -337,7 +337,7 @@ struct snd_device_index {
#define TO_NAME_INDEX(X)   #X, X

/* Used to get index from parsed sting */
struct snd_device_index snd_device_name_index[SND_DEVICE_MAX] = {
static struct name_to_index snd_device_name_index[SND_DEVICE_MAX] = {
    {TO_NAME_INDEX(SND_DEVICE_OUT_HANDSET)},
    {TO_NAME_INDEX(SND_DEVICE_OUT_SPEAKER)},
    {TO_NAME_INDEX(SND_DEVICE_OUT_SPEAKER_REVERSE)},
@@ -415,6 +415,26 @@ struct snd_device_index snd_device_name_index[SND_DEVICE_MAX] = {
    {TO_NAME_INDEX(SND_DEVICE_IN_VOIP_HEADSET_MIC)},
};

static char * backend_table[SND_DEVICE_MAX] = {0};

static struct name_to_index usecase_name_index[AUDIO_USECASE_MAX] = {
    {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_DEEP_BUFFER)},
    {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_LOW_LATENCY)},
    {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_MULTI_CH)},
    {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_OFFLOAD)},
    {TO_NAME_INDEX(USECASE_AUDIO_RECORD)},
    {TO_NAME_INDEX(USECASE_AUDIO_RECORD_LOW_LATENCY)},
    {TO_NAME_INDEX(USECASE_VOICE_CALL)},
    {TO_NAME_INDEX(USECASE_VOICE2_CALL)},
    {TO_NAME_INDEX(USECASE_VOLTE_CALL)},
    {TO_NAME_INDEX(USECASE_QCHAT_CALL)},
    {TO_NAME_INDEX(USECASE_VOWLAN_CALL)},
    {TO_NAME_INDEX(USECASE_INCALL_REC_UPLINK)},
    {TO_NAME_INDEX(USECASE_INCALL_REC_DOWNLINK)},
    {TO_NAME_INDEX(USECASE_INCALL_REC_UPLINK_AND_DOWNLINK)},
    {TO_NAME_INDEX(USECASE_AUDIO_HFP_SCO)},
};

#define DEEP_BUFFER_PLATFORM_DELAY (29*1000LL)
#define LOW_LATENCY_PLATFORM_DELAY (13*1000LL)

@@ -551,6 +571,32 @@ void close_csd_client(struct csd_data *csd)
    }
}

static void set_platform_defaults(struct platform_data * my_data)
{
    int32_t dev;
    for (dev = 0; dev < SND_DEVICE_MAX; dev++) {
        backend_table[dev] = NULL;
    }

    // TBD - do these go to the platform-info.xml file.
    // will help in avoiding strdups here
    backend_table[SND_DEVICE_IN_BT_SCO_MIC] = strdup("bt-sco");
    backend_table[SND_DEVICE_IN_BT_SCO_MIC_WB] = strdup("bt-sco-wb");
    backend_table[SND_DEVICE_OUT_BT_SCO] = strdup("bt-sco");
    backend_table[SND_DEVICE_OUT_BT_SCO_WB] = strdup("bt-sco-wb");
    backend_table[SND_DEVICE_OUT_HDMI] = strdup("hdmi");
    backend_table[SND_DEVICE_OUT_SPEAKER_AND_HDMI] = strdup("speaker-and-hdmi");
    backend_table[SND_DEVICE_OUT_VOICE_TX] = strdup("afe-proxy");
    backend_table[SND_DEVICE_IN_VOICE_RX] = strdup("afe-proxy");
    backend_table[SND_DEVICE_OUT_AFE_PROXY] = strdup("afe-proxy");
    backend_table[SND_DEVICE_OUT_USB_HEADSET] = strdup("usb-headphones");
    backend_table[SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET] =
        strdup("speaker-and-usb-headphones");
    backend_table[SND_DEVICE_IN_USB_HEADSET_MIC] = strdup("usb-headset-mic");
    backend_table[SND_DEVICE_IN_CAPTURE_FM] = strdup("capture-fm");
    backend_table[SND_DEVICE_OUT_TRANSMISSION_FM] = strdup("transmission-fm");
}

void *platform_init(struct audio_device *adev)
{
    char platform[PROPERTY_VALUE_MAX];
@@ -687,6 +733,8 @@ void *platform_init(struct audio_device *adev)
            my_data->acdb_init();
    }

    set_platform_defaults(my_data);

    /* Initialize ACDB ID's */
    platform_info_init();

@@ -719,6 +767,14 @@ void platform_deinit(void *platform)
    hw_info_deinit(my_data->hw_info);
    close_csd_client(my_data->csd);

    int32_t dev;
    for (dev = 0; dev < SND_DEVICE_MAX; dev++) {
        if (backend_table[dev]) {
            free(backend_table[dev]);
            backend_table[dev]= NULL;
        }
    }

    free(platform);
    /* deinit usb */
    audio_extn_usb_deinit();
@@ -750,35 +806,17 @@ int platform_get_snd_device_name_extn(void *platform, snd_device_t snd_device,

void platform_add_backend_name(char *mixer_path, snd_device_t snd_device)
{
    if (snd_device == SND_DEVICE_IN_BT_SCO_MIC)
        strlcat(mixer_path, " bt-sco", MIXER_PATH_MAX_LENGTH);
    else if (snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB)
        strlcat(mixer_path, " bt-sco-wb", MIXER_PATH_MAX_LENGTH);
    else if(snd_device == SND_DEVICE_OUT_BT_SCO)
        strlcat(mixer_path, " bt-sco", MIXER_PATH_MAX_LENGTH);
    else if(snd_device == SND_DEVICE_OUT_BT_SCO_WB)
        strlcat(mixer_path, " bt-sco-wb", MIXER_PATH_MAX_LENGTH);
    else if (snd_device == SND_DEVICE_OUT_HDMI)
        strlcat(mixer_path, " hdmi", MIXER_PATH_MAX_LENGTH);
    else if (snd_device == SND_DEVICE_OUT_SPEAKER_AND_HDMI)
        strcat(mixer_path, " speaker-and-hdmi");
    else if (snd_device == SND_DEVICE_OUT_VOICE_TX)
        strlcat(mixer_path, " afe-proxy", MIXER_PATH_MAX_LENGTH);
    else if (snd_device == SND_DEVICE_IN_VOICE_RX)
        strlcat(mixer_path, " afe-proxy", MIXER_PATH_MAX_LENGTH);
    else if (snd_device == SND_DEVICE_OUT_AFE_PROXY)
        strlcat(mixer_path, " afe-proxy", MIXER_PATH_MAX_LENGTH);
    else if (snd_device == SND_DEVICE_OUT_USB_HEADSET)
        strlcat(mixer_path, " usb-headphones", MIXER_PATH_MAX_LENGTH);
    else if (snd_device == SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET)
        strlcat(mixer_path, " speaker-and-usb-headphones",
                MIXER_PATH_MAX_LENGTH);
    else if (snd_device == SND_DEVICE_IN_USB_HEADSET_MIC)
        strlcat(mixer_path, " usb-headset-mic", MIXER_PATH_MAX_LENGTH);
    else if (snd_device == SND_DEVICE_IN_CAPTURE_FM)
        strlcat(mixer_path, " capture-fm", MIXER_PATH_MAX_LENGTH);
    else if (snd_device == SND_DEVICE_OUT_TRANSMISSION_FM)
        strlcat(mixer_path, " transmission-fm", MIXER_PATH_MAX_LENGTH);
    if ((snd_device < SND_DEVICE_MIN) || (snd_device >= SND_DEVICE_MAX)) {
        ALOGE("%s: Invalid snd_device = %d", __func__, snd_device);
        return;
    }

    const char * suffix = backend_table[snd_device];

    if (suffix != NULL) {
        strlcat(mixer_path, " ", MIXER_PATH_MAX_LENGTH);
        strlcat(mixer_path, suffix, MIXER_PATH_MAX_LENGTH);
    }
}

int platform_get_pcm_device_id(audio_usecase_t usecase, int device_type)
@@ -791,30 +829,51 @@ int platform_get_pcm_device_id(audio_usecase_t usecase, int device_type)
    return device_id;
}

int platform_get_snd_device_index(char *snd_device_index_name)
static int find_index(struct name_to_index * table, int32_t len, const char * name)
{
    int ret = 0;
    int i;
    int32_t i;

    if (table == NULL) {
        ALOGE("%s: table is NULL", __func__);
        ret = -ENODEV;
        goto done;
    }

    if (snd_device_index_name == NULL) {
        ALOGE("%s: snd_device_index_name is NULL", __func__);
    if (name == NULL) {
        ALOGE("null key");
        ret = -ENODEV;
        goto done;
    }

    for (i=0; i < SND_DEVICE_MAX; i++) {
        if(strcmp(snd_device_name_index[i].name, snd_device_index_name) == 0) {
            ret = snd_device_name_index[i].index;
    for (i=0; i < len; i++) {
        const char* tn = table[i].name;
        int32_t len = strlen(tn);
        if (strncmp(tn, name, len) == 0) {
            if (strlen(name) != len) {
                continue; // substring
            }
            ret = table[i].index;
            goto done;
        }
    }
    ALOGE("%s: Could not find index for snd_device_index_name = %s",
            __func__, snd_device_index_name);
    ALOGE("%s: Could not find index for name = %s",
            __func__, name);
    ret = -ENODEV;
done:
    return ret;
}

int platform_get_snd_device_index(char *device_name)
{
    return find_index(snd_device_name_index, SND_DEVICE_MAX, device_name);
}

int platform_get_usecase_index(const char *usecase_name)
{
    return find_index(usecase_name_index, AUDIO_USECASE_MAX, usecase_name);
}

int platform_set_snd_device_acdb_id(snd_device_t snd_device, unsigned int acdb_id)
{
    int ret = 0;
@@ -1955,3 +2014,39 @@ uint32_t platform_get_pcm_offload_buffer_size(audio_offload_info_t* info)
    return fragment_size;
}

int platform_set_snd_device_backend(snd_device_t device, const char *backend)
{
    int ret = 0;

    if ((device < SND_DEVICE_MIN) || (device >= SND_DEVICE_MAX)) {
        ALOGE("%s: Invalid snd_device = %d",
            __func__, device);
        ret = -EINVAL;
        goto done;
    }

    if (backend_table[device]) {
        free(backend_table[device]);
    }
    backend_table[device] = strdup(backend);
done:
    return ret;
}

int platform_set_usecase_pcm_id(audio_usecase_t usecase, int32_t type, int32_t pcm_id)
{
    int ret = 0;
    if ((usecase <= USECASE_INVALID) || (usecase >= AUDIO_USECASE_MAX)) {
        ALOGE("%s: invalid usecase case idx %d", __func__, usecase);
        ret = -EINVAL;
        goto done;
    }

    if ((type != 0) && (type != 1)) {
        ALOGE("%s: invalid usecase type", __func__);
        ret = -EINVAL;
    }
    pcm_device_table[usecase][type] = pcm_id;
done:
    return ret;
}
+7 −2
Original line number Diff line number Diff line
@@ -62,11 +62,16 @@ int platform_update_usecase_from_source(int source, audio_usecase_t usecase);

bool platform_listen_update_status(snd_device_t snd_device);

int platform_set_snd_device_backend(snd_device_t snd_device, const char * backend);

/* From platform_info_parser.c */
int platform_info_init(void);

struct audio_offload_info_t;
uint32_t platform_get_compress_offload_buffer_size(audio_offload_info_t* info);
uint32_t platform_get_pcm_offload_buffer_size(audio_offload_info_t* info);

/* From platform_info_parser.c */
int platform_info_init(void);
int platform_get_usecase_index(const char * usecase);
int platform_set_usecase_pcm_id(audio_usecase_t usecase, int32_t type, int32_t pcm_id);

#endif // AUDIO_PLATFORM_API_H
+169 −10
Original line number Diff line number Diff line
@@ -41,7 +41,137 @@
#define PLATFORM_INFO_XML_PATH      "/system/etc/audio_platform_info.xml"
#define BUF_SIZE                    1024

static void process_device(const XML_Char **attr)
typedef enum {
    ROOT,
    ACDB,
    PCM_ID,
    BACKEND_NAME,
} section_t;

typedef void (* section_process_fn)(const XML_Char **attr);

static void process_acdb_id(const XML_Char **attr);
static void process_pcm_id(const XML_Char **attr);
static void process_backend_name(const XML_Char **attr);
static void process_root(const XML_Char **attr);

static section_process_fn section_table[] = {
    [ROOT] = process_root,
    [ACDB] = process_acdb_id,
    [PCM_ID] = process_pcm_id,
    [BACKEND_NAME] = process_backend_name,
};

static section_t section;

/*
 * <audio_platform_info>
 * <acdb_ids>
 * <device name="???" acdb_id="???"/>
 * ...
 * ...
 * </acdb_ids>
 * <backend_names>
 * <device name="???" backend="???"/>
 * ...
 * ...
 * </backend_names>
 * <pcm_ids>
 * <usecase name="???" type="in/out" id="???"/>
 * ...
 * ...
 * </pcm_ids>
 * </audio_platform_info>
 */

static void process_root(const XML_Char **attr __unused)
{
}

/* mapping from usecase to pcm dev id */
static void process_pcm_id(const XML_Char **attr)
{
    int index;

    if (strcmp(attr[0], "name") != 0) {
        ALOGE("%s: 'name' not found, no ACDB ID set!", __func__);
        goto done;
    }

    index = platform_get_usecase_index((char *)attr[1]);
    if (index < 0) {
        ALOGE("%s: usecase %s not found!",
              __func__, attr[1]);
        goto done;
    }

    if (strcmp(attr[2], "type") != 0) {
        ALOGE("%s: usecase type not mentioned", __func__);
        goto done;
    }

    int type = -1;

    if (!strcasecmp((char *)attr[3], "in")) {
        type = 1;
    } else if (!strcasecmp((char *)attr[3], "out")) {
        type = 0;
    } else {
        ALOGE("%s: type must be IN or OUT", __func__);
        goto done;
    }

    if (strcmp(attr[4], "id") != 0) {
        ALOGE("%s: usecase id not mentioned", __func__);
        goto done;
    }

    int id = atoi((char *)attr[5]);

    if (platform_set_usecase_pcm_id(index, type, id) < 0) {
        ALOGE("%s: usecase %s type %d id %d was not set!",
              __func__, attr[1], type, id);
        goto done;
    }

done:
    return;
}

/* backend to be used for a device */
static void process_backend_name(const XML_Char **attr)
{
    int index;

    if (strcmp(attr[0], "name") != 0) {
        ALOGE("%s: 'name' not found, no ACDB ID set!", __func__);
        goto done;
    }

    index = platform_get_snd_device_index((char *)attr[1]);
    if (index < 0) {
        ALOGE("%s: Device %s not found, no ACDB ID set!",
              __func__, attr[1]);
        goto done;
    }

    if (strcmp(attr[2], "backend") != 0) {
        ALOGE("%s: Device %s has no backend set!",
              __func__, attr[1]);
        goto done;
    }

    if (platform_set_snd_device_backend(index, attr[3]) < 0) {
        ALOGE("%s: Device %s backend %s was not set!",
              __func__, attr[1], attr[3]);
        goto done;
    }

done:
    return;
}

static void process_acdb_id(const XML_Char **attr)
{
    int index;

@@ -64,8 +194,8 @@ static void process_device(const XML_Char **attr)
    }

    if (platform_set_snd_device_acdb_id(index, atoi((char *)attr[3])) < 0) {
        ALOGE("%s: Device %s in %s, ACDB ID %d was not set!",
              __func__, attr[1], PLATFORM_INFO_XML_PATH, atoi((char *)attr[3]));
        ALOGE("%s: Device %s, ACDB ID %d was not set!",
              __func__, attr[1], atoi((char *)attr[3]));
        goto done;
    }

@@ -73,23 +203,50 @@ done:
    return;
}

static void start_tag(void *userdata, const XML_Char *tag_name,
static void start_tag(void *userdata __unused, const XML_Char *tag_name,
                      const XML_Char **attr)
{
    const XML_Char              *attr_name = NULL;
    const XML_Char              *attr_value = NULL;
    unsigned int                i;

    if (strcmp(tag_name, "device") == 0)
        process_device(attr);
    if (strcmp(tag_name, "acdb_ids") == 0) {
        section = ACDB;
    } else if (strcmp(tag_name, "pcm_ids") == 0) {
        section = PCM_ID;
    } else if (strcmp(tag_name, "backend_names") == 0) {
        section = BACKEND_NAME;
    } else if (strcmp(tag_name, "device") == 0) {
        if ((section != ACDB) && (section != BACKEND_NAME)) {
            ALOGE("device tag only supported for acdb/backend names");
            return;
        }

        /* call into process function for the current section */
        section_process_fn fn = section_table[section];
        fn(attr);
    } else if (strcmp(tag_name, "usecase") == 0) {
        if (section != PCM_ID) {
            ALOGE("usecase tag only supported with PCM_ID section");
            return;
        }

        section_process_fn fn = section_table[PCM_ID];
        fn(attr);
    }

    return;
}

static void end_tag(void *userdata __unused,
                    const XML_Char *tag_name __unused)
static void end_tag(void *userdata __unused, const XML_Char *tag_name)
{

    if (strcmp(tag_name, "acdb_ids") == 0) {
        section = ROOT;
    } else if (strcmp(tag_name, "pcm_ids") == 0) {
        section = ROOT;
    } else if (strcmp(tag_name, "backend_names") == 0) {
        section = ROOT;
    }
}

int platform_info_init(void)
@@ -101,6 +258,8 @@ int platform_info_init(void)
    void            *buf;

    file = fopen(PLATFORM_INFO_XML_PATH, "r");
    section = ROOT;

    if (!file) {
        ALOGD("%s: Failed to open %s, using defaults.",
            __func__, PLATFORM_INFO_XML_PATH);
Loading