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