Linux Audio

Check our new training course

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