Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/dev/pci Work-in-progress of AC'97 modem support. Current...
details: https://anonhg.NetBSD.org/src/rev/ff3f40dcd189
branches: trunk
changeset: 580013:ff3f40dcd189
user: jmcneill <jmcneill%NetBSD.org@localhost>
date: Mon Apr 04 19:41:50 2005 +0000
description:
Work-in-progress of AC'97 modem support. Currently disabled by default
(can be enabled by options AUICH_ATTACH_MODEM), and untested. Shouldn't
have any impact on auich audio capabilities.
diffstat:
sys/dev/pci/auich.c | 240 ++++++++++++++++++++++++++++++++++++---------------
1 files changed, 167 insertions(+), 73 deletions(-)
diffs (truncated from 491 to 300 lines):
diff -r b3c8ea192577 -r ff3f40dcd189 sys/dev/pci/auich.c
--- a/sys/dev/pci/auich.c Mon Apr 04 19:11:18 2005 +0000
+++ b/sys/dev/pci/auich.c Mon Apr 04 19:41:50 2005 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: auich.c,v 1.90 2005/03/11 22:29:16 mycroft Exp $ */
+/* $NetBSD: auich.c,v 1.91 2005/04/04 19:41:50 jmcneill Exp $ */
/*-
* Copyright (c) 2000, 2004, 2005 The NetBSD Foundation, Inc.
@@ -118,7 +118,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: auich.c,v 1.90 2005/03/11 22:29:16 mycroft Exp $");
+__KERNEL_RCSID(0, "$NetBSD: auich.c,v 1.91 2005/04/04 19:41:50 jmcneill Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -186,6 +186,7 @@
struct ac97_codec_if *codec_if;
struct ac97_host_if host_if;
+ int codecnum;
/* DMA scatter-gather lists. */
bus_dmamap_t sc_cddmamap;
@@ -222,8 +223,12 @@
uint32_t sc_ac97_clock;
int sc_ac97_clock_mib;
-#define AUICH_NFORMATS 3
- struct audio_format sc_formats[AUICH_NFORMATS];
+ int sc_modem_offset;
+
+#define AUICH_AUDIO_NFORMATS 3
+#define AUICH_MODEM_NFORMATS 1
+ struct audio_format sc_audio_formats[AUICH_AUDIO_NFORMATS];
+ struct audio_format sc_modem_formats[AUICH_MODEM_NFORMATS];
struct audio_encoding_set *sc_encodings;
};
@@ -287,6 +292,7 @@
static int auich_read_codec(void *, uint8_t, uint16_t *);
static int auich_write_codec(void *, uint8_t, uint16_t);
static int auich_reset_codec(void *);
+static enum ac97_host_flags auich_flags_codec(void *);
const struct audio_hw_if auich_hw_if = {
NULL, /* open */
@@ -318,9 +324,10 @@
NULL, /* dev_ioctl */
};
+#define AUICH_FORMATS_1CH 0
#define AUICH_FORMATS_4CH 1
#define AUICH_FORMATS_6CH 2
-static const struct audio_format auich_formats[AUICH_NFORMATS] = {
+static const struct audio_format auich_audio_formats[AUICH_AUDIO_NFORMATS] = {
{NULL, AUMODE_PLAY | AUMODE_RECORD, AUDIO_ENCODING_SLINEAR_LE, 16, 16,
2, AUFMT_STEREO, 0, {8000, 48000}},
{NULL, AUMODE_PLAY, AUDIO_ENCODING_SLINEAR_LE, 16, 16,
@@ -329,6 +336,11 @@
6, AUFMT_DOLBY_5_1, 0, {8000, 48000}},
};
+static const struct audio_format auich_modem_formats[AUICH_MODEM_NFORMATS] = {
+ {NULL, AUMODE_PLAY | AUMODE_RECORD, AUDIO_ENCODING_SLINEAR_LE, 16, 16,
+ 1, AUFMT_MONAURAL, 0, {8000, 16000}},
+};
+
#define PCI_ID_CODE0(v, p) PCI_ID_CODE(PCI_VENDOR_##v, PCI_PRODUCT_##v##_##p)
#define PCIID_ICH PCI_ID_CODE0(INTEL, 82801AA_ACA)
#define PCIID_ICH0 PCI_ID_CODE0(INTEL, 82801AB_ACA)
@@ -348,11 +360,15 @@
#define PCIID_AMD768 PCI_ID_CODE0(AMD, PBC768_AC)
#define PCIID_AMD8111 PCI_ID_CODE0(AMD, PBC8111_AC)
-static const struct auich_devtype {
+#define PCIID_ICH4MODEM PCI_ID_CODE0(INTEL, 82801DB_MOD)
+
+struct auich_devtype {
pcireg_t id;
const char *name;
const char *shortname; /* must be less than 11 characters */
-} auich_devices[] = {
+};
+
+static const struct auich_devtype auich_audio_devices[] = {
{ PCIID_ICH, "i82801AA (ICH) AC-97 Audio", "ICH" },
{ PCIID_ICH0, "i82801AB (ICH0) AC-97 Audio", "ICH0" },
{ PCIID_ICH2, "i82801BA (ICH2) AC-97 Audio", "ICH2" },
@@ -373,8 +389,15 @@
{ 0, NULL, NULL },
};
+static const struct auich_devtype auich_modem_devices[] = {
+#ifdef AUICH_ATTACH_MODEM
+ { PCIID_ICH4MODEM, "i82801DB (ICH4) AC-97 Modem", "ICH4MODEM" },
+#endif
+ { 0, NULL, NULL },
+};
+
static const struct auich_devtype *
-auich_lookup(struct pci_attach_args *pa)
+auich_lookup(struct pci_attach_args *pa, const struct auich_devtype *auich_devices)
{
const struct auich_devtype *d;
@@ -392,7 +415,9 @@
struct pci_attach_args *pa;
pa = aux;
- if (auich_lookup(pa) != NULL)
+ if (auich_lookup(pa, auich_audio_devices) != NULL)
+ return 1;
+ if (auich_lookup(pa, auich_modem_devices) != NULL)
return 1;
return 0;
@@ -407,23 +432,31 @@
pcireg_t v;
const char *intrstr;
const struct auich_devtype *d;
- struct sysctlnode *node;
+ struct sysctlnode *node, *node_ac97clock;
int err, node_mib, i;
sc = (struct auich_softc *)self;
pa = aux;
- aprint_naive(": Audio controller\n");
- d = auich_lookup(pa);
- if (d == NULL)
+ if ((d = auich_lookup(pa, auich_modem_devices)) != NULL)
+ sc->sc_modem_offset = 0x10;
+ else if ((d = auich_lookup(pa, auich_audio_devices)) != NULL)
+ sc->sc_modem_offset = 0;
+ else
panic("auich_attach: impossible");
+ if (sc->sc_modem_offset == 0)
+ aprint_naive(": Audio controller\n");
+ else
+ aprint_naive(": Modem controller\n");
+
sc->sc_pc = pa->pa_pc;
sc->sc_pt = pa->pa_tag;
aprint_normal(": %s\n", d->name);
- if (d->id == PCIID_ICH4 || d->id == PCIID_ICH5 || d->id == PCIID_ICH6) {
+ if (d->id == PCIID_ICH4 || d->id == PCIID_ICH5 || d->id == PCIID_ICH6
+ || d->id == PCIID_ICH4MODEM) {
/*
* Use native mode for ICH4/ICH5/ICH6
*/
@@ -524,32 +557,41 @@
DPRINTF(ICH_DEBUG_DMA, ("auich_attach: lists %p %p %p\n",
sc->pcmo.dmalist, sc->pcmi.dmalist, sc->mici.dmalist));
+ sc->codecnum = sc->sc_modem_offset == 0 ? 0 : 1;
+
sc->host_if.arg = sc;
sc->host_if.attach = auich_attach_codec;
sc->host_if.read = auich_read_codec;
sc->host_if.write = auich_write_codec;
sc->host_if.reset = auich_reset_codec;
+ sc->host_if.flags = auich_flags_codec;
if (ac97_attach(&sc->host_if, self) != 0)
return;
/* setup audio_format */
- memcpy(sc->sc_formats, auich_formats, sizeof(auich_formats));
- if (!AC97_IS_4CH(sc->codec_if))
- AUFMT_INVALIDATE(&sc->sc_formats[AUICH_FORMATS_4CH]);
- if (!AC97_IS_6CH(sc->codec_if))
- AUFMT_INVALIDATE(&sc->sc_formats[AUICH_FORMATS_6CH]);
- if (AC97_IS_FIXED_RATE(sc->codec_if)) {
- for (i = 0; i < AUICH_NFORMATS; i++) {
- sc->sc_formats[i].frequency_type = 1;
- sc->sc_formats[i].frequency[0] = 48000;
+ if (sc->sc_modem_offset == 0) {
+ memcpy(sc->sc_audio_formats, auich_audio_formats, sizeof(auich_audio_formats));
+ if (!AC97_IS_4CH(sc->codec_if))
+ AUFMT_INVALIDATE(&sc->sc_audio_formats[AUICH_FORMATS_4CH]);
+ if (!AC97_IS_6CH(sc->codec_if))
+ AUFMT_INVALIDATE(&sc->sc_audio_formats[AUICH_FORMATS_6CH]);
+ if (AC97_IS_FIXED_RATE(sc->codec_if)) {
+ for (i = 0; i < AUICH_AUDIO_NFORMATS; i++) {
+ sc->sc_audio_formats[i].frequency_type = 1;
+ sc->sc_audio_formats[i].frequency[0] = 48000;
+ }
}
+ if (0 != auconv_create_encodings(sc->sc_audio_formats, AUICH_AUDIO_NFORMATS,
+ &sc->sc_encodings))
+ return;
+ } else {
+ memcpy(sc->sc_modem_formats, auich_modem_formats, sizeof(auich_modem_formats));
+ if (0 != auconv_create_encodings(sc->sc_modem_formats, AUICH_MODEM_NFORMATS,
+ &sc->sc_encodings))
+ return;
}
- if (0 != auconv_create_encodings(sc->sc_formats, AUICH_NFORMATS,
- &sc->sc_encodings)) {
- return;
- }
/* Watch for power change */
sc->sc_suspend = PWR_RESUME;
@@ -558,8 +600,9 @@
config_interrupts(self, auich_finish_attach);
/* sysctl setup */
- if (AC97_IS_FIXED_RATE(sc->codec_if))
+ if (AC97_IS_FIXED_RATE(sc->codec_if) && sc->sc_modem_offset == 0)
return;
+
err = sysctl_createv(&sc->sc_log, 0, NULL, NULL, 0,
CTLTYPE_NODE, "hw", NULL, NULL, 0, NULL, 0,
CTL_HW, CTL_EOL);
@@ -571,15 +614,19 @@
if (err != 0)
goto sysctl_err;
node_mib = node->sysctl_num;
- /* passing the sc address instead of &sc->sc_ac97_clock */
- err = sysctl_createv(&sc->sc_log, 0, NULL, &node, CTLFLAG_READWRITE,
- CTLTYPE_INT, "ac97rate",
- SYSCTL_DESCR("AC'97 codec link rate"),
- auich_sysctl_verify, 0, sc, 0,
- CTL_HW, node_mib, CTL_CREATE, CTL_EOL);
- if (err != 0)
- goto sysctl_err;
- sc->sc_ac97_clock_mib = node->sysctl_num;
+
+ if (!AC97_IS_FIXED_RATE(sc->codec_if)) {
+ /* passing the sc address instead of &sc->sc_ac97_clock */
+ err = sysctl_createv(&sc->sc_log, 0, NULL, &node_ac97clock,
+ CTLFLAG_READWRITE,
+ CTLTYPE_INT, "ac97rate",
+ SYSCTL_DESCR("AC'97 codec link rate"),
+ auich_sysctl_verify, 0, sc, 0,
+ CTL_HW, node_mib, CTL_CREATE, CTL_EOL);
+ if (err != 0)
+ goto sysctl_err;
+ sc->sc_ac97_clock_mib = node_ac97clock->sysctl_num;
+ }
return;
@@ -648,13 +695,13 @@
node = *rnode;
sc = rnode->sysctl_data;
- tmp = sc->sc_ac97_clock;
- node.sysctl_data = &tmp;
- error = sysctl_lookup(SYSCTLFN_CALL(&node));
- if (error || newp == NULL)
- return error;
+ if (node.sysctl_num == sc->sc_ac97_clock_mib) {
+ tmp = sc->sc_ac97_clock;
+ node.sysctl_data = &tmp;
+ error = sysctl_lookup(SYSCTLFN_CALL(&node));
+ if (error || newp == NULL)
+ return error;
- if (node.sysctl_num == sc->sc_ac97_clock_mib) {
if (tmp < 48000 || tmp > 96000)
return EINVAL;
sc->sc_ac97_clock = tmp;
@@ -686,16 +733,19 @@
sc = v;
/* wait for an access semaphore */
for (i = ICH_SEMATIMO / ICH_CODECIO_INTERVAL; i-- &&
- bus_space_read_1(sc->iot, sc->aud_ioh, ICH_CAS) & 1;
+ bus_space_read_1(sc->iot, sc->aud_ioh,
+ ICH_CAS + sc->sc_modem_offset) & 1;
DELAY(ICH_CODECIO_INTERVAL));
if (i > 0) {
- *val = bus_space_read_2(sc->iot, sc->mix_ioh, reg);
+ *val = bus_space_read_2(sc->iot, sc->mix_ioh, reg + (sc->codecnum * 0x80));
DPRINTF(ICH_DEBUG_CODECIO,
("auich_read_codec(%x, %x)\n", reg, *val));
- status = bus_space_read_4(sc->iot, sc->aud_ioh, ICH_GSTS);
+ status = bus_space_read_4(sc->iot, sc->aud_ioh,
+ ICH_GSTS + sc->sc_modem_offset);
if (status & ICH_RCS) {
- bus_space_write_4(sc->iot, sc->aud_ioh, ICH_GSTS,
+ bus_space_write_4(sc->iot, sc->aud_ioh,
+ ICH_GSTS + sc->sc_modem_offset,
status & ~(ICH_SRI|ICH_PRI|ICH_GSCI));
*val = 0xffff;
DPRINTF(ICH_DEBUG_CODECIO,
@@ -704,8 +754,7 @@
}
return 0;
} else {
- DPRINTF(ICH_DEBUG_CODECIO,
Home |
Main Index |
Thread Index |
Old Index