Sound fixes for 3.9-rc3

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
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v2.0.19 (GNU/Linux)
 
 iQIcBAABAgAGBQJRQyORAAoJEGwxgFQ9KSmkbvkP/0WEasiViZWqKOFfDTJ4TMEt
 OI53hJKE4mr+/mitVxlQdhZ2r6q+aWRxFxq0i81uL3oB6FHHzxt+7O1P+hAC9p9Z
 M4Q0/mgPoosTyWGKQUmnJvhe13qxft4LhGs8t9A1twsb3AfIEbZsTtnFq+blQJQO
 RPWCSDIVdk1vldFHFhne3IM7SweCjqoPbfpY3dwFPKA1DeA0F6OUcsriWbNJLFys
 mv4U0XZUlkDK4MAMU6r6ksT7KwqOq2bUkJYhXGPq4kAV88oEpPKaz0BUh2nKA872
 N2EjQ7y7vkeW1zwX9DvtXCCNZt+3FeA2xHrGLPmMR8Uv/W/dwyEp08LvaBJyCcmt
 iuWSg+Y4ayiXbsm5YoIbx5OnNZExZAxchDpFxD+IMY9Oa1V3IUs8Q5ppO/nuEqjI
 O46ERVltTO4LHg+5/oVz78ASK1qp+MFymxxnQtXH7eZgbjYI8nQtTCnMi/tH+gBq
 KUX3ejn/gD4L0CCRZ9u4ynALbFL7MNOV9HsZi1O8UeZwGYMwgbNmeQCqlLgloTaI
 cagaNELLU3hcJQZnS0csz2ak9wlJbl2ud9O4l8u1UUBStiTtTDaf0eyh81GcQvYp
 A4Fv/RzI3iQiWpr7smVPOOXggRAMAojQKcMLM4gliHj2vuu1B0zIPOF4iJWjcIIV
 hxPD29F6FoB/TccjNE77
 =Zc4C
 -----END PGP SIGNATURE-----

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()
This commit is contained in:
Linus Torvalds 2013-03-15 17:35:49 -07:00
commit 5cd8846c3b
8 changed files with 90 additions and 29 deletions

View File

@ -290,10 +290,10 @@ int snd_seq_timer_open(struct snd_seq_queue *q)
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;

View File

@ -545,6 +545,9 @@ static void seq_chn_common_event(unsigned char *event_rec)
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 @@ static void seq_chn_common_event(unsigned char *event_rec)
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)

View File

@ -2549,7 +2549,7 @@ static int snd_asihpi_sampleclock_add(struct snd_card_asihpi *asihpi,
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 @@ static int snd_card_asihpi_mixer_new(struct snd_card_asihpi *asihpi)
if (snd_BUG_ON(!asihpi))
return -EINVAL;
card = asihpi->card;
strcpy(card->mixername, "Asihpi Mixer");
err =

View File

@ -494,7 +494,7 @@ static unsigned int get_num_conns(struct hda_codec *codec, hda_nid_t nid)
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 @@ int snd_hda_get_raw_connections(struct hda_codec *codec, hda_nid_t nid,
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 @@ int snd_hda_get_raw_connections(struct hda_codec *codec, hda_nid_t nid,
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 @@ int snd_hda_get_raw_connections(struct hda_codec *codec, hda_nid_t nid,
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;
}

View File

@ -3239,7 +3239,7 @@ static int ca0132_set_vipsource(struct hda_codec *codec, int val)
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_refresh_widget_caps(struct hda_codec *codec)
*/
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 @@ static bool ca0132_download_dsp_images(struct hda_codec *codec)
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 @@ static void ca0132_download_dsp(struct hda_codec *codec)
#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);

View File

@ -506,6 +506,8 @@ static int patch_cs420x(struct hda_codec *codec)
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 @@ static int patch_cs4210(struct hda_codec *codec)
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);

View File

@ -815,6 +815,29 @@ static int find_mute_led_cfg(struct hda_codec *codec, int default_polarity)
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 @@ static int patch_stac92hd73xx(struct hda_codec *codec)
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);

View File

@ -243,6 +243,21 @@ static int snd_usb_create_streams(struct snd_usb_audio *chip, int ctrlif)
struct usb_interface_assoc_descriptor *assoc =
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;