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 [EMAIL PROTECTED]
with "unsubscribe freebsd-hackers" in the body of the message

Reply via email to