Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 19b99fba authored by James Courtier-Dutton's avatar James Courtier-Dutton Committed by Jaroslav Kysela
Browse files

[ALSA] emu10k1: Partial support for Creative emu1212m



Modules: EMU10K1/EMU10K2 driver

Distorted sound now comes from the Audio Out socket. Still more work to do.

Signed-off-by: default avatarJames Courtier-Dutton <James@superbug.co.uk>
parent 481ba772
Loading
Loading
Loading
Loading
+1 −0
Original line number Original line Diff line number Diff line
@@ -1061,6 +1061,7 @@ struct snd_emu_chip_details {
	unsigned char spdif_bug;    /* Has Spdif phasing bug */
	unsigned char spdif_bug;    /* Has Spdif phasing bug */
	unsigned char ac97_chip;    /* Has an AC97 chip: 1 = mandatory, 2 = optional */
	unsigned char ac97_chip;    /* Has an AC97 chip: 1 = mandatory, 2 = optional */
	unsigned char ecard;        /* APS EEPROM */
	unsigned char ecard;        /* APS EEPROM */
	unsigned char emu1212m;     /* EMU 1212m card */
	const char *driver;
	const char *driver;
	const char *name;
	const char *name;
	const char *id;		/* for backward compatibility - can be NULL if not needed */
	const char *id;		/* for backward compatibility - can be NULL if not needed */
+146 −4
Original line number Original line Diff line number Diff line
@@ -42,6 +42,7 @@
#include "p16v.h"
#include "p16v.h"
#include "tina2.h"
#include "tina2.h"



/*************************************************************************
/*************************************************************************
 * EMU10K1 init / done
 * EMU10K1 init / done
 *************************************************************************/
 *************************************************************************/
@@ -217,7 +218,9 @@ static int snd_emu10k1_init(struct snd_emu10k1 *emu, int enable_ir, int resume)
		outl(HCFG_LOCKTANKCACHE_MASK | HCFG_AUTOMUTE | HCFG_JOYENABLE, emu->port + HCFG);
		outl(HCFG_LOCKTANKCACHE_MASK | HCFG_AUTOMUTE | HCFG_JOYENABLE, emu->port + HCFG);


	if (enable_ir) {	/* enable IR for SB Live */
	if (enable_ir) {	/* enable IR for SB Live */
		if (emu->audigy) {
		if ( emu->card_capabilities->emu1212m) {
			;  /* Disable all access to A_IOCFG for the emu1212m */
		} else if (emu->audigy) {
			unsigned int reg = inl(emu->port + A_IOCFG);
			unsigned int reg = inl(emu->port + A_IOCFG);
			outl(reg | A_IOCFG_GPOUT2, emu->port + A_IOCFG);
			outl(reg | A_IOCFG_GPOUT2, emu->port + A_IOCFG);
			udelay(500);
			udelay(500);
@@ -234,7 +237,9 @@ static int snd_emu10k1_init(struct snd_emu10k1 *emu, int enable_ir, int resume)
 		}
 		}
	}
	}
	
	
	if (emu->audigy) {	/* enable analog output */
	if ( emu->card_capabilities->emu1212m) {
		;  /* Disable all access to A_IOCFG for the emu1212m */
	} else if (emu->audigy) {	/* enable analog output */
		unsigned int reg = inl(emu->port + A_IOCFG);
		unsigned int reg = inl(emu->port + A_IOCFG);
		outl(reg | A_IOCFG_GPOUT0, emu->port + A_IOCFG);
		outl(reg | A_IOCFG_GPOUT0, emu->port + A_IOCFG);
	}
	}
@@ -250,7 +255,9 @@ static void snd_emu10k1_audio_enable(struct snd_emu10k1 *emu)
	outl(inl(emu->port + HCFG) | HCFG_AUDIOENABLE, emu->port + HCFG);
	outl(inl(emu->port + HCFG) | HCFG_AUDIOENABLE, emu->port + HCFG);


	/* Enable analog/digital outs on audigy */
	/* Enable analog/digital outs on audigy */
	if (emu->audigy) {
	if ( emu->card_capabilities->emu1212m) {
		;  /* Disable all access to A_IOCFG for the emu1212m */
	} else if (emu->audigy) {
		outl(inl(emu->port + A_IOCFG) & ~0x44, emu->port + A_IOCFG);
		outl(inl(emu->port + A_IOCFG) & ~0x44, emu->port + A_IOCFG);
 
 
		if (emu->card_capabilities->ca0151_chip) { /* audigy2 */
		if (emu->card_capabilities->ca0151_chip) { /* audigy2 */
@@ -542,6 +549,136 @@ static int __devinit snd_emu10k1_cardbus_init(struct snd_emu10k1 * emu)
	return 0;
	return 0;
}
}


static int snd_emu1212m_fpga_write(struct snd_emu10k1 * emu, int reg, int value)
{
	if (reg<0 || reg>0x3f)
		return 1;
	reg+=0x40; /* 0x40 upwards are registers. */
	if (value<0 || value>0x3f) /* 0 to 0x3f are values */
		return 1;
	outl(reg, emu->port + A_IOCFG);
	outl(reg | 0x80, emu->port + A_IOCFG);  /* High bit clocks the value into the fpga. */
	outl(value, emu->port + A_IOCFG);
	outl(value | 0x80 , emu->port + A_IOCFG);  /* High bit clocks the value into the fpga. */

	return 0;
}

static int snd_emu1212m_fpga_read(struct snd_emu10k1 * emu, int reg, int *value)
{
	if (reg<0 || reg>0x3f)
		return 1;
	reg+=0x40; /* 0x40 upwards are registers. */
	outl(reg, emu->port + A_IOCFG);
	outl(reg | 0x80, emu->port + A_IOCFG);  /* High bit clocks the value into the fpga. */
	*value = inl(emu->port + A_IOCFG);

	return 0;
}

static int snd_emu1212m_fpga_netlist_write(struct snd_emu10k1 * emu, int reg, int value)
{
	snd_emu1212m_fpga_write(emu, 0x00, ((reg >> 8) & 0x3f) );
	snd_emu1212m_fpga_write(emu, 0x01, (reg & 0x3f) );
	snd_emu1212m_fpga_write(emu, 0x02, ((value >> 8) & 0x3f) );
	snd_emu1212m_fpga_write(emu, 0x03, (value & 0x3f) );

	return 0;
}

static int __devinit snd_emu10k1_emu1212m_init(struct snd_emu10k1 * emu)
{
	unsigned int i;
	int tmp;

	snd_printk(KERN_ERR "emu1212m: Special config.\n");
	outl(0x0005a00c, emu->port + HCFG);
	outl(0x0005a004, emu->port + HCFG);
	outl(0x0005a000, emu->port + HCFG);
	outl(0x0005a000, emu->port + HCFG);

	snd_emu1212m_fpga_read(emu, 0x22, &tmp );
	snd_emu1212m_fpga_read(emu, 0x23, &tmp );
	snd_emu1212m_fpga_read(emu, 0x24, &tmp );
	snd_emu1212m_fpga_write(emu, 0x04, 0x01 );
	snd_emu1212m_fpga_read(emu, 0x0b, &tmp );
	snd_emu1212m_fpga_write(emu, 0x0b, 0x01 );
	snd_emu1212m_fpga_read(emu, 0x10, &tmp );
	snd_emu1212m_fpga_write(emu, 0x10, 0x00 );
	snd_emu1212m_fpga_read(emu, 0x11, &tmp );
	snd_emu1212m_fpga_write(emu, 0x11, 0x30 );
	snd_emu1212m_fpga_read(emu, 0x13, &tmp );
	snd_emu1212m_fpga_write(emu, 0x13, 0x0f );
	snd_emu1212m_fpga_read(emu, 0x11, &tmp );
	snd_emu1212m_fpga_write(emu, 0x11, 0x30 );
	snd_emu1212m_fpga_read(emu, 0x0a, &tmp );
	snd_emu1212m_fpga_write(emu, 0x0a, 0x10 );
	snd_emu1212m_fpga_write(emu, 0x0c, 0x19 );
	snd_emu1212m_fpga_write(emu, 0x12, 0x0c );
	snd_emu1212m_fpga_write(emu, 0x09, 0x0f );
	snd_emu1212m_fpga_write(emu, 0x06, 0x00 );
	snd_emu1212m_fpga_write(emu, 0x05, 0x00 );
	snd_emu1212m_fpga_write(emu, 0x0e, 0x12 );
	snd_emu1212m_fpga_netlist_write(emu, 0x0000, 0x0200);
	snd_emu1212m_fpga_netlist_write(emu, 0x0001, 0x0201);
	snd_emu1212m_fpga_netlist_write(emu, 0x0002, 0x0500);
	snd_emu1212m_fpga_netlist_write(emu, 0x0003, 0x0501);
	snd_emu1212m_fpga_netlist_write(emu, 0x0004, 0x0400);
	snd_emu1212m_fpga_netlist_write(emu, 0x0005, 0x0401);
	snd_emu1212m_fpga_netlist_write(emu, 0x0006, 0x0402);
	snd_emu1212m_fpga_netlist_write(emu, 0x0007, 0x0403);
	snd_emu1212m_fpga_netlist_write(emu, 0x0008, 0x0404);
	snd_emu1212m_fpga_netlist_write(emu, 0x0009, 0x0405);
	snd_emu1212m_fpga_netlist_write(emu, 0x000a, 0x0406);
	snd_emu1212m_fpga_netlist_write(emu, 0x000b, 0x0407);
	snd_emu1212m_fpga_netlist_write(emu, 0x000c, 0x0100);
	snd_emu1212m_fpga_netlist_write(emu, 0x000d, 0x0104);
	snd_emu1212m_fpga_netlist_write(emu, 0x000e, 0x0200);
	snd_emu1212m_fpga_netlist_write(emu, 0x000f, 0x0201);
	for (i=0;i < 0x20;i++) {
		snd_emu1212m_fpga_netlist_write(emu, 0x0100+i, 0x0000);
	}
	for (i=0;i < 4;i++) {
		snd_emu1212m_fpga_netlist_write(emu, 0x0200+i, 0x0000);
	}
	for (i=0;i < 7;i++) {
		snd_emu1212m_fpga_netlist_write(emu, 0x0300+i, 0x0000);
	}
	for (i=0;i < 7;i++) {
		snd_emu1212m_fpga_netlist_write(emu, 0x0400+i, 0x0000);
	}
	snd_emu1212m_fpga_netlist_write(emu, 0x0500, 0x0108);
	snd_emu1212m_fpga_netlist_write(emu, 0x0501, 0x010c);
	snd_emu1212m_fpga_netlist_write(emu, 0x0600, 0x0110);
	snd_emu1212m_fpga_netlist_write(emu, 0x0601, 0x0114);
	snd_emu1212m_fpga_netlist_write(emu, 0x0700, 0x0118);
	snd_emu1212m_fpga_netlist_write(emu, 0x0701, 0x011c);
	snd_emu1212m_fpga_write(emu, 0x07, 0x01 );

	snd_emu1212m_fpga_read(emu, 0x21, &tmp );

	outl(0x0000a000, emu->port + HCFG);
	outl(0x0000a001, emu->port + HCFG);
	/* Initial boot complete. Now patches */

	snd_emu1212m_fpga_read(emu, 0x21, &tmp );
	snd_emu1212m_fpga_write(emu, 0x0c, 0x19 );
	snd_emu1212m_fpga_write(emu, 0x12, 0x0c );
	snd_emu1212m_fpga_write(emu, 0x0c, 0x19 );
	snd_emu1212m_fpga_write(emu, 0x12, 0x0c );
	snd_emu1212m_fpga_read(emu, 0x0a, &tmp );
	snd_emu1212m_fpga_write(emu, 0x0a, 0x10 );

	snd_emu1212m_fpga_read(emu, 0x20, &tmp );
	snd_emu1212m_fpga_read(emu, 0x21, &tmp );

	snd_emu1212m_fpga_netlist_write(emu, 0x0300, 0x0312);
	snd_emu1212m_fpga_netlist_write(emu, 0x0301, 0x0313);
	snd_emu1212m_fpga_netlist_write(emu, 0x0200, 0x0302);
	snd_emu1212m_fpga_netlist_write(emu, 0x0201, 0x0303);

	return 0;
}
/*
/*
 *  Create the EMU10K1 instance
 *  Create the EMU10K1 instance
 */
 */
@@ -623,7 +760,7 @@ static struct snd_emu_chip_details emu_chip_details[] = {
	 .id = "EMU1212m",
	 .id = "EMU1212m",
	 .emu10k2_chip = 1,
	 .emu10k2_chip = 1,
	 .ca0102_chip = 1,
	 .ca0102_chip = 1,
	 .ecard = 1} ,
	 .emu1212m = 1} ,
	/* Tested by James@superbug.co.uk 3rd July 2005 */
	/* Tested by James@superbug.co.uk 3rd July 2005 */
	{.vendor = 0x1102, .device = 0x0004, .subsystem = 0x20071102,
	{.vendor = 0x1102, .device = 0x0004, .subsystem = 0x20071102,
	 .driver = "Audigy2", .name = "Audigy 4 PRO [SB0380]", 
	 .driver = "Audigy2", .name = "Audigy 4 PRO [SB0380]", 
@@ -1013,6 +1150,11 @@ int __devinit snd_emu10k1_create(struct snd_card *card,
	} else if (emu->card_capabilities->ca_cardbus_chip) {
	} else if (emu->card_capabilities->ca_cardbus_chip) {
		if ((err = snd_emu10k1_cardbus_init(emu)) < 0)
		if ((err = snd_emu10k1_cardbus_init(emu)) < 0)
			goto error;
			goto error;
 	} else if (emu->card_capabilities->emu1212m) {
 		if ((err = snd_emu10k1_emu1212m_init(emu)) < 0) {
 			snd_emu10k1_free(emu);
 			return err;
 		}
	} else {
	} else {
		/* 5.1: Enable the additional AC97 Slots. If the emu10k1 version
		/* 5.1: Enable the additional AC97 Slots. If the emu10k1 version
			does not support this, it shouldn't do any harm */
			does not support this, it shouldn't do any harm */
+9 −0
Original line number Original line Diff line number Diff line
@@ -1102,6 +1102,14 @@ static int __devinit _snd_emu10k1_audigy_init_efx(struct snd_emu10k1 *emu)
	/* stop FX processor */
	/* stop FX processor */
	snd_emu10k1_ptr_write(emu, A_DBG, 0, (emu->fx8010.dbg = 0) | A_DBG_SINGLE_STEP);
	snd_emu10k1_ptr_write(emu, A_DBG, 0, (emu->fx8010.dbg = 0) | A_DBG_SINGLE_STEP);


#if 0
	/* FIX: jcd test */
	for (z = 0; z < 80; z=z+2) {
		A_OP(icode, &ptr, iACC3, A_EXTOUT(z), A_FXBUS(FXBUS_PCM_LEFT_FRONT), A_C_00000000, A_C_00000000); /* left */
		A_OP(icode, &ptr, iACC3, A_EXTOUT(z+1), A_FXBUS(FXBUS_PCM_RIGHT_FRONT), A_C_00000000, A_C_00000000); /* right */
	}
#endif /* jcd test */
#if 1
	/* PCM front Playback Volume (independent from stereo mix) */
	/* PCM front Playback Volume (independent from stereo mix) */
	A_OP(icode, &ptr, iMAC0, A_GPR(playback), A_C_00000000, A_GPR(gpr), A_FXBUS(FXBUS_PCM_LEFT_FRONT));
	A_OP(icode, &ptr, iMAC0, A_GPR(playback), A_C_00000000, A_GPR(gpr), A_FXBUS(FXBUS_PCM_LEFT_FRONT));
	A_OP(icode, &ptr, iMAC0, A_GPR(playback+1), A_C_00000000, A_GPR(gpr+1), A_FXBUS(FXBUS_PCM_RIGHT_FRONT));
	A_OP(icode, &ptr, iMAC0, A_GPR(playback+1), A_C_00000000, A_GPR(gpr+1), A_FXBUS(FXBUS_PCM_RIGHT_FRONT));
@@ -1447,6 +1455,7 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input))
		A_OP(icode, &ptr, iACC3, A_FXBUS2(z), A_C_00000000, A_C_00000000, A_EXTIN(z));
		A_OP(icode, &ptr, iACC3, A_FXBUS2(z), A_C_00000000, A_C_00000000, A_EXTIN(z));
	}
	}
	
	
#endif /* JCD test */
	/*
	/*
	 * ok, set up done..
	 * ok, set up done..
	 */
	 */
+3 −1
Original line number Original line Diff line number Diff line
@@ -959,7 +959,9 @@ int __devinit snd_emu10k1_mixer(struct snd_emu10k1 *emu,
			return err;
			return err;
	}
	}


	if (emu->audigy) {
	if ( emu->card_capabilities->emu1212m) {
		;  /* Disable the snd_audigy_spdif_shared_spdif */
	} else if (emu->audigy) {
		if ((kctl = snd_ctl_new1(&snd_audigy_shared_spdif, emu)) == NULL)
		if ((kctl = snd_ctl_new1(&snd_audigy_shared_spdif, emu)) == NULL)
			return -ENOMEM;
			return -ENOMEM;
		if ((err = snd_ctl_add(card, kctl)))
		if ((err = snd_ctl_add(card, kctl)))