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

TOMOYO Linux Cross Reference
Linux/sound/isa/gus/gus_irq.c

Version: ~ [ linux-6.11-rc3 ] ~ [ linux-6.10.4 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.45 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.104 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.164 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.223 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.281 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.319 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0-or-later
  2 /*
  3  *  Routine for IRQ handling from GF1/InterWave chip
  4  *  Copyright (c) by Jaroslav Kysela <perex@perex.cz>
  5  */
  6 
  7 #include <sound/core.h>
  8 #include <sound/info.h>
  9 #include <sound/gus.h>
 10 
 11 #ifdef CONFIG_SND_DEBUG
 12 #define STAT_ADD(x)     ((x)++)
 13 #else
 14 #define STAT_ADD(x)     while (0) { ; }
 15 #endif
 16 
 17 irqreturn_t snd_gus_interrupt(int irq, void *dev_id)
 18 {
 19         struct snd_gus_card * gus = dev_id;
 20         unsigned char status;
 21         int loop = 100;
 22         int handled = 0;
 23 
 24 __again:
 25         status = inb(gus->gf1.reg_irqstat);
 26         if (status == 0)
 27                 return IRQ_RETVAL(handled);
 28         handled = 1;
 29         /* snd_printk(KERN_DEBUG "IRQ: status = 0x%x\n", status); */
 30         if (status & 0x02) {
 31                 STAT_ADD(gus->gf1.interrupt_stat_midi_in);
 32                 if (gus->gf1.interrupt_handler_midi_in)
 33                         gus->gf1.interrupt_handler_midi_in(gus);
 34         }
 35         if (status & 0x01) {
 36                 STAT_ADD(gus->gf1.interrupt_stat_midi_out);
 37                 if (gus->gf1.interrupt_handler_midi_out)
 38                         gus->gf1.interrupt_handler_midi_out(gus);
 39         }
 40         if (status & (0x20 | 0x40)) {
 41                 unsigned int already, _current_;
 42                 unsigned char voice_status, voice;
 43                 struct snd_gus_voice *pvoice;
 44 
 45                 already = 0;
 46                 while (((voice_status = snd_gf1_i_read8(gus, SNDRV_GF1_GB_VOICES_IRQ)) & 0xc0) != 0xc0) {
 47                         voice = voice_status & 0x1f;
 48                         _current_ = 1 << voice;
 49                         if (already & _current_)
 50                                 continue;       /* multi request */
 51                         already |= _current_;   /* mark request */
 52 #if 0
 53                         printk(KERN_DEBUG "voice = %i, voice_status = 0x%x, "
 54                                "voice_verify = %i\n",
 55                                voice, voice_status, inb(GUSP(gus, GF1PAGE)));
 56 #endif
 57                         pvoice = &gus->gf1.voices[voice]; 
 58                         if (pvoice->use) {
 59                                 if (!(voice_status & 0x80)) {   /* voice position IRQ */
 60                                         STAT_ADD(pvoice->interrupt_stat_wave);
 61                                         pvoice->handler_wave(gus, pvoice);
 62                                 }
 63                                 if (!(voice_status & 0x40)) {   /* volume ramp IRQ */
 64                                         STAT_ADD(pvoice->interrupt_stat_volume);
 65                                         pvoice->handler_volume(gus, pvoice);
 66                                 }
 67                         } else {
 68                                 STAT_ADD(gus->gf1.interrupt_stat_voice_lost);
 69                                 snd_gf1_i_ctrl_stop(gus, SNDRV_GF1_VB_ADDRESS_CONTROL);
 70                                 snd_gf1_i_ctrl_stop(gus, SNDRV_GF1_VB_VOLUME_CONTROL);
 71                         }
 72                 }
 73         }
 74         if (status & 0x04) {
 75                 STAT_ADD(gus->gf1.interrupt_stat_timer1);
 76                 if (gus->gf1.interrupt_handler_timer1)
 77                         gus->gf1.interrupt_handler_timer1(gus);
 78         }
 79         if (status & 0x08) {
 80                 STAT_ADD(gus->gf1.interrupt_stat_timer2);
 81                 if (gus->gf1.interrupt_handler_timer2)
 82                         gus->gf1.interrupt_handler_timer2(gus);
 83         }
 84         if (status & 0x80) {
 85                 if (snd_gf1_i_look8(gus, SNDRV_GF1_GB_DRAM_DMA_CONTROL) & 0x40) {
 86                         STAT_ADD(gus->gf1.interrupt_stat_dma_write);
 87                         if (gus->gf1.interrupt_handler_dma_write)
 88                                 gus->gf1.interrupt_handler_dma_write(gus);
 89                 }
 90                 if (snd_gf1_i_look8(gus, SNDRV_GF1_GB_REC_DMA_CONTROL) & 0x40) {
 91                         STAT_ADD(gus->gf1.interrupt_stat_dma_read);
 92                         if (gus->gf1.interrupt_handler_dma_read)
 93                                 gus->gf1.interrupt_handler_dma_read(gus);
 94                 }
 95         }
 96         if (--loop > 0)
 97                 goto __again;
 98         return IRQ_NONE;
 99 }
100 
101 #ifdef CONFIG_SND_DEBUG
102 static void snd_gus_irq_info_read(struct snd_info_entry *entry, 
103                                   struct snd_info_buffer *buffer)
104 {
105         struct snd_gus_card *gus;
106         struct snd_gus_voice *pvoice;
107         int idx;
108 
109         gus = entry->private_data;
110         snd_iprintf(buffer, "midi out = %u\n", gus->gf1.interrupt_stat_midi_out);
111         snd_iprintf(buffer, "midi in = %u\n", gus->gf1.interrupt_stat_midi_in);
112         snd_iprintf(buffer, "timer1 = %u\n", gus->gf1.interrupt_stat_timer1);
113         snd_iprintf(buffer, "timer2 = %u\n", gus->gf1.interrupt_stat_timer2);
114         snd_iprintf(buffer, "dma write = %u\n", gus->gf1.interrupt_stat_dma_write);
115         snd_iprintf(buffer, "dma read = %u\n", gus->gf1.interrupt_stat_dma_read);
116         snd_iprintf(buffer, "voice lost = %u\n", gus->gf1.interrupt_stat_voice_lost);
117         for (idx = 0; idx < 32; idx++) {
118                 pvoice = &gus->gf1.voices[idx];
119                 snd_iprintf(buffer, "voice %i: wave = %u, volume = %u\n",
120                                         idx,
121                                         pvoice->interrupt_stat_wave,
122                                         pvoice->interrupt_stat_volume);
123         }
124 }
125 
126 void snd_gus_irq_profile_init(struct snd_gus_card *gus)
127 {
128         snd_card_ro_proc_new(gus->card, "gusirq", gus, snd_gus_irq_info_read);
129 }
130 
131 #endif
132 

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

kernel.org | git.kernel.org | LWN.net | Project Home | 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.

sflogo.php