1
0
mirror of https://git.FreeBSD.org/src.git synced 2024-12-18 10:35:55 +00:00

Rename es1370.c to es137x.c and merge in the patches to support

ES1371 and ES1373 PCI Audio Sound Chips.
The 1371 and 1373 can be found on newer CreativeLabs/Ensoniq
sound cards such as the SoundBlaster PCI 16,64 and 128.

Submitted by:	Russell Cattelan <cattelan@thebarn.com>
Obtained from:	Parts obtained from linux, but rewritten by Russell
This commit is contained in:
Roger Hardiman 1999-11-19 07:29:10 +00:00
parent a5fad8dbcb
commit 39d409c9e1
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=53413
2 changed files with 780 additions and 34 deletions

View File

@ -1,7 +1,8 @@
/*
* Support the ENSONIQ AudioPCI board based on the ES1370 and Codec
* AK4531.
* Support the ENSONIQ AudioPCI board and Creative Labs SoundBlaster PCI
* boards based on the ES1370, ES1371 and ES1373 chips.
*
* Copyright (c) 1999 Russell Cattelan <cattelan@thebarn.com>
* Copyright (c) 1999 Cameron Grant <gandalf@vilnya.demon.co.uk>
* Copyright (c) 1998 by Joachim Kuebart. All rights reserved.
*
@ -40,34 +41,50 @@
* $FreeBSD$
*/
/*
* Part of this code was heavily inspired by the linux driver from
* Thomas Sailer (sailer@ife.ee.ethz.ch)
* Just about everything has been touched and reworked in some way but
* the all the underlying sequences/timing/register values are from
* Thomas' code.
*
*/
#include "pci.h"
#include "pcm.h"
#include <dev/pcm/sound.h>
#include <dev/pcm/pci/es1370.h>
#include <dev/pcm/ac97.h>
#include <dev/pcm/pci/es137x.h>
#include <pci/pcireg.h>
#include <pci/pcivar.h>
#include <sys/sysctl.h>
#if NPCI != 0
static int debug = 0;
SYSCTL_INT(_debug, OID_AUTO, es_debug, CTLFLAG_RW, &debug, 0, "");
#define MEM_MAP_REG 0x14
/* PCI IDs of supported chips */
#define ES1370_PCI_ID 0x50001274
#define ES1371_PCI_ID 0x13711274
/* device private data */
struct es_info;
struct es_chinfo {
typedef struct es_chinfo {
struct es_info *parent;
pcm_channel *channel;
snd_dbuf *buffer;
int dir;
u_int32_t fmt;
};
} es_chinfo_t;
struct es_info {
typedef struct es_info {
bus_space_tag_t st;
bus_space_handle_t sh;
bus_dma_tag_t parent_dmat;
@ -76,23 +93,33 @@ struct es_info {
u_long ctrl;
u_long sctrl;
struct es_chinfo pch, rch;
};
} es_info_t;
/* -------------------------------------------------------------------- */
/* prototypes */
static u_int es1371_wait_src_ready(es_info_t *);
static void es1371_src_write(es_info_t *, u_short, unsigned short);
static u_int es1371_adc_rate (es_info_t *, u_int, int);
static u_int es1371_dac1_rate(es_info_t *, u_int, int);
static u_int es1371_dac2_rate(es_info_t *, u_int, int);
static void es1371_wrcodec(void *, int, u_int32_t);
static u_int32_t es1371_rdcodec(void *, u_int32_t);
static int es1371_init(es_info_t *es);
static int eschan1371_setspeed(void *data, u_int32_t speed);
static int es_init(struct es_info *);
static void es_intr(void *);
static int write_codec(struct es_info *, u_char, u_char);
/* channel interface */
static void *eschan_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir);
static int eschan_setdir(void *data, int dir);
static int eschan_setformat(void *data, u_int32_t format);
static int eschan_setspeed(void *data, u_int32_t speed);
static int eschan_setblocksize(void *data, u_int32_t blocksize);
static int eschan_trigger(void *data, int go);
static int eschan_getptr(void *data);
static int eschan_setdir(void *data, int dir);
static int eschan_setformat(void *data, u_int32_t format);
static int eschan_setspeed(void *data, u_int32_t speed);
static int eschan_setblocksize(void *data, u_int32_t blocksize);
static int eschan_trigger(void *data, int go);
static int eschan_getptr(void *data);
static pcmchan_caps *eschan_getcaps(void *data);
static pcmchan_caps es_playcaps = {
@ -391,6 +418,331 @@ es_intr (void *p)
if (intsrc & STAT_ADC) chn_intr(es->rch.channel);
}
/* ES1371 specific code */
#define CODEC_ID_SESHIFT 10
#define CODEC_ID_SEMASK 0x1f
#define CODEC_PIRD 0x00800000 /* 0 = write AC97 register */
#define CODEC_PIADD_MASK 0x007f0000
#define CODEC_PIADD_SHIFT 16
#define CODEC_PIDAT_MASK 0x0000ffff
#define CODEC_PIDAT_SHIFT 0
#define CODEC_PORD 0x00800000 /* 0 = write AC97 register */
#define CODEC_POADD_MASK 0x007f0000
#define CODEC_POADD_SHIFT 16
#define CODEC_PODAT_MASK 0x0000ffff
#define CODEC_PODAT_SHIFT 0
#define CODEC_RDY 0x80000000 /* AC97 read data valid */
#define CODEC_WIP 0x40000000 /* AC97 write in progress */
#define ES1370_REG_CONTROL 0x00
#define ES1370_REG_SERIAL_CONTROL 0x20
#define ES1371_REG_CODEC 0x14
#define ES1371_REG_LEGACY 0x18 /* W/R: Legacy control/status register */
#define ES1371_REG_SMPRATE 0x10 /* W/R: Codec rate converter interface register */
#define ES1371_SYNC_RES (1<<14) /* Warm AC97 reset */
#define ES1371_DIS_R1 (1<<19) /* record channel accumulator update disable */
#define ES1371_DIS_P2 (1<<20) /* playback channel 2 accumulator update disable */
#define ES1371_DIS_P1 (1<<21) /* playback channel 1 accumulator update disable */
#define ES1371_DIS_SRC (1<<22) /* sample rate converter disable */
#define ES1371_SRC_RAM_BUSY (1<<23) /* R/O: sample rate memory is busy */
#define ES1371_SRC_RAM_WE (1<<24) /* R/W: read/write control for sample rate converter */
#define ES1371_SRC_RAM_ADDRO(o) (((o)&0x7f)<<25) /* address of the sample rate converter */
#define ES1371_SRC_RAM_DATAO(o) (((o)&0xffff)<<0) /* current value of the sample rate converter */
#define ES1371_SRC_RAM_DATAI(i) (((i)>>0)&0xffff) /* current value of the sample rate converter */
/*
* Sample rate converter addresses
*/
#define ES_SMPREG_DAC1 0x70
#define ES_SMPREG_DAC2 0x74
#define ES_SMPREG_ADC 0x78
#define ES_SMPREG_TRUNC_N 0x00
#define ES_SMPREG_INT_REGS 0x01
#define ES_SMPREG_VFREQ_FRAC 0x03
#define ES_SMPREG_VOL_ADC 0x6c
#define ES_SMPREG_VOL_DAC1 0x7c
#define ES_SMPREG_VOL_DAC2 0x7e
int
es1371_init(struct es_info *es)
{
int idx;
if(debug > 0) printf("es_init\n");
es->ctrl = 0;
es->sctrl = 0;
/* initialize the chips */
bus_space_write_4(es->st, es->sh, ES1370_REG_CONTROL, es->ctrl);
bus_space_write_4(es->st, es->sh, ES1370_REG_SERIAL_CONTROL, es->sctrl);
bus_space_write_4(es->st, es->sh, ES1371_REG_LEGACY, 0);
/* AC'97 warm reset to start the bitclk */
bus_space_write_4(es->st, es->sh, ES1371_REG_LEGACY, es->ctrl | ES1371_SYNC_RES);
DELAY(2000);
bus_space_write_4(es->st, es->sh, ES1370_REG_SERIAL_CONTROL,es->ctrl);
/* Init the sample rate converter */
bus_space_write_4(es->st, es->sh, ES1371_REG_SMPRATE, ES1371_DIS_SRC);
for (idx = 0; idx < 0x80; idx++)
es1371_src_write(es, idx, 0);
es1371_src_write(es, ES_SMPREG_DAC1 + ES_SMPREG_TRUNC_N, 16 << 4);
es1371_src_write(es, ES_SMPREG_DAC1 + ES_SMPREG_INT_REGS, 16 << 10);
es1371_src_write(es, ES_SMPREG_DAC2 + ES_SMPREG_TRUNC_N, 16 << 4);
es1371_src_write(es, ES_SMPREG_DAC2 + ES_SMPREG_INT_REGS, 16 << 10);
es1371_src_write(es, ES_SMPREG_VOL_ADC, 1 << 12);
es1371_src_write(es, ES_SMPREG_VOL_ADC + 1, 1 << 12);
es1371_src_write(es, ES_SMPREG_VOL_DAC1, 1 << 12);
es1371_src_write(es, ES_SMPREG_VOL_DAC1 + 1, 1 << 12);
es1371_src_write(es, ES_SMPREG_VOL_DAC2, 1 << 12);
es1371_src_write(es, ES_SMPREG_VOL_DAC2 + 1, 1 << 12);
es1371_adc_rate (es, 22050, 1);
es1371_dac1_rate(es, 22050, 1);
es1371_dac2_rate(es, 22050, 1);
/* WARNING:
* enabling the sample rate converter without properly programming
* its parameters causes the chip to lock up (the SRC busy bit will
* be stuck high, and I've found no way to rectify this other than
* power cycle)
*/
bus_space_write_4(es->st, es->sh, ES1371_REG_SMPRATE, 0);
return (0);
}
void
es1371_wrcodec(void *s, int addr, u_int32_t data)
{
/* unsigned long flags; */
int sl;
unsigned t, x;
struct es_info *es = (struct es_info*)s;
if(debug > 0) printf("wrcodec addr 0x%x data 0x%x\n",addr,data);
for (t = 0; t < 0x1000; t++)
if(!(bus_space_read_4(es->st, es->sh,(ES1371_REG_CODEC & CODEC_WIP))))
break;
sl = spltty();
/* save the current state for later */
x = bus_space_read_4(es->st, es->sh, ES1371_REG_SMPRATE);
/* enable SRC state data in SRC mux */
bus_space_write_4(es->st, es->sh, ES1371_REG_SMPRATE,
(es1371_wait_src_ready(s) &
(ES1371_DIS_SRC | ES1371_DIS_P1 | ES1371_DIS_P2 | ES1371_DIS_R1)));
/* wait for a SAFE time to write addr/data and then do it, dammit */
for (t = 0; t < 0x1000; t++)
if (( bus_space_read_4(es->st, es->sh, ES1371_REG_SMPRATE) & 0x00070000) == 0x00010000)
break;
if(debug > 2) printf("one b_s_w: 0x%x 0x%x 0x%x\n",es->sh,ES1371_REG_CODEC,
((addr << CODEC_POADD_SHIFT) & CODEC_POADD_MASK) |
((data << CODEC_PODAT_SHIFT) & CODEC_PODAT_MASK));
bus_space_write_4(es->st, es->sh,ES1371_REG_CODEC,
((addr << CODEC_POADD_SHIFT) & CODEC_POADD_MASK) |
((data << CODEC_PODAT_SHIFT) & CODEC_PODAT_MASK));
/* restore SRC reg */
es1371_wait_src_ready(s);
if(debug > 2) printf("two b_s_w: 0x%x 0x%x 0x%x\n",es->sh,ES1371_REG_SMPRATE,x);
bus_space_write_4(es->st, es->sh,ES1371_REG_SMPRATE,x);
splx(sl);
}
u_int32_t
es1371_rdcodec(void *s, u_int32_t addr)
{
/* unsigned long flags; */
int sl;
unsigned t, x;
struct es_info *es = (struct es_info *)s;
if(debug > 0) printf("rdcodec addr 0x%x ... ",addr);
for (t = 0; t < 0x1000; t++)
if (!(x = bus_space_read_4(es->st,es->sh,ES1371_REG_CODEC) & CODEC_WIP))
break;
if(debug >0) printf("loop 1 t 0x%x x 0x%x ",t,x);
sl = spltty();
/* save the current state for later */
x = bus_space_read_4(es->st, es->sh, ES1371_REG_SMPRATE);
/* enable SRC state data in SRC mux */
bus_space_write_4(es->st, es->sh, ES1371_REG_SMPRATE,
(es1371_wait_src_ready(s) &
(ES1371_DIS_SRC | ES1371_DIS_P1 | ES1371_DIS_P2 | ES1371_DIS_R1)));
/* wait for a SAFE time to write addr/data and then do it, dammit */
for (t = 0; t < 0x5000; t++)
if (( x = bus_space_read_4(es->st, es->sh, ES1371_REG_SMPRATE) & 0x00070000) == 0x00010000)
break;
if(debug >0) printf("loop 2 t 0x%x x 0x%x ",t,x);
bus_space_write_4(es->st, es->sh,ES1371_REG_CODEC,
((addr << CODEC_POADD_SHIFT) & CODEC_POADD_MASK) | CODEC_PORD);
/* restore SRC reg */
es1371_wait_src_ready(s);
bus_space_write_4(es->st,es->sh,ES1371_REG_SMPRATE,x);
splx(sl);
/* now wait for the stinkin' data (RDY) */
for (t = 0; t < 0x1000; t++)
if ((x = bus_space_read_4(es->st,es->sh,ES1371_REG_CODEC)) & CODEC_RDY)
break;
if(debug > 0) printf("loop 3 t 0x%x 0x%x ret 0x%x\n",t,x,((x & CODEC_PIDAT_MASK) >> CODEC_PIDAT_SHIFT));
return ((x & CODEC_PIDAT_MASK) >> CODEC_PIDAT_SHIFT);
}
static u_int
es1371_src_read(es_info_t *es, u_short reg){
unsigned int r;
r = es1371_wait_src_ready(es) &
(ES1371_DIS_SRC | ES1371_DIS_P1 | ES1371_DIS_P2 | ES1371_DIS_R1);
r |= ES1371_SRC_RAM_ADDRO(reg);
bus_space_write_4(es->st, es->sh,ES1371_REG_SMPRATE,r);
return ES1371_SRC_RAM_DATAI(es1371_wait_src_ready(es));
}
static void
es1371_src_write(es_info_t *es, u_short reg, u_short data){
u_int r;
r = es1371_wait_src_ready(es) &
(ES1371_DIS_SRC | ES1371_DIS_P1 | ES1371_DIS_P2 | ES1371_DIS_R1);
r |= ES1371_SRC_RAM_ADDRO(reg) | ES1371_SRC_RAM_DATAO(data);
/* printf("es1371_src_write 0x%x 0x%x\n",ES1371_REG_SMPRATE,r | ES1371_SRC_RAM_WE); */
bus_space_write_4(es->st, es->sh,ES1371_REG_SMPRATE,r | ES1371_SRC_RAM_WE);
}
static u_int
es1371_adc_rate(es_info_t *es, u_int rate, int set){
u_int n, truncm, freq, result;
if (rate > 48000)
rate = 48000;
if (rate < 4000)
rate = 4000;
n = rate / 3000;
if ((1 << n) & ((1 << 15) | (1 << 13) | (1 << 11) | (1 << 9)))
n--;
truncm = (21 * n - 1) | 1;
freq = ((48000UL << 15) / rate) * n;
result = (48000UL << 15) / (freq / n);
if (set) {
if (rate >= 24000) {
if (truncm > 239)
truncm = 239;
es1371_src_write(es, ES_SMPREG_ADC + ES_SMPREG_TRUNC_N,
(((239 - truncm) >> 1) << 9) | (n << 4));
} else {
if (truncm > 119)
truncm = 119;
es1371_src_write(es, ES_SMPREG_ADC + ES_SMPREG_TRUNC_N,
0x8000 | (((119 - truncm) >> 1) << 9) | (n << 4));
}
es1371_src_write(es, ES_SMPREG_ADC + ES_SMPREG_INT_REGS,
(es1371_src_read(es, ES_SMPREG_ADC + ES_SMPREG_INT_REGS) &
0x00ff) | ((freq >> 5) & 0xfc00));
es1371_src_write(es, ES_SMPREG_ADC + ES_SMPREG_VFREQ_FRAC, freq & 0x7fff);
es1371_src_write(es, ES_SMPREG_VOL_ADC, n << 8);
es1371_src_write(es, ES_SMPREG_VOL_ADC + 1, n << 8);
}
return result;
}
static u_int
es1371_dac1_rate(es_info_t *es, u_int rate, int set){
u_int freq, r, result;
if (rate > 48000)
rate = 48000;
if (rate < 4000)
rate = 4000;
freq = (rate << 15) / 3000;
result = (freq * 3000) >> 15;
if (set) {
r = (es1371_wait_src_ready(es) & (ES1371_DIS_SRC | ES1371_DIS_P1 | ES1371_DIS_P2 | ES1371_DIS_R1));
bus_space_write_4(es->st, es->sh,ES1371_REG_SMPRATE,r);
es1371_src_write(es, ES_SMPREG_DAC1 +
ES_SMPREG_INT_REGS,
(es1371_src_read(es,
ES_SMPREG_DAC1 + ES_SMPREG_INT_REGS) & 0x00ff) | ((freq >> 5) & 0xfc00));
es1371_src_write(es, ES_SMPREG_DAC1 + ES_SMPREG_VFREQ_FRAC, freq & 0x7fff);
r = (es1371_wait_src_ready(es) & (ES1371_DIS_SRC | ES1371_DIS_P2 | ES1371_DIS_R1));
bus_space_write_4(es->st, es->sh,ES1371_REG_SMPRATE,r);
}
return result;
}
static u_int
es1371_dac2_rate(es_info_t *es, u_int rate, int set){
u_int freq, r, result;
if (rate > 48000)
rate = 48000;
if (rate < 4000)
rate = 4000;
freq = (rate << 15) / 3000;
result = (freq * 3000) >> 15;
if (set) {
r = (es1371_wait_src_ready(es) & (ES1371_DIS_SRC | ES1371_DIS_P1 | ES1371_DIS_P2 | ES1371_DIS_R1));
bus_space_write_4(es->st, es->sh,ES1371_REG_SMPRATE,r);
/* if(debug > 0) printf("dac2_rate 0x%x\n",bus_space_read_4(es->st, es->sh,ES1371_REG_SMPRATE)); */
es1371_src_write(es, ES_SMPREG_DAC2 + ES_SMPREG_INT_REGS,
(es1371_src_read(es, ES_SMPREG_DAC2 + ES_SMPREG_INT_REGS) &
0x00ff) | ((freq >> 5) & 0xfc00));
es1371_src_write(es, ES_SMPREG_DAC2 + ES_SMPREG_VFREQ_FRAC, freq & 0x7fff);
r = (es1371_wait_src_ready(es) & (ES1371_DIS_SRC | ES1371_DIS_P1 | ES1371_DIS_R1));
bus_space_write_4(es->st, es->sh,ES1371_REG_SMPRATE,r);
/* if(debug > 0) printf("dac2_rate 0x%x\n",bus_space_read_4(es->st, es->sh,ES1371_REG_SMPRATE)); */
}
return result;
}
static u_int
es1371_wait_src_ready(es_info_t *es){
u_int t, r;
for (t = 0; t < 500; t++) {
if (!((r = bus_space_read_4(es->st, es->sh,ES1371_REG_SMPRATE)) & ES1371_SRC_RAM_BUSY)){
return r;
}
DELAY(1000);
}
printf("es1371: wait source ready timeout 0x%x [0x%x]\n", ES1371_REG_SMPRATE, r);
return 0;
}
int
eschan1371_setspeed(void *data, u_int32_t speed)
{
struct es_chinfo *ch = data;
struct es_info *es = ch->parent;
/* rec/play speeds locked together - should indicate in flags */
es1371_dac2_rate(es, speed, 1); /* play */
es1371_adc_rate (es, speed, 1); /* record */
return speed; /* XXX calc real speed */
}
/* -------------------------------------------------------------------- */
/*
@ -423,6 +775,9 @@ es_pci_probe(device_t dev)
if (pci_get_devid(dev) == ES1370_PCI_ID) {
device_set_desc(dev, "AudioPCI ES1370");
return 0;
} else if (pci_get_devid(dev) == ES1371_PCI_ID) {
device_set_desc(dev, "AudioPCI ES1371");
return 0;
}
return ENXIO;
}
@ -441,6 +796,7 @@ es_pci_attach(device_t dev)
struct resource *irq = 0;
void *ih = 0;
char status[SND_STATUSLEN];
struct ac97_info *codec;
d = device_get_softc(dev);
if ((es = malloc(sizeof *es, M_DEVBUF, M_NOWAIT)) == NULL) {
@ -477,12 +833,28 @@ es_pci_attach(device_t dev)
device_printf(dev, "unable to map register space\n");
goto bad;
}
if (es_init(es) == -1) {
if (pci_get_devid(dev) == ES1371_PCI_ID) {
if(-1 == es1371_init(es)){
device_printf(dev, "unable to initialize the card\n");
goto bad;
}
codec = ac97_create(es,(ac97_read *)es1371_rdcodec,(ac97_write *)es1371_wrcodec);
if (codec == NULL) goto bad;
/* our init routine does everything for us */
/* set to NULL; flag mixer_init not to run the ac97_init */
/* ac97_mixer.init = NULL; */
mixer_init(d, &ac97_mixer, codec);
/* change the routine for setting speed */
es_chantemplate.setspeed = eschan1371_setspeed;
} else if (pci_get_devid(dev) == ES1370_PCI_ID) {
if (-1 == es_init(es)){
device_printf(dev, "unable to initialize the card\n");
goto bad;
}
mixer_init(d, &es_mixer, es);
}
mixer_init(d, &es_mixer, es);
irqid = 0;
irq = bus_alloc_resource(dev, SYS_RES_IRQ, &irqid,
@ -540,4 +912,5 @@ static devclass_t pcm_devclass;
DRIVER_MODULE(es, pci, es_driver, pcm_devclass, 0, 0);
#endif /* NPCI != 0 */

View File

@ -1,7 +1,8 @@
/*
* Support the ENSONIQ AudioPCI board based on the ES1370 and Codec
* AK4531.
* Support the ENSONIQ AudioPCI board and Creative Labs SoundBlaster PCI
* boards based on the ES1370, ES1371 and ES1373 chips.
*
* Copyright (c) 1999 Russell Cattelan <cattelan@thebarn.com>
* Copyright (c) 1999 Cameron Grant <gandalf@vilnya.demon.co.uk>
* Copyright (c) 1998 by Joachim Kuebart. All rights reserved.
*
@ -40,34 +41,50 @@
* $FreeBSD$
*/
/*
* Part of this code was heavily inspired by the linux driver from
* Thomas Sailer (sailer@ife.ee.ethz.ch)
* Just about everything has been touched and reworked in some way but
* the all the underlying sequences/timing/register values are from
* Thomas' code.
*
*/
#include "pci.h"
#include "pcm.h"
#include <dev/pcm/sound.h>
#include <dev/pcm/pci/es1370.h>
#include <dev/pcm/ac97.h>
#include <dev/pcm/pci/es137x.h>
#include <pci/pcireg.h>
#include <pci/pcivar.h>
#include <sys/sysctl.h>
#if NPCI != 0
static int debug = 0;
SYSCTL_INT(_debug, OID_AUTO, es_debug, CTLFLAG_RW, &debug, 0, "");
#define MEM_MAP_REG 0x14
/* PCI IDs of supported chips */
#define ES1370_PCI_ID 0x50001274
#define ES1371_PCI_ID 0x13711274
/* device private data */
struct es_info;
struct es_chinfo {
typedef struct es_chinfo {
struct es_info *parent;
pcm_channel *channel;
snd_dbuf *buffer;
int dir;
u_int32_t fmt;
};
} es_chinfo_t;
struct es_info {
typedef struct es_info {
bus_space_tag_t st;
bus_space_handle_t sh;
bus_dma_tag_t parent_dmat;
@ -76,23 +93,33 @@ struct es_info {
u_long ctrl;
u_long sctrl;
struct es_chinfo pch, rch;
};
} es_info_t;
/* -------------------------------------------------------------------- */
/* prototypes */
static u_int es1371_wait_src_ready(es_info_t *);
static void es1371_src_write(es_info_t *, u_short, unsigned short);
static u_int es1371_adc_rate (es_info_t *, u_int, int);
static u_int es1371_dac1_rate(es_info_t *, u_int, int);
static u_int es1371_dac2_rate(es_info_t *, u_int, int);
static void es1371_wrcodec(void *, int, u_int32_t);
static u_int32_t es1371_rdcodec(void *, u_int32_t);
static int es1371_init(es_info_t *es);
static int eschan1371_setspeed(void *data, u_int32_t speed);
static int es_init(struct es_info *);
static void es_intr(void *);
static int write_codec(struct es_info *, u_char, u_char);
/* channel interface */
static void *eschan_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir);
static int eschan_setdir(void *data, int dir);
static int eschan_setformat(void *data, u_int32_t format);
static int eschan_setspeed(void *data, u_int32_t speed);
static int eschan_setblocksize(void *data, u_int32_t blocksize);
static int eschan_trigger(void *data, int go);
static int eschan_getptr(void *data);
static int eschan_setdir(void *data, int dir);
static int eschan_setformat(void *data, u_int32_t format);
static int eschan_setspeed(void *data, u_int32_t speed);
static int eschan_setblocksize(void *data, u_int32_t blocksize);
static int eschan_trigger(void *data, int go);
static int eschan_getptr(void *data);
static pcmchan_caps *eschan_getcaps(void *data);
static pcmchan_caps es_playcaps = {
@ -391,6 +418,331 @@ es_intr (void *p)
if (intsrc & STAT_ADC) chn_intr(es->rch.channel);
}
/* ES1371 specific code */
#define CODEC_ID_SESHIFT 10
#define CODEC_ID_SEMASK 0x1f
#define CODEC_PIRD 0x00800000 /* 0 = write AC97 register */
#define CODEC_PIADD_MASK 0x007f0000
#define CODEC_PIADD_SHIFT 16
#define CODEC_PIDAT_MASK 0x0000ffff
#define CODEC_PIDAT_SHIFT 0
#define CODEC_PORD 0x00800000 /* 0 = write AC97 register */
#define CODEC_POADD_MASK 0x007f0000
#define CODEC_POADD_SHIFT 16
#define CODEC_PODAT_MASK 0x0000ffff
#define CODEC_PODAT_SHIFT 0
#define CODEC_RDY 0x80000000 /* AC97 read data valid */
#define CODEC_WIP 0x40000000 /* AC97 write in progress */
#define ES1370_REG_CONTROL 0x00
#define ES1370_REG_SERIAL_CONTROL 0x20
#define ES1371_REG_CODEC 0x14
#define ES1371_REG_LEGACY 0x18 /* W/R: Legacy control/status register */
#define ES1371_REG_SMPRATE 0x10 /* W/R: Codec rate converter interface register */
#define ES1371_SYNC_RES (1<<14) /* Warm AC97 reset */
#define ES1371_DIS_R1 (1<<19) /* record channel accumulator update disable */
#define ES1371_DIS_P2 (1<<20) /* playback channel 2 accumulator update disable */
#define ES1371_DIS_P1 (1<<21) /* playback channel 1 accumulator update disable */
#define ES1371_DIS_SRC (1<<22) /* sample rate converter disable */
#define ES1371_SRC_RAM_BUSY (1<<23) /* R/O: sample rate memory is busy */
#define ES1371_SRC_RAM_WE (1<<24) /* R/W: read/write control for sample rate converter */
#define ES1371_SRC_RAM_ADDRO(o) (((o)&0x7f)<<25) /* address of the sample rate converter */
#define ES1371_SRC_RAM_DATAO(o) (((o)&0xffff)<<0) /* current value of the sample rate converter */
#define ES1371_SRC_RAM_DATAI(i) (((i)>>0)&0xffff) /* current value of the sample rate converter */
/*
* Sample rate converter addresses
*/
#define ES_SMPREG_DAC1 0x70
#define ES_SMPREG_DAC2 0x74
#define ES_SMPREG_ADC 0x78
#define ES_SMPREG_TRUNC_N 0x00
#define ES_SMPREG_INT_REGS 0x01
#define ES_SMPREG_VFREQ_FRAC 0x03
#define ES_SMPREG_VOL_ADC 0x6c
#define ES_SMPREG_VOL_DAC1 0x7c
#define ES_SMPREG_VOL_DAC2 0x7e
int
es1371_init(struct es_info *es)
{
int idx;
if(debug > 0) printf("es_init\n");
es->ctrl = 0;
es->sctrl = 0;
/* initialize the chips */
bus_space_write_4(es->st, es->sh, ES1370_REG_CONTROL, es->ctrl);
bus_space_write_4(es->st, es->sh, ES1370_REG_SERIAL_CONTROL, es->sctrl);
bus_space_write_4(es->st, es->sh, ES1371_REG_LEGACY, 0);
/* AC'97 warm reset to start the bitclk */
bus_space_write_4(es->st, es->sh, ES1371_REG_LEGACY, es->ctrl | ES1371_SYNC_RES);
DELAY(2000);
bus_space_write_4(es->st, es->sh, ES1370_REG_SERIAL_CONTROL,es->ctrl);
/* Init the sample rate converter */
bus_space_write_4(es->st, es->sh, ES1371_REG_SMPRATE, ES1371_DIS_SRC);
for (idx = 0; idx < 0x80; idx++)
es1371_src_write(es, idx, 0);
es1371_src_write(es, ES_SMPREG_DAC1 + ES_SMPREG_TRUNC_N, 16 << 4);
es1371_src_write(es, ES_SMPREG_DAC1 + ES_SMPREG_INT_REGS, 16 << 10);
es1371_src_write(es, ES_SMPREG_DAC2 + ES_SMPREG_TRUNC_N, 16 << 4);
es1371_src_write(es, ES_SMPREG_DAC2 + ES_SMPREG_INT_REGS, 16 << 10);
es1371_src_write(es, ES_SMPREG_VOL_ADC, 1 << 12);
es1371_src_write(es, ES_SMPREG_VOL_ADC + 1, 1 << 12);
es1371_src_write(es, ES_SMPREG_VOL_DAC1, 1 << 12);
es1371_src_write(es, ES_SMPREG_VOL_DAC1 + 1, 1 << 12);
es1371_src_write(es, ES_SMPREG_VOL_DAC2, 1 << 12);
es1371_src_write(es, ES_SMPREG_VOL_DAC2 + 1, 1 << 12);
es1371_adc_rate (es, 22050, 1);
es1371_dac1_rate(es, 22050, 1);
es1371_dac2_rate(es, 22050, 1);
/* WARNING:
* enabling the sample rate converter without properly programming
* its parameters causes the chip to lock up (the SRC busy bit will
* be stuck high, and I've found no way to rectify this other than
* power cycle)
*/
bus_space_write_4(es->st, es->sh, ES1371_REG_SMPRATE, 0);
return (0);
}
void
es1371_wrcodec(void *s, int addr, u_int32_t data)
{
/* unsigned long flags; */
int sl;
unsigned t, x;
struct es_info *es = (struct es_info*)s;
if(debug > 0) printf("wrcodec addr 0x%x data 0x%x\n",addr,data);
for (t = 0; t < 0x1000; t++)
if(!(bus_space_read_4(es->st, es->sh,(ES1371_REG_CODEC & CODEC_WIP))))
break;
sl = spltty();
/* save the current state for later */
x = bus_space_read_4(es->st, es->sh, ES1371_REG_SMPRATE);
/* enable SRC state data in SRC mux */
bus_space_write_4(es->st, es->sh, ES1371_REG_SMPRATE,
(es1371_wait_src_ready(s) &
(ES1371_DIS_SRC | ES1371_DIS_P1 | ES1371_DIS_P2 | ES1371_DIS_R1)));
/* wait for a SAFE time to write addr/data and then do it, dammit */
for (t = 0; t < 0x1000; t++)
if (( bus_space_read_4(es->st, es->sh, ES1371_REG_SMPRATE) & 0x00070000) == 0x00010000)
break;
if(debug > 2) printf("one b_s_w: 0x%x 0x%x 0x%x\n",es->sh,ES1371_REG_CODEC,
((addr << CODEC_POADD_SHIFT) & CODEC_POADD_MASK) |
((data << CODEC_PODAT_SHIFT) & CODEC_PODAT_MASK));
bus_space_write_4(es->st, es->sh,ES1371_REG_CODEC,
((addr << CODEC_POADD_SHIFT) & CODEC_POADD_MASK) |
((data << CODEC_PODAT_SHIFT) & CODEC_PODAT_MASK));
/* restore SRC reg */
es1371_wait_src_ready(s);
if(debug > 2) printf("two b_s_w: 0x%x 0x%x 0x%x\n",es->sh,ES1371_REG_SMPRATE,x);
bus_space_write_4(es->st, es->sh,ES1371_REG_SMPRATE,x);
splx(sl);
}
u_int32_t
es1371_rdcodec(void *s, u_int32_t addr)
{
/* unsigned long flags; */
int sl;
unsigned t, x;
struct es_info *es = (struct es_info *)s;
if(debug > 0) printf("rdcodec addr 0x%x ... ",addr);
for (t = 0; t < 0x1000; t++)
if (!(x = bus_space_read_4(es->st,es->sh,ES1371_REG_CODEC) & CODEC_WIP))
break;
if(debug >0) printf("loop 1 t 0x%x x 0x%x ",t,x);
sl = spltty();
/* save the current state for later */
x = bus_space_read_4(es->st, es->sh, ES1371_REG_SMPRATE);
/* enable SRC state data in SRC mux */
bus_space_write_4(es->st, es->sh, ES1371_REG_SMPRATE,
(es1371_wait_src_ready(s) &
(ES1371_DIS_SRC | ES1371_DIS_P1 | ES1371_DIS_P2 | ES1371_DIS_R1)));
/* wait for a SAFE time to write addr/data and then do it, dammit */
for (t = 0; t < 0x5000; t++)
if (( x = bus_space_read_4(es->st, es->sh, ES1371_REG_SMPRATE) & 0x00070000) == 0x00010000)
break;
if(debug >0) printf("loop 2 t 0x%x x 0x%x ",t,x);
bus_space_write_4(es->st, es->sh,ES1371_REG_CODEC,
((addr << CODEC_POADD_SHIFT) & CODEC_POADD_MASK) | CODEC_PORD);
/* restore SRC reg */
es1371_wait_src_ready(s);
bus_space_write_4(es->st,es->sh,ES1371_REG_SMPRATE,x);
splx(sl);
/* now wait for the stinkin' data (RDY) */
for (t = 0; t < 0x1000; t++)
if ((x = bus_space_read_4(es->st,es->sh,ES1371_REG_CODEC)) & CODEC_RDY)
break;
if(debug > 0) printf("loop 3 t 0x%x 0x%x ret 0x%x\n",t,x,((x & CODEC_PIDAT_MASK) >> CODEC_PIDAT_SHIFT));
return ((x & CODEC_PIDAT_MASK) >> CODEC_PIDAT_SHIFT);
}
static u_int
es1371_src_read(es_info_t *es, u_short reg){
unsigned int r;
r = es1371_wait_src_ready(es) &
(ES1371_DIS_SRC | ES1371_DIS_P1 | ES1371_DIS_P2 | ES1371_DIS_R1);
r |= ES1371_SRC_RAM_ADDRO(reg);
bus_space_write_4(es->st, es->sh,ES1371_REG_SMPRATE,r);
return ES1371_SRC_RAM_DATAI(es1371_wait_src_ready(es));
}
static void
es1371_src_write(es_info_t *es, u_short reg, u_short data){
u_int r;
r = es1371_wait_src_ready(es) &
(ES1371_DIS_SRC | ES1371_DIS_P1 | ES1371_DIS_P2 | ES1371_DIS_R1);
r |= ES1371_SRC_RAM_ADDRO(reg) | ES1371_SRC_RAM_DATAO(data);
/* printf("es1371_src_write 0x%x 0x%x\n",ES1371_REG_SMPRATE,r | ES1371_SRC_RAM_WE); */
bus_space_write_4(es->st, es->sh,ES1371_REG_SMPRATE,r | ES1371_SRC_RAM_WE);
}
static u_int
es1371_adc_rate(es_info_t *es, u_int rate, int set){
u_int n, truncm, freq, result;
if (rate > 48000)
rate = 48000;
if (rate < 4000)
rate = 4000;
n = rate / 3000;
if ((1 << n) & ((1 << 15) | (1 << 13) | (1 << 11) | (1 << 9)))
n--;
truncm = (21 * n - 1) | 1;
freq = ((48000UL << 15) / rate) * n;
result = (48000UL << 15) / (freq / n);
if (set) {
if (rate >= 24000) {
if (truncm > 239)
truncm = 239;
es1371_src_write(es, ES_SMPREG_ADC + ES_SMPREG_TRUNC_N,
(((239 - truncm) >> 1) << 9) | (n << 4));
} else {
if (truncm > 119)
truncm = 119;
es1371_src_write(es, ES_SMPREG_ADC + ES_SMPREG_TRUNC_N,
0x8000 | (((119 - truncm) >> 1) << 9) | (n << 4));
}
es1371_src_write(es, ES_SMPREG_ADC + ES_SMPREG_INT_REGS,
(es1371_src_read(es, ES_SMPREG_ADC + ES_SMPREG_INT_REGS) &
0x00ff) | ((freq >> 5) & 0xfc00));
es1371_src_write(es, ES_SMPREG_ADC + ES_SMPREG_VFREQ_FRAC, freq & 0x7fff);
es1371_src_write(es, ES_SMPREG_VOL_ADC, n << 8);
es1371_src_write(es, ES_SMPREG_VOL_ADC + 1, n << 8);
}
return result;
}
static u_int
es1371_dac1_rate(es_info_t *es, u_int rate, int set){
u_int freq, r, result;
if (rate > 48000)
rate = 48000;
if (rate < 4000)
rate = 4000;
freq = (rate << 15) / 3000;
result = (freq * 3000) >> 15;
if (set) {
r = (es1371_wait_src_ready(es) & (ES1371_DIS_SRC | ES1371_DIS_P1 | ES1371_DIS_P2 | ES1371_DIS_R1));
bus_space_write_4(es->st, es->sh,ES1371_REG_SMPRATE,r);
es1371_src_write(es, ES_SMPREG_DAC1 +
ES_SMPREG_INT_REGS,
(es1371_src_read(es,
ES_SMPREG_DAC1 + ES_SMPREG_INT_REGS) & 0x00ff) | ((freq >> 5) & 0xfc00));
es1371_src_write(es, ES_SMPREG_DAC1 + ES_SMPREG_VFREQ_FRAC, freq & 0x7fff);
r = (es1371_wait_src_ready(es) & (ES1371_DIS_SRC | ES1371_DIS_P2 | ES1371_DIS_R1));
bus_space_write_4(es->st, es->sh,ES1371_REG_SMPRATE,r);
}
return result;
}
static u_int
es1371_dac2_rate(es_info_t *es, u_int rate, int set){
u_int freq, r, result;
if (rate > 48000)
rate = 48000;
if (rate < 4000)
rate = 4000;
freq = (rate << 15) / 3000;
result = (freq * 3000) >> 15;
if (set) {
r = (es1371_wait_src_ready(es) & (ES1371_DIS_SRC | ES1371_DIS_P1 | ES1371_DIS_P2 | ES1371_DIS_R1));
bus_space_write_4(es->st, es->sh,ES1371_REG_SMPRATE,r);
/* if(debug > 0) printf("dac2_rate 0x%x\n",bus_space_read_4(es->st, es->sh,ES1371_REG_SMPRATE)); */
es1371_src_write(es, ES_SMPREG_DAC2 + ES_SMPREG_INT_REGS,
(es1371_src_read(es, ES_SMPREG_DAC2 + ES_SMPREG_INT_REGS) &
0x00ff) | ((freq >> 5) & 0xfc00));
es1371_src_write(es, ES_SMPREG_DAC2 + ES_SMPREG_VFREQ_FRAC, freq & 0x7fff);
r = (es1371_wait_src_ready(es) & (ES1371_DIS_SRC | ES1371_DIS_P1 | ES1371_DIS_R1));
bus_space_write_4(es->st, es->sh,ES1371_REG_SMPRATE,r);
/* if(debug > 0) printf("dac2_rate 0x%x\n",bus_space_read_4(es->st, es->sh,ES1371_REG_SMPRATE)); */
}
return result;
}
static u_int
es1371_wait_src_ready(es_info_t *es){
u_int t, r;
for (t = 0; t < 500; t++) {
if (!((r = bus_space_read_4(es->st, es->sh,ES1371_REG_SMPRATE)) & ES1371_SRC_RAM_BUSY)){
return r;
}
DELAY(1000);
}
printf("es1371: wait source ready timeout 0x%x [0x%x]\n", ES1371_REG_SMPRATE, r);
return 0;
}
int
eschan1371_setspeed(void *data, u_int32_t speed)
{
struct es_chinfo *ch = data;
struct es_info *es = ch->parent;
/* rec/play speeds locked together - should indicate in flags */
es1371_dac2_rate(es, speed, 1); /* play */
es1371_adc_rate (es, speed, 1); /* record */
return speed; /* XXX calc real speed */
}
/* -------------------------------------------------------------------- */
/*
@ -423,6 +775,9 @@ es_pci_probe(device_t dev)
if (pci_get_devid(dev) == ES1370_PCI_ID) {
device_set_desc(dev, "AudioPCI ES1370");
return 0;
} else if (pci_get_devid(dev) == ES1371_PCI_ID) {
device_set_desc(dev, "AudioPCI ES1371");
return 0;
}
return ENXIO;
}
@ -441,6 +796,7 @@ es_pci_attach(device_t dev)
struct resource *irq = 0;
void *ih = 0;
char status[SND_STATUSLEN];
struct ac97_info *codec;
d = device_get_softc(dev);
if ((es = malloc(sizeof *es, M_DEVBUF, M_NOWAIT)) == NULL) {
@ -477,12 +833,28 @@ es_pci_attach(device_t dev)
device_printf(dev, "unable to map register space\n");
goto bad;
}
if (es_init(es) == -1) {
if (pci_get_devid(dev) == ES1371_PCI_ID) {
if(-1 == es1371_init(es)){
device_printf(dev, "unable to initialize the card\n");
goto bad;
}
codec = ac97_create(es,(ac97_read *)es1371_rdcodec,(ac97_write *)es1371_wrcodec);
if (codec == NULL) goto bad;
/* our init routine does everything for us */
/* set to NULL; flag mixer_init not to run the ac97_init */
/* ac97_mixer.init = NULL; */
mixer_init(d, &ac97_mixer, codec);
/* change the routine for setting speed */
es_chantemplate.setspeed = eschan1371_setspeed;
} else if (pci_get_devid(dev) == ES1370_PCI_ID) {
if (-1 == es_init(es)){
device_printf(dev, "unable to initialize the card\n");
goto bad;
}
mixer_init(d, &es_mixer, es);
}
mixer_init(d, &es_mixer, es);
irqid = 0;
irq = bus_alloc_resource(dev, SYS_RES_IRQ, &irqid,
@ -540,4 +912,5 @@ static devclass_t pcm_devclass;
DRIVER_MODULE(es, pci, es_driver, pcm_devclass, 0, 0);
#endif /* NPCI != 0 */