Skip to content

Commit d4b2aee

Browse files
committed
ASoC: qcom: audioreach: add compress offload
Merge series from Srinivas Kandagatla <srinivas.kandagatla@linaro.org>: This patchset adds compressed offload support to Qualcomm audioreach drivers. Currently it supports AAC, MP3 and FALC along with gapless. Tested this on SM8450 and sc7280.
2 parents 29735f6 + c317d14 commit d4b2aee

6 files changed

Lines changed: 747 additions & 96 deletions

File tree

sound/soc/qcom/qdsp6/audioreach.c

Lines changed: 156 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -732,111 +732,67 @@ static int audioreach_codec_dma_set_media_format(struct q6apm_graph *graph,
732732
return rc;
733733
}
734734

735-
static int audioreach_sal_limiter_enable(struct q6apm_graph *graph,
736-
struct audioreach_module *module, bool enable)
735+
int audioreach_send_u32_param(struct q6apm_graph *graph, struct audioreach_module *module,
736+
uint32_t param_id, uint32_t param_val)
737737
{
738738
struct apm_module_param_data *param_data;
739-
struct param_id_sal_limiter_enable *limiter_enable;
740-
int payload_size;
741739
struct gpr_pkt *pkt;
742-
int rc;
740+
uint32_t *param;
741+
int rc, payload_size;
743742
void *p;
744743

745-
payload_size = sizeof(*limiter_enable) + APM_MODULE_PARAM_DATA_SIZE;
746-
747-
pkt = audioreach_alloc_apm_cmd_pkt(payload_size, APM_CMD_SET_CFG, 0);
748-
if (IS_ERR(pkt))
749-
return PTR_ERR(pkt);
744+
payload_size = sizeof(uint32_t) + APM_MODULE_PARAM_DATA_SIZE;
745+
p = audioreach_alloc_apm_cmd_pkt(payload_size, APM_CMD_SET_CFG, 0);
746+
if (IS_ERR(p))
747+
return -ENOMEM;
750748

751-
p = (void *)pkt + GPR_HDR_SIZE + APM_CMD_HDR_SIZE;
749+
pkt = p;
750+
p = p + GPR_HDR_SIZE + APM_CMD_HDR_SIZE;
752751

753752
param_data = p;
754753
param_data->module_instance_id = module->instance_id;
755754
param_data->error_code = 0;
756-
param_data->param_id = PARAM_ID_SAL_LIMITER_ENABLE;
757-
param_data->param_size = sizeof(*limiter_enable);
758-
p = p + APM_MODULE_PARAM_DATA_SIZE;
759-
limiter_enable = p;
755+
param_data->param_id = param_id;
756+
param_data->param_size = sizeof(uint32_t);
760757

761-
limiter_enable->enable_lim = enable;
758+
p = p + APM_MODULE_PARAM_DATA_SIZE;
759+
param = p;
760+
*param = param_val;
762761

763762
rc = q6apm_send_cmd_sync(graph->apm, pkt, 0);
764763

765764
kfree(pkt);
766765

767766
return rc;
768767
}
768+
EXPORT_SYMBOL_GPL(audioreach_send_u32_param);
769+
770+
static int audioreach_sal_limiter_enable(struct q6apm_graph *graph,
771+
struct audioreach_module *module, bool enable)
772+
{
773+
return audioreach_send_u32_param(graph, module, PARAM_ID_SAL_LIMITER_ENABLE, enable);
774+
}
769775

770776
static int audioreach_sal_set_media_format(struct q6apm_graph *graph,
771777
struct audioreach_module *module,
772778
struct audioreach_module_config *cfg)
773779
{
774-
struct apm_module_param_data *param_data;
775-
struct param_id_sal_output_config *media_format;
776-
int payload_size;
777-
struct gpr_pkt *pkt;
778-
int rc;
779-
void *p;
780-
781-
payload_size = sizeof(*media_format) + APM_MODULE_PARAM_DATA_SIZE;
782-
783-
pkt = audioreach_alloc_apm_cmd_pkt(payload_size, APM_CMD_SET_CFG, 0);
784-
if (IS_ERR(pkt))
785-
return PTR_ERR(pkt);
786-
787-
p = (void *)pkt + GPR_HDR_SIZE + APM_CMD_HDR_SIZE;
788-
789-
param_data = p;
790-
param_data->module_instance_id = module->instance_id;
791-
param_data->error_code = 0;
792-
param_data->param_id = PARAM_ID_SAL_OUTPUT_CFG;
793-
param_data->param_size = sizeof(*media_format);
794-
p = p + APM_MODULE_PARAM_DATA_SIZE;
795-
media_format = p;
796-
797-
media_format->bits_per_sample = cfg->bit_width;
798-
799-
rc = q6apm_send_cmd_sync(graph->apm, pkt, 0);
800-
801-
kfree(pkt);
802-
803-
return rc;
780+
return audioreach_send_u32_param(graph, module, PARAM_ID_SAL_OUTPUT_CFG, cfg->bit_width);
804781
}
805782

806783
static int audioreach_module_enable(struct q6apm_graph *graph,
807784
struct audioreach_module *module,
808785
bool enable)
809786
{
810-
struct apm_module_param_data *param_data;
811-
struct param_id_module_enable *param;
812-
int payload_size;
813-
struct gpr_pkt *pkt;
814-
int rc;
815-
void *p;
816-
817-
payload_size = sizeof(*param) + APM_MODULE_PARAM_DATA_SIZE;
818-
819-
pkt = audioreach_alloc_apm_cmd_pkt(payload_size, APM_CMD_SET_CFG, 0);
820-
if (IS_ERR(pkt))
821-
return PTR_ERR(pkt);
822-
823-
p = (void *)pkt + GPR_HDR_SIZE + APM_CMD_HDR_SIZE;
824-
825-
param_data = p;
826-
param_data->module_instance_id = module->instance_id;
827-
param_data->error_code = 0;
828-
param_data->param_id = PARAM_ID_MODULE_ENABLE;
829-
param_data->param_size = sizeof(*param);
830-
p = p + APM_MODULE_PARAM_DATA_SIZE;
831-
param = p;
832-
833-
param->enable = enable;
834-
835-
rc = q6apm_send_cmd_sync(graph->apm, pkt, 0);
836-
837-
kfree(pkt);
787+
return audioreach_send_u32_param(graph, module, PARAM_ID_MODULE_ENABLE, enable);
788+
}
838789

839-
return rc;
790+
static int audioreach_gapless_set_media_format(struct q6apm_graph *graph,
791+
struct audioreach_module *module,
792+
struct audioreach_module_config *cfg)
793+
{
794+
return audioreach_send_u32_param(graph, module, PARAM_ID_EARLY_EOS_DELAY,
795+
EARLY_EOS_DELAY_MS);
840796
}
841797

842798
static int audioreach_mfc_set_media_format(struct q6apm_graph *graph,
@@ -886,6 +842,99 @@ static int audioreach_mfc_set_media_format(struct q6apm_graph *graph,
886842
return rc;
887843
}
888844

845+
static int audioreach_set_compr_media_format(struct media_format *media_fmt_hdr,
846+
void *p, struct audioreach_module_config *mcfg)
847+
{
848+
struct payload_media_fmt_aac_t *aac_cfg;
849+
struct payload_media_fmt_pcm *mp3_cfg;
850+
struct payload_media_fmt_flac_t *flac_cfg;
851+
852+
switch (mcfg->fmt) {
853+
case SND_AUDIOCODEC_MP3:
854+
media_fmt_hdr->data_format = DATA_FORMAT_RAW_COMPRESSED;
855+
media_fmt_hdr->fmt_id = MEDIA_FMT_ID_MP3;
856+
media_fmt_hdr->payload_size = 0;
857+
p = p + sizeof(*media_fmt_hdr);
858+
mp3_cfg = p;
859+
mp3_cfg->sample_rate = mcfg->sample_rate;
860+
mp3_cfg->bit_width = mcfg->bit_width;
861+
mp3_cfg->alignment = PCM_LSB_ALIGNED;
862+
mp3_cfg->bits_per_sample = mcfg->bit_width;
863+
mp3_cfg->q_factor = mcfg->bit_width - 1;
864+
mp3_cfg->endianness = PCM_LITTLE_ENDIAN;
865+
mp3_cfg->num_channels = mcfg->num_channels;
866+
867+
if (mcfg->num_channels == 1) {
868+
mp3_cfg->channel_mapping[0] = PCM_CHANNEL_L;
869+
} else if (mcfg->num_channels == 2) {
870+
mp3_cfg->channel_mapping[0] = PCM_CHANNEL_L;
871+
mp3_cfg->channel_mapping[1] = PCM_CHANNEL_R;
872+
}
873+
break;
874+
case SND_AUDIOCODEC_AAC:
875+
media_fmt_hdr->data_format = DATA_FORMAT_RAW_COMPRESSED;
876+
media_fmt_hdr->fmt_id = MEDIA_FMT_ID_AAC;
877+
media_fmt_hdr->payload_size = sizeof(struct payload_media_fmt_aac_t);
878+
p = p + sizeof(*media_fmt_hdr);
879+
aac_cfg = p;
880+
aac_cfg->aac_fmt_flag = 0;
881+
aac_cfg->audio_obj_type = 5;
882+
aac_cfg->num_channels = mcfg->num_channels;
883+
aac_cfg->total_size_of_PCE_bits = 0;
884+
aac_cfg->sample_rate = mcfg->sample_rate;
885+
break;
886+
case SND_AUDIOCODEC_FLAC:
887+
media_fmt_hdr->data_format = DATA_FORMAT_RAW_COMPRESSED;
888+
media_fmt_hdr->fmt_id = MEDIA_FMT_ID_FLAC;
889+
media_fmt_hdr->payload_size = sizeof(struct payload_media_fmt_flac_t);
890+
p = p + sizeof(*media_fmt_hdr);
891+
flac_cfg = p;
892+
flac_cfg->sample_size = mcfg->codec.options.flac_d.sample_size;
893+
flac_cfg->num_channels = mcfg->num_channels;
894+
flac_cfg->min_blk_size = mcfg->codec.options.flac_d.min_blk_size;
895+
flac_cfg->max_blk_size = mcfg->codec.options.flac_d.max_blk_size;
896+
flac_cfg->sample_rate = mcfg->sample_rate;
897+
flac_cfg->min_frame_size = mcfg->codec.options.flac_d.min_frame_size;
898+
flac_cfg->max_frame_size = mcfg->codec.options.flac_d.max_frame_size;
899+
break;
900+
default:
901+
return -EINVAL;
902+
}
903+
904+
return 0;
905+
}
906+
907+
int audioreach_compr_set_param(struct q6apm_graph *graph, struct audioreach_module_config *mcfg)
908+
{
909+
struct media_format *header;
910+
struct gpr_pkt *pkt;
911+
int iid, payload_size, rc;
912+
void *p;
913+
914+
payload_size = sizeof(struct apm_sh_module_media_fmt_cmd);
915+
916+
iid = q6apm_graph_get_rx_shmem_module_iid(graph);
917+
pkt = audioreach_alloc_cmd_pkt(payload_size, DATA_CMD_WR_SH_MEM_EP_MEDIA_FORMAT,
918+
0, graph->port->id, iid);
919+
920+
if (IS_ERR(pkt))
921+
return -ENOMEM;
922+
923+
p = (void *)pkt + GPR_HDR_SIZE;
924+
header = p;
925+
rc = audioreach_set_compr_media_format(header, p, mcfg);
926+
if (rc) {
927+
kfree(pkt);
928+
return rc;
929+
}
930+
931+
rc = gpr_send_port_pkt(graph->port, pkt);
932+
kfree(pkt);
933+
934+
return rc;
935+
}
936+
EXPORT_SYMBOL_GPL(audioreach_compr_set_param);
937+
889938
static int audioreach_i2s_set_media_format(struct q6apm_graph *graph,
890939
struct audioreach_module *module,
891940
struct audioreach_module_config *cfg)
@@ -1089,25 +1138,33 @@ static int audioreach_shmem_set_media_format(struct q6apm_graph *graph,
10891138
p = p + APM_MODULE_PARAM_DATA_SIZE;
10901139

10911140
header = p;
1092-
header->data_format = DATA_FORMAT_FIXED_POINT;
1093-
header->fmt_id = MEDIA_FMT_ID_PCM;
1094-
header->payload_size = payload_size - sizeof(*header);
1095-
1096-
p = p + sizeof(*header);
1097-
cfg = p;
1098-
cfg->sample_rate = mcfg->sample_rate;
1099-
cfg->bit_width = mcfg->bit_width;
1100-
cfg->alignment = PCM_LSB_ALIGNED;
1101-
cfg->bits_per_sample = mcfg->bit_width;
1102-
cfg->q_factor = mcfg->bit_width - 1;
1103-
cfg->endianness = PCM_LITTLE_ENDIAN;
1104-
cfg->num_channels = mcfg->num_channels;
1105-
1106-
if (mcfg->num_channels == 1) {
1107-
cfg->channel_mapping[0] = PCM_CHANNEL_L;
1108-
} else if (num_channels == 2) {
1109-
cfg->channel_mapping[0] = PCM_CHANNEL_L;
1110-
cfg->channel_mapping[1] = PCM_CHANNEL_R;
1141+
if (mcfg->fmt == SND_AUDIOCODEC_PCM) {
1142+
header->data_format = DATA_FORMAT_FIXED_POINT;
1143+
header->fmt_id = MEDIA_FMT_ID_PCM;
1144+
header->payload_size = payload_size - sizeof(*header);
1145+
1146+
p = p + sizeof(*header);
1147+
cfg = p;
1148+
cfg->sample_rate = mcfg->sample_rate;
1149+
cfg->bit_width = mcfg->bit_width;
1150+
cfg->alignment = PCM_LSB_ALIGNED;
1151+
cfg->bits_per_sample = mcfg->bit_width;
1152+
cfg->q_factor = mcfg->bit_width - 1;
1153+
cfg->endianness = PCM_LITTLE_ENDIAN;
1154+
cfg->num_channels = mcfg->num_channels;
1155+
1156+
if (mcfg->num_channels == 1)
1157+
cfg->channel_mapping[0] = PCM_CHANNEL_L;
1158+
else if (num_channels == 2) {
1159+
cfg->channel_mapping[0] = PCM_CHANNEL_L;
1160+
cfg->channel_mapping[1] = PCM_CHANNEL_R;
1161+
}
1162+
} else {
1163+
rc = audioreach_set_compr_media_format(header, p, mcfg);
1164+
if (rc) {
1165+
kfree(pkt);
1166+
return rc;
1167+
}
11111168
}
11121169

11131170
rc = audioreach_graph_send_cmd_sync(graph, pkt, 0);
@@ -1192,6 +1249,8 @@ int audioreach_set_media_format(struct q6apm_graph *graph, struct audioreach_mod
11921249
case MODULE_ID_PCM_DEC:
11931250
case MODULE_ID_PCM_ENC:
11941251
case MODULE_ID_PCM_CNV:
1252+
case MODULE_ID_PLACEHOLDER_DECODER:
1253+
case MODULE_ID_PLACEHOLDER_ENCODER:
11951254
rc = audioreach_pcm_set_media_format(graph, module, cfg);
11961255
break;
11971256
case MODULE_ID_DISPLAY_PORT_SINK:
@@ -1219,6 +1278,9 @@ int audioreach_set_media_format(struct q6apm_graph *graph, struct audioreach_mod
12191278
case MODULE_ID_MFC:
12201279
rc = audioreach_mfc_set_media_format(graph, module, cfg);
12211280
break;
1281+
case MODULE_ID_GAPLESS:
1282+
rc = audioreach_gapless_set_media_format(graph, module, cfg);
1283+
break;
12221284
default:
12231285
rc = 0;
12241286
}

0 commit comments

Comments
 (0)