patch-2.3.13 linux/drivers/char/hfmodem/wss.c

Next file: linux/drivers/char/isicom.c
Previous file: linux/drivers/char/hfmodem/sbc.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.3.12/linux/drivers/char/hfmodem/wss.c linux/drivers/char/hfmodem/wss.c
@@ -1,437 +0,0 @@
-/*****************************************************************************/
-
-/*
- *      wss.c  --  Linux soundcard HF FSK driver, 
- *                 WindowsSoundSystem specific functions.
- *
- *      Copyright (C) 1997  Thomas Sailer (sailer@ife.ee.ethz.ch)
- *        Swiss Federal Institute of Technology (ETH), Electronics Lab
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the GNU General Public License as published by
- *      the Free Software Foundation; either version 2 of the License, or
- *      (at your option) any later version.
- *
- *      This program is distributed in the hope that it will be useful,
- *      but WITHOUT ANY WARRANTY; without even the implied warranty of
- *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *      GNU General Public License for more details.
- *
- *      You should have received a copy of the GNU General Public License
- *      along with this program; if not, write to the Free Software
- *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- *
- */
-
-/*****************************************************************************/
-     
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/delay.h>
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/ioport.h>
-
-#include <asm/io.h>
-#include <asm/dma.h>
- 
-#include <linux/hfmodem.h>
-
-/* --------------------------------------------------------------------- */
-
-#define WSS_CONFIG(iobase)       (iobase+0)
-#define WSS_STATUS(iobase)       (iobase+3)
-#define WSS_CODEC_IA(iobase)     (iobase+4)
-#define WSS_CODEC_ID(iobase)     (iobase+5)
-#define WSS_CODEC_STATUS(iobase) (iobase+6)
-#define WSS_CODEC_DATA(iobase)   (iobase+7)
-
-#define WSS_EXTENT   8
-
-/* --------------------------------------------------------------------- */
-
-extern const struct hfmodem_scops wss_scops;
-
-/* --------------------------------------------------------------------- */
-
-static void write_codec(struct hfmodem_state *dev, unsigned char idx,
-                        unsigned char data)
-{
-        int timeout = 900000;
-
-        /* wait until codec ready */
-        while (timeout > 0 && inb(WSS_CODEC_IA(dev->io.base_addr)) & 0x80)
-                timeout--;
-        outb(idx, WSS_CODEC_IA(dev->io.base_addr));
-        outb(data, WSS_CODEC_ID(dev->io.base_addr));
-}
-
-/* --------------------------------------------------------------------- */
-
-static unsigned char read_codec(struct hfmodem_state *dev, unsigned char idx)
-{
-        int timeout = 900000;
-
-        /* wait until codec ready */
-        while (timeout > 0 && inb(WSS_CODEC_IA(dev->io.base_addr)) & 0x80)
-                timeout--;
-        outb(idx & 0x1f, WSS_CODEC_IA(dev->io.base_addr));
-        return inb(WSS_CODEC_ID(dev->io.base_addr));
-}
-
-/* --------------------------------------------------------------------- */
-
-extern __inline__ void wss_ack_int(struct hfmodem_state *dev)
-{
-        outb(0, WSS_CODEC_STATUS(dev->io.base_addr));
-}
-
-/* --------------------------------------------------------------------- */
-
-static int wss_srate_tab[16] = {
-        8000, 5510, 16000, 11025, 27420, 18900, 32000, 22050,
-        -1, 37800, -1, 44100, 48000, 33075, 9600, 6620
-};
-
-static int wss_srate_index(int srate)
-{
-        int i;
-
-        for (i = 0; i < (sizeof(wss_srate_tab)/sizeof(wss_srate_tab[0])); i++)
-                if (srate == wss_srate_tab[i] && wss_srate_tab[i] > 0)
-                        return i;
-        return -1;
-}
-
-/* --------------------------------------------------------------------- */
-
-static int wss_set_codec_fmt(struct hfmodem_state *dev, unsigned char fmt)
-{
-        unsigned long time;
-        unsigned long flags;
-
-        save_flags(flags);
-        cli();
-        /* Clock and data format register */
-        write_codec(dev, 0x48, fmt);
-	/* MCE and interface config reg */
-	write_codec(dev, 0x49, 0xc);
-        outb(0xb, WSS_CODEC_IA(dev->io.base_addr)); /* leave MCE */
-        /*
-         * wait for ACI start
-         */
-        time = 1000;
-        while (!(read_codec(dev, 0x0b) & 0x20))
-                if (!(--time)) {
-                        printk(KERN_WARNING "%s: ad1848 auto calibration timed out (1)\n", 
-                               hfmodem_drvname);
-                        restore_flags(flags);
-                        return -1;
-                }
-        /*
-         * wait for ACI end
-         */
-        sti();
-        time = jiffies + HZ/4;
-        while ((read_codec(dev, 0x0b) & 0x20) && ((signed)(jiffies - time) < 0));
-        restore_flags(flags);
-        if ((signed)(jiffies - time) >= 0) {
-                printk(KERN_WARNING "%s: ad1848 auto calibration timed out (2)\n", 
-                       hfmodem_drvname);
-                return -1;
-        }
-        return 0;
-}
-
-/* --------------------------------------------------------------------- */
-
-static int wss_init_codec(struct hfmodem_state *dev)
-{
-        unsigned char tmp, revwss, revid;
-        static const signed char irqtab[16] = { 
-		-1, -1, 0x10, -1, -1, -1, -1, 0x08, -1, 0x10, 0x18, 0x20, -1, -1, -1, -1 
-	};
-        static const signed char dmatab[4] = { 1, 2, -1, 3 };
-	int fmt;
-        
-	if ((fmt = wss_srate_index(HFMODEM_SRATE)) < 0) {
-		printk(KERN_ERR "%s: WSS: sampling rate not supported\n", hfmodem_drvname);
-		return -1;
-	}
-	fmt &= 0x0f;
-#ifdef __BIG_ENDIAN
-	fmt |= 0xc0;
-#else /* __BIG_ENDIAN */
-	fmt |= 0x40;
-#endif /* __BIG_ENDIAN */
-        tmp = inb(WSS_STATUS(dev->io.base_addr));
-        if ((tmp & 0x3f) != 0x04 && (tmp & 0x3f) != 0x00 && 
-            (tmp & 0x3f) != 0x0f) {
-                printk(KERN_WARNING "%s: WSS card id register not found, "
-                       "address 0x%x, ID register 0x%02x\n", hfmodem_drvname,
-                       dev->io.base_addr, (int)tmp);
-                /* return -1; */
-                revwss = 0;
-        } else {
-                if ((tmp & 0x80) && ((dev->io.dma == 0) || ((dev->io.irq >= 8) && (dev->io.irq != 9)))) {
-                        printk(KERN_ERR "%s: WSS: DMA0 and/or IRQ8..IRQ15 "
-                               "(except IRQ9) cannot be used on an 8bit "
-                               "card\n", hfmodem_drvname);
-                        return -1;
-                }               
-                if (dev->io.irq > 15 || irqtab[dev->io.irq] == -1) {
-                        printk(KERN_ERR "%s: WSS: invalid interrupt %d\n", 
-                               hfmodem_drvname, (int)dev->io.irq);
-                        return -1;
-                }
-                if (dev->io.dma > 3 || dmatab[dev->io.dma] == -1) {
-                        printk(KERN_ERR "%s: WSS: invalid dma channel %d\n", 
-                               hfmodem_drvname, (int)dev->io.dma);
-                        return -1;
-                }
-                tmp = irqtab[dev->io.irq] | dmatab[dev->io.dma];
-                /* irq probe */
-                outb((tmp & 0x38) | 0x40, WSS_CONFIG(dev->io.base_addr));
-                if (!(inb(WSS_STATUS(dev->io.base_addr)) & 0x40)) {
-                        outb(0, WSS_CONFIG(dev->io.base_addr));
-                        printk(KERN_ERR "%s: WSS: IRQ%d is not free!\n", 
-                               hfmodem_drvname, dev->io.irq);
-                }
-                outb(tmp, WSS_CONFIG(dev->io.base_addr));
-                revwss = inb(WSS_STATUS(dev->io.base_addr)) & 0x3f;
-        }
-        /*
-         * initialize the codec
-         */
-        write_codec(dev, 9, 0);
-	write_codec(dev, 12, 0);
-        write_codec(dev, 0, 0x45);
-        if (read_codec(dev, 0) != 0x45)
-                goto codec_err;
-        write_codec(dev, 0, 0xaa);
-        if (read_codec(dev, 0) != 0xaa)
-                goto codec_err;
-        if (wss_set_codec_fmt(dev, fmt))
-                goto codec_err;
-        write_codec(dev, 0, 0x40); /* left input control */
-        write_codec(dev, 1, 0x40); /* right input control */
-        write_codec(dev, 2, 0x80); /* left aux#1 input control */
-        write_codec(dev, 3, 0x80); /* right aux#1 input control */
-        write_codec(dev, 4, 0x80); /* left aux#2 input control */
-        write_codec(dev, 5, 0x80); /* right aux#2 input control */
-        write_codec(dev, 6, 0x80); /* left dac control */
-        write_codec(dev, 7, 0x80); /* right dac control */
-        write_codec(dev, 0xa, 0x2); /* pin control register */
-        write_codec(dev, 0xd, 0x0); /* digital mix control */
-        revid = read_codec(dev, 0xc) & 0xf;
-        /*
-         * print revisions
-         */        
-	printk(KERN_INFO "%s: WSS revision %d, CODEC revision %d\n", 
-	       hfmodem_drvname, (int)revwss, (int)revid);
-        return 0;
- codec_err:
-        outb(0, WSS_CONFIG(dev->io.base_addr));
-        printk(KERN_ERR "%s: no WSS soundcard found at address 0x%x\n", 
-               hfmodem_drvname, dev->io.base_addr);
-        return -1;
-}
-
-/* --------------------------------------------------------------------- */
-
-int hfmodem_wssprobe(struct hfmodem_state *dev)
-{
-	if (dev->io.base_addr <= 0 || dev->io.base_addr > 0x1000-WSS_EXTENT || 
-            dev->io.irq < 2 || dev->io.irq > 15 || dev->io.dma > 3 || dev->io.dma == 2)
-                return -ENXIO;
-        if (check_region(dev->io.base_addr, WSS_EXTENT))
-                return -EACCES;
-        /*
-         * check if a card is available
-         */
-        if (wss_init_codec(dev)) {
-                printk(KERN_ERR "%s: sbc: no card at io address 0x%x\n", 
-		       hfmodem_drvname, dev->io.base_addr);
-                return -ENODEV;
-        }
-	dev->scops = &wss_scops;
-	return 0;
-}
-
-/* --------------------------------------------------------------------- */
-
-static void wss_init(struct hfmodem_state *dev)
-{
-	wss_init_codec(dev);
-}
-
-/* --------------------------------------------------------------------- */
-
-static void wss_stop(struct hfmodem_state *dev)
-{
-	unsigned long flags;
-        unsigned char oldcodecmode;
-        long abrt;
-
-        save_flags(flags);
-        cli();
-        /*
-         * perform the final DMA sequence to disable the codec request
-         */
-        oldcodecmode = read_codec(dev, 9);
-        write_codec(dev, 9, 0xc); /* disable codec */
-        wss_ack_int(dev);
-        if (read_codec(dev, 11) & 0x10) {
-                disable_dma(dev->io.dma);
-                clear_dma_ff(dev->io.dma);
-                set_dma_mode(dev->io.dma, (oldcodecmode & 1) ? 
-			     (DMA_MODE_WRITE | DMA_MODE_AUTOINIT) : (DMA_MODE_READ | DMA_MODE_AUTOINIT));
-                set_dma_addr(dev->io.dma, virt_to_bus(dev->dma.buf));
-                set_dma_count(dev->io.dma, HFMODEM_NUMFRAGS * HFMODEM_FRAGSIZE);
-                enable_dma(dev->io.dma);
-                abrt = 0;
-                while ((read_codec(dev, 11) & 0x10) || ((++abrt) >= 0x10000));
-        }
-        disable_dma(dev->io.dma);
-        restore_flags(flags);
-}
-
-/* --------------------------------------------------------------------- */
-
-static void wss_prepare_input(struct hfmodem_state *dev)
-{
-	unsigned long flags;
-
-	wss_stop(dev);
-	save_flags(flags);
-        cli();
-        disable_dma(dev->io.dma);
-        clear_dma_ff(dev->io.dma);
-        set_dma_mode(dev->io.dma, DMA_MODE_READ | DMA_MODE_AUTOINIT);
-        set_dma_addr(dev->io.dma, virt_to_bus(dev->dma.buf));
-        set_dma_count(dev->io.dma, HFMODEM_NUMFRAGS * HFMODEM_FRAGSIZE);
-        enable_dma(dev->io.dma);
-        write_codec(dev, 15, (HFMODEM_FRAGSAMPLES-1) & 0xff);
-        write_codec(dev, 14, (HFMODEM_FRAGSAMPLES-1) >> 8);
-        restore_flags(flags);
-}
-
-/* --------------------------------------------------------------------- */
-
-static void wss_trigger_input(struct hfmodem_state *dev)
-{
-	unsigned long flags;
-
-	save_flags(flags);
-        cli();
-        write_codec(dev, 9, 0x0e);
-        restore_flags(flags);
-}
-
-/* --------------------------------------------------------------------- */
-
-static void wss_prepare_output(struct hfmodem_state *dev)
-{
-	unsigned long flags;
-
-	wss_stop(dev);
-        save_flags(flags);
-        cli();
-        disable_dma(dev->io.dma);
-        clear_dma_ff(dev->io.dma);
-        set_dma_mode(dev->io.dma, DMA_MODE_WRITE | DMA_MODE_AUTOINIT);
-        set_dma_addr(dev->io.dma, virt_to_bus(dev->dma.buf));
-        set_dma_count(dev->io.dma, HFMODEM_NUMFRAGS * HFMODEM_FRAGSIZE);
-        enable_dma(dev->io.dma);
-        write_codec(dev, 15, (HFMODEM_FRAGSAMPLES-1) & 0xff);
-        write_codec(dev, 14, (HFMODEM_FRAGSAMPLES-1) >> 8);
-        restore_flags(flags);
-}
-
-/* --------------------------------------------------------------------- */
-
-static void wss_trigger_output(struct hfmodem_state *dev)
-{
-	unsigned long flags;
-
-        save_flags(flags);
-        cli();
-        write_codec(dev, 9, 0x0d);
-        restore_flags(flags);
-}
-
-/* --------------------------------------------------------------------- */
-
-static unsigned int wss_intack(struct hfmodem_state *dev)
-{
-	unsigned int dmaptr, nums;
-	unsigned long flags;
-
-	save_flags(flags);
-        cli();
-	wss_ack_int(dev);
-        disable_dma(dev->io.dma);
-        clear_dma_ff(dev->io.dma);
-        dmaptr = get_dma_residue(dev->io.dma);
-	if (dmaptr == 0 || dmaptr > HFMODEM_NUMFRAGS * HFMODEM_FRAGSIZE)
-		dmaptr = HFMODEM_NUMFRAGS * HFMODEM_FRAGSIZE;
-	nums = (((dmaptr - 1) % HFMODEM_FRAGSIZE) - 1) / 2;
-        write_codec(dev, 15, nums  & 0xff);
-        write_codec(dev, 14, nums >> 8);
-        enable_dma(dev->io.dma);
-	restore_flags(flags);
-	return (HFMODEM_NUMFRAGS * HFMODEM_FRAGSIZE - dmaptr) / 2;
-}
-
-/* --------------------------------------------------------------------- */
-
-static void wss_mixer(struct hfmodem_state *dev, int src, int igain, int ogain)
-{
-	unsigned long flags;
-	static const unsigned char srctoreg[3] = { 1, 2, 0 };
-	static const unsigned char regtosrc[4] = { 2, 0, 1, 0 };
-	unsigned char tmp;
-
-	save_flags(flags);
-	cli();
-	tmp = read_codec(dev, 0x00);
-	if (src < 0 || src > 2)
-		src = regtosrc[(tmp >> 6) & 3];
-	if (igain < 0 || igain > 255) {
-		if (src == 1)
-			igain = ((tmp & 0xf) + ((tmp & 0x20) ? 13 : 0)) << 3;
-		else
-			igain = (tmp & 0xf) << 4;
-	}
-	if (src == 1) {
-		if (igain > (28<<3))
-			tmp = 0x2f;
-		else if (igain >= (13<<3))
-			tmp = 0x20 + (((igain >> 3) - 13) & 0xf);
-		else 
-			tmp = (igain >> 3) & 0xf;
-	} else 
-		tmp = (igain >> 4) & 0xf;
-	tmp |= srctoreg[src] << 6;
-	write_codec(dev, 0, tmp);
-	write_codec(dev, 1, tmp);
-	if (ogain > 0 && ogain <= 255) {
-		tmp = 63 - (ogain >> 2);
-		write_codec(dev, 6, tmp);
-		write_codec(dev, 7, tmp);
-	} else if (ogain == 0) {
-		write_codec(dev, 6, 0x80);
-		write_codec(dev, 7, 0x80);
-	}
-	restore_flags(flags);
-}
-
-/* --------------------------------------------------------------------- */
-
-static const struct hfmodem_scops wss_scops = {
-	WSS_EXTENT, wss_init, wss_prepare_input, wss_trigger_input, 
-	wss_prepare_output, wss_trigger_output, wss_stop, wss_intack, wss_mixer
-};
-
-/* --------------------------------------------------------------------- */

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)