sound/isa/sb/emu8000_pcm.c

Source file repositories/reference/linux-study-clean/sound/isa/sb/emu8000_pcm.c

File Facts

System
Linux kernel
Corpus path
sound/isa/sb/emu8000_pcm.c
Extension
.c
Size
15874 bytes
Lines
654
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_emu8k_pcm {
	struct snd_emu8000 *emu;
	struct snd_pcm_substream *substream;

	unsigned int allocated_bytes;
	struct snd_util_memblk *block;
	unsigned int offset;
	unsigned int buf_size;
	unsigned int period_size;
	unsigned int loop_start[2];
	unsigned int pitch;
	int panning[2];
	int last_ptr;
	int period_pos;
	int voices;
	unsigned int dram_opened: 1;
	unsigned int running: 1;
	unsigned int timer_running: 1;
	struct timer_list timer;
	spinlock_t timer_lock;
};

#define LOOP_BLANK_SIZE		8


/*
 * open up channels for the simultaneous data transfer and playback
 */
static int
emu8k_open_dram_for_pcm(struct snd_emu8000 *emu, int channels)
{
	int i;

	/* reserve up to 2 voices for playback */
	snd_emux_lock_voice(emu->emu, 0);
	if (channels > 1)
		snd_emux_lock_voice(emu->emu, 1);

	/* reserve 28 voices for loading */
	for (i = channels + 1; i < EMU8000_DRAM_VOICES; i++) {
		unsigned int mode = EMU8000_RAM_WRITE;
		snd_emux_lock_voice(emu->emu, i);
#ifndef USE_NONINTERLEAVE
		if (channels > 1 && (i & 1) != 0)
			mode |= EMU8000_RAM_RIGHT;
#endif
		snd_emu8000_dma_chan(emu, i, mode);
	}

	/* assign voice 31 and 32 to ROM */
	EMU8000_VTFT_WRITE(emu, 30, 0);
	EMU8000_PSST_WRITE(emu, 30, 0x1d8);
	EMU8000_CSL_WRITE(emu, 30, 0x1e0);
	EMU8000_CCCA_WRITE(emu, 30, 0x1d8);
	EMU8000_VTFT_WRITE(emu, 31, 0);
	EMU8000_PSST_WRITE(emu, 31, 0x1d8);
	EMU8000_CSL_WRITE(emu, 31, 0x1e0);
	EMU8000_CCCA_WRITE(emu, 31, 0x1d8);

	return 0;
}

/*
 */
static void
snd_emu8000_write_wait(struct snd_emu8000 *emu, int can_schedule)
{
	while ((EMU8000_SMALW_READ(emu) & 0x80000000) != 0) {
		if (can_schedule) {
			schedule_timeout_interruptible(1);
			if (signal_pending(current))
				break;
		}
	}
}

/*
 * close all channels
 */
static void
emu8k_close_dram(struct snd_emu8000 *emu)
{
	int i;

	for (i = 0; i < 2; i++)
		snd_emux_unlock_voice(emu->emu, i);
	for (; i < EMU8000_DRAM_VOICES; i++) {
		snd_emu8000_dma_chan(emu, i, EMU8000_RAM_CLOSE);
		snd_emux_unlock_voice(emu->emu, i);
	}

Annotation

Implementation Notes