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