Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/dev/ic * Add more AC97 modem registers (from AC'97 revis...



details:   https://anonhg.NetBSD.org/src/rev/8421c34adea2
branches:  trunk
changeset: 580010:8421c34adea2
user:      jmcneill <jmcneill%NetBSD.org@localhost>
date:      Mon Apr 04 18:52:30 2005 +0000

description:
* Add more AC97 modem registers (from AC'97 revision 2.2)
* Add sysctls to control the modem's off-hook status (work in progress)

diffstat:

 sys/dev/ic/ac97.c    |  154 ++++++++++++++++++++++++++++++++++++++++++++++----
 sys/dev/ic/ac97reg.h |   53 ++++++++++++++---
 2 files changed, 182 insertions(+), 25 deletions(-)

diffs (truncated from 304 to 300 lines):

diff -r cf0740b6fe7f -r 8421c34adea2 sys/dev/ic/ac97.c
--- a/sys/dev/ic/ac97.c Mon Apr 04 18:43:55 2005 +0000
+++ b/sys/dev/ic/ac97.c Mon Apr 04 18:52:30 2005 +0000
@@ -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_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 @@
        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 @@
                        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 @@
                              (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, &reg);
+                       ac97_read(as, AC97_REG_EXT_MODEM_CTRL, &reg);
                        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);
+                       reg &= ~AC97_GPIO_LINE1_OH;
+                       ac97_write(as, AC97_REG_GPIO_CFG, reg);
+                       ac97_read(as, AC97_REG_GPIO_POLARITY, &reg);
+                       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);
+                       reg &= ~AC97_GPIO_LINE2_OH;
+                       ac97_write(as, AC97_REG_GPIO_CFG, reg);
+                       ac97_read(as, AC97_REG_GPIO_POLARITY, &reg);
+                       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_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;
+}
diff -r cf0740b6fe7f -r 8421c34adea2 sys/dev/ic/ac97reg.h
--- a/sys/dev/ic/ac97reg.h      Mon Apr 04 18:43:55 2005 +0000
+++ b/sys/dev/ic/ac97reg.h      Mon Apr 04 18:52:30 2005 +0000
@@ -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
+



Home | Main Index | Thread Index | Old Index