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 {
unsigned int alt_switch: 1; unsigned int alt_switch: 1;
unsigned int hp_detect: 1; unsigned int hp_detect: 1;
unsigned int gpio_mute: 1; unsigned int gpio_mute: 1;
unsigned int no_vol_knob :1;
unsigned int gpio_mask, gpio_data; unsigned int gpio_mask, gpio_data;
...@@ -342,42 +341,6 @@ static int stac92xx_aloopback_put(struct snd_kcontrol *kcontrol, ...@@ -342,42 +341,6 @@ static int stac92xx_aloopback_put(struct snd_kcontrol *kcontrol,
return 1; return 1;
} }
static int stac92xx_volknob_info(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = 1;
uinfo->value.integer.min = 0;
uinfo->value.integer.max = 127;
return 0;
}
static int stac92xx_volknob_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
ucontrol->value.integer.value[0] = kcontrol->private_value & 0xff;
return 0;
}
static int stac92xx_volknob_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
unsigned int val = kcontrol->private_value & 0xff;
if (val == ucontrol->value.integer.value[0])
return 0;
val = ucontrol->value.integer.value[0];
kcontrol->private_value &= ~0xff;
kcontrol->private_value |= val;
snd_hda_codec_write_cache(codec, kcontrol->private_value >> 16, 0,
AC_VERB_SET_VOLUME_KNOB_CONTROL, val | 0x80);
return 1;
}
static struct hda_verb stac9200_core_init[] = { static struct hda_verb stac9200_core_init[] = {
/* set dac0mux for dac converter */ /* set dac0mux for dac converter */
{ 0x07, AC_VERB_SET_CONNECT_SEL, 0x00}, { 0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
...@@ -446,18 +409,6 @@ static struct hda_verb stac9205_core_init[] = { ...@@ -446,18 +409,6 @@ static struct hda_verb stac9205_core_init[] = {
.private_value = verb_read | (verb_write << 16), \ .private_value = verb_read | (verb_write << 16), \
} }
#define STAC_VOLKNOB(knob_nid) \
{ \
.iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
.name = "Master Playback Volume", \
.count = 1, \
.info = stac92xx_volknob_info, \
.get = stac92xx_volknob_get, \
.put = stac92xx_volknob_put, \
.private_value = 127 | (knob_nid << 16), \
}
static struct snd_kcontrol_new stac9200_mixer[] = { static struct snd_kcontrol_new stac9200_mixer[] = {
HDA_CODEC_VOLUME("Master Playback Volume", 0xb, 0, HDA_OUTPUT), HDA_CODEC_VOLUME("Master Playback Volume", 0xb, 0, HDA_OUTPUT),
HDA_CODEC_MUTE("Master Playback Switch", 0xb, 0, HDA_OUTPUT), HDA_CODEC_MUTE("Master Playback Switch", 0xb, 0, HDA_OUTPUT),
...@@ -487,7 +438,6 @@ static struct snd_kcontrol_new stac9205_mixer[] = { ...@@ -487,7 +438,6 @@ static struct snd_kcontrol_new stac9205_mixer[] = {
}, },
STAC_INPUT_SOURCE(2), STAC_INPUT_SOURCE(2),
STAC_ANALOG_LOOPBACK(0xFE0, 0x7E0), STAC_ANALOG_LOOPBACK(0xFE0, 0x7E0),
STAC_VOLKNOB(0x24),
HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x1b, 0x0, HDA_INPUT), HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x1b, 0x0, HDA_INPUT),
HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x1d, 0x0, HDA_OUTPUT), HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x1d, 0x0, HDA_OUTPUT),
...@@ -503,7 +453,6 @@ static struct snd_kcontrol_new stac9205_mixer[] = { ...@@ -503,7 +453,6 @@ static struct snd_kcontrol_new stac9205_mixer[] = {
/* This needs to be generated dynamically based on sequence */ /* This needs to be generated dynamically based on sequence */
static struct snd_kcontrol_new stac922x_mixer[] = { static struct snd_kcontrol_new stac922x_mixer[] = {
STAC_INPUT_SOURCE(2), STAC_INPUT_SOURCE(2),
STAC_VOLKNOB(0x16),
HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x17, 0x0, HDA_INPUT), HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x17, 0x0, HDA_INPUT),
HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x17, 0x0, HDA_INPUT), HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x17, 0x0, HDA_INPUT),
HDA_CODEC_VOLUME_IDX("Mux Capture Volume", 0x0, 0x12, 0x0, HDA_OUTPUT), HDA_CODEC_VOLUME_IDX("Mux Capture Volume", 0x0, 0x12, 0x0, HDA_OUTPUT),
...@@ -517,7 +466,6 @@ static struct snd_kcontrol_new stac922x_mixer[] = { ...@@ -517,7 +466,6 @@ static struct snd_kcontrol_new stac922x_mixer[] = {
static struct snd_kcontrol_new stac927x_mixer[] = { static struct snd_kcontrol_new stac927x_mixer[] = {
STAC_INPUT_SOURCE(3), STAC_INPUT_SOURCE(3),
STAC_VOLKNOB(0x24),
STAC_ANALOG_LOOPBACK(0xFEB, 0x7EB), STAC_ANALOG_LOOPBACK(0xFEB, 0x7EB),
HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x18, 0x0, HDA_INPUT), HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x18, 0x0, HDA_INPUT),
...@@ -1931,8 +1879,7 @@ static int stac92xx_auto_create_hp_ctls(struct hda_codec *codec, ...@@ -1931,8 +1879,7 @@ static int stac92xx_auto_create_hp_ctls(struct hda_codec *codec,
} }
if (spec->multiout.hp_nid) { if (spec->multiout.hp_nid) {
const char *pfx; const char *pfx;
if (old_num_dacs == spec->multiout.num_dacs && if (old_num_dacs == spec->multiout.num_dacs)
spec->no_vol_knob)
pfx = "Master"; pfx = "Master";
else else
pfx = "Headphone"; pfx = "Headphone";
...@@ -2489,7 +2436,6 @@ static int patch_stac9200(struct hda_codec *codec) ...@@ -2489,7 +2436,6 @@ static int patch_stac9200(struct hda_codec *codec)
codec->spec = spec; codec->spec = spec;
spec->num_pins = ARRAY_SIZE(stac9200_pin_nids); spec->num_pins = ARRAY_SIZE(stac9200_pin_nids);
spec->pin_nids = stac9200_pin_nids; spec->pin_nids = stac9200_pin_nids;
spec->no_vol_knob = 1;
spec->board_config = snd_hda_check_board_config(codec, STAC_9200_MODELS, spec->board_config = snd_hda_check_board_config(codec, STAC_9200_MODELS,
stac9200_models, stac9200_models,
stac9200_cfg_tbl); stac9200_cfg_tbl);
...@@ -2544,7 +2490,6 @@ static int patch_stac925x(struct hda_codec *codec) ...@@ -2544,7 +2490,6 @@ static int patch_stac925x(struct hda_codec *codec)
codec->spec = spec; codec->spec = spec;
spec->num_pins = ARRAY_SIZE(stac925x_pin_nids); spec->num_pins = ARRAY_SIZE(stac925x_pin_nids);
spec->pin_nids = stac925x_pin_nids; spec->pin_nids = stac925x_pin_nids;
spec->no_vol_knob = 1;
spec->board_config = snd_hda_check_board_config(codec, STAC_925x_MODELS, spec->board_config = snd_hda_check_board_config(codec, STAC_925x_MODELS,
stac925x_models, stac925x_models,
stac925x_cfg_tbl); stac925x_cfg_tbl);
......
...@@ -725,7 +725,8 @@ static int cs4270_probe(struct platform_device *pdev) ...@@ -725,7 +725,8 @@ static int cs4270_probe(struct platform_device *pdev)
codec->owner = THIS_MODULE; codec->owner = THIS_MODULE;
codec->dai = &cs4270_dai; codec->dai = &cs4270_dai;
codec->num_dai = 1; codec->num_dai = 1;
codec->private_data = codec + ALIGN(sizeof(struct snd_soc_codec), 4); codec->private_data = (void *) codec +
ALIGN(sizeof(struct snd_soc_codec), 4);
socdev->codec = codec; socdev->codec = codec;
......
...@@ -32,7 +32,7 @@ ...@@ -32,7 +32,7 @@
#include <asm/hardware.h> #include <asm/hardware.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/arch/regs-ac97.h> #include <asm/plat-s3c/regs-ac97.h>
#include <asm/arch/regs-gpio.h> #include <asm/arch/regs-gpio.h>
#include <asm/arch/regs-clock.h> #include <asm/arch/regs-clock.h>
#include <asm/arch/audio.h> #include <asm/arch/audio.h>
......
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