brintos

brintos / linux-shallow public Read only

0
0
Text · 3.8 KiB · 0e10544 Raw
131 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 *  Routine for IRQ handling from GF1/InterWave chip4 *  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_DEBUG12#define STAT_ADD(x)	((x)++)13#else14#define STAT_ADD(x)	while (0) { ; }15#endif16 17irqreturn_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	if (status & 0x02) {30		STAT_ADD(gus->gf1.interrupt_stat_midi_in);31		if (gus->gf1.interrupt_handler_midi_in)32			gus->gf1.interrupt_handler_midi_in(gus);33	}34	if (status & 0x01) {35		STAT_ADD(gus->gf1.interrupt_stat_midi_out);36		if (gus->gf1.interrupt_handler_midi_out)37			gus->gf1.interrupt_handler_midi_out(gus);38	}39	if (status & (0x20 | 0x40)) {40		unsigned int already, _current_;41		unsigned char voice_status, voice;42		struct snd_gus_voice *pvoice;43 44		already = 0;45		while (((voice_status = snd_gf1_i_read8(gus, SNDRV_GF1_GB_VOICES_IRQ)) & 0xc0) != 0xc0) {46			voice = voice_status & 0x1f;47			_current_ = 1 << voice;48			if (already & _current_)49				continue;	/* multi request */50			already |= _current_;	/* mark request */51#if 052			dev_dbg(gus->card->dev,53				"voice = %i, voice_status = 0x%x, voice_verify = %i\n",54				voice, voice_status, inb(GUSP(gus, GF1PAGE)));55#endif56			pvoice = &gus->gf1.voices[voice]; 57			if (pvoice->use) {58				if (!(voice_status & 0x80)) {	/* voice position IRQ */59					STAT_ADD(pvoice->interrupt_stat_wave);60					pvoice->handler_wave(gus, pvoice);61				}62				if (!(voice_status & 0x40)) {	/* volume ramp IRQ */63					STAT_ADD(pvoice->interrupt_stat_volume);64					pvoice->handler_volume(gus, pvoice);65				}66			} else {67				STAT_ADD(gus->gf1.interrupt_stat_voice_lost);68				snd_gf1_i_ctrl_stop(gus, SNDRV_GF1_VB_ADDRESS_CONTROL);69				snd_gf1_i_ctrl_stop(gus, SNDRV_GF1_VB_VOLUME_CONTROL);70			}71		}72	}73	if (status & 0x04) {74		STAT_ADD(gus->gf1.interrupt_stat_timer1);75		if (gus->gf1.interrupt_handler_timer1)76			gus->gf1.interrupt_handler_timer1(gus);77	}78	if (status & 0x08) {79		STAT_ADD(gus->gf1.interrupt_stat_timer2);80		if (gus->gf1.interrupt_handler_timer2)81			gus->gf1.interrupt_handler_timer2(gus);82	}83	if (status & 0x80) {84		if (snd_gf1_i_look8(gus, SNDRV_GF1_GB_DRAM_DMA_CONTROL) & 0x40) {85			STAT_ADD(gus->gf1.interrupt_stat_dma_write);86			if (gus->gf1.interrupt_handler_dma_write)87				gus->gf1.interrupt_handler_dma_write(gus);88		}89		if (snd_gf1_i_look8(gus, SNDRV_GF1_GB_REC_DMA_CONTROL) & 0x40) {90			STAT_ADD(gus->gf1.interrupt_stat_dma_read);91			if (gus->gf1.interrupt_handler_dma_read)92				gus->gf1.interrupt_handler_dma_read(gus);93		}94	}95	if (--loop > 0)96		goto __again;97	return IRQ_NONE;98}99 100#ifdef CONFIG_SND_DEBUG101static void snd_gus_irq_info_read(struct snd_info_entry *entry, 102				  struct snd_info_buffer *buffer)103{104	struct snd_gus_card *gus;105	struct snd_gus_voice *pvoice;106	int idx;107 108	gus = entry->private_data;109	snd_iprintf(buffer, "midi out = %u\n", gus->gf1.interrupt_stat_midi_out);110	snd_iprintf(buffer, "midi in = %u\n", gus->gf1.interrupt_stat_midi_in);111	snd_iprintf(buffer, "timer1 = %u\n", gus->gf1.interrupt_stat_timer1);112	snd_iprintf(buffer, "timer2 = %u\n", gus->gf1.interrupt_stat_timer2);113	snd_iprintf(buffer, "dma write = %u\n", gus->gf1.interrupt_stat_dma_write);114	snd_iprintf(buffer, "dma read = %u\n", gus->gf1.interrupt_stat_dma_read);115	snd_iprintf(buffer, "voice lost = %u\n", gus->gf1.interrupt_stat_voice_lost);116	for (idx = 0; idx < 32; idx++) {117		pvoice = &gus->gf1.voices[idx];118		snd_iprintf(buffer, "voice %i: wave = %u, volume = %u\n",119					idx,120					pvoice->interrupt_stat_wave,121					pvoice->interrupt_stat_volume);122	}123}124 125void snd_gus_irq_profile_init(struct snd_gus_card *gus)126{127	snd_card_ro_proc_new(gus->card, "gusirq", gus, snd_gus_irq_info_read);128}129 130#endif131