aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/hda/hda_hwdep.c
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2008-07-30 09:01:46 -0400
committerTakashi Iwai <tiwai@suse.de>2008-10-12 20:43:02 -0400
commitd7ffba19ce4c1b153d502a89d829400bf76d6c11 (patch)
treefca202a4d4cd4dae9ded85c274746693b22a5fb4 /sound/pci/hda/hda_hwdep.c
parent6c1f45ea89b59ad2cdbfa6779e23d77b274da0a7 (diff)
ALSA: hda - Add sysfs entries to hwdep devices
Added the sysfs entries to hwdep devices so that the new features like reconfiguration can be done via sysfs. Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci/hda/hda_hwdep.c')
-rw-r--r--sound/pci/hda/hda_hwdep.c157
1 files changed, 157 insertions, 0 deletions
diff --git a/sound/pci/hda/hda_hwdep.c b/sound/pci/hda/hda_hwdep.c
index 6e18a422d993..214772c8b556 100644
--- a/sound/pci/hda/hda_hwdep.c
+++ b/sound/pci/hda/hda_hwdep.c
@@ -27,6 +27,7 @@
27#include "hda_codec.h" 27#include "hda_codec.h"
28#include "hda_local.h" 28#include "hda_local.h"
29#include <sound/hda_hwdep.h> 29#include <sound/hda_hwdep.h>
30#include <sound/minors.h>
30 31
31/* 32/*
32 * write/read an out-of-bound verb 33 * write/read an out-of-bound verb
@@ -119,3 +120,159 @@ int __devinit snd_hda_create_hwdep(struct hda_codec *codec)
119 120
120 return 0; 121 return 0;
121} 122}
123
124/*
125 * sysfs interface
126 */
127
128static int clear_codec(struct hda_codec *codec)
129{
130 snd_hda_codec_reset(codec);
131 return 0;
132}
133
134static int reconfig_codec(struct hda_codec *codec)
135{
136 int err;
137
138 snd_printk(KERN_INFO "hda-codec: reconfiguring\n");
139 snd_hda_codec_reset(codec);
140 err = snd_hda_codec_configure(codec);
141 if (err < 0)
142 return err;
143 /* rebuild PCMs */
144 err = snd_hda_build_pcms(codec->bus);
145 if (err < 0)
146 return err;
147 /* rebuild mixers */
148 err = snd_hda_codec_build_controls(codec);
149 if (err < 0)
150 return err;
151 return 0;
152}
153
154/*
155 * allocate a string at most len chars, and remove the trailing EOL
156 */
157static char *kstrndup_noeol(const char *src, size_t len)
158{
159 char *s = kstrndup(src, len, GFP_KERNEL);
160 char *p;
161 if (!s)
162 return NULL;
163 p = strchr(s, '\n');
164 if (p)
165 *p = 0;
166 return s;
167}
168
169#define CODEC_INFO_SHOW(type) \
170static ssize_t type##_show(struct device *dev, \
171 struct device_attribute *attr, \
172 char *buf) \
173{ \
174 struct snd_hwdep *hwdep = dev_get_drvdata(dev); \
175 struct hda_codec *codec = hwdep->private_data; \
176 return sprintf(buf, "0x%x\n", codec->type); \
177}
178
179#define CODEC_INFO_STR_SHOW(type) \
180static ssize_t type##_show(struct device *dev, \
181 struct device_attribute *attr, \
182 char *buf) \
183{ \
184 struct snd_hwdep *hwdep = dev_get_drvdata(dev); \
185 struct hda_codec *codec = hwdep->private_data; \
186 return sprintf(buf, "%s\n", \
187 codec->type ? codec->type : ""); \
188}
189
190CODEC_INFO_SHOW(vendor_id);
191CODEC_INFO_SHOW(subsystem_id);
192CODEC_INFO_SHOW(revision_id);
193CODEC_INFO_SHOW(afg);
194CODEC_INFO_SHOW(mfg);
195CODEC_INFO_STR_SHOW(name);
196CODEC_INFO_STR_SHOW(modelname);
197
198#define CODEC_INFO_STORE(type) \
199static ssize_t type##_store(struct device *dev, \
200 struct device_attribute *attr, \
201 const char *buf, size_t count) \
202{ \
203 struct snd_hwdep *hwdep = dev_get_drvdata(dev); \
204 struct hda_codec *codec = hwdep->private_data; \
205 char *after; \
206 codec->type = simple_strtoul(buf, &after, 0); \
207 return count; \
208}
209
210#define CODEC_INFO_STR_STORE(type) \
211static ssize_t type##_store(struct device *dev, \
212 struct device_attribute *attr, \
213 const char *buf, size_t count) \
214{ \
215 struct snd_hwdep *hwdep = dev_get_drvdata(dev); \
216 struct hda_codec *codec = hwdep->private_data; \
217 char *s = kstrndup_noeol(buf, 64); \
218 if (!s) \
219 return -ENOMEM; \
220 kfree(codec->type); \
221 codec->type = s; \
222 return count; \
223}
224
225CODEC_INFO_STORE(vendor_id);
226CODEC_INFO_STORE(subsystem_id);
227CODEC_INFO_STORE(revision_id);
228CODEC_INFO_STR_STORE(name);
229CODEC_INFO_STR_STORE(modelname);
230
231#define CODEC_ACTION_STORE(type) \
232static ssize_t type##_store(struct device *dev, \
233 struct device_attribute *attr, \
234 const char *buf, size_t count) \
235{ \
236 struct snd_hwdep *hwdep = dev_get_drvdata(dev); \
237 struct hda_codec *codec = hwdep->private_data; \
238 int err = 0; \
239 if (*buf) \
240 err = type##_codec(codec); \
241 return err < 0 ? err : count; \
242}
243
244CODEC_ACTION_STORE(reconfig);
245CODEC_ACTION_STORE(clear);
246
247#define CODEC_ATTR_RW(type) \
248 __ATTR(type, 0644, type##_show, type##_store)
249#define CODEC_ATTR_RO(type) \
250 __ATTR_RO(type)
251#define CODEC_ATTR_WO(type) \
252 __ATTR(type, 0200, NULL, type##_store)
253
254static struct device_attribute codec_attrs[] = {
255 CODEC_ATTR_RW(vendor_id),
256 CODEC_ATTR_RW(subsystem_id),
257 CODEC_ATTR_RW(revision_id),
258 CODEC_ATTR_RO(afg),
259 CODEC_ATTR_RO(mfg),
260 CODEC_ATTR_RW(name),
261 CODEC_ATTR_RW(modelname),
262 CODEC_ATTR_WO(reconfig),
263 CODEC_ATTR_WO(clear),
264};
265
266/*
267 * create sysfs files on hwdep directory
268 */
269int snd_hda_hwdep_add_sysfs(struct hda_codec *codec)
270{
271 struct snd_hwdep *hwdep = codec->hwdep;
272 int i;
273
274 for (i = 0; i < ARRAY_SIZE(codec_attrs); i++)
275 snd_add_device_sysfs_file(SNDRV_DEVICE_TYPE_HWDEP, hwdep->card,
276 hwdep->device, &codec_attrs[i]);
277 return 0;
278}