Beispiel #1
0
/*
 * Wait for a DMA transfer to complete. This is a "limited busy-wait",
 * and all locking issues are left to the caller.
 */
static int sscape_wait_dma_unsafe(unsigned io_base, enum GA_REG reg, unsigned timeout)
{
	while (!(sscape_read_unsafe(io_base, reg) & 0x01) && (timeout != 0)) {
		udelay(100);
		--timeout;
	} /* while */

	return (sscape_read_unsafe(io_base, reg) & 0x01);
}
Beispiel #2
0
/*
 * Upload a byte-stream into the SoundScape using DMA channel A.
 */
static int upload_dma_data(struct soundscape *s,
                           const unsigned char __user *data,
                           size_t size)
{
	unsigned long flags;
	struct snd_dma_buffer dma;
	int ret;

	if (!get_dmabuf(&dma, PAGE_ALIGN(size)))
		return -ENOMEM;

	spin_lock_irqsave(&s->lock, flags);

	/*
	 * Reset the board ...
	 */
	sscape_write_unsafe(s->io_base, GA_HMCTL_REG, sscape_read_unsafe(s->io_base, GA_HMCTL_REG) & 0x3f);

	/*
	 * Enable the DMA channels and configure them ...
	 */
	sscape_write_unsafe(s->io_base, GA_DMACFG_REG, 0x50);
	sscape_write_unsafe(s->io_base, GA_DMAA_REG, (s->chip->dma1 << 4) | DMA_8BIT);
	sscape_write_unsafe(s->io_base, GA_DMAB_REG, 0x20);

	/*
	 * Take the board out of reset ...
	 */
	sscape_write_unsafe(s->io_base, GA_HMCTL_REG, sscape_read_unsafe(s->io_base, GA_HMCTL_REG) | 0x80);

	/*
	 * Upload the user's data (firmware?) to the SoundScape
	 * board through the DMA channel ...
	 */
	while (size != 0) {
		unsigned long len;

		/*
		 * Apparently, copying to/from userspace can sleep.
		 * We are therefore forbidden from holding any
		 * spinlocks while we copy ...
		 */
		spin_unlock_irqrestore(&s->lock, flags);

		/*
		 * Remember that the data that we want to DMA
		 * comes from USERSPACE. We have already verified
		 * the userspace pointer ...
		 */
		len = min(size, dma.bytes);
		len -= __copy_from_user(dma.area, data, len);
		data += len;
		size -= len;

		/*
		 * Grab that spinlock again, now that we've
		 * finished copying!
		 */
		spin_lock_irqsave(&s->lock, flags);

		snd_dma_program(s->chip->dma1, dma.addr, len, DMA_MODE_WRITE);
		sscape_start_dma_unsafe(s->io_base, GA_DMAA_REG);
		if (!sscape_wait_dma_unsafe(s->io_base, GA_DMAA_REG, 5000)) {
			/*
			 * Don't forget to release this spinlock we're holding ...
			 */
			spin_unlock_irqrestore(&s->lock, flags);

			snd_printk(KERN_ERR "sscape: DMA upload has timed out\n");
			ret = -EAGAIN;
			goto _release_dma;
		}
	} /* while */

	set_host_mode_unsafe(s->io_base);

	/*
	 * Boot the board ... (I think)
	 */
	sscape_write_unsafe(s->io_base, GA_HMCTL_REG, sscape_read_unsafe(s->io_base, GA_HMCTL_REG) | 0x40);
	spin_unlock_irqrestore(&s->lock, flags);

	/*
	 * If all has gone well, then the board should acknowledge
	 * the new upload and tell us that it has rebooted OK. We
	 * give it 5 seconds (max) ...
	 */
	ret = 0;
	if (!obp_startup_ack(s, 5)) {
		snd_printk(KERN_ERR "sscape: No response from on-board processor after upload\n");
		ret = -EAGAIN;
	} else if (!host_startup_ack(s, 5)) {
		snd_printk(KERN_ERR "sscape: SoundScape failed to initialise\n");
		ret = -EAGAIN;
	}

	_release_dma:
	/*
	 * NOTE!!! We are NOT holding any spinlocks at this point !!!
	 */
	sscape_write(s, GA_DMAA_REG, (s->ic_type == IC_ODIE ? 0x70 : 0x40));
	free_dmabuf(&dma);

	return ret;
}
Beispiel #3
0
/*
 * Tell the SoundScape to activate the AD1845 chip (I think).
 * The AD1845 detection fails if we *don't* do this, so I
 * think that this is a good idea ...
 */
static inline void activate_ad1845_unsafe(unsigned io_base)
{
	sscape_write_unsafe(io_base, GA_HMCTL_REG, (sscape_read_unsafe(io_base, GA_HMCTL_REG) & 0xcf) | 0x10);
	sscape_write_unsafe(io_base, GA_CDCFG_REG, 0x80);
}
Beispiel #4
0
/*
 * Tell the SoundScape to begin a DMA tranfer using the given channel.
 * All locking issues are left to the caller.
 */
static inline void sscape_start_dma_unsafe(unsigned io_base, enum GA_REG reg)
{
	sscape_write_unsafe(io_base, reg, sscape_read_unsafe(io_base, reg) | 0x01);
	sscape_write_unsafe(io_base, reg, sscape_read_unsafe(io_base, reg) & 0xfe);
}
Beispiel #5
0
/*
 * Perform certain arcane port-checks to see whether there
 * is a SoundScape board lurking behind the given ports.
 */
static int __devinit detect_sscape(struct soundscape *s)
{
	unsigned long flags;
	unsigned d;
	int retval = 0;
	int codec = s->wss_base;

	spin_lock_irqsave(&s->lock, flags);

	/*
	 * The following code is lifted from the original OSS driver,
	 * and as I don't have a datasheet I cannot really comment
	 * on what it is doing...
	 */
	if ((inb(HOST_CTRL_IO(s->io_base)) & 0x78) != 0)
		goto _done;

	d = inb(ODIE_ADDR_IO(s->io_base)) & 0xf0;
	if ((d & 0x80) != 0)
		goto _done;

	if (d == 0) {
		s->codec_type = 1;
		s->ic_type = IC_ODIE;
	} else if ((d & 0x60) != 0) {
		s->codec_type = 2;
		s->ic_type = IC_OPUS;
	} else
		goto _done;

	outb(0xfa, ODIE_ADDR_IO(s->io_base));
	if ((inb(ODIE_ADDR_IO(s->io_base)) & 0x9f) != 0x0a)
		goto _done;

	outb(0xfe, ODIE_ADDR_IO(s->io_base));
	if ((inb(ODIE_ADDR_IO(s->io_base)) & 0x9f) != 0x0e)
		goto _done;

	outb(0xfe, ODIE_ADDR_IO(s->io_base));
	d = inb(ODIE_DATA_IO(s->io_base));
	if (s->type != SSCAPE_VIVO && (d & 0x9f) != 0x0e)
		goto _done;

	d  = sscape_read_unsafe(s->io_base, GA_HMCTL_REG) & 0x3f;
	sscape_write_unsafe(s->io_base, GA_HMCTL_REG, d | 0xc0);

	if (s->type == SSCAPE_VIVO)
		codec += 4;
	/* wait for WSS codec */
	for (d = 0; d < 500; d++) {
		if ((inb(codec) & 0x80) == 0)
			break;
		spin_unlock_irqrestore(&s->lock, flags);
		msleep(1);
		spin_lock_irqsave(&s->lock, flags);
	}
	snd_printd(KERN_INFO "init delay = %d ms\n", d);

	/*
	 * SoundScape successfully detected!
	 */
	retval = 1;

	_done:
	spin_unlock_irqrestore(&s->lock, flags);
	return retval;
}