~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/sound/pci/hda/hda_sysfs.c

Version: ~ [ linux-5.15-rc6 ] ~ [ linux-5.14.14 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.75 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.155 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.213 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.252 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.287 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.289 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.18.140 ] ~ [ linux-3.16.85 ] ~ [ linux-3.14.79 ] ~ [ linux-3.12.74 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp