1139749Simp/*- 261346Scg * Copyright (c) 2000 Cameron Grant <cg@freebsd.org> 361108Scg * All rights reserved. 461108Scg * 561108Scg * Redistribution and use in source and binary forms, with or without 661108Scg * modification, are permitted provided that the following conditions 761108Scg * are met: 861108Scg * 1. Redistributions of source code must retain the above copyright 961108Scg * notice, this list of conditions and the following disclaimer. 1061108Scg * 2. Redistributions in binary form must reproduce the above copyright 1161108Scg * notice, this list of conditions and the following disclaimer in the 1261108Scg * documentation and/or other materials provided with the distribution. 1361108Scg * 1461108Scg * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1561108Scg * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1661108Scg * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1761108Scg * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1861108Scg * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1961108Scg * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2061108Scg * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2161108Scg * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHERIN CONTRACT, STRICT 2261108Scg * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2361108Scg * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THEPOSSIBILITY OF 2461108Scg * SUCH DAMAGE. 2561108Scg */ 2661108Scg 27193640Sariff#ifdef HAVE_KERNEL_OPTION_HEADERS 28193640Sariff#include "opt_snd.h" 29193640Sariff#endif 30193640Sariff 3161108Scg#include <dev/sound/pcm/sound.h> 3261108Scg#include <dev/sound/pcm/ac97.h> 3361108Scg 34119287Simp#include <dev/pci/pcireg.h> 35119287Simp#include <dev/pci/pcivar.h> 3661108Scg 3761108Scg#include <dev/sound/pci/ds1.h> 3861108Scg#include <dev/sound/pci/ds1-fw.h> 3961108Scg 4082180ScgSND_DECLARE_FILE("$FreeBSD$"); 4182180Scg 4261108Scg/* -------------------------------------------------------------------- */ 4361108Scg 4461108Scg#define DS1_CHANS 4 4561346Scg#define DS1_RECPRIMARY 0 4670343Scg#define DS1_IRQHZ ((48000 << 8) / 256) 4771504Scg#define DS1_BUFFSIZE 4096 4861108Scg 4961108Scgstruct pbank { 5061108Scg volatile u_int32_t Format; 5161108Scg volatile u_int32_t LoopDefault; 5261108Scg volatile u_int32_t PgBase; 5361108Scg volatile u_int32_t PgLoop; 5461108Scg volatile u_int32_t PgLoopEnd; 5561108Scg volatile u_int32_t PgLoopFrac; 5661108Scg volatile u_int32_t PgDeltaEnd; 5761108Scg volatile u_int32_t LpfKEnd; 5861108Scg volatile u_int32_t EgGainEnd; 5961108Scg volatile u_int32_t LchGainEnd; 6061108Scg volatile u_int32_t RchGainEnd; 6161108Scg volatile u_int32_t Effect1GainEnd; 6261108Scg volatile u_int32_t Effect2GainEnd; 6361108Scg volatile u_int32_t Effect3GainEnd; 6461108Scg volatile u_int32_t LpfQ; 6561108Scg volatile u_int32_t Status; 6661108Scg volatile u_int32_t NumOfFrames; 6761108Scg volatile u_int32_t LoopCount; 6861108Scg volatile u_int32_t PgStart; 6961108Scg volatile u_int32_t PgStartFrac; 7061108Scg volatile u_int32_t PgDelta; 7161108Scg volatile u_int32_t LpfK; 7261108Scg volatile u_int32_t EgGain; 7361108Scg volatile u_int32_t LchGain; 7461108Scg volatile u_int32_t RchGain; 7561108Scg volatile u_int32_t Effect1Gain; 7661108Scg volatile u_int32_t Effect2Gain; 7761108Scg volatile u_int32_t Effect3Gain; 7861108Scg volatile u_int32_t LpfD1; 7961108Scg volatile u_int32_t LpfD2; 8061108Scg}; 8161108Scg 8261346Scgstruct rbank { 8361346Scg volatile u_int32_t PgBase; 8461346Scg volatile u_int32_t PgLoopEnd; 8561346Scg volatile u_int32_t PgStart; 8661346Scg volatile u_int32_t NumOfLoops; 8761346Scg}; 8861346Scg 8961108Scgstruct sc_info; 9061108Scg 9161108Scg/* channel registers */ 9261346Scgstruct sc_pchinfo { 9361108Scg int run, spd, dir, fmt; 9474763Scg struct snd_dbuf *buffer; 9574763Scg struct pcm_channel *channel; 9661108Scg volatile struct pbank *lslot, *rslot; 9761108Scg int lsnum, rsnum; 9861108Scg struct sc_info *parent; 9961108Scg}; 10061108Scg 10161346Scgstruct sc_rchinfo { 10261346Scg int run, spd, dir, fmt, num; 10374763Scg struct snd_dbuf *buffer; 10474763Scg struct pcm_channel *channel; 10561346Scg volatile struct rbank *slot; 10661346Scg struct sc_info *parent; 10761346Scg}; 10861346Scg 10961108Scg/* device private data */ 11061108Scgstruct sc_info { 11161108Scg device_t dev; 11261108Scg u_int32_t type, rev; 11361108Scg u_int32_t cd2id, ctrlbase; 11461108Scg 11561108Scg bus_space_tag_t st; 11661108Scg bus_space_handle_t sh; 11784659Scg bus_dma_tag_t buffer_dmat, control_dmat; 11865340Scg bus_dmamap_t map; 11961108Scg 12061108Scg struct resource *reg, *irq; 12161108Scg int regid, irqid; 12261108Scg void *ih; 123107285Scg struct mtx *lock; 12461108Scg 12565218Scg void *regbase; 12661108Scg u_int32_t *pbase, pbankbase, pbanksize; 12761108Scg volatile struct pbank *pbank[2 * 64]; 12861346Scg volatile struct rbank *rbank; 12961108Scg int pslotfree, currbank, pchn, rchn; 13084659Scg unsigned int bufsz; 13161108Scg 13261346Scg struct sc_pchinfo pch[DS1_CHANS]; 13361346Scg struct sc_rchinfo rch[2]; 13461108Scg}; 13561108Scg 13661108Scgstruct { 13761108Scg u_int32_t dev, subdev; 13861108Scg char *name; 13961108Scg u_int32_t *mcode; 14061108Scg} ds_devs[] = { 14161108Scg {0x00041073, 0, "Yamaha DS-1 (YMF724)", CntrlInst}, 14261108Scg {0x000d1073, 0, "Yamaha DS-1E (YMF724F)", CntrlInst1E}, 14361108Scg {0x00051073, 0, "Yamaha DS-1? (YMF734)", CntrlInst}, 14461108Scg {0x00081073, 0, "Yamaha DS-1? (YMF737)", CntrlInst}, 14561108Scg {0x00201073, 0, "Yamaha DS-1? (YMF738)", CntrlInst}, 14661108Scg {0x00061073, 0, "Yamaha DS-1? (YMF738_TEG)", CntrlInst}, 14761108Scg {0x000a1073, 0x00041073, "Yamaha DS-1 (YMF740)", CntrlInst}, 14861108Scg {0x000a1073, 0x000a1073, "Yamaha DS-1 (YMF740B)", CntrlInst}, 14970134Scg {0x000a1073, 0x53328086, "Yamaha DS-1 (YMF740I)", CntrlInst}, 15061146Speter {0x000a1073, 0, "Yamaha DS-1 (YMF740?)", CntrlInst}, 15161108Scg {0x000c1073, 0, "Yamaha DS-1E (YMF740C)", CntrlInst1E}, 15270134Scg {0x00101073, 0, "Yamaha DS-1E (YMF744)", CntrlInst1E}, 15361108Scg {0x00121073, 0, "Yamaha DS-1E (YMF754)", CntrlInst1E}, 15461108Scg {0, 0, NULL, NULL} 15561108Scg}; 15661108Scg 15761108Scg/* -------------------------------------------------------------------- */ 15861108Scg 15961108Scg/* 16061108Scg * prototypes 16161108Scg */ 16261108Scg 16361108Scg/* stuff */ 164166919Sariffstatic int ds_init(struct sc_info *); 16561108Scgstatic void ds_intr(void *); 16661108Scg 16761108Scg/* talk to the card */ 16861108Scgstatic u_int32_t ds_rd(struct sc_info *, int, int); 16961108Scgstatic void ds_wr(struct sc_info *, int, u_int32_t, int); 17061108Scg 17161108Scg/* -------------------------------------------------------------------- */ 17261108Scg 17364881Scgstatic u_int32_t ds_recfmt[] = { 174193640Sariff SND_FORMAT(AFMT_U8, 1, 0), 175193640Sariff SND_FORMAT(AFMT_U8, 2, 0), 176193640Sariff SND_FORMAT(AFMT_S8, 1, 0), 177193640Sariff SND_FORMAT(AFMT_S8, 2, 0), 178193640Sariff SND_FORMAT(AFMT_S16_LE, 1, 0), 179193640Sariff SND_FORMAT(AFMT_S16_LE, 2, 0), 180193640Sariff SND_FORMAT(AFMT_U16_LE, 1, 0), 181193640Sariff SND_FORMAT(AFMT_U16_LE, 2, 0), 18264881Scg 0 18361108Scg}; 18474763Scgstatic struct pcmchan_caps ds_reccaps = {4000, 48000, ds_recfmt, 0}; 18561108Scg 18664881Scgstatic u_int32_t ds_playfmt[] = { 187193640Sariff SND_FORMAT(AFMT_U8, 1, 0), 188193640Sariff SND_FORMAT(AFMT_U8, 2, 0), 189193640Sariff /* SND_FORMAT(AFMT_S16_LE, 1, 0), */ 190193640Sariff SND_FORMAT(AFMT_S16_LE, 2, 0), 19164881Scg 0 19261108Scg}; 19374763Scgstatic struct pcmchan_caps ds_playcaps = {4000, 96000, ds_playfmt, 0}; 19461108Scg 19561108Scg/* -------------------------------------------------------------------- */ 19661108Scg/* Hardware */ 19761108Scgstatic u_int32_t 19861108Scgds_rd(struct sc_info *sc, int regno, int size) 19961108Scg{ 20061108Scg switch (size) { 20161108Scg case 1: 20261108Scg return bus_space_read_1(sc->st, sc->sh, regno); 20361108Scg case 2: 20461108Scg return bus_space_read_2(sc->st, sc->sh, regno); 20561108Scg case 4: 20661108Scg return bus_space_read_4(sc->st, sc->sh, regno); 20761108Scg default: 20861108Scg return 0xffffffff; 20961108Scg } 21061108Scg} 21161108Scg 21261108Scgstatic void 21361108Scgds_wr(struct sc_info *sc, int regno, u_int32_t data, int size) 21461108Scg{ 21561108Scg switch (size) { 21661108Scg case 1: 21761108Scg bus_space_write_1(sc->st, sc->sh, regno, data); 21861108Scg break; 21961108Scg case 2: 22061108Scg bus_space_write_2(sc->st, sc->sh, regno, data); 22161108Scg break; 22261108Scg case 4: 22361108Scg bus_space_write_4(sc->st, sc->sh, regno, data); 22461108Scg break; 22561108Scg } 22661108Scg} 22761108Scg 22861108Scgstatic void 22961108Scgwrl(struct sc_info *sc, u_int32_t *ptr, u_int32_t val) 23061108Scg{ 23161108Scg *(volatile u_int32_t *)ptr = val; 23265171Sdfr bus_space_barrier(sc->st, sc->sh, 0, 0, BUS_SPACE_BARRIER_WRITE); 23361108Scg} 23461108Scg 23570134Scg/* -------------------------------------------------------------------- */ 23661108Scg/* ac97 codec */ 23761108Scgstatic int 23861108Scgds_cdbusy(struct sc_info *sc, int sec) 23961108Scg{ 24061108Scg int i, reg; 24161108Scg 24261108Scg reg = sec? YDSXGR_SECSTATUSADR : YDSXGR_PRISTATUSADR; 24361108Scg i = YDSXG_AC97TIMEOUT; 24461108Scg while (i > 0) { 24561108Scg if (!(ds_rd(sc, reg, 2) & 0x8000)) 24661108Scg return 0; 24761108Scg i--; 24861108Scg } 24961108Scg return ETIMEDOUT; 25061108Scg} 25161108Scg 25261108Scgstatic u_int32_t 25370134Scgds_initcd(kobj_t obj, void *devinfo) 25461108Scg{ 25561108Scg struct sc_info *sc = (struct sc_info *)devinfo; 25661108Scg u_int32_t x; 25761108Scg 25861108Scg x = pci_read_config(sc->dev, PCIR_DSXGCTRL, 1); 25961108Scg if (x & 0x03) { 26061108Scg pci_write_config(sc->dev, PCIR_DSXGCTRL, x & ~0x03, 1); 26161108Scg pci_write_config(sc->dev, PCIR_DSXGCTRL, x | 0x03, 1); 26261108Scg pci_write_config(sc->dev, PCIR_DSXGCTRL, x & ~0x03, 1); 26361146Speter /* 26461146Speter * The YMF740 on some Intel motherboards requires a pretty 26561146Speter * hefty delay after this reset for some reason... Otherwise: 26661146Speter * "pcm0: ac97 codec init failed" 26761146Speter * Maybe this is needed for all YMF740's? 26861146Speter * 400ms and 500ms here seem to work, 300ms does not. 26964015Scg * 27064015Scg * do it for all chips -cg 27161146Speter */ 27264015Scg DELAY(500000); 27361108Scg } 27461108Scg 27565490Scg return ds_cdbusy(sc, 0)? 0 : 1; 27661108Scg} 27761108Scg 27870134Scgstatic int 27970134Scgds_rdcd(kobj_t obj, void *devinfo, int regno) 28061108Scg{ 28161108Scg struct sc_info *sc = (struct sc_info *)devinfo; 28261108Scg int sec, cid, i; 28361108Scg u_int32_t cmd, reg; 28461108Scg 28561108Scg sec = regno & 0x100; 28661108Scg regno &= 0xff; 28761108Scg cid = sec? (sc->cd2id << 8) : 0; 28861108Scg reg = sec? YDSXGR_SECSTATUSDATA : YDSXGR_PRISTATUSDATA; 28961108Scg if (sec && cid == 0) 29061108Scg return 0xffffffff; 29161108Scg 29261108Scg cmd = YDSXG_AC97READCMD | cid | regno; 29361108Scg ds_wr(sc, YDSXGR_AC97CMDADR, cmd, 2); 29461108Scg 29561108Scg if (ds_cdbusy(sc, sec)) 29661108Scg return 0xffffffff; 29761108Scg 29861146Speter if (sc->type == 11 && sc->rev < 2) 29961108Scg for (i = 0; i < 600; i++) 30061108Scg ds_rd(sc, reg, 2); 30161108Scg 30261108Scg return ds_rd(sc, reg, 2); 30361108Scg} 30461108Scg 30570134Scgstatic int 30670134Scgds_wrcd(kobj_t obj, void *devinfo, int regno, u_int32_t data) 30761108Scg{ 30861108Scg struct sc_info *sc = (struct sc_info *)devinfo; 30961108Scg int sec, cid; 31061108Scg u_int32_t cmd; 31161108Scg 31261108Scg sec = regno & 0x100; 31361108Scg regno &= 0xff; 31461108Scg cid = sec? (sc->cd2id << 8) : 0; 31561108Scg if (sec && cid == 0) 31670134Scg return ENXIO; 31761108Scg 31861108Scg cmd = YDSXG_AC97WRITECMD | cid | regno; 31961108Scg cmd <<= 16; 32061108Scg cmd |= data; 32161108Scg ds_wr(sc, YDSXGR_AC97CMDDATA, cmd, 4); 32261108Scg 32370134Scg return ds_cdbusy(sc, sec); 32461108Scg} 32561108Scg 32670134Scgstatic kobj_method_t ds_ac97_methods[] = { 32770134Scg KOBJMETHOD(ac97_init, ds_initcd), 32870134Scg KOBJMETHOD(ac97_read, ds_rdcd), 32970134Scg KOBJMETHOD(ac97_write, ds_wrcd), 330193640Sariff KOBJMETHOD_END 33170134Scg}; 33270134ScgAC97_DECLARE(ds_ac97); 33370134Scg 33470134Scg/* -------------------------------------------------------------------- */ 33570134Scg 33661108Scgstatic void 33761108Scgds_enadsp(struct sc_info *sc, int on) 33861108Scg{ 33961108Scg u_int32_t v, i; 34061108Scg 34161108Scg v = on? 1 : 0; 34261108Scg if (on) { 34361108Scg ds_wr(sc, YDSXGR_CONFIG, 0x00000001, 4); 34461108Scg } else { 34561108Scg if (ds_rd(sc, YDSXGR_CONFIG, 4)) 34661108Scg ds_wr(sc, YDSXGR_CONFIG, 0x00000000, 4); 34761108Scg i = YDSXG_WORKBITTIMEOUT; 34861108Scg while (i > 0) { 34961108Scg if (!(ds_rd(sc, YDSXGR_CONFIG, 4) & 0x00000002)) 35061108Scg break; 35161108Scg i--; 35261108Scg } 35361108Scg } 35461108Scg} 35561108Scg 35661108Scgstatic volatile struct pbank * 35761108Scgds_allocpslot(struct sc_info *sc) 35861108Scg{ 35961108Scg int slot; 36061108Scg 36161108Scg if (sc->pslotfree > 63) 36261108Scg return NULL; 36361108Scg slot = sc->pslotfree++; 36461108Scg return sc->pbank[slot * 2]; 36561108Scg} 36661108Scg 36761108Scgstatic int 368111183Scognetds_initpbank(volatile struct pbank *pb, int ch, int b16, int stereo, u_int32_t rate, bus_addr_t base, u_int32_t len) 36961108Scg{ 37061108Scg u_int32_t lv[] = {1, 1, 0, 0, 0}; 37161108Scg u_int32_t rv[] = {1, 0, 1, 0, 0}; 37261108Scg u_int32_t e1[] = {0, 0, 0, 0, 0}; 37361108Scg u_int32_t e2[] = {1, 0, 0, 1, 0}; 37461108Scg u_int32_t e3[] = {1, 0, 0, 0, 1}; 37561108Scg int ss, i; 37661108Scg u_int32_t delta; 37761108Scg 37861108Scg struct { 37961108Scg int rate, fK, fQ; 38061108Scg } speedinfo[] = { 38161108Scg { 100, 0x00570000, 0x35280000}, 38261108Scg { 2000, 0x06aa0000, 0x34a70000}, 38361108Scg { 8000, 0x18b20000, 0x32020000}, 38461108Scg {11025, 0x20930000, 0x31770000}, 38561108Scg {16000, 0x2b9a0000, 0x31390000}, 38661108Scg {22050, 0x35a10000, 0x31c90000}, 38761108Scg {32000, 0x3eaa0000, 0x33d00000}, 38861108Scg/* {44100, 0x04646000, 0x370a0000}, 38961108Scg*/ {48000, 0x40000000, 0x40000000}, 39061108Scg }; 39161108Scg 39261108Scg ss = b16? 1 : 0; 39361108Scg ss += stereo? 1 : 0; 39461108Scg delta = (65536 * rate) / 48000; 39561108Scg i = 0; 39661108Scg while (i < 7 && speedinfo[i].rate < rate) 39761108Scg i++; 39861108Scg 39961108Scg pb->Format = stereo? 0x00010000 : 0; 40061108Scg pb->Format |= b16? 0 : 0x80000000; 40161108Scg pb->Format |= (stereo && (ch == 2 || ch == 4))? 0x00000001 : 0; 40261108Scg pb->LoopDefault = 0; 403188424Scognet pb->PgBase = base; 40461108Scg pb->PgLoop = 0; 40561108Scg pb->PgLoopEnd = len >> ss; 40661108Scg pb->PgLoopFrac = 0; 40761108Scg pb->Status = 0; 40861108Scg pb->NumOfFrames = 0; 40961108Scg pb->LoopCount = 0; 41061108Scg pb->PgStart = 0; 41161108Scg pb->PgStartFrac = 0; 41261108Scg pb->PgDelta = pb->PgDeltaEnd = delta << 12; 41361108Scg pb->LpfQ = speedinfo[i].fQ; 41461108Scg pb->LpfK = pb->LpfKEnd = speedinfo[i].fK; 41561108Scg pb->LpfD1 = pb->LpfD2 = 0; 41661108Scg pb->EgGain = pb->EgGainEnd = 0x40000000; 41761108Scg pb->LchGain = pb->LchGainEnd = lv[ch] * 0x40000000; 41861108Scg pb->RchGain = pb->RchGainEnd = rv[ch] * 0x40000000; 41961108Scg pb->Effect1Gain = pb->Effect1GainEnd = e1[ch] * 0x40000000; 42061108Scg pb->Effect2Gain = pb->Effect2GainEnd = e2[ch] * 0x40000000; 42161108Scg pb->Effect3Gain = pb->Effect3GainEnd = e3[ch] * 0x40000000; 42261108Scg 42361108Scg return 0; 42461108Scg} 42561108Scg 42661108Scgstatic void 42761108Scgds_enapslot(struct sc_info *sc, int slot, int go) 42861108Scg{ 42961108Scg wrl(sc, &sc->pbase[slot + 1], go? (sc->pbankbase + 2 * slot * sc->pbanksize) : 0); 43061108Scg /* printf("pbase[%d] = 0x%x\n", slot + 1, go? (sc->pbankbase + 2 * slot * sc->pbanksize) : 0); */ 43161108Scg} 43261108Scg 43361108Scgstatic void 43461346Scgds_setuppch(struct sc_pchinfo *ch) 43561108Scg{ 43661346Scg int stereo, b16, c, sz; 437111183Scognet bus_addr_t addr; 43861108Scg 439193640Sariff stereo = (AFMT_CHANNEL(ch->fmt) > 1)? 1 : 0; 44061108Scg b16 = (ch->fmt & AFMT_16BIT)? 1 : 0; 44161108Scg c = stereo? 1 : 0; 442111183Scognet addr = sndbuf_getbufaddr(ch->buffer); 44370291Scg sz = sndbuf_getsize(ch->buffer); 44461108Scg 445111183Scognet ds_initpbank(ch->lslot, c, stereo, b16, ch->spd, addr, sz); 446111183Scognet ds_initpbank(ch->lslot + 1, c, stereo, b16, ch->spd, addr, sz); 447111183Scognet ds_initpbank(ch->rslot, 2, stereo, b16, ch->spd, addr, sz); 448111183Scognet ds_initpbank(ch->rslot + 1, 2, stereo, b16, ch->spd, addr, sz); 44961108Scg} 45061108Scg 45161346Scgstatic void 45261346Scgds_setuprch(struct sc_rchinfo *ch) 45361108Scg{ 45461346Scg struct sc_info *sc = ch->parent; 45561346Scg int stereo, b16, i, sz, pri; 45661346Scg u_int32_t x, y; 457111183Scognet bus_addr_t addr; 45861346Scg 459193640Sariff stereo = (AFMT_CHANNEL(ch->fmt) > 1)? 1 : 0; 46061346Scg b16 = (ch->fmt & AFMT_16BIT)? 1 : 0; 461111183Scognet addr = sndbuf_getbufaddr(ch->buffer); 46270291Scg sz = sndbuf_getsize(ch->buffer); 46361346Scg pri = (ch->num == DS1_RECPRIMARY)? 1 : 0; 46461346Scg 46561346Scg for (i = 0; i < 2; i++) { 466111183Scognet ch->slot[i].PgBase = addr; 46761346Scg ch->slot[i].PgLoopEnd = sz; 46861346Scg ch->slot[i].PgStart = 0; 46961346Scg ch->slot[i].NumOfLoops = 0; 47061346Scg } 47161346Scg x = (b16? 0x00 : 0x01) | (stereo? 0x02 : 0x00); 47261346Scg y = (48000 * 4096) / ch->spd; 47361346Scg y--; 47461346Scg /* printf("pri = %d, x = %d, y = %d\n", pri, x, y); */ 47561346Scg ds_wr(sc, pri? YDSXGR_ADCFORMAT : YDSXGR_RECFORMAT, x, 4); 47661346Scg ds_wr(sc, pri? YDSXGR_ADCSLOTSR : YDSXGR_RECSLOTSR, y, 4); 47761346Scg} 47861346Scg 47970134Scg/* -------------------------------------------------------------------- */ 48061346Scg/* play channel interface */ 48161346Scgstatic void * 48274763Scgds1pchan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, struct pcm_channel *c, int dir) 48361346Scg{ 48461108Scg struct sc_info *sc = devinfo; 48561346Scg struct sc_pchinfo *ch; 48661108Scg 48761346Scg KASSERT(dir == PCMDIR_PLAY, ("ds1pchan_init: bad direction")); 48861346Scg 48961346Scg ch = &sc->pch[sc->pchn++]; 49061108Scg ch->buffer = b; 49161108Scg ch->parent = sc; 49261108Scg ch->channel = c; 49361346Scg ch->dir = dir; 494193640Sariff ch->fmt = SND_FORMAT(AFMT_U8, 1, 0); 49561108Scg ch->spd = 8000; 49661108Scg ch->run = 0; 497168847Sariff if (sndbuf_alloc(ch->buffer, sc->buffer_dmat, 0, sc->bufsz) != 0) 49861108Scg return NULL; 49961108Scg else { 50061108Scg ch->lsnum = sc->pslotfree; 50161108Scg ch->lslot = ds_allocpslot(sc); 50261108Scg ch->rsnum = sc->pslotfree; 50361108Scg ch->rslot = ds_allocpslot(sc); 50461346Scg ds_setuppch(ch); 50561108Scg return ch; 50661108Scg } 50761108Scg} 50861108Scg 50961108Scgstatic int 51070134Scgds1pchan_setformat(kobj_t obj, void *data, u_int32_t format) 51161108Scg{ 51261346Scg struct sc_pchinfo *ch = data; 51361108Scg 51461108Scg ch->fmt = format; 51561108Scg 51661108Scg return 0; 51761108Scg} 51861108Scg 519193640Sariffstatic u_int32_t 52070134Scgds1pchan_setspeed(kobj_t obj, void *data, u_int32_t speed) 52161108Scg{ 52261346Scg struct sc_pchinfo *ch = data; 52361108Scg 52461108Scg ch->spd = speed; 52561108Scg 52661108Scg return speed; 52761108Scg} 52861108Scg 529193640Sariffstatic u_int32_t 53070134Scgds1pchan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize) 53161108Scg{ 53270343Scg struct sc_pchinfo *ch = data; 533119362Siedowse struct sc_info *sc = ch->parent; 53470343Scg int drate; 53570343Scg 53670343Scg /* irq rate is fixed at 187.5hz */ 537193640Sariff drate = ch->spd * sndbuf_getalign(ch->buffer); 538119362Siedowse blocksize = roundup2((drate << 8) / DS1_IRQHZ, 4); 539119362Siedowse sndbuf_resize(ch->buffer, sc->bufsz / blocksize, blocksize); 54071504Scg 54161108Scg return blocksize; 54261108Scg} 54361108Scg 54461108Scg/* semantic note: must start at beginning of buffer */ 54561108Scgstatic int 54670134Scgds1pchan_trigger(kobj_t obj, void *data, int go) 54761108Scg{ 54861346Scg struct sc_pchinfo *ch = data; 54961346Scg struct sc_info *sc = ch->parent; 55061108Scg int stereo; 55161108Scg 552170521Sariff if (!PCMTRIG_COMMON(go)) 55361108Scg return 0; 554193640Sariff stereo = (AFMT_CHANNEL(ch->fmt) > 1)? 1 : 0; 55561108Scg if (go == PCMTRIG_START) { 55661108Scg ch->run = 1; 55761346Scg ds_setuppch(ch); 55861108Scg ds_enapslot(sc, ch->lsnum, 1); 55961108Scg ds_enapslot(sc, ch->rsnum, stereo); 56074763Scg snd_mtxlock(sc->lock); 56161108Scg ds_wr(sc, YDSXGR_MODE, 0x00000003, 4); 56274763Scg snd_mtxunlock(sc->lock); 56361108Scg } else { 56461108Scg ch->run = 0; 56561346Scg /* ds_setuppch(ch); */ 56661108Scg ds_enapslot(sc, ch->lsnum, 0); 56761108Scg ds_enapslot(sc, ch->rsnum, 0); 56861108Scg } 56961108Scg 57061108Scg return 0; 57161108Scg} 57261108Scg 573193640Sariffstatic u_int32_t 57470134Scgds1pchan_getptr(kobj_t obj, void *data) 57561108Scg{ 57661346Scg struct sc_pchinfo *ch = data; 57761108Scg struct sc_info *sc = ch->parent; 57861108Scg volatile struct pbank *bank; 57961108Scg int ss; 58061108Scg u_int32_t ptr; 58161108Scg 582193640Sariff ss = (AFMT_CHANNEL(ch->fmt) > 1)? 1 : 0; 58361108Scg ss += (ch->fmt & AFMT_16BIT)? 1 : 0; 58461108Scg 58561108Scg bank = ch->lslot + sc->currbank; 58661108Scg /* printf("getptr: %d\n", bank->PgStart << ss); */ 58761108Scg ptr = bank->PgStart; 58861108Scg ptr <<= ss; 58961108Scg return ptr; 59061108Scg} 59161108Scg 59274763Scgstatic struct pcmchan_caps * 59370134Scgds1pchan_getcaps(kobj_t obj, void *data) 59461108Scg{ 59561346Scg return &ds_playcaps; 59661346Scg} 59761108Scg 59870134Scgstatic kobj_method_t ds1pchan_methods[] = { 59970134Scg KOBJMETHOD(channel_init, ds1pchan_init), 60070134Scg KOBJMETHOD(channel_setformat, ds1pchan_setformat), 60170134Scg KOBJMETHOD(channel_setspeed, ds1pchan_setspeed), 60270134Scg KOBJMETHOD(channel_setblocksize, ds1pchan_setblocksize), 60370134Scg KOBJMETHOD(channel_trigger, ds1pchan_trigger), 60470134Scg KOBJMETHOD(channel_getptr, ds1pchan_getptr), 60570134Scg KOBJMETHOD(channel_getcaps, ds1pchan_getcaps), 606193640Sariff KOBJMETHOD_END 60770134Scg}; 60870134ScgCHANNEL_DECLARE(ds1pchan); 60970134Scg 61070134Scg/* -------------------------------------------------------------------- */ 61161346Scg/* record channel interface */ 61261346Scgstatic void * 61374763Scgds1rchan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, struct pcm_channel *c, int dir) 61461346Scg{ 61561346Scg struct sc_info *sc = devinfo; 61661346Scg struct sc_rchinfo *ch; 61761346Scg 61861346Scg KASSERT(dir == PCMDIR_REC, ("ds1rchan_init: bad direction")); 61961346Scg 62061346Scg ch = &sc->rch[sc->rchn]; 62161346Scg ch->num = sc->rchn++; 62261346Scg ch->buffer = b; 62361346Scg ch->parent = sc; 62461346Scg ch->channel = c; 62561346Scg ch->dir = dir; 626193640Sariff ch->fmt = SND_FORMAT(AFMT_U8, 1, 0); 62761346Scg ch->spd = 8000; 628168847Sariff if (sndbuf_alloc(ch->buffer, sc->buffer_dmat, 0, sc->bufsz) != 0) 62961346Scg return NULL; 63061346Scg else { 63161346Scg ch->slot = (ch->num == DS1_RECPRIMARY)? sc->rbank + 2: sc->rbank; 63261346Scg ds_setuprch(ch); 63361346Scg return ch; 63461346Scg } 63561108Scg} 63661108Scg 63761346Scgstatic int 63870134Scgds1rchan_setformat(kobj_t obj, void *data, u_int32_t format) 63961346Scg{ 64061346Scg struct sc_rchinfo *ch = data; 64161346Scg 64261346Scg ch->fmt = format; 64361346Scg 64461346Scg return 0; 64561346Scg} 64661346Scg 647193640Sariffstatic u_int32_t 64870134Scgds1rchan_setspeed(kobj_t obj, void *data, u_int32_t speed) 64961346Scg{ 65061346Scg struct sc_rchinfo *ch = data; 65161346Scg 65261346Scg ch->spd = speed; 65361346Scg 65461346Scg return speed; 65561346Scg} 65661346Scg 657193640Sariffstatic u_int32_t 65870134Scgds1rchan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize) 65961346Scg{ 66071504Scg struct sc_rchinfo *ch = data; 661119362Siedowse struct sc_info *sc = ch->parent; 66271504Scg int drate; 66371504Scg 66471504Scg /* irq rate is fixed at 187.5hz */ 665193640Sariff drate = ch->spd * sndbuf_getalign(ch->buffer); 666119362Siedowse blocksize = roundup2((drate << 8) / DS1_IRQHZ, 4); 667119362Siedowse sndbuf_resize(ch->buffer, sc->bufsz / blocksize, blocksize); 66871504Scg 66961346Scg return blocksize; 67061346Scg} 67161346Scg 67261346Scg/* semantic note: must start at beginning of buffer */ 67361346Scgstatic int 67470134Scgds1rchan_trigger(kobj_t obj, void *data, int go) 67561346Scg{ 67661346Scg struct sc_rchinfo *ch = data; 67761346Scg struct sc_info *sc = ch->parent; 67861346Scg u_int32_t x; 67961346Scg 680170521Sariff if (!PCMTRIG_COMMON(go)) 68161346Scg return 0; 68261346Scg if (go == PCMTRIG_START) { 68361346Scg ch->run = 1; 68461346Scg ds_setuprch(ch); 68574763Scg snd_mtxlock(sc->lock); 68661346Scg x = ds_rd(sc, YDSXGR_MAPOFREC, 4); 68761346Scg x |= (ch->num == DS1_RECPRIMARY)? 0x02 : 0x01; 68861346Scg ds_wr(sc, YDSXGR_MAPOFREC, x, 4); 68961346Scg ds_wr(sc, YDSXGR_MODE, 0x00000003, 4); 69074763Scg snd_mtxunlock(sc->lock); 69161346Scg } else { 69261346Scg ch->run = 0; 69374763Scg snd_mtxlock(sc->lock); 69461346Scg x = ds_rd(sc, YDSXGR_MAPOFREC, 4); 69561346Scg x &= ~((ch->num == DS1_RECPRIMARY)? 0x02 : 0x01); 69661346Scg ds_wr(sc, YDSXGR_MAPOFREC, x, 4); 69774763Scg snd_mtxunlock(sc->lock); 69861346Scg } 69961346Scg 70061346Scg return 0; 70161346Scg} 70261346Scg 703193640Sariffstatic u_int32_t 70470134Scgds1rchan_getptr(kobj_t obj, void *data) 70561346Scg{ 70661346Scg struct sc_rchinfo *ch = data; 70761346Scg struct sc_info *sc = ch->parent; 70861346Scg 70961346Scg return ch->slot[sc->currbank].PgStart; 71061346Scg} 71161346Scg 71274763Scgstatic struct pcmchan_caps * 71370134Scgds1rchan_getcaps(kobj_t obj, void *data) 71461346Scg{ 71561346Scg return &ds_reccaps; 71661346Scg} 71761346Scg 71870134Scgstatic kobj_method_t ds1rchan_methods[] = { 71970134Scg KOBJMETHOD(channel_init, ds1rchan_init), 72070134Scg KOBJMETHOD(channel_setformat, ds1rchan_setformat), 72170134Scg KOBJMETHOD(channel_setspeed, ds1rchan_setspeed), 72270134Scg KOBJMETHOD(channel_setblocksize, ds1rchan_setblocksize), 72370134Scg KOBJMETHOD(channel_trigger, ds1rchan_trigger), 72470134Scg KOBJMETHOD(channel_getptr, ds1rchan_getptr), 72570134Scg KOBJMETHOD(channel_getcaps, ds1rchan_getcaps), 726193640Sariff KOBJMETHOD_END 72770134Scg}; 72870134ScgCHANNEL_DECLARE(ds1rchan); 72970134Scg 73070134Scg/* -------------------------------------------------------------------- */ 73161108Scg/* The interrupt handler */ 73261108Scgstatic void 73361108Scgds_intr(void *p) 73461108Scg{ 73561108Scg struct sc_info *sc = (struct sc_info *)p; 73661108Scg u_int32_t i, x; 73761108Scg 73874763Scg snd_mtxlock(sc->lock); 73961108Scg i = ds_rd(sc, YDSXGR_STATUS, 4); 74061346Scg if (i & 0x00008000) 74161346Scg device_printf(sc->dev, "timeout irq\n"); 74261108Scg if (i & 0x80008000) { 74361108Scg ds_wr(sc, YDSXGR_STATUS, i & 0x80008000, 4); 74461108Scg sc->currbank = ds_rd(sc, YDSXGR_CTRLSELECT, 4) & 0x00000001; 74561108Scg 74661108Scg x = 0; 74761346Scg for (i = 0; i < DS1_CHANS; i++) { 74861108Scg if (sc->pch[i].run) { 74961108Scg x = 1; 750154215Sariff snd_mtxunlock(sc->lock); 75161108Scg chn_intr(sc->pch[i].channel); 752154215Sariff snd_mtxlock(sc->lock); 75361108Scg } 75461346Scg } 75561346Scg for (i = 0; i < 2; i++) { 75661346Scg if (sc->rch[i].run) { 75761346Scg x = 1; 758154215Sariff snd_mtxunlock(sc->lock); 75961346Scg chn_intr(sc->rch[i].channel); 760154215Sariff snd_mtxlock(sc->lock); 76161346Scg } 76261346Scg } 76361108Scg i = ds_rd(sc, YDSXGR_MODE, 4); 76461108Scg if (x) 76561108Scg ds_wr(sc, YDSXGR_MODE, i | 0x00000002, 4); 76661108Scg 76761108Scg } 76874763Scg snd_mtxunlock(sc->lock); 76961108Scg} 77061108Scg 77161108Scg/* -------------------------------------------------------------------- */ 77261108Scg 77361108Scg/* 77461108Scg * Probe and attach the card 77561108Scg */ 77661108Scg 77761108Scgstatic void 77861108Scgds_setmap(void *arg, bus_dma_segment_t *segs, int nseg, int error) 77961108Scg{ 78061108Scg struct sc_info *sc = arg; 78161108Scg 78261108Scg sc->ctrlbase = error? 0 : (u_int32_t)segs->ds_addr; 78361108Scg 78461108Scg if (bootverbose) { 78561133Scg printf("ds1: setmap (%lx, %lx), nseg=%d, error=%d\n", 78661133Scg (unsigned long)segs->ds_addr, (unsigned long)segs->ds_len, 78761133Scg nseg, error); 78861108Scg } 78961108Scg} 79061108Scg 79161108Scgstatic int 792166919Sariffds_init(struct sc_info *sc) 79361108Scg{ 79461108Scg int i; 79561108Scg u_int32_t *ci, r, pcs, rcs, ecs, ws, memsz, cb; 79661108Scg u_int8_t *t; 79761108Scg void *buf; 79861108Scg 79961108Scg ci = ds_devs[sc->type].mcode; 80061108Scg 80161108Scg ds_wr(sc, YDSXGR_NATIVEDACOUTVOL, 0x00000000, 4); 80261108Scg ds_enadsp(sc, 0); 80361108Scg ds_wr(sc, YDSXGR_MODE, 0x00010000, 4); 80461108Scg ds_wr(sc, YDSXGR_MODE, 0x00000000, 4); 80561108Scg ds_wr(sc, YDSXGR_MAPOFREC, 0x00000000, 4); 80661108Scg ds_wr(sc, YDSXGR_MAPOFEFFECT, 0x00000000, 4); 80761108Scg ds_wr(sc, YDSXGR_PLAYCTRLBASE, 0x00000000, 4); 80861108Scg ds_wr(sc, YDSXGR_RECCTRLBASE, 0x00000000, 4); 80961108Scg ds_wr(sc, YDSXGR_EFFCTRLBASE, 0x00000000, 4); 81061108Scg r = ds_rd(sc, YDSXGR_GLOBALCTRL, 2); 81161108Scg ds_wr(sc, YDSXGR_GLOBALCTRL, r & ~0x0007, 2); 81261108Scg 81361108Scg for (i = 0; i < YDSXG_DSPLENGTH; i += 4) 81461108Scg ds_wr(sc, YDSXGR_DSPINSTRAM + i, DspInst[i >> 2], 4); 81561108Scg 81661108Scg for (i = 0; i < YDSXG_CTRLLENGTH; i += 4) 81761108Scg ds_wr(sc, YDSXGR_CTRLINSTRAM + i, ci[i >> 2], 4); 81861108Scg 81961108Scg ds_enadsp(sc, 1); 82061108Scg 82161142Scg pcs = 0; 82261142Scg for (i = 100; i > 0; i--) { 82361142Scg pcs = ds_rd(sc, YDSXGR_PLAYCTRLSIZE, 4) << 2; 82461142Scg if (pcs == sizeof(struct pbank)) 82561142Scg break; 82661456Sdan DELAY(1000); 82761142Scg } 82861142Scg if (pcs != sizeof(struct pbank)) { 82961142Scg device_printf(sc->dev, "preposterous playctrlsize (%d)\n", pcs); 83061142Scg return -1; 83161142Scg } 83261108Scg rcs = ds_rd(sc, YDSXGR_RECCTRLSIZE, 4) << 2; 83361108Scg ecs = ds_rd(sc, YDSXGR_EFFCTRLSIZE, 4) << 2; 83461108Scg ws = ds_rd(sc, YDSXGR_WORKSIZE, 4) << 2; 83561108Scg 83661108Scg memsz = 64 * 2 * pcs + 2 * 2 * rcs + 5 * 2 * ecs + ws; 83761108Scg memsz += (64 + 1) * 4; 83861108Scg 83965218Scg if (sc->regbase == NULL) { 840166919Sariff if (bus_dma_tag_create(bus_get_dma_tag(sc->dev), 2, 0, 841166904Snetchild BUS_SPACE_MAXADDR_32BIT, 842166904Snetchild BUS_SPACE_MAXADDR, 843154494Sariff NULL, NULL, memsz, 1, memsz, 0, NULL, 844154494Sariff NULL, &sc->control_dmat)) 84565218Scg return -1; 84684659Scg if (bus_dmamem_alloc(sc->control_dmat, &buf, BUS_DMA_NOWAIT, &sc->map)) 84784659Scg return -1; 84884659Scg if (bus_dmamap_load(sc->control_dmat, sc->map, buf, memsz, ds_setmap, sc, 0) || !sc->ctrlbase) { 84965218Scg device_printf(sc->dev, "pcs=%d, rcs=%d, ecs=%d, ws=%d, memsz=%d\n", 85084659Scg pcs, rcs, ecs, ws, memsz); 85165218Scg return -1; 85265218Scg } 85365218Scg sc->regbase = buf; 85465218Scg } else 85565218Scg buf = sc->regbase; 85661108Scg 85761108Scg cb = 0; 85861108Scg t = buf; 85961108Scg ds_wr(sc, YDSXGR_WORKBASE, sc->ctrlbase + cb, 4); 86061108Scg cb += ws; 86161108Scg sc->pbase = (u_int32_t *)(t + cb); 86261108Scg /* printf("pbase = %p -> 0x%x\n", sc->pbase, sc->ctrlbase + cb); */ 86361108Scg ds_wr(sc, YDSXGR_PLAYCTRLBASE, sc->ctrlbase + cb, 4); 86461108Scg cb += (64 + 1) * 4; 86561346Scg sc->rbank = (struct rbank *)(t + cb); 86661108Scg ds_wr(sc, YDSXGR_RECCTRLBASE, sc->ctrlbase + cb, 4); 86761108Scg cb += 2 * 2 * rcs; 86861108Scg ds_wr(sc, YDSXGR_EFFCTRLBASE, sc->ctrlbase + cb, 4); 86961108Scg cb += 5 * 2 * ecs; 87061108Scg 87161108Scg sc->pbankbase = sc->ctrlbase + cb; 87261108Scg sc->pbanksize = pcs; 87361108Scg for (i = 0; i < 64; i++) { 87461108Scg wrl(sc, &sc->pbase[i + 1], 0); 87561108Scg sc->pbank[i * 2] = (struct pbank *)(t + cb); 87661108Scg /* printf("pbank[%d] = %p -> 0x%x; ", i * 2, (struct pbank *)(t + cb), sc->ctrlbase + cb - vtophys(t + cb)); */ 87761108Scg cb += pcs; 87861108Scg sc->pbank[i * 2 + 1] = (struct pbank *)(t + cb); 87961108Scg /* printf("pbank[%d] = %p -> 0x%x\n", i * 2 + 1, (struct pbank *)(t + cb), sc->ctrlbase + cb - vtophys(t + cb)); */ 88061108Scg cb += pcs; 88161108Scg } 88261108Scg wrl(sc, &sc->pbase[0], DS1_CHANS * 2); 88361108Scg 88461108Scg sc->pchn = sc->rchn = 0; 88561108Scg ds_wr(sc, YDSXGR_NATIVEDACOUTVOL, 0x3fff3fff, 4); 88661346Scg ds_wr(sc, YDSXGR_NATIVEADCINVOL, 0x3fff3fff, 4); 88761346Scg ds_wr(sc, YDSXGR_NATIVEDACINVOL, 0x3fff3fff, 4); 88870343Scg 88961108Scg return 0; 89061108Scg} 89161108Scg 89261108Scgstatic int 89365340Scgds_uninit(struct sc_info *sc) 89465340Scg{ 89565340Scg ds_wr(sc, YDSXGR_NATIVEDACOUTVOL, 0x00000000, 4); 89665340Scg ds_wr(sc, YDSXGR_NATIVEADCINVOL, 0, 4); 89765340Scg ds_wr(sc, YDSXGR_NATIVEDACINVOL, 0, 4); 89865340Scg ds_enadsp(sc, 0); 89965340Scg ds_wr(sc, YDSXGR_MODE, 0x00010000, 4); 90065340Scg ds_wr(sc, YDSXGR_MAPOFREC, 0x00000000, 4); 90165340Scg ds_wr(sc, YDSXGR_MAPOFEFFECT, 0x00000000, 4); 90265340Scg ds_wr(sc, YDSXGR_PLAYCTRLBASE, 0x00000000, 4); 90365340Scg ds_wr(sc, YDSXGR_RECCTRLBASE, 0x00000000, 4); 90465340Scg ds_wr(sc, YDSXGR_EFFCTRLBASE, 0x00000000, 4); 90565340Scg ds_wr(sc, YDSXGR_GLOBALCTRL, 0, 2); 90665340Scg 90784659Scg bus_dmamap_unload(sc->control_dmat, sc->map); 90884659Scg bus_dmamem_free(sc->control_dmat, sc->regbase, sc->map); 90965340Scg 91065340Scg return 0; 91165340Scg} 91265340Scg 91365340Scgstatic int 91461108Scgds_finddev(u_int32_t dev, u_int32_t subdev) 91561108Scg{ 91661108Scg int i; 91761108Scg 91861108Scg for (i = 0; ds_devs[i].dev; i++) { 91961108Scg if (ds_devs[i].dev == dev && 92061108Scg (ds_devs[i].subdev == subdev || ds_devs[i].subdev == 0)) 92161108Scg return i; 92261108Scg } 92361108Scg return -1; 92461108Scg} 92561108Scg 92661108Scgstatic int 92761108Scgds_pci_probe(device_t dev) 92861108Scg{ 92961108Scg int i; 93061108Scg u_int32_t subdev; 93161108Scg 93261108Scg subdev = (pci_get_subdevice(dev) << 16) | pci_get_subvendor(dev); 93361108Scg i = ds_finddev(pci_get_devid(dev), subdev); 93461108Scg if (i >= 0) { 93561108Scg device_set_desc(dev, ds_devs[i].name); 936142890Simp return BUS_PROBE_DEFAULT; 93761108Scg } else 93861108Scg return ENXIO; 93961108Scg} 94061108Scg 94161108Scgstatic int 94261108Scgds_pci_attach(device_t dev) 94361108Scg{ 94461108Scg u_int32_t subdev, i; 94561108Scg struct sc_info *sc; 94665644Scg struct ac97_info *codec = NULL; 94761108Scg char status[SND_STATUSLEN]; 94861108Scg 949170873Sariff sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK | M_ZERO); 950167608Sariff sc->lock = snd_mtxcreate(device_get_nameunit(dev), "snd_ds1 softc"); 95161108Scg sc->dev = dev; 95261108Scg subdev = (pci_get_subdevice(dev) << 16) | pci_get_subvendor(dev); 95361108Scg sc->type = ds_finddev(pci_get_devid(dev), subdev); 95461108Scg sc->rev = pci_get_revid(dev); 95561108Scg 956254306Sscottl pci_enable_busmaster(dev); 95761108Scg 958119690Sjhb sc->regid = PCIR_BAR(0); 959127135Snjl sc->reg = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->regid, 960127135Snjl RF_ACTIVE); 96161108Scg if (!sc->reg) { 96261108Scg device_printf(dev, "unable to map register space\n"); 96361108Scg goto bad; 96461108Scg } 96561108Scg 96661108Scg sc->st = rman_get_bustag(sc->reg); 96761108Scg sc->sh = rman_get_bushandle(sc->reg); 96861108Scg 96984659Scg sc->bufsz = pcm_getbuffersize(dev, 4096, DS1_BUFFSIZE, 65536); 97084659Scg 971166904Snetchild if (bus_dma_tag_create(/*parent*/bus_get_dma_tag(dev), /*alignment*/2, 972166904Snetchild /*boundary*/0, 97361108Scg /*lowaddr*/BUS_SPACE_MAXADDR_32BIT, 97461108Scg /*highaddr*/BUS_SPACE_MAXADDR, 97561108Scg /*filter*/NULL, /*filterarg*/NULL, 97684659Scg /*maxsize*/sc->bufsz, /*nsegments*/1, /*maxsegz*/0x3ffff, 977154494Sariff /*flags*/0, /*lockfunc*/NULL, 978154494Sariff /*lockarg*/NULL, &sc->buffer_dmat) != 0) { 97961108Scg device_printf(dev, "unable to create dma tag\n"); 98061108Scg goto bad; 98161108Scg } 98261108Scg 98365218Scg sc->regbase = NULL; 984166919Sariff if (ds_init(sc) == -1) { 98561108Scg device_printf(dev, "unable to initialize the card\n"); 98661108Scg goto bad; 98761108Scg } 98861108Scg 98970134Scg codec = AC97_CREATE(dev, sc, ds_ac97); 99061108Scg if (codec == NULL) 99161108Scg goto bad; 992154215Sariff /* 993154215Sariff * Turn on inverted external amplifier sense flags for few 994154215Sariff * 'special' boards. 995154215Sariff */ 996154215Sariff switch (subdev) { 997154215Sariff case 0x81171033: /* NEC ValueStar (VT550/0) */ 998154215Sariff ac97_setflags(codec, ac97_getflags(codec) | AC97_F_EAPD_INV); 999154215Sariff break; 1000154215Sariff default: 1001154215Sariff break; 1002154215Sariff } 100370134Scg mixer_init(dev, ac97_getmixerclass(), codec); 100461108Scg 100561108Scg sc->irqid = 0; 1006127135Snjl sc->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->irqid, 1007127135Snjl RF_ACTIVE | RF_SHAREABLE); 1008154215Sariff if (!sc->irq || snd_setup_intr(dev, sc->irq, INTR_MPSAFE, ds_intr, sc, &sc->ih)) { 100961108Scg device_printf(dev, "unable to map interrupt\n"); 101061108Scg goto bad; 101161108Scg } 101261108Scg 1013126695Smatk snprintf(status, SND_STATUSLEN, "at memory 0x%lx irq %ld %s", 1014126695Smatk rman_get_start(sc->reg), rman_get_start(sc->irq),PCM_KLDSTRING(snd_ds1)); 101561108Scg 101661346Scg if (pcm_register(dev, sc, DS1_CHANS, 2)) 101761108Scg goto bad; 101861108Scg for (i = 0; i < DS1_CHANS; i++) 101970134Scg pcm_addchan(dev, PCMDIR_PLAY, &ds1pchan_class, sc); 102061346Scg for (i = 0; i < 2; i++) 102170134Scg pcm_addchan(dev, PCMDIR_REC, &ds1rchan_class, sc); 102261108Scg pcm_setstatus(dev, status); 102361108Scg 102461108Scg return 0; 102561108Scg 102661108Scgbad: 102765644Scg if (codec) 102865644Scg ac97_destroy(codec); 102961108Scg if (sc->reg) 103061108Scg bus_release_resource(dev, SYS_RES_MEMORY, sc->regid, sc->reg); 103161108Scg if (sc->ih) 103261108Scg bus_teardown_intr(dev, sc->irq, sc->ih); 103361108Scg if (sc->irq) 103461108Scg bus_release_resource(dev, SYS_RES_IRQ, sc->irqid, sc->irq); 103584659Scg if (sc->buffer_dmat) 103684659Scg bus_dma_tag_destroy(sc->buffer_dmat); 103784659Scg if (sc->control_dmat) 103884659Scg bus_dma_tag_destroy(sc->control_dmat); 103974763Scg if (sc->lock) 104074763Scg snd_mtxfree(sc->lock); 104161108Scg free(sc, M_DEVBUF); 104261108Scg return ENXIO; 104361108Scg} 104461108Scg 104565218Scgstatic int 104665218Scgds_pci_resume(device_t dev) 104765218Scg{ 104865218Scg struct sc_info *sc; 104965218Scg 105065218Scg sc = pcm_getdevinfo(dev); 105165218Scg 1052166919Sariff if (ds_init(sc) == -1) { 105365218Scg device_printf(dev, "unable to reinitialize the card\n"); 105465218Scg return ENXIO; 105565218Scg } 105665340Scg if (mixer_reinit(dev) == -1) { 105765218Scg device_printf(dev, "unable to reinitialize the mixer\n"); 105865218Scg return ENXIO; 105965218Scg } 106065218Scg return 0; 106165218Scg} 106265218Scg 106365340Scgstatic int 106465340Scgds_pci_detach(device_t dev) 106565340Scg{ 106665340Scg int r; 106765340Scg struct sc_info *sc; 106865340Scg 106965340Scg r = pcm_unregister(dev); 107065340Scg if (r) 107165340Scg return r; 107265340Scg 107365340Scg sc = pcm_getdevinfo(dev); 107465340Scg ds_uninit(sc); 107565644Scg bus_release_resource(dev, SYS_RES_MEMORY, sc->regid, sc->reg); 107665644Scg bus_teardown_intr(dev, sc->irq, sc->ih); 107765644Scg bus_release_resource(dev, SYS_RES_IRQ, sc->irqid, sc->irq); 107884659Scg bus_dma_tag_destroy(sc->buffer_dmat); 107984659Scg bus_dma_tag_destroy(sc->control_dmat); 108074763Scg snd_mtxfree(sc->lock); 108165340Scg free(sc, M_DEVBUF); 108265340Scg return 0; 108365340Scg} 108465340Scg 108561108Scgstatic device_method_t ds1_methods[] = { 108661108Scg /* Device interface */ 108761108Scg DEVMETHOD(device_probe, ds_pci_probe), 108861108Scg DEVMETHOD(device_attach, ds_pci_attach), 108965340Scg DEVMETHOD(device_detach, ds_pci_detach), 109065340Scg DEVMETHOD(device_resume, ds_pci_resume), 109161108Scg { 0, 0 } 109261108Scg}; 109361108Scg 109461108Scgstatic driver_t ds1_driver = { 109561108Scg "pcm", 109661108Scg ds1_methods, 109782180Scg PCM_SOFTC_SIZE, 109861108Scg}; 109961108Scg 110062483ScgDRIVER_MODULE(snd_ds1, pci, ds1_driver, pcm_devclass, 0, 0); 1101132236StanimuraMODULE_DEPEND(snd_ds1, sound, SOUND_MINVER, SOUND_PREFVER, SOUND_MAXVER); 110262483ScgMODULE_VERSION(snd_ds1, 1); 1103