Commit 09cfd929 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'linus' of git://git.kernel.org/pub/scm/linux/kernel/git/perex/alsa

* 'linus' of git://git.kernel.org/pub/scm/linux/kernel/git/perex/alsa:
  [ALSA] version 1.0.15
  [ALSA] emu10k1 - Check value ranges in ctl callbacks
  [ALSA] emu10k1: Add mixer controls parameter checking.
  [ALSA] fix private data pointer calculation in CS4270 driver
  [ALSA] portman2x4 - Fix probe error
  [ALSA] ca0106 - Fix write proc assignment
  [ALSA] s3c2443-ac97: compilation fix
  [ALSA] hda-codec - Revert volume knob controls in STAC codecs
  [ALSA] ca0106 - Check value range in ctl callbacks
  [ALSA] hda-codec - Check PINCAP only for PIN widgets
  [ALSA] mpu401: fix recursive locking in timer
  [ALSA] cmipci: fix FLINKON/OFF bits
  [ALSA] hda-codec - Disable shared stream on AD1986A
parents 8c6531f7 7cb41c65
/* include/version.h. Generated by alsa/ksync script. */ /* include/version.h. Generated by alsa/ksync script. */
#define CONFIG_SND_VERSION "1.0.15" #define CONFIG_SND_VERSION "1.0.15"
#define CONFIG_SND_DATE " (Tue Oct 23 06:09:18 2007 UTC)" #define CONFIG_SND_DATE " (Tue Nov 20 19:16:42 2007 UTC)"
...@@ -97,23 +97,27 @@ static void snd_mpu401_uart_clear_rx(struct snd_mpu401 *mpu) ...@@ -97,23 +97,27 @@ static void snd_mpu401_uart_clear_rx(struct snd_mpu401 *mpu)
static void uart_interrupt_tx(struct snd_mpu401 *mpu) static void uart_interrupt_tx(struct snd_mpu401 *mpu)
{ {
unsigned long flags;
if (test_bit(MPU401_MODE_BIT_OUTPUT, &mpu->mode) && if (test_bit(MPU401_MODE_BIT_OUTPUT, &mpu->mode) &&
test_bit(MPU401_MODE_BIT_OUTPUT_TRIGGER, &mpu->mode)) { test_bit(MPU401_MODE_BIT_OUTPUT_TRIGGER, &mpu->mode)) {
spin_lock(&mpu->output_lock); spin_lock_irqsave(&mpu->output_lock, flags);
snd_mpu401_uart_output_write(mpu); snd_mpu401_uart_output_write(mpu);
spin_unlock(&mpu->output_lock); spin_unlock_irqrestore(&mpu->output_lock, flags);
} }
} }
static void _snd_mpu401_uart_interrupt(struct snd_mpu401 *mpu) static void _snd_mpu401_uart_interrupt(struct snd_mpu401 *mpu)
{ {
unsigned long flags;
if (mpu->info_flags & MPU401_INFO_INPUT) { if (mpu->info_flags & MPU401_INFO_INPUT) {
spin_lock(&mpu->input_lock); spin_lock_irqsave(&mpu->input_lock, flags);
if (test_bit(MPU401_MODE_BIT_INPUT, &mpu->mode)) if (test_bit(MPU401_MODE_BIT_INPUT, &mpu->mode))
snd_mpu401_uart_input_read(mpu); snd_mpu401_uart_input_read(mpu);
else else
snd_mpu401_uart_clear_rx(mpu); snd_mpu401_uart_clear_rx(mpu);
spin_unlock(&mpu->input_lock); spin_unlock_irqrestore(&mpu->input_lock, flags);
} }
if (! (mpu->info_flags & MPU401_INFO_TX_IRQ)) if (! (mpu->info_flags & MPU401_INFO_TX_IRQ))
/* ok. for better Tx performance try do some output /* ok. for better Tx performance try do some output
......
...@@ -668,7 +668,7 @@ static int __devinit snd_portman_probe_port(struct parport *p) ...@@ -668,7 +668,7 @@ static int __devinit snd_portman_probe_port(struct parport *p)
parport_release(pardev); parport_release(pardev);
parport_unregister_device(pardev); parport_unregister_device(pardev);
return res; return res ? -EIO : 0;
} }
static void __devinit snd_portman_attach(struct parport *p) static void __devinit snd_portman_attach(struct parport *p)
......
...@@ -86,7 +86,7 @@ static int snd_ca0106_shared_spdif_get(struct snd_kcontrol *kcontrol, ...@@ -86,7 +86,7 @@ static int snd_ca0106_shared_spdif_get(struct snd_kcontrol *kcontrol,
{ {
struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol); struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
ucontrol->value.enumerated.item[0] = emu->spdif_enable; ucontrol->value.integer.value[0] = emu->spdif_enable;
return 0; return 0;
} }
...@@ -98,11 +98,11 @@ static int snd_ca0106_shared_spdif_put(struct snd_kcontrol *kcontrol, ...@@ -98,11 +98,11 @@ static int snd_ca0106_shared_spdif_put(struct snd_kcontrol *kcontrol,
int change = 0; int change = 0;
u32 mask; u32 mask;
val = ucontrol->value.enumerated.item[0] ; val = !!ucontrol->value.integer.value[0];
change = (emu->spdif_enable != val); change = (emu->spdif_enable != val);
if (change) { if (change) {
emu->spdif_enable = val; emu->spdif_enable = val;
if (val == 1) { if (val) {
/* Digital */ /* Digital */
snd_ca0106_ptr_write(emu, SPDIF_SELECT1, 0, 0xf); snd_ca0106_ptr_write(emu, SPDIF_SELECT1, 0, 0xf);
snd_ca0106_ptr_write(emu, SPDIF_SELECT2, 0, 0x0b000000); snd_ca0106_ptr_write(emu, SPDIF_SELECT2, 0, 0x0b000000);
...@@ -159,6 +159,8 @@ static int snd_ca0106_capture_source_put(struct snd_kcontrol *kcontrol, ...@@ -159,6 +159,8 @@ static int snd_ca0106_capture_source_put(struct snd_kcontrol *kcontrol,
u32 source; u32 source;
val = ucontrol->value.enumerated.item[0] ; val = ucontrol->value.enumerated.item[0] ;
if (val >= 6)
return -EINVAL;
change = (emu->capture_source != val); change = (emu->capture_source != val);
if (change) { if (change) {
emu->capture_source = val; emu->capture_source = val;
...@@ -207,6 +209,8 @@ static int snd_ca0106_i2c_capture_source_put(struct snd_kcontrol *kcontrol, ...@@ -207,6 +209,8 @@ static int snd_ca0106_i2c_capture_source_put(struct snd_kcontrol *kcontrol,
* for the particular source. * for the particular source.
*/ */
source_id = ucontrol->value.enumerated.item[0] ; source_id = ucontrol->value.enumerated.item[0] ;
if (source_id >= 4)
return -EINVAL;
change = (emu->i2c_capture_source != source_id); change = (emu->i2c_capture_source != source_id);
if (change) { if (change) {
snd_ca0106_i2c_write(emu, ADC_MUX, 0); /* Mute input */ snd_ca0106_i2c_write(emu, ADC_MUX, 0); /* Mute input */
...@@ -271,6 +275,8 @@ static int snd_ca0106_capture_mic_line_in_put(struct snd_kcontrol *kcontrol, ...@@ -271,6 +275,8 @@ static int snd_ca0106_capture_mic_line_in_put(struct snd_kcontrol *kcontrol,
u32 tmp; u32 tmp;
val = ucontrol->value.enumerated.item[0] ; val = ucontrol->value.enumerated.item[0] ;
if (val > 1)
return -EINVAL;
change = (emu->capture_mic_line_in != val); change = (emu->capture_mic_line_in != val);
if (change) { if (change) {
emu->capture_mic_line_in = val; emu->capture_mic_line_in = val;
...@@ -443,7 +449,7 @@ static int snd_ca0106_i2c_volume_put(struct snd_kcontrol *kcontrol, ...@@ -443,7 +449,7 @@ static int snd_ca0106_i2c_volume_put(struct snd_kcontrol *kcontrol,
ogain = emu->i2c_capture_volume[source_id][0]; /* Left */ ogain = emu->i2c_capture_volume[source_id][0]; /* Left */
ngain = ucontrol->value.integer.value[0]; ngain = ucontrol->value.integer.value[0];
if (ngain > 0xff) if (ngain > 0xff)
return 0; return -EINVAL;
if (ogain != ngain) { if (ogain != ngain) {
if (emu->i2c_capture_source == source_id) if (emu->i2c_capture_source == source_id)
snd_ca0106_i2c_write(emu, ADC_ATTEN_ADCL, ((ngain) & 0xff) ); snd_ca0106_i2c_write(emu, ADC_ATTEN_ADCL, ((ngain) & 0xff) );
...@@ -453,7 +459,7 @@ static int snd_ca0106_i2c_volume_put(struct snd_kcontrol *kcontrol, ...@@ -453,7 +459,7 @@ static int snd_ca0106_i2c_volume_put(struct snd_kcontrol *kcontrol,
ogain = emu->i2c_capture_volume[source_id][1]; /* Right */ ogain = emu->i2c_capture_volume[source_id][1]; /* Right */
ngain = ucontrol->value.integer.value[1]; ngain = ucontrol->value.integer.value[1];
if (ngain > 0xff) if (ngain > 0xff)
return 0; return -EINVAL;
if (ogain != ngain) { if (ogain != ngain) {
if (emu->i2c_capture_source == source_id) if (emu->i2c_capture_source == source_id)
snd_ca0106_i2c_write(emu, ADC_ATTEN_ADCR, ((ngain) & 0xff)); snd_ca0106_i2c_write(emu, ADC_ATTEN_ADCR, ((ngain) & 0xff));
...@@ -497,7 +503,7 @@ static int spi_mute_put(struct snd_kcontrol *kcontrol, ...@@ -497,7 +503,7 @@ static int spi_mute_put(struct snd_kcontrol *kcontrol,
} }
ret = snd_ca0106_spi_write(emu, emu->spi_dac_reg[reg]); ret = snd_ca0106_spi_write(emu, emu->spi_dac_reg[reg]);
return ret ? -1 : 1; return ret ? -EINVAL : 1;
} }
#define CA_VOLUME(xname,chid,reg) \ #define CA_VOLUME(xname,chid,reg) \
......
...@@ -445,13 +445,11 @@ int __devinit snd_ca0106_proc_init(struct snd_ca0106 * emu) ...@@ -445,13 +445,11 @@ int __devinit snd_ca0106_proc_init(struct snd_ca0106 * emu)
snd_info_set_text_ops(entry, emu, snd_ca0106_proc_reg_read1); snd_info_set_text_ops(entry, emu, snd_ca0106_proc_reg_read1);
entry->c.text.write = snd_ca0106_proc_reg_write; entry->c.text.write = snd_ca0106_proc_reg_write;
entry->mode |= S_IWUSR; entry->mode |= S_IWUSR;
// entry->private_data = emu;
} }
if(! snd_card_proc_new(emu->card, "ca0106_i2c", &entry)) { if(! snd_card_proc_new(emu->card, "ca0106_i2c", &entry)) {
snd_info_set_text_ops(entry, emu, snd_ca0106_proc_i2c_write);
entry->c.text.write = snd_ca0106_proc_i2c_write; entry->c.text.write = snd_ca0106_proc_i2c_write;
entry->private_data = emu;
entry->mode |= S_IWUSR; entry->mode |= S_IWUSR;
// entry->private_data = emu;
} }
if(! snd_card_proc_new(emu->card, "ca0106_regs2", &entry)) if(! snd_card_proc_new(emu->card, "ca0106_regs2", &entry))
snd_info_set_text_ops(entry, emu, snd_ca0106_proc_reg_read2); snd_info_set_text_ops(entry, emu, snd_ca0106_proc_reg_read2);
......
...@@ -246,10 +246,9 @@ MODULE_PARM_DESC(joystick_port, "Joystick port address."); ...@@ -246,10 +246,9 @@ MODULE_PARM_DESC(joystick_port, "Joystick port address.");
#define CM_MMODE_MASK 0x00000E00 /* model DAA interface mode */ #define CM_MMODE_MASK 0x00000E00 /* model DAA interface mode */
#define CM_SPDIF_SELECT2 0x00000100 /* for model > 039 ? */ #define CM_SPDIF_SELECT2 0x00000100 /* for model > 039 ? */
#define CM_ENCENTER 0x00000080 #define CM_ENCENTER 0x00000080
#define CM_FLINKON 0x00000080 /* force modem link detection on, model 037 */ #define CM_FLINKON 0x00000040 /* force modem link detection on, model 037 */
#define CM_MUTECH1 0x00000040 /* mute PCI ch1 to DAC */ #define CM_MUTECH1 0x00000040 /* mute PCI ch1 to DAC */
#define CM_FLINKOFF 0x00000040 /* force modem link detection off, model 037 */ #define CM_FLINKOFF 0x00000020 /* force modem link detection off, model 037 */
#define CM_UNKNOWN_18_5 0x00000020 /* ? */
#define CM_MIDSMP 0x00000010 /* 1/2 interpolation at front end DAC */ #define CM_MIDSMP 0x00000010 /* 1/2 interpolation at front end DAC */
#define CM_UPDDMA_MASK 0x0000000C /* TDMA position update notification */ #define CM_UPDDMA_MASK 0x0000000C /* TDMA position update notification */
#define CM_UPDDMA_2048 0x00000000 #define CM_UPDDMA_2048 0x00000000
......
...@@ -58,6 +58,9 @@ static int snd_emu10k1_spdif_get(struct snd_kcontrol *kcontrol, ...@@ -58,6 +58,9 @@ static int snd_emu10k1_spdif_get(struct snd_kcontrol *kcontrol,
unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
unsigned long flags; unsigned long flags;
/* Limit: emu->spdif_bits */
if (idx >= 3)
return -EINVAL;
spin_lock_irqsave(&emu->reg_lock, flags); spin_lock_irqsave(&emu->reg_lock, flags);
ucontrol->value.iec958.status[0] = (emu->spdif_bits[idx] >> 0) & 0xff; ucontrol->value.iec958.status[0] = (emu->spdif_bits[idx] >> 0) & 0xff;
ucontrol->value.iec958.status[1] = (emu->spdif_bits[idx] >> 8) & 0xff; ucontrol->value.iec958.status[1] = (emu->spdif_bits[idx] >> 8) & 0xff;
...@@ -272,9 +275,12 @@ static int snd_emu1010_output_source_get(struct snd_kcontrol *kcontrol, ...@@ -272,9 +275,12 @@ static int snd_emu1010_output_source_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol) struct snd_ctl_elem_value *ucontrol)
{ {
struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
int channel; unsigned int channel;
channel = (kcontrol->private_value) & 0xff; channel = (kcontrol->private_value) & 0xff;
/* Limit: emu1010_output_dst, emu->emu1010.output_source */
if (channel >= 24)
return -EINVAL;
ucontrol->value.enumerated.item[0] = emu->emu1010.output_source[channel]; ucontrol->value.enumerated.item[0] = emu->emu1010.output_source[channel];
return 0; return 0;
} }
...@@ -285,11 +291,17 @@ static int snd_emu1010_output_source_put(struct snd_kcontrol *kcontrol, ...@@ -285,11 +291,17 @@ static int snd_emu1010_output_source_put(struct snd_kcontrol *kcontrol,
struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
int change = 0; int change = 0;
unsigned int val; unsigned int val;
int channel; unsigned int channel;
val = ucontrol->value.enumerated.item[0];
if (val >= 53)
return -EINVAL;
channel = (kcontrol->private_value) & 0xff; channel = (kcontrol->private_value) & 0xff;
if (emu->emu1010.output_source[channel] != ucontrol->value.enumerated.item[0]) { /* Limit: emu1010_output_dst, emu->emu1010.output_source */
val = emu->emu1010.output_source[channel] = ucontrol->value.enumerated.item[0]; if (channel >= 24)
return -EINVAL;
if (emu->emu1010.output_source[channel] != val) {
emu->emu1010.output_source[channel] = val;
change = 1; change = 1;
snd_emu1010_fpga_link_dst_src_write(emu, snd_emu1010_fpga_link_dst_src_write(emu,
emu1010_output_dst[channel], emu1010_src_regs[val]); emu1010_output_dst[channel], emu1010_src_regs[val]);
...@@ -301,9 +313,12 @@ static int snd_emu1010_input_source_get(struct snd_kcontrol *kcontrol, ...@@ -301,9 +313,12 @@ static int snd_emu1010_input_source_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol) struct snd_ctl_elem_value *ucontrol)
{ {
struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
int channel; unsigned int channel;
channel = (kcontrol->private_value) & 0xff; channel = (kcontrol->private_value) & 0xff;
/* Limit: emu1010_input_dst, emu->emu1010.input_source */
if (channel >= 22)
return -EINVAL;
ucontrol->value.enumerated.item[0] = emu->emu1010.input_source[channel]; ucontrol->value.enumerated.item[0] = emu->emu1010.input_source[channel];
return 0; return 0;
} }
...@@ -314,11 +329,17 @@ static int snd_emu1010_input_source_put(struct snd_kcontrol *kcontrol, ...@@ -314,11 +329,17 @@ static int snd_emu1010_input_source_put(struct snd_kcontrol *kcontrol,
struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
int change = 0; int change = 0;
unsigned int val; unsigned int val;
int channel; unsigned int channel;
val = ucontrol->value.enumerated.item[0];
if (val >= 53)
return -EINVAL;
channel = (kcontrol->private_value) & 0xff; channel = (kcontrol->private_value) & 0xff;
if (emu->emu1010.input_source[channel] != ucontrol->value.enumerated.item[0]) { /* Limit: emu1010_input_dst, emu->emu1010.input_source */
val = emu->emu1010.input_source[channel] = ucontrol->value.enumerated.item[0]; if (channel >= 22)
return -EINVAL;
if (emu->emu1010.input_source[channel] != val) {
emu->emu1010.input_source[channel] = val;
change = 1; change = 1;
snd_emu1010_fpga_link_dst_src_write(emu, snd_emu1010_fpga_link_dst_src_write(emu,
emu1010_input_dst[channel], emu1010_src_regs[val]); emu1010_input_dst[channel], emu1010_src_regs[val]);
...@@ -533,6 +554,9 @@ static int snd_emu1010_internal_clock_put(struct snd_kcontrol *kcontrol, ...@@ -533,6 +554,9 @@ static int snd_emu1010_internal_clock_put(struct snd_kcontrol *kcontrol,
int change = 0; int change = 0;
val = ucontrol->value.enumerated.item[0] ; val = ucontrol->value.enumerated.item[0] ;
/* Limit: uinfo->value.enumerated.items = 4; */
if (val >= 4)
return -EINVAL;
change = (emu->emu1010.internal_clock != val); change = (emu->emu1010.internal_clock != val);
if (change) { if (change) {
emu->emu1010.internal_clock = val; emu->emu1010.internal_clock = val;
...@@ -669,7 +693,11 @@ static int snd_audigy_i2c_capture_source_put(struct snd_kcontrol *kcontrol, ...@@ -669,7 +693,11 @@ static int snd_audigy_i2c_capture_source_put(struct snd_kcontrol *kcontrol,
* update the capture volume from the cached value * update the capture volume from the cached value
* for the particular source. * for the particular source.
*/ */
source_id = ucontrol->value.enumerated.item[0]; /* Use 2 and 3 */ source_id = ucontrol->value.enumerated.item[0];
/* Limit: uinfo->value.enumerated.items = 2; */
/* emu->i2c_capture_volume */
if (source_id >= 2)
return -EINVAL;
change = (emu->i2c_capture_source != source_id); change = (emu->i2c_capture_source != source_id);
if (change) { if (change) {
snd_emu10k1_i2c_write(emu, ADC_MUX, 0); /* Mute input */ snd_emu10k1_i2c_write(emu, ADC_MUX, 0); /* Mute input */
...@@ -720,9 +748,13 @@ static int snd_audigy_i2c_volume_get(struct snd_kcontrol *kcontrol, ...@@ -720,9 +748,13 @@ static int snd_audigy_i2c_volume_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol) struct snd_ctl_elem_value *ucontrol)
{ {
struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
int source_id; unsigned int source_id;
source_id = kcontrol->private_value; source_id = kcontrol->private_value;
/* Limit: emu->i2c_capture_volume */
/* capture_source: uinfo->value.enumerated.items = 2 */
if (source_id >= 2)
return -EINVAL;
ucontrol->value.integer.value[0] = emu->i2c_capture_volume[source_id][0]; ucontrol->value.integer.value[0] = emu->i2c_capture_volume[source_id][0];
ucontrol->value.integer.value[1] = emu->i2c_capture_volume[source_id][1]; ucontrol->value.integer.value[1] = emu->i2c_capture_volume[source_id][1];
...@@ -735,10 +767,14 @@ static int snd_audigy_i2c_volume_put(struct snd_kcontrol *kcontrol, ...@@ -735,10 +767,14 @@ static int snd_audigy_i2c_volume_put(struct snd_kcontrol *kcontrol,
struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
unsigned int ogain; unsigned int ogain;
unsigned int ngain; unsigned int ngain;
int source_id; unsigned int source_id;
int change = 0; int change = 0;
source_id = kcontrol->private_value; source_id = kcontrol->private_value;
/* Limit: emu->i2c_capture_volume */
/* capture_source: uinfo->value.enumerated.items = 2 */
if (source_id >= 2)
return -EINVAL;
ogain = emu->i2c_capture_volume[source_id][0]; /* Left */ ogain = emu->i2c_capture_volume[source_id][0]; /* Left */
ngain = ucontrol->value.integer.value[0]; ngain = ucontrol->value.integer.value[0];
if (ngain > 0xff) if (ngain > 0xff)
...@@ -746,7 +782,7 @@ static int snd_audigy_i2c_volume_put(struct snd_kcontrol *kcontrol, ...@@ -746,7 +782,7 @@ static int snd_audigy_i2c_volume_put(struct snd_kcontrol *kcontrol,
if (ogain != ngain) { if (ogain != ngain) {
if (emu->i2c_capture_source == source_id) if (emu->i2c_capture_source == source_id)
snd_emu10k1_i2c_write(emu, ADC_ATTEN_ADCL, ((ngain) & 0xff) ); snd_emu10k1_i2c_write(emu, ADC_ATTEN_ADCL, ((ngain) & 0xff) );
emu->i2c_capture_volume[source_id][0] = ucontrol->value.integer.value[0]; emu->i2c_capture_volume[source_id][0] = ngain;
change = 1; change = 1;
} }
ogain = emu->i2c_capture_volume[source_id][1]; /* Right */ ogain = emu->i2c_capture_volume[source_id][1]; /* Right */
...@@ -756,7 +792,7 @@ static int snd_audigy_i2c_volume_put(struct snd_kcontrol *kcontrol, ...@@ -756,7 +792,7 @@ static int snd_audigy_i2c_volume_put(struct snd_kcontrol *kcontrol,
if (ogain != ngain) { if (ogain != ngain) {
if (emu->i2c_capture_source == source_id) if (emu->i2c_capture_source == source_id)
snd_emu10k1_i2c_write(emu, ADC_ATTEN_ADCR, ((ngain) & 0xff)); snd_emu10k1_i2c_write(emu, ADC_ATTEN_ADCR, ((ngain) & 0xff));
emu->i2c_capture_volume[source_id][1] = ucontrol->value.integer.value[1]; emu->i2c_capture_volume[source_id][1] = ngain;
change = 1; change = 1;
} }
...@@ -877,6 +913,9 @@ static int snd_emu10k1_spdif_put(struct snd_kcontrol *kcontrol, ...@@ -877,6 +913,9 @@ static int snd_emu10k1_spdif_put(struct snd_kcontrol *kcontrol,
unsigned int val; unsigned int val;
unsigned long flags; unsigned long flags;
/* Limit: emu->spdif_bits */
if (idx >= 3)
return -EINVAL;
val = (ucontrol->value.iec958.status[0] << 0) | val = (ucontrol->value.iec958.status[0] << 0) |
(ucontrol->value.iec958.status[1] << 8) | (ucontrol->value.iec958.status[1] << 8) |
(ucontrol->value.iec958.status[2] << 16) | (ucontrol->value.iec958.status[2] << 16) |
......
...@@ -742,6 +742,8 @@ static int snd_p16v_capture_source_put(struct snd_kcontrol *kcontrol, ...@@ -742,6 +742,8 @@ static int snd_p16v_capture_source_put(struct snd_kcontrol *kcontrol,
u32 source; u32 source;
val = ucontrol->value.enumerated.item[0] ; val = ucontrol->value.enumerated.item[0] ;
if (val > 7)
return -EINVAL;
change = (emu->p16v_capture_source != val); change = (emu->p16v_capture_source != val);
if (change) { if (change) {
emu->p16v_capture_source = val; emu->p16v_capture_source = val;
...@@ -784,6 +786,8 @@ static int snd_p16v_capture_channel_put(struct snd_kcontrol *kcontrol, ...@@ -784,6 +786,8 @@ static int snd_p16v_capture_channel_put(struct snd_kcontrol *kcontrol,
u32 tmp; u32 tmp;
val = ucontrol->value.enumerated.item[0] ; val = ucontrol->value.enumerated.item[0] ;
if (val > 3)
return -EINVAL;
change = (emu->p16v_capture_channel != val); change = (emu->p16v_capture_channel != val);
if (change) { if (change) {
emu->p16v_capture_channel = val; emu->p16v_capture_channel = val;
......
...@@ -1625,19 +1625,26 @@ static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg, ...@@ -1625,19 +1625,26 @@ static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg,
nid = codec->start_nid; nid = codec->start_nid;
for (i = 0; i < codec->num_nodes; i++, nid++) { for (i = 0; i < codec->num_nodes; i++, nid++) {
if (get_wcaps(codec, nid) & AC_WCAP_POWER) { unsigned int wcaps = get_wcaps(codec, nid);
unsigned int pincap; if (wcaps & AC_WCAP_POWER) {
/* unsigned int wid_type = (wcaps & AC_WCAP_TYPE) >>
* don't power down the widget if it controls eapd AC_WCAP_TYPE_SHIFT;
* and EAPD_BTLENABLE is set. if (wid_type == AC_WID_PIN) {
*/ unsigned int pincap;
pincap = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP); /*
if (pincap & AC_PINCAP_EAPD) { * don't power down the widget if it controls
int eapd = snd_hda_codec_read(codec, nid, * eapd and EAPD_BTLENABLE is set.
0, AC_VERB_GET_EAPD_BTLENABLE, 0); */
eapd &= 0x02; pincap = snd_hda_param_read(codec, nid,
if (power_state == AC_PWRST_D3 && eapd) AC_PAR_PIN_CAP);
continue; if (pincap & AC_PINCAP_EAPD) {
int eapd = snd_hda_codec_read(codec,
nid, 0,
AC_VERB_GET_EAPD_BTLENABLE, 0);
eapd &= 0x02;
if (power_state == AC_PWRST_D3 && eapd)
continue;
}
} }
snd_hda_codec_write(codec, nid, 0, snd_hda_codec_write(codec, nid, 0,
AC_VERB_SET_POWER_STATE, AC_VERB_SET_POWER_STATE,
...@@ -2485,13 +2492,14 @@ int snd_hda_multi_out_analog_prepare(struct hda_codec *codec, ...@@ -2485,13 +2492,14 @@ int snd_hda_multi_out_analog_prepare(struct hda_codec *codec,
/* front */ /* front */
snd_hda_codec_setup_stream(codec, nids[HDA_FRONT], stream_tag, snd_hda_codec_setup_stream(codec, nids[HDA_FRONT], stream_tag,
0, format); 0, format);
if (mout->hp_nid && mout->hp_nid != nids[HDA_FRONT]) if (!mout->no_share_stream &&
mout->hp_nid && mout->hp_nid != nids[HDA_FRONT])
/* headphone out will just decode front left/right (stereo) */ /* headphone out will just decode front left/right (stereo) */
snd_hda_codec_setup_stream(codec, mout->hp_nid, stream_tag, snd_hda_codec_setup_stream(codec, mout->hp_nid, stream_tag,
0, format); 0, format);
/* extra outputs copied from front */ /* extra outputs copied from front */
for (i = 0; i < ARRAY_SIZE(mout->extra_out_nid); i++) for (i = 0; i < ARRAY_SIZE(mout->extra_out_nid); i++)
if (mout->extra_out_nid[i]) if (!mout->no_share_stream && mout->extra_out_nid[i])
snd_hda_codec_setup_stream(codec, snd_hda_codec_setup_stream(codec,
mout->extra_out_nid[i], mout->extra_out_nid[i],
stream_tag, 0, format); stream_tag, 0, format);
...@@ -2501,7 +2509,7 @@ int snd_hda_multi_out_analog_prepare(struct hda_codec *codec, ...@@ -2501,7 +2509,7 @@ int snd_hda_multi_out_analog_prepare(struct hda_codec *codec,
if (chs >= (i + 1) * 2) /* independent out */ if (chs >= (i + 1) * 2) /* independent out */
snd_hda_codec_setup_stream(codec, nids[i], stream_tag, snd_hda_codec_setup_stream(codec, nids[i], stream_tag,
i * 2, format); i * 2, format);
else /* copy front */ else if (!mout->no_share_stream) /* copy front */
snd_hda_codec_setup_stream(codec, nids[i], stream_tag, snd_hda_codec_setup_stream(codec, nids[i], stream_tag,
0, format); 0, format);
} }
......
...@@ -220,6 +220,7 @@ struct hda_multi_out { ...@@ -220,6 +220,7 @@ struct hda_multi_out {
hda_nid_t dig_out_nid; /* digital out audio widget */ hda_nid_t dig_out_nid; /* digital out audio widget */
int max_channels; /* currently supported analog channels */ int max_channels; /* currently supported analog channels */
int dig_out_used; /* current usage of digital out (HDA_DIG_XXX) */ int dig_out_used; /* current usage of digital out (HDA_DIG_XXX) */
int no_share_stream; /* don't share a stream with multiple pins */
}; };
int snd_hda_multi_out_dig_open(struct hda_codec *codec, int snd_hda_multi_out_dig_open(struct hda_codec *codec,
......
...@@ -957,6 +957,14 @@ static int patch_ad1986a(struct hda_codec *codec) ...@@ -957,6 +957,14 @@ static int patch_ad1986a(struct hda_codec *codec)
break; break;
} }
/* AD1986A has a hardware problem that it can't share a stream
* with multiple output pins. The copy of front to surrounds
* causes noisy or silent outputs at a certain timing, e.g.
* changing the volume.
* So, let's disable the shared stream.
*/
spec->multiout.no_share_stream = 1;
return 0; return 0;
} }
......
...@@ -111,7 +111,6 @@ struct sigmatel_spec { ...@@ -111,7 +111,6 @@ struct sigmatel_spec {