rewrite suspend/resume routine. If you suspend while playing audio,

clcs and clct continue playing when resume.
This commit is contained in:
tacha 2001-04-18 01:35:06 +00:00
parent 8490f0b0c0
commit 109656b0a7
4 changed files with 130 additions and 47 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: cs4280.c,v 1.15 2001/02/13 04:11:11 tacha Exp $ */
/* $NetBSD: cs4280.c,v 1.16 2001/04/18 01:35:06 tacha Exp $ */
/*
* Copyright (c) 1999, 2000 Tatoku Ogaito. All rights reserved.
@ -660,9 +660,7 @@ cs4280_halt_output(addr)
mem = BA1READ4(sc, CS4280_PCTL);
BA1WRITE4(sc, CS4280_PCTL, mem & ~PCTL_MASK);
#ifdef DIAGNOSTIC
sc->sc_prun = 0;
#endif
return 0;
}
@ -675,9 +673,7 @@ cs4280_halt_input(addr)
mem = BA1READ4(sc, CS4280_CCTL);
BA1WRITE4(sc, CS4280_CCTL, mem & ~CCTL_MASK);
#ifdef DIAGNOSTIC
sc->sc_rrun = 0;
#endif
return 0;
}
@ -706,8 +702,8 @@ cs4280_trigger_output(addr, start, end, blksize, intr, arg, param)
#ifdef DIAGNOSTIC
if (sc->sc_prun)
printf("cs4280_trigger_output: already running\n");
sc->sc_prun = 1;
#endif
sc->sc_prun = 1;
DPRINTF(("cs4280_trigger_output: sc=%p start=%p end=%p "
"blksize=%d intr=%p(%p)\n", addr, start, end, blksize, intr, arg));
@ -774,6 +770,7 @@ cs4280_trigger_output(addr, start, end, blksize, intr, arg, param)
BA1WRITE4(sc, CS4280_PFIE, pfie | PFIE_PI_ENABLE);
sc->sc_prate = param->sample_rate;
cs4280_set_dac_rate(sc, param->sample_rate);
pctl = BA1READ4(sc, CS4280_PCTL) & ~PCTL_MASK;
@ -798,8 +795,9 @@ cs4280_trigger_input(addr, start, end, blksize, intr, arg, param)
#ifdef DIAGNOSTIC
if (sc->sc_rrun)
printf("cs4280_trigger_input: already running\n");
sc->sc_rrun = 1;
#endif
sc->sc_rrun = 1;
DPRINTF(("cs4280_trigger_input: sc=%p start=%p end=%p "
"blksize=%d intr=%p(%p)\n", addr, start, end, blksize, intr, arg));
sc->sc_rintr = intr;
@ -846,6 +844,7 @@ cs4280_trigger_input(addr, start, end, blksize, intr, arg, param)
cie = BA1READ4(sc, CS4280_CIE) & ~CIE_CI_MASK;
BA1WRITE4(sc, CS4280_CIE, cie | CIE_CI_ENABLE);
sc->sc_rrate = param->sample_rate;
cs4280_set_adc_rate(sc, param->sample_rate);
cctl = BA1READ4(sc, CS4280_CCTL) & ~CCTL_MASK;
@ -861,6 +860,8 @@ cs4280_power(why, v)
void *v;
{
struct cs428x_softc *sc = (struct cs428x_softc *)v;
static u_int32_t pctl = 0, pba = 0, pfie = 0, pdtc = 0;
static u_int32_t cctl = 0, cba = 0, cie = 0;
DPRINTF(("%s: cs4280_power why=%d\n",
sc->sc_dev.dv_xname, why));
@ -869,10 +870,28 @@ cs4280_power(why, v)
case PWR_STANDBY:
sc->sc_suspend = why;
cs4280_halt_output(sc);
cs4280_halt_input(sc);
/* should I powerdown here ? */
cs428x_write_codec(sc, AC97_REG_POWER, CS4280_POWER_DOWN_ALL);
/* save current playback status */
if ( sc->sc_prun ) {
pctl = BA1READ4(sc, CS4280_PCTL);
pfie = BA1READ4(sc, CS4280_PFIE);
pba = BA1READ4(sc, CS4280_PBA);
pdtc = BA1READ4(sc, CS4280_PDTC);
DPRINTF(("pctl=0x%08x pfie=0x%08x pba=0x%08x pdtc=0x%08x\n",
pctl, pfie, pba, pdtc));
}
/* save current capture status */
if ( sc->sc_rrun ) {
cctl = BA1READ4(sc, CS4280_CCTL);
cie = BA1READ4(sc, CS4280_CIE);
cba = BA1READ4(sc, CS4280_CBA);
DPRINTF(("cctl=0x%08x cie=0x%08x cba=0x%08x\n",
cctl, cie, cba));
}
/* Stop DMA */
BA1WRITE4(sc, CS4280_PCTL, pctl & ~PCTL_MASK);
BA1WRITE4(sc, CS4280_CCTL, BA1READ4(sc, CS4280_CCTL) & ~CCTL_MASK);
break;
case PWR_RESUME:
if (sc->sc_suspend == PWR_RESUME) {
@ -884,7 +903,28 @@ cs4280_power(why, v)
cs4280_init(sc, 0);
cs4280_reset_codec(sc);
/* restore ac97 registers */
(*sc->codec_if->vtbl->restore_ports)(sc->codec_if);
/* restore DMA related status */
if(sc->sc_prun) {
DPRINTF(("pctl=0x%08x pfie=0x%08x pba=0x%08x pdtc=0x%08x\n",
pctl, pfie, pba, pdtc));
cs4280_set_dac_rate(sc, sc->sc_prate);
BA1WRITE4(sc, CS4280_PDTC, pdtc);
BA1WRITE4(sc, CS4280_PBA, pba);
BA1WRITE4(sc, CS4280_PFIE, pfie);
BA1WRITE4(sc, CS4280_PCTL, pctl);
}
if (sc->sc_rrun) {
DPRINTF(("cctl=0x%08x cie=0x%08x cba=0x%08x\n",
cctl, cie, cba));
cs4280_set_adc_rate(sc, sc->sc_rrate);
BA1WRITE4(sc, CS4280_CBA, cba);
BA1WRITE4(sc, CS4280_CIE, cie);
BA1WRITE4(sc, CS4280_CCTL, cctl);
}
break;
case PWR_SOFTSUSPEND:
case PWR_SOFTSTANDBY:
@ -1291,7 +1331,9 @@ cs4280_init(sc, init)
*/
mem = BA1READ4(sc, CS4280_PCTL);
sc->pctl = mem & PCTL_MASK; /* save startup value */
cs4280_halt_output(sc);
BA1WRITE4(sc, CS4280_PCTL, mem & ~PCTL_MASK);
if (init != 0)
sc->sc_prun = 0;
/* Save capture parameter and then write zero.
* this ensures that DMA doesn't immediately occur upon
@ -1299,7 +1341,9 @@ cs4280_init(sc, init)
*/
mem = BA1READ4(sc, CS4280_CCTL);
sc->cctl = mem & CCTL_MASK; /* save startup value */
cs4280_halt_input(sc);
BA1WRITE4(sc, CS4280_CCTL, mem & ~CCTL_MASK);
if (init != 0)
sc->sc_rrun = 0;
/* Processor Startup Procedure */
BA1WRITE4(sc, CS4280_FRMT, FRMT_FTV);

View File

@ -1,4 +1,4 @@
/* $NetBSD: cs4281.c,v 1.3 2001/02/07 14:41:11 tacha Exp $ */
/* $NetBSD: cs4281.c,v 1.4 2001/04/18 01:35:07 tacha Exp $ */
/*
* Copyright (c) 2000 Tatoku Ogaito. All rights reserved.
@ -95,9 +95,9 @@ void cs4281_reset_codec(void *);
/* Internal functions */
u_int8_t cs4281_sr2regval(int);
void cs4281_set_dac_rate(struct cs428x_softc *, int );
void cs4281_set_adc_rate(struct cs428x_softc *, int );
int cs4281_init(struct cs428x_softc *);
void cs4281_set_dac_rate(struct cs428x_softc *, int);
void cs4281_set_adc_rate(struct cs428x_softc *, int);
int cs4281_init(struct cs428x_softc *, int);
/* Power Management */
void cs4281_power(int, void *);
@ -262,7 +262,7 @@ cs4281_attach(parent, self, aux)
/*
* Sound System start-up
*/
if (cs4281_init(sc) != 0)
if (cs4281_init(sc,1) != 0)
return;
sc->type = TYPE_CS4281;
@ -509,9 +509,7 @@ cs4281_halt_output(addr)
struct cs428x_softc *sc = addr;
BA0WRITE4(sc, CS4281_DCR0, BA0READ4(sc, CS4281_DCR0) | DCRn_MSK);
#ifdef DIAGNOSTIC
sc->sc_prun = 0;
#endif
return 0;
}
@ -522,9 +520,7 @@ cs4281_halt_input(addr)
struct cs428x_softc *sc = addr;
BA0WRITE4(sc, CS4281_DCR1, BA0READ4(sc, CS4281_DCR1) | DCRn_MSK);
#ifdef DIAGNOSTIC
sc->sc_rrun = 0;
#endif
return 0;
}
@ -554,8 +550,8 @@ cs4281_trigger_output(addr, start, end, blksize, intr, arg, param)
#ifdef DIAGNOSTIC
if (sc->sc_prun)
printf("cs4281_trigger_output: already running\n");
sc->sc_prun = 1;
#endif
sc->sc_prun = 1;
DPRINTF(("cs4281_trigger_output: sc=%p start=%p end=%p "
"blksize=%d intr=%p(%p)\n", addr, start, end, blksize, intr, arg));
@ -617,6 +613,7 @@ cs4281_trigger_output(addr, start, end, blksize, intr, arg, param)
BA0WRITE4(sc, CS4281_DMR0, fmt);
/* set sample rate */
sc->sc_prate = param->sample_rate;
cs4281_set_dac_rate(sc, param->sample_rate);
/* start DMA */
@ -624,14 +621,6 @@ cs4281_trigger_output(addr, start, end, blksize, intr, arg, param)
/* Enable interrupts */
BA0WRITE4(sc, CS4281_HICR, HICR_IEV | HICR_CHGM);
#if 1
/* XXX
* I think these BA0WRITE4 should not be here
*/
BA0WRITE4(sc, CS4281_PPRVC, 7);
BA0WRITE4(sc, CS4281_PPLVC, 7);
#endif
DPRINTF(("HICR =0x%08x(expected 0x00000001)\n", BA0READ4(sc, CS4281_HICR)));
DPRINTF(("HIMR =0x%08x(expected 0x00f0fc3f)\n", BA0READ4(sc, CS4281_HIMR)));
DPRINTF(("DMR0 =0x%08x(expected 0x2???0018)\n", BA0READ4(sc, CS4281_DMR0)));
@ -664,8 +653,8 @@ cs4281_trigger_input(addr, start, end, blksize, intr, arg, param)
#ifdef DIAGNOSTIC
if (sc->sc_rrun)
printf("cs4281_trigger_input: already running\n");
sc->sc_rrun = 1;
#endif
sc->sc_rrun = 1;
DPRINTF(("cs4281_trigger_input: sc=%p start=%p end=%p "
"blksize=%d intr=%p(%p)\n", addr, start, end, blksize, intr, arg));
sc->sc_rintr = intr;
@ -715,6 +704,7 @@ cs4281_trigger_input(addr, start, end, blksize, intr, arg, param)
BA0WRITE4(sc, CS4281_DMR1, fmt);
/* set sample rate */
sc->sc_rrate = param->sample_rate;
cs4281_set_adc_rate(sc, param->sample_rate);
/* Start DMA */
@ -737,6 +727,8 @@ cs4281_power(why, v)
void *v;
{
struct cs428x_softc *sc = (struct cs428x_softc *)v;
static u_int32_t dba0 = 0, dbc0 = 0, dmr0 = 0, dcr0 = 0;
static u_int32_t dba1 = 0, dbc1 = 0, dmr1 = 0, dcr1 = 0;
DPRINTF(("%s: cs4281_power why=%d\n", sc->sc_dev.dv_xname, why));
switch (why) {
@ -744,10 +736,24 @@ cs4281_power(why, v)
case PWR_STANDBY:
sc->sc_suspend = why;
cs4281_halt_output(sc);
cs4281_halt_input(sc);
/* should I powerdown here ? */
cs428x_write_codec(sc, AC97_REG_POWER, CS4281_POWER_DOWN_ALL);
/* save current playback status */
if (sc->sc_prun) {
dcr0 = BA0READ4(sc, CS4281_DCR0);
dmr0 = BA0READ4(sc, CS4281_DMR0);
dbc0 = BA0READ4(sc, CS4281_DBC0);
dba0 = BA0READ4(sc, CS4281_DBA0);
}
/* save current capture status */
if (sc->sc_rrun) {
dcr1 = BA0READ4(sc, CS4281_DCR1);
dmr1 = BA0READ4(sc, CS4281_DMR1);
dbc1 = BA0READ4(sc, CS4281_DBC1);
dba1 = BA0READ4(sc, CS4281_DBA1);
}
/* Stop DMA */
BA0WRITE4(sc, CS4281_DCR0, BA0READ4(sc, CS4281_DCR0) | DCRn_MSK);
BA0WRITE4(sc, CS4281_DCR1, BA0READ4(sc, CS4281_DCR1) | DCRn_MSK);
break;
case PWR_RESUME:
if (sc->sc_suspend == PWR_RESUME) {
@ -756,10 +762,30 @@ cs4281_power(why, v)
return;
}
sc->sc_suspend = why;
cs4281_init(sc);
cs4281_init(sc,0);
cs4281_reset_codec(sc);
/* restore ac97 registers */
(*sc->codec_if->vtbl->restore_ports)(sc->codec_if);
/* restore DMA related status */
if (sc->sc_prun) {
cs4281_set_dac_rate(sc, sc->sc_prate);
BA0WRITE4(sc, CS4281_DBA0, dba0);
BA0WRITE4(sc, CS4281_DBC0, dbc0);
BA0WRITE4(sc, CS4281_DMR0, dmr0);
BA0WRITE4(sc, CS4281_DCR0, dcr0);
}
if (sc->sc_rrun) {
cs4281_set_adc_rate(sc, sc->sc_rrate);
BA0WRITE4(sc, CS4281_DBA1, dba1);
BA0WRITE4(sc, CS4281_DBC1, dbc1);
BA0WRITE4(sc, CS4281_DMR1, dmr1);
BA0WRITE4(sc, CS4281_DCR1, dcr1);
}
/* enable intterupts */
if (sc->sc_prun || sc->sc_rrun)
BA0WRITE4(sc, CS4281_HICR, HICR_IEV | HICR_CHGM);
break;
case PWR_SOFTSUSPEND:
case PWR_SOFTSTANDBY:
@ -924,8 +950,9 @@ cs4281_set_dac_rate(sc, rate)
}
int
cs4281_init(sc)
cs4281_init(sc, init)
struct cs428x_softc *sc;
int init;
{
int n;
u_int16_t data;
@ -1219,5 +1246,16 @@ cs4281_init(sc)
dat32 = ~HIMR_DMAIM & ~HIMR_D1IM & ~HIMR_D0IM;
BA0WRITE4(sc, CS4281_HIMR,
BA0READ4(sc, CS4281_HIMR) & dat32);
/* set current status */
if (init != 0) {
sc->sc_prun = 0;
sc->sc_rrun = 0;
}
/* setup playback volume */
BA0WRITE4(sc, CS4281_PPRVC, 7);
BA0WRITE4(sc, CS4281_PPLVC, 7);
return 0;
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: cs428x.c,v 1.1 2001/02/07 14:41:12 tacha Exp $ */
/* $NetBSD: cs428x.c,v 1.2 2001/04/18 01:35:07 tacha Exp $ */
/*
* Copyright (c) 2000 Tatoku Ogaito. All rights reserved.
@ -377,8 +377,11 @@ cs428x_src_wait(sc)
n = 0;
while ((BA0READ4(sc, CS428X_ACCTL) & ACCTL_DCV)) {
delay(1000);
while (++n > 1000)
while (++n > 1000) {
printf("cs428x_src_wait: 0x%08x\n",
BA0READ4(sc, CS428X_ACCTL));
return -1;
}
}
return 0;
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: cs428x.h,v 1.3 2001/02/07 14:41:12 tacha Exp $ */
/* $NetBSD: cs428x.h,v 1.4 2001/04/18 01:35:08 tacha Exp $ */
/*
* Copyright (c) 2000 Tatoku Ogaito. All rights reserved.
@ -93,9 +93,8 @@ struct cs428x_softc {
struct cs428x_dma *sc_pdma;
char *sc_pbuf;
int (*halt_output)__P((void *));
#ifdef DIAGNOSTIC
char sc_prun;
#endif
char sc_prun; /* playback status */
int sc_prate; /* playback sample rate */
/* capturing */
void (*sc_rintr)(void *); /* dma completion intr handler */
@ -107,9 +106,8 @@ struct cs428x_softc {
char *sc_rbuf;
int sc_rparam; /* record format */
int (*halt_input)__P((void *));
#ifdef DIAGNOSTIC
char sc_rrun;
#endif
char sc_rrun; /* recording status */
int sc_rrate; /* recording sample rate */
/* Although cs4281 does not support midi (yet),
* don't remove these definition.