Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/dev/pci PR/25731: Adam K kirchhoff: Audigy support with ...
details: https://anonhg.NetBSD.org/src/rev/19d1d31eaf86
branches: trunk
changeset: 567012:19d1d31eaf86
user: christos <christos%NetBSD.org@localhost>
date: Thu May 27 20:20:52 2004 +0000
description:
PR/25731: Adam K kirchhoff: Audigy support with the emuxki driver.
diffstat:
sys/dev/pci/emuxki.c | 473 ++++++++++++++++++++++++++++++++++++-----------
sys/dev/pci/emuxkireg.h | 124 +++++++++++-
sys/dev/pci/emuxkivar.h | 11 +-
sys/dev/pci/pcidevs | 3 +-
4 files changed, 484 insertions(+), 127 deletions(-)
diffs (truncated from 1073 to 300 lines):
diff -r 0dd3c5aa3bad -r 19d1d31eaf86 sys/dev/pci/emuxki.c
--- a/sys/dev/pci/emuxki.c Thu May 27 19:19:00 2004 +0000
+++ b/sys/dev/pci/emuxki.c Thu May 27 20:20:52 2004 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: emuxki.c,v 1.34 2004/05/23 11:37:25 tsutsui Exp $ */
+/* $NetBSD: emuxki.c,v 1.35 2004/05/27 20:20:52 christos Exp $ */
/*-
* Copyright (c) 2001 The NetBSD Foundation, Inc.
@@ -56,7 +56,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: emuxki.c,v 1.34 2004/05/23 11:37:25 tsutsui Exp $");
+__KERNEL_RCSID(0, "$NetBSD: emuxki.c,v 1.35 2004/05/27 20:20:52 christos Exp $");
#include <sys/param.h>
#include <sys/device.h>
@@ -114,6 +114,7 @@
static int emuxki_voice_set_bufparms(struct emuxki_voice *,
void *, u_int32_t, u_int16_t);
static void emuxki_voice_commit_parms(struct emuxki_voice *);
+static int emuxki_voice_adc_rate(struct emuxki_voice *);
static u_int32_t emuxki_voice_curaddr(struct emuxki_voice *);
static void emuxki_voice_start(struct emuxki_voice *,
void (*) (void *), void *);
@@ -210,16 +211,12 @@
NULL, /* dev_ioctl */
};
-static const int emuxki_recsrc_adcrates[] =
- { 48000, 44100, 32000, 24000, 22050, 16000, 11025, 8000, -1 };
#if 0
static const int emuxki_recsrc_intrmasks[EMU_NUMRECSRCS] =
{ EMU_INTE_MICBUFENABLE, EMU_INTE_ADCBUFENABLE, EMU_INTE_EFXBUFENABLE };
#endif
static const u_int32_t emuxki_recsrc_bufaddrreg[EMU_NUMRECSRCS] =
{ EMU_MICBA, EMU_ADCBA, EMU_FXBA };
-static const u_int32_t emuxki_recsrc_idxreg[EMU_NUMRECSRCS] =
- { EMU_RECIDX(EMU_MICIDX), EMU_RECIDX(EMU_ADCIDX), EMU_RECIDX(EMU_FXIDX) };
static const u_int32_t emuxki_recsrc_szreg[EMU_NUMRECSRCS] =
{ EMU_MICBS, EMU_ADCBS, EMU_FXBS };
static const int emuxki_recbuf_sz[] = {
@@ -335,13 +332,27 @@
if ((err = emuxki_init(sc)))
return (err);
- bus_space_write_4(sc->sc_iot, sc->sc_ioh, EMU_HCFG,
- EMU_HCFG_AUDIOENABLE | EMU_HCFG_JOYENABLE |
- EMU_HCFG_LOCKTANKCACHE_MASK | EMU_HCFG_AUTOMUTE);
+ if (sc->sc_type & EMUXKI_AUDIGY2) {
+ bus_space_write_4(sc->sc_iot, sc->sc_ioh, EMU_HCFG,
+ EMU_HCFG_AUDIOENABLE | EMU_HCFG_AC3ENABLE_CDSPDIF |
+ EMU_HCFG_AC3ENABLE_GPSPDIF | EMU_HCFG_AUTOMUTE);
+ } else if (sc->sc_type & EMUXKI_AUDIGY) {
+ bus_space_write_4(sc->sc_iot, sc->sc_ioh, EMU_HCFG,
+ EMU_HCFG_AUDIOENABLE | EMU_HCFG_AUTOMUTE);
+ } else {
+ bus_space_write_4(sc->sc_iot, sc->sc_ioh, EMU_HCFG,
+ EMU_HCFG_AUDIOENABLE |
+ EMU_HCFG_LOCKTANKCACHE_MASK | EMU_HCFG_AUTOMUTE);
+ }
bus_space_write_4(sc->sc_iot, sc->sc_ioh, EMU_INTE,
bus_space_read_4(sc->sc_iot, sc->sc_ioh, EMU_INTE) |
EMU_INTE_VOLINCRENABLE | EMU_INTE_VOLDECRENABLE |
EMU_INTE_MUTEENABLE);
+ if (sc->sc_type & EMUXKI_AUDIGY2) {
+ bus_space_write_4(sc->sc_iot, sc->sc_ioh, EMU_A_IOCFG,
+ EMU_A_IOCFG_GPOUT0 |
+ bus_space_read_4(sc->sc_iot, sc->sc_ioh, EMU_A_IOCFG));
+ }
/* No multiple voice support for now */
sc->pvoice = sc->rvoice = NULL;
@@ -366,14 +377,17 @@
{
struct pci_attach_args *pa = aux;
- if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_CREATIVELABS &&
- (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_CREATIVELABS_SBLIVE ||
- PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_CREATIVELABS_SBLIVE2))
- {
- return (1);
+ if (PCI_VENDOR(pa->pa_id) != PCI_VENDOR_CREATIVELABS)
+ return 0;
+
+ switch (PCI_PRODUCT(pa->pa_id)) {
+ case PCI_PRODUCT_CREATIVELABS_SBLIVE:
+ case PCI_PRODUCT_CREATIVELABS_SBLIVE2:
+ case PCI_PRODUCT_CREATIVELABS_AUDIGY:
+ return 1;
+ default:
+ return 0;
}
-
- return (0);
}
static void
@@ -421,13 +435,34 @@
bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_ios);
return;
}
- aprint_normal("%s: interrupting at %s\n", sc->sc_dev.dv_xname, intrstr);
+
+ /* XXX it's unknown wheather APS is made from Audigy as well */
+ if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_CREATIVELABS_AUDIGY) {
+ sc->sc_type = EMUXKI_AUDIGY;
+ if (PCI_REVISION(pa->pa_class) == 0x04) {
+ sc->sc_type |= EMUXKI_AUDIGY2;
+ strlcpy(sc->sc_audv.name, "Audigy2", sizeof sc->sc_audv.name);
+ } else {
+ strlcpy(sc->sc_audv.name, "Audigy", sizeof sc->sc_audv.name);
+ }
+ } else if (pci_conf_read(pa->pa_pc, pa->pa_tag,
+ PCI_SUBSYS_ID_REG) == EMU_SUBSYS_APS) {
+ sc->sc_type = EMUXKI_APS;
+ strlcpy(sc->sc_audv.name, "E-mu APS", sizeof sc->sc_audv.name);
+ } else {
+ sc->sc_type = EMUXKI_SBLIVE;
+ strlcpy(sc->sc_audv.name, "SB Live!", sizeof sc->sc_audv.name);
+ }
+ snprintf(sc->sc_audv.version, sizeof sc->sc_audv.version, "0x%02x",
+ PCI_REVISION(pa->pa_class));
+ strlcpy(sc->sc_audv.config, "emuxki", sizeof sc->sc_audv.config);
if (emuxki_scinit(sc) || emuxki_ac97_init(sc) ||
(sc->sc_audev = audio_attach_mi(&emuxki_hw_if, sc, self)) == NULL) {
emuxki_pci_shutdown(sc);
return;
}
+ aprint_normal("%s: interrupting at %s\n", sc->sc_dev.dv_xname, intrstr);
#if 0
sc->rsourcectl.dev =
sc->codecif->vtbl->get_portnum_by_name(sc->codec_if, AudioCrecord,
@@ -530,7 +565,9 @@
u_int8_t size, offset = 0;
int s;
- ptr = ((((u_int32_t) reg) << 16) & EMU_PTR_ADDR_MASK) |
+ ptr = ((((u_int32_t) reg) << 16) &
+ (sc->sc_type & EMUXKI_AUDIGY ?
+ EMU_A_PTR_ADDR_MASK : EMU_PTR_ADDR_MASK)) |
(chano & EMU_PTR_CHNO_MASK);
if (reg & 0xff000000) {
size = (reg >> 24) & 0x3f;
@@ -555,7 +592,9 @@
u_int8_t size, offset;
int s;
- ptr = ((((u_int32_t) reg) << 16) & EMU_PTR_ADDR_MASK) |
+ ptr = ((((u_int32_t) reg) << 16) &
+ (sc->sc_type & EMUXKI_AUDIGY ?
+ EMU_A_PTR_ADDR_MASK : EMU_PTR_ADDR_MASK)) |
(chano & EMU_PTR_CHNO_MASK);
if (reg & 0xff000000) {
size = (reg >> 24) & 0x3f;
@@ -576,21 +615,34 @@
static void
emuxki_write_micro(struct emuxki_softc *sc, u_int32_t pc, u_int32_t data)
{
- emuxki_write(sc, 0, EMU_MICROCODEBASE + pc, data);
+ emuxki_write(sc, 0,
+ (sc->sc_type & EMUXKI_AUDIGY ?
+ EMU_A_MICROCODEBASE : EMU_MICROCODEBASE) + pc,
+ data);
}
static void
emuxki_dsp_addop(struct emuxki_softc *sc, u_int16_t *pc, u_int8_t op,
u_int16_t r, u_int16_t a, u_int16_t x, u_int16_t y)
{
- emuxki_write_micro(sc, *pc << 1,
- ((x << 10) & EMU_DSP_LOWORD_OPX_MASK) |
- (y & EMU_DSP_LOWORD_OPY_MASK));
- emuxki_write_micro(sc, (*pc << 1) + 1,
- ((op << 20) & EMU_DSP_HIWORD_OPCODE_MASK) |
- ((r << 10) & EMU_DSP_HIWORD_RESULT_MASK) |
- (a & EMU_DSP_HIWORD_OPA_MASK));
- (*pc)++;
+ if (sc->sc_type & EMUXKI_AUDIGY) {
+ emuxki_write_micro(sc, *pc << 1,
+ ((x << 12) & EMU_A_DSP_LOWORD_OPX_MASK) |
+ (y & EMU_A_DSP_LOWORD_OPY_MASK));
+ emuxki_write_micro(sc, (*pc << 1) + 1,
+ ((op << 24) & EMU_A_DSP_HIWORD_OPCODE_MASK) |
+ ((r << 12) & EMU_A_DSP_HIWORD_RESULT_MASK) |
+ (a & EMU_A_DSP_HIWORD_OPA_MASK));
+ } else {
+ emuxki_write_micro(sc, *pc << 1,
+ ((x << 10) & EMU_DSP_LOWORD_OPX_MASK) |
+ (y & EMU_DSP_LOWORD_OPY_MASK));
+ emuxki_write_micro(sc, (*pc << 1) + 1,
+ ((op << 20) & EMU_DSP_HIWORD_OPCODE_MASK) |
+ ((r << 10) & EMU_DSP_HIWORD_RESULT_MASK) |
+ (a & EMU_DSP_HIWORD_OPA_MASK));
+ }
+ (*pc)++;
}
/* init and shutdown */
@@ -608,43 +660,86 @@
emuxki_write(sc, 0, EMU_TANKMEMADDRREGBASE + pc, 0);
}
pc = 0;
- /* AC97 Out (l/r) = AC97 In (l/r) + FX[0/1] * 4 */
- emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_MACINTS,
- EMU_DSP_OUTL(EMU_DSP_OUT_AC97),
- EMU_DSP_CST(0),
- EMU_DSP_FX(0), EMU_DSP_CST(4));
- emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_MACINTS,
- EMU_DSP_OUTR(EMU_DSP_OUT_AC97),
- EMU_DSP_CST(0),
- EMU_DSP_FX(1), EMU_DSP_CST(4));
- /* Rear channel OUT (l/r) = FX[2/3] * 4 */
+ if (sc->sc_type & EMUXKI_AUDIGY) {
+ /* AC97 Out (l/r) = AC97 In (l/r) + FX[0/1] * 4 */
+ emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_MACINTS,
+ EMU_A_DSP_OUTL(EMU_A_DSP_OUT_A_FRONT),
+ EMU_A_DSP_CST(0),
+ EMU_DSP_FX(0), EMU_A_DSP_CST(4));
+ emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_MACINTS,
+ EMU_A_DSP_OUTR(EMU_A_DSP_OUT_A_FRONT),
+ EMU_A_DSP_CST(0),
+ EMU_DSP_FX(1), EMU_A_DSP_CST(4));
+
+ /* Rear channel OUT (l/r) = FX[2/3] * 4 */
#if 0
- emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_MACINTS,
- EMU_DSP_OUTL(EMU_DSP_OUT_RCHAN),
- EMU_DSP_OUTL(EMU_DSP_OUT_AC97),
- EMU_DSP_FX(0), EMU_DSP_CST(4));
- emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_MACINTS,
- EMU_DSP_OUTR(EMU_DSP_OUT_RCHAN),
- EMU_DSP_OUTR(EMU_DSP_OUT_AC97),
- EMU_DSP_FX(1), EMU_DSP_CST(4));
+ emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_MACINTS,
+ EMU_A_DSP_OUTL(EMU_A_DSP_OUT_A_REAR),
+ EMU_A_DSP_OUTL(EMU_A_DSP_OUT_A_FRONT),
+ EMU_DSP_FX(0), EMU_A_DSP_CST(4));
+ emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_MACINTS,
+ EMU_A_DSP_OUTR(EMU_A_DSP_OUT_A_REAR),
+ EMU_A_DSP_OUTR(EMU_A_DSP_OUT_A_FRONT),
+ EMU_DSP_FX(1), EMU_A_DSP_CST(4));
#endif
- /* ADC recording (l/r) = AC97 In (l/r) */
- emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_ACC3,
- EMU_DSP_OUTL(EMU_DSP_OUT_ADC),
- EMU_DSP_INL(EMU_DSP_IN_AC97),
- EMU_DSP_CST(0), EMU_DSP_CST(0));
- emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_ACC3,
- EMU_DSP_OUTR(EMU_DSP_OUT_ADC),
- EMU_DSP_INR(EMU_DSP_IN_AC97),
- EMU_DSP_CST(0), EMU_DSP_CST(0));
- /* zero out the rest of the microcode */
- while (pc < 512)
+ /* ADC recording (l/r) = AC97 In (l/r) */
+ emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_ACC3,
+ EMU_A_DSP_OUTL(EMU_A_DSP_OUT_ADC),
+ EMU_A_DSP_INL(EMU_DSP_IN_AC97),
+ EMU_A_DSP_CST(0), EMU_A_DSP_CST(0));
emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_ACC3,
- EMU_DSP_CST(0), EMU_DSP_CST(0),
+ EMU_A_DSP_OUTR(EMU_A_DSP_OUT_ADC),
+ EMU_A_DSP_INR(EMU_DSP_IN_AC97),
+ EMU_A_DSP_CST(0), EMU_A_DSP_CST(0));
+
+ /* zero out the rest of the microcode */
+ while (pc < 512)
+ emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_ACC3,
+ EMU_A_DSP_CST(0), EMU_A_DSP_CST(0),
+ EMU_A_DSP_CST(0), EMU_A_DSP_CST(0));
+
+ emuxki_write(sc, 0, EMU_A_DBG, 0); /* Is it really necessary ? */
+ } else {
+ /* AC97 Out (l/r) = AC97 In (l/r) + FX[0/1] * 4 */
+ emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_MACINTS,
+ EMU_DSP_OUTL(EMU_DSP_OUT_A_FRONT),
+ EMU_DSP_CST(0),
+ EMU_DSP_FX(0), EMU_DSP_CST(4));
+ emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_MACINTS,
+ EMU_DSP_OUTR(EMU_DSP_OUT_A_FRONT),
+ EMU_DSP_CST(0),
+ EMU_DSP_FX(1), EMU_DSP_CST(4));
+
+ /* Rear channel OUT (l/r) = FX[2/3] * 4 */
+#if 0
+ emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_MACINTS,
+ EMU_DSP_OUTL(EMU_DSP_OUT_AD_REAR),
+ EMU_DSP_OUTL(EMU_DSP_OUT_A_FRONT),
+ EMU_DSP_FX(0), EMU_DSP_CST(4));
+ emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_MACINTS,
+ EMU_DSP_OUTR(EMU_DSP_OUT_AD_REAR),
+ EMU_DSP_OUTR(EMU_DSP_OUT_A_FRONT),
+ EMU_DSP_FX(1), EMU_DSP_CST(4));
+#endif
+ /* ADC recording (l/r) = AC97 In (l/r) */
+ emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_ACC3,
+ EMU_DSP_OUTL(EMU_DSP_OUT_ADC),
Home |
Main Index |
Thread Index |
Old Index