Commit b54c3835 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6:
  ALSA: hda - Fix mute control with some ALC262 models
  ALSA: snd_usb_caiaq: add support for Audio2DJ
  ALSA: pcm - Fix hwptr buffer-size overlap bug
  ALSA: pcm - Fix warnings in debug loggings
  ALSA: pcm - Add logging of hwptr updates and interrupt updates
  ASoC: tlv320aic3x: Enable PLL when not bypassed
  ALSA: hda - Restore GPIO1 properly at resume with AD1984A
  ALSA: ctxfi - Fix uninitialized error checks
  ALSA: hda - Use snprintf() to be safer
  ALSA: usb-audio - Volume control quirk for QuickCam E 3500
  ALSA: pcm - Fix regressions with VMware
parents 04fc0a40 57e4a5c4
...@@ -101,6 +101,8 @@ card*/pcm*/xrun_debug ...@@ -101,6 +101,8 @@ card*/pcm*/xrun_debug
bit 0 = Enable XRUN/jiffies debug messages bit 0 = Enable XRUN/jiffies debug messages
bit 1 = Show stack trace at XRUN / jiffies check bit 1 = Show stack trace at XRUN / jiffies check
bit 2 = Enable additional jiffies check bit 2 = Enable additional jiffies check
bit 3 = Log hwptr update at each period interrupt
bit 4 = Log hwptr update at each snd_pcm_update_hw_ptr()
When the bit 0 is set, the driver will show the messages to When the bit 0 is set, the driver will show the messages to
kernel log when an xrun is detected. The debug message is kernel log when an xrun is detected. The debug message is
...@@ -117,6 +119,9 @@ card*/pcm*/xrun_debug ...@@ -117,6 +119,9 @@ card*/pcm*/xrun_debug
buggy) hardware that doesn't give smooth pointer updates. buggy) hardware that doesn't give smooth pointer updates.
This feature is enabled via the bit 2. This feature is enabled via the bit 2.
Bits 3 and 4 are for logging the hwptr records. Note that
these will give flood of kernel messages.
card*/pcm*/sub*/info card*/pcm*/sub*/info
The general information of this PCM sub-stream. The general information of this PCM sub-stream.
......
...@@ -233,6 +233,18 @@ static int snd_pcm_update_hw_ptr_interrupt(struct snd_pcm_substream *substream) ...@@ -233,6 +233,18 @@ static int snd_pcm_update_hw_ptr_interrupt(struct snd_pcm_substream *substream)
xrun(substream); xrun(substream);
return -EPIPE; return -EPIPE;
} }
if (xrun_debug(substream, 8)) {
char name[16];
pcm_debug_name(substream, name, sizeof(name));
snd_printd("period_update: %s: pos=0x%x/0x%x/0x%x, "
"hwptr=0x%lx, hw_base=0x%lx, hw_intr=0x%lx\n",
name, (unsigned int)pos,
(unsigned int)runtime->period_size,
(unsigned int)runtime->buffer_size,
(unsigned long)old_hw_ptr,
(unsigned long)runtime->hw_ptr_base,
(unsigned long)runtime->hw_ptr_interrupt);
}
hw_base = runtime->hw_ptr_base; hw_base = runtime->hw_ptr_base;
new_hw_ptr = hw_base + pos; new_hw_ptr = hw_base + pos;
hw_ptr_interrupt = runtime->hw_ptr_interrupt + runtime->period_size; hw_ptr_interrupt = runtime->hw_ptr_interrupt + runtime->period_size;
...@@ -244,18 +256,27 @@ static int snd_pcm_update_hw_ptr_interrupt(struct snd_pcm_substream *substream) ...@@ -244,18 +256,27 @@ static int snd_pcm_update_hw_ptr_interrupt(struct snd_pcm_substream *substream)
delta = new_hw_ptr - hw_ptr_interrupt; delta = new_hw_ptr - hw_ptr_interrupt;
} }
if (delta < 0) { if (delta < 0) {
delta += runtime->buffer_size; if (runtime->periods == 1 || new_hw_ptr < old_hw_ptr)
delta += runtime->buffer_size;
if (delta < 0) { if (delta < 0) {
hw_ptr_error(substream, hw_ptr_error(substream,
"Unexpected hw_pointer value " "Unexpected hw_pointer value "
"(stream=%i, pos=%ld, intr_ptr=%ld)\n", "(stream=%i, pos=%ld, intr_ptr=%ld)\n",
substream->stream, (long)pos, substream->stream, (long)pos,
(long)hw_ptr_interrupt); (long)hw_ptr_interrupt);
#if 1
/* simply skipping the hwptr update seems more
* robust in some cases, e.g. on VMware with
* inaccurate timer source
*/
return 0; /* skip this update */
#else
/* rebase to interrupt position */ /* rebase to interrupt position */
hw_base = new_hw_ptr = hw_ptr_interrupt; hw_base = new_hw_ptr = hw_ptr_interrupt;
/* align hw_base to buffer_size */ /* align hw_base to buffer_size */
hw_base -= hw_base % runtime->buffer_size; hw_base -= hw_base % runtime->buffer_size;
delta = 0; delta = 0;
#endif
} else { } else {
hw_base += runtime->buffer_size; hw_base += runtime->buffer_size;
if (hw_base >= runtime->boundary) if (hw_base >= runtime->boundary)
...@@ -344,6 +365,19 @@ int snd_pcm_update_hw_ptr(struct snd_pcm_substream *substream) ...@@ -344,6 +365,19 @@ int snd_pcm_update_hw_ptr(struct snd_pcm_substream *substream)
xrun(substream); xrun(substream);
return -EPIPE; return -EPIPE;
} }
if (xrun_debug(substream, 16)) {
char name[16];
pcm_debug_name(substream, name, sizeof(name));
snd_printd("hw_update: %s: pos=0x%x/0x%x/0x%x, "
"hwptr=0x%lx, hw_base=0x%lx, hw_intr=0x%lx\n",
name, (unsigned int)pos,
(unsigned int)runtime->period_size,
(unsigned int)runtime->buffer_size,
(unsigned long)old_hw_ptr,
(unsigned long)runtime->hw_ptr_base,
(unsigned long)runtime->hw_ptr_interrupt);
}
hw_base = runtime->hw_ptr_base; hw_base = runtime->hw_ptr_base;
new_hw_ptr = hw_base + pos; new_hw_ptr = hw_base + pos;
......
...@@ -242,13 +242,12 @@ static int get_amixer_rsc(struct amixer_mgr *mgr, ...@@ -242,13 +242,12 @@ static int get_amixer_rsc(struct amixer_mgr *mgr,
/* Allocate mem for amixer resource */ /* Allocate mem for amixer resource */
amixer = kzalloc(sizeof(*amixer), GFP_KERNEL); amixer = kzalloc(sizeof(*amixer), GFP_KERNEL);
if (NULL == amixer) { if (!amixer)
err = -ENOMEM; return -ENOMEM;
return err;
}
/* Check whether there are sufficient /* Check whether there are sufficient
* amixer resources to meet request. */ * amixer resources to meet request. */
err = 0;
spin_lock_irqsave(&mgr->mgr_lock, flags); spin_lock_irqsave(&mgr->mgr_lock, flags);
for (i = 0; i < desc->msr; i++) { for (i = 0; i < desc->msr; i++) {
err = mgr_get_resource(&mgr->mgr, 1, &idx); err = mgr_get_resource(&mgr->mgr, 1, &idx);
...@@ -397,12 +396,11 @@ static int get_sum_rsc(struct sum_mgr *mgr, ...@@ -397,12 +396,11 @@ static int get_sum_rsc(struct sum_mgr *mgr,
/* Allocate mem for sum resource */ /* Allocate mem for sum resource */
sum = kzalloc(sizeof(*sum), GFP_KERNEL); sum = kzalloc(sizeof(*sum), GFP_KERNEL);
if (NULL == sum) { if (!sum)
err = -ENOMEM; return -ENOMEM;
return err;
}
/* Check whether there are sufficient sum resources to meet request. */ /* Check whether there are sufficient sum resources to meet request. */
err = 0;
spin_lock_irqsave(&mgr->mgr_lock, flags); spin_lock_irqsave(&mgr->mgr_lock, flags);
for (i = 0; i < desc->msr; i++) { for (i = 0; i < desc->msr; i++) {
err = mgr_get_resource(&mgr->mgr, 1, &idx); err = mgr_get_resource(&mgr->mgr, 1, &idx);
......
...@@ -724,12 +724,11 @@ static int get_srcimp_rsc(struct srcimp_mgr *mgr, ...@@ -724,12 +724,11 @@ static int get_srcimp_rsc(struct srcimp_mgr *mgr,
/* Allocate mem for SRCIMP resource */ /* Allocate mem for SRCIMP resource */
srcimp = kzalloc(sizeof(*srcimp), GFP_KERNEL); srcimp = kzalloc(sizeof(*srcimp), GFP_KERNEL);
if (NULL == srcimp) { if (!srcimp)
err = -ENOMEM; return -ENOMEM;
return err;
}
/* Check whether there are sufficient SRCIMP resources. */ /* Check whether there are sufficient SRCIMP resources. */
err = 0;
spin_lock_irqsave(&mgr->mgr_lock, flags); spin_lock_irqsave(&mgr->mgr_lock, flags);
for (i = 0; i < desc->msr; i++) { for (i = 0; i < desc->msr; i++) {
err = mgr_get_resource(&mgr->mgr, 1, &idx); err = mgr_get_resource(&mgr->mgr, 1, &idx);
......
...@@ -3754,7 +3754,7 @@ static int ad1884a_mobile_master_sw_put(struct snd_kcontrol *kcontrol, ...@@ -3754,7 +3754,7 @@ static int ad1884a_mobile_master_sw_put(struct snd_kcontrol *kcontrol,
int mute = (!ucontrol->value.integer.value[0] && int mute = (!ucontrol->value.integer.value[0] &&
!ucontrol->value.integer.value[1]); !ucontrol->value.integer.value[1]);
/* toggle GPIO1 according to the mute state */ /* toggle GPIO1 according to the mute state */
snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA, snd_hda_codec_write_cache(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA,
mute ? 0x02 : 0x0); mute ? 0x02 : 0x0);
return ret; return ret;
} }
......
...@@ -10631,6 +10631,18 @@ static void alc262_lenovo_3000_unsol_event(struct hda_codec *codec, ...@@ -10631,6 +10631,18 @@ static void alc262_lenovo_3000_unsol_event(struct hda_codec *codec,
alc262_lenovo_3000_automute(codec, 1); alc262_lenovo_3000_automute(codec, 1);
} }
static int amp_stereo_mute_update(struct hda_codec *codec, hda_nid_t nid,
int dir, int idx, long *valp)
{
int i, change = 0;
for (i = 0; i < 2; i++, valp++)
change |= snd_hda_codec_amp_update(codec, nid, i, dir, idx,
HDA_AMP_MUTE,
*valp ? 0 : HDA_AMP_MUTE);
return change;
}
/* bind hp and internal speaker mute (with plug check) */ /* bind hp and internal speaker mute (with plug check) */
static int alc262_fujitsu_master_sw_put(struct snd_kcontrol *kcontrol, static int alc262_fujitsu_master_sw_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol) struct snd_ctl_elem_value *ucontrol)
...@@ -10639,13 +10651,8 @@ static int alc262_fujitsu_master_sw_put(struct snd_kcontrol *kcontrol, ...@@ -10639,13 +10651,8 @@ static int alc262_fujitsu_master_sw_put(struct snd_kcontrol *kcontrol,
long *valp = ucontrol->value.integer.value; long *valp = ucontrol->value.integer.value;
int change; int change;
change = snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0, change = amp_stereo_mute_update(codec, 0x14, HDA_OUTPUT, 0, valp);
HDA_AMP_MUTE, change |= amp_stereo_mute_update(codec, 0x1b, HDA_OUTPUT, 0, valp);
valp ? 0 : HDA_AMP_MUTE);
change |= snd_hda_codec_amp_stereo(codec, 0x1b, HDA_OUTPUT, 0,
HDA_AMP_MUTE,
valp ? 0 : HDA_AMP_MUTE);
if (change) if (change)
alc262_fujitsu_automute(codec, 0); alc262_fujitsu_automute(codec, 0);
return change; return change;
...@@ -10680,10 +10687,7 @@ static int alc262_lenovo_3000_master_sw_put(struct snd_kcontrol *kcontrol, ...@@ -10680,10 +10687,7 @@ static int alc262_lenovo_3000_master_sw_put(struct snd_kcontrol *kcontrol,
long *valp = ucontrol->value.integer.value; long *valp = ucontrol->value.integer.value;
int change; int change;
change = snd_hda_codec_amp_stereo(codec, 0x1b, HDA_OUTPUT, 0, change = amp_stereo_mute_update(codec, 0x1b, HDA_OUTPUT, 0, valp);
HDA_AMP_MUTE,
valp ? 0 : HDA_AMP_MUTE);
if (change) if (change)
alc262_lenovo_3000_automute(codec, 0); alc262_lenovo_3000_automute(codec, 0);
return change; return change;
...@@ -11854,12 +11858,7 @@ static int alc268_acer_master_sw_put(struct snd_kcontrol *kcontrol, ...@@ -11854,12 +11858,7 @@ static int alc268_acer_master_sw_put(struct snd_kcontrol *kcontrol,
long *valp = ucontrol->value.integer.value; long *valp = ucontrol->value.integer.value;
int change; int change;
change = snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0, change = amp_stereo_mute_update(codec, 0x14, HDA_OUTPUT, 0, valp);
HDA_AMP_MUTE,
valp[0] ? 0 : HDA_AMP_MUTE);
change |= snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0,
HDA_AMP_MUTE,
valp[1] ? 0 : HDA_AMP_MUTE);
if (change) if (change)
alc268_acer_automute(codec, 0); alc268_acer_automute(codec, 0);
return change; return change;
......
...@@ -4066,7 +4066,7 @@ static int stac92xx_add_jack(struct hda_codec *codec, ...@@ -4066,7 +4066,7 @@ static int stac92xx_add_jack(struct hda_codec *codec,
jack->nid = nid; jack->nid = nid;
jack->type = type; jack->type = type;
sprintf(name, "%s at %s %s Jack", snprintf(name, sizeof(name), "%s at %s %s Jack",
snd_hda_get_jack_type(def_conf), snd_hda_get_jack_type(def_conf),
snd_hda_get_jack_connectivity(def_conf), snd_hda_get_jack_connectivity(def_conf),
snd_hda_get_jack_location(def_conf)); snd_hda_get_jack_location(def_conf));
......
...@@ -767,6 +767,7 @@ static int aic3x_hw_params(struct snd_pcm_substream *substream, ...@@ -767,6 +767,7 @@ static int aic3x_hw_params(struct snd_pcm_substream *substream,
int codec_clk = 0, bypass_pll = 0, fsref, last_clk = 0; int codec_clk = 0, bypass_pll = 0, fsref, last_clk = 0;
u8 data, r, p, pll_q, pll_p = 1, pll_r = 1, pll_j = 1; u8 data, r, p, pll_q, pll_p = 1, pll_r = 1, pll_j = 1;
u16 pll_d = 1; u16 pll_d = 1;
u8 reg;
/* select data word length */ /* select data word length */
data = data =
...@@ -801,8 +802,16 @@ static int aic3x_hw_params(struct snd_pcm_substream *substream, ...@@ -801,8 +802,16 @@ static int aic3x_hw_params(struct snd_pcm_substream *substream,
pll_q &= 0xf; pll_q &= 0xf;
aic3x_write(codec, AIC3X_PLL_PROGA_REG, pll_q << PLLQ_SHIFT); aic3x_write(codec, AIC3X_PLL_PROGA_REG, pll_q << PLLQ_SHIFT);
aic3x_write(codec, AIC3X_GPIOB_REG, CODEC_CLKIN_CLKDIV); aic3x_write(codec, AIC3X_GPIOB_REG, CODEC_CLKIN_CLKDIV);
} else /* disable PLL if it is bypassed */
reg = aic3x_read_reg_cache(codec, AIC3X_PLL_PROGA_REG);
aic3x_write(codec, AIC3X_PLL_PROGA_REG, reg & ~PLL_ENABLE);
} else {
aic3x_write(codec, AIC3X_GPIOB_REG, CODEC_CLKIN_PLLDIV); aic3x_write(codec, AIC3X_GPIOB_REG, CODEC_CLKIN_PLLDIV);
/* enable PLL when it is used */
reg = aic3x_read_reg_cache(codec, AIC3X_PLL_PROGA_REG);
aic3x_write(codec, AIC3X_PLL_PROGA_REG, reg | PLL_ENABLE);
}
/* Route Left DAC to left channel input and /* Route Left DAC to left channel input and
* right DAC to right channel input */ * right DAC to right channel input */
......
...@@ -48,6 +48,7 @@ config SND_USB_CAIAQ ...@@ -48,6 +48,7 @@ config SND_USB_CAIAQ
* Native Instruments Kore Controller * Native Instruments Kore Controller
* Native Instruments Kore Controller 2 * Native Instruments Kore Controller 2
* Native Instruments Audio Kontrol 1 * Native Instruments Audio Kontrol 1
* Native Instruments Audio 2 DJ
* Native Instruments Audio 4 DJ * Native Instruments Audio 4 DJ
* Native Instruments Audio 8 DJ * Native Instruments Audio 8 DJ
* Native Instruments Guitar Rig Session I/O * Native Instruments Guitar Rig Session I/O
......
...@@ -646,6 +646,7 @@ int snd_usb_caiaq_audio_init(struct snd_usb_caiaqdev *dev) ...@@ -646,6 +646,7 @@ int snd_usb_caiaq_audio_init(struct snd_usb_caiaqdev *dev)
case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_GUITARRIGMOBILE): case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_GUITARRIGMOBILE):
dev->samplerates |= SNDRV_PCM_RATE_192000; dev->samplerates |= SNDRV_PCM_RATE_192000;
/* fall thru */ /* fall thru */
case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO2DJ):
case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO4DJ): case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO4DJ):
case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO8DJ): case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO8DJ):
dev->samplerates |= SNDRV_PCM_RATE_88200; dev->samplerates |= SNDRV_PCM_RATE_88200;
......
...@@ -35,13 +35,14 @@ ...@@ -35,13 +35,14 @@
#include "input.h" #include "input.h"
MODULE_AUTHOR("Daniel Mack <daniel@caiaq.de>"); MODULE_AUTHOR("Daniel Mack <daniel@caiaq.de>");
MODULE_DESCRIPTION("caiaq USB audio, version 1.3.18"); MODULE_DESCRIPTION("caiaq USB audio, version 1.3.19");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_SUPPORTED_DEVICE("{{Native Instruments, RigKontrol2}," MODULE_SUPPORTED_DEVICE("{{Native Instruments, RigKontrol2},"
"{Native Instruments, RigKontrol3}," "{Native Instruments, RigKontrol3},"
"{Native Instruments, Kore Controller}," "{Native Instruments, Kore Controller},"
"{Native Instruments, Kore Controller 2}," "{Native Instruments, Kore Controller 2},"
"{Native Instruments, Audio Kontrol 1}," "{Native Instruments, Audio Kontrol 1},"
"{Native Instruments, Audio 2 DJ},"
"{Native Instruments, Audio 4 DJ}," "{Native Instruments, Audio 4 DJ},"
"{Native Instruments, Audio 8 DJ}," "{Native Instruments, Audio 8 DJ},"
"{Native Instruments, Session I/O}," "{Native Instruments, Session I/O},"
...@@ -121,6 +122,11 @@ static struct usb_device_id snd_usb_id_table[] = { ...@@ -121,6 +122,11 @@ static struct usb_device_id snd_usb_id_table[] = {
.idVendor = USB_VID_NATIVEINSTRUMENTS, .idVendor = USB_VID_NATIVEINSTRUMENTS,
.idProduct = USB_PID_AUDIO4DJ .idProduct = USB_PID_AUDIO4DJ
}, },
{
.match_flags = USB_DEVICE_ID_MATCH_DEVICE,
.idVendor = USB_VID_NATIVEINSTRUMENTS,
.idProduct = USB_PID_AUDIO2DJ
},
{ /* terminator */ } { /* terminator */ }
}; };
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#define USB_PID_KORECONTROLLER 0x4711 #define USB_PID_KORECONTROLLER 0x4711
#define USB_PID_KORECONTROLLER2 0x4712 #define USB_PID_KORECONTROLLER2 0x4712
#define USB_PID_AK1 0x0815 #define USB_PID_AK1 0x0815
#define USB_PID_AUDIO2DJ 0x041c
#define USB_PID_AUDIO4DJ 0x0839 #define USB_PID_AUDIO4DJ 0x0839
#define USB_PID_AUDIO8DJ 0x1978 #define USB_PID_AUDIO8DJ 0x1978
#define USB_PID_SESSIONIO 0x1915 #define USB_PID_SESSIONIO 0x1915
......
...@@ -990,20 +990,35 @@ static void build_feature_ctl(struct mixer_build *state, unsigned char *desc, ...@@ -990,20 +990,35 @@ static void build_feature_ctl(struct mixer_build *state, unsigned char *desc,
break; break;
} }
/* quirk for UDA1321/N101 */ /* volume control quirks */
/* note that detection between firmware 2.1.1.7 (N101) and later 2.1.1.21 */
/* is not very clear from datasheets */
/* I hope that the min value is -15360 for newer firmware --jk */
switch (state->chip->usb_id) { switch (state->chip->usb_id) {
case USB_ID(0x0471, 0x0101): case USB_ID(0x0471, 0x0101):
case USB_ID(0x0471, 0x0104): case USB_ID(0x0471, 0x0104):
case USB_ID(0x0471, 0x0105): case USB_ID(0x0471, 0x0105):
case USB_ID(0x0672, 0x1041): case USB_ID(0x0672, 0x1041):
/* quirk for UDA1321/N101.
* note that detection between firmware 2.1.1.7 (N101)
* and later 2.1.1.21 is not very clear from datasheets.
* I hope that the min value is -15360 for newer firmware --jk
*/
if (!strcmp(kctl->id.name, "PCM Playback Volume") && if (!strcmp(kctl->id.name, "PCM Playback Volume") &&
cval->min == -15616) { cval->min == -15616) {
snd_printk(KERN_INFO "using volume control quirk for the UDA1321/N101 chip\n"); snd_printk(KERN_INFO
"set volume quirk for UDA1321/N101 chip\n");
cval->max = -256; cval->max = -256;
} }
break;
case USB_ID(0x046d, 0x09a4):
if (!strcmp(kctl->id.name, "Mic Capture Volume")) {
snd_printk(KERN_INFO
"set volume quirk for QuickCam E3500\n");
cval->min = 6080;
cval->max = 8768;
cval->res = 192;
}
break;
} }
snd_printdd(KERN_INFO "[%d] FU [%s] ch = %d, val = %d/%d/%d\n", snd_printdd(KERN_INFO "[%d] FU [%s] ch = %d, val = %d/%d/%d\n",
......
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