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 += 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 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, ¶m) != 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 += 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 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 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 */ 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