Skip to content

Commit ce13062

Browse files
committed
ASoC: SOF: ipc4-topology: implement KCPS adjustment
The SOF already supports the REGISTER_KCPS IPC, this patch also adds support for it to the driver. A new topology token is used for this, which specified the KCPS requirement for each pipeline. When a pipeline is created, that had a KCPS value specified for it in the topology, that value is sent to the firmware for clock adjustment. When such a pipeline is destroyed, the same negative value is sent to return the system clock rate to the original state. Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
1 parent cff45ee commit ce13062

File tree

4 files changed

+38
-0
lines changed

4 files changed

+38
-0
lines changed

include/sound/sof/ipc4/header.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -389,6 +389,7 @@ enum sof_ipc4_base_fw_params {
389389
SOF_IPC4_FW_PARAM_MODULES_INFO_GET,
390390
SOF_IPC4_FW_PARAM_LIBRARIES_INFO_GET = 16,
391391
SOF_IPC4_FW_PARAM_SYSTEM_TIME = 20,
392+
SOF_IPC4_FW_PARAM_REGISTER_KCPS = 22,
392393
};
393394

394395
enum sof_ipc4_fw_config_params {

include/uapi/sound/sof/tokens.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
#define SOF_TKN_SCHED_LP_MODE 207
5656
#define SOF_TKN_SCHED_MEM_USAGE 208
5757
#define SOF_TKN_SCHED_USE_CHAIN_DMA 209
58+
#define SOF_TKN_SCHED_PIPELINE_KCPS 210
5859

5960
/* volume */
6061
#define SOF_TKN_VOLUME_RAMP_STEP_TYPE 250

sound/soc/sof/ipc4-topology.c

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ static const struct sof_topology_token ipc4_sched_tokens[] = {
3131
offsetof(struct sof_ipc4_pipeline, use_chain_dma)},
3232
{SOF_TKN_SCHED_CORE, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
3333
offsetof(struct sof_ipc4_pipeline, core_id)},
34+
{SOF_TKN_SCHED_PIPELINE_KCPS, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
35+
offsetof(struct sof_ipc4_pipeline, kcps)},
3436
};
3537

3638
static const struct sof_topology_token pipeline_tokens[] = {
@@ -1976,12 +1978,30 @@ static int sof_ipc4_control_setup(struct snd_sof_dev *sdev, struct snd_sof_contr
19761978
return 0;
19771979
}
19781980

1981+
static int sof_ipc4_send_kcps(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget,
1982+
__s32 delta_kcps)
1983+
{
1984+
const struct sof_ipc_ops *iops = sdev->ipc->ops;
1985+
struct sof_ipc4_msg msg = {
1986+
.primary = SOF_IPC4_MSG_TARGET(SOF_IPC4_MODULE_MSG) |
1987+
SOF_IPC4_MSG_DIR(SOF_IPC4_MSG_REQUEST) |
1988+
SOF_IPC4_MOD_ID(SOF_IPC4_MOD_INIT_BASEFW_MOD_ID) |
1989+
SOF_IPC4_MOD_INSTANCE(SOF_IPC4_MOD_INIT_BASEFW_INSTANCE_ID),
1990+
.extension = SOF_IPC4_MOD_EXT_MSG_PARAM_ID(SOF_IPC4_FW_PARAM_REGISTER_KCPS),
1991+
.data_size = sizeof(delta_kcps),
1992+
.data_ptr = &delta_kcps,
1993+
};
1994+
1995+
return iops->set_get_data(sdev, &msg, msg.data_size, true);
1996+
}
1997+
19791998
static int sof_ipc4_widget_setup(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget)
19801999
{
19812000
struct snd_sof_widget *pipe_widget = swidget->spipe->pipe_widget;
19822001
struct sof_ipc4_fw_data *ipc4_data = sdev->private;
19832002
struct sof_ipc4_pipeline *pipeline;
19842003
struct sof_ipc4_msg *msg;
2004+
__s32 delta_kcps = 0;
19852005
void *ipc_data = NULL;
19862006
u32 ipc_size = 0;
19872007
int ret;
@@ -2008,6 +2028,7 @@ static int sof_ipc4_widget_setup(struct snd_sof_dev *sdev, struct snd_sof_widget
20082028
}
20092029
msg->primary &= ~SOF_IPC4_GLB_PIPE_INSTANCE_MASK;
20102030
msg->primary |= SOF_IPC4_GLB_PIPE_INSTANCE_ID(swidget->instance_id);
2031+
delta_kcps = pipeline->kcps;
20112032
break;
20122033
case snd_soc_dapm_aif_in:
20132034
case snd_soc_dapm_aif_out:
@@ -2127,6 +2148,12 @@ static int sof_ipc4_widget_setup(struct snd_sof_dev *sdev, struct snd_sof_widget
21272148
} else {
21282149
ida_free(&pipeline_ida, swidget->instance_id);
21292150
}
2151+
} else if (delta_kcps) {
2152+
ret = sof_ipc4_send_kcps(sdev, swidget, delta_kcps);
2153+
if (ret < 0) {
2154+
dev_warn(sdev->dev, "failed to increase KCPS: %d, continuing\n", ret);
2155+
ret = 0;
2156+
}
21302157
}
21312158

21322159
return ret;
@@ -2161,6 +2188,13 @@ static int sof_ipc4_widget_free(struct snd_sof_dev *sdev, struct snd_sof_widget
21612188
dev_err(sdev->dev, "failed to free pipeline widget %s\n",
21622189
swidget->widget->name);
21632190

2191+
if (pipeline->kcps) {
2192+
ret = sof_ipc4_send_kcps(sdev, swidget, -pipeline->kcps);
2193+
if (ret < 0)
2194+
dev_warn(sdev->dev,
2195+
"failed to decrease KCPS: %d, continuing\n", ret);
2196+
}
2197+
21642198
pipeline->mem_usage = 0;
21652199
pipeline->state = SOF_IPC4_PIPE_UNINITIALIZED;
21662200
ida_free(&pipeline_ida, swidget->instance_id);

sound/soc/sof/ipc4-topology.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@ struct sof_ipc4_copier_config_set_sink_format {
125125
* @lp_mode: Low power mode
126126
* @mem_usage: Memory usage
127127
* @core_id: Target core for the pipeline
128+
* @kcps: optionally provided by the topology pipeline KCPS requirement
128129
* @state: Pipeline state
129130
* @use_chain_dma: flag to indicate if the firmware shall use chained DMA
130131
* @msg: message structure for pipeline
@@ -135,6 +136,7 @@ struct sof_ipc4_pipeline {
135136
uint32_t lp_mode;
136137
uint32_t mem_usage;
137138
uint32_t core_id;
139+
uint32_t kcps;
138140
int state;
139141
bool use_chain_dma;
140142
struct sof_ipc4_msg msg;

0 commit comments

Comments
 (0)