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