diff options
-rw-r--r-- | arch/mips/kernel/mips_ksyms.c | 10 | ||||
-rw-r--r-- | arch/mips/sgi/kernel/Makefile | 4 | ||||
-rw-r--r-- | drivers/sgi/audio/hal2.c | 202 |
3 files changed, 101 insertions, 115 deletions
diff --git a/arch/mips/kernel/mips_ksyms.c b/arch/mips/kernel/mips_ksyms.c index a07a13b37..9b2dd1bd9 100644 --- a/arch/mips/kernel/mips_ksyms.c +++ b/arch/mips/kernel/mips_ksyms.c @@ -1,4 +1,4 @@ -/* $Id: mips_ksyms.c,v 1.11 1999/01/27 19:24:54 ulfc Exp $ +/* $Id: mips_ksyms.c,v 1.12 1999/02/06 03:57:40 adevries Exp $ * * Export MIPS-specific functions needed for loadable modules. * @@ -25,7 +25,6 @@ #include <asm/sgihpc.h> #include <asm/softirq.h> #include <asm/uaccess.h> -#include <asm/indy_pbus.h> extern void *__bzero(void *__s, size_t __count); extern long __strncpy_from_user_nocheck_asm(char *__to, @@ -96,13 +95,6 @@ EXPORT_SYMBOL(vdma_log2phys); #ifdef CONFIG_SGI EXPORT_SYMBOL(hpc3c0); - -EXPORT_SYMBOL(sgipbus_request); -EXPORT_SYMBOL(sgipbus_free); -EXPORT_SYMBOL(sgipbus_enable); -EXPORT_SYMBOL(sgipbus_disable); -EXPORT_SYMBOL(sgipbus_setup); -EXPORT_SYMBOL(sgipbus_interrupted); #endif /* diff --git a/arch/mips/sgi/kernel/Makefile b/arch/mips/sgi/kernel/Makefile index 8c425912a..aca1cb036 100644 --- a/arch/mips/sgi/kernel/Makefile +++ b/arch/mips/sgi/kernel/Makefile @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.4 1998/08/25 09:14:48 ralf Exp $ +# $Id: Makefile,v 1.5 1999/01/27 04:50:27 adevries Exp $ # Makefile for the SGI specific kernel interface routines # under Linux. # @@ -13,7 +13,7 @@ .S.o: $(CC) $(CFLAGS) -c $< -o $*.o -OBJS = indy_mc.o indy_sc.o indy_hpc.o indy_int.o indy_rtc.o indy_pbus.o \ +OBJS = indy_mc.o indy_sc.o indy_hpc.o indy_int.o indy_rtc.o \ system.o indy_timer.o indyIRQ.o reset.o setup.o time.o all: sgikern.a diff --git a/drivers/sgi/audio/hal2.c b/drivers/sgi/audio/hal2.c index e28f0b389..5052ea471 100644 --- a/drivers/sgi/audio/hal2.c +++ b/drivers/sgi/audio/hal2.c @@ -1,4 +1,4 @@ -/* $Id: hal2.c,v 1.10 1999/02/02 20:24:46 ulfc Exp $ +/* $Id: hal2.c,v 1.11 1999/02/03 23:25:31 tsbogend Exp $ * * drivers/sgi/audio/hal2.c * @@ -45,19 +45,22 @@ struct hal2_channel { struct hal2_buffer *ring; int pbus; - int stereo; - int little_end; - int bres_mod; - int bres_master; /* 0=48.0k 1=44.1k */ - - enum {DAC, ADC} type; - int pbus_requested; - int pbus_enabled; - int hal2_enabled; + int bres_mod; + int bres_master; int bufs; int free_bufs; + + unsigned long flags; +#define H2_CH_LITTLE_END (1<<0) +#define H2_CH_DAC (1<<1) +#define H2_CH_STEREO (1<<2) +#define H2_CH_MASTER (1<<3) /* 0=48.0k 1=44.1k */ +#define H2_CH_PORT_ENBL (1<<4) +#define H2_CH_PBUS_SETUP (1<<5) +#define H2_CH_PBUS_ENBL (1<<6) + }; struct hal2_private { @@ -109,14 +112,12 @@ struct sgiaudio_chan_ops { #define INDIRECT_WAIT(regs) \ { \ int cnt = 1000; \ - udelay(200); \ printk("hal2: waiting isr:%04hx ", regs->isr); \ - udelay(200); \ printk("idr0:%04hx idr1:%04hx idr2:%04hx idr3:%04hx\n", \ regs->idr0, regs->idr1, regs->idr2, regs->idr3); \ \ while(regs->isr & H2_ISR_TSTATUS && --cnt) \ - udelay(200); \ + udelay(5); \ if (!cnt) \ printk("hal2: failed waiting for indirect trans.\n"); \ \ @@ -124,14 +125,12 @@ struct sgiaudio_chan_ops { cnt, regs->isr); \ printk("idr0:%04hx idr1:%04hx idr2:%04hx idr3:%04hx\n", \ regs->idr0, regs->idr1, regs->idr2, regs->idr3); \ - udelay(200); \ } \ static unsigned short ireg_read(unsigned short address) { unsigned short tmp; - udelay(200); h2_ctrl->iar = address; INDIRECT_WAIT(h2_ctrl) tmp = h2_ctrl->idr0; @@ -140,9 +139,7 @@ static unsigned short ireg_read(unsigned short address) static void ireg_write(unsigned short address, unsigned short val) { - udelay(200); h2_ctrl->idr0 = val; - udelay(200); h2_ctrl->iar = address; INDIRECT_WAIT(h2_ctrl) } @@ -150,11 +147,8 @@ static void ireg_write(unsigned short address, unsigned short val) static void ireg_write2(unsigned short address, unsigned short val0, unsigned short val1) { - udelay(200); h2_ctrl->idr0 = val0; - udelay(200); h2_ctrl->idr1 = val1; - udelay(200); h2_ctrl->iar = address; INDIRECT_WAIT(h2_ctrl) } @@ -162,15 +156,10 @@ static void ireg_write2(unsigned short address, unsigned short val0, unsigned static void ireg_write4(unsigned short address, unsigned short val0, unsigned short val1, unsigned short val2, unsigned short val3) { - udelay(200); h2_ctrl->idr0 = val0; - udelay(200); h2_ctrl->idr1 = val1; - udelay(200); h2_ctrl->idr2 = val2; - udelay(200); h2_ctrl->idr3 = val3; - udelay(200); h2_ctrl->iar = address; INDIRECT_WAIT(h2_ctrl) } @@ -184,7 +173,6 @@ static void ireg_setbit(unsigned short write_address, unsigned short INDIRECT_WAIT(h2_ctrl); tmp = h2_ctrl->idr0; h2_ctrl->idr0 = tmp | bit; - udelay(200); h2_ctrl->iar = write_address; INDIRECT_WAIT(h2_ctrl); } @@ -198,7 +186,6 @@ static void ireg_clearbit(unsigned short write_address, unsigned short INDIRECT_WAIT(h2_ctrl); tmp = h2_ctrl->idr0; h2_ctrl->idr0 = tmp & ~bit; - udelay(200); h2_ctrl->iar = write_address; INDIRECT_WAIT(h2_ctrl); } @@ -206,16 +193,39 @@ static void ireg_clearbit(unsigned short write_address, unsigned short static void hal2_reset(void) { printk("resetting global isr:%04hx\n", h2_ctrl->isr); - udelay(200); h2_ctrl->isr = 0; /* reset the card */ - udelay(200); printk("reset done isr:%04hx\n", h2_ctrl->isr); - udelay(200); h2_ctrl->isr = H2_ISR_GLOBAL_RESET_N | H2_ISR_CODEC_RESET_N; - udelay(200); printk("reactivation done isr:%04hx\n", h2_ctrl->isr); } +/* enable/disable a specific PBUS dma channel */ +__inline__ void sgipbus_enable(unsigned int channel, unsigned long desc) +{ + struct hpc3_pbus_dmacregs *pbus = &hpc3c0->pbdma0; + + pbus[channel].pbdma_dptr = desc; + pbus[channel].pbdma_ctrl |= HPC3_PDMACTRL_ACT; +} + +__inline__ void sgipbus_disable(unsigned int channel) +{ + struct hpc3_pbus_dmacregs *pbus = &hpc3c0->pbdma0; + + pbus[channel].pbdma_ctrl &= ~HPC3_PDMACTRL_ACT; +} + +__inline__ int sgipbus_interrupted(unsigned int channel) +{ + struct hpc3_pbus_dmacregs *pbus = &hpc3c0->pbdma0; + + /* When we read pbdma_ctrl, bit 0 indicates interrupt signal. + * The interrupt signal is also cleared after read + */ + + return (pbus[channel].pbdma_ctrl & 0x01); +} + static int hal2_probe(void) { unsigned short board, major, minor; @@ -234,7 +244,7 @@ static int hal2_probe(void) major = (h2_ctrl->rev & H2_REV_MAJOR_CHIP_M) >> 4; minor = (h2_ctrl->rev & H2_REV_MINOR_CHIP_M); - printk("SGI HAL2 Processor, Revision %i.%i.%i\n", + printk("SGI H2 Processor, Revision %i.%i.%i\n", board, major, minor); if (board != 4 || major != 1 || minor != 0) { @@ -283,7 +293,7 @@ static int hal2_init(struct sgiaudio *sa) if (initialized) { printk("hal2_init: already initialized?\n"); - goto out; + return 0; } if (!sa->private) { @@ -307,7 +317,7 @@ static int hal2_init(struct sgiaudio *sa) printk("hal2 init done..\n"); initialized = 1; -out: + return 0; } @@ -405,19 +415,17 @@ static int hal2_init_adc(struct sgiaudio *sa) static __inline__ int hal2_sample_size(struct hal2_channel *chan) { - return (chan->stereo ? 4 : 2); + return (chan->flags & H2_CH_STEREO ? 4 : 2); } static int hal2_setup_pbus(struct hal2_private *hp, struct hal2_channel *chan) { + struct hpc3_pbus_dmacregs *pbus = &hpc3c0->pbdma0; int sample_sz, highwater, fifosize; - unsigned long dmacfg; unsigned long flags; - char *device_id; - char *s1 = "hal2 "; - char *s2 = (chan->type == ADC ? "adc" : "dac"); - int i; - int err; + unsigned long fifobeg, fifoend; + + chan->pbus = (chan->flags & H2_CH_DAC) ? 0 : 1; sample_sz = hal2_sample_size(chan); /* bytes/sample */ @@ -427,36 +435,28 @@ static int hal2_setup_pbus(struct hal2_private *hp, struct hal2_channel *chan) fifosize = (sample_sz * 4) >> 3; /* doublewords */ highwater = (sample_sz * 2) >> 1; /* halfwords */ - device_id = (char *) kmalloc(strlen(s1) + strlen(s2), GFP_KERNEL); - if (!device_id) - return -ENOMEM; + /* DAC is always before ADC in our PBUS DMA FIFO. Reserve space for the + * maximum fifo length, we might change to stereo later if we're in mono + * now + */ - device_id[0] = 0; + if (chan->flags & H2_CH_DAC) + fifobeg = 0; + else + fifobeg = (4 * 4) >> 3; - strcat(device_id, s1); - strcat(device_id, s2); + fifoend = fifobeg + fifosize; - if (!chan->pbus_requested) { - for (i = 0; i < MAX_PBUS_CHANNELS; i++) { - if(sgipbus_request(i, device_id) == 0) { - chan->pbus = i; - chan->pbus_requested = 1; - printk("got pbus %d\n", chan->pbus); - break; - } - } + flags = HPC3_PDMACTRL_RT | + (chan->flags & H2_CH_DAC ? 0 : HPC3_PDMACTRL_RCV) | + (chan->flags & H2_CH_LITTLE_END ? HPC3_PDMACTRL_SEL : 0); - if (i == MAX_PBUS_CHANNELS) - return -EBUSY; - } + pbus[chan->pbus].pbdma_ctrl = (highwater << 8) | (fifobeg << 16) | + (fifoend << 24) | flags; - flags = HPC3_PDMACTRL_RT | (chan->type==ADC ? HPC3_PDMACTRL_RCV : 0) | - (chan->little_end ? HPC3_PDMACTRL_SEL : 0); - dmacfg = 0x8248844; /* realtime, 16-bit, cycles to spend etc.. */ - - err = sgipbus_setup(chan->pbus, fifosize, highwater, flags, dmacfg); - if (err) - return err; + /* Realtime, 16-bit, cycles to spend and more default settings for + * soundcards, taken directly from the spec. */ + hpc3c0->pbus_dmacfgs[chan->pbus][0] = 0x8248844; return 0; } @@ -587,40 +587,34 @@ static void hal2_reset_adc_ring(struct hal2_private *hp, struct hal2_channel static void hal2_enable_port(struct hal2_private *hp, struct hal2_channel *chan) { - if (!chan->hal2_enabled) { + if (!(chan->flags & H2_CH_PORT_ENBL)) { /* pick a dma port */ ireg_setbit(H2IW_DMA_DRV, H2IR_DMA_DRV, (1 << chan->pbus)); /* activate it! */ - switch (chan->type) { - case DAC: + if (chan->flags & H2_CH_DAC) ireg_setbit(H2IW_DMA_PORT_EN, H2IR_DMA_PORT_EN, H2I_DMA_PORT_EN_CODECTX); - break; - case ADC: + else ireg_setbit(H2IW_DMA_PORT_EN, H2IR_DMA_PORT_EN, H2I_DMA_PORT_EN_CODECR); - break; - } - chan->hal2_enabled = 1; + + chan->flags |= H2_CH_PORT_ENBL; } } static void hal2_disable_port(struct hal2_private *hp, struct hal2_channel *chan) { - if (chan->hal2_enabled) { - switch (chan->type) { - case DAC: + if (chan->flags & H2_CH_PORT_ENBL) { + if (chan->flags & H2_CH_DAC) ireg_clearbit(H2IW_DMA_PORT_EN, H2IR_DMA_PORT_EN, H2I_DMA_PORT_EN_CODECTX); - break; - case ADC: + else ireg_clearbit(H2IW_DMA_PORT_EN, H2IR_DMA_PORT_EN, H2I_DMA_PORT_EN_CODECR); - break; - } - chan->hal2_enabled = 0; + + chan->flags &= ~H2_CH_PORT_ENBL; } } @@ -711,7 +705,7 @@ static int hal2_configure_dac(struct sgiaudio *sa) { struct hal2_private *hp = (struct hal2_private *) sa->private; struct hal2_channel *chan = &hp->dac_chan; - int datatype = (chan->stereo?2:0) << 8; + int datatype = ((chan->flags & H2_CH_STEREO)?2:0) << 8; int clock = 1 << 3; /* Let's be sure that the dma port is disabled */ @@ -719,7 +713,7 @@ static int hal2_configure_dac(struct sgiaudio *sa) hal2_configure_bres1(hp, chan); - if (chan->little_end) + if (chan->flags & H2_CH_LITTLE_END) ireg_setbit(H2IW_DMA_END, H2IR_DMA_END, H2I_DMA_PORT_EN_CODECTX); else @@ -742,14 +736,14 @@ static int hal2_configure_adc(struct sgiaudio *sa) { struct hal2_private *hp = (struct hal2_private *) sa->private; struct hal2_channel *chan = &hp->dac_chan; - int datatype = (chan->stereo?2:0) << 8; + int datatype = ((chan->flags & H2_CH_STEREO)?2:0) << 8; int clock = 2 << 3; hal2_disable_port(hp, chan); hal2_configure_bres2(hp, chan); - if (chan->little_end) + if (chan->flags & H2_CH_LITTLE_END) ireg_setbit(H2IW_DMA_END, H2IR_DMA_END, H2I_DMA_PORT_EN_CODECR); else ireg_clearbit(H2IW_DMA_END, H2IR_DMA_END, @@ -772,7 +766,7 @@ static int hal2_set_dac_stereo(struct sgiaudio *sa, int stereo) struct hal2_private *hp = (struct hal2_private *) sa->private; struct hal2_channel *chan = &hp->dac_chan; - chan->stereo = stereo; + chan->flags |= H2_CH_STEREO; return 0; } @@ -782,7 +776,7 @@ static int hal2_set_adc_stereo(struct sgiaudio *sa, int stereo) struct hal2_private *hp = (struct hal2_private *) sa->private; struct hal2_channel *chan = &hp->dac_chan; - chan->stereo = stereo; + chan->flags |= H2_CH_STEREO; return 0; } @@ -792,7 +786,10 @@ static int hal2_set_dac_endian(struct sgiaudio *sa, int little_end) struct hal2_private *hp = (struct hal2_private *) sa->private; struct hal2_channel *chan = &hp->dac_chan; - chan->little_end = little_end; + if (little_end) + chan->flags |= H2_CH_LITTLE_END; + else + chan->flags &= ~H2_CH_LITTLE_END; return 0; } @@ -802,7 +799,10 @@ static int hal2_set_adc_endian(struct sgiaudio *sa, int little_end) struct hal2_private *hp = (struct hal2_private *) sa->private; struct hal2_channel *chan = &hp->adc_chan; - chan->little_end = little_end; + if (little_end) + chan->flags |= H2_CH_LITTLE_END; + else + chan->flags &= ~H2_CH_LITTLE_END; return 0; } @@ -836,24 +836,24 @@ static void hal2_go(struct hal2_channel *chan) { /* The hal2 *has* to be enabled before we enable PBUS DMA transfers, * atleast I say so.. (we need some kind of "order") */ - if (!chan->hal2_enabled) + if (!(chan->flags & H2_CH_PORT_ENBL)) return; - if (!chan->pbus_enabled) { + if (!(chan->flags & H2_CH_PBUS_ENBL)) { sgipbus_enable(chan->pbus, PHYSADDR(&chan->ring->desc)); - chan->pbus_enabled = 1; + chan->flags |= H2_CH_PBUS_ENBL; } #ifdef DEBUG else - printk("Attempt to enable the HAL2 DMA channel twice\n"); + printk("Attempt to enable the H2 DMA channel twice\n"); #endif } static void hal2_stop_pbus(struct hal2_channel *chan) { - if (chan->pbus_enabled) { + if (chan->flags & H2_CH_PBUS_ENBL) { sgipbus_enable(chan->pbus, PHYSADDR(&chan->ring->desc)); - chan->pbus_enabled = 0; + chan->flags &= ~H2_CH_PBUS_ENBL; } #ifdef DEBUG else @@ -911,9 +911,6 @@ static void hal2_free_dac(struct sgiaudio *sa) if (!hp) return; - if (chan->pbus_requested) - sgipbus_free(chan->pbus); - kfree(hp); } @@ -925,9 +922,6 @@ static void hal2_free_adc(struct sgiaudio *sa) if (!hp) return; - if (chan->pbus_requested) - sgipbus_free(chan->pbus); - kfree(hp); } @@ -939,12 +933,12 @@ void hal2_interrupt(int irq, void *dev_id, struct pt_regs *regs) struct hal2_channel *chan; chan = &hp->dac_chan; - if (chan->pbus_enabled && sgipbus_interrupted(chan->pbus)) + if ((chan->flags & H2_CH_PBUS_ENBL) && sgipbus_interrupted(chan->pbus)) while (chan->free_bufs && !hp->dac_underrun) hal2_update_dac_buf(sa, hp); chan = &hp->adc_chan; - if (chan->pbus_enabled && sgipbus_interrupted(chan->pbus)) + if ((chan->flags & H2_CH_PBUS_ENBL) && sgipbus_interrupted(chan->pbus)) ; } |