diff options
| -rw-r--r-- | include/sound/control.h | 3 | ||||
| -rw-r--r-- | sound/core/seq/seq_lock.c | 4 | ||||
| -rw-r--r-- | sound/core/seq/seq_lock.h | 12 | ||||
| -rw-r--r-- | sound/core/vmaster.c | 31 | ||||
| -rw-r--r-- | sound/hda/hdac_controller.c | 5 | ||||
| -rw-r--r-- | sound/pci/hda/hda_codec.c | 97 | ||||
| -rw-r--r-- | sound/usb/quirks.c | 1 |
7 files changed, 95 insertions, 58 deletions
diff --git a/include/sound/control.h b/include/sound/control.h index bd7246de58e7..a1f1152bc687 100644 --- a/include/sound/control.h +++ b/include/sound/control.h | |||
| @@ -248,6 +248,9 @@ int snd_ctl_add_vmaster_hook(struct snd_kcontrol *kctl, | |||
| 248 | void *private_data); | 248 | void *private_data); |
| 249 | void snd_ctl_sync_vmaster(struct snd_kcontrol *kctl, bool hook_only); | 249 | void snd_ctl_sync_vmaster(struct snd_kcontrol *kctl, bool hook_only); |
| 250 | #define snd_ctl_sync_vmaster_hook(kctl) snd_ctl_sync_vmaster(kctl, true) | 250 | #define snd_ctl_sync_vmaster_hook(kctl) snd_ctl_sync_vmaster(kctl, true) |
| 251 | int snd_ctl_apply_vmaster_slaves(struct snd_kcontrol *kctl, | ||
| 252 | int (*func)(struct snd_kcontrol *, void *), | ||
| 253 | void *arg); | ||
| 251 | 254 | ||
| 252 | /* | 255 | /* |
| 253 | * Helper functions for jack-detection controls | 256 | * Helper functions for jack-detection controls |
diff --git a/sound/core/seq/seq_lock.c b/sound/core/seq/seq_lock.c index 0ff7926a5a69..cda64b489e42 100644 --- a/sound/core/seq/seq_lock.c +++ b/sound/core/seq/seq_lock.c | |||
| @@ -23,8 +23,6 @@ | |||
| 23 | #include <sound/core.h> | 23 | #include <sound/core.h> |
| 24 | #include "seq_lock.h" | 24 | #include "seq_lock.h" |
| 25 | 25 | ||
| 26 | #if defined(CONFIG_SMP) || defined(CONFIG_SND_DEBUG) | ||
| 27 | |||
| 28 | /* wait until all locks are released */ | 26 | /* wait until all locks are released */ |
| 29 | void snd_use_lock_sync_helper(snd_use_lock_t *lockp, const char *file, int line) | 27 | void snd_use_lock_sync_helper(snd_use_lock_t *lockp, const char *file, int line) |
| 30 | { | 28 | { |
| @@ -41,5 +39,3 @@ void snd_use_lock_sync_helper(snd_use_lock_t *lockp, const char *file, int line) | |||
| 41 | } | 39 | } |
| 42 | } | 40 | } |
| 43 | EXPORT_SYMBOL(snd_use_lock_sync_helper); | 41 | EXPORT_SYMBOL(snd_use_lock_sync_helper); |
| 44 | |||
| 45 | #endif | ||
diff --git a/sound/core/seq/seq_lock.h b/sound/core/seq/seq_lock.h index 54044bc2c9ef..ac38031c370e 100644 --- a/sound/core/seq/seq_lock.h +++ b/sound/core/seq/seq_lock.h | |||
| @@ -3,8 +3,6 @@ | |||
| 3 | 3 | ||
| 4 | #include <linux/sched.h> | 4 | #include <linux/sched.h> |
| 5 | 5 | ||
| 6 | #if defined(CONFIG_SMP) || defined(CONFIG_SND_DEBUG) | ||
| 7 | |||
| 8 | typedef atomic_t snd_use_lock_t; | 6 | typedef atomic_t snd_use_lock_t; |
| 9 | 7 | ||
| 10 | /* initialize lock */ | 8 | /* initialize lock */ |
| @@ -20,14 +18,4 @@ typedef atomic_t snd_use_lock_t; | |||
| 20 | void snd_use_lock_sync_helper(snd_use_lock_t *lock, const char *file, int line); | 18 | void snd_use_lock_sync_helper(snd_use_lock_t *lock, const char *file, int line); |
| 21 | #define snd_use_lock_sync(lockp) snd_use_lock_sync_helper(lockp, __BASE_FILE__, __LINE__) | 19 | #define snd_use_lock_sync(lockp) snd_use_lock_sync_helper(lockp, __BASE_FILE__, __LINE__) |
| 22 | 20 | ||
| 23 | #else /* SMP || CONFIG_SND_DEBUG */ | ||
| 24 | |||
| 25 | typedef spinlock_t snd_use_lock_t; /* dummy */ | ||
| 26 | #define snd_use_lock_init(lockp) /**/ | ||
| 27 | #define snd_use_lock_use(lockp) /**/ | ||
| 28 | #define snd_use_lock_free(lockp) /**/ | ||
| 29 | #define snd_use_lock_sync(lockp) /**/ | ||
| 30 | |||
| 31 | #endif /* SMP || CONFIG_SND_DEBUG */ | ||
| 32 | |||
| 33 | #endif /* __SND_SEQ_LOCK_H */ | 21 | #endif /* __SND_SEQ_LOCK_H */ |
diff --git a/sound/core/vmaster.c b/sound/core/vmaster.c index 6c58e6f73a01..e43af18d4383 100644 --- a/sound/core/vmaster.c +++ b/sound/core/vmaster.c | |||
| @@ -484,3 +484,34 @@ void snd_ctl_sync_vmaster(struct snd_kcontrol *kcontrol, bool hook_only) | |||
| 484 | master->hook(master->hook_private_data, master->val); | 484 | master->hook(master->hook_private_data, master->val); |
| 485 | } | 485 | } |
| 486 | EXPORT_SYMBOL_GPL(snd_ctl_sync_vmaster); | 486 | EXPORT_SYMBOL_GPL(snd_ctl_sync_vmaster); |
| 487 | |||
| 488 | /** | ||
| 489 | * snd_ctl_apply_vmaster_slaves - Apply function to each vmaster slave | ||
| 490 | * @kctl: vmaster kctl element | ||
| 491 | * @func: function to apply | ||
| 492 | * @arg: optional function argument | ||
| 493 | * | ||
| 494 | * Apply the function @func to each slave kctl of the given vmaster kctl. | ||
| 495 | * Returns 0 if successful, or a negative error code. | ||
| 496 | */ | ||
| 497 | int snd_ctl_apply_vmaster_slaves(struct snd_kcontrol *kctl, | ||
| 498 | int (*func)(struct snd_kcontrol *, void *), | ||
| 499 | void *arg) | ||
| 500 | { | ||
| 501 | struct link_master *master; | ||
| 502 | struct link_slave *slave; | ||
| 503 | int err; | ||
| 504 | |||
| 505 | master = snd_kcontrol_chip(kctl); | ||
| 506 | err = master_init(master); | ||
| 507 | if (err < 0) | ||
| 508 | return err; | ||
| 509 | list_for_each_entry(slave, &master->slaves, list) { | ||
| 510 | err = func(&slave->slave, arg); | ||
| 511 | if (err < 0) | ||
| 512 | return err; | ||
| 513 | } | ||
| 514 | |||
| 515 | return 0; | ||
| 516 | } | ||
| 517 | EXPORT_SYMBOL_GPL(snd_ctl_apply_vmaster_slaves); | ||
diff --git a/sound/hda/hdac_controller.c b/sound/hda/hdac_controller.c index 978dc1801b3a..f6d2985b2520 100644 --- a/sound/hda/hdac_controller.c +++ b/sound/hda/hdac_controller.c | |||
| @@ -284,6 +284,11 @@ int snd_hdac_bus_parse_capabilities(struct hdac_bus *bus) | |||
| 284 | dev_dbg(bus->dev, "HDA capability ID: 0x%x\n", | 284 | dev_dbg(bus->dev, "HDA capability ID: 0x%x\n", |
| 285 | (cur_cap & AZX_CAP_HDR_ID_MASK) >> AZX_CAP_HDR_ID_OFF); | 285 | (cur_cap & AZX_CAP_HDR_ID_MASK) >> AZX_CAP_HDR_ID_OFF); |
| 286 | 286 | ||
| 287 | if (cur_cap == -1) { | ||
| 288 | dev_dbg(bus->dev, "Invalid capability reg read\n"); | ||
| 289 | break; | ||
| 290 | } | ||
| 291 | |||
| 287 | switch ((cur_cap & AZX_CAP_HDR_ID_MASK) >> AZX_CAP_HDR_ID_OFF) { | 292 | switch ((cur_cap & AZX_CAP_HDR_ID_MASK) >> AZX_CAP_HDR_ID_OFF) { |
| 288 | case AZX_ML_CAP_ID: | 293 | case AZX_ML_CAP_ID: |
| 289 | dev_dbg(bus->dev, "Found ML capability\n"); | 294 | dev_dbg(bus->dev, "Found ML capability\n"); |
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 3db26c451837..a0989d231fd0 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c | |||
| @@ -1803,36 +1803,6 @@ static int check_slave_present(struct hda_codec *codec, | |||
| 1803 | return 1; | 1803 | return 1; |
| 1804 | } | 1804 | } |
| 1805 | 1805 | ||
| 1806 | /* guess the value corresponding to 0dB */ | ||
| 1807 | static int get_kctl_0dB_offset(struct hda_codec *codec, | ||
| 1808 | struct snd_kcontrol *kctl, int *step_to_check) | ||
| 1809 | { | ||
| 1810 | int _tlv[4]; | ||
| 1811 | const int *tlv = NULL; | ||
| 1812 | int val = -1; | ||
| 1813 | |||
| 1814 | if ((kctl->vd[0].access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) && | ||
| 1815 | kctl->tlv.c == snd_hda_mixer_amp_tlv) { | ||
| 1816 | get_ctl_amp_tlv(kctl, _tlv); | ||
| 1817 | tlv = _tlv; | ||
| 1818 | } else if (kctl->vd[0].access & SNDRV_CTL_ELEM_ACCESS_TLV_READ) | ||
| 1819 | tlv = kctl->tlv.p; | ||
| 1820 | if (tlv && tlv[0] == SNDRV_CTL_TLVT_DB_SCALE) { | ||
| 1821 | int step = tlv[3]; | ||
| 1822 | step &= ~TLV_DB_SCALE_MUTE; | ||
| 1823 | if (!step) | ||
| 1824 | return -1; | ||
| 1825 | if (*step_to_check && *step_to_check != step) { | ||
| 1826 | codec_err(codec, "Mismatching dB step for vmaster slave (%d!=%d)\n", | ||
| 1827 | - *step_to_check, step); | ||
| 1828 | return -1; | ||
| 1829 | } | ||
| 1830 | *step_to_check = step; | ||
| 1831 | val = -tlv[2] / step; | ||
| 1832 | } | ||
| 1833 | return val; | ||
| 1834 | } | ||
| 1835 | |||
| 1836 | /* call kctl->put with the given value(s) */ | 1806 | /* call kctl->put with the given value(s) */ |
| 1837 | static int put_kctl_with_value(struct snd_kcontrol *kctl, int val) | 1807 | static int put_kctl_with_value(struct snd_kcontrol *kctl, int val) |
| 1838 | { | 1808 | { |
| @@ -1847,19 +1817,58 @@ static int put_kctl_with_value(struct snd_kcontrol *kctl, int val) | |||
| 1847 | return 0; | 1817 | return 0; |
| 1848 | } | 1818 | } |
| 1849 | 1819 | ||
| 1850 | /* initialize the slave volume with 0dB */ | 1820 | struct slave_init_arg { |
| 1851 | static int init_slave_0dB(struct hda_codec *codec, | 1821 | struct hda_codec *codec; |
| 1852 | void *data, struct snd_kcontrol *slave) | 1822 | int step; |
| 1823 | }; | ||
| 1824 | |||
| 1825 | /* initialize the slave volume with 0dB via snd_ctl_apply_vmaster_slaves() */ | ||
| 1826 | static int init_slave_0dB(struct snd_kcontrol *kctl, void *_arg) | ||
| 1853 | { | 1827 | { |
| 1854 | int offset = get_kctl_0dB_offset(codec, slave, data); | 1828 | struct slave_init_arg *arg = _arg; |
| 1855 | if (offset > 0) | 1829 | int _tlv[4]; |
| 1856 | put_kctl_with_value(slave, offset); | 1830 | const int *tlv = NULL; |
| 1831 | int step; | ||
| 1832 | int val; | ||
| 1833 | |||
| 1834 | if (kctl->vd[0].access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) { | ||
| 1835 | if (kctl->tlv.c != snd_hda_mixer_amp_tlv) { | ||
| 1836 | codec_err(arg->codec, | ||
| 1837 | "Unexpected TLV callback for slave %s:%d\n", | ||
| 1838 | kctl->id.name, kctl->id.index); | ||
| 1839 | return 0; /* ignore */ | ||
| 1840 | } | ||
| 1841 | get_ctl_amp_tlv(kctl, _tlv); | ||
| 1842 | tlv = _tlv; | ||
| 1843 | } else if (kctl->vd[0].access & SNDRV_CTL_ELEM_ACCESS_TLV_READ) | ||
| 1844 | tlv = kctl->tlv.p; | ||
| 1845 | |||
| 1846 | if (!tlv || tlv[0] != SNDRV_CTL_TLVT_DB_SCALE) | ||
| 1847 | return 0; | ||
| 1848 | |||
| 1849 | step = tlv[3]; | ||
| 1850 | step &= ~TLV_DB_SCALE_MUTE; | ||
| 1851 | if (!step) | ||
| 1852 | return 0; | ||
| 1853 | if (arg->step && arg->step != step) { | ||
| 1854 | codec_err(arg->codec, | ||
| 1855 | |||
