es137x.c revision 168847
1139743Simp/*- 2123474Swpaul * Support the ENSONIQ AudioPCI board and Creative Labs SoundBlaster PCI 3123474Swpaul * boards based on the ES1370, ES1371 and ES1373 chips. 4123474Swpaul * 5123474Swpaul * Copyright (c) 1999 Russell Cattelan <cattelan@thebarn.com> 6123474Swpaul * Copyright (c) 1999 Cameron Grant <cg@freebsd.org> 7123474Swpaul * Copyright (c) 1998 by Joachim Kuebart. All rights reserved. 8123474Swpaul * 9123474Swpaul * Redistribution and use in source and binary forms, with or without 10123474Swpaul * modification, are permitted provided that the following conditions 11123474Swpaul * are met: 12123474Swpaul * 13123474Swpaul * 1. Redistributions of source code must retain the above copyright 14123474Swpaul * notice, this list of conditions and the following disclaimer. 15123474Swpaul * 16123474Swpaul * 2. Redistributions in binary form must reproduce the above copyright 17123474Swpaul * notice, this list of conditions and the following disclaimer in 18123474Swpaul * the documentation and/or other materials provided with the 19123474Swpaul * distribution. 20123474Swpaul * 21123474Swpaul * 3. All advertising materials mentioning features or use of this 22123474Swpaul * software must display the following acknowledgement: 23123474Swpaul * This product includes software developed by Joachim Kuebart. 24123474Swpaul * 25123474Swpaul * 4. The name of the author may not be used to endorse or promote 26123474Swpaul * products derived from this software without specific prior 27123474Swpaul * written permission. 28123474Swpaul * 29123474Swpaul * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED 30123474Swpaul * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 31123474Swpaul * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 32123474Swpaul * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 33123474Swpaul * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 34123474Swpaul * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 35123474Swpaul * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 36123474Swpaul * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 37123474Swpaul * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 38140751Swpaul * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 39140751Swpaul * OF THE POSSIBILITY OF SUCH DAMAGE. 40140751Swpaul */ 41140751Swpaul 42140751Swpaul/* 43140751Swpaul * Part of this code was heavily inspired by the linux driver from 44140751Swpaul * Thomas Sailer (sailer@ife.ee.ethz.ch) 45140751Swpaul * Just about everything has been touched and reworked in some way but 46140751Swpaul * the all the underlying sequences/timing/register values are from 47140751Swpaul * Thomas' code. 48140751Swpaul * 49140751Swpaul*/ 50140751Swpaul 51140751Swpaul#include <dev/sound/pcm/sound.h> 52140751Swpaul#include <dev/sound/pcm/ac97.h> 53140751Swpaul#include <dev/sound/pci/es137x.h> 54140751Swpaul 55140751Swpaul#include <dev/pci/pcireg.h> 56140751Swpaul#include <dev/pci/pcivar.h> 57140751Swpaul 58140751Swpaul#include <sys/sysctl.h> 59140751Swpaul 60140751Swpaul#include "mixer_if.h" 61140751Swpaul 62140751SwpaulSND_DECLARE_FILE("$FreeBSD: head/sys/dev/sound/pci/es137x.c 168847 2007-04-18 18:26:41Z ariff $"); 63140751Swpaul 64140751Swpaul#define MEM_MAP_REG 0x14 65140751Swpaul 66140751Swpaul/* PCI IDs of supported chips */ 67140751Swpaul#define ES1370_PCI_ID 0x50001274 68140751Swpaul#define ES1371_PCI_ID 0x13711274 69140751Swpaul#define ES1371_PCI_ID2 0x13713274 70140751Swpaul#define CT5880_PCI_ID 0x58801274 71140751Swpaul#define CT4730_PCI_ID 0x89381102 72140751Swpaul 73140751Swpaul#define ES1371REV_ES1371_A 0x02 74140751Swpaul#define ES1371REV_ES1371_B 0x09 75140751Swpaul 76140751Swpaul#define ES1371REV_ES1373_8 0x08 77140751Swpaul#define ES1371REV_ES1373_A 0x04 78140751Swpaul#define ES1371REV_ES1373_B 0x06 79140751Swpaul 80140751Swpaul#define ES1371REV_CT5880_A 0x07 81140751Swpaul 82140751Swpaul#define CT5880REV_CT5880_C 0x02 83140751Swpaul#define CT5880REV_CT5880_D 0x03 84140751Swpaul#define CT5880REV_CT5880_E 0x04 85140751Swpaul 86140751Swpaul#define CT4730REV_CT4730_A 0x00 87140751Swpaul 88140751Swpaul#define ES_DEFAULT_BUFSZ 4096 89140751Swpaul 90140751Swpaul/* 2 DAC for playback, 1 ADC for record */ 91140751Swpaul#define ES_DAC1 0 92140751Swpaul#define ES_DAC2 1 93140751Swpaul#define ES_ADC 2 94140751Swpaul#define ES_NCHANS 3 95140751Swpaul 96140751Swpaul#define ES_DMA_SEGS_MIN 2 97140751Swpaul#define ES_DMA_SEGS_MAX 256 98140751Swpaul#define ES_BLK_MIN 64 99140751Swpaul#define ES_BLK_ALIGN (~(ES_BLK_MIN - 1)) 100140751Swpaul 101140751Swpaul#define ES1370_DAC1_MINSPEED 5512 102140751Swpaul#define ES1370_DAC1_MAXSPEED 44100 103142530Swpaul 104140751Swpaul/* device private data */ 105142530Swpaulstruct es_info; 106142530Swpaul 107142530Swpaulstruct es_chinfo { 108123512Swpaul struct es_info *parent; 109140751Swpaul struct pcm_channel *channel; 110140751Swpaul struct snd_dbuf *buffer; 111123512Swpaul struct pcmchan_caps caps; 112140751Swpaul int dir, num, index; 113140751Swpaul uint32_t fmt, blksz, blkcnt, bufsz; 114140751Swpaul uint32_t ptr, prevptr; 115140751Swpaul int active; 116140751Swpaul}; 117140751Swpaul 118123512Swpaul/* 119140751Swpaul * 32bit Ensoniq Configuration (es->escfg). 120123512Swpaul * ---------------------------------------- 121140751Swpaul * 122123757Swpaul * +-------+--------+------+------+---------+--------+---------+---------+ 123123757Swpaul * len | 16 | 1 | 1 | 1 | 2 | 2 | 1 | 8 | 124140751Swpaul * +-------+--------+------+------+---------+--------+---------+---------+ 125123757Swpaul * | fixed | single | | | | | is | general | 126123757Swpaul * | rate | pcm | DACx | DACy | numplay | numrec | es1370? | purpose | 127140751Swpaul * | | mixer | | | | | | | 128140751Swpaul * +-------+--------+------+------+---------+--------+---------+---------+ 129140751Swpaul */ 130140751Swpaul#define ES_FIXED_RATE(cfgv) \ 131140751Swpaul (((cfgv) & 0xffff0000) >> 16) 132140751Swpaul#define ES_SET_FIXED_RATE(cfgv, nv) \ 133144175Swpaul (((cfgv) & ~0xffff0000) | (((nv) & 0xffff) << 16)) 134140751Swpaul#define ES_SINGLE_PCM_MIX(cfgv) \ 135140751Swpaul (((cfgv) & 0x8000) >> 15) 136140751Swpaul#define ES_SET_SINGLE_PCM_MIX(cfgv, nv) \ 137140751Swpaul (((cfgv) & ~0x8000) | (((nv) ? 1 : 0) << 15)) 138123512Swpaul#define ES_DAC_FIRST(cfgv) \ 139140751Swpaul (((cfgv) & 0x4000) >> 14) 140140751Swpaul#define ES_SET_DAC_FIRST(cfgv, nv) \ 141140751Swpaul (((cfgv) & ~0x4000) | (((nv) & 0x1) << 14)) 142140751Swpaul#define ES_DAC_SECOND(cfgv) \ 143140751Swpaul (((cfgv) & 0x2000) >> 13) 144140751Swpaul#define ES_SET_DAC_SECOND(cfgv, nv) \ 145140751Swpaul (((cfgv) & ~0x2000) | (((nv) & 0x1) << 13)) 146124729Swpaul#define ES_NUMPLAY(cfgv) \ 147124729Swpaul (((cfgv) & 0x1800) >> 11) 148124729Swpaul#define ES_SET_NUMPLAY(cfgv, nv) \ 149124729Swpaul (((cfgv) & ~0x1800) | (((nv) & 0x3) << 11)) 150124729Swpaul#define ES_NUMREC(cfgv) \ 151124729Swpaul (((cfgv) & 0x600) >> 9) 152124729Swpaul#define ES_SET_NUMREC(cfgv, nv) \ 153124582Sobrien (((cfgv) & ~0x600) | (((nv) & 0x3) << 9)) 154124582Sobrien#define ES_IS_ES1370(cfgv) \ 155124582Sobrien (((cfgv) & 0x100) >> 8) 156124582Sobrien#define ES_SET_IS_ES1370(cfgv, nv) \ 157124582Sobrien (((cfgv) & ~0x100) | (((nv) ? 1 : 0) << 8)) 158124582Sobrien#define ES_GP(cfgv) \ 159124582Sobrien ((cfgv) & 0xff) 160124582Sobrien#define ES_SET_GP(cfgv, nv) \ 161124582Sobrien (((cfgv) & ~0xff) | ((nv) & 0xff)) 162124582Sobrien 163124582Sobrien#define ES_DAC1_ENABLED(cfgv) \ 164124582Sobrien (ES_NUMPLAY(cfgv) > 1 || \ 165124582Sobrien (ES_NUMPLAY(cfgv) == 1 && ES_DAC_FIRST(cfgv) == ES_DAC1)) 166124582Sobrien#define ES_DAC2_ENABLED(cfgv) \ 167124582Sobrien (ES_NUMPLAY(cfgv) > 1 || \ 168124582Sobrien (ES_NUMPLAY(cfgv) == 1 && ES_DAC_FIRST(cfgv) == ES_DAC2)) 169124582Sobrien 170124582Sobrien/* 171124582Sobrien * DAC 1/2 configuration through kernel hint - hint.pcm.<unit>.dac="val" 172124582Sobrien * 173123474Swpaul * 0 = Enable both DACs - Default 174124582Sobrien * 1 = Enable single DAC (DAC1) 175124582Sobrien * 2 = Enable single DAC (DAC2) 176123474Swpaul * 3 = Enable both DACs, swap position (DAC2 comes first instead of DAC1) 177123474Swpaul */ 178123474Swpaul#define ES_DEFAULT_DAC_CFG 0 179123474Swpaul 180123474Swpaulstruct es_info { 181123474Swpaul bus_space_tag_t st; 182123474Swpaul bus_space_handle_t sh; 183123474Swpaul bus_dma_tag_t parent_dmat; 184123474Swpaul 185123474Swpaul struct resource *reg, *irq; 186123474Swpaul int regtype, regid, irqid; 187123474Swpaul void *ih; 188123474Swpaul 189123474Swpaul device_t dev; 190123474Swpaul int num; 191123474Swpaul unsigned int bufsz, blkcnt; 192123474Swpaul 193123507Swpaul /* Contents of board's registers */ 194123507Swpaul uint32_t ctrl; 195123507Swpaul uint32_t sctrl; 196123507Swpaul uint32_t escfg; 197123507Swpaul struct es_chinfo ch[ES_NCHANS]; 198123507Swpaul struct mtx *lock; 199123507Swpaul struct callout poll_timer; 200125551Swpaul int poll_ticks, polling; 201141524Swpaul}; 202125551Swpaul 203125551Swpaul#define ES_LOCK(sc) snd_mtxlock((sc)->lock) 204125551Swpaul#define ES_UNLOCK(sc) snd_mtxunlock((sc)->lock) 205125551Swpaul#define ES_LOCK_ASSERT(sc) snd_mtxassert((sc)->lock) 206125551Swpaul 207125551Swpaul/* prototypes */ 208125551Swpaulstatic void es_intr(void *); 209125551Swpaulstatic uint32_t es1371_wait_src_ready(struct es_info *); 210125551Swpaulstatic void es1371_src_write(struct es_info *, 211125551Swpaul unsigned short, unsigned short); 212125551Swpaulstatic unsigned int es1371_adc_rate(struct es_info *, unsigned int, int); 213125551Swpaulstatic unsigned int es1371_dac_rate(struct es_info *, unsigned int, int); 214125551Swpaulstatic int es1371_init(struct es_info *); 215125551Swpaulstatic int es1370_init(struct es_info *); 216125551Swpaulstatic int es1370_wrcodec(struct es_info *, unsigned char, unsigned char); 217125551Swpaul 218125551Swpaulstatic uint32_t es_fmt[] = { 219125551Swpaul AFMT_U8, 220125551Swpaul AFMT_STEREO | AFMT_U8, 221125551Swpaul AFMT_S16_LE, 222125551Swpaul AFMT_STEREO | AFMT_S16_LE, 223125551Swpaul 0 224125551Swpaul}; 225125551Swpaulstatic struct pcmchan_caps es_caps = {4000, 48000, es_fmt, 0}; 226125551Swpaul 227125551Swpaulstatic const struct { 228125551Swpaul unsigned volidx:4; 229125551Swpaul unsigned left:4; 230125551Swpaul unsigned right:4; 231125551Swpaul unsigned stereo:1; 232125551Swpaul unsigned recmask:13; 233125551Swpaul unsigned avail:1; 234125551Swpaul} mixtable[SOUND_MIXER_NRDEVICES] = { 235125551Swpaul [SOUND_MIXER_VOLUME] = { 0, 0x0, 0x1, 1, 0x1f7f, 1 }, 236125551Swpaul [SOUND_MIXER_PCM] = { 1, 0x2, 0x3, 1, 0x0400, 1 }, 237125551Swpaul [SOUND_MIXER_SYNTH] = { 2, 0x4, 0x5, 1, 0x0060, 1 }, 238125551Swpaul [SOUND_MIXER_CD] = { 3, 0x6, 0x7, 1, 0x0006, 1 }, 239125551Swpaul [SOUND_MIXER_LINE] = { 4, 0x8, 0x9, 1, 0x0018, 1 }, 240125551Swpaul [SOUND_MIXER_LINE1] = { 5, 0xa, 0xb, 1, 0x1800, 1 }, 241125860Swpaul [SOUND_MIXER_LINE2] = { 6, 0xc, 0x0, 0, 0x0100, 1 }, 242125551Swpaul [SOUND_MIXER_LINE3] = { 7, 0xd, 0x0, 0, 0x0200, 1 }, 243141524Swpaul [SOUND_MIXER_MIC] = { 8, 0xe, 0x0, 0, 0x0001, 1 }, 244141524Swpaul [SOUND_MIXER_OGAIN] = { 9, 0xf, 0x0, 0, 0x0000, 1 } 245125551Swpaul}; 246125551Swpaul 247125551Swpaulstatic __inline uint32_t 248125551Swpaules_rd(struct es_info *es, int regno, int size) 249125551Swpaul{ 250125551Swpaul switch (size) { 251125551Swpaul case 1: 252125551Swpaul return (bus_space_read_1(es->st, es->sh, regno)); 253125551Swpaul case 2: 254125551Swpaul return (bus_space_read_2(es->st, es->sh, regno)); 255125551Swpaul case 4: 256125551Swpaul return (bus_space_read_4(es->st, es->sh, regno)); 257125551Swpaul default: 258125551Swpaul return (0xFFFFFFFF); 259125551Swpaul } 260125551Swpaul} 261125551Swpaul 262125551Swpaulstatic __inline void 263125551Swpaules_wr(struct es_info *es, int regno, uint32_t data, int size) 264125551Swpaul{ 265125551Swpaul 266125551Swpaul switch (size) { 267125551Swpaul case 1: 268125551Swpaul bus_space_write_1(es->st, es->sh, regno, data); 269125551Swpaul break; 270125551Swpaul case 2: 271125551Swpaul bus_space_write_2(es->st, es->sh, regno, data); 272125551Swpaul break; 273125551Swpaul case 4: 274125551Swpaul bus_space_write_4(es->st, es->sh, regno, data); 275125551Swpaul break; 276125551Swpaul } 277125551Swpaul} 278125551Swpaul 279125551Swpaul/* -------------------------------------------------------------------- */ 280128229Swpaul/* The es1370 mixer interface */ 281125551Swpaul 282125551Swpaulstatic int 283125551Swpaules1370_mixinit(struct snd_mixer *m) 284125551Swpaul{ 285125551Swpaul struct es_info *es; 286125551Swpaul int i; 287125551Swpaul uint32_t v; 288125551Swpaul 289125551Swpaul es = mix_getdevinfo(m); 290125551Swpaul v = 0; 291128229Swpaul for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) { 292128229Swpaul if (mixtable[i].avail) 293128229Swpaul v |= (1 << i); 294128229Swpaul } 295128449Swpaul /* 296128229Swpaul * Each DAC1/2 for ES1370 can be controlled independently 297128229Swpaul * DAC1 = controlled by synth 298128295Swpaul * DAC2 = controlled by pcm 299128229Swpaul * This is indeed can confuse user if DAC1 become primary playback 300128229Swpaul * channel. Try to be smart and combine both if necessary. 301128229Swpaul */ 302128229Swpaul if (ES_SINGLE_PCM_MIX(es->escfg)) 303125551Swpaul v &= ~(1 << SOUND_MIXER_SYNTH); 304125551Swpaul mix_setdevs(m, v); 305125551Swpaul v = 0; 306125551Swpaul for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) { 307125551Swpaul if (mixtable[i].recmask) 308125551Swpaul v |= (1 << i); 309125551Swpaul } 310125551Swpaul if (ES_SINGLE_PCM_MIX(es->escfg)) /* ditto */ 311125551Swpaul v &= ~(1 << SOUND_MIXER_SYNTH); 312125551Swpaul mix_setrecdevs(m, v); 313125551Swpaul return (0); 314125551Swpaul} 315125551Swpaul 316126620Swpaulstatic int 317126620Swpaules1370_mixset(struct snd_mixer *m, unsigned dev, unsigned left, unsigned right) 318126620Swpaul{ 319126620Swpaul struct es_info *es; 320126620Swpaul int l, r, rl, rr, set_dac1; 321126620Swpaul 322126620Swpaul if (!mixtable[dev].avail) 323126620Swpaul return (-1); 324126620Swpaul l = left; 325126620Swpaul r = (mixtable[dev].stereo) ? right : l; 326126620Swpaul if (mixtable[dev].left == 0xf) 327126620Swpaul rl = (l < 2) ? 0x80 : 7 - (l - 2) / 14; 328126620Swpaul else 329125551Swpaul rl = (l < 10) ? 0x80 : 15 - (l - 10) / 6; 330125551Swpaul es = mix_getdevinfo(m); 331125551Swpaul ES_LOCK(es); 332126620Swpaul if (dev == SOUND_MIXER_PCM && (ES_SINGLE_PCM_MIX(es->escfg)) && 333126620Swpaul ES_DAC1_ENABLED(es->escfg)) 334126620Swpaul set_dac1 = 1; 335126620Swpaul else 336125551Swpaul set_dac1 = 0; 337125551Swpaul if (mixtable[dev].stereo) { 338125551Swpaul rr = (r < 10) ? 0x80 : 15 - (r - 10) / 6; 339125551Swpaul es1370_wrcodec(es, mixtable[dev].right, rr); 340126620Swpaul if (set_dac1 && mixtable[SOUND_MIXER_SYNTH].stereo) 341126620Swpaul es1370_wrcodec(es, 342126620Swpaul mixtable[SOUND_MIXER_SYNTH].right, rr); 343126620Swpaul } 344126620Swpaul es1370_wrcodec(es, mixtable[dev].left, rl); 345125551Swpaul if (set_dac1) 346125551Swpaul es1370_wrcodec(es, mixtable[SOUND_MIXER_SYNTH].left, rl); 347125551Swpaul ES_UNLOCK(es); 348125551Swpaul 349125551Swpaul return (l | (r << 8)); 350125551Swpaul} 351125551Swpaul 352125551Swpaulstatic int 353125551Swpaules1370_mixsetrecsrc(struct snd_mixer *m, uint32_t src) 354144888Swpaul{ 355125551Swpaul struct es_info *es; 356125551Swpaul int i, j = 0; 357125551Swpaul 358125551Swpaul es = mix_getdevinfo(m); 359125551Swpaul if (src == 0) src = 1 << SOUND_MIXER_MIC; 360125551Swpaul src &= mix_getrecdevs(m); 361140827Swpaul for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) 362125551Swpaul if ((src & (1 << i)) != 0) j |= mixtable[i].recmask; 363125551Swpaul 364125551Swpaul ES_LOCK(es); 365127552Swpaul if ((src & (1 << SOUND_MIXER_PCM)) && ES_SINGLE_PCM_MIX(es->escfg) && 366125551Swpaul ES_DAC1_ENABLED(es->escfg)) 367125551Swpaul j |= mixtable[SOUND_MIXER_SYNTH].recmask; 368126620Swpaul es1370_wrcodec(es, CODEC_LIMIX1, j & 0x55); 369126620Swpaul es1370_wrcodec(es, CODEC_RIMIX1, j & 0xaa); 370125551Swpaul es1370_wrcodec(es, CODEC_LIMIX2, (j >> 8) & 0x17); 371125551Swpaul es1370_wrcodec(es, CODEC_RIMIX2, (j >> 8) & 0x0f); 372125551Swpaul es1370_wrcodec(es, CODEC_OMIX1, 0x7f); 373125551Swpaul es1370_wrcodec(es, CODEC_OMIX2, 0x3f); 374125551Swpaul ES_UNLOCK(es); 375125551Swpaul 376125551Swpaul return (src); 377125551Swpaul} 378125551Swpaul 379125551Swpaulstatic kobj_method_t es1370_mixer_methods[] = { 380125551Swpaul KOBJMETHOD(mixer_init, es1370_mixinit), 381125551Swpaul KOBJMETHOD(mixer_set, es1370_mixset), 382125551Swpaul KOBJMETHOD(mixer_setrecsrc, es1370_mixsetrecsrc), 383126620Swpaul { 0, 0 } 384126620Swpaul}; 385126620SwpaulMIXER_DECLARE(es1370_mixer); 386126620Swpaul 387125551Swpaul/* -------------------------------------------------------------------- */ 388125551Swpaul 389125551Swpaulstatic int 390125551Swpaules1370_wrcodec(struct es_info *es, unsigned char i, unsigned char data) 391125551Swpaul{ 392126620Swpaul unsigned int t; 393126620Swpaul 394126620Swpaul ES_LOCK_ASSERT(es); 395125551Swpaul 396125551Swpaul for (t = 0; t < 0x1000; t++) { 397125860Swpaul if ((es_rd(es, ES1370_REG_STATUS, 4) & 398125860Swpaul STAT_CSTAT) == 0) { 399123474Swpaul es_wr(es, ES1370_REG_CODEC, 400123474Swpaul ((unsigned short)i << CODEC_INDEX_SHIFT) | data, 2); 401123474Swpaul return (0); 402123474Swpaul } 403123474Swpaul DELAY(1); 404123474Swpaul } 405123474Swpaul device_printf(es->dev, "%s: timed out\n", __func__); 406123474Swpaul return (-1); 407123474Swpaul} 408123474Swpaul 409123474Swpaul/* -------------------------------------------------------------------- */ 410123474Swpaul 411123474Swpaul/* channel interface */ 412123474Swpaulstatic void * 413123474Swpauleschan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, 414123474Swpaul struct pcm_channel *c, int dir) 415123474Swpaul{ 416123474Swpaul struct es_info *es = devinfo; 417123474Swpaul struct es_chinfo *ch; 418123507Swpaul uint32_t index; 419123474Swpaul 420123474Swpaul ES_LOCK(es); 421123474Swpaul 422123474Swpaul if (dir == PCMDIR_PLAY) { 423123474Swpaul index = ES_GP(es->escfg); 424123474Swpaul es->escfg = ES_SET_GP(es->escfg, index + 1); 425123474Swpaul if (index == 0) 426123474Swpaul index = ES_DAC_FIRST(es->escfg); 427123474Swpaul else if (index == 1) 428123474Swpaul index = ES_DAC_SECOND(es->escfg); 429123474Swpaul else { 430123474Swpaul device_printf(es->dev, 431144240Swpaul "Invalid ES_GP index: %d\n", index); 432123474Swpaul ES_UNLOCK(es); 433144240Swpaul return (NULL); 434123474Swpaul } 435123474Swpaul if (!(index == ES_DAC1 || index == ES_DAC2)) { 436123474Swpaul device_printf(es->dev, "Unknown DAC: %d\n", index + 1); 437123474Swpaul ES_UNLOCK(es); 438123474Swpaul return (NULL); 439123474Swpaul } 440123474Swpaul if (es->ch[index].channel != NULL) { 441123474Swpaul device_printf(es->dev, "DAC%d already initialized!\n", 442125551Swpaul index + 1); 443123474Swpaul ES_UNLOCK(es); 444125551Swpaul return (NULL); 445125551Swpaul } 446125551Swpaul } else 447125551Swpaul index = ES_ADC; 448125551Swpaul 449125551Swpaul ch = &es->ch[index]; 450125551Swpaul ch->index = index; 451125551Swpaul ch->num = es->num++; 452125551Swpaul ch->caps = es_caps; 453125551Swpaul if (ES_IS_ES1370(es->escfg)) { 454125551Swpaul if (ch->index == ES_DAC1) { 455125551Swpaul ch->caps.maxspeed = ES1370_DAC1_MAXSPEED; 456125551Swpaul ch->caps.minspeed = ES1370_DAC1_MINSPEED; 457125551Swpaul } else { 458125551Swpaul uint32_t fixed_rate = ES_FIXED_RATE(es->escfg); 459125551Swpaul if (!(fixed_rate < es_caps.minspeed || 460125551Swpaul fixed_rate > es_caps.maxspeed)) { 461125551Swpaul ch->caps.maxspeed = fixed_rate; 462125551Swpaul ch->caps.minspeed = fixed_rate; 463125551Swpaul } 464125551Swpaul } 465125551Swpaul } 466125551Swpaul ch->parent = es; 467125551Swpaul ch->channel = c; 468125551Swpaul ch->buffer = b; 469125551Swpaul ch->bufsz = es->bufsz; 470125551Swpaul ch->blkcnt = es->blkcnt; 471125551Swpaul ch->blksz = ch->bufsz / ch->blkcnt; 472125551Swpaul ch->dir = dir; 473125551Swpaul ES_UNLOCK(es); 474125551Swpaul if (sndbuf_alloc(ch->buffer, es->parent_dmat, 0, ch->bufsz) != 0) 475125551Swpaul return (NULL); 476125551Swpaul ES_LOCK(es); 477125551Swpaul if (dir == PCMDIR_PLAY) { 478125551Swpaul if (ch->index == ES_DAC1) { 479125551Swpaul es_wr(es, ES1370_REG_MEMPAGE, 480125551Swpaul ES1370_REG_DAC1_FRAMEADR >> 8, 1); 481125551Swpaul es_wr(es, ES1370_REG_DAC1_FRAMEADR & 0xff, 482125551Swpaul sndbuf_getbufaddr(ch->buffer), 4); 483125551Swpaul es_wr(es, ES1370_REG_DAC1_FRAMECNT & 0xff, 484125551Swpaul (ch->bufsz >> 2) - 1, 4); 485125551Swpaul } else { 486125551Swpaul es_wr(es, ES1370_REG_MEMPAGE, 487125551Swpaul ES1370_REG_DAC2_FRAMEADR >> 8, 1); 488125551Swpaul es_wr(es, ES1370_REG_DAC2_FRAMEADR & 0xff, 489125551Swpaul sndbuf_getbufaddr(ch->buffer), 4); 490125551Swpaul es_wr(es, ES1370_REG_DAC2_FRAMECNT & 0xff, 491125551Swpaul (ch->bufsz >> 2) - 1, 4); 492125551Swpaul } 493125551Swpaul } else { 494125551Swpaul es_wr(es, ES1370_REG_MEMPAGE, ES1370_REG_ADC_FRAMEADR >> 8, 1); 495125551Swpaul es_wr(es, ES1370_REG_ADC_FRAMEADR & 0xff, 496125551Swpaul sndbuf_getbufaddr(ch->buffer), 4); 497125551Swpaul es_wr(es, ES1370_REG_ADC_FRAMECNT & 0xff, 498140751Swpaul (ch->bufsz >> 2) - 1, 4); 499140751Swpaul } 500140751Swpaul ES_UNLOCK(es); 501140751Swpaul return (ch); 502140751Swpaul} 503140751Swpaul 504140751Swpaulstatic int 505140751Swpauleschan_setformat(kobj_t obj, void *data, uint32_t format) 506140751Swpaul{ 507141524Swpaul struct es_chinfo *ch = data; 508141524Swpaul struct es_info *es = ch->parent; 509141524Swpaul 510141524Swpaul ES_LOCK(es); 511141524Swpaul if (ch->dir == PCMDIR_PLAY) { 512141524Swpaul if (ch->index == ES_DAC1) { 513141524Swpaul es->sctrl &= ~SCTRL_P1FMT; 514141524Swpaul if (format & AFMT_S16_LE) 515140751Swpaul es->sctrl |= SCTRL_P1SEB; 516140751Swpaul if (format & AFMT_STEREO) 517140751Swpaul es->sctrl |= SCTRL_P1SMB; 518140751Swpaul } else { 519141524Swpaul es->sctrl &= ~SCTRL_P2FMT; 520141524Swpaul if (format & AFMT_S16_LE) 521141524Swpaul es->sctrl |= SCTRL_P2SEB; 522141524Swpaul if (format & AFMT_STEREO) 523141524Swpaul es->sctrl |= SCTRL_P2SMB; 524141524Swpaul } 525141524Swpaul } else { 526140751Swpaul es->sctrl &= ~SCTRL_R1FMT; 527140751Swpaul if (format & AFMT_S16_LE) 528140751Swpaul es->sctrl |= SCTRL_R1SEB; 529140751Swpaul if (format & AFMT_STEREO) 530140751Swpaul es->sctrl |= SCTRL_R1SMB; 531140751Swpaul } 532140751Swpaul es_wr(es, ES1370_REG_SERIAL_CONTROL, es->sctrl, 4); 533140751Swpaul ES_UNLOCK(es); 534140751Swpaul ch->fmt = format; 535140751Swpaul return (0); 536140751Swpaul} 537140751Swpaul 538140751Swpaulstatic int 539140751Swpauleschan1370_setspeed(kobj_t obj, void *data, uint32_t speed) 540140751Swpaul{ 541140751Swpaul struct es_chinfo *ch = data; 542125551Swpaul struct es_info *es = ch->parent; 543125551Swpaul 544125551Swpaul ES_LOCK(es); 545125551Swpaul /* Fixed rate , do nothing. */ 546141524Swpaul if (ch->caps.minspeed == ch->caps.maxspeed) 547125551Swpaul return (ch->caps.maxspeed); 548125551Swpaul if (speed < ch->caps.minspeed) 549125551Swpaul speed = ch->caps.minspeed; 550125551Swpaul if (speed > ch->caps.maxspeed) 551125551Swpaul speed = ch->caps.maxspeed; 552125551Swpaul if (ch->index == ES_DAC1) { 553125551Swpaul /* 554125551Swpaul * DAC1 does not support continuous rate settings. 555141524Swpaul * Pick the nearest and use it since FEEDER_RATE will 556125551Swpaul * do the the proper conversion for us. 557125551Swpaul */ 558125551Swpaul es->ctrl &= ~CTRL_WTSRSEL; 559125551Swpaul if (speed < 8268) { 560125551Swpaul speed = 5512; 561125551Swpaul es->ctrl |= 0 << CTRL_SH_WTSRSEL; 562125551Swpaul } else if (speed < 16537) { 563125551Swpaul speed = 11025; 564125551Swpaul es->ctrl |= 1 << CTRL_SH_WTSRSEL; 565125551Swpaul } else if (speed < 33075) { 566125551Swpaul speed = 22050; 567125551Swpaul es->ctrl |= 2 << CTRL_SH_WTSRSEL; 568125551Swpaul } else { 569140751Swpaul speed = 44100; 570125551Swpaul es->ctrl |= 3 << CTRL_SH_WTSRSEL; 571125551Swpaul } 572125551Swpaul } else { 573125551Swpaul es->ctrl &= ~CTRL_PCLKDIV; 574125551Swpaul es->ctrl |= DAC2_SRTODIV(speed) << CTRL_SH_PCLKDIV; 575140751Swpaul } 576140751Swpaul es_wr(es, ES1370_REG_CONTROL, es->ctrl, 4); 577140751Swpaul ES_UNLOCK(es); 578140751Swpaul return (speed); 579140751Swpaul} 580140751Swpaul 581140751Swpaulstatic int 582140751Swpauleschan1371_setspeed(kobj_t obj, void *data, uint32_t speed) 583142311Swpaul{ 584142311Swpaul struct es_chinfo *ch = data; 585142311Swpaul struct es_info *es = ch->parent; 586142311Swpaul uint32_t i; 587142311Swpaul int delta; 588142311Swpaul 589142311Swpaul ES_LOCK(es); 590142311Swpaul if (ch->dir == PCMDIR_PLAY) 591142311Swpaul i = es1371_dac_rate(es, speed, ch->index); /* play */ 592142311Swpaul else 593142311Swpaul i = es1371_adc_rate(es, speed, ch->index); /* record */ 594142311Swpaul ES_UNLOCK(es); 595142311Swpaul delta = (speed > i) ? (speed - i) : (i - speed); 596142311Swpaul if (delta < 2) 597142311Swpaul return (speed); 598142311Swpaul return (i); 599142311Swpaul} 600142311Swpaul 601142311Swpaulstatic int 602142311Swpauleschan_setfragments(kobj_t obj, void *data, uint32_t blksz, uint32_t blkcnt) 603140751Swpaul{ 604140751Swpaul struct es_chinfo *ch = data; 605140751Swpaul struct es_info *es = ch->parent; 606140751Swpaul 607140751Swpaul blksz &= ES_BLK_ALIGN; 608140751Swpaul 609140751Swpaul if (blksz > (sndbuf_getmaxsize(ch->buffer) / ES_DMA_SEGS_MIN)) 610140751Swpaul blksz = sndbuf_getmaxsize(ch->buffer) / ES_DMA_SEGS_MIN; 611140751Swpaul if (blksz < ES_BLK_MIN) 612140751Swpaul blksz = ES_BLK_MIN; 613140751Swpaul if (blkcnt > ES_DMA_SEGS_MAX) 614140751Swpaul blkcnt = ES_DMA_SEGS_MAX; 615140751Swpaul if (blkcnt < ES_DMA_SEGS_MIN) 616140751Swpaul blkcnt = ES_DMA_SEGS_MIN; 617140751Swpaul 618140751Swpaul while ((blksz * blkcnt) > sndbuf_getmaxsize(ch->buffer)) { 619140751Swpaul if ((blkcnt >> 1) >= ES_DMA_SEGS_MIN) 620140751Swpaul blkcnt >>= 1; 621140751Swpaul else if ((blksz >> 1) >= ES_BLK_MIN) 622140751Swpaul blksz >>= 1; 623140751Swpaul else 624140751Swpaul break; 625140751Swpaul } 626140751Swpaul 627140751Swpaul if ((sndbuf_getblksz(ch->buffer) != blksz || 628140751Swpaul sndbuf_getblkcnt(ch->buffer) != blkcnt) && 629140751Swpaul sndbuf_resize(ch->buffer, blkcnt, blksz) != 0) 630140751Swpaul device_printf(es->dev, "%s: failed blksz=%u blkcnt=%u\n", 631140751Swpaul __func__, blksz, blkcnt); 632140751Swpaul 633140751Swpaul ch->bufsz = sndbuf_getsize(ch->buffer); 634140751Swpaul ch->blksz = sndbuf_getblksz(ch->buffer); 635140751Swpaul ch->blkcnt = sndbuf_getblkcnt(ch->buffer); 636140751Swpaul 637140751Swpaul return (1); 638140751Swpaul} 639140751Swpaul 640140751Swpaulstatic int 641140751Swpauleschan_setblocksize(kobj_t obj, void *data, uint32_t blksz) 642140751Swpaul{ 643140751Swpaul struct es_chinfo *ch = data; 644140751Swpaul struct es_info *es = ch->parent; 645140751Swpaul 646140751Swpaul eschan_setfragments(obj, data, blksz, es->blkcnt); 647140751Swpaul 648140751Swpaul return (ch->blksz); 649140751Swpaul} 650140751Swpaul 651140751Swpaul#define es_chan_active(es) ((es)->ch[ES_DAC1].active + \ 652140751Swpaul (es)->ch[ES_DAC2].active + \ 653140751Swpaul (es)->ch[ES_ADC].active) 654140751Swpaul 655140751Swpaulstatic __inline int 656140751Swpaules_poll_channel(struct es_chinfo *ch) 657140751Swpaul{ 658140751Swpaul struct es_info *es; 659144240Swpaul uint32_t sz, delta; 660140751Swpaul uint32_t reg, ptr; 661140751Swpaul 662140751Swpaul if (ch == NULL || ch->channel == NULL || ch->active == 0) 663140751Swpaul return (0); 664140751Swpaul 665140751Swpaul es = ch->parent; 666140751Swpaul if (ch->dir == PCMDIR_PLAY) { 667140751Swpaul if (ch->index == ES_DAC1) 668140751Swpaul reg = ES1370_REG_DAC1_FRAMECNT; 669140751Swpaul else 670140751Swpaul reg = ES1370_REG_DAC2_FRAMECNT; 671140751Swpaul } else 672140751Swpaul reg = ES1370_REG_ADC_FRAMECNT; 673140751Swpaul sz = ch->blksz * ch->blkcnt; 674140751Swpaul es_wr(es, ES1370_REG_MEMPAGE, reg >> 8, 4); 675140751Swpaul ptr = es_rd(es, reg & 0x000000ff, 4) >> 16; 676140751Swpaul ptr <<= 2; 677140751Swpaul ch->ptr = ptr; 678140751Swpaul ptr %= sz; 679140751Swpaul ptr &= ~(ch->blksz - 1); 680140751Swpaul delta = (sz + ptr - ch->prevptr) % sz; 681140751Swpaul 682140751Swpaul if (delta < ch->blksz) 683140751Swpaul return (0); 684140751Swpaul 685140751Swpaul ch->prevptr = ptr; 686140751Swpaul 687140751Swpaul return (1); 688140751Swpaul} 689140751Swpaul 690140751Swpaulstatic void 691140751Swpaules_poll_callback(void *arg) 692140751Swpaul{ 693140751Swpaul struct es_info *es = arg; 694140751Swpaul uint32_t trigger = 0; 695140751Swpaul int i; 696140751Swpaul 697140751Swpaul if (es == NULL) 698140751Swpaul return; 699140751Swpaul 700140751Swpaul ES_LOCK(es); 701140751Swpaul if (es->polling == 0 || es_chan_active(es) == 0) { 702140751Swpaul ES_UNLOCK(es); 703140751Swpaul return; 704140751Swpaul } 705140751Swpaul 706140751Swpaul for (i = 0; i < ES_NCHANS; i++) { 707140751Swpaul if (es_poll_channel(&es->ch[i]) != 0) 708140751Swpaul trigger |= 1 << i; 709140751Swpaul } 710140751Swpaul 711140751Swpaul /* XXX */ 712140751Swpaul callout_reset(&es->poll_timer, 1/*es->poll_ticks*/, 713140751Swpaul es_poll_callback, es); 714140751Swpaul 715140751Swpaul ES_UNLOCK(es); 716140751Swpaul 717140751Swpaul for (i = 0; i < ES_NCHANS; i++) { 718140751Swpaul if (trigger & (1 << i)) 719140751Swpaul chn_intr(es->ch[i].channel); 720140751Swpaul } 721140751Swpaul} 722140751Swpaul 723140751Swpaulstatic int 724140751Swpauleschan_trigger(kobj_t obj, void *data, int go) 725140751Swpaul{ 726140751Swpaul struct es_chinfo *ch = data; 727140751Swpaul struct es_info *es = ch->parent; 728140751Swpaul uint32_t cnt, b = 0; 729140751Swpaul 730140751Swpaul if (go == PCMTRIG_EMLDMAWR || go == PCMTRIG_EMLDMARD) 731140751Swpaul return (0); 732140751Swpaul 733140751Swpaul ES_LOCK(es); 734140751Swpaul cnt = (ch->blksz / sndbuf_getbps(ch->buffer)) - 1; 735140751Swpaul if (ch->fmt & AFMT_16BIT) 736140751Swpaul b |= 0x02; 737140751Swpaul if (ch->fmt & AFMT_STEREO) 738140751Swpaul b |= 0x01; 739140751Swpaul if (ch->dir == PCMDIR_PLAY) { 740140751Swpaul if (go == PCMTRIG_START) { 741140751Swpaul if (ch->index == ES_DAC1) { 742140751Swpaul es->ctrl |= CTRL_DAC1_EN; 743140751Swpaul es->sctrl &= ~(SCTRL_P1LOOPSEL | 744140751Swpaul SCTRL_P1PAUSE | SCTRL_P1SCTRLD); 745140751Swpaul if (es->polling == 0) 746140751Swpaul es->sctrl |= SCTRL_P1INTEN; 747140751Swpaul else 748140751Swpaul es->sctrl &= ~SCTRL_P1INTEN; 749140751Swpaul es->sctrl |= b; 750140751Swpaul es_wr(es, ES1370_REG_DAC1_SCOUNT, cnt, 4); 751140751Swpaul /* start at beginning of buffer */ 752142311Swpaul es_wr(es, ES1370_REG_MEMPAGE, 753142311Swpaul ES1370_REG_DAC1_FRAMECNT >> 8, 4); 754142311Swpaul es_wr(es, ES1370_REG_DAC1_FRAMECNT & 0xff, 755142311Swpaul (ch->bufsz >> 2) - 1, 4); 756142311Swpaul } else { 757142311Swpaul es->ctrl |= CTRL_DAC2_EN; 758142311Swpaul es->sctrl &= ~(SCTRL_P2ENDINC | SCTRL_P2STINC | 759142497Swpaul SCTRL_P2LOOPSEL | SCTRL_P2PAUSE | 760142497Swpaul SCTRL_P2DACSEN); 761142497Swpaul if (es->polling == 0) 762142497Swpaul es->sctrl |= SCTRL_P2INTEN; 763142497Swpaul else 764142497Swpaul es->sctrl &= ~SCTRL_P2INTEN; 765142497Swpaul es->sctrl |= (b << 2) | 766142497Swpaul ((((b >> 1) & 1) + 1) << SCTRL_SH_P2ENDINC); 767142497Swpaul es_wr(es, ES1370_REG_DAC2_SCOUNT, cnt, 4); 768142311Swpaul /* start at beginning of buffer */ 769142311Swpaul es_wr(es, ES1370_REG_MEMPAGE, 770142497Swpaul ES1370_REG_DAC2_FRAMECNT >> 8, 4); 771142497Swpaul es_wr(es, ES1370_REG_DAC2_FRAMECNT & 0xff, 772142497Swpaul (ch->bufsz >> 2) - 1, 4); 773142497Swpaul } 774142497Swpaul } else 775142497Swpaul es->ctrl &= ~((ch->index == ES_DAC1) ? 776142497Swpaul CTRL_DAC1_EN : CTRL_DAC2_EN); 777142497Swpaul } else { 778142497Swpaul if (go == PCMTRIG_START) { 779142497Swpaul es->ctrl |= CTRL_ADC_EN; 780140751Swpaul es->sctrl &= ~SCTRL_R1LOOPSEL; 781140751Swpaul if (es->polling == 0) 782140751Swpaul es->sctrl |= SCTRL_R1INTEN; 783140751Swpaul else 784140751Swpaul es->sctrl &= ~SCTRL_R1INTEN; 785140751Swpaul es->sctrl |= b << 4; 786140751Swpaul es_wr(es, ES1370_REG_ADC_SCOUNT, cnt, 4); 787141524Swpaul /* start at beginning of buffer */ 788141524Swpaul es_wr(es, ES1370_REG_MEMPAGE, 789140751Swpaul ES1370_REG_ADC_FRAMECNT >> 8, 4); 790140751Swpaul es_wr(es, ES1370_REG_ADC_FRAMECNT & 0xff, 791140751Swpaul (ch->bufsz >> 2) - 1, 4); 792140751Swpaul } else 793140751Swpaul es->ctrl &= ~CTRL_ADC_EN; 794140751Swpaul } 795140751Swpaul es_wr(es, ES1370_REG_SERIAL_CONTROL, es->sctrl, 4); 796140751Swpaul es_wr(es, ES1370_REG_CONTROL, es->ctrl, 4); 797140751Swpaul if (go == PCMTRIG_START) { 798140751Swpaul if (es->polling != 0) { 799140751Swpaul ch->ptr = 0; 800140751Swpaul ch->prevptr = 0; 801140751Swpaul if (es_chan_active(es) == 0) { 802140751Swpaul es->poll_ticks = 1; 803140751Swpaul callout_reset(&es->poll_timer, 1, 804140751Swpaul es_poll_callback, es); 805140751Swpaul } 806140751Swpaul } 807140751Swpaul ch->active = 1; 808140751Swpaul } else { 809140751Swpaul ch->active = 0; 810140751Swpaul if (es->polling != 0) { 811144888Swpaul if (es_chan_active(es) == 0) { 812141524Swpaul callout_stop(&es->poll_timer); 813144888Swpaul es->poll_ticks = 1; 814142311Swpaul } 815141524Swpaul } 816140751Swpaul } 817140751Swpaul ES_UNLOCK(es); 818140751Swpaul return (0); 819140751Swpaul} 820140751Swpaul 821140751Swpaulstatic int 822140751Swpauleschan_getptr(kobj_t obj, void *data) 823140751Swpaul{ 824140751Swpaul struct es_chinfo *ch = data; 825140751Swpaul struct es_info *es = ch->parent; 826140751Swpaul uint32_t reg, cnt; 827140751Swpaul 828140751Swpaul ES_LOCK(es); 829140751Swpaul if (es->polling != 0) 830140751Swpaul cnt = ch->ptr; 831140751Swpaul else { 832140751Swpaul if (ch->dir == PCMDIR_PLAY) { 833140751Swpaul if (ch->index == ES_DAC1) 834142311Swpaul reg = ES1370_REG_DAC1_FRAMECNT; 835142311Swpaul else 836142311Swpaul reg = ES1370_REG_DAC2_FRAMECNT; 837142311Swpaul } else 838142311Swpaul reg = ES1370_REG_ADC_FRAMECNT; 839142311Swpaul es_wr(es, ES1370_REG_MEMPAGE, reg >> 8, 4); 840142311Swpaul cnt = es_rd(es, reg & 0x000000ff, 4) >> 16; 841142311Swpaul /* cnt is longwords */ 842142311Swpaul cnt <<= 2; 843142311Swpaul } 844142311Swpaul ES_UNLOCK(es); 845142311Swpaul 846142311Swpaul cnt &= ES_BLK_ALIGN; 847142311Swpaul 848142311Swpaul return (cnt); 849142311Swpaul} 850140751Swpaul 851140751Swpaulstatic struct pcmchan_caps * 852140751Swpauleschan_getcaps(kobj_t obj, void *data) 853140751Swpaul{ 854140751Swpaul struct es_chinfo *ch = data; 855142311Swpaul 856140751Swpaul return (&ch->caps); 857140751Swpaul} 858140751Swpaul 859141524Swpaulstatic kobj_method_t eschan1370_methods[] = { 860140751Swpaul KOBJMETHOD(channel_init, eschan_init), 861140751Swpaul KOBJMETHOD(channel_setformat, eschan_setformat), 862140751Swpaul KOBJMETHOD(channel_setspeed, eschan1370_setspeed), 863140751Swpaul KOBJMETHOD(channel_setblocksize, eschan_setblocksize), 864140751Swpaul KOBJMETHOD(channel_setfragments, eschan_setfragments), 865140751Swpaul KOBJMETHOD(channel_trigger, eschan_trigger), 866140751Swpaul KOBJMETHOD(channel_getptr, eschan_getptr), 867140751Swpaul KOBJMETHOD(channel_getcaps, eschan_getcaps), 868140751Swpaul { 0, 0 } 869140751Swpaul}; 870140751SwpaulCHANNEL_DECLARE(eschan1370); 871140751Swpaul 872125551Swpaulstatic kobj_method_t eschan1371_methods[] = { 873140751Swpaul KOBJMETHOD(channel_init, eschan_init), 874140751Swpaul KOBJMETHOD(channel_setformat, eschan_setformat), 875140751Swpaul KOBJMETHOD(channel_setspeed, eschan1371_setspeed), 876140751Swpaul KOBJMETHOD(channel_setblocksize, eschan_setblocksize), 877140751Swpaul KOBJMETHOD(channel_setfragments, eschan_setfragments), 878140751Swpaul KOBJMETHOD(channel_trigger, eschan_trigger), 879140751Swpaul KOBJMETHOD(channel_getptr, eschan_getptr), 880140751Swpaul KOBJMETHOD(channel_getcaps, eschan_getcaps), 881140751Swpaul { 0, 0 } 882140751Swpaul}; 883140751SwpaulCHANNEL_DECLARE(eschan1371); 884140751Swpaul 885140751Swpaul/* -------------------------------------------------------------------- */ 886140751Swpaul/* The interrupt handler */ 887140751Swpaulstatic void 888140751Swpaules_intr(void *p) 889140751Swpaul{ 890140751Swpaul struct es_info *es = p; 891140751Swpaul uint32_t intsrc, sctrl; 892140751Swpaul 893141524Swpaul ES_LOCK(es); 894140751Swpaul if (es->polling != 0) { 895140751Swpaul ES_UNLOCK(es); 896140751Swpaul return; 897140751Swpaul } 898140751Swpaul intsrc = es_rd(es, ES1370_REG_STATUS, 4); 899140751Swpaul if ((intsrc & STAT_INTR) == 0) { 900140751Swpaul ES_UNLOCK(es); 901142311Swpaul return; 902140751Swpaul } 903140751Swpaul 904140751Swpaul sctrl = es->sctrl; 905140751Swpaul if (intsrc & STAT_ADC) 906140751Swpaul sctrl &= ~SCTRL_R1INTEN; 907140751Swpaul if (intsrc & STAT_DAC1) 908140751Swpaul sctrl &= ~SCTRL_P1INTEN; 909140751Swpaul if (intsrc & STAT_DAC2) 910140751Swpaul sctrl &= ~SCTRL_P2INTEN; 911140751Swpaul 912140751Swpaul es_wr(es, ES1370_REG_SERIAL_CONTROL, sctrl, 4); 913140751Swpaul es_wr(es, ES1370_REG_SERIAL_CONTROL, es->sctrl, 4); 914140751Swpaul ES_UNLOCK(es); 915140751Swpaul 916140751Swpaul if (intsrc & STAT_ADC) 917140751Swpaul chn_intr(es->ch[ES_ADC].channel); 918140751Swpaul if (intsrc & STAT_DAC1) 919140751Swpaul chn_intr(es->ch[ES_DAC1].channel); 920140751Swpaul if (intsrc & STAT_DAC2) 921140751Swpaul chn_intr(es->ch[ES_DAC2].channel); 922140751Swpaul} 923140751Swpaul 924140751Swpaul/* ES1370 specific */ 925140751Swpaulstatic int 926140751Swpaules1370_init(struct es_info *es) 927140751Swpaul{ 928125551Swpaul uint32_t fixed_rate; 929125551Swpaul int r, single_pcm; 930140751Swpaul 931140751Swpaul /* ES1370 default to fixed rate operation */ 932140751Swpaul if (resource_int_value(device_get_name(es->dev), 933125551Swpaul device_get_unit(es->dev), "fixed_rate", &r) == 0) { 934125551Swpaul fixed_rate = r; 935142311Swpaul if (fixed_rate) { 936144888Swpaul if (fixed_rate < es_caps.minspeed) 937142311Swpaul fixed_rate = es_caps.minspeed; 938141524Swpaul if (fixed_rate > es_caps.maxspeed) 939141524Swpaul fixed_rate = es_caps.maxspeed; 940141524Swpaul } 941142311Swpaul } else 942142311Swpaul fixed_rate = es_caps.maxspeed; 943142311Swpaul 944141524Swpaul if (resource_int_value(device_get_name(es->dev), 945140751Swpaul device_get_unit(es->dev), "single_pcm_mixer", &r) == 0) 946140751Swpaul single_pcm = (r != 0) ? 1 : 0; 947140751Swpaul else 948140751Swpaul single_pcm = 1; 949140751Swpaul 950140751Swpaul ES_LOCK(es); 951141524Swpaul if (ES_NUMPLAY(es->escfg) == 1) 952141524Swpaul single_pcm = 1; 953141524Swpaul /* This is ES1370 */ 954141524Swpaul es->escfg = ES_SET_IS_ES1370(es->escfg, 1); 955141524Swpaul if (fixed_rate) 956141524Swpaul es->escfg = ES_SET_FIXED_RATE(es->escfg, fixed_rate); 957140751Swpaul else { 958140751Swpaul es->escfg = ES_SET_FIXED_RATE(es->escfg, 0); 959140751Swpaul fixed_rate = DSP_DEFAULT_SPEED; 960140751Swpaul } 961140751Swpaul if (single_pcm) 962140751Swpaul es->escfg = ES_SET_SINGLE_PCM_MIX(es->escfg, 1); 963140751Swpaul else 964141524Swpaul es->escfg = ES_SET_SINGLE_PCM_MIX(es->escfg, 0); 965141524Swpaul es->ctrl = CTRL_CDC_EN | CTRL_JYSTK_EN | CTRL_SERR_DIS | 966141524Swpaul (DAC2_SRTODIV(fixed_rate) << CTRL_SH_PCLKDIV); 967140751Swpaul es->ctrl |= 3 << CTRL_SH_WTSRSEL; 968140751Swpaul es_wr(es, ES1370_REG_CONTROL, es->ctrl, 4); 969140751Swpaul 970140751Swpaul es->sctrl = 0; 971140751Swpaul es_wr(es, ES1370_REG_SERIAL_CONTROL, es->sctrl, 4); 972140751Swpaul 973140751Swpaul /* No RST, PD */ 974140751Swpaul es1370_wrcodec(es, CODEC_RES_PD, 3); 975140751Swpaul /* 976140751Swpaul * CODEC ADC and CODEC DAC use {LR,B}CLK2 and run off the LRCLK2 PLL; 977140751Swpaul * program DAC_SYNC=0! 978140751Swpaul */ 979140751Swpaul es1370_wrcodec(es, CODEC_CSEL, 0); 980140751Swpaul /* Recording source is mixer */ 981140751Swpaul es1370_wrcodec(es, CODEC_ADSEL, 0); 982140751Swpaul /* MIC amp is 0db */ 983140751Swpaul es1370_wrcodec(es, CODEC_MGAIN, 0); 984140751Swpaul ES_UNLOCK(es); 985140751Swpaul 986140751Swpaul return (0); 987144175Swpaul} 988144175Swpaul 989144175Swpaul/* ES1371 specific */ 990144175Swpaulint 991144175Swpaules1371_init(struct es_info *es) 992144175Swpaul{ 993144888Swpaul uint32_t cssr, devid, revid, subdev; 994125551Swpaul int idx; 995140751Swpaul 996140751Swpaul ES_LOCK(es); 997140751Swpaul /* This is NOT ES1370 */ 998140751Swpaul es->escfg = ES_SET_IS_ES1370(es->escfg, 0); 999140751Swpaul es->num = 0; 1000140751Swpaul es->sctrl = 0; 1001140751Swpaul cssr = 0; 1002140751Swpaul devid = pci_get_devid(es->dev); 1003140751Swpaul revid = pci_get_revid(es->dev); 1004140751Swpaul subdev = (pci_get_subdevice(es->dev) << 16) | 1005140751Swpaul pci_get_subvendor(es->dev); 1006140751Swpaul /* 1007140751Swpaul * Joyport blacklist. Either we're facing with broken hardware 1008140751Swpaul * or because this hardware need special (unknown) initialization 1009140751Swpaul * procedures. 1010140751Swpaul */ 1011140751Swpaul switch (subdev) { 1012140751Swpaul case 0x20001274: /* old Ensoniq */ 1013141524Swpaul es->ctrl = 0; 1014140751Swpaul break; 1015140751Swpaul default: 1016140751Swpaul es->ctrl = CTRL_JYSTK_EN; 1017140751Swpaul break; 1018140751Swpaul } 1019140751Swpaul if (devid == CT4730_PCI_ID) { 1020141524Swpaul /* XXX amplifier hack? */ 1021140751Swpaul es->ctrl |= (1 << 16); 1022140751Swpaul } 1023140751Swpaul /* initialize the chips */ 1024140751Swpaul es_wr(es, ES1370_REG_CONTROL, es->ctrl, 4); 1025125551Swpaul es_wr(es, ES1370_REG_SERIAL_CONTROL, es->sctrl, 4); 1026125551Swpaul es_wr(es, ES1371_REG_LEGACY, 0, 4); 1027125551Swpaul if ((devid == ES1371_PCI_ID && revid == ES1371REV_ES1373_8) || 1028125551Swpaul (devid == ES1371_PCI_ID && revid == ES1371REV_CT5880_A) || 1029125551Swpaul (devid == CT5880_PCI_ID && revid == CT5880REV_CT5880_C) || 1030125551Swpaul (devid == CT5880_PCI_ID && revid == CT5880REV_CT5880_D) || 1031125551Swpaul (devid == CT5880_PCI_ID && revid == CT5880REV_CT5880_E)) { 1032125551Swpaul cssr = 1 << 29; 1033125551Swpaul es_wr(es, ES1370_REG_STATUS, cssr, 4); 1034125551Swpaul DELAY(20000); 1035125551Swpaul } 1036125551Swpaul /* AC'97 warm reset to start the bitclk */ 1037125551Swpaul es_wr(es, ES1370_REG_CONTROL, es->ctrl, 4); 1038125551Swpaul es_wr(es, ES1371_REG_LEGACY, ES1371_SYNC_RES, 4); 1039125551Swpaul DELAY(2000); 1040125551Swpaul es_wr(es, ES1370_REG_CONTROL, es->sctrl, 4); 1041125551Swpaul es1371_wait_src_ready(es); 1042125551Swpaul /* Init the sample rate converter */ 1043125551Swpaul es_wr(es, ES1371_REG_SMPRATE, ES1371_DIS_SRC, 4); 1044125551Swpaul for (idx = 0; idx < 0x80; idx++) 1045125551Swpaul es1371_src_write(es, idx, 0); 1046141524Swpaul es1371_src_write(es, ES_SMPREG_DAC1 + ES_SMPREG_TRUNC_N, 16 << 4); 1047141524Swpaul es1371_src_write(es, ES_SMPREG_DAC1 + ES_SMPREG_INT_REGS, 16 << 10); 1048141524Swpaul es1371_src_write(es, ES_SMPREG_DAC2 + ES_SMPREG_TRUNC_N, 16 << 4); 1049141524Swpaul es1371_src_write(es, ES_SMPREG_DAC2 + ES_SMPREG_INT_REGS, 16 << 10); 1050141524Swpaul es1371_src_write(es, ES_SMPREG_VOL_ADC, 1 << 12); 1051141524Swpaul es1371_src_write(es, ES_SMPREG_VOL_ADC + 1, 1 << 12); 1052141524Swpaul es1371_src_write(es, ES_SMPREG_VOL_DAC1, 1 << 12); 1053141524Swpaul es1371_src_write(es, ES_SMPREG_VOL_DAC1 + 1, 1 << 12); 1054141524Swpaul es1371_src_write(es, ES_SMPREG_VOL_DAC2, 1 << 12); 1055141524Swpaul es1371_src_write(es, ES_SMPREG_VOL_DAC2 + 1, 1 << 12); 1056141524Swpaul es1371_adc_rate(es, 22050, ES_ADC); 1057141524Swpaul es1371_dac_rate(es, 22050, ES_DAC1); 1058141524Swpaul es1371_dac_rate(es, 22050, ES_DAC2); 1059141524Swpaul /* 1060141524Swpaul * WARNING: 1061141524Swpaul * enabling the sample rate converter without properly programming 1062141524Swpaul * its parameters causes the chip to lock up (the SRC busy bit will 1063141524Swpaul * be stuck high, and I've found no way to rectify this other than 1064141524Swpaul * power cycle) 1065141524Swpaul */ 1066141524Swpaul es1371_wait_src_ready(es); 1067141524Swpaul es_wr(es, ES1371_REG_SMPRATE, 0, 4); 1068141524Swpaul /* try to reset codec directly */ 1069141524Swpaul es_wr(es, ES1371_REG_CODEC, 0, 4); 1070141524Swpaul es_wr(es, ES1370_REG_STATUS, cssr, 4); 1071141524Swpaul ES_UNLOCK(es); 1072141524Swpaul 1073141524Swpaul return (0); 1074141524Swpaul} 1075141524Swpaul 1076141524Swpaul/* -------------------------------------------------------------------- */ 1077141524Swpaul 1078141524Swpaulstatic int 1079141524Swpaules1371_wrcd(kobj_t obj, void *s, int addr, uint32_t data) 1080141524Swpaul{ 1081141524Swpaul uint32_t t, x, orig; 1082141524Swpaul struct es_info *es = (struct es_info*)s; 1083141524Swpaul 1084141524Swpaul for (t = 0; t < 0x1000; t++) { 1085141524Swpaul if (!es_rd(es, ES1371_REG_CODEC & CODEC_WIP, 4)) 1086141524Swpaul break; 1087141524Swpaul } 1088141524Swpaul /* save the current state for later */ 1089141524Swpaul x = orig = es_rd(es, ES1371_REG_SMPRATE, 4); 1090141524Swpaul /* enable SRC state data in SRC mux */ 1091141524Swpaul es_wr(es, ES1371_REG_SMPRATE, (x & (ES1371_DIS_SRC | ES1371_DIS_P1 | 1092141524Swpaul ES1371_DIS_P2 | ES1371_DIS_R1)) | 0x00010000, 4); 1093141524Swpaul /* busy wait */ 1094141524Swpaul for (t = 0; t < 0x1000; t++) { 1095141524Swpaul if ((es_rd(es, ES1371_REG_SMPRATE, 4) & 0x00870000) == 1096141524Swpaul 0x00000000) 1097141524Swpaul break; 1098141524Swpaul } 1099141524Swpaul /* wait for a SAFE time to write addr/data and then do it, dammit */ 1100141524Swpaul for (t = 0; t < 0x1000; t++) { 1101141524Swpaul if ((es_rd(es, ES1371_REG_SMPRATE, 4) & 0x00870000) == 1102141524Swpaul 0x00010000) 1103141524Swpaul break; 1104141524Swpaul } 1105141524Swpaul 1106141524Swpaul es_wr(es, ES1371_REG_CODEC, ((addr << CODEC_POADD_SHIFT) & 1107141524Swpaul CODEC_POADD_MASK) | ((data << CODEC_PODAT_SHIFT) & 1108141524Swpaul CODEC_PODAT_MASK), 4); 1109141524Swpaul /* restore SRC reg */ 1110141524Swpaul es1371_wait_src_ready(s); 1111141524Swpaul es_wr(es, ES1371_REG_SMPRATE, orig, 4); 1112141524Swpaul 1113141524Swpaul return (0); 1114141524Swpaul} 1115141524Swpaul 1116141524Swpaulstatic int 1117141524Swpaules1371_rdcd(kobj_t obj, void *s, int addr) 1118141524Swpaul{ 1119141524Swpaul uint32_t t, x, orig; 1120141524Swpaul struct es_info *es = (struct es_info *)s; 1121125551Swpaul 1122125551Swpaul for (t = 0; t < 0x1000; t++) { 1123125551Swpaul if (!(x = es_rd(es, ES1371_REG_CODEC, 4) & CODEC_WIP)) 1124125551Swpaul break; 1125125551Swpaul } 1126142443Swpaul 1127125551Swpaul /* save the current state for later */ 1128125551Swpaul x = orig = es_rd(es, ES1371_REG_SMPRATE, 4); 1129141524Swpaul /* enable SRC state data in SRC mux */ 1130125551Swpaul es_wr(es, ES1371_REG_SMPRATE, (x & (ES1371_DIS_SRC | ES1371_DIS_P1 | 1131125551Swpaul ES1371_DIS_P2 | ES1371_DIS_R1)) | 0x00010000, 4); 1132125551Swpaul /* busy wait */ 1133141524Swpaul for (t = 0; t < 0x1000; t++) { 1134125551Swpaul if ((x = es_rd(es, ES1371_REG_SMPRATE, 4) & 0x00870000) == 1135125551Swpaul 0x00000000) 1136125551Swpaul break; 1137141524Swpaul } 1138141524Swpaul /* wait for a SAFE time to write addr/data and then do it, dammit */ 1139141524Swpaul for (t = 0; t < 0x1000; t++) { 1140141524Swpaul if ((x = es_rd(es, ES1371_REG_SMPRATE, 4) & 0x00870000) == 1141141524Swpaul 0x00010000) 1142141524Swpaul break; 1143141524Swpaul } 1144141524Swpaul 1145141524Swpaul es_wr(es, ES1371_REG_CODEC, ((addr << CODEC_POADD_SHIFT) & 1146141524Swpaul CODEC_POADD_MASK) | CODEC_PORD, 4); 1147141524Swpaul 1148127284Swpaul /* restore SRC reg */ 1149127284Swpaul es1371_wait_src_ready(s); 1150127284Swpaul es_wr(es, ES1371_REG_SMPRATE, orig, 4); 1151127284Swpaul 1152127284Swpaul /* now wait for the stinkin' data (RDY) */ 1153127284Swpaul for (t = 0; t < 0x1000; t++) { 1154127284Swpaul if ((x = es_rd(es, ES1371_REG_CODEC, 4)) & CODEC_RDY) 1155144888Swpaul break; 1156144888Swpaul } 1157144888Swpaul 1158144888Swpaul return ((x & CODEC_PIDAT_MASK) >> CODEC_PIDAT_SHIFT); 1159144888Swpaul} 1160144888Swpaul 1161144888Swpaulstatic kobj_method_t es1371_ac97_methods[] = { 1162144888Swpaul KOBJMETHOD(ac97_read, es1371_rdcd), 1163144888Swpaul KOBJMETHOD(ac97_write, es1371_wrcd), 1164144888Swpaul { 0, 0 } 1165123474Swpaul}; 1166141963SwpaulAC97_DECLARE(es1371_ac97); 1167123474Swpaul 1168123474Swpaul/* -------------------------------------------------------------------- */ 1169141524Swpaul 1170141524Swpaulstatic unsigned int 1171142399Swpaules1371_src_read(struct es_info *es, unsigned short reg) 1172141524Swpaul{ 1173141524Swpaul uint32_t r; 1174141524Swpaul 1175141524Swpaul r = es1371_wait_src_ready(es) & (ES1371_DIS_SRC | ES1371_DIS_P1 | 1176141524Swpaul ES1371_DIS_P2 | ES1371_DIS_R1); 1177141524Swpaul r |= ES1371_SRC_RAM_ADDRO(reg); 1178144888Swpaul es_wr(es, ES1371_REG_SMPRATE, r, 4); 1179141963Swpaul return (ES1371_SRC_RAM_DATAI(es1371_wait_src_ready(es))); 1180144888Swpaul} 1181144888Swpaul 1182141524Swpaulstatic void 1183123474Swpaules1371_src_write(struct es_info *es, unsigned short reg, unsigned short data) 1184123474Swpaul{ 1185144888Swpaul uint32_t r; 1186144888Swpaul 1187144888Swpaul r = es1371_wait_src_ready(es) & (ES1371_DIS_SRC | ES1371_DIS_P1 | 1188144888Swpaul ES1371_DIS_P2 | ES1371_DIS_R1); 1189144888Swpaul r |= ES1371_SRC_RAM_ADDRO(reg) | ES1371_SRC_RAM_DATAO(data); 1190144888Swpaul es_wr(es, ES1371_REG_SMPRATE, r | ES1371_SRC_RAM_WE, 4); 1191144888Swpaul} 1192144888Swpaul 1193144888Swpaulstatic unsigned int 1194144888Swpaules1371_adc_rate(struct es_info *es, unsigned int rate, int set) 1195127248Swpaul{ 1196144888Swpaul unsigned int n, truncm, freq, result; 1197144888Swpaul 1198144888Swpaul ES_LOCK_ASSERT(es); 1199144888Swpaul 1200144888Swpaul if (rate > 48000) 1201144175Swpaul rate = 48000; 1202144888Swpaul if (rate < 4000) 1203144888Swpaul rate = 4000; 1204144888Swpaul n = rate / 3000; 1205144175Swpaul if ((1 << n) & ((1 << 15) | (1 << 13) | (1 << 11) | (1 << 9))) 1206144888Swpaul n--; 1207144888Swpaul truncm = (21 * n - 1) | 1; 1208144175Swpaul freq = ((48000UL << 15) / rate) * n; 1209144888Swpaul result = (48000UL << 15) / (freq / n); 1210144888Swpaul if (set) { 1211144888Swpaul if (rate >= 24000) { 1212144888Swpaul if (truncm > 239) 1213144888Swpaul truncm = 239; 1214144888Swpaul es1371_src_write(es, ES_SMPREG_ADC + ES_SMPREG_TRUNC_N, 1215141524Swpaul (((239 - truncm) >> 1) << 9) | (n << 4)); 1216144888Swpaul } else { 1217144888Swpaul if (truncm > 119) 1218141524Swpaul truncm = 119; 1219144888Swpaul es1371_src_write(es, ES_SMPREG_ADC + ES_SMPREG_TRUNC_N, 1220144888Swpaul 0x8000 | (((119 - truncm) >> 1) << 9) | (n << 4)); 1221144888Swpaul } 1222144888Swpaul es1371_src_write(es, ES_SMPREG_ADC + ES_SMPREG_INT_REGS, 1223144888Swpaul (es1371_src_read(es, ES_SMPREG_ADC + ES_SMPREG_INT_REGS) & 1224144888Swpaul 0x00ff) | ((freq >> 5) & 0xfc00)); 1225144888Swpaul es1371_src_write(es, ES_SMPREG_ADC + ES_SMPREG_VFREQ_FRAC, 1226144888Swpaul freq & 0x7fff); 1227144888Swpaul es1371_src_write(es, ES_SMPREG_VOL_ADC, n << 8); 1228141524Swpaul es1371_src_write(es, ES_SMPREG_VOL_ADC + 1, n << 8); 1229144888Swpaul } 1230144888Swpaul return (result); 1231128229Swpaul} 1232144888Swpaul 1233144888Swpaulstatic unsigned int 1234140751Swpaules1371_dac_rate(struct es_info *es, unsigned int rate, int set) 1235128229Swpaul{ 1236128229Swpaul unsigned int freq, r, result, dac, dis; 1237128229Swpaul 1238128229Swpaul ES_LOCK_ASSERT(es); 1239128229Swpaul 1240144888Swpaul if (rate > 48000) 1241144888Swpaul rate = 48000; 1242144888Swpaul if (rate < 4000) 1243144888Swpaul rate = 4000; 1244144888Swpaul freq = ((rate << 15) + 1500) / 3000; 1245144888Swpaul result = (freq * 3000) >> 15; 1246128229Swpaul 1247141963Swpaul dac = (set == ES_DAC1) ? ES_SMPREG_DAC1 : ES_SMPREG_DAC2; 1248141963Swpaul dis = (set == ES_DAC1) ? ES1371_DIS_P2 : ES1371_DIS_P1; 1249141980Swpaul r = (es1371_wait_src_ready(es) & (ES1371_DIS_SRC | ES1371_DIS_P1 | 1250141980Swpaul ES1371_DIS_P2 | ES1371_DIS_R1)); 1251141963Swpaul es_wr(es, ES1371_REG_SMPRATE, r, 4); 1252141963Swpaul es1371_src_write(es, dac + ES_SMPREG_INT_REGS, 1253141963Swpaul (es1371_src_read(es, dac + ES_SMPREG_INT_REGS) & 0x00ff) | 1254141963Swpaul ((freq >> 5) & 0xfc00)); 1255141963Swpaul es1371_src_write(es, dac + ES_SMPREG_VFREQ_FRAC, freq & 0x7fff); 1256141963Swpaul r = (es1371_wait_src_ready(es) & 1257141963Swpaul (ES1371_DIS_SRC | dis | ES1371_DIS_R1)); 1258141963Swpaul es_wr(es, ES1371_REG_SMPRATE, r, 4); 1259141963Swpaul return (result); 1260123474Swpaul} 1261123474Swpaul 1262123474Swpaulstatic uint32_t 1263es1371_wait_src_ready(struct es_info *es) 1264{ 1265 uint32_t t, r; 1266 1267 for (t = 0; t < 0x1000; t++) { 1268 if (!((r = es_rd(es, ES1371_REG_SMPRATE, 4)) & 1269 ES1371_SRC_RAM_BUSY)) 1270 return (r); 1271 DELAY(1); 1272 } 1273 device_printf(es->dev, "%s: timed out 0x%x [0x%x]\n", __func__, 1274 ES1371_REG_SMPRATE, r); 1275 return (0); 1276} 1277 1278/* -------------------------------------------------------------------- */ 1279 1280/* 1281 * Probe and attach the card 1282 */ 1283 1284static int 1285es_pci_probe(device_t dev) 1286{ 1287 switch(pci_get_devid(dev)) { 1288 case ES1370_PCI_ID: 1289 device_set_desc(dev, "AudioPCI ES1370"); 1290 return (BUS_PROBE_DEFAULT); 1291 case ES1371_PCI_ID: 1292 switch(pci_get_revid(dev)) { 1293 case ES1371REV_ES1371_A: 1294 device_set_desc(dev, "AudioPCI ES1371-A"); 1295 return (BUS_PROBE_DEFAULT); 1296 case ES1371REV_ES1371_B: 1297 device_set_desc(dev, "AudioPCI ES1371-B"); 1298 return (BUS_PROBE_DEFAULT); 1299 case ES1371REV_ES1373_A: 1300 device_set_desc(dev, "AudioPCI ES1373-A"); 1301 return (BUS_PROBE_DEFAULT); 1302 case ES1371REV_ES1373_B: 1303 device_set_desc(dev, "AudioPCI ES1373-B"); 1304 return (BUS_PROBE_DEFAULT); 1305 case ES1371REV_ES1373_8: 1306 device_set_desc(dev, "AudioPCI ES1373-8"); 1307 return (BUS_PROBE_DEFAULT); 1308 case ES1371REV_CT5880_A: 1309 device_set_desc(dev, "Creative CT5880-A"); 1310 return (BUS_PROBE_DEFAULT); 1311 default: 1312 device_set_desc(dev, "AudioPCI ES1371-?"); 1313 device_printf(dev, 1314 "unknown revision %d -- please report to " 1315 "freebsd-multimedia@freebsd.org\n", 1316 pci_get_revid(dev)); 1317 return (BUS_PROBE_DEFAULT); 1318 } 1319 case ES1371_PCI_ID2: 1320 device_set_desc(dev, "Strange AudioPCI ES1371-? (vid=3274)"); 1321 device_printf(dev, 1322 "unknown revision %d -- please report to " 1323 "freebsd-multimedia@freebsd.org\n", pci_get_revid(dev)); 1324 return (BUS_PROBE_DEFAULT); 1325 case CT4730_PCI_ID: 1326 switch(pci_get_revid(dev)) { 1327 case CT4730REV_CT4730_A: 1328 device_set_desc(dev, 1329 "Creative SB AudioPCI CT4730/EV1938"); 1330 return (BUS_PROBE_DEFAULT); 1331 default: 1332 device_set_desc(dev, "Creative SB AudioPCI CT4730-?"); 1333 device_printf(dev, 1334 "unknown revision %d -- please report to " 1335 "freebsd-multimedia@freebsd.org\n", 1336 pci_get_revid(dev)); 1337 return (BUS_PROBE_DEFAULT); 1338 } 1339 case CT5880_PCI_ID: 1340 switch(pci_get_revid(dev)) { 1341 case CT5880REV_CT5880_C: 1342 device_set_desc(dev, "Creative CT5880-C"); 1343 return (BUS_PROBE_DEFAULT); 1344 case CT5880REV_CT5880_D: 1345 device_set_desc(dev, "Creative CT5880-D"); 1346 return (BUS_PROBE_DEFAULT); 1347 case CT5880REV_CT5880_E: 1348 device_set_desc(dev, "Creative CT5880-E"); 1349 return (BUS_PROBE_DEFAULT); 1350 default: 1351 device_set_desc(dev, "Creative CT5880-?"); 1352 device_printf(dev, 1353 "unknown revision %d -- please report to " 1354 "freebsd-multimedia@freebsd.org\n", 1355 pci_get_revid(dev)); 1356 return (BUS_PROBE_DEFAULT); 1357 } 1358 default: 1359 return (ENXIO); 1360 } 1361} 1362 1363#ifdef SND_DYNSYSCTL 1364static int 1365sysctl_es137x_spdif_enable(SYSCTL_HANDLER_ARGS) 1366{ 1367 struct es_info *es; 1368 device_t dev; 1369 uint32_t r; 1370 int err, new_en; 1371 1372 dev = oidp->oid_arg1; 1373 es = pcm_getdevinfo(dev); 1374 ES_LOCK(es); 1375 r = es_rd(es, ES1370_REG_STATUS, 4); 1376 ES_UNLOCK(es); 1377 new_en = (r & ENABLE_SPDIF) ? 1 : 0; 1378 err = sysctl_handle_int(oidp, &new_en, sizeof(new_en), req); 1379 1380 if (err || req->newptr == NULL) 1381 return (err); 1382 if (new_en < 0 || new_en > 1) 1383 return (EINVAL); 1384 1385 ES_LOCK(es); 1386 if (new_en) { 1387 r |= ENABLE_SPDIF; 1388 es->ctrl |= SPDIFEN_B; 1389 es->ctrl |= RECEN_B; 1390 } else { 1391 r &= ~ENABLE_SPDIF; 1392 es->ctrl &= ~SPDIFEN_B; 1393 es->ctrl &= ~RECEN_B; 1394 } 1395 es_wr(es, ES1370_REG_CONTROL, es->ctrl, 4); 1396 es_wr(es, ES1370_REG_STATUS, r, 4); 1397 ES_UNLOCK(es); 1398 1399 return (0); 1400} 1401 1402static int 1403sysctl_es137x_latency_timer(SYSCTL_HANDLER_ARGS) 1404{ 1405 struct es_info *es; 1406 device_t dev; 1407 uint32_t val; 1408 int err; 1409 1410 dev = oidp->oid_arg1; 1411 es = pcm_getdevinfo(dev); 1412 ES_LOCK(es); 1413 val = pci_read_config(dev, PCIR_LATTIMER, 1); 1414 ES_UNLOCK(es); 1415 err = sysctl_handle_int(oidp, &val, sizeof(val), req); 1416 1417 if (err || req->newptr == NULL) 1418 return (err); 1419 if (val > 255) 1420 return (EINVAL); 1421 1422 ES_LOCK(es); 1423 pci_write_config(dev, PCIR_LATTIMER, val, 1); 1424 ES_UNLOCK(es); 1425 1426 return (0); 1427} 1428 1429static int 1430sysctl_es137x_fixed_rate(SYSCTL_HANDLER_ARGS) 1431{ 1432 struct es_info *es; 1433 device_t dev; 1434 uint32_t val; 1435 int err; 1436 1437 dev = oidp->oid_arg1; 1438 es = pcm_getdevinfo(dev); 1439 ES_LOCK(es); 1440 val = ES_FIXED_RATE(es->escfg); 1441 if (val < es_caps.minspeed) 1442 val = 0; 1443 ES_UNLOCK(es); 1444 err = sysctl_handle_int(oidp, &val, sizeof(val), req); 1445 1446 if (err || req->newptr == NULL) 1447 return (err); 1448 if (val != 0 && (val < es_caps.minspeed || val > es_caps.maxspeed)) 1449 return (EINVAL); 1450 1451 ES_LOCK(es); 1452 if (es->ctrl & (CTRL_DAC2_EN|CTRL_ADC_EN)) { 1453 ES_UNLOCK(es); 1454 return (EBUSY); 1455 } 1456 if (val) { 1457 if (val != ES_FIXED_RATE(es->escfg)) { 1458 es->escfg = ES_SET_FIXED_RATE(es->escfg, val); 1459 es->ch[ES_DAC2].caps.maxspeed = val; 1460 es->ch[ES_DAC2].caps.minspeed = val; 1461 es->ch[ES_ADC].caps.maxspeed = val; 1462 es->ch[ES_ADC].caps.minspeed = val; 1463 es->ctrl &= ~CTRL_PCLKDIV; 1464 es->ctrl |= DAC2_SRTODIV(val) << CTRL_SH_PCLKDIV; 1465 es_wr(es, ES1370_REG_CONTROL, es->ctrl, 4); 1466 } 1467 } else { 1468 es->escfg = ES_SET_FIXED_RATE(es->escfg, 0); 1469 es->ch[ES_DAC2].caps = es_caps; 1470 es->ch[ES_ADC].caps = es_caps; 1471 } 1472 ES_UNLOCK(es); 1473 1474 return (0); 1475} 1476 1477static int 1478sysctl_es137x_single_pcm_mixer(SYSCTL_HANDLER_ARGS) 1479{ 1480 struct es_info *es; 1481 struct snddev_info *d; 1482 struct snd_mixer *m; 1483 struct cdev *i_dev; 1484 device_t dev; 1485 uint32_t val, set; 1486 int recsrc, level, err; 1487 1488 dev = oidp->oid_arg1; 1489 d = device_get_softc(dev); 1490 if (d == NULL || d->mixer_dev == NULL || d->mixer_dev->si_drv1 == NULL) 1491 return (EINVAL); 1492 es = d->devinfo; 1493 if (es == NULL) 1494 return (EINVAL); 1495 ES_LOCK(es); 1496 set = ES_SINGLE_PCM_MIX(es->escfg); 1497 val = set; 1498 ES_UNLOCK(es); 1499 err = sysctl_handle_int(oidp, &val, sizeof(val), req); 1500 1501 if (err || req->newptr == NULL) 1502 return (err); 1503 if (!(val == 0 || val == 1)) 1504 return (EINVAL); 1505 if (val == set) 1506 return (0); 1507 i_dev = d->mixer_dev; 1508 if (mixer_ioctl(i_dev, 0, (caddr_t)&recsrc, 0, NULL) != EBADF) 1509 return (EBUSY); 1510 err = mixer_ioctl(i_dev, MIXER_READ(SOUND_MIXER_PCM), (caddr_t)&level, 1511 -1, NULL); 1512 if (!err) 1513 err = mixer_ioctl(i_dev, MIXER_READ(SOUND_MIXER_RECSRC), 1514 (caddr_t)&recsrc, -1, NULL); 1515 if (err) 1516 return (err); 1517 if (level < 0) 1518 return (EINVAL); 1519 1520 ES_LOCK(es); 1521 if (es->ctrl & (CTRL_ADC_EN | CTRL_DAC1_EN | CTRL_DAC2_EN)) { 1522 ES_UNLOCK(es); 1523 return (EBUSY); 1524 } 1525 if (val) 1526 es->escfg = ES_SET_SINGLE_PCM_MIX(es->escfg, 1); 1527 else 1528 es->escfg = ES_SET_SINGLE_PCM_MIX(es->escfg, 0); 1529 ES_UNLOCK(es); 1530 m = i_dev->si_drv1; 1531 if (!val) { 1532 mix_setdevs(m, mix_getdevs(d->mixer_dev->si_drv1) | 1533 (1 << SOUND_MIXER_SYNTH)); 1534 mix_setrecdevs(m, mix_getrecdevs(d->mixer_dev->si_drv1) | 1535 (1 << SOUND_MIXER_SYNTH)); 1536 err = mixer_ioctl(i_dev, MIXER_WRITE(SOUND_MIXER_SYNTH), 1537 (caddr_t)&level, -1, NULL); 1538 } else { 1539 err = mixer_ioctl(i_dev, MIXER_WRITE(SOUND_MIXER_SYNTH), 1540 (caddr_t)&level, -1, NULL); 1541 mix_setdevs(m, mix_getdevs(d->mixer_dev->si_drv1) & 1542 ~(1 << SOUND_MIXER_SYNTH)); 1543 mix_setrecdevs(m, mix_getrecdevs(d->mixer_dev->si_drv1) & 1544 ~(1 << SOUND_MIXER_SYNTH)); 1545 } 1546 if (!err) { 1547 level = recsrc; 1548 if (recsrc & (1 << SOUND_MIXER_PCM)) 1549 recsrc |= 1 << SOUND_MIXER_SYNTH; 1550 else if (recsrc & (1 << SOUND_MIXER_SYNTH)) 1551 recsrc |= 1 << SOUND_MIXER_PCM; 1552 if (level != recsrc) 1553 err = mixer_ioctl(i_dev, 1554 MIXER_WRITE(SOUND_MIXER_RECSRC), 1555 (caddr_t)&recsrc, -1, NULL); 1556 } 1557 return (err); 1558} 1559 1560static int 1561sysctl_es_polling(SYSCTL_HANDLER_ARGS) 1562{ 1563 struct es_info *es; 1564 device_t dev; 1565 int err, val; 1566 1567 dev = oidp->oid_arg1; 1568 es = pcm_getdevinfo(dev); 1569 if (es == NULL) 1570 return (EINVAL); 1571 ES_LOCK(es); 1572 val = es->polling; 1573 ES_UNLOCK(es); 1574 err = sysctl_handle_int(oidp, &val, sizeof(val), req); 1575 1576 if (err || req->newptr == NULL) 1577 return (err); 1578 if (val < 0 || val > 1) 1579 return (EINVAL); 1580 1581 ES_LOCK(es); 1582 if (val != es->polling) { 1583 if (es_chan_active(es) != 0) 1584 err = EBUSY; 1585 else if (val == 0) 1586 es->polling = 0; 1587 else 1588 es->polling = 1; 1589 } 1590 ES_UNLOCK(es); 1591 1592 return (err); 1593} 1594#endif /* SND_DYNSYSCTL */ 1595 1596static void 1597es_init_sysctls(device_t dev) 1598{ 1599#ifdef SND_DYNSYSCTL 1600 struct es_info *es; 1601 int r, devid, revid; 1602 1603 devid = pci_get_devid(dev); 1604 revid = pci_get_revid(dev); 1605 es = pcm_getdevinfo(dev); 1606 if ((devid == ES1371_PCI_ID && revid == ES1371REV_ES1373_8) || 1607 (devid == ES1371_PCI_ID && revid == ES1371REV_CT5880_A) || 1608 (devid == CT5880_PCI_ID && revid == CT5880REV_CT5880_C) || 1609 (devid == CT5880_PCI_ID && revid == CT5880REV_CT5880_D) || 1610 (devid == CT5880_PCI_ID && revid == CT5880REV_CT5880_E)) { 1611 /* XXX: an user should be able to set this with a control tool, 1612 if not done before 7.0-RELEASE, this needs to be converted 1613 to a device specific sysctl "dev.pcm.X.yyy" via 1614 device_get_sysctl_*() as discussed on multimedia@ in msg-id 1615 <861wujij2q.fsf@xps.des.no> */ 1616 SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), 1617 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, 1618 "spdif_enabled", CTLTYPE_INT | CTLFLAG_RW, dev, sizeof(dev), 1619 sysctl_es137x_spdif_enable, "I", 1620 "Enable S/PDIF output on primary playback channel"); 1621 } else if (devid == ES1370_PCI_ID) { 1622 /* 1623 * Enable fixed rate sysctl if both DAC2 / ADC enabled. 1624 */ 1625 if (es->ch[ES_DAC2].channel != NULL && 1626 es->ch[ES_ADC].channel != NULL) { 1627 /* XXX: an user should be able to set this with a control tool, 1628 if not done before 7.0-RELEASE, this needs to be converted 1629 to a device specific sysctl "dev.pcm.X.yyy" via 1630 device_get_sysctl_*() as discussed on multimedia@ in msg-id 1631 <861wujij2q.fsf@xps.des.no> */ 1632 SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), 1633 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), 1634 OID_AUTO, "fixed_rate", CTLTYPE_INT | CTLFLAG_RW, 1635 dev, sizeof(dev), sysctl_es137x_fixed_rate, "I", 1636 "Enable fixed rate playback/recording"); 1637 } 1638 /* 1639 * Enable single pcm mixer sysctl if both DAC1/2 enabled. 1640 */ 1641 if (es->ch[ES_DAC1].channel != NULL && 1642 es->ch[ES_DAC2].channel != NULL) { 1643 /* XXX: an user should be able to set this with a control tool, 1644 if not done before 7.0-RELEASE, this needs to be converted 1645 to a device specific sysctl "dev.pcm.X.yyy" via 1646 device_get_sysctl_*() as discussed on multimedia@ in msg-id 1647 <861wujij2q.fsf@xps.des.no> */ 1648 SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), 1649 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), 1650 OID_AUTO, "single_pcm_mixer", 1651 CTLTYPE_INT | CTLFLAG_RW, dev, sizeof(dev), 1652 sysctl_es137x_single_pcm_mixer, "I", 1653 "Single PCM mixer controller for both DAC1/DAC2"); 1654 } 1655 } 1656 if (resource_int_value(device_get_name(dev), device_get_unit(dev), 1657 "latency_timer", &r) == 0 && !(r < 0 || r > 255)) 1658 pci_write_config(dev, PCIR_LATTIMER, r, 1); 1659 /* XXX: this needs to be converted to a device specific sysctl 1660 "dev.pcm.X.yyy" via device_get_sysctl_*() as discussed on 1661 multimedia@ in msg-id <861wujij2q.fsf@xps.des.no> */ 1662 SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), 1663 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, 1664 "latency_timer", CTLTYPE_INT | CTLFLAG_RW, dev, sizeof(dev), 1665 sysctl_es137x_latency_timer, "I", 1666 "PCI Latency Timer configuration"); 1667 SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), 1668 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, 1669 "polling", CTLTYPE_INT | CTLFLAG_RW, dev, sizeof(dev), 1670 sysctl_es_polling, "I", 1671 "Enable polling mode"); 1672#endif /* SND_DYNSYSCTL */ 1673} 1674 1675static int 1676es_pci_attach(device_t dev) 1677{ 1678 uint32_t data; 1679 struct es_info *es = NULL; 1680 int mapped, i, numplay, dac_cfg; 1681 char status[SND_STATUSLEN]; 1682 struct ac97_info *codec = NULL; 1683 kobj_class_t ct = NULL; 1684 uint32_t devid; 1685 1686 if ((es = malloc(sizeof *es, M_DEVBUF, M_NOWAIT | M_ZERO)) == NULL) { 1687 device_printf(dev, "cannot allocate softc\n"); 1688 return (ENXIO); 1689 } 1690 es->lock = snd_mtxcreate(device_get_nameunit(dev), "snd_es137x softc"); 1691 es->dev = dev; 1692 es->escfg = 0; 1693 mapped = 0; 1694 1695 pci_enable_busmaster(dev); 1696 data = pci_read_config(dev, PCIR_COMMAND, 2); 1697 data |= (PCIM_CMD_PORTEN|PCIM_CMD_MEMEN); 1698 pci_write_config(dev, PCIR_COMMAND, data, 2); 1699 data = pci_read_config(dev, PCIR_COMMAND, 2); 1700 if (mapped == 0 && (data & PCIM_CMD_MEMEN)) { 1701 es->regid = MEM_MAP_REG; 1702 es->regtype = SYS_RES_MEMORY; 1703 es->reg = bus_alloc_resource_any(dev, es->regtype, &es->regid, 1704 RF_ACTIVE); 1705 if (es->reg) 1706 mapped++; 1707 } 1708 if (mapped == 0 && (data & PCIM_CMD_PORTEN)) { 1709 es->regid = PCIR_BAR(0); 1710 es->regtype = SYS_RES_IOPORT; 1711 es->reg = bus_alloc_resource_any(dev, es->regtype, &es->regid, 1712 RF_ACTIVE); 1713 if (es->reg) 1714 mapped++; 1715 } 1716 if (mapped == 0) { 1717 device_printf(dev, "unable to map register space\n"); 1718 goto bad; 1719 } 1720 1721 es->st = rman_get_bustag(es->reg); 1722 es->sh = rman_get_bushandle(es->reg); 1723 callout_init(&es->poll_timer, CALLOUT_MPSAFE); 1724 es->poll_ticks = 1; 1725 1726 if (resource_int_value(device_get_name(dev), 1727 device_get_unit(dev), "polling", &i) == 0 && i != 0) 1728 es->polling = 1; 1729 else 1730 es->polling = 0; 1731 1732 es->bufsz = pcm_getbuffersize(dev, 4096, ES_DEFAULT_BUFSZ, 65536); 1733 if (resource_int_value(device_get_name(dev), 1734 device_get_unit(dev), "blocksize", &i) == 0 && i > 0) { 1735 i &= ES_BLK_ALIGN; 1736 if (i < ES_BLK_MIN) 1737 i = ES_BLK_MIN; 1738 es->blkcnt = es->bufsz / i; 1739 i = 0; 1740 while (es->blkcnt >> i) 1741 i++; 1742 es->blkcnt = 1 << (i - 1); 1743 if (es->blkcnt < ES_DMA_SEGS_MIN) 1744 es->blkcnt = ES_DMA_SEGS_MIN; 1745 else if (es->blkcnt > ES_DMA_SEGS_MAX) 1746 es->blkcnt = ES_DMA_SEGS_MAX; 1747 1748 } else 1749 es->blkcnt = 2; 1750 1751 if (resource_int_value(device_get_name(dev), device_get_unit(dev), 1752 "dac", &dac_cfg) == 0) { 1753 if (dac_cfg < 0 || dac_cfg > 3) 1754 dac_cfg = ES_DEFAULT_DAC_CFG; 1755 } else 1756 dac_cfg = ES_DEFAULT_DAC_CFG; 1757 1758 switch (dac_cfg) { 1759 case 0: /* Enable all DAC: DAC1, DAC2 */ 1760 numplay = 2; 1761 es->escfg = ES_SET_DAC_FIRST(es->escfg, ES_DAC1); 1762 es->escfg = ES_SET_DAC_SECOND(es->escfg, ES_DAC2); 1763 break; 1764 case 1: /* Only DAC1 */ 1765 numplay = 1; 1766 es->escfg = ES_SET_DAC_FIRST(es->escfg, ES_DAC1); 1767 break; 1768 case 3: /* Enable all DAC / swap position: DAC2, DAC1 */ 1769 numplay = 2; 1770 es->escfg = ES_SET_DAC_FIRST(es->escfg, ES_DAC2); 1771 es->escfg = ES_SET_DAC_SECOND(es->escfg, ES_DAC1); 1772 break; 1773 case 2: /* Only DAC2 */ 1774 default: 1775 numplay = 1; 1776 es->escfg = ES_SET_DAC_FIRST(es->escfg, ES_DAC2); 1777 break; 1778 } 1779 es->escfg = ES_SET_NUMPLAY(es->escfg, numplay); 1780 es->escfg = ES_SET_NUMREC(es->escfg, 1); 1781 1782 devid = pci_get_devid(dev); 1783 switch (devid) { 1784 case ES1371_PCI_ID: 1785 case ES1371_PCI_ID2: 1786 case CT5880_PCI_ID: 1787 case CT4730_PCI_ID: 1788 es1371_init(es); 1789 codec = AC97_CREATE(dev, es, es1371_ac97); 1790 if (codec == NULL) 1791 goto bad; 1792 /* our init routine does everything for us */ 1793 /* set to NULL; flag mixer_init not to run the ac97_init */ 1794 /* ac97_mixer.init = NULL; */ 1795 if (mixer_init(dev, ac97_getmixerclass(), codec)) 1796 goto bad; 1797 ct = &eschan1371_class; 1798 break; 1799 case ES1370_PCI_ID: 1800 es1370_init(es); 1801 /* 1802 * Disable fixed rate operation if DAC2 disabled. 1803 * This is a special case for es1370 only, where the 1804 * speed of both ADC and DAC2 locked together. 1805 */ 1806 if (!ES_DAC2_ENABLED(es->escfg)) 1807 es->escfg = ES_SET_FIXED_RATE(es->escfg, 0); 1808 if (mixer_init(dev, &es1370_mixer_class, es)) 1809 goto bad; 1810 ct = &eschan1370_class; 1811 break; 1812 default: 1813 goto bad; 1814 /* NOTREACHED */ 1815 } 1816 1817 es->irqid = 0; 1818 es->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &es->irqid, 1819 RF_ACTIVE | RF_SHAREABLE); 1820 if (!es->irq || snd_setup_intr(dev, es->irq, INTR_MPSAFE, es_intr, 1821 es, &es->ih)) { 1822 device_printf(dev, "unable to map interrupt\n"); 1823 goto bad; 1824 } 1825 1826 if (bus_dma_tag_create(/*parent*/bus_get_dma_tag(dev), 1827 /*alignment*/2, /*boundary*/0, 1828 /*lowaddr*/BUS_SPACE_MAXADDR_32BIT, 1829 /*highaddr*/BUS_SPACE_MAXADDR, 1830 /*filter*/NULL, /*filterarg*/NULL, 1831 /*maxsize*/es->bufsz, /*nsegments*/1, /*maxsegz*/0x3ffff, 1832 /*flags*/0, /*lockfunc*/NULL, 1833 /*lockarg*/NULL, &es->parent_dmat) != 0) { 1834 device_printf(dev, "unable to create dma tag\n"); 1835 goto bad; 1836 } 1837 1838 snprintf(status, SND_STATUSLEN, "at %s 0x%lx irq %ld %s", 1839 (es->regtype == SYS_RES_IOPORT)? "io" : "memory", 1840 rman_get_start(es->reg), rman_get_start(es->irq), 1841 PCM_KLDSTRING(snd_es137x)); 1842 1843 if (pcm_register(dev, es, numplay, 1)) 1844 goto bad; 1845 for (i = 0; i < numplay; i++) 1846 pcm_addchan(dev, PCMDIR_PLAY, ct, es); 1847 pcm_addchan(dev, PCMDIR_REC, ct, es); 1848 es_init_sysctls(dev); 1849 pcm_setstatus(dev, status); 1850 es->escfg = ES_SET_GP(es->escfg, 0); 1851 if (numplay == 1) 1852 device_printf(dev, "<Playback: DAC%d / Record: ADC>\n", 1853 ES_DAC_FIRST(es->escfg) + 1); 1854 else if (numplay == 2) 1855 device_printf(dev, "<Playback: DAC%d,DAC%d / Record: ADC>\n", 1856 ES_DAC_FIRST(es->escfg) + 1, ES_DAC_SECOND(es->escfg) + 1); 1857 return (0); 1858 1859bad: 1860 if (es->parent_dmat) 1861 bus_dma_tag_destroy(es->parent_dmat); 1862 if (es->ih) 1863 bus_teardown_intr(dev, es->irq, es->ih); 1864 if (es->irq) 1865 bus_release_resource(dev, SYS_RES_IRQ, es->irqid, es->irq); 1866 if (codec) 1867 ac97_destroy(codec); 1868 if (es->reg) 1869 bus_release_resource(dev, es->regtype, es->regid, es->reg); 1870 if (es->lock) 1871 snd_mtxfree(es->lock); 1872 if (es) 1873 free(es, M_DEVBUF); 1874 return (ENXIO); 1875} 1876 1877static int 1878es_pci_detach(device_t dev) 1879{ 1880 int r; 1881 struct es_info *es; 1882 1883 r = pcm_unregister(dev); 1884 if (r) 1885 return (r); 1886 1887 es = pcm_getdevinfo(dev); 1888 bus_teardown_intr(dev, es->irq, es->ih); 1889 bus_release_resource(dev, SYS_RES_IRQ, es->irqid, es->irq); 1890 bus_release_resource(dev, es->regtype, es->regid, es->reg); 1891 bus_dma_tag_destroy(es->parent_dmat); 1892 snd_mtxfree(es->lock); 1893 free(es, M_DEVBUF); 1894 1895 return (0); 1896} 1897 1898static device_method_t es_methods[] = { 1899 /* Device interface */ 1900 DEVMETHOD(device_probe, es_pci_probe), 1901 DEVMETHOD(device_attach, es_pci_attach), 1902 DEVMETHOD(device_detach, es_pci_detach), 1903 1904 { 0, 0 } 1905}; 1906 1907static driver_t es_driver = { 1908 "pcm", 1909 es_methods, 1910 PCM_SOFTC_SIZE, 1911}; 1912 1913DRIVER_MODULE(snd_es137x, pci, es_driver, pcm_devclass, 0, 0); 1914MODULE_DEPEND(snd_es137x, sound, SOUND_MINVER, SOUND_PREFVER, SOUND_MAXVER); 1915MODULE_VERSION(snd_es137x, 1); 1916