From owner-freebsd-hackers Sat Dec 22 2: 4:29 2001 Delivered-To: freebsd-hackers@freebsd.org Received: from metroweb.co.za (www.metroweb.co.za [196.23.181.201]) by hub.freebsd.org (Postfix) with ESMTP id 4395A37B405 for ; Sat, 22 Dec 2001 02:04:18 -0800 (PST) Received: from Yorick. (ppp-179-16.isp.org.za [196.23.179.16]) by metroweb.co.za (8.12.1/8.12.1) with ESMTP id fBMA232h016028 for ; Sat, 22 Dec 2001 12:02:04 +0200 Received: (from yorick@localhost) by Yorick. (8.11.6/8.11.6) id fBMCG2C02623 for freebsd-hackers@freebsd.org; Sat, 22 Dec 2001 12:16:02 GMT (envelope-from yorickhardy@yahoo.com) Date: Sat, 22 Dec 2001 12:16:02 GMT From: yorickhardy@yahoo.com Message-Id: <200112221216.fBMCG2C02623@Yorick.> X-Authentication-Warning: Yorick.: yorick set sender to yorickhardy@yahoo.com using -f MIME-Version: 1.0 To: freebsd-hackers@freebsd.org Subject: patch for sb live rear output Sender: owner-freebsd-hackers@FreeBSD.ORG Precedence: bulk List-ID: List-Archive: (Web Archive) List-Help: (List Instructions) List-Subscribe: List-Unsubscribe: X-Loop: FreeBSD.ORG This patch should enable the rear output (not digital to my knowledge) for the sb live, the volume can be set using the pcm2 setting from the mixer. I hope the patch applies correctly. It should work when applied with /usr/src as the current directory. Yorick Hardy. *** sys/dev/sound/pci/emu10k1.c.orig Tue Dec 21 11:01:14 1999 --- sys/dev/sound/pci/emu10k1.c Fri Dec 21 22:33:00 2001 *************** *** 28,33 **** --- 28,34 ---- #include #include + #include "mixer_if.h" #include #include *************** *** 39,44 **** --- 40,49 ---- #define EMU10K1_PCI_ID 0x00021102 #define EMU_BUFFSIZE 4096 #define EMU_CHANS 4 + /*define which general purpose registers to use + to store the rear volume information*/ + #define REARLVOLREG 0x110 + #define REARRVOLREG 0x111 #undef EMUDEBUG struct emu_memblk { *************** *** 88,93 **** --- 93,101 ---- device_t dev; u_int32_t type, rev; u_int32_t tos_link:1, APS:1; + u_int32_t rearvol_ops; + + struct snd_mixer *ac97mixer; bus_space_tag_t st; bus_space_handle_t sh; *************** *** 127,132 **** --- 135,149 ---- static u_int32_t emu_rd(struct sc_info *, int, int); static void emu_wr(struct sc_info *, int, u_int32_t, int); + /* mixer */ + static int emumix_init(struct snd_mixer *m); + static int emumix_reinit(struct snd_mixer *m); + static int emumix_uninit(struct snd_mixer *m); + static int emumix_set(struct snd_mixer *m, unsigned dev, unsigned left, unsigned right); + static u_int32_t emumix_setrecsrc(struct snd_mixer *m, u_int32_t src); + kobj_class_t emu_getmixerclass(void); + extern struct malloc_type M_MIXER[1]; + /* -------------------------------------------------------------------- */ static u_int32_t emu_rfmt_ac97[] = { *************** *** 163,168 **** --- 180,193 ---- static int adcspeed[8] = {48000, 44100, 32000, 24000, 22050, 16000, 11025, 8000}; + #define MAX_EFX_CONSTS 17 + static int efx_consts[2*MAX_EFX_CONSTS] = { + 0x0, 0x40, 0x1, 0x41, 0x2, 0x42, 0x3, 0x43, 0x4, 0x44, 0x8, 0x45, + 0x10, 0x46, 0x20, 0x047, 0x100, 0x048, 0x10000, 0x049, 0x80000, 0x4a, + 0x10000000, 0x04b, 0x20000000, 0x4c, 0x40000000, 0x4d, 0x80000000, 0x4e, + 0x7fffffff, 0x4f, 0xffffffff, 0x50 + }; + /* -------------------------------------------------------------------- */ /* Hardware */ static u_int32_t *************** *** 1180,1187 **** emu_addefxop(sc, 6, 0x21, 0x40, 0x41, 0x101, &pc); /* RearOut = (GPR[0/1] * RearVolume) >> 31 */ /* RearVolume = GRP[0x10/0x11] */ ! emu_addefxop(sc, 0, 0x28, 0x40, 0x110, 0x100, &pc); ! emu_addefxop(sc, 0, 0x29, 0x40, 0x111, 0x101, &pc); /* TOS out = GPR[0/1] */ emu_addefxop(sc, 6, 0x22, 0x40, 0x40, 0x100, &pc); emu_addefxop(sc, 6, 0x23, 0x40, 0x40, 0x101, &pc); --- 1205,1221 ---- emu_addefxop(sc, 6, 0x21, 0x40, 0x41, 0x101, &pc); /* RearOut = (GPR[0/1] * RearVolume) >> 31 */ /* RearVolume = GRP[0x10/0x11] */ ! emu_addefxop(sc, 6, 0x100, 0x100, 0x40, 0x10, &pc); ! emu_addefxop(sc, 6, 0x101, 0x101, 0x40, 0x11, &pc); ! emu_addefxop(sc, 6, REARLVOLREG, 0x40, 0x40, 0x40, &pc); ! emu_addefxop(sc, 6, REARRVOLREG, 0x40, 0x40, 0x40, &pc); ! sc->rearvol_ops = pc; ! for (i = 0; i < MAX_EFX_CONSTS; i++) { ! emu_addefxop(sc, 6, REARLVOLREG, 0x40, 0x40, 0x40, &pc); ! emu_addefxop(sc, 6, REARRVOLREG, 0x40, 0x40, 0x40, &pc); ! } ! emu_addefxop(sc, 0, 0x28, 0x40, REARLVOLREG, 0x100, &pc); ! emu_addefxop(sc, 0, 0x29, 0x40, REARRVOLREG, 0x101, &pc); /* TOS out = GPR[0/1] */ emu_addefxop(sc, 6, 0x22, 0x40, 0x40, 0x100, &pc); emu_addefxop(sc, 6, 0x23, 0x40, 0x40, 0x101, &pc); *************** *** 1472,1478 **** codec = AC97_CREATE(dev, sc, emu_ac97); if (codec == NULL) goto bad; ! if (mixer_init(dev, ac97_getmixerclass(), codec) == -1) goto bad; sc->irqid = 0; sc->irq = bus_alloc_resource(dev, SYS_RES_IRQ, &sc->irqid, --- 1506,1519 ---- codec = AC97_CREATE(dev, sc, emu_ac97); if (codec == NULL) goto bad; ! ! /* unsure how to do this nicely, ! copy the code from mixer.c to access the ac97 mixer */ ! sc->ac97mixer = (struct snd_mixer *)kobj_create(ac97_getmixerclass(), M_MIXER, M_WAITOK | M_ZERO); ! if (sc->ac97mixer == NULL) goto bad; ! mix_setdevinfo(sc->ac97mixer, codec); ! ! if (mixer_init(dev, emu_getmixerclass(), sc) == -1) goto bad; sc->irqid = 0; sc->irq = bus_alloc_resource(dev, SYS_RES_IRQ, &sc->irqid, *************** *** 1497,1502 **** --- 1538,1544 ---- return 0; bad: + if (sc->ac97mixer) kobj_delete((kobj_t)sc->ac97mixer, M_MIXER); if (codec) ac97_destroy(codec); if (sc->reg) bus_release_resource(dev, sc->regtype, sc->regid, sc->reg); if (sc->ih) bus_teardown_intr(dev, sc->irq, sc->ih); *************** *** 1597,1600 **** --- 1639,1735 ---- static devclass_t emujoy_devclass; DRIVER_MODULE(emujoy, pci, emujoy_driver, emujoy_devclass, 0, 0); + + + static int + emumix_init(struct snd_mixer *m) + { + struct sc_info *sc = mix_getdevinfo(m); + u_int32_t devs; + int r; + + if (r = MIXER_INIT(sc->ac97mixer)) + return r; + devs = mix_getdevs(sc->ac97mixer); + mix_setdevs(m, devs | SOUND_MASK_ALTPCM); + devs = mix_getrecdevs(sc->ac97mixer); + mix_setrecdevs(m, devs | SOUND_MASK_ALTPCM); + return 0; + } + + static int + emumix_reinit(struct snd_mixer *m) + { + struct sc_info *sc = mix_getdevinfo(m); + return MIXER_REINIT(sc->ac97mixer); + } + + static int + emumix_uninit(struct snd_mixer *m) + { + struct sc_info *sc = mix_getdevinfo(m); + MIXER_UNINIT(sc->ac97mixer); + kobj_delete((kobj_t)sc->ac97mixer, M_MIXER); + return 0; + } + + static int + emumix_set(struct snd_mixer *m, unsigned dev, unsigned left, unsigned right) + { + struct sc_info *sc = mix_getdevinfo(m); + u_int32_t pc; + int i; + unsigned efx_lvol,efx_rvol; + + if (sc == NULL) + return -1; + + /* use ALTPCM until someone suggests something better */ + if (dev != SOUND_MIXER_ALTPCM) + return MIXER_SET(sc->ac97mixer,dev,left,right); + + efx_lvol = (((1 << 31) - 1) / 100) * left; + efx_rvol = (((1 << 31) - 1) / 100) * right; + + pc = sc->rearvol_ops; + for (i = MAX_EFX_CONSTS - 1; i >= 0; i--) { + if (efx_lvol >= efx_consts[i*2]) { + efx_lvol -= efx_consts[i*2]; + emu_addefxop(sc, 6, REARLVOLREG, REARLVOLREG, efx_consts[2*i+1], 0x40, &pc); + } + else + emu_addefxop(sc, 6, REARLVOLREG, REARLVOLREG, 0x40, 0x40, &pc); + if (efx_rvol >= efx_consts[i*2]) { + efx_rvol -= efx_consts[i*2]; + emu_addefxop(sc, 6, REARRVOLREG, REARRVOLREG, efx_consts[2*i+1], 0x40, &pc); + } + else + emu_addefxop(sc, 6, REARLVOLREG, REARLVOLREG, 0x40, 0x40, &pc); + } + + return 0; + } + + static u_int32_t + emumix_setrecsrc(struct snd_mixer *m, u_int32_t src) + { + struct sc_info *sc = mix_getdevinfo(m); + return MIXER_SETRECSRC(sc->ac97mixer,src); + } + + static kobj_method_t emumix_methods[] = { + KOBJMETHOD(mixer_init, emumix_init), + KOBJMETHOD(mixer_reinit, emumix_reinit), + KOBJMETHOD(mixer_uninit, emumix_uninit), + KOBJMETHOD(mixer_set, emumix_set), + KOBJMETHOD(mixer_setrecsrc, emumix_setrecsrc), + { 0, 0 } + }; + MIXER_DECLARE(emumix); + + kobj_class_t + emu_getmixerclass(void) + { + return &emumix_class; + } *** /home/yorick/FreeBSD/ctm/src/sys/dev/sound/pcm/mixer.h Wed Aug 1 23:32:26 2001 --- sys/dev/sound/pcm/mixer.h Fri Dec 21 21:01:01 2001 *************** *** 40,45 **** --- 40,46 ---- u_int32_t mix_getdevs(struct snd_mixer *m); u_int32_t mix_getrecdevs(struct snd_mixer *m); void *mix_getdevinfo(struct snd_mixer *m); + void mix_setdevinfo(struct snd_mixer *m, void *d); /* * this is a kludge to allow hiding of the struct snd_mixer definition *** /home/yorick/FreeBSD/ctm/src/sys/dev/sound/pcm/mixer.c Sat Aug 4 13:27:18 2001 --- sys/dev/sound/pcm/mixer.c Fri Dec 21 21:00:05 2001 *************** *** 192,197 **** --- 192,203 ---- return m->devinfo; } + void + mix_setdevinfo(struct snd_mixer *m, void *d) + { + m->devinfo = d; + } + int mixer_init(device_t dev, kobj_class_t cls, void *devinfo) { To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-hackers" in the body of the message