Commit 16453c9c authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'sound-4.16-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound

Pull sound fixes from Takashi Iwai:
 "The only core change is the fix for possible memory corruption by ALSA
  ctl API since 4.14 kernel due to a thinko.

  The rest are all device-specific: in addition to the usual suspects
  (HD-audio and USB-audio fixups), a few LPE HDMI audio fixes came in at
  this time"

* tag 'sound-4.16-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound:
  ALSA: x86: Fix potential crash at error path
  ALSA: x86: Fix missing spinlock and mutex initializations
  ALSA: control: Fix memory corruption risk in snd_ctl_elem_read
  ALSA: hda - Fix pincfg at resume on Lenovo T470 dock
  ALSA: usb-audio: Add a quirck for B&W PX headphones
  ALSA: hda: Add a power_save blacklist
  ALSA: x86: hdmi: Add single_port option for compatible behavior
parents 44896cd1 c77a6edb
...@@ -889,7 +889,7 @@ static int snd_ctl_elem_read(struct snd_card *card, ...@@ -889,7 +889,7 @@ static int snd_ctl_elem_read(struct snd_card *card,
index_offset = snd_ctl_get_ioff(kctl, &control->id); index_offset = snd_ctl_get_ioff(kctl, &control->id);
vd = &kctl->vd[index_offset]; vd = &kctl->vd[index_offset];
if (!(vd->access & SNDRV_CTL_ELEM_ACCESS_READ) && kctl->get == NULL) if (!(vd->access & SNDRV_CTL_ELEM_ACCESS_READ) || kctl->get == NULL)
return -EPERM; return -EPERM;
snd_ctl_build_ioff(&control->id, kctl, index_offset); snd_ctl_build_ioff(&control->id, kctl, index_offset);
......
...@@ -181,7 +181,7 @@ static const struct kernel_param_ops param_ops_xint = { ...@@ -181,7 +181,7 @@ static const struct kernel_param_ops param_ops_xint = {
}; };
#define param_check_xint param_check_int #define param_check_xint param_check_int
static int power_save = CONFIG_SND_HDA_POWER_SAVE_DEFAULT; static int power_save = -1;
module_param(power_save, xint, 0644); module_param(power_save, xint, 0644);
MODULE_PARM_DESC(power_save, "Automatic power-saving timeout " MODULE_PARM_DESC(power_save, "Automatic power-saving timeout "
"(in second, 0 = disable)."); "(in second, 0 = disable).");
...@@ -2186,6 +2186,24 @@ static int azx_probe(struct pci_dev *pci, ...@@ -2186,6 +2186,24 @@ static int azx_probe(struct pci_dev *pci,
return err; return err;
} }
#ifdef CONFIG_PM
/* On some boards setting power_save to a non 0 value leads to clicking /
* popping sounds when ever we enter/leave powersaving mode. Ideally we would
* figure out how to avoid these sounds, but that is not always feasible.
* So we keep a list of devices where we disable powersaving as its known
* to causes problems on these devices.
*/
static struct snd_pci_quirk power_save_blacklist[] = {
/* https://bugzilla.redhat.com/show_bug.cgi?id=1525104 */
SND_PCI_QUIRK(0x1849, 0x0c0c, "Asrock B85M-ITX", 0),
/* https://bugzilla.redhat.com/show_bug.cgi?id=1525104 */
SND_PCI_QUIRK(0x1043, 0x8733, "Asus Prime X370-Pro", 0),
/* https://bugzilla.kernel.org/show_bug.cgi?id=198611 */
SND_PCI_QUIRK(0x17aa, 0x2227, "Lenovo X1 Carbon 3rd Gen", 0),
{}
};
#endif /* CONFIG_PM */
/* number of codec slots for each chipset: 0 = default slots (i.e. 4) */ /* number of codec slots for each chipset: 0 = default slots (i.e. 4) */
static unsigned int azx_max_codecs[AZX_NUM_DRIVERS] = { static unsigned int azx_max_codecs[AZX_NUM_DRIVERS] = {
[AZX_DRIVER_NVIDIA] = 8, [AZX_DRIVER_NVIDIA] = 8,
...@@ -2198,6 +2216,7 @@ static int azx_probe_continue(struct azx *chip) ...@@ -2198,6 +2216,7 @@ static int azx_probe_continue(struct azx *chip)
struct hdac_bus *bus = azx_bus(chip); struct hdac_bus *bus = azx_bus(chip);
struct pci_dev *pci = chip->pci; struct pci_dev *pci = chip->pci;
int dev = chip->dev_index; int dev = chip->dev_index;
int val;
int err; int err;
hda->probe_continued = 1; hda->probe_continued = 1;
...@@ -2278,7 +2297,22 @@ static int azx_probe_continue(struct azx *chip) ...@@ -2278,7 +2297,22 @@ static int azx_probe_continue(struct azx *chip)
chip->running = 1; chip->running = 1;
azx_add_card_list(chip); azx_add_card_list(chip);
snd_hda_set_power_save(&chip->bus, power_save * 1000);
val = power_save;
#ifdef CONFIG_PM
if (val == -1) {
const struct snd_pci_quirk *q;
val = CONFIG_SND_HDA_POWER_SAVE_DEFAULT;
q = snd_pci_quirk_lookup(chip->pci, power_save_blacklist);
if (q && val) {
dev_info(chip->card->dev, "device %04x:%04x is on the power_save blacklist, forcing power_save to 0\n",
q->subvendor, q->subdevice);
val = 0;
}
}
#endif /* CONFIG_PM */
snd_hda_set_power_save(&chip->bus, val * 1000);
if (azx_has_pm_runtime(chip) || hda->use_vga_switcheroo) if (azx_has_pm_runtime(chip) || hda->use_vga_switcheroo)
pm_runtime_put_autosuspend(&pci->dev); pm_runtime_put_autosuspend(&pci->dev);
......
...@@ -4997,13 +4997,14 @@ static void alc_fixup_tpt470_dock(struct hda_codec *codec, ...@@ -4997,13 +4997,14 @@ static void alc_fixup_tpt470_dock(struct hda_codec *codec,
if (action == HDA_FIXUP_ACT_PRE_PROBE) { if (action == HDA_FIXUP_ACT_PRE_PROBE) {
spec->parse_flags = HDA_PINCFG_NO_HP_FIXUP; spec->parse_flags = HDA_PINCFG_NO_HP_FIXUP;
snd_hda_apply_pincfgs(codec, pincfgs);
} else if (action == HDA_FIXUP_ACT_INIT) {
/* Enable DOCK device */ /* Enable DOCK device */
snd_hda_codec_write(codec, 0x17, 0, snd_hda_codec_write(codec, 0x17, 0,
AC_VERB_SET_CONFIG_DEFAULT_BYTES_3, 0); AC_VERB_SET_CONFIG_DEFAULT_BYTES_3, 0);
/* Enable DOCK device */ /* Enable DOCK device */
snd_hda_codec_write(codec, 0x19, 0, snd_hda_codec_write(codec, 0x19, 0,
AC_VERB_SET_CONFIG_DEFAULT_BYTES_3, 0); AC_VERB_SET_CONFIG_DEFAULT_BYTES_3, 0);
snd_hda_apply_pincfgs(codec, pincfgs);
} }
} }
......
...@@ -3325,4 +3325,51 @@ AU0828_DEVICE(0x2040, 0x7270, "Hauppauge", "HVR-950Q"), ...@@ -3325,4 +3325,51 @@ AU0828_DEVICE(0x2040, 0x7270, "Hauppauge", "HVR-950Q"),
} }
}, },
{
/*
* Bower's & Wilkins PX headphones only support the 48 kHz sample rate
* even though it advertises more. The capture interface doesn't work
* even on windows.
*/
USB_DEVICE(0x19b5, 0x0021),
.driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) {
.ifnum = QUIRK_ANY_INTERFACE,
.type = QUIRK_COMPOSITE,
.data = (const struct snd_usb_audio_quirk[]) {
{
.ifnum = 0,
.type = QUIRK_AUDIO_STANDARD_MIXER,
},
/* Capture */
{
.ifnum = 1,
.type = QUIRK_IGNORE_INTERFACE,
},
/* Playback */
{
.ifnum = 2,
.type = QUIRK_AUDIO_FIXED_ENDPOINT,
.data = &(const struct audioformat) {
.formats = SNDRV_PCM_FMTBIT_S16_LE,
.channels = 2,
.iface = 2,
.altsetting = 1,
.altset_idx = 1,
.attributes = UAC_EP_CS_ATTR_FILL_MAX |
UAC_EP_CS_ATTR_SAMPLE_RATE,
.endpoint = 0x03,
.ep_attr = USB_ENDPOINT_XFER_ISOC,
.rates = SNDRV_PCM_RATE_48000,
.rate_min = 48000,
.rate_max = 48000,
.nr_rates = 1,
.rate_table = (unsigned int[]) {
48000
}
}
},
}
}
},
#undef USB_DEVICE_VENDOR_SPEC #undef USB_DEVICE_VENDOR_SPEC
...@@ -50,6 +50,7 @@ ...@@ -50,6 +50,7 @@
/*standard module options for ALSA. This module supports only one card*/ /*standard module options for ALSA. This module supports only one card*/
static int hdmi_card_index = SNDRV_DEFAULT_IDX1; static int hdmi_card_index = SNDRV_DEFAULT_IDX1;
static char *hdmi_card_id = SNDRV_DEFAULT_STR1; static char *hdmi_card_id = SNDRV_DEFAULT_STR1;
static bool single_port;
module_param_named(index, hdmi_card_index, int, 0444); module_param_named(index, hdmi_card_index, int, 0444);
MODULE_PARM_DESC(index, MODULE_PARM_DESC(index,
...@@ -57,6 +58,9 @@ MODULE_PARM_DESC(index, ...@@ -57,6 +58,9 @@ MODULE_PARM_DESC(index,
module_param_named(id, hdmi_card_id, charp, 0444); module_param_named(id, hdmi_card_id, charp, 0444);
MODULE_PARM_DESC(id, MODULE_PARM_DESC(id,
"ID string for INTEL Intel HDMI Audio controller."); "ID string for INTEL Intel HDMI Audio controller.");
module_param(single_port, bool, 0444);
MODULE_PARM_DESC(single_port,
"Single-port mode (for compatibility)");
/* /*
* ELD SA bits in the CEA Speaker Allocation data block * ELD SA bits in the CEA Speaker Allocation data block
...@@ -1579,7 +1583,11 @@ static irqreturn_t display_pipe_interrupt_handler(int irq, void *dev_id) ...@@ -1579,7 +1583,11 @@ static irqreturn_t display_pipe_interrupt_handler(int irq, void *dev_id)
static void notify_audio_lpe(struct platform_device *pdev, int port) static void notify_audio_lpe(struct platform_device *pdev, int port)
{ {
struct snd_intelhad_card *card_ctx = platform_get_drvdata(pdev); struct snd_intelhad_card *card_ctx = platform_get_drvdata(pdev);
struct snd_intelhad *ctx = &card_ctx->pcm_ctx[port]; struct snd_intelhad *ctx;
ctx = &card_ctx->pcm_ctx[single_port ? 0 : port];
if (single_port)
ctx->port = port;
schedule_work(&ctx->hdmi_audio_wq); schedule_work(&ctx->hdmi_audio_wq);
} }
...@@ -1743,6 +1751,7 @@ static int hdmi_lpe_audio_probe(struct platform_device *pdev) ...@@ -1743,6 +1751,7 @@ static int hdmi_lpe_audio_probe(struct platform_device *pdev)
{ {
struct snd_card *card; struct snd_card *card;
struct snd_intelhad_card *card_ctx; struct snd_intelhad_card *card_ctx;
struct snd_intelhad *ctx;
struct snd_pcm *pcm; struct snd_pcm *pcm;
struct intel_hdmi_lpe_audio_pdata *pdata; struct intel_hdmi_lpe_audio_pdata *pdata;
int irq; int irq;
...@@ -1787,6 +1796,21 @@ static int hdmi_lpe_audio_probe(struct platform_device *pdev) ...@@ -1787,6 +1796,21 @@ static int hdmi_lpe_audio_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, card_ctx); platform_set_drvdata(pdev, card_ctx);
card_ctx->num_pipes = pdata->num_pipes;
card_ctx->num_ports = single_port ? 1 : pdata->num_ports;
for_each_port(card_ctx, port) {
ctx = &card_ctx->pcm_ctx[port];
ctx->card_ctx = card_ctx;
ctx->dev = card_ctx->dev;
ctx->port = single_port ? -1 : port;
ctx->pipe = -1;
spin_lock_init(&ctx->had_spinlock);
mutex_init(&ctx->mutex);
INIT_WORK(&ctx->hdmi_audio_wq, had_audio_wq);
}
dev_dbg(&pdev->dev, "%s: mmio_start = 0x%x, mmio_end = 0x%x\n", dev_dbg(&pdev->dev, "%s: mmio_start = 0x%x, mmio_end = 0x%x\n",
__func__, (unsigned int)res_mmio->start, __func__, (unsigned int)res_mmio->start,
(unsigned int)res_mmio->end); (unsigned int)res_mmio->end);
...@@ -1816,19 +1840,12 @@ static int hdmi_lpe_audio_probe(struct platform_device *pdev) ...@@ -1816,19 +1840,12 @@ static int hdmi_lpe_audio_probe(struct platform_device *pdev)
init_channel_allocations(); init_channel_allocations();
card_ctx->num_pipes = pdata->num_pipes; card_ctx->num_pipes = pdata->num_pipes;
card_ctx->num_ports = pdata->num_ports; card_ctx->num_ports = single_port ? 1 : pdata->num_ports;
for_each_port(card_ctx, port) { for_each_port(card_ctx, port) {
struct snd_intelhad *ctx = &card_ctx->pcm_ctx[port];
int i; int i;
ctx->card_ctx = card_ctx; ctx = &card_ctx->pcm_ctx[port];
ctx->dev = card_ctx->dev;
ctx->port = port;
ctx->pipe = -1;
INIT_WORK(&ctx->hdmi_audio_wq, had_audio_wq);
ret = snd_pcm_new(card, INTEL_HAD, port, MAX_PB_STREAMS, ret = snd_pcm_new(card, INTEL_HAD, port, MAX_PB_STREAMS,
MAX_CAP_STREAMS, &pcm); MAX_CAP_STREAMS, &pcm);
if (ret) if (ret)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment