OpenCores
URL https://opencores.org/ocsvn/test_project/test_project/trunk

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [sound/] [pci/] [emu10k1/] [irq.c] - Blame information for rev 62

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/*
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 <sound/driver.h>
29
#include <linux/time.h>
30
#include <sound/core.h>
31
#include <sound/emu10k1.h>
32
 
33
irqreturn_t snd_emu10k1_interrupt(int irq, void *dev_id)
34
{
35
        struct snd_emu10k1 *emu = dev_id;
36
        unsigned int status, status2, orig_status, orig_status2;
37
        int handled = 0;
38
 
39
        while ((status = inl(emu->port + IPR)) != 0) {
40
                //snd_printk(KERN_INFO "emu10k1 irq - status = 0x%x\n", status);
41
                orig_status = status;
42
                handled = 1;
43
                if ((status & 0xffffffff) == 0xffffffff) {
44
                        snd_printk(KERN_INFO "snd-emu10k1: Suspected sound card removal\n");
45
                        break;
46
                }
47
                if (status & IPR_PCIERROR) {
48
                        snd_printk(KERN_ERR "interrupt: PCI error\n");
49
                        snd_emu10k1_intr_disable(emu, INTE_PCIERRORENABLE);
50
                        status &= ~IPR_PCIERROR;
51
                }
52
                if (status & (IPR_VOLINCR|IPR_VOLDECR|IPR_MUTE)) {
53
                        if (emu->hwvol_interrupt)
54
                                emu->hwvol_interrupt(emu, status);
55
                        else
56
                                snd_emu10k1_intr_disable(emu, INTE_VOLINCRENABLE|INTE_VOLDECRENABLE|INTE_MUTEENABLE);
57
                        status &= ~(IPR_VOLINCR|IPR_VOLDECR|IPR_MUTE);
58
                }
59
                if (status & IPR_CHANNELLOOP) {
60
                        int voice;
61
                        int voice_max = status & IPR_CHANNELNUMBERMASK;
62
                        u32 val;
63
                        struct snd_emu10k1_voice *pvoice = emu->voices;
64
 
65
                        val = snd_emu10k1_ptr_read(emu, CLIPL, 0);
66
                        for (voice = 0; voice <= voice_max; voice++) {
67
                                if (voice == 0x20)
68
                                        val = snd_emu10k1_ptr_read(emu, CLIPH, 0);
69
                                if (val & 1) {
70
                                        if (pvoice->use && pvoice->interrupt != NULL) {
71
                                                pvoice->interrupt(emu, pvoice);
72
                                                snd_emu10k1_voice_intr_ack(emu, voice);
73
                                        } else {
74
                                                snd_emu10k1_voice_intr_disable(emu, voice);
75
                                        }
76
                                }
77
                                val >>= 1;
78
                                pvoice++;
79
                        }
80
                        val = snd_emu10k1_ptr_read(emu, HLIPL, 0);
81
                        for (voice = 0; voice <= voice_max; voice++) {
82
                                if (voice == 0x20)
83
                                        val = snd_emu10k1_ptr_read(emu, HLIPH, 0);
84
                                if (val & 1) {
85
                                        if (pvoice->use && pvoice->interrupt != NULL) {
86
                                                pvoice->interrupt(emu, pvoice);
87
                                                snd_emu10k1_voice_half_loop_intr_ack(emu, voice);
88
                                        } else {
89
                                                snd_emu10k1_voice_half_loop_intr_disable(emu, voice);
90
                                        }
91
                                }
92
                                val >>= 1;
93
                                pvoice++;
94
                        }
95
                        status &= ~IPR_CHANNELLOOP;
96
                }
97
                status &= ~IPR_CHANNELNUMBERMASK;
98
                if (status & (IPR_ADCBUFFULL|IPR_ADCBUFHALFFULL)) {
99
                        if (emu->capture_interrupt)
100
                                emu->capture_interrupt(emu, status);
101
                        else
102
                                snd_emu10k1_intr_disable(emu, INTE_ADCBUFENABLE);
103
                        status &= ~(IPR_ADCBUFFULL|IPR_ADCBUFHALFFULL);
104
                }
105
                if (status & (IPR_MICBUFFULL|IPR_MICBUFHALFFULL)) {
106
                        if (emu->capture_mic_interrupt)
107
                                emu->capture_mic_interrupt(emu, status);
108
                        else
109
                                snd_emu10k1_intr_disable(emu, INTE_MICBUFENABLE);
110
                        status &= ~(IPR_MICBUFFULL|IPR_MICBUFHALFFULL);
111
                }
112
                if (status & (IPR_EFXBUFFULL|IPR_EFXBUFHALFFULL)) {
113
                        if (emu->capture_efx_interrupt)
114
                                emu->capture_efx_interrupt(emu, status);
115
                        else
116
                                snd_emu10k1_intr_disable(emu, INTE_EFXBUFENABLE);
117
                        status &= ~(IPR_EFXBUFFULL|IPR_EFXBUFHALFFULL);
118
                }
119
                if (status & (IPR_MIDITRANSBUFEMPTY|IPR_MIDIRECVBUFEMPTY)) {
120
                        if (emu->midi.interrupt)
121
                                emu->midi.interrupt(emu, status);
122
                        else
123
                                snd_emu10k1_intr_disable(emu, INTE_MIDITXENABLE|INTE_MIDIRXENABLE);
124
                        status &= ~(IPR_MIDITRANSBUFEMPTY|IPR_MIDIRECVBUFEMPTY);
125
                }
126
                if (status & (IPR_A_MIDITRANSBUFEMPTY2|IPR_A_MIDIRECVBUFEMPTY2)) {
127
                        if (emu->midi2.interrupt)
128
                                emu->midi2.interrupt(emu, status);
129
                        else
130
                                snd_emu10k1_intr_disable(emu, INTE_A_MIDITXENABLE2|INTE_A_MIDIRXENABLE2);
131
                        status &= ~(IPR_A_MIDITRANSBUFEMPTY2|IPR_A_MIDIRECVBUFEMPTY2);
132
                }
133
                if (status & IPR_INTERVALTIMER) {
134
                        if (emu->timer)
135
                                snd_timer_interrupt(emu->timer, emu->timer->sticks);
136
                        else
137
                                snd_emu10k1_intr_disable(emu, INTE_INTERVALTIMERENB);
138
                        status &= ~IPR_INTERVALTIMER;
139
                }
140
                if (status & (IPR_GPSPDIFSTATUSCHANGE|IPR_CDROMSTATUSCHANGE)) {
141
                        if (emu->spdif_interrupt)
142
                                emu->spdif_interrupt(emu, status);
143
                        else
144
                                snd_emu10k1_intr_disable(emu, INTE_GPSPDIFENABLE|INTE_CDSPDIFENABLE);
145
                        status &= ~(IPR_GPSPDIFSTATUSCHANGE|IPR_CDROMSTATUSCHANGE);
146
                }
147
                if (status & IPR_FXDSP) {
148
                        if (emu->dsp_interrupt)
149
                                emu->dsp_interrupt(emu);
150
                        else
151
                                snd_emu10k1_intr_disable(emu, INTE_FXDSPENABLE);
152
                        status &= ~IPR_FXDSP;
153
                }
154
                if (status & IPR_P16V) {
155
                        while ((status2 = inl(emu->port + IPR2)) != 0) {
156
                                u32 mask = INTE2_PLAYBACK_CH_0_LOOP;  /* Full Loop */
157
                                struct snd_emu10k1_voice *pvoice = &(emu->p16v_voices[0]);
158
                                struct snd_emu10k1_voice *cvoice = &(emu->p16v_capture_voice);
159
 
160
                                //printk(KERN_INFO "status2=0x%x\n", status2);
161
                                orig_status2 = status2;
162
                                if(status2 & mask) {
163
                                        if(pvoice->use) {
164
                                                snd_pcm_period_elapsed(pvoice->epcm->substream);
165
                                        } else {
166
                                                snd_printk(KERN_ERR "p16v: status: 0x%08x, mask=0x%08x, pvoice=%p, use=%d\n", status2, mask, pvoice, pvoice->use);
167
                                        }
168
                                }
169
                                if(status2 & 0x110000) {
170
                                        //printk(KERN_INFO "capture int found\n");
171
                                        if(cvoice->use) {
172
                                                //printk(KERN_INFO "capture period_elapsed\n");
173
                                                snd_pcm_period_elapsed(cvoice->epcm->substream);
174
                                        }
175
                                }
176
                                outl(orig_status2, emu->port + IPR2); /* ack all */
177
                        }
178
                        status &= ~IPR_P16V;
179
                }
180
 
181
                if (status) {
182
                        unsigned int bits;
183
                        snd_printk(KERN_ERR "emu10k1: unhandled interrupt: 0x%08x\n", status);
184
                        //make sure any interrupts we don't handle are disabled:
185
                        bits = INTE_FXDSPENABLE |
186
                                INTE_PCIERRORENABLE |
187
                                INTE_VOLINCRENABLE |
188
                                INTE_VOLDECRENABLE |
189
                                INTE_MUTEENABLE |
190
                                INTE_MICBUFENABLE |
191
                                INTE_ADCBUFENABLE |
192
                                INTE_EFXBUFENABLE |
193
                                INTE_GPSPDIFENABLE |
194
                                INTE_CDSPDIFENABLE |
195
                                INTE_INTERVALTIMERENB |
196
                                INTE_MIDITXENABLE |
197
                                INTE_MIDIRXENABLE;
198
                        if (emu->audigy)
199
                                bits |= INTE_A_MIDITXENABLE2 | INTE_A_MIDIRXENABLE2;
200
                        snd_emu10k1_intr_disable(emu, bits);
201
                }
202
                outl(orig_status, emu->port + IPR); /* ack all */
203
        }
204
        return IRQ_RETVAL(handled);
205
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.