Several things:
* Use the new trigger_{in,out}put interface. * Allow the play and record channels to have different encodings (but the same sample rate). * Play u-law and a-law as 16-bit data. (This may not work yet...)
This commit is contained in:
parent
17431823fb
commit
4ffebebb25
@ -1,13 +1,13 @@
|
||||
/* $NetBSD: eap.c,v 1.8 1998/07/06 11:12:21 augustss Exp $ */
|
||||
/* $NetBSD: eap.c,v 1.9 1998/08/09 20:32:34 mycroft Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1998 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Author: Lennart Augustsson <augustss@cs.chalmers.se>
|
||||
* Charles Hannum <mycroft@netbsd.org>
|
||||
*
|
||||
* Debugging: Andreas Gustafsson <gson@araneus.fi>
|
||||
* Charles Hannum <mycroft@netbsd.org>
|
||||
* Testing: Chuck Cranor <chuck@maria.wustl.edu>
|
||||
* Phil Nelson <phil@cs.wwu.edu>
|
||||
*
|
||||
@ -118,7 +118,6 @@
|
||||
#define EAP_P2_S_EB 0x00000008
|
||||
#define EAP_R1_S_MB 0x00000010
|
||||
#define EAP_R1_S_EB 0x00000020
|
||||
#define EAP_R1P2_BITS 0x0000003c
|
||||
#define EAP_P2_DAC_SEN 0x00000040
|
||||
#define EAP_P1_SCT_RLD 0x00000080
|
||||
#define EAP_P1_INTR_EN 0x00000100
|
||||
@ -240,11 +239,11 @@ int eap_intr __P((void *));
|
||||
|
||||
struct eap_dma {
|
||||
bus_dmamap_t map;
|
||||
caddr_t addr;
|
||||
bus_dma_segment_t segs[1];
|
||||
int nsegs;
|
||||
size_t size;
|
||||
struct eap_dma *next;
|
||||
caddr_t addr;
|
||||
bus_dma_segment_t segs[1];
|
||||
int nsegs;
|
||||
size_t size;
|
||||
struct eap_dma *next;
|
||||
};
|
||||
#define DMAADDR(map) ((map)->segs[0].ds_addr)
|
||||
#define KERNADDR(map) ((void *)((map)->addr))
|
||||
@ -256,17 +255,19 @@ struct eap_softc {
|
||||
bus_space_handle_t ioh;
|
||||
bus_dma_tag_t sc_dmatag; /* DMA tag */
|
||||
|
||||
struct eap_dma *sc_dmas;
|
||||
struct eap_dma *sc_dmas;
|
||||
|
||||
void (*sc_pintr)(void *); /* dma completion intr handler */
|
||||
void *sc_parg; /* arg for sc_intr() */
|
||||
#ifdef DIAGNOSTIC
|
||||
char sc_prun;
|
||||
#endif
|
||||
|
||||
void (*sc_rintr)(void *); /* dma completion intr handler */
|
||||
void *sc_rarg; /* arg for sc_intr() */
|
||||
#ifdef DIAGNOSTIC
|
||||
char sc_rrun;
|
||||
|
||||
int sc_sampsize; /* bytes / sample */
|
||||
#endif
|
||||
|
||||
u_char sc_port[AK_NPORTS]; /* mirror of the hardware setting */
|
||||
u_int sc_record_source; /* recording source mask */
|
||||
@ -290,12 +291,12 @@ void eap_close __P((void *));
|
||||
int eap_query_encoding __P((void *, struct audio_encoding *));
|
||||
int eap_set_params __P((void *, int, int, struct audio_params *, struct audio_params *));
|
||||
int eap_round_blocksize __P((void *, int));
|
||||
int eap_dma_init_output __P((void *, void *, int));
|
||||
int eap_dma_init_input __P((void *, void *, int));
|
||||
int eap_dma_output __P((void *, void *, int, void (*)(void *), void*));
|
||||
int eap_dma_input __P((void *, void *, int, void (*)(void *), void*));
|
||||
int eap_halt_in_dma __P((void *));
|
||||
int eap_halt_out_dma __P((void *));
|
||||
int eap_trigger_output __P((void *, void *, void *, int, void (*)(void *),
|
||||
void *, struct audio_params *));
|
||||
int eap_trigger_input __P((void *, void *, void *, int, void (*)(void *),
|
||||
void *, struct audio_params *));
|
||||
int eap_halt_output __P((void *));
|
||||
int eap_halt_input __P((void *));
|
||||
int eap_getdev __P((void *, struct audio_device *));
|
||||
int eap_mixer_set_port __P((void *, mixer_ctrl_t *));
|
||||
int eap_mixer_get_port __P((void *, mixer_ctrl_t *));
|
||||
@ -316,12 +317,12 @@ struct audio_hw_if eap_hw_if = {
|
||||
eap_set_params,
|
||||
eap_round_blocksize,
|
||||
NULL,
|
||||
eap_dma_init_output,
|
||||
eap_dma_init_input,
|
||||
eap_dma_output,
|
||||
eap_dma_input,
|
||||
eap_halt_out_dma,
|
||||
eap_halt_in_dma,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
eap_halt_output,
|
||||
eap_halt_input,
|
||||
NULL,
|
||||
eap_getdev,
|
||||
NULL,
|
||||
@ -333,6 +334,8 @@ struct audio_hw_if eap_hw_if = {
|
||||
eap_round,
|
||||
eap_mappage,
|
||||
eap_get_props,
|
||||
eap_trigger_output,
|
||||
eap_trigger_input,
|
||||
};
|
||||
|
||||
struct audio_device eap_device = {
|
||||
@ -365,7 +368,7 @@ eap_write_codec(sc, a, d)
|
||||
int icss;
|
||||
|
||||
do {
|
||||
icss = EREAD4(sc, EAP_ICSS);
|
||||
icss = EREAD4(sc, EAP_ICSS);
|
||||
DPRINTFN(5,("eap: codec %d prog: icss=0x%08x\n", a, icss));
|
||||
} while(icss & EAP_CWRIP);
|
||||
EWRITE4(sc, EAP_CODEC, EAP_SET_CODEC(a, d));
|
||||
@ -422,8 +425,8 @@ eap_attach(parent, self, aux)
|
||||
printf("%s: interrupting at %s\n", sc->sc_dev.dv_xname, intrstr);
|
||||
|
||||
/* Enable interrupts and looping mode. */
|
||||
EWRITE4(sc, EAP_SIC, EAP_P2_INTR_EN | EAP_R1_INTR_EN);
|
||||
EWRITE4(sc, EAP_ICSC, EAP_CDC_EN); /* enable the parts we need */
|
||||
EWRITE4(sc, EAP_SIC, EAP_P2_INTR_EN | EAP_R1_INTR_EN);
|
||||
EWRITE4(sc, EAP_ICSC, EAP_CDC_EN); /* enable the parts we need */
|
||||
|
||||
eap_write_codec(sc, AK_RESET, AK_PD); /* reset codec */
|
||||
eap_write_codec(sc, AK_RESET, AK_PD | AK_NRST); /* normal operation */
|
||||
@ -449,7 +452,7 @@ eap_attach(parent, self, aux)
|
||||
ctl.un.mask = 1 << EAP_MIC_VOL;
|
||||
eap_mixer_set_port(sc, &ctl);
|
||||
|
||||
audio_attach_mi(&eap_hw_if, 0, sc, &sc->sc_dev);
|
||||
audio_attach_mi(&eap_hw_if, 0, sc, &sc->sc_dev);
|
||||
}
|
||||
|
||||
int
|
||||
@ -459,43 +462,43 @@ eap_intr(p)
|
||||
struct eap_softc *sc = p;
|
||||
u_int32_t intr, sic;
|
||||
|
||||
intr = EREAD4(sc, EAP_ICSS);
|
||||
if (!(intr & EAP_INTR))
|
||||
return (0);
|
||||
intr = EREAD4(sc, EAP_ICSS);
|
||||
if (!(intr & EAP_INTR))
|
||||
return (0);
|
||||
sic = EREAD4(sc, EAP_SIC);
|
||||
DPRINTFN(5, ("eap_intr: ICSS=0x%08x, SIC=0x%08x\n", intr, sic));
|
||||
if (intr & EAP_I_ADC) {
|
||||
/*
|
||||
* XXX This is a hack!
|
||||
* The EAP chip sometimes generates the recording interrupt
|
||||
* while it is still transferring the data. To make sure
|
||||
* it has all arrived we busy wait until the count is right.
|
||||
* The transfer we are waiting for is 8 longwords.
|
||||
*/
|
||||
int s, nw, n;
|
||||
EWRITE4(sc, EAP_MEMPAGE, EAP_ADC_PAGE);
|
||||
s = EREAD4(sc, EAP_ADC_CSR);
|
||||
nw = ((s & 0xffff) + 1) / 4; /* # of words in DMA */
|
||||
n = 0;
|
||||
while (((EREAD4(sc, EAP_ADC_SIZE) >> 16) + 8) % nw == 0) {
|
||||
delay(10);
|
||||
if (++n > 100) {
|
||||
printf("eapintr: dma fix timeout");
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* Continue with normal interrupt handling. */
|
||||
if (intr & EAP_I_ADC) {
|
||||
/*
|
||||
* XXX This is a hack!
|
||||
* The EAP chip sometimes generates the recording interrupt
|
||||
* while it is still transferring the data. To make sure
|
||||
* it has all arrived we busy wait until the count is right.
|
||||
* The transfer we are waiting for is 8 longwords.
|
||||
*/
|
||||
int s, nw, n;
|
||||
EWRITE4(sc, EAP_MEMPAGE, EAP_ADC_PAGE);
|
||||
s = EREAD4(sc, EAP_ADC_CSR);
|
||||
nw = ((s & 0xffff) + 1) >> 2; /* # of words in DMA */
|
||||
n = 0;
|
||||
while (((EREAD4(sc, EAP_ADC_SIZE) >> 16) + 8) % nw == 0) {
|
||||
delay(10);
|
||||
if (++n > 100) {
|
||||
printf("eapintr: dma fix timeout");
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* Continue with normal interrupt handling. */
|
||||
EWRITE4(sc, EAP_SIC, sic & ~EAP_R1_INTR_EN);
|
||||
EWRITE4(sc, EAP_SIC, sic);
|
||||
if (sc->sc_rintr)
|
||||
sc->sc_rintr(sc->sc_rarg);
|
||||
}
|
||||
if (intr & EAP_I_DAC2) {
|
||||
if (sc->sc_rintr)
|
||||
sc->sc_rintr(sc->sc_rarg);
|
||||
}
|
||||
if (intr & EAP_I_DAC2) {
|
||||
EWRITE4(sc, EAP_SIC, sic & ~EAP_P2_INTR_EN);
|
||||
EWRITE4(sc, EAP_SIC, sic);
|
||||
if (sc->sc_pintr)
|
||||
sc->sc_pintr(sc->sc_parg);
|
||||
}
|
||||
if (sc->sc_pintr)
|
||||
sc->sc_pintr(sc->sc_parg);
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
|
||||
@ -504,7 +507,7 @@ eap_allocmem(sc, size, align, p)
|
||||
struct eap_softc *sc;
|
||||
size_t size;
|
||||
size_t align;
|
||||
struct eap_dma *p;
|
||||
struct eap_dma *p;
|
||||
{
|
||||
int error;
|
||||
|
||||
@ -543,7 +546,7 @@ free:
|
||||
int
|
||||
eap_freemem(sc, p)
|
||||
struct eap_softc *sc;
|
||||
struct eap_dma *p;
|
||||
struct eap_dma *p;
|
||||
{
|
||||
bus_dmamap_unload(sc->sc_dmatag, p->map);
|
||||
bus_dmamap_destroy(sc->sc_dmatag, p->map);
|
||||
@ -557,14 +560,8 @@ eap_open(addr, flags)
|
||||
void *addr;
|
||||
int flags;
|
||||
{
|
||||
struct eap_softc *sc = addr;
|
||||
|
||||
DPRINTF(("eap_open: sc=%p\n", sc));
|
||||
|
||||
sc->sc_pintr = 0;
|
||||
sc->sc_rintr = 0;
|
||||
|
||||
return (0);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -576,11 +573,11 @@ eap_close(addr)
|
||||
{
|
||||
struct eap_softc *sc = addr;
|
||||
|
||||
eap_halt_in_dma(sc);
|
||||
eap_halt_out_dma(sc);
|
||||
eap_halt_output(sc);
|
||||
eap_halt_input(sc);
|
||||
|
||||
sc->sc_pintr = 0;
|
||||
sc->sc_rintr = 0;
|
||||
sc->sc_pintr = 0;
|
||||
sc->sc_rintr = 0;
|
||||
}
|
||||
|
||||
int
|
||||
@ -613,7 +610,7 @@ eap_query_encoding(addr, fp)
|
||||
fp->precision = 8;
|
||||
fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
|
||||
return (0);
|
||||
case 4:
|
||||
case 4:
|
||||
strcpy(fp->name, AudioEslinear_le);
|
||||
fp->encoding = AUDIO_ENCODING_SLINEAR_LE;
|
||||
fp->precision = 16;
|
||||
@ -643,81 +640,97 @@ eap_query_encoding(addr, fp)
|
||||
}
|
||||
|
||||
int
|
||||
eap_set_params(addr, setmode, usemode, p, r)
|
||||
eap_set_params(addr, setmode, usemode, play, rec)
|
||||
void *addr;
|
||||
int setmode, usemode;
|
||||
struct audio_params *p, *r;
|
||||
struct audio_params *play, *rec;
|
||||
{
|
||||
struct eap_softc *sc = addr;
|
||||
void (*pswcode) __P((void *, u_char *buf, int cnt));
|
||||
void (*rswcode) __P((void *, u_char *buf, int cnt));
|
||||
u_int32_t mode, div;
|
||||
|
||||
struct audio_params *p;
|
||||
u_int32_t mode, div;
|
||||
|
||||
pswcode = rswcode = 0;
|
||||
switch (p->encoding) {
|
||||
case AUDIO_ENCODING_SLINEAR_BE:
|
||||
if (p->precision == 16)
|
||||
rswcode = pswcode = swap_bytes;
|
||||
/*
|
||||
* This device only has one clock, so make the sample rates match.
|
||||
*/
|
||||
if (play->sample_rate != rec->sample_rate) {
|
||||
if ((usemode | setmode) == AUMODE_PLAY)
|
||||
rec->sample_rate = play->sample_rate;
|
||||
else if ((usemode | setmode) == AUMODE_RECORD)
|
||||
play->sample_rate = rec->sample_rate;
|
||||
else
|
||||
pswcode = rswcode = change_sign8;
|
||||
break;
|
||||
case AUDIO_ENCODING_SLINEAR_LE:
|
||||
if (p->precision != 16)
|
||||
pswcode = rswcode = change_sign8;
|
||||
break;
|
||||
case AUDIO_ENCODING_ULINEAR_BE:
|
||||
if (p->precision == 16) {
|
||||
pswcode = swap_bytes_change_sign16;
|
||||
rswcode = change_sign16_swap_bytes;
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
for (mode = AUMODE_RECORD; mode != -1;
|
||||
mode = mode == AUMODE_RECORD ? AUMODE_PLAY : -1) {
|
||||
if ((setmode & mode) == 0)
|
||||
continue;
|
||||
|
||||
p = mode == AUMODE_PLAY ? play : rec;
|
||||
|
||||
if (p->sample_rate < 4000 || p->sample_rate > 50000 ||
|
||||
(p->precision != 8 && p->precision != 16) ||
|
||||
(p->channels != 1 && p->channels != 2))
|
||||
return (EINVAL);
|
||||
|
||||
p->factor = 1;
|
||||
p->sw_code = 0;
|
||||
switch (p->encoding) {
|
||||
case AUDIO_ENCODING_SLINEAR_BE:
|
||||
if (p->precision == 16)
|
||||
p->sw_code = swap_bytes;
|
||||
else
|
||||
p->sw_code = change_sign8;
|
||||
break;
|
||||
case AUDIO_ENCODING_SLINEAR_LE:
|
||||
if (p->precision != 16)
|
||||
p->sw_code = change_sign8;
|
||||
break;
|
||||
case AUDIO_ENCODING_ULINEAR_BE:
|
||||
if (p->precision == 16)
|
||||
if (mode == AUMODE_PLAY)
|
||||
p->sw_code = swap_bytes_change_sign16;
|
||||
else
|
||||
p->sw_code = change_sign16_swap_bytes;
|
||||
break;
|
||||
case AUDIO_ENCODING_ULINEAR_LE:
|
||||
if (p->precision == 16)
|
||||
p->sw_code = change_sign16;
|
||||
break;
|
||||
case AUDIO_ENCODING_ULAW:
|
||||
if (mode == AUMODE_PLAY) {
|
||||
p->factor = 2;
|
||||
p->sw_code = mulaw_to_slinear16;
|
||||
} else
|
||||
p->sw_code = ulinear8_to_mulaw;
|
||||
break;
|
||||
case AUDIO_ENCODING_ALAW:
|
||||
if (mode == AUMODE_PLAY) {
|
||||
p->factor = 2;
|
||||
p->sw_code = alaw_to_slinear16;
|
||||
} else
|
||||
p->sw_code = ulinear8_to_alaw;
|
||||
break;
|
||||
default:
|
||||
return (EINVAL);
|
||||
}
|
||||
break;
|
||||
case AUDIO_ENCODING_ULINEAR_LE:
|
||||
if (p->precision == 16)
|
||||
pswcode = rswcode = change_sign16;
|
||||
break;
|
||||
case AUDIO_ENCODING_ULAW:
|
||||
pswcode = mulaw_to_ulinear8;
|
||||
rswcode = ulinear8_to_mulaw;
|
||||
break;
|
||||
case AUDIO_ENCODING_ALAW:
|
||||
pswcode = alaw_to_ulinear8;
|
||||
rswcode = ulinear8_to_alaw;
|
||||
break;
|
||||
default:
|
||||
return (EINVAL);
|
||||
}
|
||||
if (p->precision == 16)
|
||||
mode = EAP_P2_S_EB | EAP_R1_S_EB;
|
||||
else
|
||||
mode = 0;
|
||||
if (p->channels == 2)
|
||||
mode |= EAP_P2_S_MB | EAP_R1_S_MB;
|
||||
else if (p->channels != 1)
|
||||
return (EINVAL);
|
||||
if (p->sample_rate < 4000 || p->sample_rate > 50000)
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
sc->sc_sampsize = p->precision / 8 * p->channels; /* bytes / sample */
|
||||
p->sw_code = pswcode;
|
||||
r->sw_code = rswcode;
|
||||
|
||||
/* Set the encoding */
|
||||
mode |= EREAD4(sc, EAP_SIC) & ~(EAP_R1P2_BITS | EAP_INC_BITS);
|
||||
mode |= EAP_SET_P2_ST_INC(0) | EAP_SET_P2_END_INC(p->precision / 8);
|
||||
EWRITE4(sc, EAP_SIC, mode);
|
||||
DPRINTFN(2, ("eap_set_params: set SIC = 0x%08x\n", mode));
|
||||
|
||||
/* Set the speed */
|
||||
/* Set the speed */
|
||||
DPRINTFN(2, ("eap_set_params: old ICSC = 0x%08x\n",
|
||||
EREAD4(sc, EAP_ICSC)));
|
||||
div = EREAD4(sc, EAP_ICSC) & ~EAP_PCLKBITS;
|
||||
div |= EAP_SET_PCLKDIV(EAP_XTAL_FREQ / p->sample_rate - 2);
|
||||
/*
|
||||
* XXX
|
||||
* The -2 isn't documented, but seemed to make the wall time match
|
||||
* what I expect. - mycroft
|
||||
*/
|
||||
div |= EAP_SET_PCLKDIV(EAP_XTAL_FREQ / play->sample_rate - 2);
|
||||
div |= EAP_CCB_INTRM;
|
||||
EWRITE4(sc, EAP_ICSC, div);
|
||||
EWRITE4(sc, EAP_ICSC, div);
|
||||
DPRINTFN(2, ("eap_set_params: set ICSC = 0x%08x\n", div));
|
||||
|
||||
return (0);
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
@ -729,169 +742,180 @@ eap_round_blocksize(addr, blk)
|
||||
}
|
||||
|
||||
int
|
||||
eap_dma_init_input(addr, buf, cc)
|
||||
eap_trigger_output(addr, start, end, blksize, intr, arg, param)
|
||||
void *addr;
|
||||
void *buf;
|
||||
int cc;
|
||||
{
|
||||
struct eap_softc *sc = addr;
|
||||
struct eap_dma *p;
|
||||
|
||||
DPRINTF(("eap_dma_init_input: dma start loop input addr=%p cc=%d\n",
|
||||
buf, cc));
|
||||
for (p = sc->sc_dmas; p && KERNADDR(p) != buf; p = p->next)
|
||||
;
|
||||
if (!p) {
|
||||
printf("eap_dma_init_input: bad addr %p\n", buf);
|
||||
return (EINVAL);
|
||||
}
|
||||
EWRITE4(sc, EAP_MEMPAGE, EAP_ADC_PAGE);
|
||||
EWRITE4(sc, EAP_ADC_ADDR, DMAADDR(p));
|
||||
EWRITE4(sc, EAP_ADC_SIZE, EAP_SET_SIZE(0, cc / 4 - 1));
|
||||
DPRINTF(("eap_dma_init_input: ADC_ADDR=0x%x, ADC_SIZE=0x%x\n",
|
||||
(int)DMAADDR(p), EAP_SET_SIZE(0, cc / 4 - 1)));
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
eap_dma_init_output(addr, buf, cc)
|
||||
void *addr;
|
||||
void *buf;
|
||||
int cc;
|
||||
{
|
||||
struct eap_softc *sc = addr;
|
||||
struct eap_dma *p;
|
||||
|
||||
DPRINTF(("eap: dma start loop output buf=%p cc=%d\n", buf, cc));
|
||||
for (p = sc->sc_dmas; p && KERNADDR(p) != buf; p = p->next)
|
||||
;
|
||||
if (!p) {
|
||||
printf("eap_dma_init_output: bad addr %p\n", buf);
|
||||
return (EINVAL);
|
||||
}
|
||||
EWRITE4(sc, EAP_MEMPAGE, EAP_DAC_PAGE);
|
||||
EWRITE4(sc, EAP_DAC2_ADDR, DMAADDR(p));
|
||||
EWRITE4(sc, EAP_DAC2_SIZE, EAP_SET_SIZE(0, cc / 4 - 1));
|
||||
DPRINTF(("eap_dma_init_output: DAC2_ADDR=0x%x, DAC2_SIZE=0x%x\n",
|
||||
(int)DMAADDR(p), EAP_SET_SIZE(0, cc / 4 - 1)));
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
eap_dma_output(addr, p, cc, intr, arg)
|
||||
void *addr;
|
||||
void *p;
|
||||
int cc;
|
||||
void *start, *end;
|
||||
int blksize;
|
||||
void (*intr) __P((void *));
|
||||
void *arg;
|
||||
struct audio_params *param;
|
||||
{
|
||||
struct eap_softc *sc = addr;
|
||||
struct eap_dma *p;
|
||||
u_int32_t mode;
|
||||
int sampshift;
|
||||
|
||||
DPRINTFN(sc->sc_prun ? 5 : 1,
|
||||
("eap_dma_output: sc=%p buf=%p cc=%d intr=%p(%p)\n",
|
||||
addr, p, cc, intr, arg));
|
||||
#ifdef DIAGNOSTIC
|
||||
if (sc->sc_prun)
|
||||
panic("eap_trigger_output: already running");
|
||||
#endif
|
||||
|
||||
DPRINTFN(1, ("eap_trigger_output: sc=%p start=%p end=%d blksize=%d intr=%p(%p)\n",
|
||||
addr, start, end, blksize, intr, arg));
|
||||
sc->sc_pintr = intr;
|
||||
sc->sc_parg = arg;
|
||||
if (!sc->sc_prun) {
|
||||
#if defined(DIAGNOSTIC) || defined(AUDIO_DEBUG)
|
||||
if (sc->sc_sampsize == 0) {
|
||||
printf("eap_dma_output: sampsize == 0\n");
|
||||
return EINVAL;
|
||||
}
|
||||
#endif
|
||||
EWRITE2(sc, EAP_DAC2_CSR, cc / sc->sc_sampsize - 1);
|
||||
DPRINTFN(1, ("eap_dma_output: set DAC2_CSR = %d\n",
|
||||
cc / sc->sc_sampsize - 1));
|
||||
DPRINTFN(1, ("eap_dma_output: old ICSC = 0x%08x\n",
|
||||
EREAD4(sc, EAP_ICSC)));
|
||||
mode = EREAD4(sc, EAP_ICSC) & ~EAP_DAC2_EN;
|
||||
EWRITE4(sc, EAP_ICSC, mode);
|
||||
mode |= EAP_DAC2_EN;
|
||||
EWRITE4(sc, EAP_ICSC, mode);
|
||||
DPRINTFN(1, ("eap_dma_output: set ICSC = 0x%08x\n", mode));
|
||||
sc->sc_prun = 1;
|
||||
|
||||
mode = EREAD4(sc, EAP_SIC) & ~(EAP_P2_S_EB | EAP_P2_S_MB | EAP_INC_BITS);
|
||||
mode |= EAP_SET_P2_ST_INC(0) | EAP_SET_P2_END_INC(param->precision * param->factor / 8);
|
||||
sampshift = 0;
|
||||
if (param->precision * param->factor == 16) {
|
||||
mode |= EAP_P2_S_EB;
|
||||
sampshift++;
|
||||
}
|
||||
return (0);
|
||||
if (param->channels == 2) {
|
||||
mode |= EAP_P2_S_MB;
|
||||
sampshift++;
|
||||
}
|
||||
EWRITE4(sc, EAP_SIC, mode);
|
||||
|
||||
for (p = sc->sc_dmas; p && KERNADDR(p) != start; p = p->next)
|
||||
;
|
||||
if (!p) {
|
||||
printf("eap_trigger_output: bad addr %p\n", start);
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
DPRINTF(("eap_trigger_output: DAC2_ADDR=0x%x, DAC2_SIZE=0x%x\n",
|
||||
(int)DMAADDR(p), EAP_SET_SIZE(0, ((end - start) >> 2) - 1)));
|
||||
EWRITE4(sc, EAP_MEMPAGE, EAP_DAC_PAGE);
|
||||
EWRITE4(sc, EAP_DAC2_ADDR, DMAADDR(p));
|
||||
EWRITE4(sc, EAP_DAC2_SIZE, EAP_SET_SIZE(0, ((end - start) >> 2) - 1));
|
||||
|
||||
EWRITE2(sc, EAP_DAC2_CSR, (blksize >> sampshift) - 1);
|
||||
mode = EREAD4(sc, EAP_ICSC) & ~EAP_DAC2_EN;
|
||||
EWRITE4(sc, EAP_ICSC, mode);
|
||||
mode |= EAP_DAC2_EN;
|
||||
EWRITE4(sc, EAP_ICSC, mode);
|
||||
DPRINTFN(1, ("eap_trigger_output: set ICSC = 0x%08x\n", mode));
|
||||
|
||||
#ifdef DIAGNOSTIC
|
||||
sc->sc_prun = 1;
|
||||
#endif
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
eap_dma_input(addr, p, cc, intr, arg)
|
||||
eap_trigger_input(addr, start, end, blksize, intr, arg, param)
|
||||
void *addr;
|
||||
void *p;
|
||||
int cc;
|
||||
void *start, *end;
|
||||
int blksize;
|
||||
void (*intr) __P((void *));
|
||||
void *arg;
|
||||
struct audio_params *param;
|
||||
{
|
||||
struct eap_softc *sc = addr;
|
||||
struct eap_dma *p;
|
||||
u_int32_t mode;
|
||||
int sampshift;
|
||||
|
||||
DPRINTFN(1, ("eap_dma_input: sc=%p buf=%p cc=%d intr=%p(%p)\n",
|
||||
addr, p, cc, intr, arg));
|
||||
#ifdef DIAGNOSTIC
|
||||
if (sc->sc_rrun)
|
||||
panic("eap_trigger_input: already running");
|
||||
#endif
|
||||
|
||||
DPRINTFN(1, ("eap_trigger_input: sc=%p start=%p end=%d blksize=%d intr=%p(%p)\n",
|
||||
addr, start, end, blksize, intr, arg));
|
||||
sc->sc_rintr = intr;
|
||||
sc->sc_rarg = arg;
|
||||
if (!sc->sc_rrun) {
|
||||
#if defined(DIAGNOSTIC) || defined(AUDIO_DEBUG)
|
||||
if (sc->sc_sampsize == 0) {
|
||||
printf("eap_dma_input: sampsize == 0\n");
|
||||
return EINVAL;
|
||||
}
|
||||
#endif
|
||||
EWRITE2(sc, EAP_ADC_CSR, cc / sc->sc_sampsize - 1);
|
||||
mode = EREAD4(sc, EAP_ICSC) & ~EAP_ADC_EN;
|
||||
EWRITE4(sc, EAP_ICSC, mode);
|
||||
mode |= EAP_ADC_EN;
|
||||
EWRITE4(sc, EAP_ICSC, mode);
|
||||
DPRINTFN(1, ("eap_dma_input: set ICSC = 0x%08x\n", mode));
|
||||
sc->sc_rrun = 1;
|
||||
|
||||
mode = EREAD4(sc, EAP_SIC) & ~(EAP_R1_S_EB | EAP_R1_S_MB);
|
||||
sampshift = 0;
|
||||
if (param->precision * param->factor == 16) {
|
||||
mode |= EAP_R1_S_EB;
|
||||
sampshift++;
|
||||
}
|
||||
return (0);
|
||||
if (param->channels == 2) {
|
||||
mode |= EAP_R1_S_MB;
|
||||
sampshift++;
|
||||
}
|
||||
EWRITE4(sc, EAP_SIC, mode);
|
||||
|
||||
for (p = sc->sc_dmas; p && KERNADDR(p) != start; p = p->next)
|
||||
;
|
||||
if (!p) {
|
||||
printf("eap_trigger_input: bad addr %p\n", start);
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
DPRINTF(("eap_trigger_input: ADC_ADDR=0x%x, ADC_SIZE=0x%x\n",
|
||||
(int)DMAADDR(p), EAP_SET_SIZE(0, ((end - start) >> 2) - 1)));
|
||||
EWRITE4(sc, EAP_MEMPAGE, EAP_ADC_PAGE);
|
||||
EWRITE4(sc, EAP_ADC_ADDR, DMAADDR(p));
|
||||
EWRITE4(sc, EAP_ADC_SIZE, EAP_SET_SIZE(0, ((end - start) >> 2) - 1));
|
||||
|
||||
EWRITE2(sc, EAP_ADC_CSR, (blksize >> sampshift) - 1);
|
||||
mode = EREAD4(sc, EAP_ICSC) & ~EAP_ADC_EN;
|
||||
EWRITE4(sc, EAP_ICSC, mode);
|
||||
mode |= EAP_ADC_EN;
|
||||
EWRITE4(sc, EAP_ICSC, mode);
|
||||
DPRINTFN(1, ("eap_trigger_input: set ICSC = 0x%08x\n", mode));
|
||||
|
||||
#ifdef DIAGNOSTIC
|
||||
sc->sc_rrun = 1;
|
||||
#endif
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
eap_halt_out_dma(addr)
|
||||
eap_halt_output(addr)
|
||||
void *addr;
|
||||
{
|
||||
struct eap_softc *sc = addr;
|
||||
u_int32_t mode;
|
||||
|
||||
DPRINTF(("eap: eap_halt_out_dma\n"));
|
||||
DPRINTF(("eap: eap_halt_output\n"));
|
||||
mode = EREAD4(sc, EAP_ICSC) & ~EAP_DAC2_EN;
|
||||
EWRITE4(sc, EAP_ICSC, mode);
|
||||
#ifdef DIAGNOSTIC
|
||||
sc->sc_prun = 0;
|
||||
return (0);
|
||||
#endif
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
eap_halt_in_dma(addr)
|
||||
eap_halt_input(addr)
|
||||
void *addr;
|
||||
{
|
||||
struct eap_softc *sc = addr;
|
||||
u_int32_t mode;
|
||||
|
||||
DPRINTF(("eap: eap_halt_in_dma\n"));
|
||||
DPRINTF(("eap: eap_halt_input\n"));
|
||||
mode = EREAD4(sc, EAP_ICSC) & ~EAP_ADC_EN;
|
||||
EWRITE4(sc, EAP_ICSC, mode);
|
||||
#ifdef DIAGNOSTIC
|
||||
sc->sc_rrun = 0;
|
||||
return (0);
|
||||
#endif
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
eap_getdev(addr, retp)
|
||||
void *addr;
|
||||
struct audio_device *retp;
|
||||
struct audio_device *retp;
|
||||
{
|
||||
*retp = eap_device;
|
||||
return (0);
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
eap_set_mixer(sc, a, d)
|
||||
struct eap_softc *sc;
|
||||
int a, d;
|
||||
int a, d;
|
||||
{
|
||||
eap_write_codec(sc, a, d);
|
||||
DPRINTFN(1, ("eap_mixer_set_port port 0x%02x = 0x%02x\n", a, d));
|
||||
DPRINTFN(1, ("eap_mixer_set_port port 0x%02x = 0x%02x\n", a, d));
|
||||
}
|
||||
|
||||
|
||||
@ -1018,8 +1042,8 @@ eap_mixer_get_port(addr, cp)
|
||||
cp->un.mask = sc->sc_record_source;
|
||||
return (0);
|
||||
case EAP_OUTPUT_SELECT:
|
||||
cp->un.mask = sc->sc_output_source;
|
||||
return (0);
|
||||
cp->un.mask = sc->sc_output_source;
|
||||
return (0);
|
||||
case EAP_MASTER_VOL:
|
||||
l = ATT5_TO_VOL(sc->sc_port[AK_MASTER_L]);
|
||||
r = ATT5_TO_VOL(sc->sc_port[AK_MASTER_R]);
|
||||
@ -1200,19 +1224,19 @@ eap_malloc(addr, size, pool, flags)
|
||||
int flags;
|
||||
{
|
||||
struct eap_softc *sc = addr;
|
||||
struct eap_dma *p;
|
||||
int error;
|
||||
struct eap_dma *p;
|
||||
int error;
|
||||
|
||||
p = malloc(sizeof(*p), pool, flags);
|
||||
if (!p)
|
||||
return (0);
|
||||
error = eap_allocmem(sc, size, 16, p);
|
||||
if (error) {
|
||||
free(p, pool);
|
||||
return (0);
|
||||
}
|
||||
p->next = sc->sc_dmas;
|
||||
sc->sc_dmas = p;
|
||||
p = malloc(sizeof(*p), pool, flags);
|
||||
if (!p)
|
||||
return (0);
|
||||
error = eap_allocmem(sc, size, 16, p);
|
||||
if (error) {
|
||||
free(p, pool);
|
||||
return (0);
|
||||
}
|
||||
p->next = sc->sc_dmas;
|
||||
sc->sc_dmas = p;
|
||||
return (KERNADDR(p));
|
||||
}
|
||||
|
||||
@ -1223,16 +1247,16 @@ eap_free(addr, ptr, pool)
|
||||
int pool;
|
||||
{
|
||||
struct eap_softc *sc = addr;
|
||||
struct eap_dma **p;
|
||||
struct eap_dma **p;
|
||||
|
||||
for (p = &sc->sc_dmas; *p; p = &(*p)->next) {
|
||||
if (KERNADDR(*p) == ptr) {
|
||||
eap_freemem(sc, *p);
|
||||
*p = (*p)->next;
|
||||
free(*p, pool);
|
||||
return;
|
||||
}
|
||||
}
|
||||
for (p = &sc->sc_dmas; *p; p = &(*p)->next) {
|
||||
if (KERNADDR(*p) == ptr) {
|
||||
eap_freemem(sc, *p);
|
||||
*p = (*p)->next;
|
||||
free(*p, pool);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
u_long
|
||||
@ -1246,14 +1270,14 @@ eap_round(addr, size)
|
||||
int
|
||||
eap_mappage(addr, mem, off, prot)
|
||||
void *addr;
|
||||
void *mem;
|
||||
int off;
|
||||
void *mem;
|
||||
int off;
|
||||
int prot;
|
||||
{
|
||||
struct eap_softc *sc = addr;
|
||||
struct eap_dma *p;
|
||||
struct eap_dma *p;
|
||||
|
||||
for (p = sc->sc_dmas; p && KERNADDR(p) != mem; p = p->next)
|
||||
for (p = sc->sc_dmas; p && KERNADDR(p) != mem; p = p->next)
|
||||
;
|
||||
if (!p)
|
||||
return (-1);
|
||||
@ -1265,5 +1289,5 @@ int
|
||||
eap_get_props(addr)
|
||||
void *addr;
|
||||
{
|
||||
return (AUDIO_PROP_MMAP | AUDIO_PROP_FULLDUPLEX);
|
||||
return (AUDIO_PROP_MMAP | AUDIO_PROP_INDEPENDENT | AUDIO_PROP_FULLDUPLEX);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user