1 // SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
3 // This file is provided under a dual BSD/GPLv2 license. When using or
4 // redistributing this file, you may do so under either license.
6 // Copyright(c) 2018 Intel Corporation. All rights reserved.
8 // Author: Liam Girdwood <liam.r.girdwood@linux.intel.com>
13 #include <linux/pm_runtime.h>
14 #include <linux/leds.h>
16 #include "sof-audio.h"
18 int snd_sof_volume_get(struct snd_kcontrol *kcontrol,
19 struct snd_ctl_elem_value *ucontrol)
21 struct soc_mixer_control *sm = (struct soc_mixer_control *)kcontrol->private_value;
22 struct snd_sof_control *scontrol = sm->dobj.private;
23 struct snd_soc_component *scomp = scontrol->scomp;
24 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
25 const struct sof_ipc_tplg_ops *tplg_ops = sof_ipc_get_ops(sdev, tplg);
27 if (tplg_ops && tplg_ops->control && tplg_ops->control->volume_get)
28 return tplg_ops->control->volume_get(scontrol, ucontrol);
33 int snd_sof_volume_put(struct snd_kcontrol *kcontrol,
34 struct snd_ctl_elem_value *ucontrol)
36 struct soc_mixer_control *sm = (struct soc_mixer_control *)kcontrol->private_value;
37 struct snd_sof_control *scontrol = sm->dobj.private;
38 struct snd_soc_component *scomp = scontrol->scomp;
39 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
40 const struct sof_ipc_tplg_ops *tplg_ops = sof_ipc_get_ops(sdev, tplg);
42 if (tplg_ops && tplg_ops->control && tplg_ops->control->volume_put)
43 return tplg_ops->control->volume_put(scontrol, ucontrol);
48 int snd_sof_volume_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
50 struct soc_mixer_control *sm = (struct soc_mixer_control *)kcontrol->private_value;
51 struct snd_sof_control *scontrol = sm->dobj.private;
52 unsigned int channels = scontrol->num_channels;
55 if (!sm->platform_max)
56 sm->platform_max = sm->max;
57 platform_max = sm->platform_max;
59 if (platform_max == 1 && !strstr(kcontrol->id.name, " Volume"))
60 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
62 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
64 uinfo->count = channels;
65 uinfo->value.integer.min = 0;
66 uinfo->value.integer.max = platform_max - sm->min;
70 int snd_sof_switch_get(struct snd_kcontrol *kcontrol,
71 struct snd_ctl_elem_value *ucontrol)
73 struct soc_mixer_control *sm = (struct soc_mixer_control *)kcontrol->private_value;
74 struct snd_sof_control *scontrol = sm->dobj.private;
75 struct snd_soc_component *scomp = scontrol->scomp;
76 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
77 const struct sof_ipc_tplg_ops *tplg_ops = sof_ipc_get_ops(sdev, tplg);
79 if (tplg_ops && tplg_ops->control && tplg_ops->control->switch_get)
80 return tplg_ops->control->switch_get(scontrol, ucontrol);
85 int snd_sof_switch_put(struct snd_kcontrol *kcontrol,
86 struct snd_ctl_elem_value *ucontrol)
88 struct soc_mixer_control *sm = (struct soc_mixer_control *)kcontrol->private_value;
89 struct snd_sof_control *scontrol = sm->dobj.private;
90 struct snd_soc_component *scomp = scontrol->scomp;
91 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
92 const struct sof_ipc_tplg_ops *tplg_ops = sof_ipc_get_ops(sdev, tplg);
94 if (tplg_ops && tplg_ops->control && tplg_ops->control->switch_put)
95 return tplg_ops->control->switch_put(scontrol, ucontrol);
100 int snd_sof_enum_get(struct snd_kcontrol *kcontrol,
101 struct snd_ctl_elem_value *ucontrol)
103 struct soc_enum *se = (struct soc_enum *)kcontrol->private_value;
104 struct snd_sof_control *scontrol = se->dobj.private;
105 struct snd_soc_component *scomp = scontrol->scomp;
106 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
107 const struct sof_ipc_tplg_ops *tplg_ops = sof_ipc_get_ops(sdev, tplg);
109 if (tplg_ops && tplg_ops->control && tplg_ops->control->enum_get)
110 return tplg_ops->control->enum_get(scontrol, ucontrol);
115 int snd_sof_enum_put(struct snd_kcontrol *kcontrol,
116 struct snd_ctl_elem_value *ucontrol)
118 struct soc_enum *se = (struct soc_enum *)kcontrol->private_value;
119 struct snd_sof_control *scontrol = se->dobj.private;
120 struct snd_soc_component *scomp = scontrol->scomp;
121 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
122 const struct sof_ipc_tplg_ops *tplg_ops = sof_ipc_get_ops(sdev, tplg);
124 if (tplg_ops && tplg_ops->control && tplg_ops->control->enum_put)
125 return tplg_ops->control->enum_put(scontrol, ucontrol);
130 int snd_sof_bytes_get(struct snd_kcontrol *kcontrol,
131 struct snd_ctl_elem_value *ucontrol)
133 struct soc_bytes_ext *be = (struct soc_bytes_ext *)kcontrol->private_value;
134 struct snd_sof_control *scontrol = be->dobj.private;
135 struct snd_soc_component *scomp = scontrol->scomp;
136 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
137 const struct sof_ipc_tplg_ops *tplg_ops = sof_ipc_get_ops(sdev, tplg);
139 if (tplg_ops && tplg_ops->control && tplg_ops->control->bytes_get)
140 return tplg_ops->control->bytes_get(scontrol, ucontrol);
145 int snd_sof_bytes_put(struct snd_kcontrol *kcontrol,
146 struct snd_ctl_elem_value *ucontrol)
148 struct soc_bytes_ext *be = (struct soc_bytes_ext *)kcontrol->private_value;
149 struct snd_sof_control *scontrol = be->dobj.private;
150 struct snd_soc_component *scomp = scontrol->scomp;
151 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
152 const struct sof_ipc_tplg_ops *tplg_ops = sof_ipc_get_ops(sdev, tplg);
154 if (tplg_ops && tplg_ops->control && tplg_ops->control->bytes_put)
155 return tplg_ops->control->bytes_put(scontrol, ucontrol);
160 int snd_sof_bytes_ext_put(struct snd_kcontrol *kcontrol,
161 const unsigned int __user *binary_data,
164 struct soc_bytes_ext *be = (struct soc_bytes_ext *)kcontrol->private_value;
165 struct snd_sof_control *scontrol = be->dobj.private;
166 struct snd_soc_component *scomp = scontrol->scomp;
167 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
168 const struct sof_ipc_tplg_ops *tplg_ops = sof_ipc_get_ops(sdev, tplg);
170 /* make sure we have at least a header */
171 if (size < sizeof(struct snd_ctl_tlv))
174 if (tplg_ops && tplg_ops->control && tplg_ops->control->bytes_ext_put)
175 return tplg_ops->control->bytes_ext_put(scontrol, binary_data, size);
180 int snd_sof_bytes_ext_volatile_get(struct snd_kcontrol *kcontrol, unsigned int __user *binary_data,
183 struct soc_bytes_ext *be = (struct soc_bytes_ext *)kcontrol->private_value;
184 struct snd_sof_control *scontrol = be->dobj.private;
185 struct snd_soc_component *scomp = scontrol->scomp;
186 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
187 const struct sof_ipc_tplg_ops *tplg_ops = sof_ipc_get_ops(sdev, tplg);
190 ret = pm_runtime_resume_and_get(scomp->dev);
191 if (ret < 0 && ret != -EACCES) {
192 dev_err_ratelimited(scomp->dev, "%s: failed to resume %d\n", __func__, ret);
196 if (tplg_ops && tplg_ops->control && tplg_ops->control->bytes_ext_volatile_get)
197 ret = tplg_ops->control->bytes_ext_volatile_get(scontrol, binary_data, size);
199 pm_runtime_mark_last_busy(scomp->dev);
200 err = pm_runtime_put_autosuspend(scomp->dev);
202 dev_err_ratelimited(scomp->dev, "%s: failed to idle %d\n", __func__, err);
207 int snd_sof_bytes_ext_get(struct snd_kcontrol *kcontrol,
208 unsigned int __user *binary_data,
211 struct soc_bytes_ext *be = (struct soc_bytes_ext *)kcontrol->private_value;
212 struct snd_sof_control *scontrol = be->dobj.private;
213 struct snd_soc_component *scomp = scontrol->scomp;
214 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
215 const struct sof_ipc_tplg_ops *tplg_ops = sof_ipc_get_ops(sdev, tplg);
217 if (tplg_ops && tplg_ops->control && tplg_ops->control->bytes_ext_get)
218 return tplg_ops->control->bytes_ext_get(scontrol, binary_data, size);