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 #define MAX_PIN_CONFIGS 32 379 380 static 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 394 static 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 */ 406 static DEVICE_ATTR_RW(init_verbs); 407 static DEVICE_ATTR_RW(hints); 408 static DEVICE_ATTR_RW(user_pin_configs); 409 static DEVICE_ATTR_WO(reconfig); 410 static 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 */ 420 const 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 } 425 EXPORT_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 */ 436 int 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 } 460 EXPORT_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 */ 472 int 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 } 491 EXPORT_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 502 static RECONFIG_DEVICE_ATTR(vendor_id); 503 static RECONFIG_DEVICE_ATTR(subsystem_id); 504 static RECONFIG_DEVICE_ATTR(revision_id); 505 static DEVICE_ATTR_RO(afg); 506 static DEVICE_ATTR_RO(mfg); 507 static RECONFIG_DEVICE_ATTR(vendor_name); 508 static RECONFIG_DEVICE_ATTR(chip_name); 509 static RECONFIG_DEVICE_ATTR(modelname); 510 static DEVICE_ATTR_RO(init_pin_configs); 511 static DEVICE_ATTR_RO(driver_pin_configs); 512 513 514 #ifdef CONFIG_SND_HDA_PATCH_LOADER 515 516 /* parser mode */ 517 enum { 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 531 static 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 */ 539 static 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 */ 562 static 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 568 static void parse_verb_mode(char *buf, struct hda_bus *bus, 569 struct hda_codec **codecp) 570 { 571 parse_init_verbs(*codecp, buf); 572 } 573 574 static void parse_hint_mode(char *buf, struct hda_bus *bus, 575 struct hda_codec **codecp) 576 { 577 parse_hints(*codecp, buf); 578 } 579 580 static 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 587 static 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) \ 594 static 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 602 DEFINE_PARSE_ID_MODE(vendor_id); 603 DEFINE_PARSE_ID_MODE(subsystem_id); 604 DEFINE_PARSE_ID_MODE(revision_id); 605 606 607 struct 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 613 static const 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 */ 656 static 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 */ 676 static 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 */ 714 int 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 } 733 EXPORT_SYMBOL_GPL(snd_hda_load_patch); 734 #endif /* CONFIG_SND_HDA_PATCH_LOADER */ 735 736 /* 737 * sysfs entries 738 */ 739 static 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 764 static const struct attribute_group hda_dev_attr_group = { 765 .attrs = hda_dev_attrs, 766 }; 767 768 const struct attribute_group *snd_hda_dev_attr_groups[] = { 769 &hda_dev_attr_group, 770 NULL 771 }; 772 773 void 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 783 void snd_hda_sysfs_clear(struct hda_codec *codec) 784 { 785 #ifdef CONFIG_SND_HDA_RECONFIG 786 struct hda_hint *hint; 787 int i; 788 789 /* clear init verbs */ 790 snd_array_free(&codec->init_verbs); 791 /* clear hints */ 792 snd_array_for_each(&codec->hints, i, hint) { 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