sound/isa/gus/gusmax.c

Source file repositories/reference/linux-study-clean/sound/isa/gus/gusmax.c

File Facts

System
Linux kernel
Corpus path
sound/isa/gus/gusmax.c
Extension
.c
Size
10198 bytes
Lines
369
Domain
Driver Families
Bucket
sound/isa
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct snd_gusmax {
	int irq;
	struct snd_card *card;
	struct snd_gus_card *gus;
	struct snd_wss *wss;
	unsigned short gus_status_reg;
	unsigned short pcm_status_reg;
};

static int snd_gusmax_detect(struct snd_gus_card *gus)
{
	unsigned char d;

	snd_gf1_i_write8(gus, SNDRV_GF1_GB_RESET, 0);	/* reset GF1 */
	d = snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET);
	if ((d & 0x07) != 0) {
		dev_dbg(gus->card->dev, "[0x%lx] check 1 failed - 0x%x\n", gus->gf1.port, d);
		return -ENODEV;
	}
	udelay(160);
	snd_gf1_i_write8(gus, SNDRV_GF1_GB_RESET, 1);	/* release reset */
	udelay(160);
	d = snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET);
	if ((d & 0x07) != 1) {
		dev_dbg(gus->card->dev, "[0x%lx] check 2 failed - 0x%x\n", gus->gf1.port, d);
		return -ENODEV;
	}

	return 0;
}

static irqreturn_t snd_gusmax_interrupt(int irq, void *dev_id)
{
	struct snd_gusmax *maxcard = dev_id;
	int loop, max = 5;
	int handled = 0;

	do {
		loop = 0;
		if (inb(maxcard->gus_status_reg)) {
			handled = 1;
			snd_gus_interrupt(irq, maxcard->gus);
			loop++;
		}
		if (inb(maxcard->pcm_status_reg) & 0x01) { /* IRQ bit is set? */
			handled = 1;
			snd_wss_interrupt(irq, maxcard->wss);
			loop++;
		}
	} while (loop && --max > 0);
	return IRQ_RETVAL(handled);
}

static void snd_gusmax_init(int dev, struct snd_card *card,
			    struct snd_gus_card *gus)
{
	gus->equal_irq = 1;
	gus->codec_flag = 1;
	gus->joystick_dac = joystick_dac[dev];
	/* init control register */
	gus->max_cntrl_val = (gus->gf1.port >> 4) & 0x0f;
	if (gus->gf1.dma1 > 3)
		gus->max_cntrl_val |= 0x10;
	if (gus->gf1.dma2 > 3)
		gus->max_cntrl_val |= 0x20;
	gus->max_cntrl_val |= 0x40;
	outb(gus->max_cntrl_val, GUSP(gus, MAXCNTRLPORT));
}

static int snd_gusmax_mixer(struct snd_wss *chip)
{
	struct snd_card *card = chip->card;
	struct snd_ctl_elem_id id1, id2;
	int err;
	
	memset(&id1, 0, sizeof(id1));
	memset(&id2, 0, sizeof(id2));
	id1.iface = id2.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
	/* reassign AUXA to SYNTHESIZER */
	strscpy(id1.name, "Aux Playback Switch");
	strscpy(id2.name, "Synth Playback Switch");
	err = snd_ctl_rename_id(card, &id1, &id2);
	if (err < 0)
		return err;
	strscpy(id1.name, "Aux Playback Volume");
	strscpy(id2.name, "Synth Playback Volume");
	err = snd_ctl_rename_id(card, &id1, &id2);
	if (err < 0)
		return err;
	/* reassign AUXB to CD */

Annotation

Implementation Notes