diff options
| -rw-r--r-- | include/sound/emu10k1.h | 2 | ||||
| -rw-r--r-- | sound/pci/emu10k1/emu10k1_callback.c | 15 | ||||
| -rw-r--r-- | sound/pci/emu10k1/emu10k1_main.c | 6 | ||||
| -rw-r--r-- | sound/pci/emu10k1/emu10k1_synth.c | 45 | ||||
| -rw-r--r-- | sound/pci/emu10k1/io.c | 52 | ||||
| -rw-r--r-- | sound/pci/emu10k1/irq.c | 8 |
6 files changed, 82 insertions, 46 deletions
diff --git a/include/sound/emu10k1.h b/include/sound/emu10k1.h index 494648dd7073..7b7b9b13b4dd 100644 --- a/include/sound/emu10k1.h +++ b/include/sound/emu10k1.h | |||
| @@ -1742,6 +1742,8 @@ struct snd_emu10k1 { | |||
| 1742 | spinlock_t reg_lock; | 1742 | spinlock_t reg_lock; |
| 1743 | spinlock_t emu_lock; | 1743 | spinlock_t emu_lock; |
| 1744 | spinlock_t voice_lock; | 1744 | spinlock_t voice_lock; |
| 1745 | spinlock_t spi_lock; /* serialises access to spi port */ | ||
| 1746 | spinlock_t i2c_lock; /* serialises access to i2c port */ | ||
| 1745 | 1747 | ||
| 1746 | struct snd_emu10k1_voice voices[NUM_G]; | 1748 | struct snd_emu10k1_voice voices[NUM_G]; |
| 1747 | struct snd_emu10k1_voice p16v_voices[4]; | 1749 | struct snd_emu10k1_voice p16v_voices[4]; |
diff --git a/sound/pci/emu10k1/emu10k1_callback.c b/sound/pci/emu10k1/emu10k1_callback.c index 01965bd99966..45088ebcce50 100644 --- a/sound/pci/emu10k1/emu10k1_callback.c +++ b/sound/pci/emu10k1/emu10k1_callback.c | |||
| @@ -35,9 +35,9 @@ struct best_voice { | |||
| 35 | /* | 35 | /* |
| 36 | * prototypes | 36 | * prototypes |
| 37 | */ | 37 | */ |
| 38 | static void lookup_voices(struct snd_emux *emu, struct snd_emu10k1 *hw, | 38 | static void lookup_voices(struct snd_emux *emux, struct snd_emu10k1 *hw, |
| 39 | struct best_voice *best, int active_only); | 39 | struct best_voice *best, int active_only); |
| 40 | static struct snd_emux_voice *get_voice(struct snd_emux *emu, | 40 | static struct snd_emux_voice *get_voice(struct snd_emux *emux, |
| 41 | struct snd_emux_port *port); | 41 | struct snd_emux_port *port); |
| 42 | static int start_voice(struct snd_emux_voice *vp); | 42 | static int start_voice(struct snd_emux_voice *vp); |
| 43 | static void trigger_voice(struct snd_emux_voice *vp); | 43 | static void trigger_voice(struct snd_emux_voice *vp); |
| @@ -45,7 +45,6 @@ static void release_voice(struct snd_emux_voice *vp); | |||
| 45 | static void update_voice(struct snd_emux_voice *vp, int update); | 45 | static void update_voice(struct snd_emux_voice *vp, int update); |
| 46 | static void terminate_voice(struct snd_emux_voice *vp); | 46 | static void terminate_voice(struct snd_emux_voice *vp); |
| 47 | static void free_voice(struct snd_emux_voice *vp); | 47 | static void free_voice(struct snd_emux_voice *vp); |
| 48 | |||
| 49 | static void set_fmmod(struct snd_emu10k1 *hw, struct snd_emux_voice *vp); | 48 | static void set_fmmod(struct snd_emu10k1 *hw, struct snd_emux_voice *vp); |
| 50 | static void set_fm2frq2(struct snd_emu10k1 *hw, struct snd_emux_voice *vp); | 49 | static void set_fm2frq2(struct snd_emu10k1 *hw, struct snd_emux_voice *vp); |
| 51 | static void set_filterQ(struct snd_emu10k1 *hw, struct snd_emux_voice *vp); | 50 | static void set_filterQ(struct snd_emu10k1 *hw, struct snd_emux_voice *vp); |
| @@ -75,9 +74,9 @@ static struct snd_emux_operators emu10k1_ops = { | |||
| 75 | }; | 74 | }; |
| 76 | 75 | ||
| 77 | void | 76 | void |
| 78 | snd_emu10k1_ops_setup(struct snd_emux *emu) | 77 | snd_emu10k1_ops_setup(struct snd_emux *emux) |
| 79 | { | 78 | { |
| 80 | emu->ops = emu10k1_ops; | 79 | emux->ops = emu10k1_ops; |
| 81 | } | 80 | } |
| 82 | 81 | ||
| 83 | 82 | ||
| @@ -166,7 +165,11 @@ free_voice(struct snd_emux_voice *vp) | |||
| 166 | struct snd_emu10k1 *hw; | 165 | struct snd_emu10k1 *hw; |
| 167 | 166 | ||
| 168 | hw = vp->hw; | 167 | hw = vp->hw; |
| 169 | if (vp->ch >= 0) { | 168 | /* FIXME: emu10k1_synth is broken. */ |
| 169 | /* This can get called with hw == 0 */ | ||
| 170 | /* Problem apparent on plug, unplug then plug */ | ||
| 171 | /* on the Audigy 2 ZS Notebook. */ | ||
| 172 | if (hw && (vp->ch >= 0)) { | ||
| 170 | snd_emu10k1_ptr_write(hw, IFATN, vp->ch, 0xff00); | 173 | snd_emu10k1_ptr_write(hw, IFATN, vp->ch, 0xff00); |
| 171 | snd_emu10k1_ptr_write(hw, DCYSUSV, vp->ch, 0x807f | DCYSUSV_CHANNELENABLE_MASK); | 174 | snd_emu10k1_ptr_write(hw, DCYSUSV, vp->ch, 0x807f | DCYSUSV_CHANNELENABLE_MASK); |
| 172 | // snd_emu10k1_ptr_write(hw, DCYSUSV, vp->ch, 0); | 175 | // snd_emu10k1_ptr_write(hw, DCYSUSV, vp->ch, 0); |
diff --git a/sound/pci/emu10k1/emu10k1_main.c b/sound/pci/emu10k1/emu10k1_main.c index 7e46325974a5..f29caf1afe06 100644 --- a/sound/pci/emu10k1/emu10k1_main.c +++ b/sound/pci/emu10k1/emu10k1_main.c | |||
| @@ -259,7 +259,6 @@ static int snd_emu10k1_init(struct snd_emu10k1 *emu, int enable_ir, int resume) | |||
| 259 | * GPIO7: Unknown | 259 | * GPIO7: Unknown |
| 260 | */ | 260 | */ |
| 261 | outl(0x76, emu->port + A_IOCFG); /* Windows uses 0x3f76 */ | 261 | outl(0x76, emu->port + A_IOCFG); /* Windows uses 0x3f76 */ |
| 262 | |||
| 263 | } | 262 | } |
| 264 | if (emu->card_capabilities->i2c_adc) { /* Audigy 2 ZS Notebook with ADC Wolfson WM8775 */ | 263 | if (emu->card_capabilities->i2c_adc) { /* Audigy 2 ZS Notebook with ADC Wolfson WM8775 */ |
| 265 | int size, n; | 264 | int size, n; |
| @@ -275,7 +274,6 @@ static int snd_emu10k1_init(struct snd_emu10k1 *emu, int enable_ir, int resume) | |||
| 275 | emu->i2c_capture_volume[n][0]= 0xcf; | 274 | emu->i2c_capture_volume[n][0]= 0xcf; |
| 276 | emu->i2c_capture_volume[n][1]= 0xcf; | 275 | emu->i2c_capture_volume[n][1]= 0xcf; |
| 277 | } | 276 | } |
| 278 | |||
| 279 | } | 277 | } |
| 280 | 278 | ||
| 281 | 279 | ||
| @@ -653,6 +651,8 @@ static int snd_emu10k1_cardbus_init(struct snd_emu10k1 * emu) | |||
| 653 | value = inl(special_port); | 651 | value = inl(special_port); |
| 654 | 652 | ||
| 655 | snd_emu10k1_ptr20_write(emu, TINA2_VOLUME, 0, 0xfefefefe); /* Defaults to 0x30303030 */ | 653 | snd_emu10k1_ptr20_write(emu, TINA2_VOLUME, 0, 0xfefefefe); /* Defaults to 0x30303030 */ |
| 654 | /* Delay to give time for ADC chip to switch on. It needs 113ms */ | ||
| 655 | msleep(200); | ||
| 656 | return 0; | 656 | return 0; |
| 657 | } | 657 | } |
| 658 | 658 | ||
| @@ -1717,6 +1717,8 @@ int __devinit snd_emu10k1_create(struct snd_card *card, | |||
| 1717 | emu->card = card; | 1717 | emu->card = card; |
| 1718 | spin_lock_init(&emu->reg_lock); | 1718 | spin_lock_init(&emu->reg_lock); |
| 1719 | spin_lock_init(&emu->emu_lock); | 1719 | spin_lock_init(&emu->emu_lock); |
| 1720 | spin_lock_init(&emu->spi_lock); | ||
| 1721 | spin_lock_init(&emu->i2c_lock); | ||
| 1720 | spin_lock_init(&emu->voice_lock); | 1722 | spin_lock_init(&emu->voice_lock); |
| 1721 | spin_lock_init(&emu->synth_lock); | 1723 | spin_lock_init(&emu->synth_lock); |
| 1722 | spin_lock_init(&emu->memblk_lock); | 1724 | spin_lock_init(&emu->memblk_lock); |
diff --git a/sound/pci/emu10k1/emu10k1_synth.c b/sound/pci/emu10k1/emu10k1_synth.c index 204995a1dfbd..ad7b71491fc4 100644 --- a/sound/pci/emu10k1/emu10k1_synth.c +++ b/sound/pci/emu10k1/emu10k1_synth.c | |||
| @@ -30,7 +30,7 @@ MODULE_LICENSE("GPL"); | |||
| 30 | */ | 30 | */ |
| 31 | static int snd_emu10k1_synth_new_device(struct snd_seq_device *dev) | 31 | static int snd_emu10k1_synth_new_device(struct snd_seq_device *dev) |
| 32 | { | 32 | { |
| 33 | struct snd_emux *emu; | 33 | struct snd_emux *emux; |
| 34 | struct snd_emu10k1 *hw; | 34 | struct snd_emu10k1 *hw; |
| 35 | struct snd_emu10k1_synth_arg *arg; | 35 | struct snd_emu10k1_synth_arg *arg; |
| 36 | unsigned long flags; | 36 | unsigned long flags; |
| @@ -46,53 +46,56 @@ static int snd_emu10k1_synth_new_device(struct snd_seq_device *dev) | |||
| 46 | else if (arg->max_voices > 64) | 46 | else if (arg->max_voices > 64) |
| 47 | arg->max_voices = 64; | 47 | arg->max_voices = 64; |
| 48 | 48 | ||
| 49 | if (snd_emux_new(&emu) < 0) | 49 | if (snd_emux_new(&emux) < 0) |
| 50 | return -ENOMEM; | 50 | return -ENOMEM; |
| 51 | 51 | ||
| 52 | snd_emu10k1_ops_setup(emu); | 52 | snd_emu10k1_ops_setup(emux); |
| 53 | emu->hw = hw = arg->hwptr; | 53 | hw = arg->hwptr; |
| 54 | emu->max_voices = arg->max_voices; | 54 | emux->hw = hw; |
| 55 | emu->num_ports = arg->seq_ports; | 55 | emux->max_voices = arg->max_voices; |
| 56 | emu->pitch_shift = -501; | 56 | emux->num_ports = arg->seq_ports; |
| 57 | emu->memhdr = hw->memhdr; | 57 | emux->pitch_shift = -501; |
| 58 | emu->midi_ports = arg->seq_ports < 2 ? arg->seq_ports : 2; /* maximum two ports */ | 58 | emux->memhdr = hw->memhdr; |
| 59 | emu->midi_devidx = hw->audigy ? 2 : 1; /* audigy has two external midis */ | 59 | /* maximum two ports */ |
| 60 | emu->linear_panning = 0; | 60 | emux->midi_ports = arg->seq_ports < 2 ? arg->seq_ports : 2; |
| 61 | emu->hwdep_idx = 2; /* FIXED */ | 61 | /* audigy has two external midis */ |
| 62 | 62 | emux->midi_devidx = hw->audigy ? 2 : 1; | |
| 63 | if (snd_emux_register(emu, dev->card, arg->index, "Emu10k1") < 0) { | 63 | emux->linear_panning = 0; |
| 64 | snd_emux_free(emu); | 64 | emux->hwdep_idx = 2; /* FIXED */ |
| 65 | |||
| 66 | if (snd_emux_register(emux, dev->card, arg->index, "Emu10k1") < 0) { | ||
| 67 | snd_emux_free(emux); | ||
| 65 | return -ENOMEM; | 68 | return -ENOMEM; |
| 66 | } | 69 | } |
| 67 | 70 | ||
| 68 | spin_lock_irqsave(&hw->voice_lock, flags); | 71 | spin_lock_irqsave(&hw->voice_lock, flags); |
| 69 | hw->synth = emu; | 72 | hw->synth = emux; |
| 70 | hw->get_synth_voice = snd_emu10k1_synth_get_voice; | 73 | hw->get_synth_voice = snd_emu10k1_synth_get_voice; |
| 71 | spin_unlock_irqrestore(&hw->voice_lock, flags); | 74 | spin_unlock_irqrestore(&hw->voice_lock, flags); |
| 72 | 75 | ||
| 73 | dev->driver_data = emu; | 76 | dev->driver_data = emux; |
| 74 | 77 | ||
| 75 | return 0; | 78 | return 0; |
| 76 | } | 79 | } |
| 77 | 80 | ||
| 78 | static int snd_emu10k1_synth_delete_device(struct snd_seq_device *dev) | 81 | static int snd_emu10k1_synth_delete_device(struct snd_seq_device *dev) |
| 79 | { | 82 | { |
| 80 | struct snd_emux *emu; | 83 | struct snd_emux *emux; |
| 81 | struct snd_emu10k1 *hw; | 84 | struct snd_emu10k1 *hw; |
| 82 | unsigned long flags; | 85 | unsigned long flags; |
| 83 | 86 | ||
| 84 | if (dev->driver_data == NULL) | 87 | if (dev->driver_data == NULL) |
| 85 | return 0; /* not registered actually */ | 88 | return 0; /* not registered actually */ |
| 86 | 89 | ||
| 87 | emu = dev->driver_data; | 90 | emux = dev->driver_data; |
| 88 | 91 | ||
| 89 | hw = emu->hw; | 92 | hw = emux->hw; |
| 90 | spin_lock_irqsave(&hw->voice_lock, flags); | 93 | spin_lock_irqsave(&hw->voice_lock, flags); |
| 91 | hw->synth = NULL; | 94 | hw->synth = NULL; |
| 92 | hw->get_synth_voice = NULL; | 95 | hw->get_synth_voice = NULL; |
| 93 | spin_unlock_irqrestore(&hw->voice_lock, flags); | 96 | spin_unlock_irqrestore(&hw->voice_lock, flags); |
| 94 | 97 | ||
| 95 | snd_emux_free(emu); | 98 | snd_emux_free(emux); |
| 96 | return 0; | 99 | return 0; |
| 97 | } | 100 | } |
| 98 | 101 | ||
diff --git a/sound/pci/emu10k1/io.c b/sound/pci/emu10k1/io.c index a02638350a0a..b5a802bdeb7c 100644 --- a/sound/pci/emu10k1/io.c +++ b/sound/pci/emu10k1/io.c | |||
| @@ -70,6 +70,11 @@ void snd_emu10k1_ptr_write(struct snd_emu10k1 *emu, unsigned int reg, unsigned i | |||
| 70 | unsigned long flags; | 70 | unsigned long flags; |
| 71 | unsigned int mask; | 71 | unsigned int mask; |
| 72 | 72 | ||
| 73 | if (!emu) { | ||
| 74 | snd_printk(KERN_ERR "ptr_write: emu is null!\n"); | ||
| 75 | dump_stack(); | ||
| 76 | return; | ||
| 77 | } | ||
| 73 | mask = emu->audigy ? A_PTR_ADDRESS_MASK : PTR_ADDRESS_MASK; | 78 | mask = emu->audigy ? A_PTR_ADDRESS_MASK : PTR_ADDRESS_MASK; |
| 74 | regptr = ((reg << 16) & mask) | (chn & PTR_CHANNELNUM_MASK); | 79 | regptr = ((reg << 16) & mask) | (chn & PTR_CHANNELNUM_MASK); |
| 75 | 80 | ||
| @@ -134,15 +139,23 @@ int snd_emu10k1_spi_write(struct snd_emu10k1 * emu, | |||
| 134 | unsigned int reset, set; | 139 | unsigned int reset, set; |
| 135 | unsigned int reg, tmp; | 140 | unsigned int reg, tmp; |
| 136 | int n, result; | 141 | int n, result; |
| 142 | int err = 0; | ||
| 143 | |||
| 144 | /* This function is not re-entrant, so protect against it. */ | ||
| 145 | spin_lock(&emu->spi_lock); | ||
| 137 | if (emu->card_capabilities->ca0108_chip) | 146 | if (emu->card_capabilities->ca0108_chip) |
| 138 | reg = 0x3c; /* PTR20, reg 0x3c */ | 147 | reg = 0x3c; /* PTR20, reg 0x3c */ |
| 139 | else { | 148 | else { |
| 140 | /* For other chip types the SPI register | 149 | /* For other chip types the SPI register |
| 141 | * is currently unknown. */ | 150 | * is currently unknown. */ |
| 142 | return 1; | 151 | err = 1; |
| 152 | goto spi_write_exit; | ||
| 153 | } | ||
| 154 | if (data > 0xffff) { | ||
| 155 | /* Only 16bit values allowed */ | ||
| 156 | err = 1; | ||
| 157 | goto spi_write_exit; | ||
| 143 | } | 158 | } |
| 144 | if (data > 0xffff) /* Only 16bit values allowed */ | ||
| 145 | return 1; | ||
| 146 | 159 | ||
| 147 | tmp = snd_emu10k1_ptr20_read(emu, reg, 0); | 160 | tmp = snd_emu10k1_ptr20_read(emu, reg, 0); |
| 148 | reset = (tmp & ~0x3ffff) | 0x20000; /* Set xxx20000 */ | 161 | reset = (tmp & ~0x3ffff) | 0x20000; /* Set xxx20000 */ |
| @@ -160,11 +173,17 @@ int snd_emu10k1_spi_write(struct snd_emu10k1 * emu, | |||
| 160 | break; | 173 | break; |
| 161 | } | 174 | } |
| 162 | } | 175 | } |
| 163 | if (result) /* Timed out */ | 176 | if (result) { |
| 164 | return 1; | 177 | /* Timed out */ |
| 178 | err = 1; | ||
| 179 | goto spi_write_exit; | ||
| 180 | } | ||
| 165 | snd_emu10k1_ptr20_write(emu, reg, 0, reset | data); | 181 | snd_emu10k1_ptr20_write(emu, reg, 0, reset | data); |
| 166 | tmp = snd_emu10k1_ptr20_read(emu, reg, 0); /* Write post */ | 182 | tmp = snd_emu10k1_ptr20_read(emu, reg, 0); /* Write post */ |
| 167 | return 0; | 183 | err = 0; |
| 184 | spi_write_exit: | ||
| 185 | spin_unlock(&emu->spi_lock); | ||
| 186 | return err; | ||
| 168 | } | 187 | } |
| 169 | 188 | ||
| 170 | /* The ADC does not support i2c read, so only write is implemented */ | 189 | /* The ADC does not support i2c read, so only write is implemented */ |
| @@ -176,15 +195,17 @@ int snd_emu10k1_i2c_write(struct snd_emu10k1 *emu, | |||
| 176 | int timeout = 0; | 195 | int timeout = 0; |
| 177 | int status; | 196 | int status; |
| 178 | int retry; | 197 | int retry; |
| 198 | int err = 0; | ||
| 199 | |||
| 179 | if ((reg > 0x7f) || (value > 0x1ff)) { | 200 | if ((reg > 0x7f) || (value > 0x1ff)) { |
| 180 | snd_printk(KERN_ERR "i2c_write: invalid values.\n"); | 201 | snd_printk(KERN_ERR "i2c_write: invalid values.\n"); |
| 181 | return -EINVAL; | 202 | return -EINVAL; |
| 182 | } | 203 | } |
| 183 | 204 | ||
| 205 | /* This function is not re-entrant, so protect against it. */ | ||
| 206 | spin_lock(&emu->i2c_lock); | ||
| 207 | |||
| 184 | tmp = reg << 25 | value << 16; | 208 | tmp = reg << 25 | value << 16; |
| 185 | // snd_printk("I2C-write:reg=0x%x, value=0x%x\n", reg, value); | ||
| 186 | /* Not sure what this I2C channel controls. */ | ||
| 187 | /* snd_emu10k1_ptr_write(emu, P17V_I2C_0, 0, tmp); */ | ||
| 188 | 209 | ||
| 189 | /* This controls the I2C connected to the WM8775 ADC Codec */ | 210 | /* This controls the I2C connected to the WM8775 ADC Codec */ |
| 190 | snd_emu10k1_ptr20_write(emu, P17V_I2C_1, 0, tmp); | 211 | snd_emu10k1_ptr20_write(emu, P17V_I2C_1, 0, tmp); |
| @@ -192,17 +213,14 @@ int snd_emu10k1_i2c_write(struct snd_emu10k1 *emu, | |||
| 192 | 213 | ||
| 193 | for (retry = 0; retry < 10; retry++) { | 214 | for (retry = 0; retry < 10; retry++) { |
| 194 | /* Send the data to i2c */ | 215 | /* Send the data to i2c */ |
| 195 | //tmp = snd_emu10k1_ptr_read(emu, P17V_I2C_ADDR, 0); | ||
| 196 | //tmp = tmp & ~(I2C_A_ADC_READ|I2C_A_ADC_LAST|I2C_A_ADC_START|I2C_A_ADC_ADD_MASK); | ||
| 197 | tmp = 0; | 216 | tmp = 0; |
| 198 | tmp = tmp | (I2C_A_ADC_LAST|I2C_A_ADC_START|I2C_A_ADC_ADD); | 217 | tmp = tmp | (I2C_A_ADC_LAST|I2C_A_ADC_START|I2C_A_ADC_ADD); |
| 199 | snd_emu10k1_ptr20_write(emu, P17V_I2C_ADDR, 0, tmp); | 218 | snd_emu10k1_ptr20_write(emu, P17V_I2C_ADDR, 0, tmp); |
| 200 | 219 | ||
| 201 | /* Wait till the transaction ends */ | 220 | /* Wait till the transaction ends */ |
| 202 | while (1) { | 221 | while (1) { |
| 203 | udelay(10); | 222 | mdelay(1); |
| 204 | status = snd_emu10k1_ptr20_read(emu, P17V_I2C_ADDR, 0); | 223 | status = snd_emu10k1_ptr20_read(emu, P17V_I2C_ADDR, 0); |
| 205 | // snd_printk("I2C:status=0x%x\n", status); | ||
| 206 | timeout++; | 224 | timeout++; |
| 207 | if ((status & I2C_A_ADC_START) == 0) | 225 | if ((status & I2C_A_ADC_START) == 0) |
| 208 | break; | 226 | break; |
| @@ -219,10 +237,14 @@ int snd_emu10k1_i2c_write(struct snd_emu10k1 *emu, | |||
| 219 | 237 | ||
| 220 | if (retry == 10) { | 238 | if (retry == 10) { |
| 221 | snd_printk(KERN_ERR "Writing to ADC failed!\n"); | 239 | snd_printk(KERN_ERR "Writing to ADC failed!\n"); |
| 222 | return -EINVAL; | 240 | snd_printk(KERN_ERR "status=0x%x, reg=%d, value=%d\n", |
| 241 | status, reg, value); | ||
| 242 | /* dump_stack(); */ | ||
| 243 | err = -EINVAL; | ||
| 223 | } | 244 | } |
| 224 | 245 | ||
| 225 | return 0; | 246 | spin_unlock(&emu->i2c_lock); |
| 247 | return err; | ||
| 226 | } | 248 | } |
| 227 | 249 | ||
| 228 | int snd_emu1010_fpga_write(struct snd_emu10k1 * emu, u32 reg, u32 value) | 250 | int snd_emu1010_fpga_write(struct snd_emu10k1 * emu, u32 reg, u32 value) |
diff --git a/sound/pci/emu10k1/irq.c b/sound/pci/emu10k1/irq.c index 276d08c88f91..30bfed6f8339 100644 --- a/sound/pci/emu10k1/irq.c +++ b/sound/pci/emu10k1/irq.c | |||
| @@ -34,9 +34,10 @@ irqreturn_t snd_emu10k1_interrupt(int irq, void *dev_id) | |||
| 34 | struct snd_emu10k1 *emu = dev_id; | 34 | struct snd_emu10k1 *emu = dev_id; |
| 35 | unsigned int status, status2, orig_status, orig_status2; | 35 | unsigned int status, status2, orig_status, orig_status2; |
| 36 | int handled = 0; | 36 | int handled = 0; |
| 37 | int timeout = 0; | ||
| 37 | 38 | ||
| 38 | while ((status = inl(emu->port + IPR)) != 0) { | 39 | while (((status = inl(emu->port + IPR)) != 0) && (timeout < 1000)) { |
| 39 | //snd_printk(KERN_INFO "emu10k1 irq - status = 0x%x\n", status); | 40 | timeout++; |
| 40 | orig_status = status; | 41 | orig_status = status; |
| 41 | handled = 1; | 42 | handled = 1; |
| 42 | if ((status & 0xffffffff) == 0xffffffff) { | 43 | if ((status & 0xffffffff) == 0xffffffff) { |
| @@ -200,5 +201,8 @@ irqreturn_t snd_emu10k1_interrupt(int irq, void *dev_id) | |||
| 200 | } | 201 | } |
| 201 | outl(orig_status, emu->port + IPR); /* ack all */ | 202 | outl(orig_status, emu->port + IPR); /* ack all */ |
| 202 | } | 203 | } |
| 204 | if (timeout == 1000) | ||
| 205 | snd_printk(KERN_INFO "emu10k1 irq routine failure\n"); | ||
| 206 | |||
| 203 | return IRQ_RETVAL(handled); | 207 | return IRQ_RETVAL(handled); |
| 204 | } | 208 | } |
