Commit 0200971d authored by Linus Torvalds's avatar Linus Torvalds

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

sound fixes for 3.3-rc5

Just a collection of boring small fixes for ASoC, HD-audio Realtek
and USB-audio drivers.

* tag 'sound-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound:
  ALSA: snd-usb-caiaq: Fix the return of XRUN
  ASoC: ak4642: fixup HeadPhone L/R dapm settings
  ALSA: hda/realtek - Fix surround output regression on Acer Aspire 5935
  ALSA: hda/realtek - Fix overflow of vol/sw check bitmap
  ALSA: usb-audio: avoid integer overflow in create_fixed_stream_quirk()
  ASoC: wm8962: Fix sidetone enumeration texts
parents 45196cee cb74eb15
...@@ -80,6 +80,8 @@ enum { ...@@ -80,6 +80,8 @@ enum {
ALC_AUTOMUTE_MIXER, /* mute/unmute mixer widget AMP */ ALC_AUTOMUTE_MIXER, /* mute/unmute mixer widget AMP */
}; };
#define MAX_VOL_NIDS 0x40
struct alc_spec { struct alc_spec {
/* codec parameterization */ /* codec parameterization */
const struct snd_kcontrol_new *mixers[5]; /* mixer arrays */ const struct snd_kcontrol_new *mixers[5]; /* mixer arrays */
...@@ -118,8 +120,8 @@ struct alc_spec { ...@@ -118,8 +120,8 @@ struct alc_spec {
const hda_nid_t *capsrc_nids; const hda_nid_t *capsrc_nids;
hda_nid_t dig_in_nid; /* digital-in NID; optional */ hda_nid_t dig_in_nid; /* digital-in NID; optional */
hda_nid_t mixer_nid; /* analog-mixer NID */ hda_nid_t mixer_nid; /* analog-mixer NID */
DECLARE_BITMAP(vol_ctls, 0x20 << 1); DECLARE_BITMAP(vol_ctls, MAX_VOL_NIDS << 1);
DECLARE_BITMAP(sw_ctls, 0x20 << 1); DECLARE_BITMAP(sw_ctls, MAX_VOL_NIDS << 1);
/* capture setup for dynamic dual-adc switch */ /* capture setup for dynamic dual-adc switch */
hda_nid_t cur_adc; hda_nid_t cur_adc;
...@@ -3149,7 +3151,10 @@ static int alc_auto_fill_dac_nids(struct hda_codec *codec) ...@@ -3149,7 +3151,10 @@ static int alc_auto_fill_dac_nids(struct hda_codec *codec)
static inline unsigned int get_ctl_pos(unsigned int data) static inline unsigned int get_ctl_pos(unsigned int data)
{ {
hda_nid_t nid = get_amp_nid_(data); hda_nid_t nid = get_amp_nid_(data);
unsigned int dir = get_amp_direction_(data); unsigned int dir;
if (snd_BUG_ON(nid >= MAX_VOL_NIDS))
return 0;
dir = get_amp_direction_(data);
return (nid << 1) | dir; return (nid << 1) | dir;
} }
...@@ -4436,12 +4441,20 @@ static void alc889_fixup_dac_route(struct hda_codec *codec, ...@@ -4436,12 +4441,20 @@ static void alc889_fixup_dac_route(struct hda_codec *codec,
const struct alc_fixup *fix, int action) const struct alc_fixup *fix, int action)
{ {
if (action == ALC_FIXUP_ACT_PRE_PROBE) { if (action == ALC_FIXUP_ACT_PRE_PROBE) {
/* fake the connections during parsing the tree */
hda_nid_t conn1[2] = { 0x0c, 0x0d }; hda_nid_t conn1[2] = { 0x0c, 0x0d };
hda_nid_t conn2[2] = { 0x0e, 0x0f }; hda_nid_t conn2[2] = { 0x0e, 0x0f };
snd_hda_override_conn_list(codec, 0x14, 2, conn1); snd_hda_override_conn_list(codec, 0x14, 2, conn1);
snd_hda_override_conn_list(codec, 0x15, 2, conn1); snd_hda_override_conn_list(codec, 0x15, 2, conn1);
snd_hda_override_conn_list(codec, 0x18, 2, conn2); snd_hda_override_conn_list(codec, 0x18, 2, conn2);
snd_hda_override_conn_list(codec, 0x1a, 2, conn2); snd_hda_override_conn_list(codec, 0x1a, 2, conn2);
} else if (action == ALC_FIXUP_ACT_PROBE) {
/* restore the connections */
hda_nid_t conn[5] = { 0x0c, 0x0d, 0x0e, 0x0f, 0x26 };
snd_hda_override_conn_list(codec, 0x14, 5, conn);
snd_hda_override_conn_list(codec, 0x15, 5, conn);
snd_hda_override_conn_list(codec, 0x18, 5, conn);
snd_hda_override_conn_list(codec, 0x1a, 5, conn);
} }
} }
......
...@@ -146,13 +146,10 @@ static const struct snd_kcontrol_new ak4642_snd_controls[] = { ...@@ -146,13 +146,10 @@ static const struct snd_kcontrol_new ak4642_snd_controls[] = {
SOC_DOUBLE_R_TLV("Digital Playback Volume", L_DVC, R_DVC, SOC_DOUBLE_R_TLV("Digital Playback Volume", L_DVC, R_DVC,
0, 0xFF, 1, out_tlv), 0, 0xFF, 1, out_tlv),
SOC_SINGLE("Headphone Switch", PW_MGMT2, 6, 1, 0),
}; };
static const struct snd_kcontrol_new ak4642_hpout_mixer_controls[] = { static const struct snd_kcontrol_new ak4642_headphone_control =
SOC_DAPM_SINGLE("DACH", MD_CTL4, 0, 1, 0), SOC_DAPM_SINGLE("Switch", PW_MGMT2, 6, 1, 0);
};
static const struct snd_kcontrol_new ak4642_lout_mixer_controls[] = { static const struct snd_kcontrol_new ak4642_lout_mixer_controls[] = {
SOC_DAPM_SINGLE("DACL", SG_SL1, 4, 1, 0), SOC_DAPM_SINGLE("DACL", SG_SL1, 4, 1, 0),
...@@ -165,13 +162,12 @@ static const struct snd_soc_dapm_widget ak4642_dapm_widgets[] = { ...@@ -165,13 +162,12 @@ static const struct snd_soc_dapm_widget ak4642_dapm_widgets[] = {
SND_SOC_DAPM_OUTPUT("HPOUTR"), SND_SOC_DAPM_OUTPUT("HPOUTR"),
SND_SOC_DAPM_OUTPUT("LINEOUT"), SND_SOC_DAPM_OUTPUT("LINEOUT"),
SND_SOC_DAPM_MIXER("HPOUTL Mixer", PW_MGMT2, 5, 0, SND_SOC_DAPM_PGA("HPL Out", PW_MGMT2, 5, 0, NULL, 0),
&ak4642_hpout_mixer_controls[0], SND_SOC_DAPM_PGA("HPR Out", PW_MGMT2, 4, 0, NULL, 0),
ARRAY_SIZE(ak4642_hpout_mixer_controls)), SND_SOC_DAPM_SWITCH("Headphone Enable", SND_SOC_NOPM, 0, 0,
&ak4642_headphone_control),
SND_SOC_DAPM_MIXER("HPOUTR Mixer", PW_MGMT2, 4, 0, SND_SOC_DAPM_PGA("DACH", MD_CTL4, 0, 0, NULL, 0),
&ak4642_hpout_mixer_controls[0],
ARRAY_SIZE(ak4642_hpout_mixer_controls)),
SND_SOC_DAPM_MIXER("LINEOUT Mixer", PW_MGMT1, 3, 0, SND_SOC_DAPM_MIXER("LINEOUT Mixer", PW_MGMT1, 3, 0,
&ak4642_lout_mixer_controls[0], &ak4642_lout_mixer_controls[0],
...@@ -184,12 +180,17 @@ static const struct snd_soc_dapm_widget ak4642_dapm_widgets[] = { ...@@ -184,12 +180,17 @@ static const struct snd_soc_dapm_widget ak4642_dapm_widgets[] = {
static const struct snd_soc_dapm_route ak4642_intercon[] = { static const struct snd_soc_dapm_route ak4642_intercon[] = {
/* Outputs */ /* Outputs */
{"HPOUTL", NULL, "HPOUTL Mixer"}, {"HPOUTL", NULL, "HPL Out"},
{"HPOUTR", NULL, "HPOUTR Mixer"}, {"HPOUTR", NULL, "HPR Out"},
{"LINEOUT", NULL, "LINEOUT Mixer"}, {"LINEOUT", NULL, "LINEOUT Mixer"},
{"HPOUTL Mixer", "DACH", "DAC"}, {"HPL Out", NULL, "Headphone Enable"},
{"HPOUTR Mixer", "DACH", "DAC"}, {"HPR Out", NULL, "Headphone Enable"},
{"Headphone Enable", "Switch", "DACH"},
{"DACH", NULL, "DAC"},
{"LINEOUT Mixer", "DACL", "DAC"}, {"LINEOUT Mixer", "DACL", "DAC"},
}; };
......
...@@ -2564,7 +2564,7 @@ static int dsp2_event(struct snd_soc_dapm_widget *w, ...@@ -2564,7 +2564,7 @@ static int dsp2_event(struct snd_soc_dapm_widget *w,
return 0; return 0;
} }
static const char *st_text[] = { "None", "Right", "Left" }; static const char *st_text[] = { "None", "Left", "Right" };
static const struct soc_enum str_enum = static const struct soc_enum str_enum =
SOC_ENUM_SINGLE(WM8962_DAC_DSP_MIXING_1, 2, 3, st_text); SOC_ENUM_SINGLE(WM8962_DAC_DSP_MIXING_1, 2, 3, st_text);
......
...@@ -311,8 +311,10 @@ snd_usb_caiaq_pcm_pointer(struct snd_pcm_substream *sub) ...@@ -311,8 +311,10 @@ snd_usb_caiaq_pcm_pointer(struct snd_pcm_substream *sub)
spin_lock(&dev->spinlock); spin_lock(&dev->spinlock);
if (dev->input_panic || dev->output_panic) if (dev->input_panic || dev->output_panic) {
ptr = SNDRV_PCM_POS_XRUN; ptr = SNDRV_PCM_POS_XRUN;
goto unlock;
}
if (sub->stream == SNDRV_PCM_STREAM_PLAYBACK) if (sub->stream == SNDRV_PCM_STREAM_PLAYBACK)
ptr = bytes_to_frames(sub->runtime, ptr = bytes_to_frames(sub->runtime,
...@@ -321,6 +323,7 @@ snd_usb_caiaq_pcm_pointer(struct snd_pcm_substream *sub) ...@@ -321,6 +323,7 @@ snd_usb_caiaq_pcm_pointer(struct snd_pcm_substream *sub)
ptr = bytes_to_frames(sub->runtime, ptr = bytes_to_frames(sub->runtime,
dev->audio_in_buf_pos[index]); dev->audio_in_buf_pos[index]);
unlock:
spin_unlock(&dev->spinlock); spin_unlock(&dev->spinlock);
return ptr; return ptr;
} }
......
#ifndef __USBAUDIO_CARD_H #ifndef __USBAUDIO_CARD_H
#define __USBAUDIO_CARD_H #define __USBAUDIO_CARD_H
#define MAX_NR_RATES 1024
#define MAX_PACKS 20 #define MAX_PACKS 20
#define MAX_PACKS_HS (MAX_PACKS * 8) /* in high speed mode */ #define MAX_PACKS_HS (MAX_PACKS * 8) /* in high speed mode */
#define MAX_URBS 8 #define MAX_URBS 8
......
...@@ -209,8 +209,6 @@ static int parse_audio_format_rates_v1(struct snd_usb_audio *chip, struct audiof ...@@ -209,8 +209,6 @@ static int parse_audio_format_rates_v1(struct snd_usb_audio *chip, struct audiof
return 0; return 0;
} }
#define MAX_UAC2_NR_RATES 1024
/* /*
* Helper function to walk the array of sample rate triplets reported by * Helper function to walk the array of sample rate triplets reported by
* the device. The problem is that we need to parse whole array first to * the device. The problem is that we need to parse whole array first to
...@@ -255,7 +253,7 @@ static int parse_uac2_sample_rate_range(struct audioformat *fp, int nr_triplets, ...@@ -255,7 +253,7 @@ static int parse_uac2_sample_rate_range(struct audioformat *fp, int nr_triplets,
fp->rates |= snd_pcm_rate_to_rate_bit(rate); fp->rates |= snd_pcm_rate_to_rate_bit(rate);
nr_rates++; nr_rates++;
if (nr_rates >= MAX_UAC2_NR_RATES) { if (nr_rates >= MAX_NR_RATES) {
snd_printk(KERN_ERR "invalid uac2 rates\n"); snd_printk(KERN_ERR "invalid uac2 rates\n");
break; break;
} }
......
...@@ -132,10 +132,14 @@ static int create_fixed_stream_quirk(struct snd_usb_audio *chip, ...@@ -132,10 +132,14 @@ static int create_fixed_stream_quirk(struct snd_usb_audio *chip,
unsigned *rate_table = NULL; unsigned *rate_table = NULL;
fp = kmemdup(quirk->data, sizeof(*fp), GFP_KERNEL); fp = kmemdup(quirk->data, sizeof(*fp), GFP_KERNEL);
if (! fp) { if (!fp) {
snd_printk(KERN_ERR "cannot memdup\n"); snd_printk(KERN_ERR "cannot memdup\n");
return -ENOMEM; return -ENOMEM;
} }
if (fp->nr_rates > MAX_NR_RATES) {
kfree(fp);
return -EINVAL;
}
if (fp->nr_rates > 0) { if (fp->nr_rates > 0) {
rate_table = kmemdup(fp->rate_table, rate_table = kmemdup(fp->rate_table,
sizeof(int) * fp->nr_rates, GFP_KERNEL); sizeof(int) * fp->nr_rates, GFP_KERNEL);
......
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