aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/cx88/cx88-alsa.c
diff options
context:
space:
mode:
authorTrent Piepho <xyzzy@speakeasy.org>2007-08-18 21:09:42 -0400
committerMauro Carvalho Chehab <mchehab@infradead.org>2007-10-09 21:05:55 -0400
commit59fd8f8d8ee9f7539758419965381bcccfa6f798 (patch)
tree314a527b8adea2dc3460d933322832de9a58269d /drivers/media/video/cx88/cx88-alsa.c
parent5ba862b77e2d7f9e6e2cb133c43be32ac612aea5 (diff)
V4L/DVB (6066): cx88-alsa: Change order of interrupt enabling, fix spurious IRQs
Currently the driver turns on audio interrupts, then sets the audio interrupt mask to select which interrupts to get. One could received unwanted interrupts since the mask is set _after_ interrupts have already been turned on. Change the order of the operations, and clear any audio interrupt status bits that are already set for good measure. Before changing the SRAM FIFO parameters, make sure the FIFO isn't being used. This shouldn't happen with just the ALSA driver, as it should never try to turn on FIFO/RISC/DMA while they are already on. However, the V4L driver needs to turn the audio FIFO on for analog audio output to work (undocumented cx88 bug). The FIFO parameters are in an inconsistent state while they are updated, and this results in many FIFO sync error IRQs if the FIFO is in use while it's in this inconsistent state. Also create and use a bunch of symbolic constants for audio interrupt mask bits. Signed-off-by: Trent Piepho <xyzzy@speakeasy.org> Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Diffstat (limited to 'drivers/media/video/cx88/cx88-alsa.c')
-rw-r--r--drivers/media/video/cx88/cx88-alsa.c42
1 files changed, 20 insertions, 22 deletions
diff --git a/drivers/media/video/cx88/cx88-alsa.c b/drivers/media/video/cx88/cx88-alsa.c
index 76a8c01208c1..ecb9a74ae03d 100644
--- a/drivers/media/video/cx88/cx88-alsa.c
+++ b/drivers/media/video/cx88/cx88-alsa.c
@@ -136,12 +136,11 @@ static int _cx88_start_audio_dma(snd_cx88_card_t *chip)
136 struct cx88_core *core=chip->core; 136 struct cx88_core *core=chip->core;
137 struct sram_channel *audio_ch = &cx88_sram_channels[SRAM_CH25]; 137 struct sram_channel *audio_ch = &cx88_sram_channels[SRAM_CH25];
138 138
139 139 /* Make sure RISC/FIFO are off before changing FIFO/RISC settings */
140 dprintk(1, "Starting audio DMA for %i bytes/line and %i (%i) lines at address %08x\n",buf->bpl, chip->num_periods, audio_ch->fifo_size / buf->bpl, audio_ch->fifo_start); 140 cx_clear(MO_AUD_DMACNTRL, 0x11);
141 141
142 /* setup fifo + format - out channel */ 142 /* setup fifo + format - out channel */
143 cx88_sram_channel_setup(chip->core, &cx88_sram_channels[SRAM_CH25], 143 cx88_sram_channel_setup(chip->core, audio_ch, buf->bpl, buf->risc.dma);
144 buf->bpl, buf->risc.dma);
145 144
146 /* sets bpl size */ 145 /* sets bpl size */
147 cx_write(MO_AUDD_LNGTH, buf->bpl); 146 cx_write(MO_AUDD_LNGTH, buf->bpl);
@@ -149,27 +148,30 @@ static int _cx88_start_audio_dma(snd_cx88_card_t *chip)
149 /* reset counter */ 148 /* reset counter */
150 cx_write(MO_AUDD_GPCNTRL,GP_COUNT_CONTROL_RESET); 149 cx_write(MO_AUDD_GPCNTRL,GP_COUNT_CONTROL_RESET);
151 150
151 dprintk(1, "Start audio DMA, %d B/line, %d lines/FIFO, %d lines/irq, "
152 "%d B/irq\n", buf->bpl, cx_read(audio_ch->cmds_start + 8)>>1,
153 chip->num_periods, buf->bpl * chip->num_periods);
154
152 dprintk(1, "Enabling IRQ, setting mask from 0x%x to 0x%x\n", 155 dprintk(1, "Enabling IRQ, setting mask from 0x%x to 0x%x\n",
153 chip->core->pci_irqmask, 156 chip->core->pci_irqmask,
154 chip->core->pci_irqmask | PCI_INT_AUDINT); 157 chip->core->pci_irqmask | PCI_INT_AUDINT);
155 /* enable irqs */
156 cx_set(MO_PCI_INTMSK, chip->core->pci_irqmask | PCI_INT_AUDINT);
157
158 158
159 /* Enables corresponding bits at AUD_INT_STAT */ 159 /* Enables corresponding bits at AUD_INT_STAT */
160 cx_write(MO_AUD_INTMSK, 160 cx_write(MO_AUD_INTMSK, AUD_INT_OPC_ERR | AUD_INT_DN_SYNC |
161 (1<<16)| 161 AUD_INT_DN_RISCI2 | AUD_INT_DN_RISCI1);
162 (1<<12)| 162
163 (1<<4)| 163 /* Clean any pending interrupt bits already set */
164 (1<<0) 164 cx_write(MO_AUD_INTSTAT, ~0);
165 ); 165
166 /* enable audio irqs */
167 cx_set(MO_PCI_INTMSK, chip->core->pci_irqmask | PCI_INT_AUDINT);
166 168
167 /* start dma */ 169 /* start dma */
168 cx_set(MO_DEV_CNTRL2, (1<<5)); /* Enables Risc Processor */ 170 cx_set(MO_DEV_CNTRL2, (1<<5)); /* Enables Risc Processor */
169 cx_set(MO_AUD_DMACNTRL, 0x11); /* audio downstream FIFO and RISC enable */ 171 cx_set(MO_AUD_DMACNTRL, 0x11); /* audio downstream FIFO and RISC enable */
170 172
171 if (debug) 173 if (debug)
172 cx88_sram_channel_dump(chip->core, &cx88_sram_channels[SRAM_CH25]); 174 cx88_sram_channel_dump(chip->core, audio_ch);
173 175
174 return 0; 176 return 0;
175} 177}
@@ -187,12 +189,8 @@ static int _cx88_stop_audio_dma(snd_cx88_card_t *chip)
187 189
188 /* disable irqs */ 190 /* disable irqs */
189 cx_clear(MO_PCI_INTMSK, PCI_INT_AUDINT); 191 cx_clear(MO_PCI_INTMSK, PCI_INT_AUDINT);
190 cx_clear(MO_AUD_INTMSK, 192 cx_clear(MO_AUD_INTMSK, AUD_INT_OPC_ERR | AUD_INT_DN_SYNC |
191 (1<<16)| 193 AUD_INT_DN_RISCI2 | AUD_INT_DN_RISCI1);
192 (1<<12)|
193 (1<<4)|
194 (1<<0)
195 );
196 194
197 if (debug) 195 if (debug)
198 cx88_sram_channel_dump(chip->core, &cx88_sram_channels[SRAM_CH25]); 196 cx88_sram_channel_dump(chip->core, &cx88_sram_channels[SRAM_CH25]);
@@ -239,14 +237,14 @@ static void cx8801_aud_irq(snd_cx88_card_t *chip)
239 cx88_aud_irqs, ARRAY_SIZE(cx88_aud_irqs), 237 cx88_aud_irqs, ARRAY_SIZE(cx88_aud_irqs),
240 status, mask); 238 status, mask);
241 /* risc op code error */ 239 /* risc op code error */
242 if (status & (1 << 16)) { 240 if (status & AUD_INT_OPC_ERR) {
243 printk(KERN_WARNING "%s/0: audio risc op code error\n",core->name); 241 printk(KERN_WARNING "%s/0: audio risc op code error\n",core->name);
244 cx_clear(MO_AUD_DMACNTRL, 0x11); 242 cx_clear(MO_AUD_DMACNTRL, 0x11);
245 cx88_sram_channel_dump(core, &cx88_sram_channels[SRAM_CH25]); 243 cx88_sram_channel_dump(core, &cx88_sram_channels[SRAM_CH25]);
246 } 244 }
247 245
248 /* risc1 downstream */ 246 /* risc1 downstream */
249 if (status & 0x01) { 247 if (status & AUD_INT_DN_RISCI1) {
250 spin_lock(&chip->reg_lock); 248 spin_lock(&chip->reg_lock);
251 count = cx_read(MO_AUDD_GPCNT); 249 count = cx_read(MO_AUDD_GPCNT);
252 spin_unlock(&chip->reg_lock); 250 spin_unlock(&chip->reg_lock);