static int snd_gus_dram_peek(snd_gus_card_t *gus, char __user *_buffer,
			     unsigned int address, unsigned int size,
			     int rom)
{
	unsigned long flags;
	unsigned int size1, size2;
	char buffer[512], *pbuffer;

	while (size > 0) {
		size1 = size > 512 ? 512 : size;
		if (gus->interwave) {
			spin_lock_irqsave(&gus->reg_lock, flags);
			snd_gf1_write8(gus, SNDRV_GF1_GB_MEMORY_CONTROL, rom ? 0x03 : 0x01);
			snd_gf1_dram_addr(gus, address);
			insb(GUSP(gus, DRAM), buffer, size1);
			snd_gf1_write8(gus, SNDRV_GF1_GB_MEMORY_CONTROL, 0x01);
			spin_unlock_irqrestore(&gus->reg_lock, flags);
			address += size1;
		} else {
			pbuffer = buffer;
			size2 = size1;
			while (size2--)
				*pbuffer++ = snd_gf1_peek(gus, address++);
		}
		if (copy_to_user(_buffer, buffer, size1))
			return -EFAULT;
		size -= size1;
		_buffer += size1;
	}
	return 0;
}
Esempio n. 2
0
static int snd_gf1_pcm_poke_block(struct snd_gus_card *gus, unsigned char *buf,
				  unsigned int pos, unsigned int count,
				  int w16, int invert)
{
	unsigned int len;
	unsigned long flags;

	/*
	printk(KERN_DEBUG
	       "poke block; buf = 0x%x, pos = %i, count = %i, port = 0x%x\n",
	       (int)buf, pos, count, gus->gf1.port);
	*/
	while (count > 0) {
		len = count;
		if (len > 512)		/* limit, to allow IRQ */
			len = 512;
		count -= len;
		if (gus->interwave) {
			spin_lock_irqsave(&gus->reg_lock, flags);
			snd_gf1_write8(gus, SNDRV_GF1_GB_MEMORY_CONTROL, 0x01 | (invert ? 0x08 : 0x00));
			snd_gf1_dram_addr(gus, pos);
			if (w16) {
				outb(SNDRV_GF1_GW_DRAM_IO16, GUSP(gus, GF1REGSEL));
				outsw(GUSP(gus, GF1DATALOW), buf, len >> 1);
			} else {
				outsb(GUSP(gus, DRAM), buf, len);
			}
			spin_unlock_irqrestore(&gus->reg_lock, flags);
			buf += 512;
			pos += 512;
		} else {
Esempio n. 3
0
static int snd_gf1_timer2_start(snd_timer_t * timer)
{
	unsigned long flags;
	unsigned char tmp;
	unsigned int ticks;
	snd_gus_card_t *gus;

	gus = snd_timer_chip(timer);
	spin_lock_irqsave(&gus->reg_lock, flags);
	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 */
	spin_unlock_irqrestore(&gus->reg_lock, flags);
	return 0;
}
Esempio n. 4
0
static void snd_gf1_dma_ack(struct snd_gus_card * gus)
{
	unsigned long flags;

	spin_lock_irqsave(&gus->reg_lock, flags);
	snd_gf1_write8(gus, SNDRV_GF1_GB_DRAM_DMA_CONTROL, 0x00);
	snd_gf1_look8(gus, SNDRV_GF1_GB_DRAM_DMA_CONTROL);
	spin_unlock_irqrestore(&gus->reg_lock, flags);
}
Esempio n. 5
0
static int snd_gf1_timer2_stop(snd_timer_t * timer)
{
	unsigned long flags;
	unsigned char tmp;
	snd_gus_card_t *gus;

	gus = snd_timer_chip(timer);
	spin_lock_irqsave(&gus->reg_lock, flags);
	tmp = (gus->gf1.timer_enabled &= ~8);
	snd_gf1_write8(gus, SNDRV_GF1_GB_SOUND_BLASTER_CONTROL, tmp);	/* disable timer #1 */
	spin_unlock_irqrestore(&gus->reg_lock, flags);
	return 0;
}
static int snd_gus_joystick_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
	struct snd_gus_card *gus = snd_kcontrol_chip(kcontrol);
	unsigned long flags;
	int change;
	unsigned char nval;

	nval = ucontrol->value.integer.value[0] & 31;
	spin_lock_irqsave(&gus->reg_lock, flags);
	change = gus->joystick_dac != nval;
	gus->joystick_dac = nval;
	snd_gf1_write8(gus, SNDRV_GF1_GB_JOYSTICK_DAC_LEVEL, gus->joystick_dac);
	spin_unlock_irqrestore(&gus->reg_lock, flags);
	return change;
}
Esempio n. 7
0
static void snd_gf1_pcm_interrupt_wave(struct snd_gus_card * gus,
				       struct snd_gus_voice *pvoice)
{
	struct gus_pcm_private * pcmp;
	struct snd_pcm_runtime *runtime;
	unsigned char voice_ctrl, ramp_ctrl;
	unsigned int idx;
	unsigned int end, step;

	if (!pvoice->private_data) {
		snd_printd("snd_gf1_pcm: unknown wave irq?\n");
		snd_gf1_smart_stop_voice(gus, pvoice->number);
		return;
	}
	pcmp = pvoice->private_data;
	if (pcmp == NULL) {
		snd_printd("snd_gf1_pcm: unknown wave irq?\n");
		snd_gf1_smart_stop_voice(gus, pvoice->number);
		return;
	}		
	gus = pcmp->gus;
	runtime = pcmp->substream->runtime;

	spin_lock(&gus->reg_lock);
	snd_gf1_select_voice(gus, pvoice->number);
	voice_ctrl = snd_gf1_read8(gus, SNDRV_GF1_VB_ADDRESS_CONTROL) & ~0x8b;
	ramp_ctrl = (snd_gf1_read8(gus, SNDRV_GF1_VB_VOLUME_CONTROL) & ~0xa4) | 0x03;
#if 0
	snd_gf1_select_voice(gus, pvoice->number);
	printk(KERN_DEBUG "position = 0x%x\n",
	       (snd_gf1_read_addr(gus, SNDRV_GF1_VA_CURRENT, voice_ctrl & 4) >> 4));
	snd_gf1_select_voice(gus, pcmp->pvoices[1]->number);
	printk(KERN_DEBUG "position = 0x%x\n",
	       (snd_gf1_read_addr(gus, SNDRV_GF1_VA_CURRENT, voice_ctrl & 4) >> 4));
	snd_gf1_select_voice(gus, pvoice->number);
#endif
	pcmp->bpos++;
	pcmp->bpos %= pcmp->blocks;
	if (pcmp->bpos + 1 >= pcmp->blocks) {	/* last block? */
		voice_ctrl |= 0x08;	/* enable loop */
	} else {
		ramp_ctrl |= 0x04;	/* enable rollover */
	}
	end = pcmp->memory + (((pcmp->bpos + 1) * pcmp->block_size) / runtime->channels);
	end -= voice_ctrl & 4 ? 2 : 1;
	step = pcmp->dma_size / runtime->channels;
	voice_ctrl |= 0x20;
	if (!pcmp->final_volume) {
		ramp_ctrl |= 0x20;
		ramp_ctrl &= ~0x03;
	}
	for (idx = 0; idx < pcmp->voices; idx++, end += step) {
		snd_gf1_select_voice(gus, pcmp->pvoices[idx]->number);
		snd_gf1_write_addr(gus, SNDRV_GF1_VA_END, end << 4, voice_ctrl & 4);
		snd_gf1_write8(gus, SNDRV_GF1_VB_ADDRESS_CONTROL, voice_ctrl);
		snd_gf1_write8(gus, SNDRV_GF1_VB_VOLUME_CONTROL, ramp_ctrl);
		voice_ctrl &= ~0x20;
	}
	if (!gus->gf1.enh_mode) {
		snd_gf1_delay(gus);
		voice_ctrl |= 0x20;
		for (idx = 0; idx < pcmp->voices; idx++) {
			snd_gf1_select_voice(gus, pcmp->pvoices[idx]->number);
			snd_gf1_write8(gus, SNDRV_GF1_VB_ADDRESS_CONTROL, voice_ctrl);
			snd_gf1_write8(gus, SNDRV_GF1_VB_VOLUME_CONTROL, ramp_ctrl);
			voice_ctrl &= ~0x20;
		}
	}
	spin_unlock(&gus->reg_lock);

	snd_pcm_period_elapsed(pcmp->substream);
#if 0
	if ((runtime->flags & SNDRV_PCM_FLG_MMAP) &&
	    *runtime->state == SNDRV_PCM_STATE_RUNNING) {
		end = pcmp->bpos * pcmp->block_size;
		if (runtime->channels > 1) {
			snd_gf1_pcm_block_change(pcmp->substream, end, pcmp->memory + (end / 2), pcmp->block_size / 2);
			snd_gf1_pcm_block_change(pcmp->substream, end + (pcmp->block_size / 2), pcmp->memory + (pcmp->dma_size / 2) + (end / 2), pcmp->block_size / 2);
		} else {
			snd_gf1_pcm_block_change(pcmp->substream, end, pcmp->memory + end, pcmp->block_size);
		}
	}
#endif
}
Esempio n. 8
0
static void snd_gf1_pcm_trigger_up(struct snd_pcm_substream *substream)
{
	struct snd_pcm_runtime *runtime = substream->runtime;
	struct gus_pcm_private *pcmp = runtime->private_data;
	struct snd_gus_card * gus = pcmp->gus;
	unsigned long flags;
	unsigned char voice_ctrl, ramp_ctrl;
	unsigned short rate;
	unsigned int curr, begin, end;
	unsigned short vol;
	unsigned char pan;
	unsigned int voice;

	spin_lock_irqsave(&pcmp->lock, flags);
	if (pcmp->flags & SNDRV_GF1_PCM_PFLG_ACTIVE) {
		spin_unlock_irqrestore(&pcmp->lock, flags);
		return;
	}
	pcmp->flags |= SNDRV_GF1_PCM_PFLG_ACTIVE;
	pcmp->final_volume = 0;
	spin_unlock_irqrestore(&pcmp->lock, flags);
	rate = snd_gf1_translate_freq(gus, runtime->rate << 4);
	/* enable WAVE IRQ */
	voice_ctrl = snd_pcm_format_width(runtime->format) == 16 ? 0x24 : 0x20;
	/* enable RAMP IRQ + rollover */
	ramp_ctrl = 0x24;
	if (pcmp->blocks == 1) {
		voice_ctrl |= 0x08;	/* loop enable */
		ramp_ctrl &= ~0x04;	/* disable rollover */
	}
	for (voice = 0; voice < pcmp->voices; voice++) {
		begin = pcmp->memory + voice * (pcmp->dma_size / runtime->channels);
		curr = begin + (pcmp->bpos * pcmp->block_size) / runtime->channels;
		end = curr + (pcmp->block_size / runtime->channels);
		end -= snd_pcm_format_width(runtime->format) == 16 ? 2 : 1;
		/*
		snd_printk(KERN_DEBUG "init: curr=0x%x, begin=0x%x, end=0x%x, "
			   "ctrl=0x%x, ramp=0x%x, rate=0x%x\n",
			   curr, begin, end, voice_ctrl, ramp_ctrl, rate);
		*/
		pan = runtime->channels == 2 ? (!voice ? 1 : 14) : 8;
		vol = !voice ? gus->gf1.pcm_volume_level_left : gus->gf1.pcm_volume_level_right;
		spin_lock_irqsave(&gus->reg_lock, flags);
		snd_gf1_select_voice(gus, pcmp->pvoices[voice]->number);
		snd_gf1_write8(gus, SNDRV_GF1_VB_PAN, pan);
		snd_gf1_write16(gus, SNDRV_GF1_VW_FREQUENCY, rate);
		snd_gf1_write_addr(gus, SNDRV_GF1_VA_START, begin << 4, voice_ctrl & 4);
		snd_gf1_write_addr(gus, SNDRV_GF1_VA_END, end << 4, voice_ctrl & 4);
		snd_gf1_write_addr(gus, SNDRV_GF1_VA_CURRENT, curr << 4, voice_ctrl & 4);
		snd_gf1_write16(gus, SNDRV_GF1_VW_VOLUME, SNDRV_GF1_MIN_VOLUME << 4);
		snd_gf1_write8(gus, SNDRV_GF1_VB_VOLUME_RATE, 0x2f);
		snd_gf1_write8(gus, SNDRV_GF1_VB_VOLUME_START, SNDRV_GF1_MIN_OFFSET);
		snd_gf1_write8(gus, SNDRV_GF1_VB_VOLUME_END, vol >> 8);
		snd_gf1_write8(gus, SNDRV_GF1_VB_VOLUME_CONTROL, ramp_ctrl);
		if (!gus->gf1.enh_mode) {
			snd_gf1_delay(gus);
			snd_gf1_write8(gus, SNDRV_GF1_VB_VOLUME_CONTROL, ramp_ctrl);
		}
		spin_unlock_irqrestore(&gus->reg_lock, flags);
	}
	spin_lock_irqsave(&gus->reg_lock, flags);
	for (voice = 0; voice < pcmp->voices; voice++) {
		snd_gf1_select_voice(gus, pcmp->pvoices[voice]->number);
		if (gus->gf1.enh_mode)
			snd_gf1_write8(gus, SNDRV_GF1_VB_MODE, 0x00);	/* deactivate voice */
		snd_gf1_write8(gus, SNDRV_GF1_VB_ADDRESS_CONTROL, voice_ctrl);
		voice_ctrl &= ~0x20;
	}
	voice_ctrl |= 0x20;
	if (!gus->gf1.enh_mode) {
		snd_gf1_delay(gus);
		for (voice = 0; voice < pcmp->voices; voice++) {
			snd_gf1_select_voice(gus, pcmp->pvoices[voice]->number);
			snd_gf1_write8(gus, SNDRV_GF1_VB_ADDRESS_CONTROL, voice_ctrl);
			voice_ctrl &= ~0x20;	/* disable IRQ for next voice */
		}
	}
	spin_unlock_irqrestore(&gus->reg_lock, flags);
}