Add a new op set_up_volume_table for control IPC ops. Define and set the op for IPC3. Signed-off-by: Ranjani Sridharan <ranjani.sridharan@xxxxxxxxxxxxxxx> Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart@xxxxxxxxxxxxxxx> Reviewed-by: Bard Liao <yung-chuan.liao@xxxxxxxxxxxxxxx> Reviewed-by: Péter Ujfalusi <peter.ujfalusi@xxxxxxxxxxxxxxx> --- sound/soc/sof/ipc3-control.c | 18 ++++++++++++++++++ sound/soc/sof/sof-audio.h | 6 ++++++ sound/soc/sof/topology.c | 26 +++++++++++--------------- 3 files changed, 35 insertions(+), 15 deletions(-) diff --git a/sound/soc/sof/ipc3-control.c b/sound/soc/sof/ipc3-control.c index cde9e481f7f2..bea26e73a741 100644 --- a/sound/soc/sof/ipc3-control.c +++ b/sound/soc/sof/ipc3-control.c @@ -694,6 +694,23 @@ static int sof_ipc3_widget_kcontrol_setup(struct snd_sof_dev *sdev, return 0; } +static int +sof_ipc3_set_up_volume_table(struct snd_sof_control *scontrol, int tlv[SOF_TLV_ITEMS], int size) +{ + int i; + + /* init the volume table */ + scontrol->volume_table = kcalloc(size, sizeof(u32), GFP_KERNEL); + if (!scontrol->volume_table) + return -ENOMEM; + + /* populate the volume table */ + for (i = 0; i < size ; i++) + scontrol->volume_table[i] = vol_compute_gain(i, tlv); + + return 0; +} + const struct sof_ipc_tplg_control_ops tplg_ipc3_control_ops = { .volume_put = sof_ipc3_volume_put, .volume_get = sof_ipc3_volume_get, @@ -708,4 +725,5 @@ const struct sof_ipc_tplg_control_ops tplg_ipc3_control_ops = { .bytes_ext_volatile_get = sof_ipc3_bytes_ext_volatile_get, .update = sof_ipc3_control_update, .widget_kcontrol_setup = sof_ipc3_widget_kcontrol_setup, + .set_up_volume_table = sof_ipc3_set_up_volume_table, }; diff --git a/sound/soc/sof/sof-audio.h b/sound/soc/sof/sof-audio.h index a0af7c421fd9..e254b22ea8a9 100644 --- a/sound/soc/sof/sof-audio.h +++ b/sound/soc/sof/sof-audio.h @@ -39,6 +39,8 @@ */ #define VOLUME_FWL 16 +#define SOF_TLV_ITEMS 3 + struct snd_sof_widget; struct snd_sof_route; struct snd_sof_control; @@ -88,6 +90,9 @@ struct sof_ipc_tplg_control_ops { void (*update)(struct snd_sof_dev *sdev, void *ipc_control_message); /* Optional callback to setup kcontrols associated with an swidget */ int (*widget_kcontrol_setup)(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget); + /* mandatory callback to set up volume table for volume kcontrols */ + int (*set_up_volume_table)(struct snd_sof_control *scontrol, int tlv[SOF_TLV_ITEMS], + int size); }; /** @@ -464,4 +469,5 @@ int sof_update_ipc_object(struct snd_soc_component *scomp, void *object, enum so size_t object_size, int token_instance_num); int sof_pcm_setup_connected_widgets(struct snd_sof_dev *sdev, struct snd_soc_pcm_runtime *rtd, struct snd_sof_pcm *spcm, int dir); +u32 vol_compute_gain(u32 value, int *tlv); #endif diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c index 5e959f8c4cb9..739f343010fc 100644 --- a/sound/soc/sof/topology.c +++ b/sound/soc/sof/topology.c @@ -32,7 +32,6 @@ #define VOL_HALF_DB_STEP 50 /* TLV data items */ -#define TLV_ITEMS 3 #define TLV_MIN 0 #define TLV_STEP 1 #define TLV_MUTE 2 @@ -134,7 +133,7 @@ int sof_update_ipc_object(struct snd_soc_component *scomp, void *object, enum so return 0; } -static inline int get_tlv_data(const int *p, int tlv[TLV_ITEMS]) +static inline int get_tlv_data(const int *p, int tlv[SOF_TLV_ITEMS]) { /* we only support dB scale TLV type at the moment */ if ((int)p[SNDRV_CTL_TLVO_TYPE] != SNDRV_CTL_TLVT_DB_SCALE) @@ -224,7 +223,7 @@ static u32 vol_pow32(u32 a, int exp, u32 fwl) * Function to calculate volume gain from TLV data. * This function can only handle gain steps that are multiples of 0.5 dB */ -static u32 vol_compute_gain(u32 value, int *tlv) +u32 vol_compute_gain(u32 value, int *tlv) { int dB_gain; u32 linear_gain; @@ -263,20 +262,17 @@ static u32 vol_compute_gain(u32 value, int *tlv) * "size" specifies the number of entries in the table */ static int set_up_volume_table(struct snd_sof_control *scontrol, - int tlv[TLV_ITEMS], int size) + int tlv[SOF_TLV_ITEMS], int size) { - int j; - - /* init the volume table */ - scontrol->volume_table = kcalloc(size, sizeof(u32), GFP_KERNEL); - if (!scontrol->volume_table) - return -ENOMEM; + struct snd_soc_component *scomp = scontrol->scomp; + struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); + const struct sof_ipc_tplg_ops *tplg_ops = sdev->ipc->ops->tplg; - /* populate the volume table */ - for (j = 0; j < size ; j++) - scontrol->volume_table[j] = vol_compute_gain(j, tlv); + if (tplg_ops->control->set_up_volume_table) + return tplg_ops->control->set_up_volume_table(scontrol, tlv, size); - return 0; + dev_err(scomp->dev, "Mandatory op %s not set\n", __func__); + return -EINVAL; } struct sof_dai_types { @@ -772,7 +768,7 @@ static int sof_control_load_volume(struct snd_soc_component *scomp, struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); struct snd_soc_tplg_mixer_control *mc = container_of(hdr, struct snd_soc_tplg_mixer_control, hdr); - int tlv[TLV_ITEMS]; + int tlv[SOF_TLV_ITEMS]; unsigned int mask; int ret; -- 2.25.1