From c74eb31f219b16ff8c84fb58c4016f9d5b713e2b Mon Sep 17 00:00:00 2001 From: jmcneill Date: Mon, 4 Apr 2005 02:08:58 +0000 Subject: [PATCH] * Add support for skipping either the modem or audio AC'97 probes via host_flags: AC97_HOST_SKIP_AUDIO, AC97_HOST_SKIP_MODEM * If we're dealing with a modem codec, print the extended modem capabilities. * Add basic AC'97 modem initialization support. * Add some (but not all) AC'97 modem registers. More will be added later. --- sys/dev/ic/ac97.c | 73 +++++++++++++++++++++++++++++++++++++++----- sys/dev/ic/ac97reg.h | 32 ++++++++++++++++++- sys/dev/ic/ac97var.h | 6 ++-- 3 files changed, 100 insertions(+), 11 deletions(-) diff --git a/sys/dev/ic/ac97.c b/sys/dev/ic/ac97.c index 3c3a28a24242..4f7debffb355 100644 --- a/sys/dev/ic/ac97.c +++ b/sys/dev/ic/ac97.c @@ -1,4 +1,4 @@ -/* $NetBSD: ac97.c,v 1.66 2005/01/10 22:01:37 kent Exp $ */ +/* $NetBSD: ac97.c,v 1.67 2005/04/04 02:08:58 jmcneill Exp $ */ /* $OpenBSD: ac97.c,v 1.8 2000/07/19 09:01:35 csapuntz Exp $ */ /* @@ -63,7 +63,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: ac97.c,v 1.66 2005/01/10 22:01:37 kent Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ac97.c,v 1.67 2005/04/04 02:08:58 jmcneill Exp $"); #include #include @@ -335,6 +335,7 @@ struct ac97_softc { #define AC97_STANDARD_CLOCK 48000U uint16_t caps; /* -> AC97_REG_RESET */ uint16_t ext_id; /* -> AC97_REG_EXT_AUDIO_ID */ + uint16_t ext_mid; /* -> AC97_REG_EXT_MODEM_ID */ uint16_t shadow_reg[128]; }; @@ -985,11 +986,13 @@ ac97_attach(struct ac97_host_if *host_if, struct device *sc_dev) #define AC97_POWER_ALL (AC97_POWER_REF | AC97_POWER_ANL | AC97_POWER_DAC \ | AC97_POWER_ADC) - for (i = 500000; i >= 0; i--) { - ac97_read(as, AC97_REG_POWER, &val); - if ((val & AC97_POWER_ALL) == AC97_POWER_ALL) - break; - DELAY(1); + if (!(as->host_flags & AC97_HOST_SKIP_AUDIO)) { + for (i = 500000; i >= 0; i--) { + ac97_read(as, AC97_REG_POWER, &val); + if ((val & AC97_POWER_ALL) == AC97_POWER_ALL) + break; + DELAY(1); + } } #undef AC97_POWER_ALL @@ -1036,7 +1039,8 @@ ac97_attach(struct ac97_host_if *host_if, struct device *sc_dev) ac97enhancement[AC97_CAPS_ENHANCEMENT(as->caps)]); as->ac97_clock = AC97_STANDARD_CLOCK; - ac97_read(as, AC97_REG_EXT_AUDIO_ID, &as->ext_id); + if (!(as->host_flags & AC97_HOST_SKIP_AUDIO)) + ac97_read(as, AC97_REG_EXT_AUDIO_ID, &as->ext_id); if (as->ext_id != 0) { /* Print capabilities */ bitmask_snprintf(as->ext_id, "\20\20SECONDARY10\17SECONDARY01" @@ -1099,6 +1103,59 @@ ac97_attach(struct ac97_host_if *host_if, struct device *sc_dev) } } + if (as->ext_id == 0 && !(as->host_flags & AC97_HOST_SKIP_MODEM)) { + ac97_read(as, AC97_REG_EXT_MODEM_ID, &as->ext_mid); + if (as->ext_mid == 0xffff) + as->ext_mid = 0; + } + if (as->ext_mid != 0) { + uint16_t rate = 12000; + uint16_t val, reg; + + /* Print capabilities */ + bitmask_snprintf(as->ext_mid, + "\20\5CID2\4CID1\3HANDSET\2LINE2\1LINE1", + flagbuf, FLAGBUFLEN); + aprint_normal("%s: ac97: ext mid %s", sc_dev->dv_xname, + flagbuf); + aprint_normal(", %s codec\n", + (as->ext_mid & 0xc000) == 0 ? + "primary" : "secondary"); + + /* Setup modem */ + val = AC97_MEA_GPIO; + if (as->ext_mid & AC97_EXT_MODEM_LINE1) { + ac97_write(as, AC97_REG_LINE1_RATE, rate); + val |= AC97_MEA_ADC1 | AC97_MEA_DAC1; + } + if (as->ext_mid & AC97_EXT_MODEM_LINE2) { + ac97_write(as, AC97_REG_LINE2_RATE, rate); + val |= AC97_MEA_ADC2 | AC97_MEA_DAC2; + } + if (as->ext_mid & AC97_EXT_MODEM_HANDSET) { + ac97_write(as, AC97_REG_HANDSET_RATE, rate); + val |= AC97_MEA_HADC | AC97_MEA_HDAC; + } + ac97_write(as, AC97_REG_EXT_MODEM_STATUS, 0xff00 & ~(val << 8)); + delay(100); + ac97_write(as, AC97_REG_EXT_MODEM_STATUS, 0xff00 & ~(val << 8)); + do { + ac97_read(as, AC97_REG_EXT_MODEM_STATUS, ®); + delay(1); + } while ((reg & val) != val && i--); + if (i == 0) + printf("%s: error setting extended modem controls\n", + sc_dev->dv_xname); + + ac97_write(as, AC97_REG_GPIO_CFG, + 0xffff & ~(AC97_GPIO_LINE1_OH)); + ac97_write(as, AC97_REG_GPIO_POLARITY, + 0xffff & ~(AC97_GPIO_LINE1_OH)); + ac97_write(as, AC97_REG_GPIO_STICKY, 0xffff); + ac97_write(as, AC97_REG_GPIO_WAKEUP, 0x0); + ac97_write(as, AC97_REG_MISC_AFE, 0x0); + } + ac97_setup_source_info(as); memset(&ctl, 0, sizeof(ctl)); diff --git a/sys/dev/ic/ac97reg.h b/sys/dev/ic/ac97reg.h index 9364fbd776db..448211890206 100644 --- a/sys/dev/ic/ac97reg.h +++ b/sys/dev/ic/ac97reg.h @@ -1,4 +1,4 @@ -/* $NetBSD: ac97reg.h,v 1.9 2003/09/07 11:27:33 kent Exp $ */ +/* $NetBSD: ac97reg.h,v 1.10 2005/04/04 02:08:58 jmcneill Exp $ */ /* * Copyright (c) 1999 Constantine Sapuntzakis @@ -136,6 +136,36 @@ #define AC97_SPDIF_PRO 0x0001 /* Modem -- 0x3c-0x58 */ +#define AC97_REG_EXT_MODEM_ID 0x3c /* extended modem id */ +#define AC97_EXT_MODEM_LINE1 0x0001 +#define AC97_EXT_MODEM_LINE2 0x0002 +#define AC97_EXT_MODEM_HANDSET 0x0004 +#define AC97_EXT_MODEM_CID1 0x0008 +#define AC97_EXT_MODEM_CID2 0x0010 +#define AC97_REG_EXT_MODEM_STATUS 0x3e /* extended modem status */ +#define AC97_MEA_GPIO 0x0001 /* gpio is ready */ +#define AC97_MEA_ADC1 0x0004 +#define AC97_MEA_DAC1 0x0008 +#define AC97_MEA_ADC2 0x0010 +#define AC97_MEA_DAC2 0x0020 +#define AC97_MEA_HADC 0x0040 +#define AC97_MEA_HDAC 0x0080 + +#define AC97_REG_LINE1_RATE 0x40 +#define AC97_REG_LINE2_RATE 0x42 +#define AC97_REG_HANDSET_RATE 0x44 +#define AC97_REG_LINE1_LEVEL 0x46 +#define AC97_REG_LINE2_LEVEL 0x48 +#define AC97_REG_HANDSET_LEVEL 0x4a +#define AC97_REG_GPIO_CFG 0x4c /* gpio config */ +#define AC97_REG_GPIO_POLARITY 0x4e /* gpio pin polarity */ +#define AC97_REG_GPIO_STICKY 0x50 /* gpio pin sticky */ +#define AC97_REG_GPIO_WAKEUP 0x52 /* gpio pin wakeup */ +#define AC97_REG_GPIO_STATUS 0x54 +#define AC97_GPIO_LINE1_OH 0x0001 /* off-hook */ +#define AC97_GPIO_LINE1_RI 0x0002 /* ring detect */ +#define AC97_GPIO_LINE1_CID 0x0004 /* caller-id */ +#define AC97_REG_MISC_AFE 0x56 /* misc modem afe status & control */ /* Vendor specific -- 0x5a-0x7b */ diff --git a/sys/dev/ic/ac97var.h b/sys/dev/ic/ac97var.h index 406fb39ca2d7..079689b5a69d 100644 --- a/sys/dev/ic/ac97var.h +++ b/sys/dev/ic/ac97var.h @@ -1,4 +1,4 @@ -/* $NetBSD: ac97var.h,v 1.14 2005/01/10 22:01:37 kent Exp $ */ +/* $NetBSD: ac97var.h,v 1.15 2005/04/04 02:08:58 jmcneill Exp $ */ /* $OpenBSD: ac97.h,v 1.4 2000/07/19 09:01:35 csapuntz Exp $ */ /* @@ -39,7 +39,9 @@ struct ac97_codec_if; */ enum ac97_host_flags { AC97_HOST_DONT_READ = 0x1, - AC97_HOST_SWAPPED_CHANNELS = 0x2 /* l/r is reversed */ + AC97_HOST_SWAPPED_CHANNELS = 0x2, /* l/r is reversed */ + AC97_HOST_SKIP_AUDIO = 0x4, + AC97_HOST_SKIP_MODEM = 0x8 }; struct ac97_host_if {