Date: Sat, 22 Dec 2001 12:16:02 GMT From: yorickhardy@yahoo.com To: freebsd-hackers@freebsd.org Subject: patch for sb live rear output Message-ID: <200112221216.fBMCG2C02623@Yorick.>
next in thread | raw e-mail | index | archive | help
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 <dev/sound/pcm/sound.h>
#include <dev/sound/pcm/ac97.h>
+ #include "mixer_if.h"
#include <gnu/dev/sound/pci/emu10k1.h>
#include <pci/pcireg.h>
***************
*** 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
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200112221216.fBMCG2C02623>
