Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions include/uapi/sound/snd_ar_tokens.h
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,16 @@ enum ar_event_types {
#define AR_TKN_U32_MODULE_LOG_TAP_POINT_ID 260
#define AR_TKN_U32_MODULE_LOG_MODE 261

#define AR_TKN_U32_MODULE_SYNC_SRC 262
#define AR_TKN_U32_MODULE_CTRL_DATA_OUT_ENABLE 263
#define AR_TKN_U32_MODULE_SLOT_MASK 264
#define AR_TKN_U32_MODULE_NSLOTS_PER_FRAME 265
#define AR_TKN_U32_MODULE_SLOT_WIDTH 266
#define AR_TKN_U32_MODULE_SYNC_MODE 267
#define AR_TKN_U32_MODULE_CTRL_INVERT_SYNC_PULSE 268
#define AR_TKN_U32_MODULE_CTRL_SYNC_DATA_DELAY 269
#define AR_TKN_U32_MODULE_RESERVED 270

#define SND_SOC_AR_TPLG_MODULE_CFG_TYPE 0x01001006
struct audioreach_module_priv_data {
__le32 size; /* size in bytes of the array, including all elements */
Expand Down
83 changes: 83 additions & 0 deletions sound/soc/qcom/qdsp6/audioreach.c
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,13 @@ struct apm_i2s_module_intf_cfg {

#define APM_I2S_INTF_CFG_PSIZE ALIGN(sizeof(struct apm_i2s_module_intf_cfg), 8)

struct apm_tdm_module_intf_cfg {
struct apm_module_param_data param_data;
struct param_id_tdm_intf_cfg cfg;
} __packed;

#define APM_TDM_INTF_CFG_PSIZE ALIGN(sizeof(struct apm_tdm_module_intf_cfg), 8)

struct apm_module_hw_ep_mf_cfg {
struct apm_module_param_data param_data;
struct param_id_hw_ep_mf mf;
Expand Down Expand Up @@ -1067,6 +1074,78 @@ static int audioreach_i2s_set_media_format(struct q6apm_graph *graph,
return rc;
}

static int audioreach_tdm_set_media_format(struct q6apm_graph *graph,
struct audioreach_module *module,
struct audioreach_module_config *cfg)
{
struct apm_module_frame_size_factor_cfg *fs_cfg;
struct apm_module_param_data *param_data;
struct apm_tdm_module_intf_cfg *intf_cfg;
struct apm_module_hw_ep_mf_cfg *hw_cfg;
int ic_sz, ep_sz, fs_sz;
int rc, payload_size;
struct gpr_pkt *pkt;
void *p;

ic_sz = APM_TDM_INTF_CFG_PSIZE;
ep_sz = APM_HW_EP_CFG_PSIZE;
fs_sz = APM_FS_CFG_PSIZE;

payload_size = ic_sz + ep_sz + fs_sz;

pkt = audioreach_alloc_apm_cmd_pkt(payload_size, APM_CMD_SET_CFG, 0);
if (IS_ERR(pkt))
return PTR_ERR(pkt);

p = (void *)pkt + GPR_HDR_SIZE + APM_CMD_HDR_SIZE;
intf_cfg = p;

param_data = &intf_cfg->param_data;
param_data->module_instance_id = module->instance_id;
param_data->error_code = 0;
param_data->param_id = PARAM_ID_TDM_INTF_CFG;
param_data->param_size = ic_sz - APM_MODULE_PARAM_DATA_SIZE;

intf_cfg->cfg.intf_idx = module->hw_interface_idx;
intf_cfg->cfg.sync_src = module->sync_src;
intf_cfg->cfg.ctrl_data_out_enable = module->ctrl_data_out_enable;
intf_cfg->cfg.slot_mask = module->slot_mask;
intf_cfg->cfg.nslots_per_frame = module->nslots_per_frame;
intf_cfg->cfg.slot_width = module->slot_width;
intf_cfg->cfg.sync_mode = module->sync_mode;
intf_cfg->cfg.ctrl_invert_sync_pulse = module->ctrl_invert_sync_pulse;
intf_cfg->cfg.ctrl_sync_data_delay = module->ctrl_sync_data_delay;
intf_cfg->cfg.reserved = module->reserved;

p += ic_sz;
hw_cfg = p;
param_data = &hw_cfg->param_data;
param_data->module_instance_id = module->instance_id;
param_data->error_code = 0;
param_data->param_id = PARAM_ID_HW_EP_MF_CFG;
param_data->param_size = ep_sz - APM_MODULE_PARAM_DATA_SIZE;

hw_cfg->mf.sample_rate = cfg->sample_rate;
hw_cfg->mf.bit_width = cfg->bit_width;
hw_cfg->mf.num_channels = cfg->num_channels;
hw_cfg->mf.data_format = module->data_format;

p += ep_sz;
fs_cfg = p;
param_data = &fs_cfg->param_data;
param_data->module_instance_id = module->instance_id;
param_data->error_code = 0;
param_data->param_id = PARAM_ID_HW_EP_FRAME_SIZE_FACTOR;
param_data->param_size = fs_sz - APM_MODULE_PARAM_DATA_SIZE;
fs_cfg->frame_size_factor = 1;

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

kfree(pkt);

return rc;
}

static int audioreach_logging_set_media_format(struct q6apm_graph *graph,
struct audioreach_module *module)
{
Expand Down Expand Up @@ -1306,6 +1385,10 @@ int audioreach_set_media_format(struct q6apm_graph *graph, struct audioreach_mod
case MODULE_ID_I2S_SINK:
rc = audioreach_i2s_set_media_format(graph, module, cfg);
break;
case MODULE_ID_TDM_SOURCE:
case MODULE_ID_TDM_SINK:
rc = audioreach_tdm_set_media_format(graph, module, cfg);
break;
case MODULE_ID_WR_SHARED_MEM_EP:
rc = audioreach_shmem_set_media_format(graph, module, cfg);
break;
Expand Down
43 changes: 43 additions & 0 deletions sound/soc/qcom/qdsp6/audioreach.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ struct q6apm_graph;
#define MODULE_ID_PLACEHOLDER_DECODER 0x07001009
#define MODULE_ID_I2S_SINK 0x0700100A
#define MODULE_ID_I2S_SOURCE 0x0700100B
#define MODULE_ID_TDM_SINK 0x0700100E
#define MODULE_ID_TDM_SOURCE 0x0700100F
#define MODULE_ID_SAL 0x07001010
#define MODULE_ID_MFC 0x07001015
#define MODULE_ID_DATA_LOGGING 0x0700101A
Expand Down Expand Up @@ -493,6 +495,36 @@ struct param_id_i2s_intf_cfg {
#define PORT_ID_I2S_OUPUT 1
#define I2S_STACK_SIZE 2048

#define CONFIG_TDM_SYNC_SRC_EXTERNAL 0x0
#define CONFIG_TDM_SYNC_SRC_INTERNAL 0x1

#define PARAM_ID_TDM_INTF_CFG 0x0800101B

struct param_id_tdm_intf_cfg {
uint32_t lpaif_type;
uint32_t intf_idx;
uint16_t sync_src;
uint16_t ctrl_data_out_enable;
uint32_t slot_mask;
uint16_t nslots_per_frame;
uint16_t slot_width;
uint16_t sync_mode;
uint16_t ctrl_invert_sync_pulse;
uint16_t ctrl_sync_data_delay;
uint16_t reserved;
} __packed;


#define TDM_INTF_TYPE_PRIMARY 0
#define TDM_INTF_TYPE_SECOINDARY 1
#define TDM_INTF_TYPE_TERTINARY 2
#define TDM_INTF_TYPE_QUATERNARY 3
#define TDM_INTF_TYPE_QUINARY 4

#define PORT_ID_TDM_INPUT 2
#define PORT_ID_TDM_OUPUT 1
#define TDM_STACK_SIZE 2048

#define PARAM_ID_DISPLAY_PORT_INTF_CFG 0x08001154

struct param_id_display_port_intf_cfg {
Expand Down Expand Up @@ -746,6 +778,17 @@ struct audioreach_module {
uint32_t data_format;
uint32_t hw_interface_type;

/* TDM module */
uint32_t sync_src;
uint32_t ctrl_data_out_enable;
uint32_t slot_mask;
uint32_t nslots_per_frame;
uint32_t slot_width;
uint32_t sync_mode;
uint32_t ctrl_invert_sync_pulse;
uint32_t ctrl_sync_data_delay;
uint32_t reserved;

/* PCM module specific */
uint32_t interleave_type;

Expand Down
9 changes: 9 additions & 0 deletions sound/soc/qcom/qdsp6/q6apm-lpass-dais.c
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,14 @@ static const struct snd_soc_dai_ops q6hdmi_ops = {
.set_fmt = q6i2s_set_fmt,
};

static const struct snd_soc_dai_ops q6tdm_ops = {
.prepare = q6apm_lpass_dai_prepare,
.startup = q6apm_lpass_dai_startup,
.shutdown = q6apm_lpass_dai_shutdown,
.set_channel_map = q6dma_set_channel_map,
.hw_params = q6i2s_set_fmt,
};

static const struct snd_soc_component_driver q6apm_lpass_dai_component = {
.name = "q6apm-be-dai-component",
.of_xlate_dai_name = q6dsp_audio_ports_of_xlate_dai_name,
Expand All @@ -298,6 +306,7 @@ static int q6apm_lpass_dai_dev_probe(struct platform_device *pdev)
cfg.q6i2s_ops = &q6i2s_ops;
cfg.q6dma_ops = &q6dma_ops;
cfg.q6hdmi_ops = &q6hdmi_ops;
cfg.q6tdm_ops = &q6tdm_ops;
dais = q6dsp_audio_ports_set_config(dev, &cfg, &num_dais);

return devm_snd_soc_register_component(dev, &q6apm_lpass_dai_component, dais, num_dais);
Expand Down
60 changes: 60 additions & 0 deletions sound/soc/qcom/qdsp6/topology.c
Original file line number Diff line number Diff line change
Expand Up @@ -753,6 +753,62 @@ static int audioreach_widget_i2s_module_load(struct audioreach_module *mod,
return 0;
}

static int audioreach_widget_tdm_module_load(struct audioreach_module *mod,
struct snd_soc_tplg_vendor_array *mod_array)
{
struct snd_soc_tplg_vendor_value_elem *mod_elem;
int tkn_count = 0;

mod_elem = mod_array->value;

while (tkn_count <= (le32_to_cpu(mod_array->num_elems) - 1)) {
switch (le32_to_cpu(mod_elem->token)) {
case AR_TKN_U32_MODULE_HW_IF_IDX:
mod->hw_interface_idx = le32_to_cpu(mod_elem->value);
break;
case AR_TKN_U32_MODULE_FMT_DATA:
mod->data_format = le32_to_cpu(mod_elem->value);
break;
case AR_TKN_U32_MODULE_HW_IF_TYPE:
mod->hw_interface_type = le32_to_cpu(mod_elem->value);
break;
case AR_TKN_U32_MODULE_SYNC_SRC:
mod->sync_src = le32_to_cpu(mod_elem->value);
break;
case AR_TKN_U32_MODULE_CTRL_DATA_OUT_ENABLE:
mod->ctrl_data_out_enable = le32_to_cpu(mod_elem->value);
break;
case AR_TKN_U32_MODULE_SLOT_MASK:
mod->slot_mask = le32_to_cpu(mod_elem->value);
break;
case AR_TKN_U32_MODULE_NSLOTS_PER_FRAME:
mod->nslots_per_frame = le32_to_cpu(mod_elem->value);
break;
case AR_TKN_U32_MODULE_SLOT_WIDTH:
mod->slot_width = le32_to_cpu(mod_elem->value);
break;
case AR_TKN_U32_MODULE_SYNC_MODE:
mod->sync_mode = le32_to_cpu(mod_elem->value);
break;
case AR_TKN_U32_MODULE_CTRL_INVERT_SYNC_PULSE:
mod->ctrl_invert_sync_pulse = le32_to_cpu(mod_elem->value);
break;
case AR_TKN_U32_MODULE_CTRL_SYNC_DATA_DELAY:
mod->ctrl_sync_data_delay = le32_to_cpu(mod_elem->value);
break;
case AR_TKN_U32_MODULE_RESERVED:
mod->reserved = le32_to_cpu(mod_elem->value);
break;
default:
break;
}
tkn_count++;
mod_elem++;
}

return 0;
}

static int audioreach_widget_dp_module_load(struct audioreach_module *mod,
struct snd_soc_tplg_vendor_array *mod_array)
{
Expand Down Expand Up @@ -806,6 +862,10 @@ static int audioreach_widget_load_buffer(struct snd_soc_component *component,
case MODULE_ID_I2S_SOURCE:
audioreach_widget_i2s_module_load(mod, mod_array);
break;
case MODULE_ID_TDM_SINK:
case MODULE_ID_TDM_SOURCE:
audioreach_widget_tdm_module_load(mod, mod_array);
break;
case MODULE_ID_DISPLAY_PORT_SINK:
audioreach_widget_dp_module_load(mod, mod_array);
break;
Expand Down