ASoC: SOF: Add a new op to set up volume table
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>
This commit is contained in:
Родитель
ce216cfa84
Коммит
48d2a1ceae
|
@ -694,6 +694,23 @@ static int sof_ipc3_widget_kcontrol_setup(struct snd_sof_dev *sdev,
|
||||||
return 0;
|
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 = {
|
const struct sof_ipc_tplg_control_ops tplg_ipc3_control_ops = {
|
||||||
.volume_put = sof_ipc3_volume_put,
|
.volume_put = sof_ipc3_volume_put,
|
||||||
.volume_get = sof_ipc3_volume_get,
|
.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,
|
.bytes_ext_volatile_get = sof_ipc3_bytes_ext_volatile_get,
|
||||||
.update = sof_ipc3_control_update,
|
.update = sof_ipc3_control_update,
|
||||||
.widget_kcontrol_setup = sof_ipc3_widget_kcontrol_setup,
|
.widget_kcontrol_setup = sof_ipc3_widget_kcontrol_setup,
|
||||||
|
.set_up_volume_table = sof_ipc3_set_up_volume_table,
|
||||||
};
|
};
|
||||||
|
|
|
@ -39,6 +39,8 @@
|
||||||
*/
|
*/
|
||||||
#define VOLUME_FWL 16
|
#define VOLUME_FWL 16
|
||||||
|
|
||||||
|
#define SOF_TLV_ITEMS 3
|
||||||
|
|
||||||
struct snd_sof_widget;
|
struct snd_sof_widget;
|
||||||
struct snd_sof_route;
|
struct snd_sof_route;
|
||||||
struct snd_sof_control;
|
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);
|
void (*update)(struct snd_sof_dev *sdev, void *ipc_control_message);
|
||||||
/* Optional callback to setup kcontrols associated with an swidget */
|
/* Optional callback to setup kcontrols associated with an swidget */
|
||||||
int (*widget_kcontrol_setup)(struct snd_sof_dev *sdev, struct snd_sof_widget *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);
|
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,
|
int sof_pcm_setup_connected_widgets(struct snd_sof_dev *sdev, struct snd_soc_pcm_runtime *rtd,
|
||||||
struct snd_sof_pcm *spcm, int dir);
|
struct snd_sof_pcm *spcm, int dir);
|
||||||
|
u32 vol_compute_gain(u32 value, int *tlv);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -32,7 +32,6 @@
|
||||||
#define VOL_HALF_DB_STEP 50
|
#define VOL_HALF_DB_STEP 50
|
||||||
|
|
||||||
/* TLV data items */
|
/* TLV data items */
|
||||||
#define TLV_ITEMS 3
|
|
||||||
#define TLV_MIN 0
|
#define TLV_MIN 0
|
||||||
#define TLV_STEP 1
|
#define TLV_STEP 1
|
||||||
#define TLV_MUTE 2
|
#define TLV_MUTE 2
|
||||||
|
@ -134,7 +133,7 @@ int sof_update_ipc_object(struct snd_soc_component *scomp, void *object, enum so
|
||||||
return 0;
|
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 */
|
/* we only support dB scale TLV type at the moment */
|
||||||
if ((int)p[SNDRV_CTL_TLVO_TYPE] != SNDRV_CTL_TLVT_DB_SCALE)
|
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.
|
* Function to calculate volume gain from TLV data.
|
||||||
* This function can only handle gain steps that are multiples of 0.5 dB
|
* 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;
|
int dB_gain;
|
||||||
u32 linear_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
|
* "size" specifies the number of entries in the table
|
||||||
*/
|
*/
|
||||||
static int set_up_volume_table(struct snd_sof_control *scontrol,
|
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;
|
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;
|
||||||
|
|
||||||
/* init the volume table */
|
if (tplg_ops->control->set_up_volume_table)
|
||||||
scontrol->volume_table = kcalloc(size, sizeof(u32), GFP_KERNEL);
|
return tplg_ops->control->set_up_volume_table(scontrol, tlv, size);
|
||||||
if (!scontrol->volume_table)
|
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
/* populate the volume table */
|
dev_err(scomp->dev, "Mandatory op %s not set\n", __func__);
|
||||||
for (j = 0; j < size ; j++)
|
return -EINVAL;
|
||||||
scontrol->volume_table[j] = vol_compute_gain(j, tlv);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct sof_dai_types {
|
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_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
|
||||||
struct snd_soc_tplg_mixer_control *mc =
|
struct snd_soc_tplg_mixer_control *mc =
|
||||||
container_of(hdr, struct snd_soc_tplg_mixer_control, hdr);
|
container_of(hdr, struct snd_soc_tplg_mixer_control, hdr);
|
||||||
int tlv[TLV_ITEMS];
|
int tlv[SOF_TLV_ITEMS];
|
||||||
unsigned int mask;
|
unsigned int mask;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче