Ejemplo n.º 1
0
static int snd_als300_capture_prepare(struct snd_pcm_substream *substream)
{
	u32 tmp;
	struct snd_als300 *chip = snd_pcm_substream_chip(substream);
	struct snd_pcm_runtime *runtime = substream->runtime;
	unsigned short period_bytes = snd_pcm_lib_period_bytes(substream);
	unsigned short buffer_bytes = snd_pcm_lib_buffer_bytes(substream);

	spin_lock_irq(&chip->reg_lock);
	tmp = snd_als300_gcr_read(chip->port, RECORD_CONTROL);
	tmp &= ~TRANSFER_START;

	snd_als300_dbgplay("Period bytes: %d Buffer bytes %d\n", period_bytes,
							buffer_bytes);

	/* set block size */
	tmp &= 0xffff0000;
	tmp |= period_bytes - 1;

	/* set dma area */
	snd_als300_gcr_write(chip->port, RECORD_CONTROL, tmp);
	snd_als300_gcr_write(chip->port, RECORD_START,
					runtime->dma_addr);
	snd_als300_gcr_write(chip->port, RECORD_END,
					runtime->dma_addr + buffer_bytes - 1);
	spin_unlock_irq(&chip->reg_lock);
	return 0;
}
Ejemplo n.º 2
0
static snd_pcm_uframes_t snd_als300_pointer(struct snd_pcm_substream *substream)
{
	u16 current_ptr;
	struct snd_als300 *chip = snd_pcm_substream_chip(substream);
	struct snd_als300_substream_data *data;
	unsigned short period_bytes;

	data = substream->runtime->private_data;
	period_bytes = snd_pcm_lib_period_bytes(substream);
	
	snd_als300_dbgcallenter();
	spin_lock(&chip->reg_lock);
	current_ptr = (u16) snd_als300_gcr_read(chip->port,
					data->block_counter_register) + 4;
	spin_unlock(&chip->reg_lock);
	if (current_ptr > period_bytes)
		current_ptr = 0;
	else
		current_ptr = period_bytes - current_ptr;

	if (data->period_flipflop == 0)
		current_ptr += period_bytes;
	snd_als300_dbgplay("Pointer (bytes): %d\n", current_ptr);
	snd_als300_dbgcallleave();
	return bytes_to_frames(substream->runtime, current_ptr);
}
Ejemplo n.º 3
0
static int snd_als300_trigger(struct snd_pcm_substream *substream, int cmd)
{
	struct snd_als300 *chip = snd_pcm_substream_chip(substream);
	u32 tmp;
	struct snd_als300_substream_data *data;
	unsigned short reg;
	int ret = 0;

	data = substream->runtime->private_data;
	reg = data->control_register;

	snd_als300_dbgcallenter();
	spin_lock(&chip->reg_lock);
	switch (cmd) {
	case SNDRV_PCM_TRIGGER_START:
	case SNDRV_PCM_TRIGGER_RESUME:
		tmp = snd_als300_gcr_read(chip->port, reg);
		data->period_flipflop = 1;
		snd_als300_gcr_write(chip->port, reg, tmp | TRANSFER_START);
		snd_als300_dbgplay("TRIGGER START\n");
		break;
	case SNDRV_PCM_TRIGGER_STOP:
	case SNDRV_PCM_TRIGGER_SUSPEND:
		tmp = snd_als300_gcr_read(chip->port, reg);
		snd_als300_gcr_write(chip->port, reg, tmp & ~TRANSFER_START);
		snd_als300_dbgplay("TRIGGER STOP\n");
		break;
	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
		tmp = snd_als300_gcr_read(chip->port, reg);
		snd_als300_gcr_write(chip->port, reg, tmp | FIFO_PAUSE);
		snd_als300_dbgplay("TRIGGER PAUSE\n");
		break;
	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
		tmp = snd_als300_gcr_read(chip->port, reg);
		snd_als300_gcr_write(chip->port, reg, tmp & ~FIFO_PAUSE);
		snd_als300_dbgplay("TRIGGER RELEASE\n");
		break;
	default:
		snd_als300_dbgplay("TRIGGER INVALID\n");
		ret = -EINVAL;
	}
	spin_unlock(&chip->reg_lock);
	snd_als300_dbgcallleave();
	return ret;
}
Ejemplo n.º 4
0
static irqreturn_t snd_als300plus_interrupt(int irq, void *dev_id)
{
	u8 general, mpu, dram;
	struct snd_als300 *chip = dev_id;
	struct snd_als300_substream_data *data;
	
	general = inb(chip->port+ALS300P_IRQ_STATUS);
	mpu = inb(chip->port+MPU_IRQ_STATUS);
	dram = inb(chip->port+ALS300P_DRAM_IRQ_STATUS);

	/* shared IRQ, for different device?? Exit ASAP! */
	if ((general == 0) && ((mpu & 0x80) == 0) && ((dram & 0x01) == 0))
		return IRQ_NONE;

	if (general & IRQ_PLAYBACK) {
		if (chip->pcm && chip->playback_substream) {
			outb(IRQ_PLAYBACK, chip->port+ALS300P_IRQ_STATUS);
			data = chip->playback_substream->runtime->private_data;
			data->period_flipflop ^= 1;
			snd_pcm_period_elapsed(chip->playback_substream);
			snd_als300_dbgplay("IRQ_PLAYBACK\n");
		}
	}
	if (general & IRQ_CAPTURE) {
		if (chip->pcm && chip->capture_substream) {
			outb(IRQ_CAPTURE, chip->port+ALS300P_IRQ_STATUS);
			data = chip->capture_substream->runtime->private_data;
			data->period_flipflop ^= 1;
			snd_pcm_period_elapsed(chip->capture_substream);
			snd_als300_dbgplay("IRQ_CAPTURE\n");
		}
	}
	/* FIXME: Ack other interrupt types. Not important right now as
	 * those other devices aren't enabled. */
	return IRQ_HANDLED;
}
Ejemplo n.º 5
0
static irqreturn_t snd_als300plus_interrupt(int irq, void *dev_id)
{
	u8 general, mpu, dram;
	struct snd_als300 *chip = dev_id;
	struct snd_als300_substream_data *data;
	
	general = inb(chip->port+ALS300P_IRQ_STATUS);
	mpu = inb(chip->port+MPU_IRQ_STATUS);
	dram = inb(chip->port+ALS300P_DRAM_IRQ_STATUS);

	/*                                               */
	if ((general == 0) && ((mpu & 0x80) == 0) && ((dram & 0x01) == 0))
		return IRQ_NONE;

	if (general & IRQ_PLAYBACK) {
		if (chip->pcm && chip->playback_substream) {
			outb(IRQ_PLAYBACK, chip->port+ALS300P_IRQ_STATUS);
			data = chip->playback_substream->runtime->private_data;
			data->period_flipflop ^= 1;
			snd_pcm_period_elapsed(chip->playback_substream);
			snd_als300_dbgplay("IRQ_PLAYBACK\n");
		}
	}
	if (general & IRQ_CAPTURE) {
		if (chip->pcm && chip->capture_substream) {
			outb(IRQ_CAPTURE, chip->port+ALS300P_IRQ_STATUS);
			data = chip->capture_substream->runtime->private_data;
			data->period_flipflop ^= 1;
			snd_pcm_period_elapsed(chip->capture_substream);
			snd_als300_dbgplay("IRQ_CAPTURE\n");
		}
	}
	/*                                                             
                                        */
	return IRQ_HANDLED;
}