ASoC: q6dsp: audioreach: Add support to set compress format params
authorMohammad Rafi Shaik <quic_mohs@quicinc.com>
Mon, 19 Jun 2023 10:16:47 +0000 (11:16 +0100)
committerMark Brown <broonie@kernel.org>
Mon, 19 Jun 2023 11:59:01 +0000 (12:59 +0100)
Add function for setting compress params.

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

index 34cbc4d..ba26240 100644 (file)
@@ -834,6 +834,99 @@ static int audioreach_mfc_set_media_format(struct q6apm_graph *graph,
        return rc;
 }
 
+static int audioreach_set_compr_media_format(struct media_format *media_fmt_hdr,
+                                            void *p, struct audioreach_module_config *mcfg)
+{
+       struct payload_media_fmt_aac_t *aac_cfg;
+       struct payload_media_fmt_pcm *mp3_cfg;
+       struct payload_media_fmt_flac_t *flac_cfg;
+
+       switch (mcfg->fmt) {
+       case SND_AUDIOCODEC_MP3:
+               media_fmt_hdr->data_format = DATA_FORMAT_RAW_COMPRESSED;
+               media_fmt_hdr->fmt_id = MEDIA_FMT_ID_MP3;
+               media_fmt_hdr->payload_size = 0;
+               p = p + sizeof(*media_fmt_hdr);
+               mp3_cfg = p;
+               mp3_cfg->sample_rate = mcfg->sample_rate;
+               mp3_cfg->bit_width = mcfg->bit_width;
+               mp3_cfg->alignment = PCM_LSB_ALIGNED;
+               mp3_cfg->bits_per_sample = mcfg->bit_width;
+               mp3_cfg->q_factor = mcfg->bit_width - 1;
+               mp3_cfg->endianness = PCM_LITTLE_ENDIAN;
+               mp3_cfg->num_channels = mcfg->num_channels;
+
+               if (mcfg->num_channels == 1) {
+                       mp3_cfg->channel_mapping[0] =  PCM_CHANNEL_L;
+               } else if (mcfg->num_channels == 2) {
+                       mp3_cfg->channel_mapping[0] =  PCM_CHANNEL_L;
+                       mp3_cfg->channel_mapping[1] =  PCM_CHANNEL_R;
+               }
+               break;
+       case SND_AUDIOCODEC_AAC:
+               media_fmt_hdr->data_format = DATA_FORMAT_RAW_COMPRESSED;
+               media_fmt_hdr->fmt_id = MEDIA_FMT_ID_AAC;
+               media_fmt_hdr->payload_size = sizeof(struct payload_media_fmt_aac_t);
+               p = p + sizeof(*media_fmt_hdr);
+               aac_cfg = p;
+               aac_cfg->aac_fmt_flag = 0;
+               aac_cfg->audio_obj_type = 5;
+               aac_cfg->num_channels = mcfg->num_channels;
+               aac_cfg->total_size_of_PCE_bits = 0;
+               aac_cfg->sample_rate = mcfg->sample_rate;
+               break;
+       case SND_AUDIOCODEC_FLAC:
+               media_fmt_hdr->data_format = DATA_FORMAT_RAW_COMPRESSED;
+               media_fmt_hdr->fmt_id = MEDIA_FMT_ID_FLAC;
+               media_fmt_hdr->payload_size = sizeof(struct payload_media_fmt_flac_t);
+               p = p + sizeof(*media_fmt_hdr);
+               flac_cfg = p;
+               flac_cfg->sample_size = mcfg->codec.options.flac_d.sample_size;
+               flac_cfg->num_channels = mcfg->num_channels;
+               flac_cfg->min_blk_size = mcfg->codec.options.flac_d.min_blk_size;
+               flac_cfg->max_blk_size = mcfg->codec.options.flac_d.max_blk_size;
+               flac_cfg->sample_rate = mcfg->sample_rate;
+               flac_cfg->min_frame_size = mcfg->codec.options.flac_d.min_frame_size;
+               flac_cfg->max_frame_size = mcfg->codec.options.flac_d.max_frame_size;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+int audioreach_compr_set_param(struct q6apm_graph *graph, struct audioreach_module_config *mcfg)
+{
+       struct media_format *header;
+       struct gpr_pkt *pkt;
+       int iid, payload_size, rc;
+       void *p;
+
+       payload_size = sizeof(struct apm_sh_module_media_fmt_cmd);
+
+       iid = q6apm_graph_get_rx_shmem_module_iid(graph);
+       pkt = audioreach_alloc_cmd_pkt(payload_size, DATA_CMD_WR_SH_MEM_EP_MEDIA_FORMAT,
+                       0, graph->port->id, iid);
+
+       if (IS_ERR(pkt))
+               return -ENOMEM;
+
+       p = (void *)pkt + GPR_HDR_SIZE;
+       header = p;
+       rc = audioreach_set_compr_media_format(header, p, mcfg);
+       if (rc) {
+               kfree(pkt);
+               return rc;
+       }
+
+       rc = gpr_send_port_pkt(graph->port, pkt);
+       kfree(pkt);
+
+       return rc;
+}
+EXPORT_SYMBOL_GPL(audioreach_compr_set_param);
+
 static int audioreach_i2s_set_media_format(struct q6apm_graph *graph,
                                           struct audioreach_module *module,
                                           struct audioreach_module_config *cfg)
@@ -1037,25 +1130,33 @@ static int audioreach_shmem_set_media_format(struct q6apm_graph *graph,
        p = p + APM_MODULE_PARAM_DATA_SIZE;
 
        header = p;
-       header->data_format = DATA_FORMAT_FIXED_POINT;
-       header->fmt_id = MEDIA_FMT_ID_PCM;
-       header->payload_size = payload_size - sizeof(*header);
-
-       p = p + sizeof(*header);
-       cfg = p;
-       cfg->sample_rate = mcfg->sample_rate;
-       cfg->bit_width = mcfg->bit_width;
-       cfg->alignment = PCM_LSB_ALIGNED;
-       cfg->bits_per_sample = mcfg->bit_width;
-       cfg->q_factor = mcfg->bit_width - 1;
-       cfg->endianness = PCM_LITTLE_ENDIAN;
-       cfg->num_channels = mcfg->num_channels;
-
-       if (mcfg->num_channels == 1) {
-               cfg->channel_mapping[0] =  PCM_CHANNEL_L;
-       } else if (num_channels == 2) {
-               cfg->channel_mapping[0] =  PCM_CHANNEL_L;
-               cfg->channel_mapping[1] =  PCM_CHANNEL_R;
+       if (mcfg->fmt == SND_AUDIOCODEC_PCM) {
+               header->data_format = DATA_FORMAT_FIXED_POINT;
+               header->fmt_id =  MEDIA_FMT_ID_PCM;
+               header->payload_size = payload_size - sizeof(*header);
+
+               p = p + sizeof(*header);
+               cfg = p;
+               cfg->sample_rate = mcfg->sample_rate;
+               cfg->bit_width = mcfg->bit_width;
+               cfg->alignment = PCM_LSB_ALIGNED;
+               cfg->bits_per_sample = mcfg->bit_width;
+               cfg->q_factor = mcfg->bit_width - 1;
+               cfg->endianness = PCM_LITTLE_ENDIAN;
+               cfg->num_channels = mcfg->num_channels;
+
+               if (mcfg->num_channels == 1)
+                       cfg->channel_mapping[0] =  PCM_CHANNEL_L;
+               else if (num_channels == 2) {
+                       cfg->channel_mapping[0] =  PCM_CHANNEL_L;
+                       cfg->channel_mapping[1] =  PCM_CHANNEL_R;
+               }
+       } else {
+               rc = audioreach_set_compr_media_format(header, p, mcfg);
+               if (rc) {
+                       kfree(pkt);
+                       return rc;
+               }
        }
 
        rc = audioreach_graph_send_cmd_sync(graph, pkt, 0);
index c4e03a4..dc08987 100644 (file)
@@ -148,12 +148,15 @@ struct param_id_enc_bitrate_param {
 } __packed;
 
 #define DATA_FORMAT_FIXED_POINT                1
+#define DATA_FORMAT_GENERIC_COMPRESSED 5
+#define DATA_FORMAT_RAW_COMPRESSED     6
 #define PCM_LSB_ALIGNED                        1
 #define PCM_MSB_ALIGNED                        2
 #define PCM_LITTLE_ENDIAN              1
 #define PCM_BIT_ENDIAN                 2
 
 #define MEDIA_FMT_ID_PCM       0x09001000
+#define MEDIA_FMT_ID_MP3       0x09001009
 #define PCM_CHANNEL_L          1
 #define PCM_CHANNEL_R          2
 #define SAMPLE_RATE_48K                48000
@@ -231,6 +234,28 @@ struct apm_media_format {
        uint32_t payload_size;
 } __packed;
 
+#define MEDIA_FMT_ID_FLAC      0x09001004
+
+struct payload_media_fmt_flac_t {
+       uint16_t num_channels;
+       uint16_t sample_size;
+       uint16_t min_blk_size;
+       uint16_t max_blk_size;
+       uint32_t sample_rate;
+       uint32_t min_frame_size;
+       uint32_t max_frame_size;
+} __packed;
+
+#define MEDIA_FMT_ID_AAC       0x09001001
+
+struct payload_media_fmt_aac_t {
+       uint16_t aac_fmt_flag;
+       uint16_t audio_obj_type;
+       uint16_t num_channels;
+       uint16_t total_size_of_PCE_bits;
+       uint32_t sample_rate;
+} __packed;
+
 #define DATA_CMD_WR_SH_MEM_EP_EOS                      0x04001002
 #define WR_SH_MEM_EP_EOS_POLICY_LAST   1
 #define WR_SH_MEM_EP_EOS_POLICY_EACH   2
@@ -730,6 +755,7 @@ struct audioreach_module_config {
        u32     channel_allocation;
        u32     sd_line_mask;
        int     fmt;
+       struct snd_codec codec;
        u8 channel_map[AR_PCM_MAX_NUM_CHANNEL];
 };
 
@@ -768,4 +794,6 @@ int audioreach_gain_set_vol_ctrl(struct q6apm *apm,
                                 struct audioreach_module *module, int vol);
 int audioreach_send_u32_param(struct q6apm_graph *graph, struct audioreach_module *module,
                              uint32_t param_id, uint32_t param_val);
+int audioreach_compr_set_param(struct q6apm_graph *graph, struct audioreach_module_config *mcfg);
+
 #endif /* __AUDIOREACH_H__ */
index 7f02f5b..9fff41e 100644 (file)
@@ -155,6 +155,7 @@ static int q6apm_dai_prepare(struct snd_soc_component *component,
        cfg.sample_rate = runtime->rate;
        cfg.num_channels = runtime->channels;
        cfg.bit_width = prtd->bits_per_sample;
+       cfg.fmt = SND_AUDIOCODEC_PCM;
 
        if (prtd->state) {
                /* clear the previous setup if any  */