Skip site navigation (1)Skip section navigation (2)
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>