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

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

Merge "hal: Support Multichannel Speaker playback"

parents b8c55cef 5d57defb
Loading
Loading
Loading
Loading
+8 −1
Original line number Diff line number Diff line
@@ -990,7 +990,14 @@ static int send_app_type_cfg_for_device(struct audio_device *adev,
        if (usecase->id == USECASE_AUDIO_PLAYBACK_VOIP) {
            usecase->stream.out->app_type_cfg.sample_rate = usecase->stream.out->sample_rate;
        } else if (usecase->stream.out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
            if (platform_spkr_use_default_sample_rate(adev->platform)) {
                 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
            } else {
                 platform_check_and_update_copp_sample_rate(adev->platform, snd_device,
                                      usecase->stream.out->sample_rate,
                                      &usecase->stream.out->app_type_cfg.sample_rate);
            }

        } else if ((snd_device == SND_DEVICE_OUT_HDMI ||
                    snd_device == SND_DEVICE_OUT_USB_HEADSET ||
                    snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
+27 −3
Original line number Diff line number Diff line
@@ -4502,6 +4502,15 @@ static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
                audio_format_t dst_format = out->hal_op_format;
                audio_format_t src_format = out->hal_ip_format;

                /* prevent division-by-zero */
                uint32_t bitwidth_src = format_to_bitwidth_table[src_format];
                uint32_t bitwidth_dst = format_to_bitwidth_table[dst_format];
                if ((bitwidth_src == 0) || (bitwidth_dst == 0)) {
                    ALOGE("%s: Error bitwidth == 0", __func__);
                    ATRACE_END();
                    return -EINVAL;
                }

                uint32_t frames = bytes / format_to_bitwidth_table[src_format];
                uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];

@@ -4642,10 +4651,18 @@ exit:
            out->standby = true;
        }
        out_on_error(&out->stream.common);
        if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
            usleep((uint64_t)bytes * 1000000 / audio_stream_out_frame_size(stream) /
                            out_get_sample_rate(&out->stream.common));
        if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
            /* prevent division-by-zero */
            uint32_t stream_size = audio_stream_out_frame_size(stream);
            uint32_t srate = out_get_sample_rate(&out->stream.common);

            if ((stream_size == 0) || (srate == 0)) {
                ALOGE("%s: stream_size= %d, srate = %d", __func__, stream_size, srate);
                ATRACE_END();
                return -EINVAL;
             }
             usleep((uint64_t)bytes * 1000000 / stream_size / srate);
        }
        if (audio_extn_passthru_is_passthrough_stream(out)) {
                ALOGE("%s: write error, ret = %zd", __func__, ret);
                ATRACE_END();
@@ -7079,6 +7096,13 @@ static int adev_open_input_stream(struct audio_hw_device *dev,
                                            config->format,
                                            channel_count,
                                            is_low_latency);
            /* prevent division-by-zero */
            if (frame_size == 0) {
                ALOGE("%s: Error frame_size==0", __func__);
                ret = -EINVAL;
                goto err_open;
            }

            in->config.period_size = buffer_size / frame_size;

            if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
+21 −0
Original line number Diff line number Diff line
@@ -57,6 +57,27 @@
#define PCM_CHANNEL_FRC  14  /* Front right of center.                        */
#define PCM_CHANNEL_RLC  15  /* Rear left of center.                          */
#define PCM_CHANNEL_RRC  16  /* Rear right of center.                         */
#define PCM_CHANNEL_LFE2 17  /* Second low frequency channel.                 */
#define PCM_CHANNEL_SL   18  /* Side left channel.                            */
#define PCM_CHANNEL_SR   19  /* Side right channel.                           */
#define PCM_CHANNEL_TFL  20  /* Top front left channel.                       */
#define PCM_CHANNEL_LVH  20  /* Left vertical height channel.                 */
#define PCM_CHANNEL_TFR  21  /* Top front right channel.                      */
#define PCM_CHANNEL_RVH  21  /* Right vertical height channel.                */
#define PCM_CHANNEL_TC   22  /* Top center channel.                           */
#define PCM_CHANNEL_TBL  23  /* Top back left channel.                        */
#define PCM_CHANNEL_TBR  24  /* Top back right channel.                       */
#define PCM_CHANNEL_TSL  25  /* Top side left channel.                        */
#define PCM_CHANNEL_TSR  26  /* Top side right channel.                       */
#define PCM_CHANNEL_TBC  27  /* Top back center channel.                      */
#define PCM_CHANNEL_BFC  28  /* Bottom front center channel.                  */
#define PCM_CHANNEL_BFL  29  /* Bottom front left channel.                    */
#define PCM_CHANNEL_BFR  30  /* Bottom front right channel.                   */
#define PCM_CHANNEL_LW   31  /* Left wide channel.                            */
#define PCM_CHANNEL_RW   32  /* Right wide channel.                           */
#define PCM_CHANNEL_LSD  33  /* Left side direct channel.                     */
#define PCM_CHANNEL_RSD  34  /* Right side direct channel.                    */


#define MAX_HDMI_CHANNEL_CNT 8

hal/msm8916/platform.c

100755 → 100644
+7 −0
Original line number Diff line number Diff line
@@ -298,6 +298,7 @@ struct platform_data {
    struct acdb_init_data_v4 acdb_init_data;
    bool use_generic_handset;
    struct  spkr_device_chmap *spkr_ch_map;
    bool use_sprk_default_sample_rate;
};

struct  spkr_device_chmap {
@@ -2290,6 +2291,7 @@ void *platform_init(struct audio_device *adev)
    my_data->hw_dep_fd = -1;
    my_data->mono_speaker = SPKR_1;
    my_data->spkr_ch_map = NULL;
    my_data->use_sprk_default_sample_rate = true;

    be_dai_name_table = NULL;

@@ -7385,6 +7387,11 @@ void platform_cache_edid(void * platform)
    platform_get_edid_info(platform);
}

bool platform_spkr_use_default_sample_rate(void *platform) {
    struct platform_data *my_data = (struct platform_data *)platform;
    return my_data->use_sprk_default_sample_rate;
}

void platform_invalidate_backend_config(void * platform,snd_device_t snd_device)
{
    struct platform_data *my_data = (struct platform_data *)platform;
+106 −12
Original line number Diff line number Diff line
@@ -276,6 +276,7 @@ struct platform_data {
    struct acdb_init_data_v4 acdb_init_data;
    bool use_generic_handset;
    struct  spkr_device_chmap *spkr_ch_map;
    bool use_sprk_default_sample_rate;
};

struct  spkr_device_chmap {
@@ -2096,7 +2097,7 @@ void *platform_init(struct audio_device *adev)
    my_data->mono_speaker = SPKR_1;
    my_data->speaker_lr_swap = false;
    my_data->spkr_ch_map = NULL;

    my_data->use_sprk_default_sample_rate = true;
    be_dai_name_table = NULL;

    property_get("ro.vendor.audio.sdk.fluencetype", my_data->fluence_cap, "");
@@ -2182,6 +2183,15 @@ void *platform_init(struct audio_device *adev)
    else
        platform_info_init(PLATFORM_INFO_XML_PATH, my_data, PLATFORM);

    /* CSRA devices support multiple sample rates via I2S at spkr out */
    if (!strncmp(snd_card_name, "qcs405-csra", strlen("qcs405-csra"))) {
        ALOGE("%s: soundcard: %s supports multiple sample rates", __func__, snd_card_name);
        my_data->use_sprk_default_sample_rate = false;
    } else {
        my_data->use_sprk_default_sample_rate = true;
        ALOGE("%s: soundcard: %s supports only default sample rate", __func__, snd_card_name);
    }

    my_data->voice_feature_set = VOICE_FEATURE_SET_DEFAULT;
    my_data->acdb_handle = dlopen(LIB_ACDB_LOADER, RTLD_NOW);
    if (my_data->acdb_handle == NULL) {
@@ -2437,11 +2447,18 @@ acdb_init_fail:

    } else {
        if (!strncmp(snd_card_name, "qcs405", strlen("qcs405"))) {

            if (!strncmp(snd_card_name, "qcs405-csra", strlen("qcs405-csra"))) {
               my_data->current_backend_cfg[DEFAULT_CODEC_BACKEND].bitwidth_mixer_ctl =
                   strdup("PRIM_MI2S_RX Format");
               my_data->current_backend_cfg[DEFAULT_CODEC_BACKEND].samplerate_mixer_ctl =
                   strdup("PRIM_MI2S_RX SampleRate");
            } else {
               my_data->current_backend_cfg[DEFAULT_CODEC_BACKEND].bitwidth_mixer_ctl =
                   strdup("WSA_CDC_DMA_RX_0 Format");
               my_data->current_backend_cfg[DEFAULT_CODEC_BACKEND].samplerate_mixer_ctl =
                   strdup("WSA_CDC_DMA_RX_0 SampleRate");

            }
            my_data->current_backend_cfg[DEFAULT_CODEC_TX_BACKEND].bitwidth_mixer_ctl =
                strdup("VA_CDC_DMA_TX_0 Format");
            my_data->current_backend_cfg[DEFAULT_CODEC_TX_BACKEND].samplerate_mixer_ctl =
@@ -6281,10 +6298,16 @@ static bool platform_check_codec_backend_cfg(struct audio_device* adev,
            bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
            ALOGD("%s:becf: afe: reset to default bitwidth %d", __func__, bit_width);
        }
        /*
         * In case of CSRA speaker out, all sample rates are supported, so
         *  check platform here
         */
        if (platform_spkr_use_default_sample_rate(adev->platform)) {
            sample_rate = CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
            ALOGD("%s:becf: afe: playback on codec device not supporting native playback set "
            "default Sample Rate(48k)", __func__);
        }
    }

    if (backend_idx == USB_AUDIO_RX_BACKEND) {
        audio_extn_usb_is_config_supported(&bit_width, &sample_rate, &channels, true);
@@ -6954,6 +6977,40 @@ int platform_set_stream_channel_map(void *platform, audio_channel_mask_t channel
                channel_map[6] = PCM_CHANNEL_LS;
                channel_map[7] = PCM_CHANNEL_RS;
                break;
           case 12:
                /* AUDIO_CHANNEL_OUT_7POINT1POINT4 */
                channel_map[0] = PCM_CHANNEL_FL;
                channel_map[1] = PCM_CHANNEL_FR;
                channel_map[2] = PCM_CHANNEL_FC;
                channel_map[3] = PCM_CHANNEL_LFE;
                channel_map[4] = PCM_CHANNEL_LB;
                channel_map[5] = PCM_CHANNEL_RB;
                channel_map[6] = PCM_CHANNEL_LS;
                channel_map[7] = PCM_CHANNEL_RS;
                channel_map[8] = PCM_CHANNEL_TFL;
                channel_map[9] = PCM_CHANNEL_TFR;
                channel_map[10] = PCM_CHANNEL_TSL;
                channel_map[11] = PCM_CHANNEL_TSR;
                break;
          case 16:
                /* 16 channels */
                channel_map[0] = PCM_CHANNEL_FL;
                channel_map[1] = PCM_CHANNEL_FR;
                channel_map[2] = PCM_CHANNEL_FC;
                channel_map[3] = PCM_CHANNEL_LFE;
                channel_map[4] = PCM_CHANNEL_LB;
                channel_map[5] = PCM_CHANNEL_RB;
                channel_map[6] = PCM_CHANNEL_LS;
                channel_map[7] = PCM_CHANNEL_RS;
                channel_map[8] = PCM_CHANNEL_TFL;
                channel_map[9] = PCM_CHANNEL_TFR;
                channel_map[10] = PCM_CHANNEL_TSL;
                channel_map[11] = PCM_CHANNEL_TSR;
                channel_map[12] = PCM_CHANNEL_FLC;
                channel_map[13] = PCM_CHANNEL_FRC;
                channel_map[14] = PCM_CHANNEL_RLC;
                channel_map[15] = PCM_CHANNEL_RRC;
                break;
            default:
                ALOGE("unsupported channels %d for setting channel map", channels);
                return -1;
@@ -7078,12 +7135,21 @@ int platform_set_channel_map(void *platform, int ch_count, char *ch_map, int snd
    struct mixer_ctl *ctl;
    char mixer_ctl_name[44] = {0}; // max length of name is 44 as defined
    int ret;
    unsigned int i;
    long set_values[FCC_8] = {0};
    unsigned int i=0, n=0;
    long set_values[AUDIO_MAX_DSP_CHANNELS];
    struct platform_data *my_data = (struct platform_data *)platform;
    struct audio_device *adev = my_data->adev;
    ALOGV("%s channel_count:%d",__func__, ch_count);
    if (NULL == ch_map || (ch_count < 1) || (ch_count > FCC_8)) {

    /*
     * FIXME:
     * Currently the channel mask in audio.h is limited to 30 channels,
     * (=AUDIO_CHANNEL_COUNT_MAX), whereas the mixer controls already
     * allow up to AUDIO_MAX_DSP_CHANNELS channels as per final requirement.
     * Until channel mask definition is not changed from a uint32_t value
     * to something else, a sanity check is needed here.
     */
    if (NULL == ch_map || (ch_count < 1) || (ch_count > AUDIO_CHANNEL_COUNT_MAX)) {
        ALOGE("%s: Invalid channel mapping or channel count value", __func__);
        return -EINVAL;
    }
@@ -7101,12 +7167,34 @@ int platform_set_channel_map(void *platform, int ch_count, char *ch_map, int snd
    ALOGD("%s mixer_ctl_name:%s", __func__, mixer_ctl_name);

    ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);

    if (!ctl) {
        ALOGE("%s: Could not get ctl for mixer cmd - %s",
              __func__, mixer_ctl_name);
        return -EINVAL;
    }
    for (i = 0; i < (unsigned int)ch_count; i++) {

    /* find out how many values the control can set */
    n = mixer_ctl_get_num_values(ctl);

    if (n != ch_count)
        ALOGV("%s chcnt %d != mixerctl elem size %d",__func__, ch_count, n);

    if (n < ch_count) {
        ALOGE("%s chcnt %d > mixerctl elem size %d",__func__, ch_count, n);
        return -EINVAL;
    }

    if (n > AUDIO_MAX_DSP_CHANNELS) {
        ALOGE("%s mixerctl elem size %d > AUDIO_MAX_DSP_CHANNELS %d",__func__, n, AUDIO_MAX_DSP_CHANNELS);
        return -EINVAL;
    }

    /* initialize all set_values to zero */
    memset (set_values, 0, sizeof(set_values));

    /* copy only as many values as corresponding mixer_ctrl allows */
    for (i = 0; i < ch_count; i++) {
        set_values[i] = ch_map[i];
    }

@@ -7114,7 +7202,8 @@ int platform_set_channel_map(void *platform, int ch_count, char *ch_map, int snd
        set_values[0], set_values[1], set_values[2], set_values[3], set_values[4],
        set_values[5], set_values[6], set_values[7], ch_count);

    ret = mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
    ret = mixer_ctl_set_array(ctl, set_values, n);

    if (ret < 0) {
        ALOGE("%s: Could not set ctl, error:%d ch_count:%d",
              __func__, ret, ch_count);
@@ -7279,6 +7368,11 @@ int platform_edid_get_highest_supported_sr(void *platform)
    return 0;
}

bool platform_spkr_use_default_sample_rate(void *platform) {
    struct platform_data *my_data = (struct platform_data *)platform;
    return my_data->use_sprk_default_sample_rate;
}

int platform_set_edid_channels_configuration(void *platform, int channels) {

    struct platform_data *my_data = (struct platform_data *)platform;
Loading