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, field) \ 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->field); \ 58 } 59 60 #define CODEC_INFO_STR_SHOW(type, field) \ 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->field ? codec->field : ""); \ 68 } 69 70 CODEC_INFO_SHOW(vendor_id, core.vendor_id); 71 CODEC_INFO_SHOW(subsystem_id, core.subsystem_id); 72 CODEC_INFO_SHOW(revision_id, core.revision_id); 73 CODEC_INFO_SHOW(afg, core.afg); 74 CODEC_INFO_SHOW(mfg, core.mfg); 75 CODEC_INFO_STR_SHOW(vendor_name, core.vendor_name); 76 CODEC_INFO_STR_SHOW(chip_name, core.chip_name); 77 CODEC_INFO_STR_SHOW(modelname, 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->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, field) \ 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->field = val; \ 184 return count; \ 185 } 186 187 #define CODEC_INFO_STR_STORE(type, field) \ 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->field); \ 197 codec->field = s; \ 198 return count; \ 199 } 200 201 CODEC_INFO_STORE(vendor_id, core.vendor_id); 202 CODEC_INFO_STORE(subsystem_id, core.subsystem_id); 203 CODEC_INFO_STORE(revision_id, core.revision_id); 204 CODEC_INFO_STR_STORE(vendor_name, core.vendor_name); 205 CODEC_INFO_STR_STORE(chip_name, core.chip_name); 206 CODEC_INFO_STR_STORE(modelname, 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_codec(codec, bus) { 556 if ((vendorid <= 0 || codec->core.vendor_id == vendorid) && 557 (subid <= 0 || codec->core.subsystem_id == subid) && 558 codec->core.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 snd_hda_codec_set_name(*codecp, buf); 599 } 600 601 #define DEFINE_PARSE_ID_MODE(name) \ 602 static void parse_##name##_mode(char *buf, struct hda_bus *bus, \ 603 struct hda_codec **codecp) \ 604 { \ 605 unsigned long val; \ 606 if (!kstrtoul(buf, 0, &val)) \ 607 (*codecp)->core.name = val; \ 608 } 609 610 DEFINE_PARSE_ID_MODE(vendor_id); 611 DEFINE_PARSE_ID_MODE(subsystem_id); 612 DEFINE_PARSE_ID_MODE(revision_id); 613 614 615 struct hda_patch_item { 616 const char *tag; 617 const char *alias; 618 void (*parser)(char *buf, struct hda_bus *bus, struct hda_codec **retc); 619 }; 620 621 static struct hda_patch_item patch_items[NUM_LINE_MODES] = { 622 [LINE_MODE_CODEC] = { 623 .tag = "[codec]", 624 .parser = parse_codec_mode, 625 }, 626 [LINE_MODE_MODEL] = { 627 .tag = "[model]", 628 .parser = parse_model_mode, 629 }, 630 [LINE_MODE_VERB] = { 631 .tag = "[verb]", 632 .alias = "[init_verbs]", 633 .parser = parse_verb_mode, 634 }, 635 [LINE_MODE_PINCFG] = { 636 .tag = "[pincfg]", 637 .alias = "[user_pin_configs]", 638 .parser = parse_pincfg_mode, 639 }, 640 [LINE_MODE_HINT] = { 641 .tag = "[hint]", 642 .alias = "[hints]", 643 .parser = parse_hint_mode 644 }, 645 [LINE_MODE_VENDOR_ID] = { 646 .tag = "[vendor_id]", 647 .parser = parse_vendor_id_mode, 648 }, 649 [LINE_MODE_SUBSYSTEM_ID] = { 650 .tag = "[subsystem_id]", 651 .parser = parse_subsystem_id_mode, 652 }, 653 [LINE_MODE_REVISION_ID] = { 654 .tag = "[revision_id]", 655 .parser = parse_revision_id_mode, 656 }, 657 [LINE_MODE_CHIP_NAME] = { 658 .tag = "[chip_name]", 659 .parser = parse_chip_name_mode, 660 }, 661 }; 662 663 /* check the line starting with '[' -- change the parser mode accodingly */ 664 static int parse_line_mode(char *buf, struct hda_bus *bus) 665 { 666 int i; 667 for (i = 0; i < ARRAY_SIZE(patch_items); i++) { 668 if (!patch_items[i].tag) 669 continue; 670 if (strmatch(buf, patch_items[i].tag)) 671 return i; 672 if (patch_items[i].alias && strmatch(buf, patch_items[i].alias)) 673 return i; 674 } 675 return LINE_MODE_NONE; 676 } 677 678 /* copy one line from the buffer in fw, and update the fields in fw 679 * return zero if it reaches to the end of the buffer, or non-zero 680 * if successfully copied a line 681 * 682 * the spaces at the beginning and the end of the line are stripped 683 */ 684 static int get_line_from_fw(char *buf, int size, size_t *fw_size_p, 685 const void **fw_data_p) 686 { 687 int len; 688 size_t fw_size = *fw_size_p; 689 const char *p = *fw_data_p; 690 691 while (isspace(*p) && fw_size) { 692 p++; 693 fw_size--; 694 } 695 if (!fw_size) 696 return 0; 697 698 for (len = 0; len < fw_size; len++) { 699 if (!*p) 700 break; 701 if (*p == '\n') { 702 p++; 703 len++; 704 break; 705 } 706 if (len < size) 707 *buf++ = *p++; 708 } 709 *buf = 0; 710 *fw_size_p = fw_size - len; 711 *fw_data_p = p; 712 remove_trail_spaces(buf); 713 return 1; 714 } 715 716 /** 717 * snd_hda_load_patch - load a "patch" firmware file and parse it 718 * @bus: HD-audio bus 719 * @fw_size: the firmware byte size 720 * @fw_buf: the firmware data 721 */ 722 int snd_hda_load_patch(struct hda_bus *bus, size_t fw_size, const void *fw_buf) 723 { 724 char buf[128]; 725 struct hda_codec *codec; 726 int line_mode; 727 728 line_mode = LINE_MODE_NONE; 729 codec = NULL; 730 while (get_line_from_fw(buf, sizeof(buf) - 1, &fw_size, &fw_buf)) { 731 if (!*buf || *buf == '#' || *buf == '\n') 732 continue; 733 if (*buf == '[') 734 line_mode = parse_line_mode(buf, bus); 735 else if (patch_items[line_mode].parser && 736 (codec || line_mode <= LINE_MODE_CODEC)) 737 patch_items[line_mode].parser(buf, bus, &codec); 738 } 739 return 0; 740 } 741 EXPORT_SYMBOL_GPL(snd_hda_load_patch); 742 #endif /* CONFIG_SND_HDA_PATCH_LOADER */ 743 744 /* 745 * sysfs entries 746 */ 747 static struct attribute *hda_dev_attrs[] = { 748 &dev_attr_vendor_id.attr, 749 &dev_attr_subsystem_id.attr, 750 &dev_attr_revision_id.attr, 751 &dev_attr_afg.attr, 752 &dev_attr_mfg.attr, 753 &dev_attr_vendor_name.attr, 754 &dev_attr_chip_name.attr, 755 &dev_attr_modelname.attr, 756 &dev_attr_init_pin_configs.attr, 757 &dev_attr_driver_pin_configs.attr, 758 #ifdef CONFIG_PM 759 &dev_attr_power_on_acct.attr, 760 &dev_attr_power_off_acct.attr, 761 #endif 762 #ifdef CONFIG_SND_HDA_RECONFIG 763 &dev_attr_init_verbs.attr, 764 &dev_attr_hints.attr, 765 &dev_attr_user_pin_configs.attr, 766 &dev_attr_reconfig.attr, 767 &dev_attr_clear.attr, 768 #endif 769 NULL 770 }; 771 772 static struct attribute_group hda_dev_attr_group = { 773 .attrs = hda_dev_attrs, 774 }; 775 776 const struct attribute_group *snd_hda_dev_attr_groups[] = { 777 &hda_dev_attr_group, 778 NULL 779 }; 780 781 void snd_hda_sysfs_init(struct hda_codec *codec) 782 { 783 mutex_init(&codec->user_mutex); 784 #ifdef CONFIG_SND_HDA_RECONFIG 785 snd_array_init(&codec->init_verbs, sizeof(struct hda_verb), 32); 786 snd_array_init(&codec->hints, sizeof(struct hda_hint), 32); 787 snd_array_init(&codec->user_pins, sizeof(struct hda_pincfg), 16); 788 #endif 789 } 790 791 void snd_hda_sysfs_clear(struct hda_codec *codec) 792 { 793 #ifdef CONFIG_SND_HDA_RECONFIG 794 int i; 795 796 /* clear init verbs */ 797 snd_array_free(&codec->init_verbs); 798 /* clear hints */ 799 for (i = 0; i < codec->hints.used; i++) { 800 struct hda_hint *hint = snd_array_elem(&codec->hints, i); 801 kfree(hint->key); /* we don't need to free hint->val */ 802 } 803 snd_array_free(&codec->hints); 804 snd_array_free(&codec->user_pins); 805 #endif 806 } 807