~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/sound/pci/emu10k1/irq.c

Version: ~ [ linux-5.6-rc1 ] ~ [ linux-5.5.2 ] ~ [ linux-5.4.17 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.102 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.170 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.213 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.213 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.140 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.81 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-3.9.11 ] ~ [ linux-3.8.13 ] ~ [ linux-3.7.10 ] ~ [ linux-3.6.11 ] ~ [ linux-3.5.7 ] ~ [ linux-3.4.113 ] ~ [ linux-3.3.8 ] ~ [ linux-3.2.102 ] ~ [ linux-3.1.10 ] ~ [ linux-3.0.101 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2  *  Copyright (c) by Jaroslav Kysela <perex@perex.cz>
  3  *                   Creative Labs, Inc.
  4  *  Routines for IRQ control of EMU10K1 chips
  5  *
  6  *  BUGS:
  7  *    --
  8  *
  9  *  TODO:
 10  *    --
 11  *
 12  *   This program is free software; you can redistribute it and/or modify
 13  *   it under the terms of the GNU General Public License as published by
 14  *   the Free Software Foundation; either version 2 of the License, or
 15  *   (at your option) any later version.
 16  *
 17  *   This program is distributed in the hope that it will be useful,
 18  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 19  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 20  *   GNU General Public License for more details.
 21  *
 22  *   You should have received a copy of the GNU General Public License
 23  *   along with this program; if not, write to the Free Software
 24  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
 25  *
 26  */
 27 
 28 #include <linux/time.h>
 29 #include <sound/core.h>
 30 #include <sound/emu10k1.h>
 31 
 32 irqreturn_t snd_emu10k1_interrupt(int irq, void *dev_id)
 33 {
 34         struct snd_emu10k1 *emu = dev_id;
 35         unsigned int status, status2, orig_status, orig_status2;
 36         int handled = 0;
 37         int timeout = 0;
 38 
 39         while (((status = inl(emu->port + IPR)) != 0) && (timeout < 1000)) {
 40                 timeout++;
 41                 orig_status = status;
 42                 handled = 1;
 43                 if ((status & 0xffffffff) == 0xffffffff) {
 44                         dev_info(emu->card->dev,
 45                                  "Suspected sound card removal\n");
 46                         break;
 47                 }
 48                 if (status & IPR_PCIERROR) {
 49                         dev_err(emu->card->dev, "interrupt: PCI error\n");
 50                         snd_emu10k1_intr_disable(emu, INTE_PCIERRORENABLE);
 51                         status &= ~IPR_PCIERROR;
 52                 }
 53                 if (status & (IPR_VOLINCR|IPR_VOLDECR|IPR_MUTE)) {
 54                         if (emu->hwvol_interrupt)
 55                                 emu->hwvol_interrupt(emu, status);
 56                         else
 57                                 snd_emu10k1_intr_disable(emu, INTE_VOLINCRENABLE|INTE_VOLDECRENABLE|INTE_MUTEENABLE);
 58                         status &= ~(IPR_VOLINCR|IPR_VOLDECR|IPR_MUTE);
 59                 }
 60                 if (status & IPR_CHANNELLOOP) {
 61                         int voice;
 62                         int voice_max = status & IPR_CHANNELNUMBERMASK;
 63                         u32 val;
 64                         struct snd_emu10k1_voice *pvoice = emu->voices;
 65 
 66                         val = snd_emu10k1_ptr_read(emu, CLIPL, 0);
 67                         for (voice = 0; voice <= voice_max; voice++) {
 68                                 if (voice == 0x20)
 69                                         val = snd_emu10k1_ptr_read(emu, CLIPH, 0);
 70                                 if (val & 1) {
 71                                         if (pvoice->use && pvoice->interrupt != NULL) {
 72                                                 pvoice->interrupt(emu, pvoice);
 73                                                 snd_emu10k1_voice_intr_ack(emu, voice);
 74                                         } else {
 75                                                 snd_emu10k1_voice_intr_disable(emu, voice);
 76                                         }
 77                                 }
 78                                 val >>= 1;
 79                                 pvoice++;
 80                         }
 81                         val = snd_emu10k1_ptr_read(emu, HLIPL, 0);
 82                         for (voice = 0; voice <= voice_max; voice++) {
 83                                 if (voice == 0x20)
 84                                         val = snd_emu10k1_ptr_read(emu, HLIPH, 0);
 85                                 if (val & 1) {
 86                                         if (pvoice->use && pvoice->interrupt != NULL) {
 87                                                 pvoice->interrupt(emu, pvoice);
 88                                                 snd_emu10k1_voice_half_loop_intr_ack(emu, voice);
 89                                         } else {
 90                                                 snd_emu10k1_voice_half_loop_intr_disable(emu, voice);
 91                                         }
 92                                 }
 93                                 val >>= 1;
 94                                 pvoice++;
 95                         }
 96                         status &= ~IPR_CHANNELLOOP;
 97                 }
 98                 status &= ~IPR_CHANNELNUMBERMASK;
 99                 if (status & (IPR_ADCBUFFULL|IPR_ADCBUFHALFFULL)) {
100                         if (emu->capture_interrupt)
101                                 emu->capture_interrupt(emu, status);
102                         else
103                                 snd_emu10k1_intr_disable(emu, INTE_ADCBUFENABLE);
104                         status &= ~(IPR_ADCBUFFULL|IPR_ADCBUFHALFFULL);
105                 }
106                 if (status & (IPR_MICBUFFULL|IPR_MICBUFHALFFULL)) {
107                         if (emu->capture_mic_interrupt)
108                                 emu->capture_mic_interrupt(emu, status);
109                         else
110                                 snd_emu10k1_intr_disable(emu, INTE_MICBUFENABLE);
111                         status &= ~(IPR_MICBUFFULL|IPR_MICBUFHALFFULL);
112                 }
113                 if (status & (IPR_EFXBUFFULL|IPR_EFXBUFHALFFULL)) {
114                         if (emu->capture_efx_interrupt)
115                                 emu->capture_efx_interrupt(emu, status);
116                         else
117                                 snd_emu10k1_intr_disable(emu, INTE_EFXBUFENABLE);
118                         status &= ~(IPR_EFXBUFFULL|IPR_EFXBUFHALFFULL);
119                 }
120                 if (status & (IPR_MIDITRANSBUFEMPTY|IPR_MIDIRECVBUFEMPTY)) {
121                         if (emu->midi.interrupt)
122                                 emu->midi.interrupt(emu, status);
123                         else
124                                 snd_emu10k1_intr_disable(emu, INTE_MIDITXENABLE|INTE_MIDIRXENABLE);
125                         status &= ~(IPR_MIDITRANSBUFEMPTY|IPR_MIDIRECVBUFEMPTY);
126                 }
127                 if (status & (IPR_A_MIDITRANSBUFEMPTY2|IPR_A_MIDIRECVBUFEMPTY2)) {
128                         if (emu->midi2.interrupt)
129                                 emu->midi2.interrupt(emu, status);
130                         else
131                                 snd_emu10k1_intr_disable(emu, INTE_A_MIDITXENABLE2|INTE_A_MIDIRXENABLE2);
132                         status &= ~(IPR_A_MIDITRANSBUFEMPTY2|IPR_A_MIDIRECVBUFEMPTY2);
133                 }
134                 if (status & IPR_INTERVALTIMER) {
135                         if (emu->timer)
136                                 snd_timer_interrupt(emu->timer, emu->timer->sticks);
137                         else
138                                 snd_emu10k1_intr_disable(emu, INTE_INTERVALTIMERENB);
139                         status &= ~IPR_INTERVALTIMER;
140                 }
141                 if (status & (IPR_GPSPDIFSTATUSCHANGE|IPR_CDROMSTATUSCHANGE)) {
142                         if (emu->spdif_interrupt)
143                                 emu->spdif_interrupt(emu, status);
144                         else
145                                 snd_emu10k1_intr_disable(emu, INTE_GPSPDIFENABLE|INTE_CDSPDIFENABLE);
146                         status &= ~(IPR_GPSPDIFSTATUSCHANGE|IPR_CDROMSTATUSCHANGE);
147                 }
148                 if (status & IPR_FXDSP) {
149                         if (emu->dsp_interrupt)
150                                 emu->dsp_interrupt(emu);
151                         else
152                                 snd_emu10k1_intr_disable(emu, INTE_FXDSPENABLE);
153                         status &= ~IPR_FXDSP;
154                 }
155                 if (status & IPR_P16V) {
156                         while ((status2 = inl(emu->port + IPR2)) != 0) {
157                                 u32 mask = INTE2_PLAYBACK_CH_0_LOOP;  /* Full Loop */
158                                 struct snd_emu10k1_voice *pvoice = &(emu->p16v_voices[0]);
159                                 struct snd_emu10k1_voice *cvoice = &(emu->p16v_capture_voice);
160 
161                                 /* dev_dbg(emu->card->dev, "status2=0x%x\n", status2); */
162                                 orig_status2 = status2;
163                                 if(status2 & mask) {
164                                         if(pvoice->use) {
165                                                 snd_pcm_period_elapsed(pvoice->epcm->substream);
166                                         } else { 
167                                                 dev_err(emu->card->dev,
168                                                         "p16v: status: 0x%08x, mask=0x%08x, pvoice=%p, use=%d\n",
169                                                         status2, mask, pvoice,
170                                                         pvoice->use);
171                                         }
172                                 }
173                                 if(status2 & 0x110000) {
174                                         /* dev_info(emu->card->dev, "capture int found\n"); */
175                                         if(cvoice->use) {
176                                                 /* dev_info(emu->card->dev, "capture period_elapsed\n"); */
177                                                 snd_pcm_period_elapsed(cvoice->epcm->substream);
178                                         }
179                                 }
180                                 outl(orig_status2, emu->port + IPR2); /* ack all */
181                         }
182                         status &= ~IPR_P16V;
183                 }
184 
185                 if (status) {
186                         unsigned int bits;
187                         dev_err(emu->card->dev,
188                                 "unhandled interrupt: 0x%08x\n", status);
189                         //make sure any interrupts we don't handle are disabled:
190                         bits = INTE_FXDSPENABLE |
191                                 INTE_PCIERRORENABLE |
192                                 INTE_VOLINCRENABLE |
193                                 INTE_VOLDECRENABLE |
194                                 INTE_MUTEENABLE |
195                                 INTE_MICBUFENABLE |
196                                 INTE_ADCBUFENABLE |
197                                 INTE_EFXBUFENABLE |
198                                 INTE_GPSPDIFENABLE |
199                                 INTE_CDSPDIFENABLE |
200                                 INTE_INTERVALTIMERENB |
201                                 INTE_MIDITXENABLE |
202                                 INTE_MIDIRXENABLE;
203                         if (emu->audigy)
204                                 bits |= INTE_A_MIDITXENABLE2 | INTE_A_MIDIRXENABLE2;
205                         snd_emu10k1_intr_disable(emu, bits);
206                 }
207                 outl(orig_status, emu->port + IPR); /* ack all */
208         }
209         if (timeout == 1000)
210                 dev_info(emu->card->dev, "emu10k1 irq routine failure\n");
211 
212         return IRQ_RETVAL(handled);
213 }
214 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp