]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blob - sound/pci/hda/hda_sysfs.c
Merge tag 'audit-pr-20200330' of git://git.kernel.org/pub/scm/linux/kernel/git/pcmoor...
[mirror_ubuntu-jammy-kernel.git] / sound / pci / hda / hda_sysfs.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3 * sysfs interface for HD-audio codec
4 *
5 * Copyright (c) 2014 Takashi Iwai <tiwai@suse.de>
6 *
7 * split from hda_hwdep.c
8 */
9
10 #include <linux/init.h>
11 #include <linux/slab.h>
12 #include <linux/compat.h>
13 #include <linux/mutex.h>
14 #include <linux/ctype.h>
15 #include <linux/string.h>
16 #include <linux/export.h>
17 #include <sound/core.h>
18 #include <sound/hda_codec.h>
19 #include "hda_local.h"
20 #include <sound/hda_hwdep.h>
21 #include <sound/minors.h>
22
23 /* hint string pair */
24 struct hda_hint {
25 const char *key;
26 const char *val; /* contained in the same alloc as key */
27 };
28
29 #ifdef CONFIG_PM
30 static ssize_t power_on_acct_show(struct device *dev,
31 struct device_attribute *attr,
32 char *buf)
33 {
34 struct hda_codec *codec = dev_get_drvdata(dev);
35 snd_hda_update_power_acct(codec);
36 return sprintf(buf, "%u\n", jiffies_to_msecs(codec->power_on_acct));
37 }
38
39 static ssize_t power_off_acct_show(struct device *dev,
40 struct device_attribute *attr,
41 char *buf)
42 {
43 struct hda_codec *codec = dev_get_drvdata(dev);
44 snd_hda_update_power_acct(codec);
45 return sprintf(buf, "%u\n", jiffies_to_msecs(codec->power_off_acct));
46 }
47
48 static DEVICE_ATTR_RO(power_on_acct);
49 static DEVICE_ATTR_RO(power_off_acct);
50 #endif /* CONFIG_PM */
51
52 #define CODEC_INFO_SHOW(type, field) \
53 static ssize_t type##_show(struct device *dev, \
54 struct device_attribute *attr, \
55 char *buf) \
56 { \
57 struct hda_codec *codec = dev_get_drvdata(dev); \
58 return sprintf(buf, "0x%x\n", codec->field); \
59 }
60
61 #define CODEC_INFO_STR_SHOW(type, field) \
62 static ssize_t type##_show(struct device *dev, \
63 struct device_attribute *attr, \
64 char *buf) \
65 { \
66 struct hda_codec *codec = dev_get_drvdata(dev); \
67 return sprintf(buf, "%s\n", \
68 codec->field ? codec->field : ""); \
69 }
70
71 CODEC_INFO_SHOW(vendor_id, core.vendor_id);
72 CODEC_INFO_SHOW(subsystem_id, core.subsystem_id);
73 CODEC_INFO_SHOW(revision_id, core.revision_id);
74 CODEC_INFO_SHOW(afg, core.afg);
75 CODEC_INFO_SHOW(mfg, core.mfg);
76 CODEC_INFO_STR_SHOW(vendor_name, core.vendor_name);
77 CODEC_INFO_STR_SHOW(chip_name, core.chip_name);
78 CODEC_INFO_STR_SHOW(modelname, modelname);
79
80 static ssize_t pin_configs_show(struct hda_codec *codec,
81 struct snd_array *list,
82 char *buf)
83 {
84 const struct hda_pincfg *pin;
85 int i, len = 0;
86 mutex_lock(&codec->user_mutex);
87 snd_array_for_each(list, i, pin) {
88 len += sprintf(buf + len, "0x%02x 0x%08x\n",
89 pin->nid, pin->cfg);
90 }
91 mutex_unlock(&codec->user_mutex);
92 return len;
93 }
94
95 static ssize_t init_pin_configs_show(struct device *dev,
96 struct device_attribute *attr,
97 char *buf)
98 {
99 struct hda_codec *codec = dev_get_drvdata(dev);
100 return pin_configs_show(codec, &codec->init_pins, buf);
101 }
102
103 static ssize_t driver_pin_configs_show(struct device *dev,
104 struct device_attribute *attr,
105 char *buf)
106 {
107 struct hda_codec *codec = dev_get_drvdata(dev);
108 return pin_configs_show(codec, &codec->driver_pins, buf);
109 }
110
111 #ifdef CONFIG_SND_HDA_RECONFIG
112
113 /*
114 * sysfs interface
115 */
116
117 static int clear_codec(struct hda_codec *codec)
118 {
119 int err;
120
121 err = snd_hda_codec_reset(codec);
122 if (err < 0) {
123 codec_err(codec, "The codec is being used, can't free.\n");
124 return err;
125 }
126 snd_hda_sysfs_clear(codec);
127 return 0;
128 }
129
130 static int reconfig_codec(struct hda_codec *codec)
131 {
132 int err;
133
134 snd_hda_power_up(codec);
135 codec_info(codec, "hda-codec: reconfiguring\n");
136 err = snd_hda_codec_reset(codec);
137 if (err < 0) {
138 codec_err(codec,
139 "The codec is being used, can't reconfigure.\n");
140 goto error;
141 }
142 err = snd_hda_codec_configure(codec);
143 if (err < 0)
144 goto error;
145 err = snd_card_register(codec->card);
146 error:
147 snd_hda_power_down(codec);
148 return err;
149 }
150
151 /*
152 * allocate a string at most len chars, and remove the trailing EOL
153 */
154 static char *kstrndup_noeol(const char *src, size_t len)
155 {
156 char *s = kstrndup(src, len, GFP_KERNEL);
157 char *p;
158 if (!s)
159 return NULL;
160 p = strchr(s, '\n');
161 if (p)
162 *p = 0;
163 return s;
164 }
165
166 #define CODEC_INFO_STORE(type, field) \
167 static ssize_t type##_store(struct device *dev, \
168 struct device_attribute *attr, \
169 const char *buf, size_t count) \
170 { \
171 struct hda_codec *codec = dev_get_drvdata(dev); \
172 unsigned long val; \
173 int err = kstrtoul(buf, 0, &val); \
174 if (err < 0) \
175 return err; \
176 codec->field = val; \
177 return count; \
178 }
179
180 #define CODEC_INFO_STR_STORE(type, field) \
181 static ssize_t type##_store(struct device *dev, \
182 struct device_attribute *attr, \
183 const char *buf, size_t count) \
184 { \
185 struct hda_codec *codec = dev_get_drvdata(dev); \
186 char *s = kstrndup_noeol(buf, 64); \
187 if (!s) \
188 return -ENOMEM; \
189 kfree(codec->field); \
190 codec->field = s; \
191 return count; \
192 }
193
194 CODEC_INFO_STORE(vendor_id, core.vendor_id);
195 CODEC_INFO_STORE(subsystem_id, core.subsystem_id);
196 CODEC_INFO_STORE(revision_id, core.revision_id);
197 CODEC_INFO_STR_STORE(vendor_name, core.vendor_name);
198 CODEC_INFO_STR_STORE(chip_name, core.chip_name);
199 CODEC_INFO_STR_STORE(modelname, modelname);
200
201 #define CODEC_ACTION_STORE(type) \
202 static ssize_t type##_store(struct device *dev, \
203 struct device_attribute *attr, \
204 const char *buf, size_t count) \
205 { \
206 struct hda_codec *codec = dev_get_drvdata(dev); \
207 int err = 0; \
208 if (*buf) \
209 err = type##_codec(codec); \
210 return err < 0 ? err : count; \
211 }
212
213 CODEC_ACTION_STORE(reconfig);
214 CODEC_ACTION_STORE(clear);
215
216 static ssize_t init_verbs_show(struct device *dev,
217 struct device_attribute *attr,
218 char *buf)
219 {
220 struct hda_codec *codec = dev_get_drvdata(dev);
221 const struct hda_verb *v;
222 int i, len = 0;
223 mutex_lock(&codec->user_mutex);
224 snd_array_for_each(&codec->init_verbs, i, v) {
225 len += scnprintf(buf + len, PAGE_SIZE - len,
226 "0x%02x 0x%03x 0x%04x\n",
227 v->nid, v->verb, v->param);
228 }
229 mutex_unlock(&codec->user_mutex);
230 return len;
231 }
232
233 static int parse_init_verbs(struct hda_codec *codec, const char *buf)
234 {
235 struct hda_verb *v;
236 int nid, verb, param;
237
238 if (sscanf(buf, "%i %i %i", &nid, &verb, &param) != 3)
239 return -EINVAL;
240 if (!nid || !verb)
241 return -EINVAL;
242 mutex_lock(&codec->user_mutex);
243 v = snd_array_new(&codec->init_verbs);
244 if (!v) {
245 mutex_unlock(&codec->user_mutex);
246 return -ENOMEM;
247 }
248 v->nid = nid;
249 v->verb = verb;
250 v->param = param;
251 mutex_unlock(&codec->user_mutex);
252 return 0;
253 }
254
255 static ssize_t init_verbs_store(struct device *dev,
256 struct device_attribute *attr,
257 const char *buf, size_t count)
258 {
259 struct hda_codec *codec = dev_get_drvdata(dev);
260 int err = parse_init_verbs(codec, buf);
261 if (err < 0)
262 return err;
263 return count;
264 }
265
266 static ssize_t hints_show(struct device *dev,
267 struct device_attribute *attr,
268 char *buf)
269 {
270 struct hda_codec *codec = dev_get_drvdata(dev);
271 const struct hda_hint *hint;
272 int i, len = 0;
273 mutex_lock(&codec->user_mutex);
274 snd_array_for_each(&codec->hints, i, hint) {
275 len += scnprintf(buf + len, PAGE_SIZE - len,
276 "%s = %s\n", hint->key, hint->val);
277 }
278 mutex_unlock(&codec->user_mutex);
279 return len;
280 }
281
282 static struct hda_hint *get_hint(struct hda_codec *codec, const char *key)
283 {
284 struct hda_hint *hint;
285 int i;
286
287 snd_array_for_each(&codec->hints, i, hint) {
288 if (!strcmp(hint->key, key))
289 return hint;
290 }
291 return NULL;
292 }
293
294 static void remove_trail_spaces(char *str)
295 {
296 char *p;
297 if (!*str)
298 return;
299 p = str + strlen(str) - 1;
300 for (; isspace(*p); p--) {
301 *p = 0;
302 if (p == str)
303 return;
304 }
305 }
306
307 #define MAX_HINTS 1024
308
309 static int parse_hints(struct hda_codec *codec, const char *buf)
310 {
311 char *key, *val;
312 struct hda_hint *hint;
313 int err = 0;
314
315 buf = skip_spaces(buf);
316 if (!*buf || *buf == '#' || *buf == '\n')
317 return 0;
318 if (*buf == '=')
319 return -EINVAL;
320 key = kstrndup_noeol(buf, 1024);
321 if (!key)
322 return -ENOMEM;
323 /* extract key and val */
324 val = strchr(key, '=');
325 if (!val) {
326 kfree(key);
327 return -EINVAL;
328 }
329 *val++ = 0;
330 val = skip_spaces(val);
331 remove_trail_spaces(key);
332 remove_trail_spaces(val);
333 mutex_lock(&codec->user_mutex);
334 hint = get_hint(codec, key);
335 if (hint) {
336 /* replace */
337 kfree(hint->key);
338 hint->key = key;
339 hint->val = val;
340 goto unlock;
341 }
342 /* allocate a new hint entry */
343 if (codec->hints.used >= MAX_HINTS)
344 hint = NULL;
345 else
346 hint = snd_array_new(&codec->hints);
347 if (hint) {
348 hint->key = key;
349 hint->val = val;
350 } else {
351 err = -ENOMEM;
352 }
353 unlock:
354 mutex_unlock(&codec->user_mutex);
355 if (err)
356 kfree(key);
357 return err;
358 }
359
360 static ssize_t hints_store(struct device *dev,
361 struct device_attribute *attr,
362 const char *buf, size_t count)
363 {
364 struct hda_codec *codec = dev_get_drvdata(dev);
365 int err = parse_hints(codec, buf);
366 if (err < 0)
367 return err;
368 return count;
369 }
370
371 static ssize_t user_pin_configs_show(struct device *dev,
372 struct device_attribute *attr,
373 char *buf)
374 {
375 struct hda_codec *codec = dev_get_drvdata(dev);
376 return pin_configs_show(codec, &codec->user_pins, buf);
377 }
378
379 #define MAX_PIN_CONFIGS 32
380
381 static int parse_user_pin_configs(struct hda_codec *codec, const char *buf)
382 {
383 int nid, cfg, err;
384
385 if (sscanf(buf, "%i %i", &nid, &cfg) != 2)
386 return -EINVAL;
387 if (!nid)
388 return -EINVAL;
389 mutex_lock(&codec->user_mutex);
390 err = snd_hda_add_pincfg(codec, &codec->user_pins, nid, cfg);
391 mutex_unlock(&codec->user_mutex);
392 return err;
393 }
394
395 static ssize_t user_pin_configs_store(struct device *dev,
396 struct device_attribute *attr,
397 const char *buf, size_t count)
398 {
399 struct hda_codec *codec = dev_get_drvdata(dev);
400 int err = parse_user_pin_configs(codec, buf);
401 if (err < 0)
402 return err;
403 return count;
404 }
405
406 /* sysfs attributes exposed only when CONFIG_SND_HDA_RECONFIG=y */
407 static DEVICE_ATTR_RW(init_verbs);
408 static DEVICE_ATTR_RW(hints);
409 static DEVICE_ATTR_RW(user_pin_configs);
410 static DEVICE_ATTR_WO(reconfig);
411 static DEVICE_ATTR_WO(clear);
412
413 /**
414 * snd_hda_get_hint - Look for hint string
415 * @codec: the HDA codec
416 * @key: the hint key string
417 *
418 * Look for a hint key/value pair matching with the given key string
419 * and returns the value string. If nothing found, returns NULL.
420 */
421 const char *snd_hda_get_hint(struct hda_codec *codec, const char *key)
422 {
423 struct hda_hint *hint = get_hint(codec, key);
424 return hint ? hint->val : NULL;
425 }
426 EXPORT_SYMBOL_GPL(snd_hda_get_hint);
427
428 /**
429 * snd_hda_get_bool_hint - Get a boolean hint value
430 * @codec: the HDA codec
431 * @key: the hint key string
432 *
433 * Look for a hint key/value pair matching with the given key string
434 * and returns a boolean value parsed from the value. If no matching
435 * key is found, return a negative value.
436 */
437 int snd_hda_get_bool_hint(struct hda_codec *codec, const char *key)
438 {
439 const char *p;
440 int ret;
441
442 mutex_lock(&codec->user_mutex);
443 p = snd_hda_get_hint(codec, key);
444 if (!p || !*p)
445 ret = -ENOENT;
446 else {
447 switch (toupper(*p)) {
448 case 'T': /* true */
449 case 'Y': /* yes */
450 case '1':
451 ret = 1;
452 break;
453 default:
454 ret = 0;
455 break;
456 }
457 }
458 mutex_unlock(&codec->user_mutex);
459 return ret;
460 }
461 EXPORT_SYMBOL_GPL(snd_hda_get_bool_hint);
462
463 /**
464 * snd_hda_get_int_hint - Get an integer hint value
465 * @codec: the HDA codec
466 * @key: the hint key string
467 * @valp: pointer to store a value
468 *
469 * Look for a hint key/value pair matching with the given key string
470 * and stores the integer value to @valp. If no matching key is found,
471 * return a negative error code. Otherwise it returns zero.
472 */
473 int snd_hda_get_int_hint(struct hda_codec *codec, const char *key, int *valp)
474 {
475 const char *p;
476 unsigned long val;
477 int ret;
478
479 mutex_lock(&codec->user_mutex);
480 p = snd_hda_get_hint(codec, key);
481 if (!p)
482 ret = -ENOENT;
483 else if (kstrtoul(p, 0, &val))
484 ret = -EINVAL;
485 else {
486 *valp = val;
487 ret = 0;
488 }
489 mutex_unlock(&codec->user_mutex);
490 return ret;
491 }
492 EXPORT_SYMBOL_GPL(snd_hda_get_int_hint);
493 #endif /* CONFIG_SND_HDA_RECONFIG */
494
495 /*
496 * common sysfs attributes
497 */
498 #ifdef CONFIG_SND_HDA_RECONFIG
499 #define RECONFIG_DEVICE_ATTR(name) DEVICE_ATTR_RW(name)
500 #else
501 #define RECONFIG_DEVICE_ATTR(name) DEVICE_ATTR_RO(name)
502 #endif
503 static RECONFIG_DEVICE_ATTR(vendor_id);
504 static RECONFIG_DEVICE_ATTR(subsystem_id);
505 static RECONFIG_DEVICE_ATTR(revision_id);
506 static DEVICE_ATTR_RO(afg);
507 static DEVICE_ATTR_RO(mfg);
508 static RECONFIG_DEVICE_ATTR(vendor_name);
509 static RECONFIG_DEVICE_ATTR(chip_name);
510 static RECONFIG_DEVICE_ATTR(modelname);
511 static DEVICE_ATTR_RO(init_pin_configs);
512 static DEVICE_ATTR_RO(driver_pin_configs);
513
514
515 #ifdef CONFIG_SND_HDA_PATCH_LOADER
516
517 /* parser mode */
518 enum {
519 LINE_MODE_NONE,
520 LINE_MODE_CODEC,
521 LINE_MODE_MODEL,
522 LINE_MODE_PINCFG,
523 LINE_MODE_VERB,
524 LINE_MODE_HINT,
525 LINE_MODE_VENDOR_ID,
526 LINE_MODE_SUBSYSTEM_ID,
527 LINE_MODE_REVISION_ID,
528 LINE_MODE_CHIP_NAME,
529 NUM_LINE_MODES,
530 };
531
532 static inline int strmatch(const char *a, const char *b)
533 {
534 return strncasecmp(a, b, strlen(b)) == 0;
535 }
536
537 /* parse the contents after the line "[codec]"
538 * accept only the line with three numbers, and assign the current codec
539 */
540 static void parse_codec_mode(char *buf, struct hda_bus *bus,
541 struct hda_codec **codecp)
542 {
543 int vendorid, subid, caddr;
544 struct hda_codec *codec;
545
546 *codecp = NULL;
547 if (sscanf(buf, "%i %i %i", &vendorid, &subid, &caddr) == 3) {
548 list_for_each_codec(codec, bus) {
549 if ((vendorid <= 0 || codec->core.vendor_id == vendorid) &&
550 (subid <= 0 || codec->core.subsystem_id == subid) &&
551 codec->core.addr == caddr) {
552 *codecp = codec;
553 break;
554 }
555 }
556 }
557 }
558
559 /* parse the contents after the other command tags, [pincfg], [verb],
560 * [vendor_id], [subsystem_id], [revision_id], [chip_name], [hint] and [model]
561 * just pass to the sysfs helper (only when any codec was specified)
562 */
563 static void parse_pincfg_mode(char *buf, struct hda_bus *bus,
564 struct hda_codec **codecp)
565 {
566 parse_user_pin_configs(*codecp, buf);
567 }
568
569 static void parse_verb_mode(char *buf, struct hda_bus *bus,
570 struct hda_codec **codecp)
571 {
572 parse_init_verbs(*codecp, buf);
573 }
574
575 static void parse_hint_mode(char *buf, struct hda_bus *bus,
576 struct hda_codec **codecp)
577 {
578 parse_hints(*codecp, buf);
579 }
580
581 static void parse_model_mode(char *buf, struct hda_bus *bus,
582 struct hda_codec **codecp)
583 {
584 kfree((*codecp)->modelname);
585 (*codecp)->modelname = kstrdup(buf, GFP_KERNEL);
586 }
587
588 static void parse_chip_name_mode(char *buf, struct hda_bus *bus,
589 struct hda_codec **codecp)
590 {
591 snd_hda_codec_set_name(*codecp, buf);
592 }
593
594 #define DEFINE_PARSE_ID_MODE(name) \
595 static void parse_##name##_mode(char *buf, struct hda_bus *bus, \
596 struct hda_codec **codecp) \
597 { \
598 unsigned long val; \
599 if (!kstrtoul(buf, 0, &val)) \
600 (*codecp)->core.name = val; \
601 }
602
603 DEFINE_PARSE_ID_MODE(vendor_id);
604 DEFINE_PARSE_ID_MODE(subsystem_id);
605 DEFINE_PARSE_ID_MODE(revision_id);
606
607
608 struct hda_patch_item {
609 const char *tag;
610 const char *alias;
611 void (*parser)(char *buf, struct hda_bus *bus, struct hda_codec **retc);
612 };
613
614 static const struct hda_patch_item patch_items[NUM_LINE_MODES] = {
615 [LINE_MODE_CODEC] = {
616 .tag = "[codec]",
617 .parser = parse_codec_mode,
618 },
619 [LINE_MODE_MODEL] = {
620 .tag = "[model]",
621 .parser = parse_model_mode,
622 },
623 [LINE_MODE_VERB] = {
624 .tag = "[verb]",
625 .alias = "[init_verbs]",
626 .parser = parse_verb_mode,
627 },
628 [LINE_MODE_PINCFG] = {
629 .tag = "[pincfg]",
630 .alias = "[user_pin_configs]",
631 .parser = parse_pincfg_mode,
632 },
633 [LINE_MODE_HINT] = {
634 .tag = "[hint]",
635 .alias = "[hints]",
636 .parser = parse_hint_mode
637 },
638 [LINE_MODE_VENDOR_ID] = {
639 .tag = "[vendor_id]",
640 .parser = parse_vendor_id_mode,
641 },
642 [LINE_MODE_SUBSYSTEM_ID] = {
643 .tag = "[subsystem_id]",
644 .parser = parse_subsystem_id_mode,
645 },
646 [LINE_MODE_REVISION_ID] = {
647 .tag = "[revision_id]",
648 .parser = parse_revision_id_mode,
649 },
650 [LINE_MODE_CHIP_NAME] = {
651 .tag = "[chip_name]",
652 .parser = parse_chip_name_mode,
653 },
654 };
655
656 /* check the line starting with '[' -- change the parser mode accodingly */
657 static int parse_line_mode(char *buf, struct hda_bus *bus)
658 {
659 int i;
660 for (i = 0; i < ARRAY_SIZE(patch_items); i++) {
661 if (!patch_items[i].tag)
662 continue;
663 if (strmatch(buf, patch_items[i].tag))
664 return i;
665 if (patch_items[i].alias && strmatch(buf, patch_items[i].alias))
666 return i;
667 }
668 return LINE_MODE_NONE;
669 }
670
671 /* copy one line from the buffer in fw, and update the fields in fw
672 * return zero if it reaches to the end of the buffer, or non-zero
673 * if successfully copied a line
674 *
675 * the spaces at the beginning and the end of the line are stripped
676 */
677 static int get_line_from_fw(char *buf, int size, size_t *fw_size_p,
678 const void **fw_data_p)
679 {
680 int len;
681 size_t fw_size = *fw_size_p;
682 const char *p = *fw_data_p;
683
684 while (isspace(*p) && fw_size) {
685 p++;
686 fw_size--;
687 }
688 if (!fw_size)
689 return 0;
690
691 for (len = 0; len < fw_size; len++) {
692 if (!*p)
693 break;
694 if (*p == '\n') {
695 p++;
696 len++;
697 break;
698 }
699 if (len < size)
700 *buf++ = *p++;
701 }
702 *buf = 0;
703 *fw_size_p = fw_size - len;
704 *fw_data_p = p;
705 remove_trail_spaces(buf);
706 return 1;
707 }
708
709 /**
710 * snd_hda_load_patch - load a "patch" firmware file and parse it
711 * @bus: HD-audio bus
712 * @fw_size: the firmware byte size
713 * @fw_buf: the firmware data
714 */
715 int snd_hda_load_patch(struct hda_bus *bus, size_t fw_size, const void *fw_buf)
716 {
717 char buf[128];
718 struct hda_codec *codec;
719 int line_mode;
720
721 line_mode = LINE_MODE_NONE;
722 codec = NULL;
723 while (get_line_from_fw(buf, sizeof(buf) - 1, &fw_size, &fw_buf)) {
724 if (!*buf || *buf == '#' || *buf == '\n')
725 continue;
726 if (*buf == '[')
727 line_mode = parse_line_mode(buf, bus);
728 else if (patch_items[line_mode].parser &&
729 (codec || line_mode <= LINE_MODE_CODEC))
730 patch_items[line_mode].parser(buf, bus, &codec);
731 }
732 return 0;
733 }
734 EXPORT_SYMBOL_GPL(snd_hda_load_patch);
735 #endif /* CONFIG_SND_HDA_PATCH_LOADER */
736
737 /*
738 * sysfs entries
739 */
740 static struct attribute *hda_dev_attrs[] = {
741 &dev_attr_vendor_id.attr,
742 &dev_attr_subsystem_id.attr,
743 &dev_attr_revision_id.attr,
744 &dev_attr_afg.attr,
745 &dev_attr_mfg.attr,
746 &dev_attr_vendor_name.attr,
747 &dev_attr_chip_name.attr,
748 &dev_attr_modelname.attr,
749 &dev_attr_init_pin_configs.attr,
750 &dev_attr_driver_pin_configs.attr,
751 #ifdef CONFIG_PM
752 &dev_attr_power_on_acct.attr,
753 &dev_attr_power_off_acct.attr,
754 #endif
755 #ifdef CONFIG_SND_HDA_RECONFIG
756 &dev_attr_init_verbs.attr,
757 &dev_attr_hints.attr,
758 &dev_attr_user_pin_configs.attr,
759 &dev_attr_reconfig.attr,
760 &dev_attr_clear.attr,
761 #endif
762 NULL
763 };
764
765 static const struct attribute_group hda_dev_attr_group = {
766 .attrs = hda_dev_attrs,
767 };
768
769 const struct attribute_group *snd_hda_dev_attr_groups[] = {
770 &hda_dev_attr_group,
771 NULL
772 };
773
774 void snd_hda_sysfs_init(struct hda_codec *codec)
775 {
776 mutex_init(&codec->user_mutex);
777 #ifdef CONFIG_SND_HDA_RECONFIG
778 snd_array_init(&codec->init_verbs, sizeof(struct hda_verb), 32);
779 snd_array_init(&codec->hints, sizeof(struct hda_hint), 32);
780 snd_array_init(&codec->user_pins, sizeof(struct hda_pincfg), 16);
781 #endif
782 }
783
784 void snd_hda_sysfs_clear(struct hda_codec *codec)
785 {
786 #ifdef CONFIG_SND_HDA_RECONFIG
787 struct hda_hint *hint;
788 int i;
789
790 /* clear init verbs */
791 snd_array_free(&codec->init_verbs);
792 /* clear hints */
793 snd_array_for_each(&codec->hints, i, hint) {
794 kfree(hint->key); /* we don't need to free hint->val */
795 }
796 snd_array_free(&codec->hints);
797 snd_array_free(&codec->user_pins);
798 #endif
799 }