Merge tag 'sound-3.9' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound
Pull sound fixes from Takashi Iwai:
"A collection of small fixes, as expected for the middle rc:
- A couple of fixes for potential NULL dereferences and out-of-range
array accesses revealed by static code parsers
- A fix for the wrong error handling detected by trinity
- A regression fix for missing audio on some MacBooks
- CA0132 DSP loader fixes
- Fix for EAPD control of IDT codecs on machines w/o speaker
- Fix a regression in the HD-audio widget list parser code
- Workaround for the NuForce UDH-100 USB audio"
* tag 'sound-3.9' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound:
ALSA: hda - Fix missing EAPD/GPIO setup for Cirrus codecs
sound: sequencer: cap array index in seq_chn_common_event()
ALSA: hda/ca0132 - Remove extra setting of dsp_state.
ALSA: hda/ca0132 - Check download state of DSP.
ALSA: hda/ca0132 - Check if dspload_image succeeded.
ALSA: hda - Disable IDT eapd_switch if there are no internal speakers
ALSA: hda - Fix snd_hda_get_num_raw_conns() to return a correct value
ALSA: usb-audio: add a workaround for the NuForce UDH-100
ALSA: asihpi - fix potential NULL pointer dereference
ALSA: seq: Fix missing error handling in snd_seq_timer_open()
diff --git a/sound/core/seq/seq_timer.c b/sound/core/seq/seq_timer.c
index 160b1bd..24d44b2 100644
--- a/sound/core/seq/seq_timer.c
+++ b/sound/core/seq/seq_timer.c
@@ -290,10 +290,10 @@
tid.device = SNDRV_TIMER_GLOBAL_SYSTEM;
err = snd_timer_open(&t, str, &tid, q->queue);
}
- if (err < 0) {
- snd_printk(KERN_ERR "seq fatal error: cannot create timer (%i)\n", err);
- return err;
- }
+ }
+ if (err < 0) {
+ snd_printk(KERN_ERR "seq fatal error: cannot create timer (%i)\n", err);
+ return err;
}
t->callback = snd_seq_timer_interrupt;
t->callback_data = q;
diff --git a/sound/oss/sequencer.c b/sound/oss/sequencer.c
index 30bcfe4..4ff60a6 100644
--- a/sound/oss/sequencer.c
+++ b/sound/oss/sequencer.c
@@ -545,6 +545,9 @@
case MIDI_PGM_CHANGE:
if (seq_mode == SEQ_2)
{
+ if (chn > 15)
+ break;
+
synth_devs[dev]->chn_info[chn].pgm_num = p1;
if ((int) dev >= num_synths)
synth_devs[dev]->set_instr(dev, chn, p1);
@@ -596,6 +599,9 @@
case MIDI_PITCH_BEND:
if (seq_mode == SEQ_2)
{
+ if (chn > 15)
+ break;
+
synth_devs[dev]->chn_info[chn].bender_value = w14;
if ((int) dev < num_synths)
diff --git a/sound/pci/asihpi/asihpi.c b/sound/pci/asihpi/asihpi.c
index 3536b07..0aabfed 100644
--- a/sound/pci/asihpi/asihpi.c
+++ b/sound/pci/asihpi/asihpi.c
@@ -2549,7 +2549,7 @@
static int snd_card_asihpi_mixer_new(struct snd_card_asihpi *asihpi)
{
- struct snd_card *card = asihpi->card;
+ struct snd_card *card;
unsigned int idx = 0;
unsigned int subindex = 0;
int err;
@@ -2557,6 +2557,7 @@
if (snd_BUG_ON(!asihpi))
return -EINVAL;
+ card = asihpi->card;
strcpy(card->mixername, "Asihpi Mixer");
err =
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index 97c68dd..a9ebcf9 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -494,7 +494,7 @@
int snd_hda_get_num_raw_conns(struct hda_codec *codec, hda_nid_t nid)
{
- return get_num_conns(codec, nid) & AC_CLIST_LENGTH;
+ return snd_hda_get_raw_connections(codec, nid, NULL, 0);
}
/**
@@ -517,9 +517,6 @@
hda_nid_t prev_nid;
int null_count = 0;
- if (snd_BUG_ON(!conn_list || max_conns <= 0))
- return -EINVAL;
-
parm = get_num_conns(codec, nid);
if (!parm)
return 0;
@@ -545,7 +542,8 @@
AC_VERB_GET_CONNECT_LIST, 0);
if (parm == -1 && codec->bus->rirb_error)
return -EIO;
- conn_list[0] = parm & mask;
+ if (conn_list)
+ conn_list[0] = parm & mask;
return 1;
}
@@ -580,14 +578,20 @@
continue;
}
for (n = prev_nid + 1; n <= val; n++) {
- if (conns >= max_conns)
- return -ENOSPC;
- conn_list[conns++] = n;
+ if (conn_list) {
+ if (conns >= max_conns)
+ return -ENOSPC;
+ conn_list[conns] = n;
+ }
+ conns++;
}
} else {
- if (conns >= max_conns)
- return -ENOSPC;
- conn_list[conns++] = val;
+ if (conn_list) {
+ if (conns >= max_conns)
+ return -ENOSPC;
+ conn_list[conns] = val;
+ }
+ conns++;
}
prev_nid = val;
}
diff --git a/sound/pci/hda/patch_ca0132.c b/sound/pci/hda/patch_ca0132.c
index eefc456..0792b57 100644
--- a/sound/pci/hda/patch_ca0132.c
+++ b/sound/pci/hda/patch_ca0132.c
@@ -3239,7 +3239,7 @@
struct ca0132_spec *spec = codec->spec;
unsigned int tmp;
- if (!dspload_is_loaded(codec))
+ if (spec->dsp_state != DSP_DOWNLOADED)
return 0;
/* if CrystalVoice if off, vipsource should be 0 */
@@ -4267,11 +4267,12 @@
*/
static void ca0132_setup_defaults(struct hda_codec *codec)
{
+ struct ca0132_spec *spec = codec->spec;
unsigned int tmp;
int num_fx;
int idx, i;
- if (!dspload_is_loaded(codec))
+ if (spec->dsp_state != DSP_DOWNLOADED)
return;
/* out, in effects + voicefx */
@@ -4351,12 +4352,16 @@
return false;
dsp_os_image = (struct dsp_image_seg *)(fw_entry->data);
- dspload_image(codec, dsp_os_image, 0, 0, true, 0);
+ if (dspload_image(codec, dsp_os_image, 0, 0, true, 0)) {
+ pr_err("ca0132 dspload_image failed.\n");
+ goto exit_download;
+ }
+
dsp_loaded = dspload_wait_loaded(codec);
+exit_download:
release_firmware(fw_entry);
-
return dsp_loaded;
}
@@ -4367,16 +4372,13 @@
#ifndef CONFIG_SND_HDA_CODEC_CA0132_DSP
return; /* NOP */
#endif
- spec->dsp_state = DSP_DOWNLOAD_INIT;
- if (spec->dsp_state == DSP_DOWNLOAD_INIT) {
- chipio_enable_clocks(codec);
- spec->dsp_state = DSP_DOWNLOADING;
- if (!ca0132_download_dsp_images(codec))
- spec->dsp_state = DSP_DOWNLOAD_FAILED;
- else
- spec->dsp_state = DSP_DOWNLOADED;
- }
+ chipio_enable_clocks(codec);
+ spec->dsp_state = DSP_DOWNLOADING;
+ if (!ca0132_download_dsp_images(codec))
+ spec->dsp_state = DSP_DOWNLOAD_FAILED;
+ else
+ spec->dsp_state = DSP_DOWNLOADED;
if (spec->dsp_state == DSP_DOWNLOADED)
ca0132_set_dsp_msr(codec, true);
diff --git a/sound/pci/hda/patch_cirrus.c b/sound/pci/hda/patch_cirrus.c
index 72ebb8a..60d08f6 100644
--- a/sound/pci/hda/patch_cirrus.c
+++ b/sound/pci/hda/patch_cirrus.c
@@ -506,6 +506,8 @@
if (!spec)
return -ENOMEM;
+ spec->gen.automute_hook = cs_automute;
+
snd_hda_pick_fixup(codec, cs420x_models, cs420x_fixup_tbl,
cs420x_fixups);
snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
@@ -893,6 +895,8 @@
if (!spec)
return -ENOMEM;
+ spec->gen.automute_hook = cs_automute;
+
snd_hda_pick_fixup(codec, cs421x_models, cs421x_fixup_tbl,
cs421x_fixups);
snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index 83d5335..dafe04a 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -815,6 +815,29 @@
return 0;
}
+/* check whether a built-in speaker is included in parsed pins */
+static bool has_builtin_speaker(struct hda_codec *codec)
+{
+ struct sigmatel_spec *spec = codec->spec;
+ hda_nid_t *nid_pin;
+ int nids, i;
+
+ if (spec->gen.autocfg.line_out_type == AUTO_PIN_SPEAKER_OUT) {
+ nid_pin = spec->gen.autocfg.line_out_pins;
+ nids = spec->gen.autocfg.line_outs;
+ } else {
+ nid_pin = spec->gen.autocfg.speaker_pins;
+ nids = spec->gen.autocfg.speaker_outs;
+ }
+
+ for (i = 0; i < nids; i++) {
+ unsigned int def_conf = snd_hda_codec_get_pincfg(codec, nid_pin[i]);
+ if (snd_hda_get_input_pin_attr(def_conf) == INPUT_PIN_ATTR_INT)
+ return true;
+ }
+ return false;
+}
+
/*
* PC beep controls
*/
@@ -3890,6 +3913,12 @@
return err;
}
+ /* Don't GPIO-mute speakers if there are no internal speakers, because
+ * the GPIO might be necessary for Headphone
+ */
+ if (spec->eapd_switch && !has_builtin_speaker(codec))
+ spec->eapd_switch = 0;
+
codec->proc_widget_hook = stac92hd7x_proc_hook;
snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
diff --git a/sound/usb/card.c b/sound/usb/card.c
index 803953a..2da8ad7 100644
--- a/sound/usb/card.c
+++ b/sound/usb/card.c
@@ -244,6 +244,21 @@
usb_ifnum_to_if(dev, ctrlif)->intf_assoc;
if (!assoc) {
+ /*
+ * Firmware writers cannot count to three. So to find
+ * the IAD on the NuForce UDH-100, also check the next
+ * interface.
+ */
+ struct usb_interface *iface =
+ usb_ifnum_to_if(dev, ctrlif + 1);
+ if (iface &&
+ iface->intf_assoc &&
+ iface->intf_assoc->bFunctionClass == USB_CLASS_AUDIO &&
+ iface->intf_assoc->bFunctionProtocol == UAC_VERSION_2)
+ assoc = iface->intf_assoc;
+ }
+
+ if (!assoc) {
snd_printk(KERN_ERR "Audio class v2 interfaces need an interface association\n");
return -EINVAL;
}