]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blame - sound/pci/hda/hda_sysfs.c
Merge tag 'powerpc-5.7-2' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc...
[mirror_ubuntu-jammy-kernel.git] / sound / pci / hda / hda_sysfs.c
CommitLineData
457c8996 1// SPDX-License-Identifier: GPL-2.0-only
648a8d27
TI
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>
be57bfff 18#include <sound/hda_codec.h>
648a8d27
TI
19#include "hda_local.h"
20#include <sound/hda_hwdep.h>
21#include <sound/minors.h>
22
23/* hint string pair */
24struct hda_hint {
25 const char *key;
26 const char *val; /* contained in the same alloc as key */
27};
28
29#ifdef CONFIG_PM
30static 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
39static 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
48static DEVICE_ATTR_RO(power_on_acct);
49static DEVICE_ATTR_RO(power_off_acct);
50#endif /* CONFIG_PM */
51
7639a06c 52#define CODEC_INFO_SHOW(type, field) \
b989d044
TI
53static 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); \
7639a06c 58 return sprintf(buf, "0x%x\n", codec->field); \
b989d044
TI
59}
60
7639a06c 61#define CODEC_INFO_STR_SHOW(type, field) \
b989d044
TI
62static 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", \
7639a06c 68 codec->field ? codec->field : ""); \
b989d044
TI
69}
70
7639a06c
TI
71CODEC_INFO_SHOW(vendor_id, core.vendor_id);
72CODEC_INFO_SHOW(subsystem_id, core.subsystem_id);
73CODEC_INFO_SHOW(revision_id, core.revision_id);
74CODEC_INFO_SHOW(afg, core.afg);
75CODEC_INFO_SHOW(mfg, core.mfg);
76CODEC_INFO_STR_SHOW(vendor_name, core.vendor_name);
77CODEC_INFO_STR_SHOW(chip_name, core.chip_name);
78CODEC_INFO_STR_SHOW(modelname, modelname);
b989d044
TI
79
80static ssize_t pin_configs_show(struct hda_codec *codec,
81 struct snd_array *list,
82 char *buf)
83{
a9c2dfc8 84 const struct hda_pincfg *pin;
b989d044
TI
85 int i, len = 0;
86 mutex_lock(&codec->user_mutex);
a9c2dfc8 87 snd_array_for_each(list, i, pin) {
b989d044
TI
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
95static 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
103static 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
648a8d27
TI
111#ifdef CONFIG_SND_HDA_RECONFIG
112
113/*
114 * sysfs interface
115 */
116
117static int clear_codec(struct hda_codec *codec)
118{
119 int err;
120
121 err = snd_hda_codec_reset(codec);
122 if (err < 0) {
4e76a883 123 codec_err(codec, "The codec is being used, can't free.\n");
648a8d27
TI
124 return err;
125 }
126 snd_hda_sysfs_clear(codec);
127 return 0;
128}
129
130static int reconfig_codec(struct hda_codec *codec)
131{
132 int err;
133
134 snd_hda_power_up(codec);
4e76a883 135 codec_info(codec, "hda-codec: reconfiguring\n");
648a8d27
TI
136 err = snd_hda_codec_reset(codec);
137 if (err < 0) {
4e76a883 138 codec_err(codec,
648a8d27
TI
139 "The codec is being used, can't reconfigure.\n");
140 goto error;
141 }
142 err = snd_hda_codec_configure(codec);
648a8d27
TI
143 if (err < 0)
144 goto error;
6efdd851 145 err = snd_card_register(codec->card);
648a8d27
TI
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 */
154static 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
7639a06c 166#define CODEC_INFO_STORE(type, field) \
648a8d27
TI
167static 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; \
7639a06c 176 codec->field = val; \
648a8d27
TI
177 return count; \
178}
179
7639a06c 180#define CODEC_INFO_STR_STORE(type, field) \
648a8d27
TI
181static 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; \
7639a06c
TI
189 kfree(codec->field); \
190 codec->field = s; \
648a8d27
TI
191 return count; \
192}
193
7639a06c
TI
194CODEC_INFO_STORE(vendor_id, core.vendor_id);
195CODEC_INFO_STORE(subsystem_id, core.subsystem_id);
196CODEC_INFO_STORE(revision_id, core.revision_id);
197CODEC_INFO_STR_STORE(vendor_name, core.vendor_name);
198CODEC_INFO_STR_STORE(chip_name, core.chip_name);
199CODEC_INFO_STR_STORE(modelname, modelname);
648a8d27
TI
200
201#define CODEC_ACTION_STORE(type) \
202static 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
213CODEC_ACTION_STORE(reconfig);
214CODEC_ACTION_STORE(clear);
215
216static 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);
a9c2dfc8 221 const struct hda_verb *v;
648a8d27
TI
222 int i, len = 0;
223 mutex_lock(&codec->user_mutex);
a9c2dfc8 224 snd_array_for_each(&codec->init_verbs, i, v) {
44eeb081 225 len += scnprintf(buf + len, PAGE_SIZE - len,
648a8d27
TI
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
233static 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
255static 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
266static 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);
a9c2dfc8 271 const struct hda_hint *hint;
648a8d27
TI
272 int i, len = 0;
273 mutex_lock(&codec->user_mutex);
a9c2dfc8 274 snd_array_for_each(&codec->hints, i, hint) {
44eeb081 275 len += scnprintf(buf + len, PAGE_SIZE - len,
648a8d27
TI
276 "%s = %s\n", hint->key, hint->val);
277 }
278 mutex_unlock(&codec->user_mutex);
279 return len;
280}
281
282static struct hda_hint *get_hint(struct hda_codec *codec, const char *key)
283{
a9c2dfc8 284 struct hda_hint *hint;
648a8d27
TI
285 int i;
286
a9c2dfc8 287 snd_array_for_each(&codec->hints, i, hint) {
648a8d27
TI
288 if (!strcmp(hint->key, key))
289 return hint;
290 }
291 return NULL;
292}
293
294static 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
309static 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
360static 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
648a8d27
TI
371static 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
648a8d27
TI
379#define MAX_PIN_CONFIGS 32
380
381static 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
395static 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
b989d044 406/* sysfs attributes exposed only when CONFIG_SND_HDA_RECONFIG=y */
648a8d27
TI
407static DEVICE_ATTR_RW(init_verbs);
408static DEVICE_ATTR_RW(hints);
648a8d27 409static DEVICE_ATTR_RW(user_pin_configs);
648a8d27
TI
410static DEVICE_ATTR_WO(reconfig);
411static DEVICE_ATTR_WO(clear);
412
95a962c3
TI
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.
648a8d27
TI
420 */
421const 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}
426EXPORT_SYMBOL_GPL(snd_hda_get_hint);
427
95a962c3
TI
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 */
648a8d27
TI
437int 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}
461EXPORT_SYMBOL_GPL(snd_hda_get_bool_hint);
462
95a962c3 463/**
c10b11f6 464 * snd_hda_get_int_hint - Get an integer hint value
95a962c3
TI
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 */
648a8d27
TI
473int 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}
492EXPORT_SYMBOL_GPL(snd_hda_get_int_hint);
493#endif /* CONFIG_SND_HDA_RECONFIG */
494
b989d044
TI
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
503static RECONFIG_DEVICE_ATTR(vendor_id);
504static RECONFIG_DEVICE_ATTR(subsystem_id);
505static RECONFIG_DEVICE_ATTR(revision_id);
506static DEVICE_ATTR_RO(afg);
507static DEVICE_ATTR_RO(mfg);
508static RECONFIG_DEVICE_ATTR(vendor_name);
509static RECONFIG_DEVICE_ATTR(chip_name);
510static RECONFIG_DEVICE_ATTR(modelname);
511static DEVICE_ATTR_RO(init_pin_configs);
512static DEVICE_ATTR_RO(driver_pin_configs);
513
514
648a8d27
TI
515#ifdef CONFIG_SND_HDA_PATCH_LOADER
516
517/* parser mode */
518enum {
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
532static inline int strmatch(const char *a, const char *b)
533{
8bb1ffdf 534 return strncasecmp(a, b, strlen(b)) == 0;
648a8d27
TI
535}
536
537/* parse the contents after the line "[codec]"
538 * accept only the line with three numbers, and assign the current codec
539 */
540static 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) {
d068ebc2 548 list_for_each_codec(codec, bus) {
7639a06c
TI
549 if ((vendorid <= 0 || codec->core.vendor_id == vendorid) &&
550 (subid <= 0 || codec->core.subsystem_id == subid) &&
551 codec->core.addr == caddr) {
648a8d27
TI
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 */
563static 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
569static void parse_verb_mode(char *buf, struct hda_bus *bus,
570 struct hda_codec **codecp)
571{
572 parse_init_verbs(*codecp, buf);
573}
574
575static void parse_hint_mode(char *buf, struct hda_bus *bus,
576 struct hda_codec **codecp)
577{
578 parse_hints(*codecp, buf);
579}
580
581static 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
588static void parse_chip_name_mode(char *buf, struct hda_bus *bus,
589 struct hda_codec **codecp)
590{
ded255be 591 snd_hda_codec_set_name(*codecp, buf);
648a8d27
TI
592}
593
594#define DEFINE_PARSE_ID_MODE(name) \
595static 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)) \
7639a06c 600 (*codecp)->core.name = val; \
648a8d27
TI
601}
602
603DEFINE_PARSE_ID_MODE(vendor_id);
604DEFINE_PARSE_ID_MODE(subsystem_id);
605DEFINE_PARSE_ID_MODE(revision_id);
606
607
608struct 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
bf82326f 614static const struct hda_patch_item patch_items[NUM_LINE_MODES] = {
648a8d27
TI
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 */
657static 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 */
677static 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
95a962c3
TI
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
648a8d27
TI
714 */
715int 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}
734EXPORT_SYMBOL_GPL(snd_hda_load_patch);
735#endif /* CONFIG_SND_HDA_PATCH_LOADER */
736
737/*
738 * sysfs entries
739 */
740static struct attribute *hda_dev_attrs[] = {
648a8d27
TI
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,
b989d044
TI
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
648a8d27
TI
756 &dev_attr_init_verbs.attr,
757 &dev_attr_hints.attr,
648a8d27 758 &dev_attr_user_pin_configs.attr,
648a8d27
TI
759 &dev_attr_reconfig.attr,
760 &dev_attr_clear.attr,
761#endif
762 NULL
763};
764
a5a041b6 765static const struct attribute_group hda_dev_attr_group = {
648a8d27
TI
766 .attrs = hda_dev_attrs,
767};
768
769const struct attribute_group *snd_hda_dev_attr_groups[] = {
770 &hda_dev_attr_group,
771 NULL
772};
773
774void snd_hda_sysfs_init(struct hda_codec *codec)
775{
648a8d27 776 mutex_init(&codec->user_mutex);
b989d044 777#ifdef CONFIG_SND_HDA_RECONFIG
648a8d27
TI
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
784void snd_hda_sysfs_clear(struct hda_codec *codec)
785{
786#ifdef CONFIG_SND_HDA_RECONFIG
a9c2dfc8 787 struct hda_hint *hint;
648a8d27
TI
788 int i;
789
790 /* clear init verbs */
791 snd_array_free(&codec->init_verbs);
792 /* clear hints */
a9c2dfc8 793 snd_array_for_each(&codec->hints, i, hint) {
648a8d27
TI
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}