diff options
Diffstat (limited to 'sound/pci/hda/hda_hwdep.c')
-rw-r--r-- | sound/pci/hda/hda_hwdep.c | 37 |
1 files changed, 37 insertions, 0 deletions
diff --git a/sound/pci/hda/hda_hwdep.c b/sound/pci/hda/hda_hwdep.c index 214772c8b556..f3400d75eba4 100644 --- a/sound/pci/hda/hda_hwdep.c +++ b/sound/pci/hda/hda_hwdep.c | |||
@@ -96,6 +96,17 @@ static int hda_hwdep_open(struct snd_hwdep *hw, struct file *file) | |||
96 | return 0; | 96 | return 0; |
97 | } | 97 | } |
98 | 98 | ||
99 | static void clear_hwdep_elements(struct hda_codec *codec) | ||
100 | { | ||
101 | /* clear init verbs */ | ||
102 | snd_array_free(&codec->init_verbs); | ||
103 | } | ||
104 | |||
105 | static void hwdep_free(struct snd_hwdep *hwdep) | ||
106 | { | ||
107 | clear_hwdep_elements(hwdep->private_data); | ||
108 | } | ||
109 | |||
99 | int __devinit snd_hda_create_hwdep(struct hda_codec *codec) | 110 | int __devinit snd_hda_create_hwdep(struct hda_codec *codec) |
100 | { | 111 | { |
101 | char hwname[16]; | 112 | char hwname[16]; |
@@ -110,6 +121,7 @@ int __devinit snd_hda_create_hwdep(struct hda_codec *codec) | |||
110 | sprintf(hwdep->name, "HDA Codec %d", codec->addr); | 121 | sprintf(hwdep->name, "HDA Codec %d", codec->addr); |
111 | hwdep->iface = SNDRV_HWDEP_IFACE_HDA; | 122 | hwdep->iface = SNDRV_HWDEP_IFACE_HDA; |
112 | hwdep->private_data = codec; | 123 | hwdep->private_data = codec; |
124 | hwdep->private_free = hwdep_free; | ||
113 | hwdep->exclusive = 1; | 125 | hwdep->exclusive = 1; |
114 | 126 | ||
115 | hwdep->ops.open = hda_hwdep_open; | 127 | hwdep->ops.open = hda_hwdep_open; |
@@ -118,6 +130,8 @@ int __devinit snd_hda_create_hwdep(struct hda_codec *codec) | |||
118 | hwdep->ops.ioctl_compat = hda_hwdep_ioctl_compat; | 130 | hwdep->ops.ioctl_compat = hda_hwdep_ioctl_compat; |
119 | #endif | 131 | #endif |
120 | 132 | ||
133 | snd_array_init(&codec->init_verbs, sizeof(struct hda_verb), 32); | ||
134 | |||
121 | return 0; | 135 | return 0; |
122 | } | 136 | } |
123 | 137 | ||
@@ -128,6 +142,7 @@ int __devinit snd_hda_create_hwdep(struct hda_codec *codec) | |||
128 | static int clear_codec(struct hda_codec *codec) | 142 | static int clear_codec(struct hda_codec *codec) |
129 | { | 143 | { |
130 | snd_hda_codec_reset(codec); | 144 | snd_hda_codec_reset(codec); |
145 | clear_hwdep_elements(codec); | ||
131 | return 0; | 146 | return 0; |
132 | } | 147 | } |
133 | 148 | ||
@@ -244,6 +259,27 @@ static ssize_t type##_store(struct device *dev, \ | |||
244 | CODEC_ACTION_STORE(reconfig); | 259 | CODEC_ACTION_STORE(reconfig); |
245 | CODEC_ACTION_STORE(clear); | 260 | CODEC_ACTION_STORE(clear); |
246 | 261 | ||
262 | static ssize_t init_verbs_store(struct device *dev, | ||
263 | struct device_attribute *attr, | ||
264 | const char *buf, size_t count) | ||
265 | { | ||
266 | struct snd_hwdep *hwdep = dev_get_drvdata(dev); | ||
267 | struct hda_codec *codec = hwdep->private_data; | ||
268 | char *p; | ||
269 | struct hda_verb verb, *v; | ||
270 | |||
271 | verb.nid = simple_strtoul(buf, &p, 0); | ||
272 | verb.verb = simple_strtoul(p, &p, 0); | ||
273 | verb.param = simple_strtoul(p, &p, 0); | ||
274 | if (!verb.nid || !verb.verb || !verb.param) | ||
275 | return -EINVAL; | ||
276 | v = snd_array_new(&codec->init_verbs); | ||
277 | if (!v) | ||
278 | return -ENOMEM; | ||
279 | *v = verb; | ||
280 | return count; | ||
281 | } | ||
282 | |||
247 | #define CODEC_ATTR_RW(type) \ | 283 | #define CODEC_ATTR_RW(type) \ |
248 | __ATTR(type, 0644, type##_show, type##_store) | 284 | __ATTR(type, 0644, type##_show, type##_store) |
249 | #define CODEC_ATTR_RO(type) \ | 285 | #define CODEC_ATTR_RO(type) \ |
@@ -259,6 +295,7 @@ static struct device_attribute codec_attrs[] = { | |||
259 | CODEC_ATTR_RO(mfg), | 295 | CODEC_ATTR_RO(mfg), |
260 | CODEC_ATTR_RW(name), | 296 | CODEC_ATTR_RW(name), |
261 | CODEC_ATTR_RW(modelname), | 297 | CODEC_ATTR_RW(modelname), |
298 | CODEC_ATTR_WO(init_verbs), | ||
262 | CODEC_ATTR_WO(reconfig), | 299 | CODEC_ATTR_WO(reconfig), |
263 | CODEC_ATTR_WO(clear), | 300 | CODEC_ATTR_WO(clear), |
264 | }; | 301 | }; |