lkml.org 
[lkml]   [2023]   [Oct]   [17]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH v9 30/34] ASoC: qcom: qdsp6: Add SND kcontrol for fetching offload status
    Date
    Add a kcontrol to the platform sound card to fetch the current offload
    status. This can allow for userspace to ensure/check which USB SND
    resources are actually busy versus having to attempt opening the USB SND
    devices, which will result in an error if offloading is active.

    Signed-off-by: Wesley Cheng <quic_wcheng@quicinc.com>
    ---
    sound/soc/qcom/qdsp6/q6usb.c | 104 ++++++++++++++++++++++++++++++++++-
    1 file changed, 101 insertions(+), 3 deletions(-)

    diff --git a/sound/soc/qcom/qdsp6/q6usb.c b/sound/soc/qcom/qdsp6/q6usb.c
    index a95276b7d91d..d2f60ce66cf3 100644
    --- a/sound/soc/qcom/qdsp6/q6usb.c
    +++ b/sound/soc/qcom/qdsp6/q6usb.c
    @@ -30,6 +30,8 @@ struct q6usb_status {
    unsigned int num_pcm;
    unsigned int chip_index;
    unsigned int pcm_index;
    + bool prepared;
    + bool running;
    };

    struct q6usb_port_data {
    @@ -52,6 +54,17 @@ static const struct snd_soc_dapm_route q6usb_dapm_routes[] = {
    {"USB Playback", NULL, "USB_RX_BE"},
    };

    +static int q6usb_find_running(struct q6usb_port_data *data)
    +{
    + int i;
    +
    + for (i = 0; i < SNDRV_CARDS; i++) {
    + if (data->status[i].running)
    + return i;
    + }
    + return -ENODEV;
    +}
    +
    static int q6usb_hw_params(struct snd_pcm_substream *substream,
    struct snd_pcm_hw_params *params,
    struct snd_soc_dai *dai)
    @@ -81,14 +94,40 @@ static int q6usb_hw_params(struct snd_pcm_substream *substream,
    goto out;

    data->status[data->sel_card_idx].pcm_index = data->sel_pcm_idx;
    + data->status[data->sel_card_idx].prepared = true;
    out:
    mutex_unlock(&data->mutex);

    return ret;
    }

    +static int q6usb_prepare(struct snd_pcm_substream *substream,
    + struct snd_soc_dai *dai)
    +{
    + struct q6usb_port_data *data = dev_get_drvdata(dai->dev);
    +
    + mutex_lock(&data->mutex);
    + data->status[data->sel_card_idx].running = true;
    + mutex_unlock(&data->mutex);
    +
    + return 0;
    +}
    +
    +static void q6usb_shutdown(struct snd_pcm_substream *substream,
    + struct snd_soc_dai *dai)
    +{
    + struct q6usb_port_data *data = dev_get_drvdata(dai->dev);
    +
    + mutex_lock(&data->mutex);
    + data->status[data->sel_card_idx].running = false;
    + data->status[data->sel_card_idx].prepared = false;
    + mutex_unlock(&data->mutex);
    +}
    +
    static const struct snd_soc_dai_ops q6usb_ops = {
    .hw_params = q6usb_hw_params,
    + .prepare = q6usb_prepare,
    + .shutdown = q6usb_shutdown,
    };

    static struct snd_soc_dai_driver q6usb_be_dais[] = {
    @@ -148,10 +187,15 @@ static int q6usb_put_offload_dev(struct snd_kcontrol *kcontrol,
    int pcmidx;
    int cardidx;

    + mutex_lock(&data->mutex);
    +
    + /* Don't allow changes to the offloading devices if session is busy */
    + if (data->sel_card_idx >= 0 && data->status[data->sel_card_idx].prepared)
    + goto out;
    +
    cardidx = ucontrol->value.integer.value[0];
    pcmidx = ucontrol->value.integer.value[1];

    - mutex_lock(&data->mutex);
    if ((cardidx >= 0 && test_bit(cardidx, &data->available_card_slot))) {
    data->sel_card_idx = cardidx;
    changed = 1;
    @@ -162,6 +206,8 @@ static int q6usb_put_offload_dev(struct snd_kcontrol *kcontrol,
    data->idx_valid = true;
    changed = 1;
    }
    +
    +out:
    mutex_unlock(&data->mutex);

    return changed;
    @@ -187,11 +233,59 @@ static const struct snd_kcontrol_new q6usb_offload_dev_ctrl = {
    .put = q6usb_put_offload_dev,
    };

    +static int q6usb_mixer_get_offload_status(struct snd_kcontrol *kcontrol,
    + struct snd_ctl_elem_value *ucontrol)
    +{
    + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
    + struct q6usb_port_data *data = dev_get_drvdata(component->dev);
    + int running;
    + int card_idx;
    + int pcm_idx;
    +
    + running = q6usb_find_running(data);
    + if (running < 0) {
    + card_idx = -1;
    + pcm_idx = -1;
    + } else {
    + card_idx = running;
    + pcm_idx = data->status[running].pcm_index;
    + }
    +
    + ucontrol->value.integer.value[0] = card_idx;
    + ucontrol->value.integer.value[1] = pcm_idx;
    + return 0;
    +}
    +
    +static int q6usb_offload_ctl_info(struct snd_kcontrol *kcontrol,
    + struct snd_ctl_elem_info *uinfo)
    +{
    + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
    + uinfo->count = 2;
    + uinfo->value.integer.min = 0;
    + uinfo->value.integer.max = SNDRV_CARDS;
    +
    + return 0;
    +}
    +
    +static const struct snd_kcontrol_new q6usb_offload_control = {
    + .iface = SNDRV_CTL_ELEM_IFACE_CARD,
    + .access = SNDRV_CTL_ELEM_ACCESS_READ,
    + .name = "Q6USB offload status",
    + .info = q6usb_offload_ctl_info,
    + .get = q6usb_mixer_get_offload_status,
    + .put = NULL,
    +};
    +
    /* Build a mixer control for a UAC connector control (jack-detect) */
    static void q6usb_connector_control_init(struct snd_soc_component *component)
    {
    int ret;

    + ret = snd_ctl_add(component->card->snd_card,
    + snd_ctl_new1(&q6usb_offload_control, component));
    + if (ret < 0)
    + return;
    +
    ret = snd_ctl_add(component->card->snd_card,
    snd_ctl_new1(&q6usb_offload_dev_ctrl, component));
    if (ret < 0)
    @@ -229,8 +323,12 @@ static int q6usb_alsa_connection_cb(struct snd_soc_usb *usb,

    mutex_lock(&data->mutex);
    if (connected) {
    - /* We only track the latest USB headset plugged in */
    - if (!data->idx_valid || data->sel_card_idx < 0)
    + /*
    + * Update the latest USB headset plugged in, if session is
    + * idle.
    + */
    + if ((!data->idx_valid || data->sel_card_idx < 0) &&
    + !data->status[data->sel_card_idx].prepared)
    data->sel_card_idx = sdev->card_idx;

    set_bit(sdev->card_idx, &data->available_card_slot);
    \
     
     \ /
      Last update: 2023-10-17 22:04    [W:4.049 / U:0.068 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site