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
- Lines: 438
- Date:
Wed Dec 31 16:00:00 1969
- Orig file:
v2.3.12/linux/drivers/char/hfmodem/wss.c
- Orig date:
Tue Aug 5 09:48:55 1997
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)