diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-10-19 16:15:17 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-10-19 16:15:17 -0400 |
commit | 962556b57c7dcc4510c2bd6cc332fc9c6bc87dc9 (patch) | |
tree | c4a16bd73389bb4d1b22270e57206d44d7e81bc2 | |
parent | 73d3393ada4f70fa3df5639c8d438f2f034c0ecb (diff) | |
parent | a91d66129fb9bcead12af3ed2008d6ddbf179509 (diff) |
Merge tag 'sound-4.14-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound
Pull sound fixes from Takashi Iwai:
"We've got slightly more fixes than wished, but heading to a good
shape. Most of changes are about HD-audio fixes, one for a buggy code
that went into 4.13, and another for avoiding a crash due to buggy
BIOS.
Apart from HD-audio, a sequencer core change that is only for UP
config (which must be pretty rare nowadays), and a USB-audio quirk as
usual"
* tag 'sound-4.14-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound:
ALSA: hda - Fix incorrect TLV callback check introduced during set_fs() removal
ALSA: hda: Remove superfluous '-' added by printk conversion
ALSA: hda: Abort capability probe at invalid register read
ALSA: seq: Enable 'use' locking in all configurations
ALSA: usb-audio: Add native DSD support for Pro-Ject Pre Box S2 Digital
-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 | "Mismatching dB step for vmaster slave (%d!=%d)\n", | ||
1856 | arg->step, step); | ||
1857 | return 0; | ||
1858 | } | ||
1859 | |||
1860 | arg->step = step; | ||
1861 | val = -tlv[2] / step; | ||
1862 | if (val > 0) { | ||
1863 | put_kctl_with_value(kctl, val); | ||
1864 | return val; | ||
1865 | } | ||
1866 | |||
1857 | return 0; | 1867 | return 0; |
1858 | } | 1868 | } |
1859 | 1869 | ||
1860 | /* unmute the slave */ | 1870 | /* unmute the slave via snd_ctl_apply_vmaster_slaves() */ |
1861 | static int init_slave_unmute(struct hda_codec *codec, | 1871 | static int init_slave_unmute(struct snd_kcontrol *slave, void *_arg) |
1862 | void *data, struct snd_kcontrol *slave) | ||
1863 | { | 1872 | { |
1864 | return put_kctl_with_value(slave, 1); | 1873 | return put_kctl_with_value(slave, 1); |
1865 | } | 1874 | } |
@@ -1919,9 +1928,13 @@ int __snd_hda_add_vmaster(struct hda_codec *codec, char *name, | |||
1919 | /* init with master mute & zero volume */ | 1928 | /* init with master mute & zero volume */ |
1920 | put_kctl_with_value(kctl, 0); | 1929 | put_kctl_with_value(kctl, 0); |
1921 | if (init_slave_vol) { | 1930 | if (init_slave_vol) { |
1922 | int step = 0; | 1931 | struct slave_init_arg arg = { |
1923 | map_slaves(codec, slaves, suffix, | 1932 | .codec = codec, |
1924 | tlv ? init_slave_0dB : init_slave_unmute, &step); | 1933 | .step = 0, |
1934 | }; | ||
1935 | snd_ctl_apply_vmaster_slaves(kctl, | ||
1936 | tlv ? init_slave_0dB : init_slave_unmute, | ||
1937 | &arg); | ||
1925 | } | 1938 | } |
1926 | 1939 | ||
1927 | if (ctl_ret) | 1940 | if (ctl_ret) |
diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c index 9ddaae3784f5..4f5f18f22974 100644 --- a/sound/usb/quirks.c +++ b/sound/usb/quirks.c | |||
@@ -1354,6 +1354,7 @@ u64 snd_usb_interface_dsd_format_quirks(struct snd_usb_audio *chip, | |||
1354 | case USB_ID(0x20b1, 0x2008): /* Matrix Audio X-Sabre */ | 1354 | case USB_ID(0x20b1, 0x2008): /* Matrix Audio X-Sabre */ |
1355 | case USB_ID(0x20b1, 0x300a): /* Matrix Audio Mini-i Pro */ | 1355 | case USB_ID(0x20b1, 0x300a): /* Matrix Audio Mini-i Pro */ |
1356 | case USB_ID(0x22d9, 0x0416): /* OPPO HA-1 */ | 1356 | case USB_ID(0x22d9, 0x0416): /* OPPO HA-1 */ |
1357 | case USB_ID(0x2772, 0x0230): /* Pro-Ject Pre Box S2 Digital */ | ||
1357 | if (fp->altsetting == 2) | 1358 | if (fp->altsetting == 2) |
1358 | return SNDRV_PCM_FMTBIT_DSD_U32_BE; | 1359 | return SNDRV_PCM_FMTBIT_DSD_U32_BE; |
1359 | break; | 1360 | break; |