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:
parent
a5fad8dbcb
commit
39d409c9e1
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=53413
@ -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 */
|
||||
|
@ -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 */
|
||||
|
Loading…
Reference in New Issue
Block a user