Dan,

Shall this driver be removed?

On Sun, Mar 25, 2007 at 04:58:38PM +0200, Adrian Bunk wrote:
> Recently, someone fixed a syntax error in the HTDMSOUND driver 
> introduced 4 years ago.
> 
> Unfortunately not by trying to compile this driver for his hardware but 
> by code inspection - which seems to be a strong indication that there 
> are no users left for this OSS sound driver.
> 
> This patch therefore removes it.
> 
> Signed-off-by: Adrian Bunk <bunk at stusta.de>
> 
> ---
> 
> This patch was already sent on:
> - 7 Mar 2007
> 
>  arch/ppc/8xx_io/Kconfig         |    4 
>  arch/ppc/8xx_io/Makefile        |    1 
>  arch/ppc/8xx_io/cs4218.h        |  166 -
>  arch/ppc/8xx_io/cs4218_tdm.c    | 2833 --------------------------------
>  arch/ppc/platforms/rpxclassic.h |    4 
>  arch/ppc/platforms/rpxhiox.h    |   41 
>  arch/ppc/platforms/rpxlite.h    |    4 
>  arch/ppc/syslib/m8xx_setup.c    |    2 
>  8 files changed, 1 insertion(+), 3054 deletions(-)
> 
> --- linux-2.6.21-rc2-mm1/arch/ppc/8xx_io/Kconfig.old  2007-03-06 
> 06:47:04.000000000 +0100
> +++ linux-2.6.21-rc2-mm1/arch/ppc/8xx_io/Kconfig      2007-03-06 
> 06:47:16.000000000 +0100
> @@ -74,10 +74,6 @@
>         Allocate large buffers for MPC8xx Ethernet. Increases throughput
>         and decreases the likelihood of dropped packets, but costs memory.
>  
> -config HTDMSOUND
> -     bool "Embedded Planet HIOX Audio"
> -     depends on SOUND=y
> -
>  # This doesn't really belong here, but it is convenient to ask
>  # 8xx specific questions.
>  comment "Generic MPC8xx Options"
> --- linux-2.6.21-rc2-mm1/arch/ppc/8xx_io/Makefile.old 2007-03-06 
> 06:47:23.000000000 +0100
> +++ linux-2.6.21-rc2-mm1/arch/ppc/8xx_io/Makefile     2007-03-06 
> 06:47:30.000000000 +0100
> @@ -7,4 +7,3 @@
>  obj-$(CONFIG_FEC_ENET)       += fec.o
>  obj-$(CONFIG_SCC_ENET)       += enet.o
>  obj-$(CONFIG_UCODE_PATCH) += micropatch.o
> -obj-$(CONFIG_HTDMSOUND) += cs4218_tdm.o
> --- linux-2.6.21-rc2-mm1/arch/ppc/platforms/rpxlite.h.old     2007-03-06 
> 06:49:05.000000000 +0100
> +++ linux-2.6.21-rc2-mm1/arch/ppc/platforms/rpxlite.h 2007-03-06 
> 06:49:41.000000000 +0100
> @@ -57,10 +57,6 @@
>  #define BCSR1_PCVCTL6          ((uint)0x00020000)
>  #define BCSR1_PCVCTL7          ((uint)0x00010000)
>  
> -#if defined(CONFIG_HTDMSOUND)
> -#include <platforms/rpxhiox.h>
> -#endif
> -
>  /* define IO_BASE for pcmcia */
>  #define _IO_BASE 0x80000000
>  #define _IO_BASE_SIZE 0x1000
> --- linux-2.6.21-rc2-mm1/arch/ppc/platforms/rpxclassic.h.old  2007-03-06 
> 06:49:51.000000000 +0100
> +++ linux-2.6.21-rc2-mm1/arch/ppc/platforms/rpxclassic.h      2007-03-06 
> 06:49:56.000000000 +0100
> @@ -69,10 +69,6 @@
>  #define BCSR2_QSPACESEL              ((uint)0x00004000)
>  #define BCSR2_FETHLEDMODE    ((uint)0x00000800)      /* CLLF */
>  
> -#if defined(CONFIG_HTDMSOUND)
> -#include <platforms/rpxhiox.h>
> -#endif
> -
>  /* define IO_BASE for pcmcia, CLLF only */
>  #if !defined(CONFIG_PCI)
>  #define _IO_BASE 0x80000000
> --- linux-2.6.21-rc2-mm1/arch/ppc/syslib/m8xx_setup.c.old     2007-03-06 
> 06:50:43.000000000 +0100
> +++ linux-2.6.21-rc2-mm1/arch/ppc/syslib/m8xx_setup.c 2007-03-06 
> 06:50:59.000000000 +0100
> @@ -413,7 +413,7 @@
>       io_block_mapping(_IO_BASE,_IO_BASE,_IO_BASE_SIZE, _PAGE_IO);
>  #endif
>  #endif
> -#if defined(CONFIG_HTDMSOUND) || defined(CONFIG_RPXTOUCH) || 
> defined(CONFIG_FB_RPX)
> +#if defined(CONFIG_RPXTOUCH) || defined(CONFIG_FB_RPX)
>       io_block_mapping(HIOX_CSR_ADDR, HIOX_CSR_ADDR, HIOX_CSR_SIZE, _PAGE_IO);
>  #endif
>  #ifdef CONFIG_FADS
> --- linux-2.6.21-rc2-mm1/arch/ppc/platforms/rpxhiox.h 2007-02-04 
> 19:44:54.000000000 +0100
> +++ /dev/null 2006-09-19 00:45:31.000000000 +0200
> @@ -1,41 +0,0 @@
> -/*
> - * The Embedded Planet HIOX expansion card definitions.
> - * There were a few different versions of these cards, but only
> - * the one that escaped real production is defined here.
> - *
> - * Copyright (c) 2000 Dan Malek (dmalek at jlc.net)
> - */
> -#ifndef __MACH_RPX_HIOX_DEFS
> -#define __MACH_RPX_HIOX_DEFS
> -
> -#define HIOX_CSR_ADDR                ((uint)0xfac00000)
> -#define HIOX_CSR_SIZE                ((uint)(4 * 1024))
> -#define HIOX_CSR0_ADDR               HIOX_CSR_ADDR
> -#define HIOX_CSR4_ADDR               ((uint)0xfac00004)
> -
> -#define HIOX_CSR0_DEFAULT    ((uint)0x380f3c00)
> -#define HIOX_CSR0_ENSCC2     ((uint)0x80000000)
> -#define HIOX_CSR0_ENSMC2     ((uint)0x04000000)
> -#define HIOX_CSR0_ENVDOCLK   ((uint)0x02000000)
> -#define HIOX_CSR0_VDORST_HL  ((uint)0x01000000)
> -#define HIOX_CSR0_RS232SEL   ((uint)0x0000c000)
> -#define HIOX_CSR0_SCC3SEL    ((uint)0x0000c000)
> -#define HIOX_CSR0_SMC1SEL    ((uint)0x00008000)
> -#define HIOX_CSR0_SCC1SEL    ((uint)0x00004000)
> -#define HIOX_CSR0_ENTOUCH    ((uint)0x00000080)
> -#define HIOX_CSR0_PDOWN100   ((uint)0x00000060)
> -#define HIOX_CSR0_PDOWN10    ((uint)0x00000040)
> -#define HIOX_CSR0_PDOWN1     ((uint)0x00000020)
> -#define HIOX_CSR0_TSELSPI    ((uint)0x00000010)
> -#define HIOX_CSR0_TIRQSTAT   ((uint)0x00000008)
> -#define HIOX_CSR4_DEFAULT    ((uint)0x00000000)
> -#define HIOX_CSR4_ENTIRQ2    ((uint)0x20000000)
> -#define HIOX_CSR4_ENTIRQ3    ((uint)0x10000000)
> -#define HIOX_CSR4_ENAUDIO    ((uint)0x00000080)
> -#define HIOX_CSR4_RSTAUDIO   ((uint)0x00000040)      /* 0 == reset */
> -#define HIOX_CSR4_AUDCLKHI   ((uint)0x00000020)
> -#define HIOX_CSR4_AUDSPISEL  ((uint)0x00000010)
> -#define HIOX_CSR4_AUDIRQSTAT ((uint)0x00000008)
> -#define HIOX_CSR4_AUDCLKSEL  ((uint)0x00000007)
> -
> -#endif
> --- linux-2.6.21-rc2-mm1/arch/ppc/8xx_io/cs4218.h     2007-02-04 
> 19:44:54.000000000 +0100
> +++ /dev/null 2006-09-19 00:45:31.000000000 +0200
> @@ -1,166 +0,0 @@
> -#ifndef _cs4218_h_
> -/*
> - *  Hacked version of linux/drivers/sound/dmasound/dmasound.h
> - *
> - *
> - *  Minor numbers for the sound driver.
> - *
> - *  Unfortunately Creative called the codec chip of SB as a DSP. For this
> - *  reason the /dev/dsp is reserved for digitized audio use. There is a
> - *  device for true DSP processors but it will be called something else.
> - *  In v3.0 it's /dev/sndproc but this could be a temporary solution.
> - */
> -#define _cs4218_h_
> -
> -#include <linux/types.h>
> -
> -#define SND_NDEVS    256     /* Number of supported devices */
> -#define SND_DEV_CTL  0       /* Control port /dev/mixer */
> -#define SND_DEV_SEQ  1       /* Sequencer output /dev/sequencer (FM
> -                                synthesizer and MIDI output) */
> -#define SND_DEV_MIDIN        2       /* Raw midi access */
> -#define SND_DEV_DSP  3       /* Digitized voice /dev/dsp */
> -#define SND_DEV_AUDIO        4       /* Sparc compatible /dev/audio */
> -#define SND_DEV_DSP16        5       /* Like /dev/dsp but 16 bits/sample */
> -#define SND_DEV_STATUS       6       /* /dev/sndstat */
> -/* #7 not in use now. Was in 2.4. Free for use after v3.0. */
> -#define SND_DEV_SEQ2 8       /* /dev/sequencer, level 2 interface */
> -#define SND_DEV_SNDPROC 9    /* /dev/sndproc for programmable devices */
> -#define SND_DEV_PSS  SND_DEV_SNDPROC
> -
> -/* switch on various prinks */
> -#define DEBUG_DMASOUND 1
> -
> -#define MAX_AUDIO_DEV        5
> -#define MAX_MIXER_DEV        4
> -#define MAX_SYNTH_DEV        3
> -#define MAX_MIDI_DEV 6
> -#define MAX_TIMER_DEV        3
> -
> -#define MAX_CATCH_RADIUS     10
> -
> -#define le2be16(x)   (((x)<<8 & 0xff00) | ((x)>>8 & 0x00ff))
> -#define le2be16dbl(x)        (((x)<<8 & 0xff00ff00) | ((x)>>8 & 0x00ff00ff))
> -
> -#define IOCTL_IN(arg, ret) \
> -     do { int error = get_user(ret, (int *)(arg)); \
> -             if (error) return error; \
> -     } while (0)
> -#define IOCTL_OUT(arg, ret)  ioctl_return((int *)(arg), ret)
> -
> -static inline int ioctl_return(int *addr, int value)
> -{
> -     return value < 0 ? value : put_user(value, addr);
> -}
> -
> -#define HAS_RECORD
> -
> -    /*
> -     *  Initialization
> -     */
> -
> -/* description of the set-up applies to either hard or soft settings */
> -
> -typedef struct {
> -    int format;              /* AFMT_* */
> -    int stereo;              /* 0 = mono, 1 = stereo */
> -    int size;                /* 8/16 bit*/
> -    int speed;               /* speed */
> -} SETTINGS;
> -
> -    /*
> -     *  Machine definitions
> -     */
> -
> -typedef struct {
> -    const char *name;
> -    const char *name2;
> -    void (*open)(void);
> -    void (*release)(void);
> -    void *(*dma_alloc)(unsigned int, gfp_t);
> -    void (*dma_free)(void *, unsigned int);
> -    int (*irqinit)(void);
> -#ifdef MODULE
> -    void (*irqcleanup)(void);
> -#endif
> -    void (*init)(void);
> -    void (*silence)(void);
> -    int (*setFormat)(int);
> -    int (*setVolume)(int);
> -    int (*setBass)(int);
> -    int (*setTreble)(int);
> -    int (*setGain)(int);
> -    void (*play)(void);
> -    void (*record)(void);            /* optional */
> -    void (*mixer_init)(void);                /* optional */
> -    int (*mixer_ioctl)(u_int, u_long);       /* optional */
> -    int (*write_sq_setup)(void);     /* optional */
> -    int (*read_sq_setup)(void);              /* optional */
> -    int (*sq_open)(mode_t);          /* optional */
> -    int (*state_info)(char *, size_t);       /* optional */
> -    void (*abort_read)(void);                /* optional */
> -    int min_dsp_speed;
> -    int max_dsp_speed;
> -    int version ;
> -    int hardware_afmts ;             /* OSS says we only return h'ware info 
> */
> -                                     /* when queried via SNDCTL_DSP_GETFMTS 
> */
> -    int capabilities ;               /* low-level reply to 
> SNDCTL_DSP_GETCAPS */
> -    SETTINGS default_hard ;  /* open() or init() should set something valid 
> */
> -    SETTINGS default_soft ;  /* you can make it look like old OSS, if you 
> want to */
> -} MACHINE;
> -
> -    /*
> -     *  Low level stuff
> -     */
> -
> -typedef struct {
> -    ssize_t (*ct_ulaw)(const u_char *, size_t, u_char *, ssize_t *, ssize_t);
> -    ssize_t (*ct_alaw)(const u_char *, size_t, u_char *, ssize_t *, ssize_t);
> -    ssize_t (*ct_s8)(const u_char *, size_t, u_char *, ssize_t *, ssize_t);
> -    ssize_t (*ct_u8)(const u_char *, size_t, u_char *, ssize_t *, ssize_t);
> -    ssize_t (*ct_s16be)(const u_char *, size_t, u_char *, ssize_t *, 
> ssize_t);
> -    ssize_t (*ct_u16be)(const u_char *, size_t, u_char *, ssize_t *, 
> ssize_t);
> -    ssize_t (*ct_s16le)(const u_char *, size_t, u_char *, ssize_t *, 
> ssize_t);
> -    ssize_t (*ct_u16le)(const u_char *, size_t, u_char *, ssize_t *, 
> ssize_t);
> -} TRANS;
> -
> -
> -    /*
> -     * Sound queue stuff, the heart of the driver
> -     */
> -
> -struct sound_queue {
> -    /* buffers allocated for this queue */
> -    int numBufs;             /* real limits on what the user can have */
> -    int bufSize;             /* in bytes */
> -    char **buffers;
> -
> -    /* current parameters */
> -    int locked ;             /* params cannot be modified when != 0 */
> -    int user_frags ;         /* user requests this many */
> -    int user_frag_size ;     /* of this size */
> -    int max_count;           /* actual # fragments <= numBufs */
> -    int block_size;          /* internal block size in bytes */
> -    int max_active;          /* in-use fragments <= max_count */
> -
> -    /* it shouldn't be necessary to declare any of these volatile */
> -    int front, rear, count;
> -    int rear_size;
> -    /*
> -     *       The use of the playing field depends on the hardware
> -     *
> -     *       Atari, PMac: The number of frames that are loaded/playing
> -     *
> -     *       Amiga: Bit 0 is set: a frame is loaded
> -     *              Bit 1 is set: a frame is playing
> -     */
> -    int active;
> -    wait_queue_head_t action_queue, open_queue, sync_queue;
> -    int open_mode;
> -    int busy, syncing, xruns, died;
> -};
> -
> -#define SLEEP(queue)         interruptible_sleep_on_timeout(&queue, HZ)
> -#define WAKE_UP(queue)               (wake_up_interruptible(&queue))
> -
> -#endif /* _cs4218_h_ */
> --- linux-2.6.21-rc2-mm1/arch/ppc/8xx_io/cs4218_tdm.c 2007-03-02 
> 20:14:59.000000000 +0100
> +++ /dev/null 2006-09-19 00:45:31.000000000 +0200
> @@ -1,2833 +0,0 @@
> -
> -/* This is a modified version of linux/drivers/sound/dmasound.c to
> - * support the CS4218 codec on the 8xx TDM port.  Thanks to everyone
> - * that contributed to the dmasound software (which includes me :-).
> - *
> - * The CS4218 is configured in Mode 4, sub-mode 0.  This provides
> - * left/right data only on the TDM port, as a 32-bit word, per frame
> - * pulse.  The control of the CS4218 is provided by some other means,
> - * like the SPI port.
> - * Dan Malek (dmalek at jlc.net)
> - */
> -
> -#include <linux/module.h>
> -#include <linux/sched.h>
> -#include <linux/timer.h>
> -#include <linux/major.h>
> -#include <linux/fcntl.h>
> -#include <linux/errno.h>
> -#include <linux/mm.h>
> -#include <linux/slab.h>
> -#include <linux/sound.h>
> -#include <linux/init.h>
> -#include <linux/delay.h>
> -
> -#include <asm/system.h>
> -#include <asm/irq.h>
> -#include <asm/pgtable.h>
> -#include <asm/uaccess.h>
> -#include <asm/io.h>
> -
> -/* Should probably do something different with this path name.....
> - * Actually, I should just stop using it...
> - */
> -#include "cs4218.h"
> -#include <linux/soundcard.h>
> -
> -#include <asm/mpc8xx.h>
> -#include <asm/8xx_immap.h>
> -#include <asm/commproc.h>
> -
> -#define DMASND_CS4218                5
> -
> -#define MAX_CATCH_RADIUS     10
> -#define MIN_BUFFERS          4
> -#define MIN_BUFSIZE          4
> -#define MAX_BUFSIZE          128
> -
> -#define HAS_8BIT_TABLES
> -
> -static int sq_unit = -1;
> -static int mixer_unit = -1;
> -static int state_unit = -1;
> -static int irq_installed = 0;
> -static char **sound_buffers = NULL;
> -static char **sound_read_buffers = NULL;
> -
> -static DEFINE_SPINLOCK(cs4218_lock);
> -
> -/* Local copies of things we put in the control register.  Output
> - * volume, like most codecs is really attenuation.
> - */
> -static int cs4218_rate_index;
> -
> -/*
> - * Stuff for outputting a beep.  The values range from -327 to +327
> - * so we can multiply by an amplitude in the range 0..100 to get a
> - * signed short value to put in the output buffer.
> - */
> -static short beep_wform[256] = {
> -     0,      40,     79,     117,    153,    187,    218,    245,
> -     269,    288,    304,    316,    323,    327,    327,    324,
> -     318,    310,    299,    288,    275,    262,    249,    236,
> -     224,    213,    204,    196,    190,    186,    183,    182,
> -     182,    183,    186,    189,    192,    196,    200,    203,
> -     206,    208,    209,    209,    209,    207,    204,    201,
> -     197,    193,    188,    183,    179,    174,    170,    166,
> -     163,    161,    160,    159,    159,    160,    161,    162,
> -     164,    166,    168,    169,    171,    171,    171,    170,
> -     169,    167,    163,    159,    155,    150,    144,    139,
> -     133,    128,    122,    117,    113,    110,    107,    105,
> -     103,    103,    103,    103,    104,    104,    105,    105,
> -     105,    103,    101,    97,     92,     86,     78,     68,
> -     58,     45,     32,     18,     3,      -11,    -26,    -41,
> -     -55,    -68,    -79,    -88,    -95,    -100,   -102,   -102,
> -     -99,    -93,    -85,    -75,    -62,    -48,    -33,    -16,
> -     0,      16,     33,     48,     62,     75,     85,     93,
> -     99,     102,    102,    100,    95,     88,     79,     68,
> -     55,     41,     26,     11,     -3,     -18,    -32,    -45,
> -     -58,    -68,    -78,    -86,    -92,    -97,    -101,   -103,
> -     -105,   -105,   -105,   -104,   -104,   -103,   -103,   -103,
> -     -103,   -105,   -107,   -110,   -113,   -117,   -122,   -128,
> -     -133,   -139,   -144,   -150,   -155,   -159,   -163,   -167,
> -     -169,   -170,   -171,   -171,   -171,   -169,   -168,   -166,
> -     -164,   -162,   -161,   -160,   -159,   -159,   -160,   -161,
> -     -163,   -166,   -170,   -174,   -179,   -183,   -188,   -193,
> -     -197,   -201,   -204,   -207,   -209,   -209,   -209,   -208,
> -     -206,   -203,   -200,   -196,   -192,   -189,   -186,   -183,
> -     -182,   -182,   -183,   -186,   -190,   -196,   -204,   -213,
> -     -224,   -236,   -249,   -262,   -275,   -288,   -299,   -310,
> -     -318,   -324,   -327,   -327,   -323,   -316,   -304,   -288,
> -     -269,   -245,   -218,   -187,   -153,   -117,   -79,    -40,
> -};
> -
> -#define BEEP_SPEED   5       /* 22050 Hz sample rate */
> -#define BEEP_BUFLEN  512
> -#define BEEP_VOLUME  15      /* 0 - 100 */
> -
> -static int beep_volume = BEEP_VOLUME;
> -static int beep_playing = 0;
> -static int beep_state = 0;
> -static short *beep_buf;
> -static void (*orig_mksound)(unsigned int, unsigned int);
> -
> -/* This is found someplace else......I guess in the keyboard driver
> - * we don't include.
> - */
> -static void (*kd_mksound)(unsigned int, unsigned int);
> -
> -static int catchRadius = 0;
> -static int numBufs = 4, bufSize = 32;
> -static int numReadBufs = 4, readbufSize = 32;
> -
> -
> -/* TDM/Serial transmit and receive buffer descriptors.
> -*/
> -static volatile cbd_t        *rx_base, *rx_cur, *tx_base, *tx_cur;
> -
> -module_param(catchRadius, int, 0);
> -module_param(numBufs, int, 0);
> -module_param(bufSize, int, 0);
> -module_param(numreadBufs, int, 0);
> -module_param(readbufSize, int, 0);
> -
> -#define arraysize(x) (sizeof(x)/sizeof(*(x)))
> -#define le2be16(x)   (((x)<<8 & 0xff00) | ((x)>>8 & 0x00ff))
> -#define le2be16dbl(x)        (((x)<<8 & 0xff00ff00) | ((x)>>8 & 0x00ff00ff))
> -
> -#define IOCTL_IN(arg, ret) \
> -     do { int error = get_user(ret, (int *)(arg)); \
> -             if (error) return error; \
> -     } while (0)
> -#define IOCTL_OUT(arg, ret)  ioctl_return((int *)(arg), ret)
> -
> -/* CS4218 serial port control in mode 4.
> -*/
> -#define CS_INTMASK   ((uint)0x40000000)
> -#define CS_DO1               ((uint)0x20000000)
> -#define CS_LATTEN    ((uint)0x1f000000)
> -#define CS_RATTEN    ((uint)0x00f80000)
> -#define CS_MUTE              ((uint)0x00040000)
> -#define CS_ISL               ((uint)0x00020000)
> -#define CS_ISR               ((uint)0x00010000)
> -#define CS_LGAIN     ((uint)0x0000f000)
> -#define CS_RGAIN     ((uint)0x00000f00)
> -
> -#define CS_LATTEN_SET(X)     (((X) & 0x1f) << 24)
> -#define CS_RATTEN_SET(X)     (((X) & 0x1f) << 19)
> -#define CS_LGAIN_SET(X)              (((X) & 0x0f) << 12)
> -#define CS_RGAIN_SET(X)              (((X) & 0x0f) << 8)
> -
> -#define CS_LATTEN_GET(X)     (((X) >> 24) & 0x1f)
> -#define CS_RATTEN_GET(X)     (((X) >> 19) & 0x1f)
> -#define CS_LGAIN_GET(X)              (((X) >> 12) & 0x0f)
> -#define CS_RGAIN_GET(X)              (((X) >> 8) & 0x0f)
> -
> -/* The control register is effectively write only.  We have to keep a copy
> - * of what we write.
> - */
> -static       uint    cs4218_control;
> -
> -/* A place to store expanding information.
> -*/
> -static int   expand_bal;
> -static int   expand_data;
> -
> -/* Since I can't make the microcode patch work for the SPI, I just
> - * clock the bits using software.
> - */
> -static       void    sw_spi_init(void);
> -static       void    sw_spi_io(u_char *obuf, u_char *ibuf, uint bcnt);
> -static       uint    cs4218_ctl_write(uint ctlreg);
> -
> -/*** Some low level helpers 
> **************************************************/
> -
> -/* 16 bit mu-law */
> -
> -static short ulaw2dma16[] = {
> -     -32124, -31100, -30076, -29052, -28028, -27004, -25980, -24956,
> -     -23932, -22908, -21884, -20860, -19836, -18812, -17788, -16764,
> -     -15996, -15484, -14972, -14460, -13948, -13436, -12924, -12412,
> -     -11900, -11388, -10876, -10364, -9852,  -9340,  -8828,  -8316,
> -     -7932,  -7676,  -7420,  -7164,  -6908,  -6652,  -6396,  -6140,
> -     -5884,  -5628,  -5372,  -5116,  -4860,  -4604,  -4348,  -4092,
> -     -3900,  -3772,  -3644,  -3516,  -3388,  -3260,  -3132,  -3004,
> -     -2876,  -2748,  -2620,  -2492,  -2364,  -2236,  -2108,  -1980,
> -     -1884,  -1820,  -1756,  -1692,  -1628,  -1564,  -1500,  -1436,
> -     -1372,  -1308,  -1244,  -1180,  -1116,  -1052,  -988,   -924,
> -     -876,   -844,   -812,   -780,   -748,   -716,   -684,   -652,
> -     -620,   -588,   -556,   -524,   -492,   -460,   -428,   -396,
> -     -372,   -356,   -340,   -324,   -308,   -292,   -276,   -260,
> -     -244,   -228,   -212,   -196,   -180,   -164,   -148,   -132,
> -     -120,   -112,   -104,   -96,    -88,    -80,    -72,    -64,
> -     -56,    -48,    -40,    -32,    -24,    -16,    -8,     0,
> -     32124,  31100,  30076,  29052,  28028,  27004,  25980,  24956,
> -     23932,  22908,  21884,  20860,  19836,  18812,  17788,  16764,
> -     15996,  15484,  14972,  14460,  13948,  13436,  12924,  12412,
> -     11900,  11388,  10876,  10364,  9852,   9340,   8828,   8316,
> -     7932,   7676,   7420,   7164,   6908,   6652,   6396,   6140,
> -     5884,   5628,   5372,   5116,   4860,   4604,   4348,   4092,
> -     3900,   3772,   3644,   3516,   3388,   3260,   3132,   3004,
> -     2876,   2748,   2620,   2492,   2364,   2236,   2108,   1980,
> -     1884,   1820,   1756,   1692,   1628,   1564,   1500,   1436,
> -     1372,   1308,   1244,   1180,   1116,   1052,   988,    924,
> -     876,    844,    812,    780,    748,    716,    684,    652,
> -     620,    588,    556,    524,    492,    460,    428,    396,
> -     372,    356,    340,    324,    308,    292,    276,    260,
> -     244,    228,    212,    196,    180,    164,    148,    132,
> -     120,    112,    104,    96,     88,     80,     72,     64,
> -     56,     48,     40,     32,     24,     16,     8,      0,
> -};
> -
> -/* 16 bit A-law */
> -
> -static short alaw2dma16[] = {
> -     -5504,  -5248,  -6016,  -5760,  -4480,  -4224,  -4992,  -4736,
> -     -7552,  -7296,  -8064,  -7808,  -6528,  -6272,  -7040,  -6784,
> -     -2752,  -2624,  -3008,  -2880,  -2240,  -2112,  -2496,  -2368,
> -     -3776,  -3648,  -4032,  -3904,  -3264,  -3136,  -3520,  -3392,
> -     -22016, -20992, -24064, -23040, -17920, -16896, -19968, -18944,
> -     -30208, -29184, -32256, -31232, -26112, -25088, -28160, -27136,
> -     -11008, -10496, -12032, -11520, -8960,  -8448,  -9984,  -9472,
> -     -15104, -14592, -16128, -15616, -13056, -12544, -14080, -13568,
> -     -344,   -328,   -376,   -360,   -280,   -264,   -312,   -296,
> -     -472,   -456,   -504,   -488,   -408,   -392,   -440,   -424,
> -     -88,    -72,    -120,   -104,   -24,    -8,     -56,    -40,
> -     -216,   -200,   -248,   -232,   -152,   -136,   -184,   -168,
> -     -1376,  -1312,  -1504,  -1440,  -1120,  -1056,  -1248,  -1184,
> -     -1888,  -1824,  -2016,  -1952,  -1632,  -1568,  -1760,  -1696,
> -     -688,   -656,   -752,   -720,   -560,   -528,   -624,   -592,
> -     -944,   -912,   -1008,  -976,   -816,   -784,   -880,   -848,
> -     5504,   5248,   6016,   5760,   4480,   4224,   4992,   4736,
> -     7552,   7296,   8064,   7808,   6528,   6272,   7040,   6784,
> -     2752,   2624,   3008,   2880,   2240,   2112,   2496,   2368,
> -     3776,   3648,   4032,   3904,   3264,   3136,   3520,   3392,
> -     22016,  20992,  24064,  23040,  17920,  16896,  19968,  18944,
> -     30208,  29184,  32256,  31232,  26112,  25088,  28160,  27136,
> -     11008,  10496,  12032,  11520,  8960,   8448,   9984,   9472,
> -     15104,  14592,  16128,  15616,  13056,  12544,  14080,  13568,
> -     344,    328,    376,    360,    280,    264,    312,    296,
> -     472,    456,    504,    488,    408,    392,    440,    424,
> -     88,     72,     120,    104,    24,     8,      56,     40,
> -     216,    200,    248,    232,    152,    136,    184,    168,
> -     1376,   1312,   1504,   1440,   1120,   1056,   1248,   1184,
> -     1888,   1824,   2016,   1952,   1632,   1568,   1760,   1696,
> -     688,    656,    752,    720,    560,    528,    624,    592,
> -     944,    912,    1008,   976,    816,    784,    880,    848,
> -};
> -
> -
> -/*** Translations 
> ************************************************************/
> -
> -
> -static ssize_t cs4218_ct_law(const u_char *userPtr, size_t userCount,
> -                        u_char frame[], ssize_t *frameUsed,
> -                        ssize_t frameLeft);
> -static ssize_t cs4218_ct_s8(const u_char *userPtr, size_t userCount,
> -                       u_char frame[], ssize_t *frameUsed,
> -                       ssize_t frameLeft);
> -static ssize_t cs4218_ct_u8(const u_char *userPtr, size_t userCount,
> -                       u_char frame[], ssize_t *frameUsed,
> -                       ssize_t frameLeft);
> -static ssize_t cs4218_ct_s16(const u_char *userPtr, size_t userCount,
> -                        u_char frame[], ssize_t *frameUsed,
> -                        ssize_t frameLeft);
> -static ssize_t cs4218_ct_u16(const u_char *userPtr, size_t userCount,
> -                        u_char frame[], ssize_t *frameUsed,
> -                        ssize_t frameLeft);
> -static ssize_t cs4218_ctx_law(const u_char *userPtr, size_t userCount,
> -                         u_char frame[], ssize_t *frameUsed,
> -                         ssize_t frameLeft);
> -static ssize_t cs4218_ctx_s8(const u_char *userPtr, size_t userCount,
> -                        u_char frame[], ssize_t *frameUsed,
> -                        ssize_t frameLeft);
> -static ssize_t cs4218_ctx_u8(const u_char *userPtr, size_t userCount,
> -                        u_char frame[], ssize_t *frameUsed,
> -                        ssize_t frameLeft);
> -static ssize_t cs4218_ctx_s16(const u_char *userPtr, size_t userCount,
> -                         u_char frame[], ssize_t *frameUsed,
> -                         ssize_t frameLeft);
> -static ssize_t cs4218_ctx_u16(const u_char *userPtr, size_t userCount,
> -                         u_char frame[], ssize_t *frameUsed,
> -                         ssize_t frameLeft);
> -static ssize_t cs4218_ct_s16_read(const u_char *userPtr, size_t userCount,
> -                        u_char frame[], ssize_t *frameUsed,
> -                        ssize_t frameLeft);
> -static ssize_t cs4218_ct_u16_read(const u_char *userPtr, size_t userCount,
> -                        u_char frame[], ssize_t *frameUsed,
> -                        ssize_t frameLeft);
> -
> -
> -/*** Low level stuff 
> *********************************************************/
> -
> -struct cs_sound_settings {
> -     MACHINE mach;           /* machine dependent things */
> -     SETTINGS hard;          /* hardware settings */
> -     SETTINGS soft;          /* software settings */
> -     SETTINGS dsp;           /* /dev/dsp default settings */
> -     TRANS *trans_write;     /* supported translations for playback */
> -     TRANS *trans_read;      /* supported translations for record */
> -     int volume_left;        /* volume (range is machine dependent) */
> -     int volume_right;
> -     int bass;               /* tone (range is machine dependent) */
> -     int treble;
> -     int gain;
> -     int minDev;             /* minor device number currently open */
> -};
> -
> -static struct cs_sound_settings sound;
> -
> -static void *CS_Alloc(unsigned int size, gfp_t flags);
> -static void CS_Free(void *ptr, unsigned int size);
> -static int CS_IrqInit(void);
> -#ifdef MODULE
> -static void CS_IrqCleanup(void);
> -#endif /* MODULE */
> -static void CS_Silence(void);
> -static void CS_Init(void);
> -static void CS_Play(void);
> -static void CS_Record(void);
> -static int CS_SetFormat(int format);
> -static int CS_SetVolume(int volume);
> -static void cs4218_tdm_tx_intr(void *devid);
> -static void cs4218_tdm_rx_intr(void *devid);
> -static void cs4218_intr(void *devid);
> -static int cs_get_volume(uint reg);
> -static int cs_volume_setter(int volume, int mute);
> -static int cs_get_gain(uint reg);
> -static int cs_set_gain(int gain);
> -static void cs_mksound(unsigned int hz, unsigned int ticks);
> -static void cs_nosound(unsigned long xx);
> -
> -/*** Mid level stuff 
> *********************************************************/
> -
> -
> -static void sound_silence(void);
> -static void sound_init(void);
> -static int sound_set_format(int format);
> -static int sound_set_speed(int speed);
> -static int sound_set_stereo(int stereo);
> -static int sound_set_volume(int volume);
> -
> -static ssize_t sound_copy_translate(const u_char *userPtr,
> -                                 size_t userCount,
> -                                 u_char frame[], ssize_t *frameUsed,
> -                                 ssize_t frameLeft);
> -static ssize_t sound_copy_translate_read(const u_char *userPtr,
> -                                 size_t userCount,
> -                                 u_char frame[], ssize_t *frameUsed,
> -                                 ssize_t frameLeft);
> -
> -
> -/*
> - * /dev/mixer abstraction
> - */
> -
> -struct sound_mixer {
> -    int busy;
> -    int modify_counter;
> -};
> -
> -static struct sound_mixer mixer;
> -
> -static struct sound_queue sq;
> -static struct sound_queue read_sq;
> -
> -#define sq_block_address(i)  (sq.buffers[i])
> -#define SIGNAL_RECEIVED      (signal_pending(current))
> -#define NON_BLOCKING(open_mode)      (open_mode & O_NONBLOCK)
> -#define ONE_SECOND   HZ      /* in jiffies (100ths of a second) */
> -#define NO_TIME_LIMIT        0xffffffff
> -
> -/*
> - * /dev/sndstat
> - */
> -
> -struct sound_state {
> -     int busy;
> -     char buf[512];
> -     int len, ptr;
> -};
> -
> -static struct sound_state state;
> -
> -/*** Common stuff ********************************************************/
> -
> -static long long sound_lseek(struct file *file, long long offset, int orig);
> -
> -/*** Config & Setup 
> **********************************************************/
> -
> -void dmasound_setup(char *str, int *ints);
> -
> -/*** Translations 
> ************************************************************/
> -
> -
> -/* ++TeSche: radically changed for new expanding purposes...
> - *
> - * These two routines now deal with copying/expanding/translating the samples
> - * from user space into our buffer at the right frequency. They take care 
> about
> - * how much data there's actually to read, how much buffer space there is and
> - * to convert samples into the right frequency/encoding. They will only work 
> on
> - * complete samples so it may happen they leave some bytes in the input 
> stream
> - * if the user didn't write a multiple of the current sample size. They both
> - * return the number of bytes they've used from both streams so you may 
> detect
> - * such a situation. Luckily all programs should be able to cope with that.
> - *
> - * I think I've optimized anything as far as one can do in plain C, all
> - * variables should fit in registers and the loops are really short. There's
> - * one loop for every possible situation. Writing a more generalized and thus
> - * parameterized loop would only produce slower code. Feel free to optimize
> - * this in assembler if you like. :)
> - *
> - * I think these routines belong here because they're not yet really hardware
> - * independent, especially the fact that the Falcon can play 16bit samples
> - * only in stereo is hardcoded in both of them!
> - *
> - * ++geert: split in even more functions (one per format)
> - */
> -
> -static ssize_t cs4218_ct_law(const u_char *userPtr, size_t userCount,
> -                        u_char frame[], ssize_t *frameUsed,
> -                        ssize_t frameLeft)
> -{
> -     short *table = sound.soft.format == AFMT_MU_LAW ? ulaw2dma16: 
> alaw2dma16;
> -     ssize_t count, used;
> -     short *p = (short *) &frame[*frameUsed];
> -     int val, stereo = sound.soft.stereo;
> -
> -     frameLeft >>= 2;
> -     if (stereo)
> -             userCount >>= 1;
> -     used = count = min(userCount, frameLeft);
> -     while (count > 0) {
> -             u_char data;
> -             if (get_user(data, userPtr++))
> -                     return -EFAULT;
> -             val = table[data];
> -             *p++ = val;
> -             if (stereo) {
> -                     if (get_user(data, userPtr++))
> -                             return -EFAULT;
> -                     val = table[data];
> -             }
> -             *p++ = val;
> -             count--;
> -     }
> -     *frameUsed += used * 4;
> -     return stereo? used * 2: used;
> -}
> -
> -
> -static ssize_t cs4218_ct_s8(const u_char *userPtr, size_t userCount,
> -                       u_char frame[], ssize_t *frameUsed,
> -                       ssize_t frameLeft)
> -{
> -     ssize_t count, used;
> -     short *p = (short *) &frame[*frameUsed];
> -     int val, stereo = sound.soft.stereo;
> -
> -     frameLeft >>= 2;
> -     if (stereo)
> -             userCount >>= 1;
> -     used = count = min(userCount, frameLeft);
> -     while (count > 0) {
> -             u_char data;
> -             if (get_user(data, userPtr++))
> -                     return -EFAULT;
> -             val = data << 8;
> -             *p++ = val;
> -             if (stereo) {
> -                     if (get_user(data, userPtr++))
> -                             return -EFAULT;
> -                     val = data << 8;
> -             }
> -             *p++ = val;
> -             count--;
> -     }
> -     *frameUsed += used * 4;
> -     return stereo? used * 2: used;
> -}
> -
> -
> -static ssize_t cs4218_ct_u8(const u_char *userPtr, size_t userCount,
> -                       u_char frame[], ssize_t *frameUsed,
> -                       ssize_t frameLeft)
> -{
> -     ssize_t count, used;
> -     short *p = (short *) &frame[*frameUsed];
> -     int val, stereo = sound.soft.stereo;
> -
> -     frameLeft >>= 2;
> -     if (stereo)
> -             userCount >>= 1;
> -     used = count = min(userCount, frameLeft);
> -     while (count > 0) {
> -             u_char data;
> -             if (get_user(data, userPtr++))
> -                     return -EFAULT;
> -             val = (data ^ 0x80) << 8;
> -             *p++ = val;
> -             if (stereo) {
> -                     if (get_user(data, userPtr++))
> -                             return -EFAULT;
> -                     val = (data ^ 0x80) << 8;
> -             }
> -             *p++ = val;
> -             count--;
> -     }
> -     *frameUsed += used * 4;
> -     return stereo? used * 2: used;
> -}
> -
> -
> -/* This is the default format of the codec.  Signed, 16-bit stereo
> - * generated by an application shouldn't have to be copied at all.
> - * We should just get the phsical address of the buffers and update
> - * the TDM BDs directly.
> - */
> -static ssize_t cs4218_ct_s16(const u_char *userPtr, size_t userCount,
> -                        u_char frame[], ssize_t *frameUsed,
> -                        ssize_t frameLeft)
> -{
> -     ssize_t count, used;
> -     int stereo = sound.soft.stereo;
> -     short *fp = (short *) &frame[*frameUsed];
> -
> -     frameLeft >>= 2;
> -     userCount >>= (stereo? 2: 1);
> -     used = count = min(userCount, frameLeft);
> -     if (!stereo) {
> -             short *up = (short *) userPtr;
> -             while (count > 0) {
> -                     short data;
> -                     if (get_user(data, up++))
> -                             return -EFAULT;
> -                     *fp++ = data;
> -                     *fp++ = data;
> -                     count--;
> -             }
> -     } else {
> -             if (copy_from_user(fp, userPtr, count * 4))
> -                     return -EFAULT;
> -     }
> -     *frameUsed += used * 4;
> -     return stereo? used * 4: used * 2;
> -}
> -
> -static ssize_t cs4218_ct_u16(const u_char *userPtr, size_t userCount,
> -                        u_char frame[], ssize_t *frameUsed,
> -                        ssize_t frameLeft)
> -{
> -     ssize_t count, used;
> -     int mask = (sound.soft.format == AFMT_U16_LE? 0x0080: 0x8000);
> -     int stereo = sound.soft.stereo;
> -     short *fp = (short *) &frame[*frameUsed];
> -     short *up = (short *) userPtr;
> -
> -     frameLeft >>= 2;
> -     userCount >>= (stereo? 2: 1);
> -     used = count = min(userCount, frameLeft);
> -     while (count > 0) {
> -             int data;
> -             if (get_user(data, up++))
> -                     return -EFAULT;
> -             data ^= mask;
> -             *fp++ = data;
> -             if (stereo) {
> -                     if (get_user(data, up++))
> -                             return -EFAULT;
> -                     data ^= mask;
> -             }
> -             *fp++ = data;
> -             count--;
> -     }
> -     *frameUsed += used * 4;
> -     return stereo? used * 4: used * 2;
> -}
> -
> -
> -static ssize_t cs4218_ctx_law(const u_char *userPtr, size_t userCount,
> -                         u_char frame[], ssize_t *frameUsed,
> -                         ssize_t frameLeft)
> -{
> -     unsigned short *table = (unsigned short *)
> -             (sound.soft.format == AFMT_MU_LAW ? ulaw2dma16: alaw2dma16);
> -     unsigned int data = expand_data;
> -     unsigned int *p = (unsigned int *) &frame[*frameUsed];
> -     int bal = expand_bal;
> -     int hSpeed = sound.hard.speed, sSpeed = sound.soft.speed;
> -     int utotal, ftotal;
> -     int stereo = sound.soft.stereo;
> -
> -     frameLeft >>= 2;
> -     if (stereo)
> -             userCount >>= 1;
> -     ftotal = frameLeft;
> -     utotal = userCount;
> -     while (frameLeft) {
> -             u_char c;
> -             if (bal < 0) {
> -                     if (userCount == 0)
> -                             break;
> -                     if (get_user(c, userPtr++))
> -                             return -EFAULT;
> -                     data = table[c];
> -                     if (stereo) {
> -                             if (get_user(c, userPtr++))
> -                                     return -EFAULT;
> -                             data = (data << 16) + table[c];
> -                     } else
> -                             data = (data << 16) + data;
> -                     userCount--;
> -                     bal += hSpeed;
> -             }
> -             *p++ = data;
> -             frameLeft--;
> -             bal -= sSpeed;
> -     }
> -     expand_bal = bal;
> -     expand_data = data;
> -     *frameUsed += (ftotal - frameLeft) * 4;
> -     utotal -= userCount;
> -     return stereo? utotal * 2: utotal;
> -}
> -
> -
> -static ssize_t cs4218_ctx_s8(const u_char *userPtr, size_t userCount,
> -                        u_char frame[], ssize_t *frameUsed,
> -                        ssize_t frameLeft)
> -{
> -     unsigned int *p = (unsigned int *) &frame[*frameUsed];
> -     unsigned int data = expand_data;
> -     int bal = expand_bal;
> -     int hSpeed = sound.hard.speed, sSpeed = sound.soft.speed;
> -     int stereo = sound.soft.stereo;
> -     int utotal, ftotal;
> -
> -     frameLeft >>= 2;
> -     if (stereo)
> -             userCount >>= 1;
> -     ftotal = frameLeft;
> -     utotal = userCount;
> -     while (frameLeft) {
> -             u_char c;
> -             if (bal < 0) {
> -                     if (userCount == 0)
> -                             break;
> -                     if (get_user(c, userPtr++))
> -                             return -EFAULT;
> -                     data = c << 8;
> -                     if (stereo) {
> -                             if (get_user(c, userPtr++))
> -                                     return -EFAULT;
> -                             data = (data << 16) + (c << 8);
> -                     } else
> -                             data = (data << 16) + data;
> -                     userCount--;
> -                     bal += hSpeed;
> -             }
> -             *p++ = data;
> -             frameLeft--;
> -             bal -= sSpeed;
> -     }
> -     expand_bal = bal;
> -     expand_data = data;
> -     *frameUsed += (ftotal - frameLeft) * 4;
> -     utotal -= userCount;
> -     return stereo? utotal * 2: utotal;
> -}
> -
> -
> -static ssize_t cs4218_ctx_u8(const u_char *userPtr, size_t userCount,
> -                        u_char frame[], ssize_t *frameUsed,
> -                        ssize_t frameLeft)
> -{
> -     unsigned int *p = (unsigned int *) &frame[*frameUsed];
> -     unsigned int data = expand_data;
> -     int bal = expand_bal;
> -     int hSpeed = sound.hard.speed, sSpeed = sound.soft.speed;
> -     int stereo = sound.soft.stereo;
> -     int utotal, ftotal;
> -
> -     frameLeft >>= 2;
> -     if (stereo)
> -             userCount >>= 1;
> -     ftotal = frameLeft;
> -     utotal = userCount;
> -     while (frameLeft) {
> -             u_char c;
> -             if (bal < 0) {
> -                     if (userCount == 0)
> -                             break;
> -                     if (get_user(c, userPtr++))
> -                             return -EFAULT;
> -                     data = (c ^ 0x80) << 8;
> -                     if (stereo) {
> -                             if (get_user(c, userPtr++))
> -                                     return -EFAULT;
> -                             data = (data << 16) + ((c ^ 0x80) << 8);
> -                     } else
> -                             data = (data << 16) + data;
> -                     userCount--;
> -                     bal += hSpeed;
> -             }
> -             *p++ = data;
> -             frameLeft--;
> -             bal -= sSpeed;
> -     }
> -     expand_bal = bal;
> -     expand_data = data;
> -     *frameUsed += (ftotal - frameLeft) * 4;
> -     utotal -= userCount;
> -     return stereo? utotal * 2: utotal;
> -}
> -
> -
> -static ssize_t cs4218_ctx_s16(const u_char *userPtr, size_t userCount,
> -                         u_char frame[], ssize_t *frameUsed,
> -                         ssize_t frameLeft)
> -{
> -     unsigned int *p = (unsigned int *) &frame[*frameUsed];
> -     unsigned int data = expand_data;
> -     unsigned short *up = (unsigned short *) userPtr;
> -     int bal = expand_bal;
> -     int hSpeed = sound.hard.speed, sSpeed = sound.soft.speed;
> -     int stereo = sound.soft.stereo;
> -     int utotal, ftotal;
> -
> -     frameLeft >>= 2;
> -     userCount >>= (stereo? 2: 1);
> -     ftotal = frameLeft;
> -     utotal = userCount;
> -     while (frameLeft) {
> -             unsigned short c;
> -             if (bal < 0) {
> -                     if (userCount == 0)
> -                             break;
> -                     if (get_user(data, up++))
> -                             return -EFAULT;
> -                     if (stereo) {
> -                             if (get_user(c, up++))
> -                                     return -EFAULT;
> -                             data = (data << 16) + c;
> -                     } else
> -                             data = (data << 16) + data;
> -                     userCount--;
> -                     bal += hSpeed;
> -             }
> -             *p++ = data;
> -             frameLeft--;
> -             bal -= sSpeed;
> -     }
> -     expand_bal = bal;
> -     expand_data = data;
> -     *frameUsed += (ftotal - frameLeft) * 4;
> -     utotal -= userCount;
> -     return stereo? utotal * 4: utotal * 2;
> -}
> -
> -
> -static ssize_t cs4218_ctx_u16(const u_char *userPtr, size_t userCount,
> -                         u_char frame[], ssize_t *frameUsed,
> -                         ssize_t frameLeft)
> -{
> -     int mask = (sound.soft.format == AFMT_U16_LE? 0x0080: 0x8000);
> -     unsigned int *p = (unsigned int *) &frame[*frameUsed];
> -     unsigned int data = expand_data;
> -     unsigned short *up = (unsigned short *) userPtr;
> -     int bal = expand_bal;
> -     int hSpeed = sound.hard.speed, sSpeed = sound.soft.speed;
> -     int stereo = sound.soft.stereo;
> -     int utotal, ftotal;
> -
> -     frameLeft >>= 2;
> -     userCount >>= (stereo? 2: 1);
> -     ftotal = frameLeft;
> -     utotal = userCount;
> -     while (frameLeft) {
> -             unsigned short c;
> -             if (bal < 0) {
> -                     if (userCount == 0)
> -                             break;
> -                     if (get_user(data, up++))
> -                             return -EFAULT;
> -                     data ^= mask;
> -                     if (stereo) {
> -                             if (get_user(c, up++))
> -                                     return -EFAULT;
> -                             data = (data << 16) + (c ^ mask);
> -                     } else
> -                             data = (data << 16) + data;
> -                     userCount--;
> -                     bal += hSpeed;
> -             }
> -             *p++ = data;
> -             frameLeft--;
> -             bal -= sSpeed;
> -     }
> -     expand_bal = bal;
> -     expand_data = data;
> -     *frameUsed += (ftotal - frameLeft) * 4;
> -     utotal -= userCount;
> -     return stereo? utotal * 4: utotal * 2;
> -}
> -
> -static ssize_t cs4218_ct_s8_read(const u_char *userPtr, size_t userCount,
> -                       u_char frame[], ssize_t *frameUsed,
> -                       ssize_t frameLeft)
> -{
> -     ssize_t count, used;
> -     short *p = (short *) &frame[*frameUsed];
> -     int val, stereo = sound.soft.stereo;
> -
> -     frameLeft >>= 2;
> -     if (stereo)
> -             userCount >>= 1;
> -     used = count = min(userCount, frameLeft);
> -     while (count > 0) {
> -             u_char data;
> -
> -             val = *p++;
> -             data = val >> 8;
> -             if (put_user(data, (u_char *)userPtr++))
> -                     return -EFAULT;
> -             if (stereo) {
> -                     val = *p;
> -                     data = val >> 8;
> -                     if (put_user(data, (u_char *)userPtr++))
> -                             return -EFAULT;
> -             }
> -             p++;
> -             count--;
> -     }
> -     *frameUsed += used * 4;
> -     return stereo? used * 2: used;
> -}
> -
> -
> -static ssize_t cs4218_ct_u8_read(const u_char *userPtr, size_t userCount,
> -                       u_char frame[], ssize_t *frameUsed,
> -                       ssize_t frameLeft)
> -{
> -     ssize_t count, used;
> -     short *p = (short *) &frame[*frameUsed];
> -     int val, stereo = sound.soft.stereo;
> -
> -     frameLeft >>= 2;
> -     if (stereo)
> -             userCount >>= 1;
> -     used = count = min(userCount, frameLeft);
> -     while (count > 0) {
> -             u_char data;
> -
> -             val = *p++;
> -             data = (val >> 8) ^ 0x80;
> -             if (put_user(data, (u_char *)userPtr++))
> -                     return -EFAULT;
> -             if (stereo) {
> -                     val = *p;
> -                     data = (val >> 8) ^ 0x80;
> -                     if (put_user(data, (u_char *)userPtr++))
> -                             return -EFAULT;
> -             }
> -             p++;
> -             count--;
> -     }
> -     *frameUsed += used * 4;
> -     return stereo? used * 2: used;
> -}
> -
> -
> -static ssize_t cs4218_ct_s16_read(const u_char *userPtr, size_t userCount,
> -                        u_char frame[], ssize_t *frameUsed,
> -                        ssize_t frameLeft)
> -{
> -     ssize_t count, used;
> -     int stereo = sound.soft.stereo;
> -     short *fp = (short *) &frame[*frameUsed];
> -
> -     frameLeft >>= 2;
> -     userCount >>= (stereo? 2: 1);
> -     used = count = min(userCount, frameLeft);
> -     if (!stereo) {
> -             short *up = (short *) userPtr;
> -             while (count > 0) {
> -                     short data;
> -                     data = *fp;
> -                     if (put_user(data, up++))
> -                             return -EFAULT;
> -                     fp+=2;
> -                     count--;
> -             }
> -     } else {
> -             if (copy_to_user((u_char *)userPtr, fp, count * 4))
> -                     return -EFAULT;
> -     }
> -     *frameUsed += used * 4;
> -     return stereo? used * 4: used * 2;
> -}
> -
> -static ssize_t cs4218_ct_u16_read(const u_char *userPtr, size_t userCount,
> -                        u_char frame[], ssize_t *frameUsed,
> -                        ssize_t frameLeft)
> -{
> -     ssize_t count, used;
> -     int mask = (sound.soft.format == AFMT_U16_LE? 0x0080: 0x8000);
> -     int stereo = sound.soft.stereo;
> -     short *fp = (short *) &frame[*frameUsed];
> -     short *up = (short *) userPtr;
> -
> -     frameLeft >>= 2;
> -     userCount >>= (stereo? 2: 1);
> -     used = count = min(userCount, frameLeft);
> -     while (count > 0) {
> -             int data;
> -
> -             data = *fp++;
> -             data ^= mask;
> -             if (put_user(data, up++))
> -                     return -EFAULT;
> -             if (stereo) {
> -                     data = *fp;
> -                     data ^= mask;
> -                     if (put_user(data, up++))
> -                             return -EFAULT;
> -             }
> -             fp++;
> -             count--;
> -     }
> -     *frameUsed += used * 4;
> -     return stereo? used * 4: used * 2;
> -}
> -
> -static TRANS transCSNormal = {
> -     cs4218_ct_law, cs4218_ct_law, cs4218_ct_s8, cs4218_ct_u8,
> -     cs4218_ct_s16, cs4218_ct_u16, cs4218_ct_s16, cs4218_ct_u16
> -};
> -
> -static TRANS transCSExpand = {
> -     cs4218_ctx_law, cs4218_ctx_law, cs4218_ctx_s8, cs4218_ctx_u8,
> -     cs4218_ctx_s16, cs4218_ctx_u16, cs4218_ctx_s16, cs4218_ctx_u16
> -};
> -
> -static TRANS transCSNormalRead = {
> -     NULL, NULL, cs4218_ct_s8_read, cs4218_ct_u8_read,
> -     cs4218_ct_s16_read, cs4218_ct_u16_read,
> -     cs4218_ct_s16_read, cs4218_ct_u16_read
> -};
> -
> -/*** Low level stuff 
> *********************************************************/
> -
> -static void *CS_Alloc(unsigned int size, gfp_t flags)
> -{
> -     int     order;
> -
> -     size >>= 13;
> -     for (order=0; order < 5; order++) {
> -             if (size == 0)
> -                     break;
> -             size >>= 1;
> -     }
> -     return (void *)__get_free_pages(flags, order);
> -}
> -
> -static void CS_Free(void *ptr, unsigned int size)
> -{
> -     int     order;
> -
> -     size >>= 13;
> -     for (order=0; order < 5; order++) {
> -             if (size == 0)
> -                     break;
> -             size >>= 1;
> -     }
> -     free_pages((ulong)ptr, order);
> -}
> -
> -static int __init CS_IrqInit(void)
> -{
> -     cpm_install_handler(CPMVEC_SMC2, cs4218_intr, NULL);
> -     return 1;
> -}
> -
> -#ifdef MODULE
> -static void CS_IrqCleanup(void)
> -{
> -     volatile smc_t          *sp;
> -     volatile cpm8xx_t       *cp;
> -
> -     /* First disable transmitter and receiver.
> -     */
> -     sp = &cpmp->cp_smc[1];
> -     sp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
> -
> -     /* And now shut down the SMC.
> -     */
> -     cp = cpmp;      /* Get pointer to Communication Processor */
> -     cp->cp_cpcr = mk_cr_cmd(CPM_CR_CH_SMC2,
> -                             CPM_CR_STOP_TX) | CPM_CR_FLG;
> -     while (cp->cp_cpcr & CPM_CR_FLG);
> -
> -     /* Release the interrupt handler.
> -     */
> -     cpm_free_handler(CPMVEC_SMC2);
> -
> -     kfree(beep_buf);
> -     kd_mksound = orig_mksound;
> -}
> -#endif /* MODULE */
> -
> -static void CS_Silence(void)
> -{
> -     volatile smc_t          *sp;
> -
> -     /* Disable transmitter.
> -     */
> -     sp = &cpmp->cp_smc[1];
> -     sp->smc_smcmr &= ~SMCMR_TEN;
> -}
> -
> -/* Frequencies depend upon external oscillator.  There are two
> - * choices, 12.288 and 11.2896 MHz.  The RPCG audio supports both through
> - * and external control register selection bit.
> - */
> -static int cs4218_freqs[] = {
> -    /* 12.288  11.2896  */
> -     48000, 44100,
> -     32000, 29400,
> -     24000, 22050,
> -     19200, 17640,
> -     16000, 14700,
> -     12000, 11025,
> -      9600,  8820,
> -      8000,  7350
> -};
> -
> -static void CS_Init(void)
> -{
> -     int i, tolerance;
> -
> -     switch (sound.soft.format) {
> -     case AFMT_S16_LE:
> -     case AFMT_U16_LE:
> -             sound.hard.format = AFMT_S16_LE;
> -             break;
> -     default:
> -             sound.hard.format = AFMT_S16_BE;
> -             break;
> -     }
> -     sound.hard.stereo = 1;
> -     sound.hard.size = 16;
> -
> -     /*
> -      * If we have a sample rate which is within catchRadius percent
> -      * of the requested value, we don't have to expand the samples.
> -      * Otherwise choose the next higher rate.
> -      */
> -     i = (sizeof(cs4218_freqs) / sizeof(int));
> -     do {
> -             tolerance = catchRadius * cs4218_freqs[--i] / 100;
> -     } while (sound.soft.speed > cs4218_freqs[i] + tolerance && i > 0);
> -     if (sound.soft.speed >= cs4218_freqs[i] - tolerance)
> -             sound.trans_write = &transCSNormal;
> -     else
> -             sound.trans_write = &transCSExpand;
> -     sound.trans_read = &transCSNormalRead;
> -     sound.hard.speed = cs4218_freqs[i];
> -     cs4218_rate_index = i;
> -
> -     /* The CS4218 has seven selectable clock dividers for the sample
> -      * clock.  The HIOX then provides one of two external rates.
> -      * An even numbered frequency table index uses the high external
> -      * clock rate.
> -      */
> -     *(uint *)HIOX_CSR4_ADDR &= ~(HIOX_CSR4_AUDCLKHI | HIOX_CSR4_AUDCLKSEL);
> -     if ((i & 1) == 0)
> -             *(uint *)HIOX_CSR4_ADDR |= HIOX_CSR4_AUDCLKHI;
> -     i >>= 1;
> -     *(uint *)HIOX_CSR4_ADDR |= (i & HIOX_CSR4_AUDCLKSEL);
> -
> -     expand_bal = -sound.soft.speed;
> -}
> -
> -static int CS_SetFormat(int format)
> -{
> -     int size;
> -
> -     switch (format) {
> -     case AFMT_QUERY:
> -             return sound.soft.format;
> -     case AFMT_MU_LAW:
> -     case AFMT_A_LAW:
> -     case AFMT_U8:
> -     case AFMT_S8:
> -             size = 8;
> -             break;
> -     case AFMT_S16_BE:
> -     case AFMT_U16_BE:
> -     case AFMT_S16_LE:
> -     case AFMT_U16_LE:
> -             size = 16;
> -             break;
> -     default: /* :-) */
> -             printk(KERN_ERR "dmasound: unknown format 0x%x, using 
> AFMT_U8\n",
> -                    format);
> -             size = 8;
> -             format = AFMT_U8;
> -     }
> -
> -     sound.soft.format = format;
> -     sound.soft.size = size;
> -     if (sound.minDev == SND_DEV_DSP) {
> -             sound.dsp.format = format;
> -             sound.dsp.size = size;
> -     }
> -
> -     CS_Init();
> -
> -     return format;
> -}
> -
> -/* Volume is the amount of attenuation we tell the codec to impose
> - * on the outputs.  There are 32 levels, with 0 the "loudest".
> - */
> -#define CS_VOLUME_TO_MASK(x) (31 - ((((x) - 1) * 31) / 99))
> -#define CS_MASK_TO_VOLUME(y) (100 - ((y) * 99 / 31))
> -
> -static int cs_get_volume(uint reg)
> -{
> -     int volume;
> -
> -     volume = CS_MASK_TO_VOLUME(CS_LATTEN_GET(reg));
> -     volume |= CS_MASK_TO_VOLUME(CS_RATTEN_GET(reg)) << 8;
> -     return volume;
> -}
> -
> -static int cs_volume_setter(int volume, int mute)
> -{
> -     uint tempctl;
> -
> -     if (mute && volume == 0) {
> -             tempctl = cs4218_control | CS_MUTE;
> -     } else {
> -             tempctl = cs4218_control & ~CS_MUTE;
> -             tempctl = tempctl & ~(CS_LATTEN | CS_RATTEN);
> -             tempctl |= CS_LATTEN_SET(CS_VOLUME_TO_MASK(volume & 0xff));
> -             tempctl |= CS_RATTEN_SET(CS_VOLUME_TO_MASK((volume >> 8) & 
> 0xff));
> -             volume = cs_get_volume(tempctl);
> -     }
> -     if (tempctl != cs4218_control) {
> -             cs4218_ctl_write(tempctl);
> -     }
> -     return volume;
> -}
> -
> -
> -/* Gain has 16 steps from 0 to 15.  These are in 1.5dB increments from
> - * 0 (no gain) to 22.5 dB.
> - */
> -#define CS_RECLEVEL_TO_GAIN(v) \
> -     ((v) < 0 ? 0 : (v) > 100 ? 15 : (v) * 3 / 20)
> -#define CS_GAIN_TO_RECLEVEL(v) (((v) * 20 + 2) / 3)
> -
> -static int cs_get_gain(uint reg)
> -{
> -     int gain;
> -
> -     gain = CS_GAIN_TO_RECLEVEL(CS_LGAIN_GET(reg));
> -     gain |= CS_GAIN_TO_RECLEVEL(CS_RGAIN_GET(reg)) << 8;
> -     return gain;
> -}
> -
> -static int cs_set_gain(int gain)
> -{
> -     uint tempctl;
> -
> -     tempctl = cs4218_control & ~(CS_LGAIN | CS_RGAIN);
> -     tempctl |= CS_LGAIN_SET(CS_RECLEVEL_TO_GAIN(gain & 0xff));
> -     tempctl |= CS_RGAIN_SET(CS_RECLEVEL_TO_GAIN((gain >> 8) & 0xff));
> -     gain = cs_get_gain(tempctl);
> -
> -     if (tempctl != cs4218_control) {
> -             cs4218_ctl_write(tempctl);
> -     }
> -     return gain;
> -}
> -
> -static int CS_SetVolume(int volume)
> -{
> -     return cs_volume_setter(volume, CS_MUTE);
> -}
> -
> -static void CS_Play(void)
> -{
> -     int i, count;
> -     unsigned long flags;
> -     volatile cbd_t  *bdp;
> -     volatile cpm8xx_t *cp;
> -
> -     /* Protect buffer */
> -     spin_lock_irqsave(&cs4218_lock, flags);
> -#if 0
> -     if (awacs_beep_state) {
> -             /* sound takes precedence over beeps */
> -             out_le32(&awacs_txdma->control, (RUN|PAUSE|FLUSH|WAKE) << 16);
> -             out_le32(&awacs->control,
> -                      (in_le32(&awacs->control) & ~0x1f00)
> -                      | (awacs_rate_index << 8));
> -             out_le32(&awacs->byteswap, sound.hard.format != AFMT_S16_BE);
> -             out_le32(&awacs_txdma->cmdptr, 
> virt_to_bus(&(awacs_tx_cmds[(sq.front+sq.active) % sq.max_count])));
> -
> -             beep_playing = 0;
> -             awacs_beep_state = 0;
> -     }
> -#endif
> -     i = sq.front + sq.active;
> -     if (i >= sq.max_count)
> -             i -= sq.max_count;
> -     while (sq.active < 2 && sq.active < sq.count) {
> -             count = (sq.count == sq.active + 1)?sq.rear_size:sq.block_size;
> -             if (count < sq.block_size && !sq.syncing)
> -                     /* last block not yet filled, and we're not syncing. */
> -                     break;
> -
> -             bdp = &tx_base[i];
> -             bdp->cbd_datlen = count;
> -
> -             flush_dcache_range((ulong)sound_buffers[i],
> -                                     (ulong)(sound_buffers[i] + count));
> -
> -             if (++i >= sq.max_count)
> -                     i = 0;
> -
> -             if (sq.active == 0) {
> -                     /* The SMC does not load its fifo until the first
> -                      * TDM frame pulse, so the transmit data gets shifted
> -                      * by one word.  To compensate for this, we incorrectly
> -                      * transmit the first buffer and shorten it by one
> -                      * word.  Subsequent buffers are then aligned properly.
> -                      */
> -                     bdp->cbd_datlen -= 2;
> -
> -                     /* Start up the SMC Transmitter.
> -                     */
> -                     cp = cpmp;
> -                     cp->cp_smc[1].smc_smcmr |= SMCMR_TEN;
> -                     cp->cp_cpcr = mk_cr_cmd(CPM_CR_CH_SMC2,
> -                                     CPM_CR_RESTART_TX) | CPM_CR_FLG;
> -                     while (cp->cp_cpcr & CPM_CR_FLG);
> -             }
> -
> -             /* Buffer is ready now.
> -             */
> -             bdp->cbd_sc |= BD_SC_READY;
> -
> -             ++sq.active;
> -     }
> -     spin_unlock_irqrestore(&cs4218_lock, flags);
> -}
> -
> -
> -static void CS_Record(void)
> -{
> -     unsigned long flags;
> -     volatile smc_t          *sp;
> -
> -     if (read_sq.active)
> -             return;
> -
> -     /* Protect buffer */
> -     spin_lock_irqsave(&cs4218_lock, flags);
> -
> -     /* This is all we have to do......Just start it up.
> -     */
> -     sp = &cpmp->cp_smc[1];
> -     sp->smc_smcmr |= SMCMR_REN;
> -
> -     read_sq.active = 1;
> -
> -        spin_unlock_irqrestore(&cs4218_lock, flags);
> -}
> -
> -
> -static void
> -cs4218_tdm_tx_intr(void *devid)
> -{
> -     int i = sq.front;
> -     volatile cbd_t *bdp;
> -
> -     while (sq.active > 0) {
> -             bdp = &tx_base[i];
> -             if (bdp->cbd_sc & BD_SC_READY)
> -                     break;  /* this frame is still going */
> -             --sq.count;
> -             --sq.active;
> -             if (++i >= sq.max_count)
> -                     i = 0;
> -     }
> -     if (i != sq.front)
> -             WAKE_UP(sq.action_queue);
> -     sq.front = i;
> -
> -     CS_Play();
> -
> -     if (!sq.active)
> -             WAKE_UP(sq.sync_queue);
> -}
> -
> -
> -static void
> -cs4218_tdm_rx_intr(void *devid)
> -{
> -
> -     /* We want to blow 'em off when shutting down.
> -     */
> -     if (read_sq.active == 0)
> -             return;
> -
> -     /* Check multiple buffers in case we were held off from
> -      * interrupt processing for a long time.  Geeze, I really hope
> -      * this doesn't happen.
> -      */
> -     while ((rx_base[read_sq.rear].cbd_sc & BD_SC_EMPTY) == 0) {
> -
> -             /* Invalidate the data cache range for this buffer.
> -             */
> -             invalidate_dcache_range(
> -                 (uint)(sound_read_buffers[read_sq.rear]),
> -                 (uint)(sound_read_buffers[read_sq.rear] + 
> read_sq.block_size));
> -
> -             /* Make buffer available again and move on.
> -             */
> -             rx_base[read_sq.rear].cbd_sc |= BD_SC_EMPTY;
> -             read_sq.rear++;
> -
> -             /* Wrap the buffer ring.
> -             */
> -             if (read_sq.rear >= read_sq.max_active)
> -                     read_sq.rear = 0;
> -
> -             /* If we have caught up to the front buffer, bump it.
> -              * This will cause weird (but not fatal) results if the
> -              * read loop is currently using this buffer.  The user is
> -              * behind in this case anyway, so weird things are going
> -              * to happen.
> -              */
> -             if (read_sq.rear == read_sq.front) {
> -                     read_sq.front++;
> -                     if (read_sq.front >= read_sq.max_active)
> -                             read_sq.front = 0;
> -             }
> -     }
> -
> -     WAKE_UP(read_sq.action_queue);
> -}
> -
> -static void cs_nosound(unsigned long xx)
> -{
> -     unsigned long flags;
> -
> -     /* not sure if this is needed, since hardware command is #if 0'd */
> -     spin_lock_irqsave(&cs4218_lock, flags);
> -     if (beep_playing) {
> -#if 0
> -             st_le16(&beep_dbdma_cmd->command, DBDMA_STOP);
> -#endif
> -             beep_playing = 0;
> -     }
> -     spin_unlock_irqrestore(&cs4218_lock, flags);
> -}
> -
> -static DEFINE_TIMER(beep_timer, cs_nosound, 0, 0);
> -
> -static void cs_mksound(unsigned int hz, unsigned int ticks)
> -{
> -     unsigned long flags;
> -     int beep_speed = BEEP_SPEED;
> -     int srate = cs4218_freqs[beep_speed];
> -     int period, ncycles, nsamples;
> -     int i, j, f;
> -     short *p;
> -     static int beep_hz_cache;
> -     static int beep_nsamples_cache;
> -     static int beep_volume_cache;
> -
> -     if (hz <= srate / BEEP_BUFLEN || hz > srate / 2) {
> -#if 1
> -             /* this is a hack for broken X server code */
> -             hz = 750;
> -             ticks = 12;
> -#else
> -             /* cancel beep currently playing */
> -             awacs_nosound(0);
> -             return;
> -#endif
> -     }
> -     /* lock while modifying beep_timer */
> -     spin_lock_irqsave(&cs4218_lock, flags);
> -     del_timer(&beep_timer);
> -     if (ticks) {
> -             beep_timer.expires = jiffies + ticks;
> -             add_timer(&beep_timer);
> -     }
> -     if (beep_playing || sq.active || beep_buf == NULL) {
> -             spin_unlock_irqrestore(&cs4218_lock, flags);
> -             return;         /* too hard, sorry :-( */
> -     }
> -     beep_playing = 1;
> -#if 0
> -     st_le16(&beep_dbdma_cmd->command, OUTPUT_MORE + BR_ALWAYS);
> -#endif
> -     spin_unlock_irqrestore(&cs4218_lock, flags);
> -
> -     if (hz == beep_hz_cache && beep_volume == beep_volume_cache) {
> -             nsamples = beep_nsamples_cache;
> -     } else {
> -             period = srate * 256 / hz;      /* fixed point */
> -             ncycles = BEEP_BUFLEN * 256 / period;
> -             nsamples = (period * ncycles) >> 8;
> -             f = ncycles * 65536 / nsamples;
> -             j = 0;
> -             p = beep_buf;
> -             for (i = 0; i < nsamples; ++i, p += 2) {
> -                     p[0] = p[1] = beep_wform[j >> 8] * beep_volume;
> -                     j = (j + f) & 0xffff;
> -             }
> -             beep_hz_cache = hz;
> -             beep_volume_cache = beep_volume;
> -             beep_nsamples_cache = nsamples;
> -     }
> -
> -#if 0
> -     st_le16(&beep_dbdma_cmd->req_count, nsamples*4);
> -     st_le16(&beep_dbdma_cmd->xfer_status, 0);
> -     st_le32(&beep_dbdma_cmd->cmd_dep, virt_to_bus(beep_dbdma_cmd));
> -     st_le32(&beep_dbdma_cmd->phy_addr, virt_to_bus(beep_buf));
> -     awacs_beep_state = 1;
> -
> -     spin_lock_irqsave(&cs4218_lock, flags);
> -     if (beep_playing) {     /* i.e. haven't been terminated already */
> -             out_le32(&awacs_txdma->control, (RUN|WAKE|FLUSH|PAUSE) << 16);
> -             out_le32(&awacs->control,
> -                      (in_le32(&awacs->control) & ~0x1f00)
> -                      | (beep_speed << 8));
> -             out_le32(&awacs->byteswap, 0);
> -             out_le32(&awacs_txdma->cmdptr, virt_to_bus(beep_dbdma_cmd));
> -             out_le32(&awacs_txdma->control, RUN | (RUN << 16));
> -     }
> -     spin_unlock_irqrestore(&cs4218_lock, flags);
> -#endif
> -}
> -
> -static MACHINE mach_cs4218 = {
> -     .owner =        THIS_MODULE,
> -     .name =         "HIOX CS4218",
> -     .name2 =        "Built-in Sound",
> -     .dma_alloc =    CS_Alloc,
> -     .dma_free =     CS_Free,
> -     .irqinit =      CS_IrqInit,
> -#ifdef MODULE
> -     .irqcleanup =   CS_IrqCleanup,
> -#endif /* MODULE */
> -     .init =         CS_Init,
> -     .silence =      CS_Silence,
> -     .setFormat =    CS_SetFormat,
> -     .setVolume =    CS_SetVolume,
> -     .play =         CS_Play
> -};
> -
> -
> -/*** Mid level stuff 
> *********************************************************/
> -
> -
> -static void sound_silence(void)
> -{
> -     /* update hardware settings one more */
> -     (*sound.mach.init)();
> -
> -     (*sound.mach.silence)();
> -}
> -
> -
> -static void sound_init(void)
> -{
> -     (*sound.mach.init)();
> -}
> -
> -
> -static int sound_set_format(int format)
> -{
> -     return(*sound.mach.setFormat)(format);
> -}
> -
> -
> -static int sound_set_speed(int speed)
> -{
> -     if (speed < 0)
> -             return(sound.soft.speed);
> -
> -     sound.soft.speed = speed;
> -     (*sound.mach.init)();
> -     if (sound.minDev == SND_DEV_DSP)
> -             sound.dsp.speed = sound.soft.speed;
> -
> -     return(sound.soft.speed);
> -}
> -
> -
> -static int sound_set_stereo(int stereo)
> -{
> -     if (stereo < 0)
> -             return(sound.soft.stereo);
> -
> -     stereo = !!stereo;    /* should be 0 or 1 now */
> -
> -     sound.soft.stereo = stereo;
> -     if (sound.minDev == SND_DEV_DSP)
> -             sound.dsp.stereo = stereo;
> -     (*sound.mach.init)();
> -
> -     return(stereo);
> -}
> -
> -
> -static int sound_set_volume(int volume)
> -{
> -     return(*sound.mach.setVolume)(volume);
> -}
> -
> -static ssize_t sound_copy_translate(const u_char *userPtr,
> -                                 size_t userCount,
> -                                 u_char frame[], ssize_t *frameUsed,
> -                                 ssize_t frameLeft)
> -{
> -     ssize_t (*ct_func)(const u_char *, size_t, u_char *, ssize_t *, 
> ssize_t) = NULL;
> -
> -     switch (sound.soft.format) {
> -     case AFMT_MU_LAW:
> -             ct_func = sound.trans_write->ct_ulaw;
> -             break;
> -     case AFMT_A_LAW:
> -             ct_func = sound.trans_write->ct_alaw;
> -             break;
> -     case AFMT_S8:
> -             ct_func = sound.trans_write->ct_s8;
> -             break;
> -     case AFMT_U8:
> -             ct_func = sound.trans_write->ct_u8;
> -             break;
> -     case AFMT_S16_BE:
> -             ct_func = sound.trans_write->ct_s16be;
> -             break;
> -     case AFMT_U16_BE:
> -             ct_func = sound.trans_write->ct_u16be;
> -             break;
> -     case AFMT_S16_LE:
> -             ct_func = sound.trans_write->ct_s16le;
> -             break;
> -     case AFMT_U16_LE:
> -             ct_func = sound.trans_write->ct_u16le;
> -             break;
> -     }
> -     if (ct_func)
> -             return ct_func(userPtr, userCount, frame, frameUsed, frameLeft);
> -     else
> -             return 0;
> -}
> -
> -static ssize_t sound_copy_translate_read(const u_char *userPtr,
> -                                 size_t userCount,
> -                                 u_char frame[], ssize_t *frameUsed,
> -                                 ssize_t frameLeft)
> -{
> -     ssize_t (*ct_func)(const u_char *, size_t, u_char *, ssize_t *, 
> ssize_t) = NULL;
> -
> -     switch (sound.soft.format) {
> -     case AFMT_MU_LAW:
> -             ct_func = sound.trans_read->ct_ulaw;
> -             break;
> -     case AFMT_A_LAW:
> -             ct_func = sound.trans_read->ct_alaw;
> -             break;
> -     case AFMT_S8:
> -             ct_func = sound.trans_read->ct_s8;
> -             break;
> -     case AFMT_U8:
> -             ct_func = sound.trans_read->ct_u8;
> -             break;
> -     case AFMT_S16_BE:
> -             ct_func = sound.trans_read->ct_s16be;
> -             break;
> -     case AFMT_U16_BE:
> -             ct_func = sound.trans_read->ct_u16be;
> -             break;
> -     case AFMT_S16_LE:
> -             ct_func = sound.trans_read->ct_s16le;
> -             break;
> -     case AFMT_U16_LE:
> -             ct_func = sound.trans_read->ct_u16le;
> -             break;
> -     }
> -     if (ct_func)
> -             return ct_func(userPtr, userCount, frame, frameUsed, frameLeft);
> -     else
> -             return 0;
> -}
> -
> -
> -/*
> - * /dev/mixer abstraction
> - */
> -
> -static int mixer_open(struct inode *inode, struct file *file)
> -{
> -     mixer.busy = 1;
> -     return nonseekable_open(inode, file);
> -}
> -
> -
> -static int mixer_release(struct inode *inode, struct file *file)
> -{
> -     mixer.busy = 0;
> -     return 0;
> -}
> -
> -
> -static int mixer_ioctl(struct inode *inode, struct file *file, u_int cmd,
> -                    u_long arg)
> -{
> -     int data;
> -     uint tmpcs;
> -
> -     if (_SIOC_DIR(cmd) & _SIOC_WRITE)
> -         mixer.modify_counter++;
> -     if (cmd == OSS_GETVERSION)
> -         return IOCTL_OUT(arg, SOUND_VERSION);
> -     switch (cmd) {
> -             case SOUND_MIXER_INFO: {
> -                 mixer_info info;
> -                 strlcpy(info.id, "CS4218_TDM", sizeof(info.id));
> -                 strlcpy(info.name, "CS4218_TDM", sizeof(info.name));
> -                 info.name[sizeof(info.name)-1] = 0;
> -                 info.modify_counter = mixer.modify_counter;
> -                 if (copy_to_user((int *)arg, &info, sizeof(info)))
> -                             return -EFAULT;
> -                 return 0;
> -             }
> -             case SOUND_MIXER_READ_DEVMASK:
> -                     data = SOUND_MASK_VOLUME | SOUND_MASK_LINE
> -                             | SOUND_MASK_MIC | SOUND_MASK_RECLEV
> -                             | SOUND_MASK_ALTPCM;
> -                     return IOCTL_OUT(arg, data);
> -             case SOUND_MIXER_READ_RECMASK:
> -                     data = SOUND_MASK_LINE | SOUND_MASK_MIC;
> -                     return IOCTL_OUT(arg, data);
> -             case SOUND_MIXER_READ_RECSRC:
> -                     if (cs4218_control & CS_DO1)
> -                             data = SOUND_MASK_LINE;
> -                     else
> -                             data = SOUND_MASK_MIC;
> -                     return IOCTL_OUT(arg, data);
> -             case SOUND_MIXER_WRITE_RECSRC:
> -                     IOCTL_IN(arg, data);
> -                     data &= (SOUND_MASK_LINE | SOUND_MASK_MIC);
> -                     if (data & SOUND_MASK_LINE)
> -                             tmpcs = cs4218_control |
> -                                             (CS_ISL | CS_ISR | CS_DO1);
> -                     if (data & SOUND_MASK_MIC)
> -                             tmpcs = cs4218_control &
> -                                             ~(CS_ISL | CS_ISR | CS_DO1);
> -                     if (tmpcs != cs4218_control)
> -                             cs4218_ctl_write(tmpcs);
> -                     return IOCTL_OUT(arg, data);
> -             case SOUND_MIXER_READ_STEREODEVS:
> -                     data = SOUND_MASK_VOLUME | SOUND_MASK_RECLEV;
> -                     return IOCTL_OUT(arg, data);
> -             case SOUND_MIXER_READ_CAPS:
> -                     return IOCTL_OUT(arg, 0);
> -             case SOUND_MIXER_READ_VOLUME:
> -                     data = (cs4218_control & CS_MUTE)? 0:
> -                             cs_get_volume(cs4218_control);
> -                     return IOCTL_OUT(arg, data);
> -             case SOUND_MIXER_WRITE_VOLUME:
> -                     IOCTL_IN(arg, data);
> -                     return IOCTL_OUT(arg, sound_set_volume(data));
> -             case SOUND_MIXER_WRITE_ALTPCM:  /* really bell volume */
> -                     IOCTL_IN(arg, data);
> -                     beep_volume = data & 0xff;
> -                     /* fall through */
> -             case SOUND_MIXER_READ_ALTPCM:
> -                     return IOCTL_OUT(arg, beep_volume);
> -             case SOUND_MIXER_WRITE_RECLEV:
> -                     IOCTL_IN(arg, data);
> -                     data = cs_set_gain(data);
> -                     return IOCTL_OUT(arg, data);
> -             case SOUND_MIXER_READ_RECLEV:
> -                     data = cs_get_gain(cs4218_control);
> -                     return IOCTL_OUT(arg, data);
> -     }
> -
> -     return -EINVAL;
> -}
> -
> -
> -static const struct file_operations mixer_fops =
> -{
> -     .owner =        THIS_MODULE,
> -     .llseek =       sound_lseek,
> -     .ioctl =        mixer_ioctl,
> -     .open =         mixer_open,
> -     .release =      mixer_release,
> -};
> -
> -
> -static void __init mixer_init(void)
> -{
> -     mixer_unit = register_sound_mixer(&mixer_fops, -1);
> -     if (mixer_unit < 0)
> -             return;
> -
> -     mixer.busy = 0;
> -     sound.treble = 0;
> -     sound.bass = 0;
> -
> -     /* Set Line input, no gain, no attenuation.
> -     */
> -     cs4218_control = CS_ISL | CS_ISR | CS_DO1;
> -     cs4218_control |= CS_LGAIN_SET(0) | CS_RGAIN_SET(0);
> -     cs4218_control |= CS_LATTEN_SET(0) | CS_RATTEN_SET(0);
> -     cs4218_ctl_write(cs4218_control);
> -}
> -
> -
> -/*
> - * Sound queue stuff, the heart of the driver
> - */
> -
> -
> -static int sq_allocate_buffers(void)
> -{
> -     int i;
> -
> -     if (sound_buffers)
> -             return 0;
> -     sound_buffers = kmalloc (numBufs * sizeof(char *), GFP_KERNEL);
> -     if (!sound_buffers)
> -             return -ENOMEM;
> -     for (i = 0; i < numBufs; i++) {
> -             sound_buffers[i] = sound.mach.dma_alloc (bufSize << 10, 
> GFP_KERNEL);
> -             if (!sound_buffers[i]) {
> -                     while (i--)
> -                             sound.mach.dma_free (sound_buffers[i], bufSize 
> << 10);
> -                     kfree (sound_buffers);
> -                     sound_buffers = 0;
> -                     return -ENOMEM;
> -             }
> -     }
> -     return 0;
> -}
> -
> -
> -static void sq_release_buffers(void)
> -{
> -     int i;
> -
> -     if (sound_buffers) {
> -             for (i = 0; i < numBufs; i++)
> -                     sound.mach.dma_free (sound_buffers[i], bufSize << 10);
> -             kfree (sound_buffers);
> -             sound_buffers = 0;
> -     }
> -}
> -
> -
> -static int sq_allocate_read_buffers(void)
> -{
> -     int i;
> -
> -     if (sound_read_buffers)
> -             return 0;
> -     sound_read_buffers = kmalloc(numReadBufs * sizeof(char *), GFP_KERNEL);
> -     if (!sound_read_buffers)
> -             return -ENOMEM;
> -     for (i = 0; i < numBufs; i++) {
> -             sound_read_buffers[i] = sound.mach.dma_alloc (readbufSize<<10,
> -                                                           GFP_KERNEL);
> -             if (!sound_read_buffers[i]) {
> -                     while (i--)
> -                             sound.mach.dma_free (sound_read_buffers[i],
> -                                                  readbufSize << 10);
> -                     kfree (sound_read_buffers);
> -                     sound_read_buffers = 0;
> -                     return -ENOMEM;
> -             }
> -     }
> -     return 0;
> -}
> -
> -static void sq_release_read_buffers(void)
> -{
> -     int i;
> -
> -     if (sound_read_buffers) {
> -             cpmp->cp_smc[1].smc_smcmr &= ~SMCMR_REN;
> -             for (i = 0; i < numReadBufs; i++)
> -                     sound.mach.dma_free (sound_read_buffers[i],
> -                                          bufSize << 10);
> -             kfree (sound_read_buffers);
> -             sound_read_buffers = 0;
> -     }
> -}
> -
> -
> -static void sq_setup(int numBufs, int bufSize, char **write_buffers)
> -{
> -     int i;
> -     volatile cbd_t *bdp;
> -     volatile cpm8xx_t       *cp;
> -     volatile smc_t  *sp;
> -
> -     /* Make sure the SMC transmit is shut down.
> -     */
> -     cp = cpmp;
> -     sp = &cpmp->cp_smc[1];
> -     sp->smc_smcmr &= ~SMCMR_TEN;
> -
> -     sq.max_count = numBufs;
> -     sq.max_active = numBufs;
> -     sq.block_size = bufSize;
> -     sq.buffers = write_buffers;
> -
> -     sq.front = sq.count = 0;
> -     sq.rear = -1;
> -     sq.syncing = 0;
> -     sq.active = 0;
> -
> -     bdp = tx_base;
> -     for (i=0; i<numBufs; i++) {
> -             bdp->cbd_bufaddr = virt_to_bus(write_buffers[i]);
> -             bdp++;
> -     }
> -
> -     /* This causes the SMC to sync up with the first buffer again.
> -     */
> -     cp->cp_cpcr = mk_cr_cmd(CPM_CR_CH_SMC2, CPM_CR_INIT_TX) | CPM_CR_FLG;
> -     while (cp->cp_cpcr & CPM_CR_FLG);
> -}
> -
> -static void read_sq_setup(int numBufs, int bufSize, char **read_buffers)
> -{
> -     int i;
> -     volatile cbd_t *bdp;
> -     volatile cpm8xx_t       *cp;
> -     volatile smc_t  *sp;
> -
> -     /* Make sure the SMC receive is shut down.
> -     */
> -     cp = cpmp;
> -     sp = &cpmp->cp_smc[1];
> -     sp->smc_smcmr &= ~SMCMR_REN;
> -
> -     read_sq.max_count = numBufs;
> -     read_sq.max_active = numBufs;
> -     read_sq.block_size = bufSize;
> -     read_sq.buffers = read_buffers;
> -
> -     read_sq.front = read_sq.count = 0;
> -     read_sq.rear = 0;
> -     read_sq.rear_size = 0;
> -     read_sq.syncing = 0;
> -     read_sq.active = 0;
> -
> -     bdp = rx_base;
> -     for (i=0; i<numReadBufs; i++) {
> -             bdp->cbd_bufaddr = virt_to_bus(read_buffers[i]);
> -             bdp->cbd_datlen = read_sq.block_size;
> -             bdp++;
> -     }
> -
> -     /* This causes the SMC to sync up with the first buffer again.
> -     */
> -     cp->cp_cpcr = mk_cr_cmd(CPM_CR_CH_SMC2, CPM_CR_INIT_RX) | CPM_CR_FLG;
> -     while (cp->cp_cpcr & CPM_CR_FLG);
> -}
> -
> -
> -static void sq_play(void)
> -{
> -     (*sound.mach.play)();
> -}
> -
> -
> -/* ++TeSche: radically changed this one too */
> -
> -static ssize_t sq_write(struct file *file, const char *src, size_t uLeft,
> -                     loff_t *ppos)
> -{
> -     ssize_t uWritten = 0;
> -     u_char *dest;
> -     ssize_t uUsed, bUsed, bLeft;
> -
> -     /* ++TeSche: Is something like this necessary?
> -      * Hey, that's an honest question! Or does any other part of the
> -      * filesystem already checks this situation? I really don't know.
> -      */
> -     if (uLeft == 0)
> -             return 0;
> -
> -     /* The interrupt doesn't start to play the last, incomplete frame.
> -      * Thus we can append to it without disabling the interrupts! (Note
> -      * also that sq.rear isn't affected by the interrupt.)
> -      */
> -
> -     if (sq.count > 0 && (bLeft = sq.block_size-sq.rear_size) > 0) {
> -             dest = sq_block_address(sq.rear);
> -             bUsed = sq.rear_size;
> -             uUsed = sound_copy_translate(src, uLeft, dest, &bUsed, bLeft);
> -             if (uUsed <= 0)
> -                     return uUsed;
> -             src += uUsed;
> -             uWritten += uUsed;
> -             uLeft -= uUsed;
> -             sq.rear_size = bUsed;
> -     }
> -
> -     do {
> -             while (sq.count == sq.max_active) {
> -                     sq_play();
> -                     if (NON_BLOCKING(sq.open_mode))
> -                             return uWritten > 0 ? uWritten : -EAGAIN;
> -                     SLEEP(sq.action_queue);
> -                     if (SIGNAL_RECEIVED)
> -                             return uWritten > 0 ? uWritten : -EINTR;
> -             }
> -
> -             /* Here, we can avoid disabling the interrupt by first
> -              * copying and translating the data, and then updating
> -              * the sq variables. Until this is done, the interrupt
> -              * won't see the new frame and we can work on it
> -              * undisturbed.
> -              */
> -
> -             dest = sq_block_address((sq.rear+1) % sq.max_count);
> -             bUsed = 0;
> -             bLeft = sq.block_size;
> -             uUsed = sound_copy_translate(src, uLeft, dest, &bUsed, bLeft);
> -             if (uUsed <= 0)
> -                     break;
> -             src += uUsed;
> -             uWritten += uUsed;
> -             uLeft -= uUsed;
> -             if (bUsed) {
> -                     sq.rear = (sq.rear+1) % sq.max_count;
> -                     sq.rear_size = bUsed;
> -                     sq.count++;
> -             }
> -     } while (bUsed);   /* uUsed may have been 0 */
> -
> -     sq_play();
> -
> -     return uUsed < 0? uUsed: uWritten;
> -}
> -
> -
> -/***********/
> -
> -/* Here is how the values are used for reading.
> - * The value 'active' simply indicates the DMA is running.  This is
> - * done so the driver semantics are DMA starts when the first read is
> - * posted.  The value 'front' indicates the buffer we should next
> - * send to the user.  The value 'rear' indicates the buffer the DMA is
> - * currently filling.  When 'front' == 'rear' the buffer "ring" is
> - * empty (we always have an empty available).  The 'rear_size' is used
> - * to track partial offsets into the current buffer.  Right now, I just keep
> - * The DMA running.  If the reader can't keep up, the interrupt tosses
> - * the oldest buffer.  We could also shut down the DMA in this case.
> - */
> -static ssize_t sq_read(struct file *file, char *dst, size_t uLeft,
> -                       loff_t *ppos)
> -{
> -
> -     ssize_t uRead, bLeft, bUsed, uUsed;
> -
> -     if (uLeft == 0)
> -             return 0;
> -
> -     if (!read_sq.active)
> -             CS_Record();    /* Kick off the record process. */
> -
> -     uRead = 0;
> -
> -     /* Move what the user requests, depending upon other options.
> -     */
> -     while (uLeft > 0) {
> -
> -             /* When front == rear, the DMA is not done yet.
> -             */
> -             while (read_sq.front == read_sq.rear) {
> -                     if (NON_BLOCKING(read_sq.open_mode)) {
> -                            return uRead > 0 ? uRead : -EAGAIN;
> -                     }
> -                     SLEEP(read_sq.action_queue);
> -                     if (SIGNAL_RECEIVED)
> -                             return uRead > 0 ? uRead : -EINTR;
> -             }
> -
> -             /* The amount we move is either what is left in the
> -              * current buffer or what the user wants.
> -              */
> -             bLeft = read_sq.block_size - read_sq.rear_size;
> -             bUsed = read_sq.rear_size;
> -             uUsed = sound_copy_translate_read(dst, uLeft,
> -                     read_sq.buffers[read_sq.front], &bUsed, bLeft);
> -             if (uUsed <= 0)
> -                     return uUsed;
> -             dst += uUsed;
> -             uRead += uUsed;
> -             uLeft -= uUsed;
> -             read_sq.rear_size += bUsed;
> -             if (read_sq.rear_size >= read_sq.block_size) {
> -                     read_sq.rear_size = 0;
> -                     read_sq.front++;
> -                     if (read_sq.front >= read_sq.max_active)
> -                             read_sq.front = 0;
> -             }
> -     }
> -     return uRead;
> -}
> -
> -static int sq_open(struct inode *inode, struct file *file)
> -{
> -     int rc = 0;
> -
> -     if (file->f_mode & FMODE_WRITE) {
> -             if (sq.busy) {
> -                     rc = -EBUSY;
> -                     if (NON_BLOCKING(file->f_flags))
> -                             goto err_out;
> -                     rc = -EINTR;
> -                     while (sq.busy) {
> -                             SLEEP(sq.open_queue);
> -                             if (SIGNAL_RECEIVED)
> -                                     goto err_out;
> -                     }
> -             }
> -             sq.busy = 1; /* Let's play spot-the-race-condition */
> -
> -             if (sq_allocate_buffers()) goto err_out_nobusy;
> -
> -             sq_setup(numBufs, bufSize<<10,sound_buffers);
> -             sq.open_mode = file->f_mode;
> -     }
> -
> -
> -     if (file->f_mode & FMODE_READ) {
> -             if (read_sq.busy) {
> -                     rc = -EBUSY;
> -                     if (NON_BLOCKING(file->f_flags))
> -                             goto err_out;
> -                     rc = -EINTR;
> -                     while (read_sq.busy) {
> -                             SLEEP(read_sq.open_queue);
> -                             if (SIGNAL_RECEIVED)
> -                                     goto err_out;
> -                     }
> -                     rc = 0;
> -             }
> -             read_sq.busy = 1;
> -             if (sq_allocate_read_buffers()) goto err_out_nobusy;
> -
> -             read_sq_setup(numReadBufs,readbufSize<<10, sound_read_buffers);
> -             read_sq.open_mode = file->f_mode;
> -     }
> -
> -     /* Start up the 4218 by:
> -      * Reset.
> -      * Enable, unreset.
> -      */
> -     *((volatile uint *)HIOX_CSR4_ADDR) &= ~HIOX_CSR4_RSTAUDIO;
> -     eieio();
> -     *((volatile uint *)HIOX_CSR4_ADDR) |= HIOX_CSR4_ENAUDIO;
> -     mdelay(50);
> -     *((volatile uint *)HIOX_CSR4_ADDR) |= HIOX_CSR4_RSTAUDIO;
> -
> -     /* We need to send the current control word in case someone
> -      * opened /dev/mixer and changed things while we were shut
> -      * down.  Chances are good the initialization that follows
> -      * would have done this, but it is still possible it wouldn't.
> -      */
> -     cs4218_ctl_write(cs4218_control);
> -
> -     sound.minDev = iminor(inode) & 0x0f;
> -     sound.soft = sound.dsp;
> -     sound.hard = sound.dsp;
> -     sound_init();
> -     if ((iminor(inode) & 0x0f) == SND_DEV_AUDIO) {
> -             sound_set_speed(8000);
> -             sound_set_stereo(0);
> -             sound_set_format(AFMT_MU_LAW);
> -     }
> -
> -     return nonseekable_open(inode, file);
> -
> -err_out_nobusy:
> -     if (file->f_mode & FMODE_WRITE) {
> -             sq.busy = 0;
> -             WAKE_UP(sq.open_queue);
> -     }
> -     if (file->f_mode & FMODE_READ) {
> -             read_sq.busy = 0;
> -             WAKE_UP(read_sq.open_queue);
> -     }
> -err_out:
> -     return rc;
> -}
> -
> -
> -static void sq_reset(void)
> -{
> -     sound_silence();
> -     sq.active = 0;
> -     sq.count = 0;
> -     sq.front = (sq.rear+1) % sq.max_count;
> -#if 0
> -     init_tdm_buffers();
> -#endif
> -}
> -
> -
> -static int sq_fsync(struct file *filp, struct dentry *dentry)
> -{
> -     int rc = 0;
> -
> -     sq.syncing = 1;
> -     sq_play();      /* there may be an incomplete frame waiting */
> -
> -     while (sq.active) {
> -             SLEEP(sq.sync_queue);
> -             if (SIGNAL_RECEIVED) {
> -                     /* While waiting for audio output to drain, an
> -                      * interrupt occurred.  Stop audio output immediately
> -                      * and clear the queue. */
> -                     sq_reset();
> -                     rc = -EINTR;
> -                     break;
> -             }
> -     }
> -
> -     sq.syncing = 0;
> -     return rc;
> -}
> -
> -static int sq_release(struct inode *inode, struct file *file)
> -{
> -     int rc = 0;
> -
> -     if (sq.busy)
> -             rc = sq_fsync(file, file->f_path.dentry);
> -     sound.soft = sound.dsp;
> -     sound.hard = sound.dsp;
> -     sound_silence();
> -
> -     sq_release_read_buffers();
> -     sq_release_buffers();
> -
> -     if (file->f_mode & FMODE_READ) {
> -             read_sq.busy = 0;
> -             WAKE_UP(read_sq.open_queue);
> -     }
> -
> -     if (file->f_mode & FMODE_WRITE) {
> -             sq.busy = 0;
> -             WAKE_UP(sq.open_queue);
> -     }
> -
> -     /* Shut down the SMC.
> -     */
> -     cpmp->cp_smc[1].smc_smcmr &= ~(SMCMR_TEN | SMCMR_REN);
> -
> -     /* Shut down the codec.
> -     */
> -     *((volatile uint *)HIOX_CSR4_ADDR) |= HIOX_CSR4_RSTAUDIO;
> -     eieio();
> -     *((volatile uint *)HIOX_CSR4_ADDR) &= ~HIOX_CSR4_ENAUDIO;
> -
> -     /* Wake up a process waiting for the queue being released.
> -      * Note: There may be several processes waiting for a call
> -      * to open() returning. */
> -
> -     return rc;
> -}
> -
> -
> -static int sq_ioctl(struct inode *inode, struct file *file, u_int cmd,
> -                 u_long arg)
> -{
> -     u_long fmt;
> -     int data;
> -#if 0
> -     int size, nbufs;
> -#else
> -     int size;
> -#endif
> -
> -     switch (cmd) {
> -     case SNDCTL_DSP_RESET:
> -             sq_reset();
> -             return 0;
> -     case SNDCTL_DSP_POST:
> -     case SNDCTL_DSP_SYNC:
> -             return sq_fsync(file, file->f_path.dentry);
> -
> -             /* ++TeSche: before changing any of these it's
> -              * probably wise to wait until sound playing has
> -              * settled down. */
> -     case SNDCTL_DSP_SPEED:
> -             sq_fsync(file, file->f_path.dentry);
> -             IOCTL_IN(arg, data);
> -             return IOCTL_OUT(arg, sound_set_speed(data));
> -     case SNDCTL_DSP_STEREO:
> -             sq_fsync(file, file->f_path.dentry);
> -             IOCTL_IN(arg, data);
> -             return IOCTL_OUT(arg, sound_set_stereo(data));
> -     case SOUND_PCM_WRITE_CHANNELS:
> -             sq_fsync(file, file->f_path.dentry);
> -             IOCTL_IN(arg, data);
> -             return IOCTL_OUT(arg, sound_set_stereo(data-1)+1);
> -     case SNDCTL_DSP_SETFMT:
> -             sq_fsync(file, file->f_path.dentry);
> -             IOCTL_IN(arg, data);
> -             return IOCTL_OUT(arg, sound_set_format(data));
> -     case SNDCTL_DSP_GETFMTS:
> -             fmt = 0;
> -             if (sound.trans_write) {
> -                     if (sound.trans_write->ct_ulaw)
> -                             fmt |= AFMT_MU_LAW;
> -                     if (sound.trans_write->ct_alaw)
> -                             fmt |= AFMT_A_LAW;
> -                     if (sound.trans_write->ct_s8)
> -                             fmt |= AFMT_S8;
> -                     if (sound.trans_write->ct_u8)
> -                             fmt |= AFMT_U8;
> -                     if (sound.trans_write->ct_s16be)
> -                             fmt |= AFMT_S16_BE;
> -                     if (sound.trans_write->ct_u16be)
> -                             fmt |= AFMT_U16_BE;
> -                     if (sound.trans_write->ct_s16le)
> -                             fmt |= AFMT_S16_LE;
> -                     if (sound.trans_write->ct_u16le)
> -                             fmt |= AFMT_U16_LE;
> -             }
> -             return IOCTL_OUT(arg, fmt);
> -     case SNDCTL_DSP_GETBLKSIZE:
> -             size = sq.block_size
> -                     * sound.soft.size * (sound.soft.stereo + 1)
> -                     / (sound.hard.size * (sound.hard.stereo + 1));
> -             return IOCTL_OUT(arg, size);
> -     case SNDCTL_DSP_SUBDIVIDE:
> -             break;
> -#if 0        /* Sorry can't do this at the moment.  The CPM allocated buffers
> -      * long ago that can't be changed.
> -      */
> -     case SNDCTL_DSP_SETFRAGMENT:
> -             if (sq.count || sq.active || sq.syncing)
> -                     return -EINVAL;
> -             IOCTL_IN(arg, size);
> -             nbufs = size >> 16;
> -             if (nbufs < 2 || nbufs > numBufs)
> -                     nbufs = numBufs;
> -             size &= 0xffff;
> -             if (size >= 8 && size <= 30) {
> -                     size = 1 << size;
> -                     size *= sound.hard.size * (sound.hard.stereo + 1);
> -                     size /= sound.soft.size * (sound.soft.stereo + 1);
> -                     if (size > (bufSize << 10))
> -                             size = bufSize << 10;
> -             } else
> -                     size = bufSize << 10;
> -             sq_setup(numBufs, size, sound_buffers);
> -             sq.max_active = nbufs;
> -             return 0;
> -#endif
> -
> -     default:
> -             return mixer_ioctl(inode, file, cmd, arg);
> -     }
> -     return -EINVAL;
> -}
> -
> -
> -
> -static const struct file_operations sq_fops =
> -{
> -     .owner =        THIS_MODULE,
> -     .llseek =       sound_lseek,
> -     .read =         sq_read,                        /* sq_read */
> -     .write =        sq_write,
> -     .ioctl =        sq_ioctl,
> -     .open =         sq_open,
> -     .release =      sq_release,
> -};
> -
> -
> -static void __init sq_init(void)
> -{
> -     sq_unit = register_sound_dsp(&sq_fops, -1);
> -     if (sq_unit < 0)
> -             return;
> -
> -     init_waitqueue_head(&sq.action_queue);
> -     init_waitqueue_head(&sq.open_queue);
> -     init_waitqueue_head(&sq.sync_queue);
> -     init_waitqueue_head(&read_sq.action_queue);
> -     init_waitqueue_head(&read_sq.open_queue);
> -     init_waitqueue_head(&read_sq.sync_queue);
> -
> -     sq.busy = 0;
> -     read_sq.busy = 0;
> -
> -     /* whatever you like as startup mode for /dev/dsp,
> -      * (/dev/audio hasn't got a startup mode). note that
> -      * once changed a new open() will *not* restore these!
> -      */
> -     sound.dsp.format = AFMT_S16_BE;
> -     sound.dsp.stereo = 1;
> -     sound.dsp.size = 16;
> -
> -     /* set minimum rate possible without expanding */
> -     sound.dsp.speed = 8000;
> -
> -     /* before the first open to /dev/dsp this wouldn't be set */
> -     sound.soft = sound.dsp;
> -     sound.hard = sound.dsp;
> -
> -     sound_silence();
> -}
> -
> -/*
> - * /dev/sndstat
> - */
> -
> -
> -/* state.buf should not overflow! */
> -
> -static int state_open(struct inode *inode, struct file *file)
> -{
> -     char *buffer = state.buf, *mach = "", cs4218_buf[50];
> -     int len = 0;
> -
> -     if (state.busy)
> -             return -EBUSY;
> -
> -     state.ptr = 0;
> -     state.busy = 1;
> -
> -     sprintf(cs4218_buf, "Crystal CS4218 on TDM, ");
> -     mach = cs4218_buf;
> -
> -     len += sprintf(buffer+len, "%sDMA sound driver:\n", mach);
> -
> -     len += sprintf(buffer+len, "\tsound.format = 0x%x", sound.soft.format);
> -     switch (sound.soft.format) {
> -     case AFMT_MU_LAW:
> -             len += sprintf(buffer+len, " (mu-law)");
> -             break;
> -     case AFMT_A_LAW:
> -             len += sprintf(buffer+len, " (A-law)");
> -             break;
> -     case AFMT_U8:
> -             len += sprintf(buffer+len, " (unsigned 8 bit)");
> -             break;
> -     case AFMT_S8:
> -             len += sprintf(buffer+len, " (signed 8 bit)");
> -             break;
> -     case AFMT_S16_BE:
> -             len += sprintf(buffer+len, " (signed 16 bit big)");
> -             break;
> -     case AFMT_U16_BE:
> -             len += sprintf(buffer+len, " (unsigned 16 bit big)");
> -             break;
> -     case AFMT_S16_LE:
> -             len += sprintf(buffer+len, " (signed 16 bit little)");
> -             break;
> -     case AFMT_U16_LE:
> -             len += sprintf(buffer+len, " (unsigned 16 bit little)");
> -             break;
> -     }
> -     len += sprintf(buffer+len, "\n");
> -     len += sprintf(buffer+len, "\tsound.speed = %dHz (phys. %dHz)\n",
> -                    sound.soft.speed, sound.hard.speed);
> -     len += sprintf(buffer+len, "\tsound.stereo = 0x%x (%s)\n",
> -                    sound.soft.stereo, sound.soft.stereo ? "stereo" : 
> "mono");
> -     len += sprintf(buffer+len, "\tsq.block_size = %d sq.max_count = %d"
> -                    " sq.max_active = %d\n",
> -                    sq.block_size, sq.max_count, sq.max_active);
> -     len += sprintf(buffer+len, "\tsq.count = %d sq.rear_size = %d\n", 
> sq.count,
> -                    sq.rear_size);
> -     len += sprintf(buffer+len, "\tsq.active = %d sq.syncing = %d\n",
> -                    sq.active, sq.syncing);
> -     state.len = len;
> -     return nonseekable_open(inode, file);
> -}
> -
> -
> -static int state_release(struct inode *inode, struct file *file)
> -{
> -     state.busy = 0;
> -     return 0;
> -}
> -
> -
> -static ssize_t state_read(struct file *file, char *buf, size_t count,
> -                       loff_t *ppos)
> -{
> -     int n = state.len - state.ptr;
> -     if (n > count)
> -             n = count;
> -     if (n <= 0)
> -             return 0;
> -     if (copy_to_user(buf, &state.buf[state.ptr], n))
> -             return -EFAULT;
> -     state.ptr += n;
> -     return n;
> -}
> -
> -
> -static const struct file_operations state_fops =
> -{
> -     .owner =        THIS_MODULE,
> -     .llseek =       sound_lseek,
> -     .read =         state_read,
> -     .open =         state_open,
> -     .release =      state_release,
> -};
> -
> -
> -static void __init state_init(void)
> -{
> -     state_unit = register_sound_special(&state_fops, SND_DEV_STATUS);
> -     if (state_unit < 0)
> -             return;
> -     state.busy = 0;
> -}
> -
> -
> -/*** Common stuff ********************************************************/
> -
> -static long long sound_lseek(struct file *file, long long offset, int orig)
> -{
> -     return -ESPIPE;
> -}
> -
> -
> -/*** Config & Setup 
> **********************************************************/
> -
> -
> -int __init tdm8xx_sound_init(void)
> -{
> -     int i, has_sound;
> -     uint                    dp_offset;
> -     volatile uint           *sirp;
> -     volatile cbd_t          *bdp;
> -     volatile cpm8xx_t       *cp;
> -     volatile smc_t          *sp;
> -     volatile smc_uart_t     *up;
> -     volatile immap_t        *immap;
> -
> -     has_sound = 0;
> -
> -     /* Program the SI/TSA to use TDMa, connected to SMC2, for 4 bytes.
> -     */
> -     cp = cpmp;      /* Get pointer to Communication Processor */
> -     immap = (immap_t *)IMAP_ADDR;   /* and to internal registers */
> -
> -     /* Set all TDMa control bits to zero.  This enables most features
> -      * we want.
> -      */
> -     cp->cp_simode &= ~0x00000fff;
> -
> -     /* Enable common receive/transmit clock pins, use IDL format.
> -      * Sync on falling edge, transmit rising clock, receive falling
> -      * clock, delay 1 bit on both Tx and Rx.  Common Tx/Rx clocks and
> -      * sync.
> -      * Connect SMC2 to TSA.
> -      */
> -     cp->cp_simode |= 0x80000141;
> -
> -     /* Configure port A pins for TDMa operation.
> -      * The RPX-Lite (MPC850/823) loses SMC2 when TDM is used.
> -      */
> -     immap->im_ioport.iop_papar |= 0x01c0; /* Enable TDMa functions */
> -     immap->im_ioport.iop_padir |= 0x00c0; /* Enable TDMa Tx/Rx */
> -     immap->im_ioport.iop_padir &= ~0x0100; /* Enable L1RCLKa */
> -
> -     immap->im_ioport.iop_pcpar |= 0x0800; /* Enable L1RSYNCa */
> -     immap->im_ioport.iop_pcdir &= ~0x0800;
> -
> -     /* Initialize the SI TDM routing table.  We use TDMa only.
> -      * The receive table and transmit table each have only one
> -      * entry, to capture/send four bytes after each frame pulse.
> -      * The 16-bit ram entry is 0000 0001 1000 1111. (SMC2)
> -      */
> -     cp->cp_sigmr = 0;
> -     sirp = (uint *)cp->cp_siram;
> -
> -     *sirp = 0x018f0000;             /* Receive entry */
> -     sirp += 64;
> -     *sirp = 0x018f0000;             /* Tramsmit entry */
> -
> -     /* Enable single TDMa routing.
> -     */
> -     cp->cp_sigmr = 0x04;
> -
> -     /* Initialize the SMC for transparent operation.
> -     */
> -     sp = &cpmp->cp_smc[1];
> -     up = (smc_uart_t *)&cp->cp_dparam[PROFF_SMC2];
> -
> -     /* We need to allocate a transmit and receive buffer
> -      * descriptors from dual port ram.
> -      */
> -     dp_addr = cpm_dpalloc(sizeof(cbd_t) * numReadBufs, 8);
> -
> -     /* Set the physical address of the host memory
> -      * buffers in the buffer descriptors, and the
> -      * virtual address for us to work with.
> -      */
> -     bdp = (cbd_t *)&cp->cp_dpmem[dp_addr];
> -     up->smc_rbase = dp_offset;
> -     rx_cur = rx_base = (cbd_t *)bdp;
> -
> -     for (i=0; i<(numReadBufs-1); i++) {
> -             bdp->cbd_bufaddr = 0;
> -             bdp->cbd_datlen = 0;
> -             bdp->cbd_sc = BD_SC_EMPTY | BD_SC_INTRPT;
> -             bdp++;
> -     }
> -     bdp->cbd_bufaddr = 0;
> -     bdp->cbd_datlen = 0;
> -     bdp->cbd_sc = BD_SC_WRAP | BD_SC_EMPTY | BD_SC_INTRPT;
> -
> -     /* Now, do the same for the transmit buffers.
> -     */
> -     dp_offset = cpm_dpalloc(sizeof(cbd_t) * numBufs, 8);
> -
> -     bdp = (cbd_t *)&cp->cp_dpmem[dp_addr];
> -     up->smc_tbase = dp_offset;
> -     tx_cur = tx_base = (cbd_t *)bdp;
> -
> -     for (i=0; i<(numBufs-1); i++) {
> -             bdp->cbd_bufaddr = 0;
> -             bdp->cbd_datlen = 0;
> -             bdp->cbd_sc = BD_SC_INTRPT;
> -             bdp++;
> -     }
> -     bdp->cbd_bufaddr = 0;
> -     bdp->cbd_datlen = 0;
> -     bdp->cbd_sc = (BD_SC_WRAP | BD_SC_INTRPT);
> -
> -     /* Set transparent SMC mode.
> -      * A few things are specific to our application.  The codec interface
> -      * is MSB first, hence the REVD selection.  The CD/CTS pulse are
> -      * used by the TSA to indicate the frame start to the SMC.
> -      */
> -     up->smc_rfcr = SCC_EB;
> -     up->smc_tfcr = SCC_EB;
> -     up->smc_mrblr = readbufSize * 1024;
> -
> -     /* Set 16-bit reversed data, transparent mode.
> -     */
> -     sp->smc_smcmr = smcr_mk_clen(15) |
> -             SMCMR_SM_TRANS | SMCMR_REVD | SMCMR_BS;
> -
> -     /* Enable and clear events.
> -      * Because of FIFO delays, all we need is the receive interrupt
> -      * and we can process both the current receive and current
> -      * transmit interrupt within a few microseconds of the transmit.
> -      */
> -     sp->smc_smce = 0xff;
> -     sp->smc_smcm = SMCM_TXE | SMCM_TX | SMCM_RX;
> -
> -     /* Send the CPM an initialize command.
> -     */
> -     cp->cp_cpcr = mk_cr_cmd(CPM_CR_CH_SMC2,
> -                             CPM_CR_INIT_TRX) | CPM_CR_FLG;
> -     while (cp->cp_cpcr & CPM_CR_FLG);
> -
> -     sound.mach = mach_cs4218;
> -     has_sound = 1;
> -
> -     /* Initialize beep stuff */
> -     orig_mksound = kd_mksound;
> -     kd_mksound = cs_mksound;
> -     beep_buf = kmalloc(BEEP_BUFLEN * 4, GFP_KERNEL);
> -     if (beep_buf == NULL)
> -             printk(KERN_WARNING "dmasound: no memory for "
> -                    "beep buffer\n");
> -
> -     if (!has_sound)
> -             return -ENODEV;
> -
> -     /* Initialize the software SPI.
> -     */
> -     sw_spi_init();
> -
> -     /* Set up sound queue, /dev/audio and /dev/dsp. */
> -
> -     /* Set default settings. */
> -     sq_init();
> -
> -     /* Set up /dev/sndstat. */
> -     state_init();
> -
> -     /* Set up /dev/mixer. */
> -     mixer_init();
> -
> -     if (!sound.mach.irqinit()) {
> -             printk(KERN_ERR "DMA sound driver: Interrupt initialization 
> failed\n");
> -             return -ENODEV;
> -     }
> -#ifdef MODULE
> -     irq_installed = 1;
> -#endif
> -
> -     printk(KERN_INFO "DMA sound driver installed, using %d buffers of 
> %dk.\n",
> -            numBufs, bufSize);
> -
> -     return 0;
> -}
> -
> -/* Due to FIFOs and bit delays, the transmit interrupt occurs a few
> - * microseconds ahead of the receive interrupt.
> - * When we get an interrupt, we service the transmit first, then
> - * check for a receive to prevent the overhead of returning through
> - * the interrupt handler only to get back here right away during
> - * full duplex operation.
> - */
> -static void
> -cs4218_intr(void *dev_id)
> -{
> -     volatile smc_t  *sp;
> -     volatile cpm8xx_t       *cp;
> -
> -     sp = &cpmp->cp_smc[1];
> -
> -     if (sp->smc_smce & SCCM_TX) {
> -             sp->smc_smce = SCCM_TX;
> -             cs4218_tdm_tx_intr((void *)sp);
> -     }
> -
> -     if (sp->smc_smce & SCCM_RX) {
> -             sp->smc_smce = SCCM_RX;
> -             cs4218_tdm_rx_intr((void *)sp);
> -     }
> -
> -     if (sp->smc_smce & SCCM_TXE) {
> -             /* Transmit underrun.  This happens with the application
> -              * didn't keep up sending buffers.  We tell the SMC to
> -              * restart, which will cause it to poll the current (next)
> -              * BD.  If the user supplied data since this occurred,
> -              * we just start running again.  If they didn't, the SMC
> -              * will poll the descriptor until data is placed there.
> -              */
> -             sp->smc_smce = SCCM_TXE;
> -             cp = cpmp;      /* Get pointer to Communication Processor */
> -             cp->cp_cpcr = mk_cr_cmd(CPM_CR_CH_SMC2,
> -                                     CPM_CR_RESTART_TX) | CPM_CR_FLG;
> -             while (cp->cp_cpcr & CPM_CR_FLG);
> -     }
> -}
> -
> -
> -#define MAXARGS              8       /* Should be sufficient for now */
> -
> -void __init dmasound_setup(char *str, int *ints)
> -{
> -     /* check the bootstrap parameter for "dmasound=" */
> -
> -     switch (ints[0]) {
> -     case 3:
> -             if ((ints[3] < 0) || (ints[3] > MAX_CATCH_RADIUS))
> -                     printk("dmasound_setup: invalid catch radius, using 
> default = %d\n", catchRadius);
> -             else
> -                     catchRadius = ints[3];
> -             /* fall through */
> -     case 2:
> -             if (ints[1] < MIN_BUFFERS)
> -                     printk("dmasound_setup: invalid number of buffers, 
> using default = %d\n", numBufs);
> -             else
> -                     numBufs = ints[1];
> -             if (ints[2] < MIN_BUFSIZE || ints[2] > MAX_BUFSIZE)
> -                     printk("dmasound_setup: invalid buffer size, using 
> default = %d\n", bufSize);
> -             else
> -                     bufSize = ints[2];
> -             break;
> -     case 0:
> -             break;
> -     default:
> -             printk("dmasound_setup: invalid number of arguments\n");
> -     }
> -}
> -
> -/* Software SPI functions.
> - * These are on Port B.
> - */
> -#define PB_SPICLK    ((uint)0x00000002)
> -#define PB_SPIMOSI   ((uint)0x00000004)
> -#define PB_SPIMISO   ((uint)0x00000008)
> -
> -static
> -void sw_spi_init(void)
> -{
> -     volatile cpm8xx_t       *cp;
> -     volatile uint           *hcsr4;
> -
> -     hcsr4 = (volatile uint *)HIOX_CSR4_ADDR;
> -     cp = cpmp;      /* Get pointer to Communication Processor */
> -
> -     *hcsr4 &= ~HIOX_CSR4_AUDSPISEL; /* Disable SPI select */
> -
> -     /* Make these Port B signals general purpose I/O.
> -      * First, make sure the clock is low.
> -      */
> -     cp->cp_pbdat &= ~PB_SPICLK;
> -     cp->cp_pbpar &= ~(PB_SPICLK | PB_SPIMOSI | PB_SPIMISO);
> -
> -     /* Clock and Master Output are outputs.
> -     */
> -     cp->cp_pbdir |= (PB_SPICLK | PB_SPIMOSI);
> -
> -     /* Master Input.
> -     */
> -     cp->cp_pbdir &= ~PB_SPIMISO;
> -
> -}
> -
> -/* Write the CS4218 control word out the SPI port.  While the
> - * the control word is going out, the status word is arriving.
> - */
> -static
> -uint cs4218_ctl_write(uint ctlreg)
> -{
> -     uint    status;
> -
> -     sw_spi_io((u_char *)&ctlreg, (u_char *)&status, 4);
> -
> -     /* Shadow the control register.....I guess we could do
> -      * the same for the status, but for now we just return it
> -      * and let the caller decide.
> -      */
> -     cs4218_control = ctlreg;
> -     return status;
> -}
> -
> -static
> -void sw_spi_io(u_char *obuf, u_char *ibuf, uint bcnt)
> -{
> -     int     bits, i;
> -     u_char  outbyte, inbyte;
> -     volatile cpm8xx_t       *cp;
> -     volatile uint           *hcsr4;
> -
> -     hcsr4 = (volatile uint *)HIOX_CSR4_ADDR;
> -     cp = cpmp;      /* Get pointer to Communication Processor */
> -
> -     /* The timing on the bus is pretty slow.  Code inefficiency
> -      * and eieio() is our friend here :-).
> -      */
> -     cp->cp_pbdat &= ~PB_SPICLK;
> -     *hcsr4 |= HIOX_CSR4_AUDSPISEL;  /* Enable SPI select */
> -     eieio();
> -
> -     /* Clock in/out the bytes.  Data is valid on the falling edge
> -      * of the clock.  Data is MSB first.
> -      */
> -     for (i=0; i<bcnt; i++) {
> -             outbyte = *obuf++;
> -             inbyte = 0;
> -             for (bits=0; bits<8; bits++) {
> -                     eieio();
> -                     cp->cp_pbdat |= PB_SPICLK;
> -                     eieio();
> -                     if (outbyte & 0x80)
> -                             cp->cp_pbdat |= PB_SPIMOSI;
> -                     else
> -                             cp->cp_pbdat &= ~PB_SPIMOSI;
> -                     eieio();
> -                     cp->cp_pbdat &= ~PB_SPICLK;
> -                     eieio();
> -                     outbyte <<= 1;
> -                     inbyte <<= 1;
> -                     if (cp->cp_pbdat & PB_SPIMISO)
> -                             inbyte |= 1;
> -             }
> -             *ibuf++ = inbyte;
> -     }
> -
> -     *hcsr4 &= ~HIOX_CSR4_AUDSPISEL; /* Disable SPI select */
> -     eieio();
> -}
> -
> -void cleanup_module(void)
> -{
> -     if (irq_installed) {
> -             sound_silence();
> -#ifdef MODULE
> -             sound.mach.irqcleanup();
> -#endif
> -     }
> -
> -     sq_release_read_buffers();
> -     sq_release_buffers();
> -
> -     if (mixer_unit >= 0)
> -             unregister_sound_mixer(mixer_unit);
> -     if (state_unit >= 0)
> -             unregister_sound_special(state_unit);
> -     if (sq_unit >= 0)
> -             unregister_sound_dsp(sq_unit);
> -}
> -
> -module_init(tdm8xx_sound_init);
> -module_exit(cleanup_module);
> -
> -

Reply via email to