sound/isa/gus/gus_timer.c

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

File Facts

System
Linux kernel
Corpus path
sound/isa/gus/gus_timer.c
Extension
.c
Size
4760 bytes
Lines
195
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

// SPDX-License-Identifier: GPL-2.0-or-later
/*
 *  Routines for Gravis UltraSound soundcards - Timers
 *  Copyright (c) by Jaroslav Kysela <perex@perex.cz>
 *
 *  GUS have similar timers as AdLib (OPL2/OPL3 chips).
 */

#include <linux/time.h>
#include <sound/core.h>
#include <sound/gus.h>

/*
 *  Timer 1 - 80us
 */

static int snd_gf1_timer1_start(struct snd_timer * timer)
{
	unsigned char tmp;
	unsigned int ticks;
	struct snd_gus_card *gus;

	gus = snd_timer_chip(timer);
	guard(spinlock_irqsave)(&gus->reg_lock);
	ticks = timer->sticks;
	tmp = (gus->gf1.timer_enabled |= 4);
	snd_gf1_write8(gus, SNDRV_GF1_GB_ADLIB_TIMER_1, 256 - ticks);	/* timer 1 count */
	snd_gf1_write8(gus, SNDRV_GF1_GB_SOUND_BLASTER_CONTROL, tmp);	/* enable timer 1 IRQ */
	snd_gf1_adlib_write(gus, 0x04, tmp >> 2);	/* timer 2 start */
	return 0;
}

static int snd_gf1_timer1_stop(struct snd_timer * timer)
{
	unsigned char tmp;
	struct snd_gus_card *gus;

	gus = snd_timer_chip(timer);
	guard(spinlock_irqsave)(&gus->reg_lock);
	tmp = (gus->gf1.timer_enabled &= ~4);
	snd_gf1_write8(gus, SNDRV_GF1_GB_SOUND_BLASTER_CONTROL, tmp);	/* disable timer #1 */
	return 0;
}

/*
 *  Timer 2 - 320us
 */

static int snd_gf1_timer2_start(struct snd_timer * timer)
{
	unsigned char tmp;
	unsigned int ticks;
	struct snd_gus_card *gus;

	gus = snd_timer_chip(timer);
	guard(spinlock_irqsave)(&gus->reg_lock);
	ticks = timer->sticks;
	tmp = (gus->gf1.timer_enabled |= 8);
	snd_gf1_write8(gus, SNDRV_GF1_GB_ADLIB_TIMER_2, 256 - ticks);	/* timer 2 count */
	snd_gf1_write8(gus, SNDRV_GF1_GB_SOUND_BLASTER_CONTROL, tmp);	/* enable timer 2 IRQ */
	snd_gf1_adlib_write(gus, 0x04, tmp >> 2);	/* timer 2 start */
	return 0;
}

static int snd_gf1_timer2_stop(struct snd_timer * timer)
{
	unsigned char tmp;
	struct snd_gus_card *gus;

	gus = snd_timer_chip(timer);
	guard(spinlock_irqsave)(&gus->reg_lock);
	tmp = (gus->gf1.timer_enabled &= ~8);
	snd_gf1_write8(gus, SNDRV_GF1_GB_SOUND_BLASTER_CONTROL, tmp);	/* disable timer #1 */
	return 0;
}

/*

 */

static void snd_gf1_interrupt_timer1(struct snd_gus_card * gus)
{
	struct snd_timer *timer = gus->gf1.timer1;

	if (timer == NULL)
		return;
	snd_timer_interrupt(timer, timer->sticks);
}

static void snd_gf1_interrupt_timer2(struct snd_gus_card * gus)

Annotation

Implementation Notes