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

Commit 479bb9c2 authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "hal: support bus dev volume over audio port config"

parents ad63a3c2 f13dd499
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -1222,6 +1222,8 @@ int audio_extn_utils_get_license_params(const struct audio_device *adev, struct
#define audio_extn_auto_hal_open_output_stream(out) (0)
#define audio_extn_auto_hal_is_bus_device_usecase(uc_id) (0)
#define audio_extn_auto_hal_get_snd_device_for_car_audio_stream(out) (0)
#define audio_extn_auto_hal_get_audio_port(dev, config) (0)
#define audio_extn_auto_hal_set_audio_port_config(dev, config) (0)
#else
int32_t audio_extn_auto_hal_init(struct audio_device *adev);
void audio_extn_auto_hal_deinit(void);
@@ -1239,6 +1241,10 @@ int32_t audio_extn_auto_hal_get_car_audio_stream_from_address(const char *addres
int32_t audio_extn_auto_hal_open_output_stream(struct stream_out *out);
bool audio_extn_auto_hal_is_bus_device_usecase(audio_usecase_t uc_id);
snd_device_t audio_extn_auto_hal_get_snd_device_for_car_audio_stream(struct stream_out *out);
int audio_extn_auto_hal_get_audio_port(struct audio_hw_device *dev,
                                struct audio_port *config);
int audio_extn_auto_hal_set_audio_port_config(struct audio_hw_device *dev,
                                const struct audio_port_config *config);
#endif

bool audio_extn_edid_is_supported_sr(edid_audio_info* info, int sr);
+128 −0
Original line number Diff line number Diff line
@@ -432,6 +432,134 @@ snd_device_t audio_extn_auto_hal_get_snd_device_for_car_audio_stream(struct stre
    }
    return snd_device;
}

int audio_extn_auto_hal_get_audio_port(struct audio_hw_device *dev __unused,
                        struct audio_port *config __unused)
{
    return -ENOSYS;
}

/* Volume min/max defined by audio policy configuration in millibel.
 * Support a range of -60dB to 6dB.
 */
#define MIN_VOLUME_VALUE_MB -6000
#define MAX_VOLUME_VALUE_MB 600

int audio_extn_auto_hal_set_audio_port_config(struct audio_hw_device *dev,
                        const struct audio_port_config *config)
{
    struct audio_device *adev = (struct audio_device *)dev;
    int ret = 0;
    struct listnode *node = NULL;
    float volume = 0.0;

    ALOGV("%s: enter", __func__);

    if (!config) {
        ALOGE("%s: invalid input parameters", __func__);
        return -EINVAL;
    }

    /* For Android automotive, audio port config from car framework
     * allows volume gain to be set to device at audio HAL level, where
     * the gain can be applied in DSP mixer or CODEC amplifier.
     *
     * Following routing should be considered:
     *     MIX -> DEVICE
     *     DEVICE -> MIX
     *     DEVICE -> DEVICE
     *
     * For BUS devices routed to/from mixer, gain will be applied to DSP
     * mixer via kernel control which audio HAL stream is associated with.
     *
     * For external (source) device (FM TUNER/AUX), routing is typically
     * done with AudioPatch to (sink) device (SPKR), thus gain should be
     * applied to CODEC amplifier via codec plugin extention as audio HAL
     * stream may not be available for external audio routing.
     */
    if (config->type == AUDIO_PORT_TYPE_DEVICE) {
        ALOGI("%s: device port: type %x, address %s, gain %d mB", __func__,
            config->ext.device.type,
            config->ext.device.address,
            config->gain.values[0]);
        if (config->role == AUDIO_PORT_ROLE_SINK) {
            /* handle output devices */
            pthread_mutex_lock(&adev->lock);
            list_for_each(node, &adev->active_outputs_list) {
                streams_output_ctxt_t *out_ctxt = node_to_item(node,
                                                    streams_output_ctxt_t,
                                                    list);
                /* limit audio gain support for bus device only */
                if (out_ctxt->output->devices == AUDIO_DEVICE_OUT_BUS &&
                    out_ctxt->output->devices == config->ext.device.type &&
                    strcmp(out_ctxt->output->address,
                        config->ext.device.address) == 0) {
                    /* millibel = 1/100 dB = 1/1000 bel
                     * q13 = (10^(mdb/100/20))*(2^13)
                     */
                    volume = powf(10.0, ((float)config->gain.values[0] / 2000));
                    ALOGV("%s: set volume to stream: %p", __func__,
                        &out_ctxt->output->stream);
                    /* set gain if output stream is active */
                    out_ctxt->output->stream.set_volume(
                                                &out_ctxt->output->stream,
                                                volume, volume);
                }
            }
            /* NOTE: Ideally audio patch list is a superset of output stream list above.
             *       However, audio HAL does not maintain patches for mix -> device or
             *       device -> mix currently. Thus doing separate lookups for device ->
             *       device in audio patch list.
             * FIXME: Cannot cache the gain if audio patch is not created. Expected gain
             *        to be part of port config upon audio patch creation. If not, need
             *        to create a list of audio port configs in adev context.
             */
#if 0
            list_for_each(node, &adev->audio_patch_record_list) {
                struct audio_patch_record *patch_record = node_to_item(node,
                                                    struct audio_patch_record,
                                                    list);
                /* limit audio gain support for bus device only */
                if (patch_record->sink.type == AUDIO_PORT_TYPE_DEVICE &&
                    patch_record->sink.role == AUDIO_PORT_ROLE_SINK &&
                    patch_record->sink.ext.device.type == AUDIO_DEVICE_OUT_BUS &&
                    patch_record->sink.ext.device.type == config->ext.device.type &&
                    strcmp(patch_record->sink.ext.device.address,
                        config->ext.device.address) == 0) {
                    /* cache / update gain per audio patch sink */
                    patch_record->sink.gain = config->gain;

                    struct audio_usecase *uc_info = get_usecase_from_list(adev,
                                                        patch_record->usecase);
                    if (!uc_info) {
                        ALOGE("%s: failed to find the usecase %d",
                            __func__, patch_record->usecase);
                        ret = -EINVAL;
                    } else {
                        volume = config->gain->values[0];
                        /* linear interpolation from millibel to level */
                        int vol_level = lrint(((volume + (0 - MIN_VOLUME_VALUE_MB)) /
                                               (MAX_VOLUME_VALUE_MB - MIN_VOLUME_VALUE_MB)) * 40);
                        ALOGV("%s: set volume to patch: %p", __func__,
                            patch_record->handle);
                        ret = audio_extn_ext_hw_plugin_set_audio_gain(adev,
                                uc_info, vol_level);
                    }
                }
            }
#endif
            pthread_mutex_unlock(&adev->lock);
        } else if (config->role == AUDIO_PORT_ROLE_SOURCE) {
            // FIXME: handle input devices.
        }
    }

    /* Only handle device port currently. */

    ALOGV("%s: exit", __func__);
    return ret;
}

int32_t audio_extn_auto_hal_init(struct audio_device *adev)
{
    int32_t ret = 0;
+35 −2
Original line number Diff line number Diff line
@@ -3665,6 +3665,8 @@ int start_output_stream(struct stream_out *out)
                  out->usecase == USECASE_AUDIO_PLAYBACK_ULL) && (out->apply_volume)) {
                 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
                 out->apply_volume = false;
        } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) {
            out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
        }
    } else {
        platform_set_stream_channel_map(adev->platform, out->channel_mask,
@@ -3727,6 +3729,22 @@ int start_output_stream(struct stream_out *out)
                adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
            audio_extn_check_and_set_dts_hpx_state(adev);
        }

        if (out->devices & AUDIO_DEVICE_OUT_BUS) {
            /* Update cached volume from media to offload/direct stream */
            struct listnode *node = NULL;
            list_for_each(node, &adev->active_outputs_list) {
                streams_output_ctxt_t *out_ctxt = node_to_item(node,
                                                    streams_output_ctxt_t,
                                                    list);
                if (out_ctxt->output->usecase == USECASE_AUDIO_PLAYBACK_MEDIA) {
                    out->volume_l = out_ctxt->output->volume_l;
                    out->volume_r = out_ctxt->output->volume_r;
                }
            }
            out_set_compr_volume(&out->stream,
                                 out->volume_l, out->volume_r);
        }
    }

    if (ret == 0) {
@@ -5111,6 +5129,13 @@ static int out_set_volume(struct audio_stream_out *stream, float left,
        out->volume_l = left;
        out->volume_r = right;
        return ret;
    } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) {
        ALOGV("%s: bus device set volume called", __func__);
        if (!out->standby)
            ret = out_set_pcm_volume(stream, left, right);
        out->volume_l = left;
        out->volume_r = right;
        return ret;
    }

    return -ENOSYS;
@@ -9128,13 +9153,21 @@ int adev_release_audio_patch(struct audio_hw_device *dev,

int adev_get_audio_port(struct audio_hw_device *dev, struct audio_port *config)
{
    return audio_extn_hw_loopback_get_audio_port(dev, config);
    int ret = 0;

    ret = audio_extn_hw_loopback_get_audio_port(dev, config);
    ret |= audio_extn_auto_hal_get_audio_port(dev, config);
    return ret;
}

int adev_set_audio_port_config(struct audio_hw_device *dev,
                        const struct audio_port_config *config)
{
    return audio_extn_hw_loopback_set_audio_port_config(dev, config);
    int ret = 0;

    ret = audio_extn_hw_loopback_set_audio_port_config(dev, config);
    ret |= audio_extn_auto_hal_set_audio_port_config(dev, config);
    return ret;
}

static int adev_dump(const audio_hw_device_t *device __unused,