* Add more AC97 modem registers (from AC'97 revision 2.2)
* Add sysctls to control the modem's off-hook status (work in progress)
This commit is contained in:
parent
914d68e290
commit
f1db07fc36
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: ac97.c,v 1.67 2005/04/04 02:08:58 jmcneill Exp $ */
|
||||
/* $NetBSD: ac97.c,v 1.68 2005/04/04 18:52:30 jmcneill Exp $ */
|
||||
/* $OpenBSD: ac97.c,v 1.8 2000/07/19 09:01:35 csapuntz Exp $ */
|
||||
|
||||
/*
|
||||
|
@ -63,13 +63,14 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: ac97.c,v 1.67 2005/04/04 02:08:58 jmcneill Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: ac97.c,v 1.68 2005/04/04 18:52:30 jmcneill Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/device.h>
|
||||
#include <sys/sysctl.h>
|
||||
|
||||
#include <sys/audioio.h>
|
||||
#include <dev/audio_if.h>
|
||||
|
@ -102,6 +103,9 @@ static void ac97_ad198x_init(struct ac97_softc *);
|
|||
static void ac97_alc650_init(struct ac97_softc *);
|
||||
static void ac97_vt1616_init(struct ac97_softc *);
|
||||
|
||||
static int ac97_modem_offhook_set(struct ac97_softc *, int, int);
|
||||
static int ac97_sysctl_verify(SYSCTLFN_ARGS);
|
||||
|
||||
#define Ac97Nphone "phone"
|
||||
|
||||
static const struct audio_mixer_enum
|
||||
|
@ -337,6 +341,13 @@ struct ac97_softc {
|
|||
uint16_t ext_id; /* -> AC97_REG_EXT_AUDIO_ID */
|
||||
uint16_t ext_mid; /* -> AC97_REG_EXT_MODEM_ID */
|
||||
uint16_t shadow_reg[128];
|
||||
|
||||
/* sysctl */
|
||||
struct sysctllog *log;
|
||||
int offhook_line1_mib;
|
||||
int offhook_line2_mib;
|
||||
int offhook_line1;
|
||||
int offhook_line2;
|
||||
};
|
||||
|
||||
static struct ac97_codec_if_vtbl ac97civ = {
|
||||
|
@ -1109,8 +1120,12 @@ ac97_attach(struct ac97_host_if *host_if, struct device *sc_dev)
|
|||
as->ext_mid = 0;
|
||||
}
|
||||
if (as->ext_mid != 0) {
|
||||
struct sysctlnode *node;
|
||||
struct sysctlnode *node_line1;
|
||||
struct sysctlnode *node_line2;
|
||||
uint16_t rate = 12000;
|
||||
uint16_t val, reg;
|
||||
int err;
|
||||
|
||||
/* Print capabilities */
|
||||
bitmask_snprintf(as->ext_mid,
|
||||
|
@ -1122,40 +1137,93 @@ ac97_attach(struct ac97_host_if *host_if, struct device *sc_dev)
|
|||
(as->ext_mid & 0xc000) == 0 ?
|
||||
"primary" : "secondary");
|
||||
|
||||
/* Setup modem */
|
||||
val = AC97_MEA_GPIO;
|
||||
/* Setup modem and sysctls */
|
||||
val = AC97_EXT_MODEM_CTRL_GPIO;
|
||||
err = sysctl_createv(&as->log, 0, NULL, NULL, 0, CTLTYPE_NODE,
|
||||
"hw", NULL, NULL, 0, NULL, 0, CTL_HW,
|
||||
CTL_EOL);
|
||||
if (err != 0)
|
||||
goto sysctl_err;
|
||||
err = sysctl_createv(&as->log, 0, NULL, &node, 0,
|
||||
CTLTYPE_NODE, sc_dev->dv_xname, NULL,
|
||||
NULL, 0, NULL, 0, CTL_HW, CTL_CREATE,
|
||||
CTL_EOL);
|
||||
if (err != 0)
|
||||
goto sysctl_err;
|
||||
if (as->ext_mid & AC97_EXT_MODEM_LINE1) {
|
||||
ac97_write(as, AC97_REG_LINE1_RATE, rate);
|
||||
val |= AC97_MEA_ADC1 | AC97_MEA_DAC1;
|
||||
val |= AC97_EXT_MODEM_CTRL_ADC1 |
|
||||
AC97_EXT_MODEM_CTRL_DAC1;
|
||||
}
|
||||
if (as->ext_mid & AC97_EXT_MODEM_LINE2) {
|
||||
ac97_write(as, AC97_REG_LINE2_RATE, rate);
|
||||
val |= AC97_MEA_ADC2 | AC97_MEA_DAC2;
|
||||
val |= AC97_EXT_MODEM_CTRL_ADC2 |
|
||||
AC97_EXT_MODEM_CTRL_DAC2;
|
||||
}
|
||||
if (as->ext_mid & AC97_EXT_MODEM_HANDSET) {
|
||||
ac97_write(as, AC97_REG_HANDSET_RATE, rate);
|
||||
val |= AC97_MEA_HADC | AC97_MEA_HDAC;
|
||||
val |= AC97_EXT_MODEM_CTRL_HADC |
|
||||
AC97_EXT_MODEM_CTRL_HDAC;
|
||||
}
|
||||
ac97_write(as, AC97_REG_EXT_MODEM_STATUS, 0xff00 & ~(val << 8));
|
||||
/* power-up everything that we have */
|
||||
ac97_write(as, AC97_REG_EXT_MODEM_CTRL, 0xff00 & ~(val << 8));
|
||||
delay(100);
|
||||
ac97_write(as, AC97_REG_EXT_MODEM_STATUS, 0xff00 & ~(val << 8));
|
||||
ac97_write(as, AC97_REG_EXT_MODEM_CTRL, 0xff00 & ~(val << 8));
|
||||
i = 500000;
|
||||
do {
|
||||
ac97_read(as, AC97_REG_EXT_MODEM_STATUS, ®);
|
||||
ac97_read(as, AC97_REG_EXT_MODEM_CTRL, ®);
|
||||
delay(1);
|
||||
} while ((reg & val) != val && i--);
|
||||
if (i == 0)
|
||||
printf("%s: error setting extended modem controls\n",
|
||||
printf("%s: error setting extended modem status\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));
|
||||
/* setup sysctls */
|
||||
if (as->ext_mid & AC97_EXT_MODEM_LINE1) {
|
||||
ac97_read(as, AC97_REG_GPIO_CFG, ®);
|
||||
reg &= ~AC97_GPIO_LINE1_OH;
|
||||
ac97_write(as, AC97_REG_GPIO_CFG, reg);
|
||||
ac97_read(as, AC97_REG_GPIO_POLARITY, ®);
|
||||
reg &= ~AC97_GPIO_LINE1_OH;
|
||||
ac97_write(as, AC97_REG_GPIO_POLARITY, reg);
|
||||
|
||||
err = sysctl_createv(&as->log, 0, NULL, &node_line1,
|
||||
CTLFLAG_READWRITE, CTLTYPE_INT,
|
||||
"line1",
|
||||
SYSCTL_DESCR("off-hook line1"),
|
||||
ac97_sysctl_verify, 0, as, 0,
|
||||
CTL_HW, node->sysctl_num,
|
||||
CTL_CREATE, CTL_EOL);
|
||||
if (err != 0)
|
||||
goto sysctl_err;
|
||||
as->offhook_line1_mib = node_line1->sysctl_num;
|
||||
}
|
||||
if (as->ext_mid & AC97_EXT_MODEM_LINE2) {
|
||||
ac97_read(as, AC97_REG_GPIO_CFG, ®);
|
||||
reg &= ~AC97_GPIO_LINE2_OH;
|
||||
ac97_write(as, AC97_REG_GPIO_CFG, reg);
|
||||
ac97_read(as, AC97_REG_GPIO_POLARITY, ®);
|
||||
reg &= ~AC97_GPIO_LINE2_OH;
|
||||
ac97_write(as, AC97_REG_GPIO_POLARITY, reg);
|
||||
|
||||
err = sysctl_createv(&as->log, 0, NULL, &node_line2,
|
||||
CTLFLAG_READWRITE, CTLTYPE_INT,
|
||||
"line2",
|
||||
SYSCTL_DESCR("off-hook line2"),
|
||||
ac97_sysctl_verify, 0, as, 0,
|
||||
CTL_HW, node->sysctl_num,
|
||||
CTL_CREATE, CTL_EOL);
|
||||
if (err != 0)
|
||||
goto sysctl_err;
|
||||
as->offhook_line2_mib = node_line2->sysctl_num;
|
||||
}
|
||||
|
||||
ac97_write(as, AC97_REG_GPIO_STICKY, 0xffff);
|
||||
ac97_write(as, AC97_REG_GPIO_WAKEUP, 0x0);
|
||||
ac97_write(as, AC97_REG_MISC_AFE, 0x0);
|
||||
}
|
||||
|
||||
sysctl_err:
|
||||
ac97_setup_source_info(as);
|
||||
|
||||
memset(&ctl, 0, sizeof(ctl));
|
||||
|
@ -1755,3 +1823,59 @@ ac97_vt1616_init(struct ac97_softc *as)
|
|||
ac97_add_port(as, &sources[1]);
|
||||
ac97_add_port(as, &sources[2]);
|
||||
}
|
||||
|
||||
static int
|
||||
ac97_modem_offhook_set(struct ac97_softc *as, int line, int newval)
|
||||
{
|
||||
uint16_t val = 0;
|
||||
|
||||
switch (newval) {
|
||||
case 0:
|
||||
val &= ~line;
|
||||
break;
|
||||
case 1:
|
||||
val |= line;
|
||||
break;
|
||||
}
|
||||
ac97_write(as, AC97_REG_GPIO_STATUS, val);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
ac97_sysctl_verify(SYSCTLFN_ARGS)
|
||||
{
|
||||
int error, tmp;
|
||||
struct sysctlnode node;
|
||||
struct ac97_softc *as;
|
||||
|
||||
node = *rnode;
|
||||
as = rnode->sysctl_data;
|
||||
if (node.sysctl_num == as->offhook_line1_mib) {
|
||||
tmp = as->offhook_line1;
|
||||
node.sysctl_data = &tmp;
|
||||
error = sysctl_lookup(SYSCTLFN_CALL(&node));
|
||||
if (error || newp == NULL)
|
||||
return error;
|
||||
|
||||
if (tmp < 0 || tmp > 1)
|
||||
return EINVAL;
|
||||
|
||||
as->offhook_line1 = tmp;
|
||||
ac97_modem_offhook_set(as, AC97_GPIO_LINE1_OH, tmp);
|
||||
} else if (node.sysctl_num == as->offhook_line2_mib) {
|
||||
tmp = as->offhook_line2;
|
||||
node.sysctl_data = &tmp;
|
||||
error = sysctl_lookup(SYSCTLFN_CALL(&node));
|
||||
if (error || newp == NULL)
|
||||
return error;
|
||||
|
||||
if (tmp < 0 || tmp > 1)
|
||||
return EINVAL;
|
||||
|
||||
as->offhook_line2 = tmp;
|
||||
ac97_modem_offhook_set(as, AC97_GPIO_LINE2_OH, tmp);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: ac97reg.h,v 1.10 2005/04/04 02:08:58 jmcneill Exp $ */
|
||||
/* $NetBSD: ac97reg.h,v 1.11 2005/04/04 18:52:30 jmcneill Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1999 Constantine Sapuntzakis
|
||||
|
@ -142,15 +142,26 @@
|
|||
#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_EXT_MODEM_ID0 0x4000
|
||||
#define AC97_EXT_MODEM_ID1 0x8000
|
||||
#define AC97_EXT_MODEM_ID_MASK 0xc000
|
||||
#define AC97_REG_EXT_MODEM_CTRL 0x3e /* extended modem ctrl */
|
||||
#define AC97_EXT_MODEM_CTRL_GPIO 0x0001 /* gpio is ready */
|
||||
#define AC97_EXT_MODEM_CTRL_MREF 0x0002 /* vref up */
|
||||
#define AC97_EXT_MODEM_CTRL_ADC1 0x0004 /* line1 adc ready */
|
||||
#define AC97_EXT_MODEM_CTRL_DAC1 0x0008 /* line1 dac ready */
|
||||
#define AC97_EXT_MODEM_CTRL_ADC2 0x0010 /* line2 adc ready */
|
||||
#define AC97_EXT_MODEM_CTRL_DAC2 0x0020 /* line2 dac ready */
|
||||
#define AC97_EXT_MODEM_CTRL_HADC 0x0040 /* handset adc ready */
|
||||
#define AC97_EXT_MODEM_CTRL_HDAC 0x0080 /* handset dac ready */
|
||||
#define AC97_EXT_MODEM_CTRL_PRA 0x0100 /* gpio off */
|
||||
#define AC97_EXT_MODEM_CTRL_PRB 0x0200 /* vref off */
|
||||
#define AC97_EXT_MODEM_CTRL_PRC 0x0400 /* line1 adc off */
|
||||
#define AC97_EXT_MODEM_CTRL_PRD 0x0800 /* line1 dac off */
|
||||
#define AC97_EXT_MODEM_CTRL_PRE 0x1000 /* line2 adc off */
|
||||
#define AC97_EXT_MODEM_CTRL_PRF 0x2000 /* line2 dac off */
|
||||
#define AC97_EXT_MODEM_CTRL_PRG 0x4000 /* handset adc off */
|
||||
#define AC97_EXT_MODEM_CTRL_PRH 0x8000 /* handset dac off */
|
||||
#define AC97_REG_LINE1_RATE 0x40
|
||||
#define AC97_REG_LINE2_RATE 0x42
|
||||
#define AC97_REG_HANDSET_RATE 0x44
|
||||
|
@ -165,7 +176,29 @@
|
|||
#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_GPIO_LINE2_OH 0x0400 /* off-hook */
|
||||
#define AC97_GPIO_LINE2_RI 0x0800 /* ring detect */
|
||||
#define AC97_GPIO_LINE2_CID 0x1000 /* caller-id */
|
||||
#define AC97_REG_MISC_AFE 0x56 /* misc modem afe status & control */
|
||||
#define AC97_MISC_AFE_L1B_MASK 0x0007 /* line1 loopback */
|
||||
#define AC97_MISC_AFE_L2B_MASK 0x0070 /* line2 loopback */
|
||||
#define AC97_MISC_AFE_HSB_MASK 0x0700 /* handset loopback */
|
||||
#define AC97_MISC_AFE_MLNK 0x1000 /* ac-link status */
|
||||
#define AC97_MISC_AFE_CID1 0x2000 /* line1 cid decode */
|
||||
#define AC97_MISC_AFE_CID2 0x4000 /* line2 cid decide */
|
||||
#define AC97_MISC_AFE_CIDR 0x8000 /* raw cid data */
|
||||
|
||||
/* Modem loopback modes */
|
||||
#define AC97_LOOPBACK_DISABLE 0
|
||||
#define AC97_LOOPBACK_ADC 1
|
||||
#define AC97_LOOPBACK_LOCAL_ANALOG 2
|
||||
#define AC97_LOOPBACK_DAC 3
|
||||
#define AC97_LOOPBACK_REMOTE_ANALOG 4
|
||||
#define AC97_LOOPBACK_VENDOR1 5
|
||||
#define AC97_LOOPBACK_VENDOR2 6
|
||||
#define AC97_LOOPBACK_VENDOR3 7
|
||||
|
||||
|
||||
|
||||
/* Vendor specific -- 0x5a-0x7b */
|
||||
|
||||
|
|
Loading…
Reference in New Issue