Commit bbc54a00 authored by Linus Torvalds's avatar Linus Torvalds

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

Pull sound fixes from Takashi Iwai:
 "This is a round of HD-audio fixes: there are a long-standing
  regression fix and a few more device/codec-specific quirks.

  In addition, a couple of FireWire regression fixes, a USB-audio quirk
  for Roland UA-22 and a sanity check in API for user-defined control
  elements"

* tag 'sound-4.0-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound:
  ALSA: hda - Don't access stereo amps for mono channel widgets
  ALSA: hda - Add workaround for MacBook Air 5,2 built-in mic
  ALSA: hda - Set single_adc_amp flag for CS420x codecs
  ALSA: snd-usb: add quirks for Roland UA-22
  ALSA: control: Add sanity checks for user ctl id name string
  ALSA: hda - Fix built-in mic on Compaq Presario CQ60
  ALSA: firewire-lib: leave unit reference counting completely
  Revert "ALSA: dice: fix wrong offsets for Dice interface"
  ALSA: hda - Fix regression of HD-audio controller fallback modes
parents 3d52c5bd ef403edb
...@@ -1170,6 +1170,10 @@ static int snd_ctl_elem_add(struct snd_ctl_file *file, ...@@ -1170,6 +1170,10 @@ static int snd_ctl_elem_add(struct snd_ctl_file *file,
if (info->count < 1) if (info->count < 1)
return -EINVAL; return -EINVAL;
if (!*info->id.name)
return -EINVAL;
if (strnlen(info->id.name, sizeof(info->id.name)) >= sizeof(info->id.name))
return -EINVAL;
access = info->access == 0 ? SNDRV_CTL_ELEM_ACCESS_READWRITE : access = info->access == 0 ? SNDRV_CTL_ELEM_ACCESS_READWRITE :
(info->access & (SNDRV_CTL_ELEM_ACCESS_READWRITE| (info->access & (SNDRV_CTL_ELEM_ACCESS_READWRITE|
SNDRV_CTL_ELEM_ACCESS_INACTIVE| SNDRV_CTL_ELEM_ACCESS_INACTIVE|
......
...@@ -298,24 +298,24 @@ ...@@ -298,24 +298,24 @@
*/ */
#define RX_ISOCHRONOUS 0x008 #define RX_ISOCHRONOUS 0x008
/*
* Index of first quadlet to be interpreted; read/write. If > 0, that many
* quadlets at the beginning of each data block will be ignored, and all the
* audio and MIDI quadlets will follow.
*/
#define RX_SEQ_START 0x00c
/* /*
* The number of audio channels; read-only. There will be one quadlet per * The number of audio channels; read-only. There will be one quadlet per
* channel. * channel.
*/ */
#define RX_NUMBER_AUDIO 0x00c #define RX_NUMBER_AUDIO 0x010
/* /*
* The number of MIDI ports, 0-8; read-only. If > 0, there will be one * The number of MIDI ports, 0-8; read-only. If > 0, there will be one
* additional quadlet in each data block, following the audio quadlets. * additional quadlet in each data block, following the audio quadlets.
*/ */
#define RX_NUMBER_MIDI 0x010 #define RX_NUMBER_MIDI 0x014
/*
* Index of first quadlet to be interpreted; read/write. If > 0, that many
* quadlets at the beginning of each data block will be ignored, and all the
* audio and MIDI quadlets will follow.
*/
#define RX_SEQ_START 0x014
/* /*
* Names of all audio channels; read-only. Quadlets are byte-swapped. Names * Names of all audio channels; read-only. Quadlets are byte-swapped. Names
......
...@@ -99,9 +99,9 @@ static void dice_proc_read(struct snd_info_entry *entry, ...@@ -99,9 +99,9 @@ static void dice_proc_read(struct snd_info_entry *entry,
} tx; } tx;
struct { struct {
u32 iso; u32 iso;
u32 seq_start;
u32 number_audio; u32 number_audio;
u32 number_midi; u32 number_midi;
u32 seq_start;
char names[RX_NAMES_SIZE]; char names[RX_NAMES_SIZE];
u32 ac3_caps; u32 ac3_caps;
u32 ac3_enable; u32 ac3_enable;
...@@ -204,10 +204,10 @@ static void dice_proc_read(struct snd_info_entry *entry, ...@@ -204,10 +204,10 @@ static void dice_proc_read(struct snd_info_entry *entry,
break; break;
snd_iprintf(buffer, "rx %u:\n", stream); snd_iprintf(buffer, "rx %u:\n", stream);
snd_iprintf(buffer, " iso channel: %d\n", (int)buf.rx.iso); snd_iprintf(buffer, " iso channel: %d\n", (int)buf.rx.iso);
snd_iprintf(buffer, " sequence start: %u\n", buf.rx.seq_start);
snd_iprintf(buffer, " audio channels: %u\n", snd_iprintf(buffer, " audio channels: %u\n",
buf.rx.number_audio); buf.rx.number_audio);
snd_iprintf(buffer, " midi ports: %u\n", buf.rx.number_midi); snd_iprintf(buffer, " midi ports: %u\n", buf.rx.number_midi);
snd_iprintf(buffer, " sequence start: %u\n", buf.rx.seq_start);
if (quadlets >= 68) { if (quadlets >= 68) {
dice_proc_fixup_string(buf.rx.names, RX_NAMES_SIZE); dice_proc_fixup_string(buf.rx.names, RX_NAMES_SIZE);
snd_iprintf(buffer, " names: %s\n", buf.rx.names); snd_iprintf(buffer, " names: %s\n", buf.rx.names);
......
...@@ -26,7 +26,7 @@ ...@@ -26,7 +26,7 @@
int fw_iso_resources_init(struct fw_iso_resources *r, struct fw_unit *unit) int fw_iso_resources_init(struct fw_iso_resources *r, struct fw_unit *unit)
{ {
r->channels_mask = ~0uLL; r->channels_mask = ~0uLL;
r->unit = fw_unit_get(unit); r->unit = unit;
mutex_init(&r->mutex); mutex_init(&r->mutex);
r->allocated = false; r->allocated = false;
...@@ -42,7 +42,6 @@ void fw_iso_resources_destroy(struct fw_iso_resources *r) ...@@ -42,7 +42,6 @@ void fw_iso_resources_destroy(struct fw_iso_resources *r)
{ {
WARN_ON(r->allocated); WARN_ON(r->allocated);
mutex_destroy(&r->mutex); mutex_destroy(&r->mutex);
fw_unit_put(r->unit);
} }
EXPORT_SYMBOL(fw_iso_resources_destroy); EXPORT_SYMBOL(fw_iso_resources_destroy);
......
...@@ -1164,7 +1164,7 @@ static unsigned int azx_rirb_get_response(struct hda_bus *bus, ...@@ -1164,7 +1164,7 @@ static unsigned int azx_rirb_get_response(struct hda_bus *bus,
} }
} }
if (!bus->no_response_fallback) if (bus->no_response_fallback)
return -1; return -1;
if (!chip->polling_mode && chip->poll_count < 2) { if (!chip->polling_mode && chip->poll_count < 2) {
......
...@@ -692,7 +692,23 @@ static void init_amp(struct hda_codec *codec, hda_nid_t nid, int dir, int idx) ...@@ -692,7 +692,23 @@ static void init_amp(struct hda_codec *codec, hda_nid_t nid, int dir, int idx)
{ {
unsigned int caps = query_amp_caps(codec, nid, dir); unsigned int caps = query_amp_caps(codec, nid, dir);
int val = get_amp_val_to_activate(codec, nid, dir, caps, false); int val = get_amp_val_to_activate(codec, nid, dir, caps, false);
if (get_wcaps(codec, nid) & AC_WCAP_STEREO)
snd_hda_codec_amp_init_stereo(codec, nid, dir, idx, 0xff, val); snd_hda_codec_amp_init_stereo(codec, nid, dir, idx, 0xff, val);
else
snd_hda_codec_amp_init(codec, nid, 0, dir, idx, 0xff, val);
}
/* update the amp, doing in stereo or mono depending on NID */
static int update_amp(struct hda_codec *codec, hda_nid_t nid, int dir, int idx,
unsigned int mask, unsigned int val)
{
if (get_wcaps(codec, nid) & AC_WCAP_STEREO)
return snd_hda_codec_amp_stereo(codec, nid, dir, idx,
mask, val);
else
return snd_hda_codec_amp_update(codec, nid, 0, dir, idx,
mask, val);
} }
/* calculate amp value mask we can modify; /* calculate amp value mask we can modify;
...@@ -732,7 +748,7 @@ static void activate_amp(struct hda_codec *codec, hda_nid_t nid, int dir, ...@@ -732,7 +748,7 @@ static void activate_amp(struct hda_codec *codec, hda_nid_t nid, int dir,
return; return;
val &= mask; val &= mask;
snd_hda_codec_amp_stereo(codec, nid, dir, idx, mask, val); update_amp(codec, nid, dir, idx, mask, val);
} }
static void activate_amp_out(struct hda_codec *codec, struct nid_path *path, static void activate_amp_out(struct hda_codec *codec, struct nid_path *path,
...@@ -4424,12 +4440,10 @@ static void mute_all_mixer_nid(struct hda_codec *codec, hda_nid_t mix) ...@@ -4424,12 +4440,10 @@ static void mute_all_mixer_nid(struct hda_codec *codec, hda_nid_t mix)
has_amp = nid_has_mute(codec, mix, HDA_INPUT); has_amp = nid_has_mute(codec, mix, HDA_INPUT);
for (i = 0; i < nums; i++) { for (i = 0; i < nums; i++) {
if (has_amp) if (has_amp)
snd_hda_codec_amp_stereo(codec, mix, update_amp(codec, mix, HDA_INPUT, i,
HDA_INPUT, i,
0xff, HDA_AMP_MUTE); 0xff, HDA_AMP_MUTE);
else if (nid_has_volume(codec, conn[i], HDA_OUTPUT)) else if (nid_has_volume(codec, conn[i], HDA_OUTPUT))
snd_hda_codec_amp_stereo(codec, conn[i], update_amp(codec, conn[i], HDA_OUTPUT, 0,
HDA_OUTPUT, 0,
0xff, HDA_AMP_MUTE); 0xff, HDA_AMP_MUTE);
} }
} }
......
...@@ -393,6 +393,7 @@ static const struct snd_pci_quirk cs420x_fixup_tbl[] = { ...@@ -393,6 +393,7 @@ static const struct snd_pci_quirk cs420x_fixup_tbl[] = {
SND_PCI_QUIRK(0x106b, 0x1c00, "MacBookPro 8,1", CS420X_MBP81), SND_PCI_QUIRK(0x106b, 0x1c00, "MacBookPro 8,1", CS420X_MBP81),
SND_PCI_QUIRK(0x106b, 0x2000, "iMac 12,2", CS420X_IMAC27_122), SND_PCI_QUIRK(0x106b, 0x2000, "iMac 12,2", CS420X_IMAC27_122),
SND_PCI_QUIRK(0x106b, 0x2800, "MacBookPro 10,1", CS420X_MBP101), SND_PCI_QUIRK(0x106b, 0x2800, "MacBookPro 10,1", CS420X_MBP101),
SND_PCI_QUIRK(0x106b, 0x5600, "MacBookAir 5,2", CS420X_MBP81),
SND_PCI_QUIRK(0x106b, 0x5b00, "MacBookAir 4,2", CS420X_MBA42), SND_PCI_QUIRK(0x106b, 0x5b00, "MacBookAir 4,2", CS420X_MBA42),
SND_PCI_QUIRK_VENDOR(0x106b, "Apple", CS420X_APPLE), SND_PCI_QUIRK_VENDOR(0x106b, "Apple", CS420X_APPLE),
{} /* terminator */ {} /* terminator */
...@@ -584,6 +585,7 @@ static int patch_cs420x(struct hda_codec *codec) ...@@ -584,6 +585,7 @@ static int patch_cs420x(struct hda_codec *codec)
return -ENOMEM; return -ENOMEM;
spec->gen.automute_hook = cs_automute; spec->gen.automute_hook = cs_automute;
codec->single_adc_amp = 1;
snd_hda_pick_fixup(codec, cs420x_models, cs420x_fixup_tbl, snd_hda_pick_fixup(codec, cs420x_models, cs420x_fixup_tbl,
cs420x_fixups); cs420x_fixups);
......
...@@ -223,6 +223,7 @@ enum { ...@@ -223,6 +223,7 @@ enum {
CXT_PINCFG_LENOVO_TP410, CXT_PINCFG_LENOVO_TP410,
CXT_PINCFG_LEMOTE_A1004, CXT_PINCFG_LEMOTE_A1004,
CXT_PINCFG_LEMOTE_A1205, CXT_PINCFG_LEMOTE_A1205,
CXT_PINCFG_COMPAQ_CQ60,
CXT_FIXUP_STEREO_DMIC, CXT_FIXUP_STEREO_DMIC,
CXT_FIXUP_INC_MIC_BOOST, CXT_FIXUP_INC_MIC_BOOST,
CXT_FIXUP_HEADPHONE_MIC_PIN, CXT_FIXUP_HEADPHONE_MIC_PIN,
...@@ -660,6 +661,15 @@ static const struct hda_fixup cxt_fixups[] = { ...@@ -660,6 +661,15 @@ static const struct hda_fixup cxt_fixups[] = {
.type = HDA_FIXUP_PINS, .type = HDA_FIXUP_PINS,
.v.pins = cxt_pincfg_lemote, .v.pins = cxt_pincfg_lemote,
}, },
[CXT_PINCFG_COMPAQ_CQ60] = {
.type = HDA_FIXUP_PINS,
.v.pins = (const struct hda_pintbl[]) {
/* 0x17 was falsely set up as a mic, it should 0x1d */
{ 0x17, 0x400001f0 },
{ 0x1d, 0x97a70120 },
{ }
}
},
[CXT_FIXUP_STEREO_DMIC] = { [CXT_FIXUP_STEREO_DMIC] = {
.type = HDA_FIXUP_FUNC, .type = HDA_FIXUP_FUNC,
.v.func = cxt_fixup_stereo_dmic, .v.func = cxt_fixup_stereo_dmic,
...@@ -769,6 +779,7 @@ static const struct hda_model_fixup cxt5047_fixup_models[] = { ...@@ -769,6 +779,7 @@ static const struct hda_model_fixup cxt5047_fixup_models[] = {
}; };
static const struct snd_pci_quirk cxt5051_fixups[] = { static const struct snd_pci_quirk cxt5051_fixups[] = {
SND_PCI_QUIRK(0x103c, 0x360b, "Compaq CQ60", CXT_PINCFG_COMPAQ_CQ60),
SND_PCI_QUIRK(0x17aa, 0x20f2, "Lenovo X200", CXT_PINCFG_LENOVO_X200), SND_PCI_QUIRK(0x17aa, 0x20f2, "Lenovo X200", CXT_PINCFG_LENOVO_X200),
{} {}
}; };
......
...@@ -1773,6 +1773,36 @@ YAMAHA_DEVICE(0x7010, "UB99"), ...@@ -1773,6 +1773,36 @@ YAMAHA_DEVICE(0x7010, "UB99"),
} }
} }
}, },
{
USB_DEVICE(0x0582, 0x0159),
.driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
/* .vendor_name = "Roland", */
/* .product_name = "UA-22", */
.ifnum = QUIRK_ANY_INTERFACE,
.type = QUIRK_COMPOSITE,
.data = (const struct snd_usb_audio_quirk[]) {
{
.ifnum = 0,
.type = QUIRK_AUDIO_STANDARD_INTERFACE
},
{
.ifnum = 1,
.type = QUIRK_AUDIO_STANDARD_INTERFACE
},
{
.ifnum = 2,
.type = QUIRK_MIDI_FIXED_ENDPOINT,
.data = & (const struct snd_usb_midi_endpoint_info) {
.out_cables = 0x0001,
.in_cables = 0x0001
}
},
{
.ifnum = -1
}
}
}
},
/* this catches most recent vendor-specific Roland devices */ /* this catches most recent vendor-specific Roland devices */
{ {
.match_flags = USB_DEVICE_ID_MATCH_VENDOR | .match_flags = USB_DEVICE_ID_MATCH_VENDOR |
......
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