1e149ca29SPierre-Louis Bossart // SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
2c3078f53SLiam Girdwood //
3c3078f53SLiam Girdwood // This file is provided under a dual BSD/GPLv2 license. When using or
4c3078f53SLiam Girdwood // redistributing this file, you may do so under either license.
5c3078f53SLiam Girdwood //
6c3078f53SLiam Girdwood // Copyright(c) 2018 Intel Corporation. All rights reserved.
7c3078f53SLiam Girdwood //
8c3078f53SLiam Girdwood // Author: Liam Girdwood <liam.r.girdwood@linux.intel.com>
9c3078f53SLiam Girdwood //
10c3078f53SLiam Girdwood
11c3078f53SLiam Girdwood /* Mixer Controls */
12c3078f53SLiam Girdwood
13c3078f53SLiam Girdwood #include <linux/pm_runtime.h>
145d43001aSJaska Uimonen #include <linux/leds.h>
15c3078f53SLiam Girdwood #include "sof-priv.h"
16ee1e79b7SRanjani Sridharan #include "sof-audio.h"
17c3078f53SLiam Girdwood
snd_sof_volume_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)18c3078f53SLiam Girdwood int snd_sof_volume_get(struct snd_kcontrol *kcontrol,
19c3078f53SLiam Girdwood struct snd_ctl_elem_value *ucontrol)
20c3078f53SLiam Girdwood {
21838d04f3SRanjani Sridharan struct soc_mixer_control *sm = (struct soc_mixer_control *)kcontrol->private_value;
22c3078f53SLiam Girdwood struct snd_sof_control *scontrol = sm->dobj.private;
23838d04f3SRanjani Sridharan struct snd_soc_component *scomp = scontrol->scomp;
24838d04f3SRanjani Sridharan struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
25*cfa12c36SPeter Ujfalusi const struct sof_ipc_tplg_ops *tplg_ops = sof_ipc_get_ops(sdev, tplg);
26c3078f53SLiam Girdwood
27*cfa12c36SPeter Ujfalusi if (tplg_ops && tplg_ops->control && tplg_ops->control->volume_get)
28838d04f3SRanjani Sridharan return tplg_ops->control->volume_get(scontrol, ucontrol);
29c3078f53SLiam Girdwood
30c3078f53SLiam Girdwood return 0;
31c3078f53SLiam Girdwood }
32c3078f53SLiam Girdwood
snd_sof_volume_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)33c3078f53SLiam Girdwood int snd_sof_volume_put(struct snd_kcontrol *kcontrol,
34c3078f53SLiam Girdwood struct snd_ctl_elem_value *ucontrol)
35c3078f53SLiam Girdwood {
36838d04f3SRanjani Sridharan struct soc_mixer_control *sm = (struct soc_mixer_control *)kcontrol->private_value;
37c3078f53SLiam Girdwood struct snd_sof_control *scontrol = sm->dobj.private;
38ee1e79b7SRanjani Sridharan struct snd_soc_component *scomp = scontrol->scomp;
39838d04f3SRanjani Sridharan struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
40*cfa12c36SPeter Ujfalusi const struct sof_ipc_tplg_ops *tplg_ops = sof_ipc_get_ops(sdev, tplg);
41c3078f53SLiam Girdwood
42*cfa12c36SPeter Ujfalusi if (tplg_ops && tplg_ops->control && tplg_ops->control->volume_put)
43838d04f3SRanjani Sridharan return tplg_ops->control->volume_put(scontrol, ucontrol);
44c3078f53SLiam Girdwood
45838d04f3SRanjani Sridharan return false;
46c3078f53SLiam Girdwood }
47c3078f53SLiam Girdwood
snd_sof_volume_info(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)48fca18e62SJaska Uimonen int snd_sof_volume_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
49fca18e62SJaska Uimonen {
50fca18e62SJaska Uimonen struct soc_mixer_control *sm = (struct soc_mixer_control *)kcontrol->private_value;
51fca18e62SJaska Uimonen struct snd_sof_control *scontrol = sm->dobj.private;
52fca18e62SJaska Uimonen unsigned int channels = scontrol->num_channels;
53fca18e62SJaska Uimonen int platform_max;
54fca18e62SJaska Uimonen
55fca18e62SJaska Uimonen if (!sm->platform_max)
56fca18e62SJaska Uimonen sm->platform_max = sm->max;
57fca18e62SJaska Uimonen platform_max = sm->platform_max;
58fca18e62SJaska Uimonen
59fca18e62SJaska Uimonen if (platform_max == 1 && !strstr(kcontrol->id.name, " Volume"))
60fca18e62SJaska Uimonen uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
61fca18e62SJaska Uimonen else
62fca18e62SJaska Uimonen uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
63fca18e62SJaska Uimonen
64fca18e62SJaska Uimonen uinfo->count = channels;
65fca18e62SJaska Uimonen uinfo->value.integer.min = 0;
66fca18e62SJaska Uimonen uinfo->value.integer.max = platform_max - sm->min;
67fca18e62SJaska Uimonen return 0;
68fca18e62SJaska Uimonen }
69fca18e62SJaska Uimonen
snd_sof_switch_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)70c3078f53SLiam Girdwood int snd_sof_switch_get(struct snd_kcontrol *kcontrol,
71c3078f53SLiam Girdwood struct snd_ctl_elem_value *ucontrol)
72c3078f53SLiam Girdwood {
73a6668746SRanjani Sridharan struct soc_mixer_control *sm = (struct soc_mixer_control *)kcontrol->private_value;
74c3078f53SLiam Girdwood struct snd_sof_control *scontrol = sm->dobj.private;
75a6668746SRanjani Sridharan struct snd_soc_component *scomp = scontrol->scomp;
76a6668746SRanjani Sridharan struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
77*cfa12c36SPeter Ujfalusi const struct sof_ipc_tplg_ops *tplg_ops = sof_ipc_get_ops(sdev, tplg);
78c3078f53SLiam Girdwood
79*cfa12c36SPeter Ujfalusi if (tplg_ops && tplg_ops->control && tplg_ops->control->switch_get)
80a6668746SRanjani Sridharan return tplg_ops->control->switch_get(scontrol, ucontrol);
81c3078f53SLiam Girdwood
82c3078f53SLiam Girdwood return 0;
83c3078f53SLiam Girdwood }
84c3078f53SLiam Girdwood
snd_sof_switch_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)85c3078f53SLiam Girdwood int snd_sof_switch_put(struct snd_kcontrol *kcontrol,
86c3078f53SLiam Girdwood struct snd_ctl_elem_value *ucontrol)
87c3078f53SLiam Girdwood {
88a6668746SRanjani Sridharan struct soc_mixer_control *sm = (struct soc_mixer_control *)kcontrol->private_value;
89c3078f53SLiam Girdwood struct snd_sof_control *scontrol = sm->dobj.private;
90ee1e79b7SRanjani Sridharan struct snd_soc_component *scomp = scontrol->scomp;
91a6668746SRanjani Sridharan struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
92*cfa12c36SPeter Ujfalusi const struct sof_ipc_tplg_ops *tplg_ops = sof_ipc_get_ops(sdev, tplg);
93c3078f53SLiam Girdwood
94*cfa12c36SPeter Ujfalusi if (tplg_ops && tplg_ops->control && tplg_ops->control->switch_put)
95a6668746SRanjani Sridharan return tplg_ops->control->switch_put(scontrol, ucontrol);
96c3078f53SLiam Girdwood
97a6668746SRanjani Sridharan return false;
98c3078f53SLiam Girdwood }
99c3078f53SLiam Girdwood
snd_sof_enum_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)100c3078f53SLiam Girdwood int snd_sof_enum_get(struct snd_kcontrol *kcontrol,
101c3078f53SLiam Girdwood struct snd_ctl_elem_value *ucontrol)
102c3078f53SLiam Girdwood {
103049307aaSRanjani Sridharan struct soc_enum *se = (struct soc_enum *)kcontrol->private_value;
104c3078f53SLiam Girdwood struct snd_sof_control *scontrol = se->dobj.private;
105049307aaSRanjani Sridharan struct snd_soc_component *scomp = scontrol->scomp;
106049307aaSRanjani Sridharan struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
107*cfa12c36SPeter Ujfalusi const struct sof_ipc_tplg_ops *tplg_ops = sof_ipc_get_ops(sdev, tplg);
108c3078f53SLiam Girdwood
109*cfa12c36SPeter Ujfalusi if (tplg_ops && tplg_ops->control && tplg_ops->control->enum_get)
110049307aaSRanjani Sridharan return tplg_ops->control->enum_get(scontrol, ucontrol);
111c3078f53SLiam Girdwood
112c3078f53SLiam Girdwood return 0;
113c3078f53SLiam Girdwood }
114c3078f53SLiam Girdwood
snd_sof_enum_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)115c3078f53SLiam Girdwood int snd_sof_enum_put(struct snd_kcontrol *kcontrol,
116c3078f53SLiam Girdwood struct snd_ctl_elem_value *ucontrol)
117c3078f53SLiam Girdwood {
118049307aaSRanjani Sridharan struct soc_enum *se = (struct soc_enum *)kcontrol->private_value;
119c3078f53SLiam Girdwood struct snd_sof_control *scontrol = se->dobj.private;
120ee1e79b7SRanjani Sridharan struct snd_soc_component *scomp = scontrol->scomp;
121049307aaSRanjani Sridharan struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
122*cfa12c36SPeter Ujfalusi const struct sof_ipc_tplg_ops *tplg_ops = sof_ipc_get_ops(sdev, tplg);
123c3078f53SLiam Girdwood
124*cfa12c36SPeter Ujfalusi if (tplg_ops && tplg_ops->control && tplg_ops->control->enum_put)
125049307aaSRanjani Sridharan return tplg_ops->control->enum_put(scontrol, ucontrol);
126c3078f53SLiam Girdwood
127049307aaSRanjani Sridharan return false;
128c3078f53SLiam Girdwood }
129c3078f53SLiam Girdwood
snd_sof_bytes_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)130c3078f53SLiam Girdwood int snd_sof_bytes_get(struct snd_kcontrol *kcontrol,
131c3078f53SLiam Girdwood struct snd_ctl_elem_value *ucontrol)
132c3078f53SLiam Girdwood {
133544ac885SRanjani Sridharan struct soc_bytes_ext *be = (struct soc_bytes_ext *)kcontrol->private_value;
134c3078f53SLiam Girdwood struct snd_sof_control *scontrol = be->dobj.private;
135ee1e79b7SRanjani Sridharan struct snd_soc_component *scomp = scontrol->scomp;
136544ac885SRanjani Sridharan struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
137*cfa12c36SPeter Ujfalusi const struct sof_ipc_tplg_ops *tplg_ops = sof_ipc_get_ops(sdev, tplg);
138c3078f53SLiam Girdwood
139*cfa12c36SPeter Ujfalusi if (tplg_ops && tplg_ops->control && tplg_ops->control->bytes_get)
140544ac885SRanjani Sridharan return tplg_ops->control->bytes_get(scontrol, ucontrol);
141c3078f53SLiam Girdwood
142b9f8e138SGuennadi Liakhovetski return 0;
143c3078f53SLiam Girdwood }
144c3078f53SLiam Girdwood
snd_sof_bytes_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)145c3078f53SLiam Girdwood int snd_sof_bytes_put(struct snd_kcontrol *kcontrol,
146c3078f53SLiam Girdwood struct snd_ctl_elem_value *ucontrol)
147c3078f53SLiam Girdwood {
148544ac885SRanjani Sridharan struct soc_bytes_ext *be = (struct soc_bytes_ext *)kcontrol->private_value;
149c3078f53SLiam Girdwood struct snd_sof_control *scontrol = be->dobj.private;
150ee1e79b7SRanjani Sridharan struct snd_soc_component *scomp = scontrol->scomp;
151544ac885SRanjani Sridharan struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
152*cfa12c36SPeter Ujfalusi const struct sof_ipc_tplg_ops *tplg_ops = sof_ipc_get_ops(sdev, tplg);
153c3078f53SLiam Girdwood
154*cfa12c36SPeter Ujfalusi if (tplg_ops && tplg_ops->control && tplg_ops->control->bytes_put)
155544ac885SRanjani Sridharan return tplg_ops->control->bytes_put(scontrol, ucontrol);
156c3078f53SLiam Girdwood
1570c888babSBard Liao return 0;
158c3078f53SLiam Girdwood }
159c3078f53SLiam Girdwood
snd_sof_bytes_ext_put(struct snd_kcontrol * kcontrol,const unsigned int __user * binary_data,unsigned int size)160c3078f53SLiam Girdwood int snd_sof_bytes_ext_put(struct snd_kcontrol *kcontrol,
161c3078f53SLiam Girdwood const unsigned int __user *binary_data,
162c3078f53SLiam Girdwood unsigned int size)
163c3078f53SLiam Girdwood {
16467ec2a09SRanjani Sridharan struct soc_bytes_ext *be = (struct soc_bytes_ext *)kcontrol->private_value;
165c3078f53SLiam Girdwood struct snd_sof_control *scontrol = be->dobj.private;
166ee1e79b7SRanjani Sridharan struct snd_soc_component *scomp = scontrol->scomp;
16767ec2a09SRanjani Sridharan struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
168*cfa12c36SPeter Ujfalusi const struct sof_ipc_tplg_ops *tplg_ops = sof_ipc_get_ops(sdev, tplg);
169c3078f53SLiam Girdwood
1702ca21011SPierre-Louis Bossart /* make sure we have at least a header */
1712ca21011SPierre-Louis Bossart if (size < sizeof(struct snd_ctl_tlv))
1722ca21011SPierre-Louis Bossart return -EINVAL;
1732ca21011SPierre-Louis Bossart
174*cfa12c36SPeter Ujfalusi if (tplg_ops && tplg_ops->control && tplg_ops->control->bytes_ext_put)
17567ec2a09SRanjani Sridharan return tplg_ops->control->bytes_ext_put(scontrol, binary_data, size);
176c3078f53SLiam Girdwood
1770c888babSBard Liao return 0;
178c3078f53SLiam Girdwood }
179c3078f53SLiam Girdwood
snd_sof_bytes_ext_volatile_get(struct snd_kcontrol * kcontrol,unsigned int __user * binary_data,unsigned int size)180783560d0SDharageswari R int snd_sof_bytes_ext_volatile_get(struct snd_kcontrol *kcontrol, unsigned int __user *binary_data,
181783560d0SDharageswari R unsigned int size)
182783560d0SDharageswari R {
183783560d0SDharageswari R struct soc_bytes_ext *be = (struct soc_bytes_ext *)kcontrol->private_value;
184783560d0SDharageswari R struct snd_sof_control *scontrol = be->dobj.private;
185783560d0SDharageswari R struct snd_soc_component *scomp = scontrol->scomp;
18667ec2a09SRanjani Sridharan struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
187*cfa12c36SPeter Ujfalusi const struct sof_ipc_tplg_ops *tplg_ops = sof_ipc_get_ops(sdev, tplg);
18867ec2a09SRanjani Sridharan int ret, err;
189ec5a9762SPierre-Louis Bossart
190bf0736e5SPierre-Louis Bossart ret = pm_runtime_resume_and_get(scomp->dev);
19199ceec5cSPierre-Louis Bossart if (ret < 0 && ret != -EACCES) {
19267ec2a09SRanjani Sridharan dev_err_ratelimited(scomp->dev, "%s: failed to resume %d\n", __func__, ret);
193783560d0SDharageswari R return ret;
194783560d0SDharageswari R }
195783560d0SDharageswari R
196*cfa12c36SPeter Ujfalusi if (tplg_ops && tplg_ops->control && tplg_ops->control->bytes_ext_volatile_get)
19767ec2a09SRanjani Sridharan ret = tplg_ops->control->bytes_ext_volatile_get(scontrol, binary_data, size);
198783560d0SDharageswari R
199783560d0SDharageswari R pm_runtime_mark_last_busy(scomp->dev);
200783560d0SDharageswari R err = pm_runtime_put_autosuspend(scomp->dev);
201783560d0SDharageswari R if (err < 0)
20267ec2a09SRanjani Sridharan dev_err_ratelimited(scomp->dev, "%s: failed to idle %d\n", __func__, err);
203783560d0SDharageswari R
204783560d0SDharageswari R return ret;
205783560d0SDharageswari R }
206783560d0SDharageswari R
snd_sof_bytes_ext_get(struct snd_kcontrol * kcontrol,unsigned int __user * binary_data,unsigned int size)207c3078f53SLiam Girdwood int snd_sof_bytes_ext_get(struct snd_kcontrol *kcontrol,
208c3078f53SLiam Girdwood unsigned int __user *binary_data,
209c3078f53SLiam Girdwood unsigned int size)
210c3078f53SLiam Girdwood {
21167ec2a09SRanjani Sridharan struct soc_bytes_ext *be = (struct soc_bytes_ext *)kcontrol->private_value;
212c3078f53SLiam Girdwood struct snd_sof_control *scontrol = be->dobj.private;
213ee1e79b7SRanjani Sridharan struct snd_soc_component *scomp = scontrol->scomp;
21467ec2a09SRanjani Sridharan struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
215*cfa12c36SPeter Ujfalusi const struct sof_ipc_tplg_ops *tplg_ops = sof_ipc_get_ops(sdev, tplg);
216c3078f53SLiam Girdwood
217*cfa12c36SPeter Ujfalusi if (tplg_ops && tplg_ops->control && tplg_ops->control->bytes_ext_get)
21867ec2a09SRanjani Sridharan return tplg_ops->control->bytes_ext_get(scontrol, binary_data, size);
219c3078f53SLiam Girdwood
220b9f8e138SGuennadi Liakhovetski return 0;
221c3078f53SLiam Girdwood }
222