cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

hda_sysfs.c (19110B)


      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
     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
     52#define CODEC_INFO_SHOW(type, field)				\
     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);		\
     58	return sprintf(buf, "0x%x\n", codec->field);		\
     59}
     60
     61#define CODEC_INFO_STR_SHOW(type, field)			\
     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",				\
     68		       codec->field ? codec->field : "");	\
     69}
     70
     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);
     79
     80static 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
     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
    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) {
    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
    130static 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 = device_reprobe(hda_codec_dev(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 */
    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
    166#define CODEC_INFO_STORE(type, field)				\
    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;					\
    176	codec->field = val;					\
    177	return count;						\
    178}
    179
    180#define CODEC_INFO_STR_STORE(type, field)			\
    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;					\
    189	kfree(codec->field);					\
    190	codec->field = s;					\
    191	return count;						\
    192}
    193
    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);
    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);
    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
    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);
    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
    282static 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
    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
    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
    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
    406/* sysfs attributes exposed only when CONFIG_SND_HDA_RECONFIG=y */
    407static DEVICE_ATTR_RW(init_verbs);
    408static DEVICE_ATTR_RW(hints);
    409static DEVICE_ATTR_RW(user_pin_configs);
    410static DEVICE_ATTR_WO(reconfig);
    411static 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 */
    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
    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 */
    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
    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 */
    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
    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
    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{
    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 */
    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) {
    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 */
    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{
    591	snd_hda_codec_set_name(*codecp, buf);
    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)) \
    600		(*codecp)->core.name = val; \
    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
    614static 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 */
    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
    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 */
    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[] = {
    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
    765static const struct attribute_group hda_dev_attr_group = {
    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{
    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
    784void 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}