OSDN Git Service

ASoC: SOF: Add a new op to set up volume table
authorRanjani Sridharan <ranjani.sridharan@linux.intel.com>
Tue, 26 Apr 2022 17:17:33 +0000 (10:17 -0700)
committerMark Brown <broonie@kernel.org>
Fri, 29 Apr 2022 12:05:54 +0000 (13:05 +0100)
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@linux.intel.com>
Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Reviewed-by: Bard Liao <yung-chuan.liao@linux.intel.com>
Reviewed-by: Péter Ujfalusi <peter.ujfalusi@linux.intel.com>
Link: https://lore.kernel.org/r/20220426171743.171061-2-ranjani.sridharan@linux.intel.com
Signed-off-by: Mark Brown <broonie@kernel.org>
sound/soc/sof/ipc3-control.c
sound/soc/sof/sof-audio.h
sound/soc/sof/topology.c

index cde9e48..bea26e7 100644 (file)
@@ -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,
 };
index f36c4f6..d8ab860 100644 (file)
@@ -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);
 };
 
 /**
@@ -463,4 +468,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
index 5e959f8..739f343 100644 (file)
@@ -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;