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 sysfs_emit(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 sysfs_emit(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 sysfs_emit(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 sysfs_emit(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 += sysfs_emit_at(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 = 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 */ 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 += sysfs_emit_at(buf, len, "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 232 static 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 254 static 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 265 static 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 const struct hda_hint *hint; 271 int i, len = 0; 272 mutex_lock(&codec->user_mutex); 273 snd_array_for_each(&codec->hints, i, hint) { 274 len += sysfs_emit_at(buf, len, "%s = %s\n", 275 hint->key, hint->val); 276 } 277 mutex_unlock(&codec->user_mutex); 278 return len; 279 } 280 281 static struct hda_hint *get_hint(struct hda_codec *codec, const char *key) 282 { 283 struct hda_hint *hint; 284 int i; 285 286 snd_array_for_each(&codec->hints, i, hint) { 287 if (!strcmp(hint->key, key)) 288 return hint; 289 } 290 return NULL; 291 } 292 293 static 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 308 static 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 359 static 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 370 static 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 static int parse_user_pin_configs(struct hda_codec *codec, const char *buf) 379 { 380 int nid, cfg, err; 381 382 if (sscanf(buf, "%i %i", &nid, &cfg) != 2) 383 return -EINVAL; 384 if (!nid) 385 return -EINVAL; 386 mutex_lock(&codec->user_mutex); 387 err = snd_hda_add_pincfg(codec, &codec->user_pins, nid, cfg); 388 mutex_unlock(&codec->user_mutex); 389 return err; 390 } 391 392 static ssize_t user_pin_configs_store(struct device *dev, 393 struct device_attribute *attr, 394 const char *buf, size_t count) 395 { 396 struct hda_codec *codec = dev_get_drvdata(dev); 397 int err = parse_user_pin_configs(codec, buf); 398 if (err < 0) 399 return err; 400 return count; 401 } 402 403 /* sysfs attributes exposed only when CONFIG_SND_HDA_RECONFIG=y */ 404 static DEVICE_ATTR_RW(init_verbs); 405 static DEVICE_ATTR_RW(hints); 406 static DEVICE_ATTR_RW(user_pin_configs); 407 static DEVICE_ATTR_WO(reconfig); 408 static DEVICE_ATTR_WO(clear); 409 410 /** 411 * snd_hda_get_hint - Look for hint string 412 * @codec: the HDA codec 413 * @key: the hint key string 414 * 415 * Look for a hint key/value pair matching with the given key string 416 * and returns the value string. If nothing found, returns NULL. 417 */ 418 const char *snd_hda_get_hint(struct hda_codec *codec, const char *key) 419 { 420 struct hda_hint *hint = get_hint(codec, key); 421 return hint ? hint->val : NULL; 422 } 423 EXPORT_SYMBOL_GPL(snd_hda_get_hint); 424 425 /** 426 * snd_hda_get_bool_hint - Get a boolean hint value 427 * @codec: the HDA codec 428 * @key: the hint key string 429 * 430 * Look for a hint key/value pair matching with the given key string 431 * and returns a boolean value parsed from the value. If no matching 432 * key is found, return a negative value. 433 */ 434 int snd_hda_get_bool_hint(struct hda_codec *codec, const char *key) 435 { 436 const char *p; 437 int ret; 438 439 mutex_lock(&codec->user_mutex); 440 p = snd_hda_get_hint(codec, key); 441 if (!p || !*p) 442 ret = -ENOENT; 443 else { 444 switch (toupper(*p)) { 445 case 'T': /* true */ 446 case 'Y': /* yes */ 447 case '1': 448 ret = 1; 449 break; 450 default: 451 ret = 0; 452 break; 453 } 454 } 455 mutex_unlock(&codec->user_mutex); 456 return ret; 457 } 458 EXPORT_SYMBOL_GPL(snd_hda_get_bool_hint); 459 460 /** 461 * snd_hda_get_int_hint - Get an integer hint value 462 * @codec: the HDA codec 463 * @key: the hint key string 464 * @valp: pointer to store a value 465 * 466 * Look for a hint key/value pair matching with the given key string 467 * and stores the integer value to @valp. If no matching key is found, 468 * return a negative error code. Otherwise it returns zero. 469 */ 470 int snd_hda_get_int_hint(struct hda_codec *codec, const char *key, int *valp) 471 { 472 const char *p; 473 unsigned long val; 474 int ret; 475 476 mutex_lock(&codec->user_mutex); 477 p = snd_hda_get_hint(codec, key); 478 if (!p) 479 ret = -ENOENT; 480 else if (kstrtoul(p, 0, &val)) 481 ret = -EINVAL; 482 else { 483 *valp = val; 484 ret = 0; 485 } 486 mutex_unlock(&codec->user_mutex); 487 return ret; 488 } 489 EXPORT_SYMBOL_GPL(snd_hda_get_int_hint); 490 #endif /* CONFIG_SND_HDA_RECONFIG */ 491 492 /* 493 * common sysfs attributes 494 */ 495 #ifdef CONFIG_SND_HDA_RECONFIG 496 #define RECONFIG_DEVICE_ATTR(name) DEVICE_ATTR_RW(name) 497 #else 498 #define RECONFIG_DEVICE_ATTR(name) DEVICE_ATTR_RO(name) 499 #endif 500 static RECONFIG_DEVICE_ATTR(vendor_id); 501 static RECONFIG_DEVICE_ATTR(subsystem_id); 502 static RECONFIG_DEVICE_ATTR(revision_id); 503 static DEVICE_ATTR_RO(afg); 504 static DEVICE_ATTR_RO(mfg); 505 static RECONFIG_DEVICE_ATTR(vendor_name); 506 static RECONFIG_DEVICE_ATTR(chip_name); 507 static RECONFIG_DEVICE_ATTR(modelname); 508 static DEVICE_ATTR_RO(init_pin_configs); 509 static DEVICE_ATTR_RO(driver_pin_configs); 510 511 512 #ifdef CONFIG_SND_HDA_PATCH_LOADER 513 514 /* parser mode */ 515 enum { 516 LINE_MODE_NONE, 517 LINE_MODE_CODEC, 518 LINE_MODE_MODEL, 519 LINE_MODE_PINCFG, 520 LINE_MODE_VERB, 521 LINE_MODE_HINT, 522 LINE_MODE_VENDOR_ID, 523 LINE_MODE_SUBSYSTEM_ID, 524 LINE_MODE_REVISION_ID, 525 LINE_MODE_CHIP_NAME, 526 NUM_LINE_MODES, 527 }; 528 529 static inline int strmatch(const char *a, const char *b) 530 { 531 return strncasecmp(a, b, strlen(b)) == 0; 532 } 533 534 /* parse the contents after the line "[codec]" 535 * accept only the line with three numbers, and assign the current codec 536 */ 537 static void parse_codec_mode(char *buf, struct hda_bus *bus, 538 struct hda_codec **codecp) 539 { 540 int vendorid, subid, caddr; 541 struct hda_codec *codec; 542 543 *codecp = NULL; 544 if (sscanf(buf, "%i %i %i", &vendorid, &subid, &caddr) == 3) { 545 list_for_each_codec(codec, bus) { 546 if ((vendorid <= 0 || codec->core.vendor_id == vendorid) && 547 (subid <= 0 || codec->core.subsystem_id == subid) && 548 codec->core.addr == caddr) { 549 *codecp = codec; 550 break; 551 } 552 } 553 } 554 } 555 556 /* parse the contents after the other command tags, [pincfg], [verb], 557 * [vendor_id], [subsystem_id], [revision_id], [chip_name], [hint] and [model] 558 * just pass to the sysfs helper (only when any codec was specified) 559 */ 560 static void parse_pincfg_mode(char *buf, struct hda_bus *bus, 561 struct hda_codec **codecp) 562 { 563 parse_user_pin_configs(*codecp, buf); 564 } 565 566 static void parse_verb_mode(char *buf, struct hda_bus *bus, 567 struct hda_codec **codecp) 568 { 569 parse_init_verbs(*codecp, buf); 570 } 571 572 static void parse_hint_mode(char *buf, struct hda_bus *bus, 573 struct hda_codec **codecp) 574 { 575 parse_hints(*codecp, buf); 576 } 577 578 static void parse_model_mode(char *buf, struct hda_bus *bus, 579 struct hda_codec **codecp) 580 { 581 kfree((*codecp)->modelname); 582 (*codecp)->modelname = kstrdup(buf, GFP_KERNEL); 583 } 584 585 static void parse_chip_name_mode(char *buf, struct hda_bus *bus, 586 struct hda_codec **codecp) 587 { 588 snd_hda_codec_set_name(*codecp, buf); 589 } 590 591 #define DEFINE_PARSE_ID_MODE(name) \ 592 static void parse_##name##_mode(char *buf, struct hda_bus *bus, \ 593 struct hda_codec **codecp) \ 594 { \ 595 unsigned long val; \ 596 if (!kstrtoul(buf, 0, &val)) \ 597 (*codecp)->core.name = val; \ 598 } 599 600 DEFINE_PARSE_ID_MODE(vendor_id); 601 DEFINE_PARSE_ID_MODE(subsystem_id); 602 DEFINE_PARSE_ID_MODE(revision_id); 603 604 605 struct hda_patch_item { 606 const char *tag; 607 const char *alias; 608 void (*parser)(char *buf, struct hda_bus *bus, struct hda_codec **retc); 609 }; 610 611 static const struct hda_patch_item patch_items[NUM_LINE_MODES] = { 612 [LINE_MODE_CODEC] = { 613 .tag = "[codec]", 614 .parser = parse_codec_mode, 615 }, 616 [LINE_MODE_MODEL] = { 617 .tag = "[model]", 618 .parser = parse_model_mode, 619 }, 620 [LINE_MODE_VERB] = { 621 .tag = "[verb]", 622 .alias = "[init_verbs]", 623 .parser = parse_verb_mode, 624 }, 625 [LINE_MODE_PINCFG] = { 626 .tag = "[pincfg]", 627 .alias = "[user_pin_configs]", 628 .parser = parse_pincfg_mode, 629 }, 630 [LINE_MODE_HINT] = { 631 .tag = "[hint]", 632 .alias = "[hints]", 633 .parser = parse_hint_mode 634 }, 635 [LINE_MODE_VENDOR_ID] = { 636 .tag = "[vendor_id]", 637 .parser = parse_vendor_id_mode, 638 }, 639 [LINE_MODE_SUBSYSTEM_ID] = { 640 .tag = "[subsystem_id]", 641 .parser = parse_subsystem_id_mode, 642 }, 643 [LINE_MODE_REVISION_ID] = { 644 .tag = "[revision_id]", 645 .parser = parse_revision_id_mode, 646 }, 647 [LINE_MODE_CHIP_NAME] = { 648 .tag = "[chip_name]", 649 .parser = parse_chip_name_mode, 650 }, 651 }; 652 653 /* check the line starting with '[' -- change the parser mode accodingly */ 654 static int parse_line_mode(char *buf, struct hda_bus *bus) 655 { 656 int i; 657 for (i = 0; i < ARRAY_SIZE(patch_items); i++) { 658 if (!patch_items[i].tag) 659 continue; 660 if (strmatch(buf, patch_items[i].tag)) 661 return i; 662 if (patch_items[i].alias && strmatch(buf, patch_items[i].alias)) 663 return i; 664 } 665 return LINE_MODE_NONE; 666 } 667 668 /* copy one line from the buffer in fw, and update the fields in fw 669 * return zero if it reaches to the end of the buffer, or non-zero 670 * if successfully copied a line 671 * 672 * the spaces at the beginning and the end of the line are stripped 673 */ 674 static int get_line_from_fw(char *buf, int size, size_t *fw_size_p, 675 const void **fw_data_p) 676 { 677 int len; 678 size_t fw_size = *fw_size_p; 679 const char *p = *fw_data_p; 680 681 while (isspace(*p) && fw_size) { 682 p++; 683 fw_size--; 684 } 685 if (!fw_size) 686 return 0; 687 688 for (len = 0; len < fw_size; len++) { 689 if (!*p) 690 break; 691 if (*p == '\n') { 692 p++; 693 len++; 694 break; 695 } 696 if (len < size) 697 *buf++ = *p++; 698 } 699 *buf = 0; 700 *fw_size_p = fw_size - len; 701 *fw_data_p = p; 702 remove_trail_spaces(buf); 703 return 1; 704 } 705 706 /** 707 * snd_hda_load_patch - load a "patch" firmware file and parse it 708 * @bus: HD-audio bus 709 * @fw_size: the firmware byte size 710 * @fw_buf: the firmware data 711 */ 712 int snd_hda_load_patch(struct hda_bus *bus, size_t fw_size, const void *fw_buf) 713 { 714 char buf[128]; 715 struct hda_codec *codec; 716 int line_mode; 717 718 line_mode = LINE_MODE_NONE; 719 codec = NULL; 720 while (get_line_from_fw(buf, sizeof(buf) - 1, &fw_size, &fw_buf)) { 721 if (!*buf || *buf == '#' || *buf == '\n') 722 continue; 723 if (*buf == '[') 724 line_mode = parse_line_mode(buf, bus); 725 else if (patch_items[line_mode].parser && 726 (codec || line_mode <= LINE_MODE_CODEC)) 727 patch_items[line_mode].parser(buf, bus, &codec); 728 } 729 return 0; 730 } 731 EXPORT_SYMBOL_GPL(snd_hda_load_patch); 732 #endif /* CONFIG_SND_HDA_PATCH_LOADER */ 733 734 /* 735 * sysfs entries 736 */ 737 static struct attribute *hda_dev_attrs[] = { 738 &dev_attr_vendor_id.attr, 739 &dev_attr_subsystem_id.attr, 740 &dev_attr_revision_id.attr, 741 &dev_attr_afg.attr, 742 &dev_attr_mfg.attr, 743 &dev_attr_vendor_name.attr, 744 &dev_attr_chip_name.attr, 745 &dev_attr_modelname.attr, 746 &dev_attr_init_pin_configs.attr, 747 &dev_attr_driver_pin_configs.attr, 748 #ifdef CONFIG_PM 749 &dev_attr_power_on_acct.attr, 750 &dev_attr_power_off_acct.attr, 751 #endif 752 #ifdef CONFIG_SND_HDA_RECONFIG 753 &dev_attr_init_verbs.attr, 754 &dev_attr_hints.attr, 755 &dev_attr_user_pin_configs.attr, 756 &dev_attr_reconfig.attr, 757 &dev_attr_clear.attr, 758 #endif 759 NULL 760 }; 761 762 static const struct attribute_group hda_dev_attr_group = { 763 .attrs = hda_dev_attrs, 764 }; 765 766 const struct attribute_group *snd_hda_dev_attr_groups[] = { 767 &hda_dev_attr_group, 768 NULL 769 }; 770 771 void snd_hda_sysfs_init(struct hda_codec *codec) 772 { 773 mutex_init(&codec->user_mutex); 774 #ifdef CONFIG_SND_HDA_RECONFIG 775 snd_array_init(&codec->init_verbs, sizeof(struct hda_verb), 32); 776 snd_array_init(&codec->hints, sizeof(struct hda_hint), 32); 777 snd_array_init(&codec->user_pins, sizeof(struct hda_pincfg), 16); 778 #endif 779 } 780 781 void snd_hda_sysfs_clear(struct hda_codec *codec) 782 { 783 #ifdef CONFIG_SND_HDA_RECONFIG 784 struct hda_hint *hint; 785 int i; 786 787 /* clear init verbs */ 788 snd_array_free(&codec->init_verbs); 789 /* clear hints */ 790 snd_array_for_each(&codec->hints, i, hint) { 791 kfree(hint->key); /* we don't need to free hint->val */ 792 } 793 snd_array_free(&codec->hints); 794 snd_array_free(&codec->user_pins); 795 #endif 796 } 797