ASoC: q6dsp: q6apm-dai: Add compress set params and metadata DAI callbacks
authorSrinivas Kandagatla <srinivas.kandagatla@linaro.org>
Mon, 19 Jun 2023 10:16:52 +0000 (11:16 +0100)
committerMark Brown <broonie@kernel.org>
Mon, 19 Jun 2023 11:59:05 +0000 (12:59 +0100)
Add q6apm compress DAI callbacks for setting params and metadata to support
compress offload playback.

Co-developed-by: Mohammad Rafi Shaik <quic_mohs@quicinc.com>
Signed-off-by: Mohammad Rafi Shaik <quic_mohs@quicinc.com>
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
Link: https://lore.kernel.org/r/20230619101653.9750-11-srinivas.kandagatla@linaro.org
Signed-off-by: Mark Brown <broonie@kernel.org>
sound/soc/qcom/qdsp6/q6apm-dai.c

index 9543b79..c67147e 100644 (file)
@@ -76,6 +76,8 @@ struct q6apm_dai_rtd {
        enum stream_state state;
        struct q6apm_graph *graph;
        spinlock_t lock;
+       uint32_t initial_samples_drop;
+       uint32_t trailing_samples_drop;
        bool notify_on_drain;
 };
 
@@ -632,6 +634,109 @@ static int q6apm_dai_compr_ack(struct snd_soc_component *component, struct snd_c
        return count;
 }
 
+static int q6apm_dai_compr_set_params(struct snd_soc_component *component,
+                                     struct snd_compr_stream *stream,
+                                     struct snd_compr_params *params)
+{
+       struct snd_compr_runtime *runtime = stream->runtime;
+       struct q6apm_dai_rtd *prtd = runtime->private_data;
+       struct q6apm_dai_data *pdata;
+       struct audioreach_module_config cfg;
+       struct snd_codec *codec = &params->codec;
+       int dir = stream->direction;
+       int ret;
+
+       pdata = snd_soc_component_get_drvdata(component);
+       if (!pdata)
+               return -EINVAL;
+
+       prtd->periods = runtime->fragments;
+       prtd->pcm_count = runtime->fragment_size;
+       prtd->pcm_size = runtime->fragments * runtime->fragment_size;
+       prtd->bits_per_sample = 16;
+
+       prtd->pos = 0;
+
+       if (prtd->next_track != true) {
+               memcpy(&prtd->codec, codec, sizeof(*codec));
+
+               ret = q6apm_set_real_module_id(component->dev, prtd->graph, codec->id);
+               if (ret)
+                       return ret;
+
+               cfg.direction = dir;
+               cfg.sample_rate = codec->sample_rate;
+               cfg.num_channels = 2;
+               cfg.bit_width = prtd->bits_per_sample;
+               cfg.fmt = codec->id;
+               memcpy(&cfg.codec, codec, sizeof(*codec));
+
+               ret = q6apm_graph_media_format_shmem(prtd->graph, &cfg);
+               if (ret < 0)
+                       return ret;
+
+               ret = q6apm_graph_media_format_pcm(prtd->graph, &cfg);
+               if (ret)
+                       return ret;
+
+               ret = q6apm_map_memory_regions(prtd->graph, SNDRV_PCM_STREAM_PLAYBACK,
+                                              prtd->phys, (prtd->pcm_size / prtd->periods),
+                                              prtd->periods);
+               if (ret < 0)
+                       return -ENOMEM;
+
+               ret = q6apm_graph_prepare(prtd->graph);
+               if (ret)
+                       return ret;
+
+               ret = q6apm_graph_start(prtd->graph);
+               if (ret)
+                       return ret;
+
+       } else {
+               cfg.direction = dir;
+               cfg.sample_rate = codec->sample_rate;
+               cfg.num_channels = 2;
+               cfg.bit_width = prtd->bits_per_sample;
+               cfg.fmt = codec->id;
+               memcpy(&cfg.codec, codec, sizeof(*codec));
+
+               ret = audioreach_compr_set_param(prtd->graph,  &cfg);
+               if (ret < 0)
+                       return ret;
+       }
+       prtd->state = Q6APM_STREAM_RUNNING;
+
+       return 0;
+}
+
+static int q6apm_dai_compr_set_metadata(struct snd_soc_component *component,
+                                       struct snd_compr_stream *stream,
+                                       struct snd_compr_metadata *metadata)
+{
+       struct snd_compr_runtime *runtime = stream->runtime;
+       struct q6apm_dai_rtd *prtd = runtime->private_data;
+       int ret = 0;
+
+       switch (metadata->key) {
+       case SNDRV_COMPRESS_ENCODER_PADDING:
+               prtd->trailing_samples_drop = metadata->value[0];
+               q6apm_remove_trailing_silence(component->dev, prtd->graph,
+                                             prtd->trailing_samples_drop);
+               break;
+       case SNDRV_COMPRESS_ENCODER_DELAY:
+               prtd->initial_samples_drop = metadata->value[0];
+               q6apm_remove_initial_silence(component->dev, prtd->graph,
+                                            prtd->initial_samples_drop);
+               break;
+       default:
+               ret = -EINVAL;
+               break;
+       }
+
+       return ret;
+}
+
 static const struct snd_compress_ops q6apm_dai_compress_ops = {
        .open           = q6apm_dai_compr_open,
        .free           = q6apm_dai_compr_free,
@@ -640,6 +745,8 @@ static const struct snd_compress_ops q6apm_dai_compress_ops = {
        .pointer        = q6apm_dai_compr_pointer,
        .trigger        = q6apm_dai_compr_trigger,
        .ack            = q6apm_dai_compr_ack,
+       .set_params     = q6apm_dai_compr_set_params,
+       .set_metadata   = q6apm_dai_compr_set_metadata,
 };
 
 static const struct snd_soc_component_driver q6apm_fe_dai_component = {