1/* 2 * HWDEP Interface for HD-audio codec 3 * 4 * Copyright (c) 2007 Takashi Iwai <tiwai@suse.de> 5 * 6 * This driver is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 * 11 * This driver is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 */ 20 21#include <linux/init.h> 22#include <linux/slab.h> 23#include <linux/pci.h> 24#include <linux/compat.h> 25#include <linux/mutex.h> 26#include <linux/ctype.h> 27#include <linux/string.h> 28#include <linux/firmware.h> 29#include <sound/core.h> 30#include "hda_codec.h" 31#include "hda_local.h" 32#include <sound/hda_hwdep.h> 33#include <sound/minors.h> 34 35/* hint string pair */ 36struct hda_hint { 37 const char *key; 38 const char *val; /* contained in the same alloc as key */ 39}; 40 41/* 42 * write/read an out-of-bound verb 43 */ 44static int verb_write_ioctl(struct hda_codec *codec, 45 struct hda_verb_ioctl __user *arg) 46{ 47 u32 verb, res; 48 49 if (get_user(verb, &arg->verb)) 50 return -EFAULT; 51 res = snd_hda_codec_read(codec, verb >> 24, 0, 52 (verb >> 8) & 0xffff, verb & 0xff); 53 if (put_user(res, &arg->res)) 54 return -EFAULT; 55 return 0; 56} 57 58static int get_wcap_ioctl(struct hda_codec *codec, 59 struct hda_verb_ioctl __user *arg) 60{ 61 u32 verb, res; 62 63 if (get_user(verb, &arg->verb)) 64 return -EFAULT; 65 res = get_wcaps(codec, verb >> 24); 66 if (put_user(res, &arg->res)) 67 return -EFAULT; 68 return 0; 69} 70 71 72/* 73 */ 74static int hda_hwdep_ioctl(struct snd_hwdep *hw, struct file *file, 75 unsigned int cmd, unsigned long arg) 76{ 77 struct hda_codec *codec = hw->private_data; 78 void __user *argp = (void __user *)arg; 79 80 switch (cmd) { 81 case HDA_IOCTL_PVERSION: 82 return put_user(HDA_HWDEP_VERSION, (int __user *)argp); 83 case HDA_IOCTL_VERB_WRITE: 84 return verb_write_ioctl(codec, argp); 85 case HDA_IOCTL_GET_WCAP: 86 return get_wcap_ioctl(codec, argp); 87 } 88 return -ENOIOCTLCMD; 89} 90 91#ifdef CONFIG_COMPAT 92static int hda_hwdep_ioctl_compat(struct snd_hwdep *hw, struct file *file, 93 unsigned int cmd, unsigned long arg) 94{ 95 return hda_hwdep_ioctl(hw, file, cmd, (unsigned long)compat_ptr(arg)); 96} 97#endif 98 99static int hda_hwdep_open(struct snd_hwdep *hw, struct file *file) 100{ 101#ifndef CONFIG_SND_DEBUG_VERBOSE 102 if (!capable(CAP_SYS_RAWIO)) 103 return -EACCES; 104#endif 105 return 0; 106} 107 108static void clear_hwdep_elements(struct hda_codec *codec) 109{ 110 int i; 111 112 /* clear init verbs */ 113 snd_array_free(&codec->init_verbs); 114 /* clear hints */ 115 for (i = 0; i < codec->hints.used; i++) { 116 struct hda_hint *hint = snd_array_elem(&codec->hints, i); 117 kfree(hint->key); /* we don't need to free hint->val */ 118 } 119 snd_array_free(&codec->hints); 120 snd_array_free(&codec->user_pins); 121} 122 123static void hwdep_free(struct snd_hwdep *hwdep) 124{ 125 clear_hwdep_elements(hwdep->private_data); 126} 127 128int /*__devinit*/ snd_hda_create_hwdep(struct hda_codec *codec) 129{ 130 char hwname[16]; 131 struct snd_hwdep *hwdep; 132 int err; 133 134 sprintf(hwname, "HDA Codec %d", codec->addr); 135 err = snd_hwdep_new(codec->bus->card, hwname, codec->addr, &hwdep); 136 if (err < 0) 137 return err; 138 codec->hwdep = hwdep; 139 sprintf(hwdep->name, "HDA Codec %d", codec->addr); 140 hwdep->iface = SNDRV_HWDEP_IFACE_HDA; 141 hwdep->private_data = codec; 142 hwdep->private_free = hwdep_free; 143 hwdep->exclusive = 1; 144 145 hwdep->ops.open = hda_hwdep_open; 146 hwdep->ops.ioctl = hda_hwdep_ioctl; 147#ifdef CONFIG_COMPAT 148 hwdep->ops.ioctl_compat = hda_hwdep_ioctl_compat; 149#endif 150 151 snd_array_init(&codec->init_verbs, sizeof(struct hda_verb), 32); 152 snd_array_init(&codec->hints, sizeof(struct hda_hint), 32); 153 snd_array_init(&codec->user_pins, sizeof(struct hda_pincfg), 16); 154 155 return 0; 156} 157 158#ifdef CONFIG_SND_HDA_POWER_SAVE 159static ssize_t power_on_acct_show(struct device *dev, 160 struct device_attribute *attr, 161 char *buf) 162{ 163 struct snd_hwdep *hwdep = dev_get_drvdata(dev); 164 struct hda_codec *codec = hwdep->private_data; 165 snd_hda_update_power_acct(codec); 166 return sprintf(buf, "%u\n", jiffies_to_msecs(codec->power_on_acct)); 167} 168 169static ssize_t power_off_acct_show(struct device *dev, 170 struct device_attribute *attr, 171 char *buf) 172{ 173 struct snd_hwdep *hwdep = dev_get_drvdata(dev); 174 struct hda_codec *codec = hwdep->private_data; 175 snd_hda_update_power_acct(codec); 176 return sprintf(buf, "%u\n", jiffies_to_msecs(codec->power_off_acct)); 177} 178 179static struct device_attribute power_attrs[] = { 180 __ATTR_RO(power_on_acct), 181 __ATTR_RO(power_off_acct), 182}; 183 184int snd_hda_hwdep_add_power_sysfs(struct hda_codec *codec) 185{ 186 struct snd_hwdep *hwdep = codec->hwdep; 187 int i; 188 189 for (i = 0; i < ARRAY_SIZE(power_attrs); i++) 190 snd_add_device_sysfs_file(SNDRV_DEVICE_TYPE_HWDEP, hwdep->card, 191 hwdep->device, &power_attrs[i]); 192 return 0; 193} 194#endif /* CONFIG_SND_HDA_POWER_SAVE */ 195 196#ifdef CONFIG_SND_HDA_RECONFIG 197 198/* 199 * sysfs interface 200 */ 201 202static int clear_codec(struct hda_codec *codec) 203{ 204 int err; 205 206 err = snd_hda_codec_reset(codec); 207 if (err < 0) { 208 snd_printk(KERN_ERR "The codec is being used, can't free.\n"); 209 return err; 210 } 211 clear_hwdep_elements(codec); 212 return 0; 213} 214 215static int reconfig_codec(struct hda_codec *codec) 216{ 217 int err; 218 219 snd_hda_power_up(codec); 220 snd_printk(KERN_INFO "hda-codec: reconfiguring\n"); 221 err = snd_hda_codec_reset(codec); 222 if (err < 0) { 223 snd_printk(KERN_ERR 224 "The codec is being used, can't reconfigure.\n"); 225 goto error; 226 } 227 err = snd_hda_codec_configure(codec); 228 if (err < 0) 229 goto error; 230 /* rebuild PCMs */ 231 err = snd_hda_codec_build_pcms(codec); 232 if (err < 0) 233 goto error; 234 /* rebuild mixers */ 235 err = snd_hda_codec_build_controls(codec); 236 if (err < 0) 237 goto error; 238 err = snd_card_register(codec->bus->card); 239 error: 240 snd_hda_power_down(codec); 241 return err; 242} 243 244/* 245 * allocate a string at most len chars, and remove the trailing EOL 246 */ 247static char *kstrndup_noeol(const char *src, size_t len) 248{ 249 char *s = kstrndup(src, len, GFP_KERNEL); 250 char *p; 251 if (!s) 252 return NULL; 253 p = strchr(s, '\n'); 254 if (p) 255 *p = 0; 256 return s; 257} 258 259#define CODEC_INFO_SHOW(type) \ 260static ssize_t type##_show(struct device *dev, \ 261 struct device_attribute *attr, \ 262 char *buf) \ 263{ \ 264 struct snd_hwdep *hwdep = dev_get_drvdata(dev); \ 265 struct hda_codec *codec = hwdep->private_data; \ 266 return sprintf(buf, "0x%x\n", codec->type); \ 267} 268 269#define CODEC_INFO_STR_SHOW(type) \ 270static ssize_t type##_show(struct device *dev, \ 271 struct device_attribute *attr, \ 272 char *buf) \ 273{ \ 274 struct snd_hwdep *hwdep = dev_get_drvdata(dev); \ 275 struct hda_codec *codec = hwdep->private_data; \ 276 return sprintf(buf, "%s\n", \ 277 codec->type ? codec->type : ""); \ 278} 279 280CODEC_INFO_SHOW(vendor_id); 281CODEC_INFO_SHOW(subsystem_id); 282CODEC_INFO_SHOW(revision_id); 283CODEC_INFO_SHOW(afg); 284CODEC_INFO_SHOW(mfg); 285CODEC_INFO_STR_SHOW(vendor_name); 286CODEC_INFO_STR_SHOW(chip_name); 287CODEC_INFO_STR_SHOW(modelname); 288 289#define CODEC_INFO_STORE(type) \ 290static ssize_t type##_store(struct device *dev, \ 291 struct device_attribute *attr, \ 292 const char *buf, size_t count) \ 293{ \ 294 struct snd_hwdep *hwdep = dev_get_drvdata(dev); \ 295 struct hda_codec *codec = hwdep->private_data; \ 296 unsigned long val; \ 297 int err = strict_strtoul(buf, 0, &val); \ 298 if (err < 0) \ 299 return err; \ 300 codec->type = val; \ 301 return count; \ 302} 303 304#define CODEC_INFO_STR_STORE(type) \ 305static ssize_t type##_store(struct device *dev, \ 306 struct device_attribute *attr, \ 307 const char *buf, size_t count) \ 308{ \ 309 struct snd_hwdep *hwdep = dev_get_drvdata(dev); \ 310 struct hda_codec *codec = hwdep->private_data; \ 311 char *s = kstrndup_noeol(buf, 64); \ 312 if (!s) \ 313 return -ENOMEM; \ 314 kfree(codec->type); \ 315 codec->type = s; \ 316 return count; \ 317} 318 319CODEC_INFO_STORE(vendor_id); 320CODEC_INFO_STORE(subsystem_id); 321CODEC_INFO_STORE(revision_id); 322CODEC_INFO_STR_STORE(vendor_name); 323CODEC_INFO_STR_STORE(chip_name); 324CODEC_INFO_STR_STORE(modelname); 325 326#define CODEC_ACTION_STORE(type) \ 327static ssize_t type##_store(struct device *dev, \ 328 struct device_attribute *attr, \ 329 const char *buf, size_t count) \ 330{ \ 331 struct snd_hwdep *hwdep = dev_get_drvdata(dev); \ 332 struct hda_codec *codec = hwdep->private_data; \ 333 int err = 0; \ 334 if (*buf) \ 335 err = type##_codec(codec); \ 336 return err < 0 ? err : count; \ 337} 338 339CODEC_ACTION_STORE(reconfig); 340CODEC_ACTION_STORE(clear); 341 342static ssize_t init_verbs_show(struct device *dev, 343 struct device_attribute *attr, 344 char *buf) 345{ 346 struct snd_hwdep *hwdep = dev_get_drvdata(dev); 347 struct hda_codec *codec = hwdep->private_data; 348 int i, len = 0; 349 for (i = 0; i < codec->init_verbs.used; i++) { 350 struct hda_verb *v = snd_array_elem(&codec->init_verbs, i); 351 len += snprintf(buf + len, PAGE_SIZE - len, 352 "0x%02x 0x%03x 0x%04x\n", 353 v->nid, v->verb, v->param); 354 } 355 return len; 356} 357 358static int parse_init_verbs(struct hda_codec *codec, const char *buf) 359{ 360 struct hda_verb *v; 361 int nid, verb, param; 362 363 if (sscanf(buf, "%i %i %i", &nid, &verb, ¶m) != 3) 364 return -EINVAL; 365 if (!nid || !verb) 366 return -EINVAL; 367 v = snd_array_new(&codec->init_verbs); 368 if (!v) 369 return -ENOMEM; 370 v->nid = nid; 371 v->verb = verb; 372 v->param = param; 373 return 0; 374} 375 376static ssize_t init_verbs_store(struct device *dev, 377 struct device_attribute *attr, 378 const char *buf, size_t count) 379{ 380 struct snd_hwdep *hwdep = dev_get_drvdata(dev); 381 struct hda_codec *codec = hwdep->private_data; 382 int err = parse_init_verbs(codec, buf); 383 if (err < 0) 384 return err; 385 return count; 386} 387 388static ssize_t hints_show(struct device *dev, 389 struct device_attribute *attr, 390 char *buf) 391{ 392 struct snd_hwdep *hwdep = dev_get_drvdata(dev); 393 struct hda_codec *codec = hwdep->private_data; 394 int i, len = 0; 395 for (i = 0; i < codec->hints.used; i++) { 396 struct hda_hint *hint = snd_array_elem(&codec->hints, i); 397 len += snprintf(buf + len, PAGE_SIZE - len, 398 "%s = %s\n", hint->key, hint->val); 399 } 400 return len; 401} 402 403static struct hda_hint *get_hint(struct hda_codec *codec, const char *key) 404{ 405 int i; 406 407 for (i = 0; i < codec->hints.used; i++) { 408 struct hda_hint *hint = snd_array_elem(&codec->hints, i); 409 if (!strcmp(hint->key, key)) 410 return hint; 411 } 412 return NULL; 413} 414 415static void remove_trail_spaces(char *str) 416{ 417 char *p; 418 if (!*str) 419 return; 420 p = str + strlen(str) - 1; 421 for (; isspace(*p); p--) { 422 *p = 0; 423 if (p == str) 424 return; 425 } 426} 427 428#define MAX_HINTS 1024 429 430static int parse_hints(struct hda_codec *codec, const char *buf) 431{ 432 char *key, *val; 433 struct hda_hint *hint; 434 435 buf = skip_spaces(buf); 436 if (!*buf || *buf == '#' || *buf == '\n') 437 return 0; 438 if (*buf == '=') 439 return -EINVAL; 440 key = kstrndup_noeol(buf, 1024); 441 if (!key) 442 return -ENOMEM; 443 /* extract key and val */ 444 val = strchr(key, '='); 445 if (!val) { 446 kfree(key); 447 return -EINVAL; 448 } 449 *val++ = 0; 450 val = skip_spaces(val); 451 remove_trail_spaces(key); 452 remove_trail_spaces(val); 453 hint = get_hint(codec, key); 454 if (hint) { 455 /* replace */ 456 kfree(hint->key); 457 hint->key = key; 458 hint->val = val; 459 return 0; 460 } 461 /* allocate a new hint entry */ 462 if (codec->hints.used >= MAX_HINTS) 463 hint = NULL; 464 else 465 hint = snd_array_new(&codec->hints); 466 if (!hint) { 467 kfree(key); 468 return -ENOMEM; 469 } 470 hint->key = key; 471 hint->val = val; 472 return 0; 473} 474 475static ssize_t hints_store(struct device *dev, 476 struct device_attribute *attr, 477 const char *buf, size_t count) 478{ 479 struct snd_hwdep *hwdep = dev_get_drvdata(dev); 480 struct hda_codec *codec = hwdep->private_data; 481 int err = parse_hints(codec, buf); 482 if (err < 0) 483 return err; 484 return count; 485} 486 487static ssize_t pin_configs_show(struct hda_codec *codec, 488 struct snd_array *list, 489 char *buf) 490{ 491 int i, len = 0; 492 for (i = 0; i < list->used; i++) { 493 struct hda_pincfg *pin = snd_array_elem(list, i); 494 len += sprintf(buf + len, "0x%02x 0x%08x\n", 495 pin->nid, pin->cfg); 496 } 497 return len; 498} 499 500static ssize_t init_pin_configs_show(struct device *dev, 501 struct device_attribute *attr, 502 char *buf) 503{ 504 struct snd_hwdep *hwdep = dev_get_drvdata(dev); 505 struct hda_codec *codec = hwdep->private_data; 506 return pin_configs_show(codec, &codec->init_pins, buf); 507} 508 509static ssize_t user_pin_configs_show(struct device *dev, 510 struct device_attribute *attr, 511 char *buf) 512{ 513 struct snd_hwdep *hwdep = dev_get_drvdata(dev); 514 struct hda_codec *codec = hwdep->private_data; 515 return pin_configs_show(codec, &codec->user_pins, buf); 516} 517 518static ssize_t driver_pin_configs_show(struct device *dev, 519 struct device_attribute *attr, 520 char *buf) 521{ 522 struct snd_hwdep *hwdep = dev_get_drvdata(dev); 523 struct hda_codec *codec = hwdep->private_data; 524 return pin_configs_show(codec, &codec->driver_pins, buf); 525} 526 527#define MAX_PIN_CONFIGS 32 528 529static int parse_user_pin_configs(struct hda_codec *codec, const char *buf) 530{ 531 int nid, cfg; 532 533 if (sscanf(buf, "%i %i", &nid, &cfg) != 2) 534 return -EINVAL; 535 if (!nid) 536 return -EINVAL; 537 return snd_hda_add_pincfg(codec, &codec->user_pins, nid, cfg); 538} 539 540static ssize_t user_pin_configs_store(struct device *dev, 541 struct device_attribute *attr, 542 const char *buf, size_t count) 543{ 544 struct snd_hwdep *hwdep = dev_get_drvdata(dev); 545 struct hda_codec *codec = hwdep->private_data; 546 int err = parse_user_pin_configs(codec, buf); 547 if (err < 0) 548 return err; 549 return count; 550} 551 552#define CODEC_ATTR_RW(type) \ 553 __ATTR(type, 0644, type##_show, type##_store) 554#define CODEC_ATTR_RO(type) \ 555 __ATTR_RO(type) 556#define CODEC_ATTR_WO(type) \ 557 __ATTR(type, 0200, NULL, type##_store) 558 559static struct device_attribute codec_attrs[] = { 560 CODEC_ATTR_RW(vendor_id), 561 CODEC_ATTR_RW(subsystem_id), 562 CODEC_ATTR_RW(revision_id), 563 CODEC_ATTR_RO(afg), 564 CODEC_ATTR_RO(mfg), 565 CODEC_ATTR_RW(vendor_name), 566 CODEC_ATTR_RW(chip_name), 567 CODEC_ATTR_RW(modelname), 568 CODEC_ATTR_RW(init_verbs), 569 CODEC_ATTR_RW(hints), 570 CODEC_ATTR_RO(init_pin_configs), 571 CODEC_ATTR_RW(user_pin_configs), 572 CODEC_ATTR_RO(driver_pin_configs), 573 CODEC_ATTR_WO(reconfig), 574 CODEC_ATTR_WO(clear), 575}; 576 577/* 578 * create sysfs files on hwdep directory 579 */ 580int snd_hda_hwdep_add_sysfs(struct hda_codec *codec) 581{ 582 struct snd_hwdep *hwdep = codec->hwdep; 583 int i; 584 585 for (i = 0; i < ARRAY_SIZE(codec_attrs); i++) 586 snd_add_device_sysfs_file(SNDRV_DEVICE_TYPE_HWDEP, hwdep->card, 587 hwdep->device, &codec_attrs[i]); 588 return 0; 589} 590 591/* 592 * Look for hint string 593 */ 594const char *snd_hda_get_hint(struct hda_codec *codec, const char *key) 595{ 596 struct hda_hint *hint = get_hint(codec, key); 597 return hint ? hint->val : NULL; 598} 599EXPORT_SYMBOL_HDA(snd_hda_get_hint); 600 601int snd_hda_get_bool_hint(struct hda_codec *codec, const char *key) 602{ 603 const char *p = snd_hda_get_hint(codec, key); 604 if (!p || !*p) 605 return -ENOENT; 606 switch (toupper(*p)) { 607 case 'T': /* true */ 608 case 'Y': /* yes */ 609 case '1': 610 return 1; 611 } 612 return 0; 613} 614EXPORT_SYMBOL_HDA(snd_hda_get_bool_hint); 615 616#endif /* CONFIG_SND_HDA_RECONFIG */ 617 618#ifdef CONFIG_SND_HDA_PATCH_LOADER 619 620/* parser mode */ 621enum { 622 LINE_MODE_NONE, 623 LINE_MODE_CODEC, 624 LINE_MODE_MODEL, 625 LINE_MODE_PINCFG, 626 LINE_MODE_VERB, 627 LINE_MODE_HINT, 628 LINE_MODE_VENDOR_ID, 629 LINE_MODE_SUBSYSTEM_ID, 630 LINE_MODE_REVISION_ID, 631 LINE_MODE_CHIP_NAME, 632 NUM_LINE_MODES, 633}; 634 635static inline int strmatch(const char *a, const char *b) 636{ 637 return strnicmp(a, b, strlen(b)) == 0; 638} 639 640/* parse the contents after the line "[codec]" 641 * accept only the line with three numbers, and assign the current codec 642 */ 643static void parse_codec_mode(char *buf, struct hda_bus *bus, 644 struct hda_codec **codecp) 645{ 646 unsigned int vendorid, subid, caddr; 647 struct hda_codec *codec; 648 649 *codecp = NULL; 650 if (sscanf(buf, "%i %i %i", &vendorid, &subid, &caddr) == 3) { 651 list_for_each_entry(codec, &bus->codec_list, list) { 652 if (codec->vendor_id == vendorid && 653 codec->subsystem_id == subid && 654 codec->addr == caddr) { 655 *codecp = codec; 656 break; 657 } 658 } 659 } 660} 661 662/* parse the contents after the other command tags, [pincfg], [verb], 663 * [vendor_id], [subsystem_id], [revision_id], [chip_name], [hint] and [model] 664 * just pass to the sysfs helper (only when any codec was specified) 665 */ 666static void parse_pincfg_mode(char *buf, struct hda_bus *bus, 667 struct hda_codec **codecp) 668{ 669 parse_user_pin_configs(*codecp, buf); 670} 671 672static void parse_verb_mode(char *buf, struct hda_bus *bus, 673 struct hda_codec **codecp) 674{ 675 parse_init_verbs(*codecp, buf); 676} 677 678static void parse_hint_mode(char *buf, struct hda_bus *bus, 679 struct hda_codec **codecp) 680{ 681 parse_hints(*codecp, buf); 682} 683 684static void parse_model_mode(char *buf, struct hda_bus *bus, 685 struct hda_codec **codecp) 686{ 687 kfree((*codecp)->modelname); 688 (*codecp)->modelname = kstrdup(buf, GFP_KERNEL); 689} 690 691static void parse_chip_name_mode(char *buf, struct hda_bus *bus, 692 struct hda_codec **codecp) 693{ 694 kfree((*codecp)->chip_name); 695 (*codecp)->chip_name = kstrdup(buf, GFP_KERNEL); 696} 697 698#define DEFINE_PARSE_ID_MODE(name) \ 699static void parse_##name##_mode(char *buf, struct hda_bus *bus, \ 700 struct hda_codec **codecp) \ 701{ \ 702 unsigned long val; \ 703 if (!strict_strtoul(buf, 0, &val)) \ 704 (*codecp)->name = val; \ 705} 706 707DEFINE_PARSE_ID_MODE(vendor_id); 708DEFINE_PARSE_ID_MODE(subsystem_id); 709DEFINE_PARSE_ID_MODE(revision_id); 710 711 712struct hda_patch_item { 713 const char *tag; 714 void (*parser)(char *buf, struct hda_bus *bus, struct hda_codec **retc); 715 int need_codec; 716}; 717 718static struct hda_patch_item patch_items[NUM_LINE_MODES] = { 719 [LINE_MODE_CODEC] = { "[codec]", parse_codec_mode, 0 }, 720 [LINE_MODE_MODEL] = { "[model]", parse_model_mode, 1 }, 721 [LINE_MODE_VERB] = { "[verb]", parse_verb_mode, 1 }, 722 [LINE_MODE_PINCFG] = { "[pincfg]", parse_pincfg_mode, 1 }, 723 [LINE_MODE_HINT] = { "[hint]", parse_hint_mode, 1 }, 724 [LINE_MODE_VENDOR_ID] = { "[vendor_id]", parse_vendor_id_mode, 1 }, 725 [LINE_MODE_SUBSYSTEM_ID] = { "[subsystem_id]", parse_subsystem_id_mode, 1 }, 726 [LINE_MODE_REVISION_ID] = { "[revision_id]", parse_revision_id_mode, 1 }, 727 [LINE_MODE_CHIP_NAME] = { "[chip_name]", parse_chip_name_mode, 1 }, 728}; 729 730/* check the line starting with '[' -- change the parser mode accodingly */ 731static int parse_line_mode(char *buf, struct hda_bus *bus) 732{ 733 int i; 734 for (i = 0; i < ARRAY_SIZE(patch_items); i++) { 735 if (!patch_items[i].tag) 736 continue; 737 if (strmatch(buf, patch_items[i].tag)) 738 return i; 739 } 740 return LINE_MODE_NONE; 741} 742 743/* copy one line from the buffer in fw, and update the fields in fw 744 * return zero if it reaches to the end of the buffer, or non-zero 745 * if successfully copied a line 746 * 747 * the spaces at the beginning and the end of the line are stripped 748 */ 749static int get_line_from_fw(char *buf, int size, struct firmware *fw) 750{ 751 int len; 752 const char *p = fw->data; 753 while (isspace(*p) && fw->size) { 754 p++; 755 fw->size--; 756 } 757 if (!fw->size) 758 return 0; 759 if (size < fw->size) 760 size = fw->size; 761 762 for (len = 0; len < fw->size; len++) { 763 if (!*p) 764 break; 765 if (*p == '\n') { 766 p++; 767 len++; 768 break; 769 } 770 if (len < size) 771 *buf++ = *p++; 772 } 773 *buf = 0; 774 fw->size -= len; 775 fw->data = p; 776 remove_trail_spaces(buf); 777 return 1; 778} 779 780/* 781 * load a "patch" firmware file and parse it 782 */ 783int snd_hda_load_patch(struct hda_bus *bus, const char *patch) 784{ 785 int err; 786 const struct firmware *fw; 787 struct firmware tmp; 788 char buf[128]; 789 struct hda_codec *codec; 790 int line_mode; 791 struct device *dev = bus->card->dev; 792 793 if (snd_BUG_ON(!dev)) 794 return -ENODEV; 795 err = request_firmware(&fw, patch, dev); 796 if (err < 0) { 797 printk(KERN_ERR "hda-codec: Cannot load the patch '%s'\n", 798 patch); 799 return err; 800 } 801 802 tmp = *fw; 803 line_mode = LINE_MODE_NONE; 804 codec = NULL; 805 while (get_line_from_fw(buf, sizeof(buf) - 1, &tmp)) { 806 if (!*buf || *buf == '#' || *buf == '\n') 807 continue; 808 if (*buf == '[') 809 line_mode = parse_line_mode(buf, bus); 810 else if (patch_items[line_mode].parser && 811 (codec || !patch_items[line_mode].need_codec)) 812 patch_items[line_mode].parser(buf, bus, &codec); 813 } 814 release_firmware(fw); 815 return 0; 816} 817EXPORT_SYMBOL_HDA(snd_hda_load_patch); 818#endif /* CONFIG_SND_HDA_PATCH_LOADER */ 819