diff options
-rw-r--r-- | sound/pci/hda/hda_codec.c | 13 | ||||
-rw-r--r-- | sound/pci/hda/hda_codec.h | 1 | ||||
-rw-r--r-- | sound/pci/hda/hda_hwdep.c | 67 | ||||
-rw-r--r-- | sound/pci/hda/patch_sigmatel.c | 5 |
4 files changed, 65 insertions, 21 deletions
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 0a531f2f9255..b28e4031b8a1 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c | |||
@@ -1086,9 +1086,16 @@ unsigned int snd_hda_codec_get_pincfg(struct hda_codec *codec, hda_nid_t nid) | |||
1086 | struct hda_pincfg *pin; | 1086 | struct hda_pincfg *pin; |
1087 | 1087 | ||
1088 | #ifdef CONFIG_SND_HDA_HWDEP | 1088 | #ifdef CONFIG_SND_HDA_HWDEP |
1089 | pin = look_up_pincfg(codec, &codec->user_pins, nid); | 1089 | { |
1090 | if (pin) | 1090 | unsigned int cfg = 0; |
1091 | return pin->cfg; | 1091 | mutex_lock(&codec->user_mutex); |
1092 | pin = look_up_pincfg(codec, &codec->user_pins, nid); | ||
1093 | if (pin) | ||
1094 | cfg = pin->cfg; | ||
1095 | mutex_unlock(&codec->user_mutex); | ||
1096 | if (cfg) | ||
1097 | return cfg; | ||
1098 | } | ||
1092 | #endif | 1099 | #endif |
1093 | pin = look_up_pincfg(codec, &codec->driver_pins, nid); | 1100 | pin = look_up_pincfg(codec, &codec->driver_pins, nid); |
1094 | if (pin) | 1101 | if (pin) |
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h index 4c4f1660e654..61085b311059 100644 --- a/sound/pci/hda/hda_codec.h +++ b/sound/pci/hda/hda_codec.h | |||
@@ -845,6 +845,7 @@ struct hda_codec { | |||
845 | struct snd_array cvt_setups; /* audio convert setups */ | 845 | struct snd_array cvt_setups; /* audio convert setups */ |
846 | 846 | ||
847 | #ifdef CONFIG_SND_HDA_HWDEP | 847 | #ifdef CONFIG_SND_HDA_HWDEP |
848 | struct mutex user_mutex; | ||
848 | struct snd_hwdep *hwdep; /* assigned hwdep device */ | 849 | struct snd_hwdep *hwdep; /* assigned hwdep device */ |
849 | struct snd_array init_verbs; /* additional init verbs */ | 850 | struct snd_array init_verbs; /* additional init verbs */ |
850 | struct snd_array hints; /* additional hints */ | 851 | struct snd_array hints; /* additional hints */ |
diff --git a/sound/pci/hda/hda_hwdep.c b/sound/pci/hda/hda_hwdep.c index a5c9411bb367..2dddf7fbebcc 100644 --- a/sound/pci/hda/hda_hwdep.c +++ b/sound/pci/hda/hda_hwdep.c | |||
@@ -148,6 +148,7 @@ int snd_hda_create_hwdep(struct hda_codec *codec) | |||
148 | hwdep->ops.ioctl_compat = hda_hwdep_ioctl_compat; | 148 | hwdep->ops.ioctl_compat = hda_hwdep_ioctl_compat; |
149 | #endif | 149 | #endif |
150 | 150 | ||
151 | mutex_init(&codec->user_mutex); | ||
151 | snd_array_init(&codec->init_verbs, sizeof(struct hda_verb), 32); | 152 | 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->hints, sizeof(struct hda_hint), 32); |
153 | snd_array_init(&codec->user_pins, sizeof(struct hda_pincfg), 16); | 154 | snd_array_init(&codec->user_pins, sizeof(struct hda_pincfg), 16); |
@@ -346,12 +347,14 @@ static ssize_t init_verbs_show(struct device *dev, | |||
346 | struct snd_hwdep *hwdep = dev_get_drvdata(dev); | 347 | struct snd_hwdep *hwdep = dev_get_drvdata(dev); |
347 | struct hda_codec *codec = hwdep->private_data; | 348 | struct hda_codec *codec = hwdep->private_data; |
348 | int i, len = 0; | 349 | int i, len = 0; |
350 | mutex_lock(&codec->user_mutex); | ||
349 | for (i = 0; i < codec->init_verbs.used; i++) { | 351 | for (i = 0; i < codec->init_verbs.used; i++) { |
350 | struct hda_verb *v = snd_array_elem(&codec->init_verbs, i); | 352 | struct hda_verb *v = snd_array_elem(&codec->init_verbs, i); |
351 | len += snprintf(buf + len, PAGE_SIZE - len, | 353 | len += snprintf(buf + len, PAGE_SIZE - len, |
352 | "0x%02x 0x%03x 0x%04x\n", | 354 | "0x%02x 0x%03x 0x%04x\n", |
353 | v->nid, v->verb, v->param); | 355 | v->nid, v->verb, v->param); |
354 | } | 356 | } |
357 | mutex_unlock(&codec->user_mutex); | ||
355 | return len; | 358 | return len; |
356 | } | 359 | } |
357 | 360 | ||
@@ -364,12 +367,16 @@ static int parse_init_verbs(struct hda_codec *codec, const char *buf) | |||
364 | return -EINVAL; | 367 | return -EINVAL; |
365 | if (!nid || !verb) | 368 | if (!nid || !verb) |
366 | return -EINVAL; | 369 | return -EINVAL; |
370 | mutex_lock(&codec->user_mutex); | ||
367 | v = snd_array_new(&codec->init_verbs); | 371 | v = snd_array_new(&codec->init_verbs); |
368 | if (!v) | 372 | if (!v) { |
373 | mutex_unlock(&codec->user_mutex); | ||
369 | return -ENOMEM; | 374 | return -ENOMEM; |
375 | } | ||
370 | v->nid = nid; | 376 | v->nid = nid; |
371 | v->verb = verb; | 377 | v->verb = verb; |
372 | v->param = param; | 378 | v->param = param; |
379 | mutex_unlock(&codec->user_mutex); | ||
373 | return 0; | 380 | return 0; |
374 | } | 381 | } |
375 | 382 | ||
@@ -392,11 +399,13 @@ static ssize_t hints_show(struct device *dev, | |||
392 | struct snd_hwdep *hwdep = dev_get_drvdata(dev); | 399 | struct snd_hwdep *hwdep = dev_get_drvdata(dev); |
393 | struct hda_codec *codec = hwdep->private_data; | 400 | struct hda_codec *codec = hwdep->private_data; |
394 | int i, len = 0; | 401 | int i, len = 0; |
402 | mutex_lock(&codec->user_mutex); | ||
395 | for (i = 0; i < codec->hints.used; i++) { | 403 | for (i = 0; i < codec->hints.used; i++) { |
396 | struct hda_hint *hint = snd_array_elem(&codec->hints, i); | 404 | struct hda_hint *hint = snd_array_elem(&codec->hints, i); |
397 | len += snprintf(buf + len, PAGE_SIZE - len, | 405 | len += snprintf(buf + len, PAGE_SIZE - len, |
398 | "%s = %s\n", hint->key, hint->val); | 406 | "%s = %s\n", hint->key, hint->val); |
399 | } | 407 | } |
408 | mutex_unlock(&codec->user_mutex); | ||
400 | return len; | 409 | return len; |
401 | } | 410 | } |
402 | 411 | ||
@@ -431,6 +440,7 @@ static int parse_hints(struct hda_codec *codec, const char *buf) | |||
431 | { | 440 | { |
432 | char *key, *val; | 441 | char *key, *val; |
433 | struct hda_hint *hint; | 442 | struct hda_hint *hint; |
443 | int err = 0; | ||
434 | 444 | ||
435 | buf = skip_spaces(buf); | 445 | buf = skip_spaces(buf); |
436 | if (!*buf || *buf == '#' || *buf == '\n') | 446 | if (!*buf || *buf == '#' || *buf == '\n') |
@@ -450,26 +460,31 @@ static int parse_hints(struct hda_codec *codec, const char *buf) | |||
450 | val = skip_spaces(val); | 460 | val = skip_spaces(val); |
451 | remove_trail_spaces(key); | 461 | remove_trail_spaces(key); |
452 | remove_trail_spaces(val); | 462 | remove_trail_spaces(val); |
463 | mutex_lock(&codec->user_mutex); | ||
453 | hint = get_hint(codec, key); | 464 | hint = get_hint(codec, key); |
454 | if (hint) { | 465 | if (hint) { |
455 | /* replace */ | 466 | /* replace */ |
456 | kfree(hint->key); | 467 | kfree(hint->key); |
457 | hint->key = key; | 468 | hint->key = key; |
458 | hint->val = val; | 469 | hint->val = val; |
459 | return 0; | 470 | goto unlock; |
460 | } | 471 | } |
461 | /* allocate a new hint entry */ | 472 | /* allocate a new hint entry */ |
462 | if (codec->hints.used >= MAX_HINTS) | 473 | if (codec->hints.used >= MAX_HINTS) |
463 | hint = NULL; | 474 | hint = NULL; |
464 | else | 475 | else |
465 | hint = snd_array_new(&codec->hints); | 476 | hint = snd_array_new(&codec->hints); |
466 | if (!hint) { | 477 | if (hint) { |
467 | kfree(key); | 478 | hint->key = key; |
468 | return -ENOMEM; | 479 | hint->val = val; |
480 | } else { | ||
481 | err = -ENOMEM; | ||
469 | } | 482 | } |
470 | hint->key = key; | 483 | unlock: |
471 | hint->val = val; | 484 | mutex_unlock(&codec->user_mutex); |
472 | return 0; | 485 | if (err) |
486 | kfree(key); | ||
487 | return err; | ||
473 | } | 488 | } |
474 | 489 | ||
475 | static ssize_t hints_store(struct device *dev, | 490 | static ssize_t hints_store(struct device *dev, |
@@ -489,11 +504,13 @@ static ssize_t pin_configs_show(struct hda_codec *codec, | |||
489 | char *buf) | 504 | char *buf) |
490 | { | 505 | { |
491 | int i, len = 0; | 506 | int i, len = 0; |
507 | mutex_lock(&codec->user_mutex); | ||
492 | for (i = 0; i < list->used; i++) { | 508 | for (i = 0; i < list->used; i++) { |
493 | struct hda_pincfg *pin = snd_array_elem(list, i); | 509 | struct hda_pincfg *pin = snd_array_elem(list, i); |
494 | len += sprintf(buf + len, "0x%02x 0x%08x\n", | 510 | len += sprintf(buf + len, "0x%02x 0x%08x\n", |
495 | pin->nid, pin->cfg); | 511 | pin->nid, pin->cfg); |
496 | } | 512 | } |
513 | mutex_unlock(&codec->user_mutex); | ||
497 | return len; | 514 | return len; |
498 | } | 515 | } |
499 | 516 | ||
@@ -528,13 +545,16 @@ static ssize_t driver_pin_configs_show(struct device *dev, | |||
528 | 545 | ||
529 | static int parse_user_pin_configs(struct hda_codec *codec, const char *buf) | 546 | static int parse_user_pin_configs(struct hda_codec *codec, const char *buf) |
530 | { | 547 | { |
531 | int nid, cfg; | 548 | int nid, cfg, err; |
532 | 549 | ||
533 | if (sscanf(buf, "%i %i", &nid, &cfg) != 2) | 550 | if (sscanf(buf, "%i %i", &nid, &cfg) != 2) |
534 | return -EINVAL; | 551 | return -EINVAL; |
535 | if (!nid) | 552 | if (!nid) |
536 | return -EINVAL; | 553 | return -EINVAL; |
537 | return snd_hda_add_pincfg(codec, &codec->user_pins, nid, cfg); | 554 | mutex_lock(&codec->user_mutex); |
555 | err = snd_hda_add_pincfg(codec, &codec->user_pins, nid, cfg); | ||
556 | mutex_unlock(&codec->user_mutex); | ||
557 | return err; | ||
538 | } | 558 | } |
539 | 559 | ||
540 | static ssize_t user_pin_configs_store(struct device *dev, | 560 | static ssize_t user_pin_configs_store(struct device *dev, |
@@ -600,16 +620,27 @@ EXPORT_SYMBOL_HDA(snd_hda_get_hint); | |||
600 | 620 | ||
601 | int snd_hda_get_bool_hint(struct hda_codec *codec, const char *key) | 621 | int snd_hda_get_bool_hint(struct hda_codec *codec, const char *key) |
602 | { | 622 | { |
603 | const char *p = snd_hda_get_hint(codec, key); | 623 | const char *p; |
624 | int ret; | ||
625 | |||
626 | mutex_lock(&codec->user_mutex); | ||
627 | p = snd_hda_get_hint(codec, key); | ||
604 | if (!p || !*p) | 628 | if (!p || !*p) |
605 | return -ENOENT; | 629 | ret = -ENOENT; |
606 | switch (toupper(*p)) { | 630 | else { |
607 | case 'T': /* true */ | 631 | switch (toupper(*p)) { |
608 | case 'Y': /* yes */ | 632 | case 'T': /* true */ |
609 | case '1': | 633 | case 'Y': /* yes */ |
610 | return 1; | 634 | case '1': |
635 | ret = 1; | ||
636 | break; | ||
637 | default: | ||
638 | ret = 0; | ||
639 | break; | ||
640 | } | ||
611 | } | 641 | } |
612 | return 0; | 642 | mutex_unlock(&codec->user_mutex); |
643 | return ret; | ||
613 | } | 644 | } |
614 | EXPORT_SYMBOL_HDA(snd_hda_get_bool_hint); | 645 | EXPORT_SYMBOL_HDA(snd_hda_get_bool_hint); |
615 | 646 | ||
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index a86547ca17c8..d3a81f10fe5c 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c | |||
@@ -4298,15 +4298,20 @@ static void stac_toggle_power_map(struct hda_codec *codec, hda_nid_t nid, | |||
4298 | static inline int get_int_hint(struct hda_codec *codec, const char *key, | 4298 | static inline int get_int_hint(struct hda_codec *codec, const char *key, |
4299 | int *valp) | 4299 | int *valp) |
4300 | { | 4300 | { |
4301 | #ifdef CONFIG_SND_HDA_RECONFIG | ||
4301 | const char *p; | 4302 | const char *p; |
4303 | mutex_lock(&codec->user_mutex); | ||
4302 | p = snd_hda_get_hint(codec, key); | 4304 | p = snd_hda_get_hint(codec, key); |
4303 | if (p) { | 4305 | if (p) { |
4304 | unsigned long val; | 4306 | unsigned long val; |
4305 | if (!strict_strtoul(p, 0, &val)) { | 4307 | if (!strict_strtoul(p, 0, &val)) { |
4306 | *valp = val; | 4308 | *valp = val; |
4309 | mutex_unlock(&codec->user_mutex); | ||
4307 | return 1; | 4310 | return 1; |
4308 | } | 4311 | } |
4309 | } | 4312 | } |
4313 | mutex_unlock(&codec->user_mutex); | ||
4314 | #endif | ||
4310 | return 0; | 4315 | return 0; |
4311 | } | 4316 | } |
4312 | 4317 | ||