Hi,

I have been hacking on the ce4231 driver on my sparc64 box. This patch:
a) does some bits with the audio encoding (from jacob).
b) fixes (almost) the mixer interface.

I can't test the inputs, as it seems that part of the driver is broken
or unfinished. Observe:

blade% sudo aucat -f /dev/audio -o test
aucat: /dev/audio: can't open device

But thats another story. Lets tackle that later. This is my desktop
machine and I need the outputs to work for music atleast.

Expanding upon b):
* Make a setup_input() like there was a setup_output().
* get_port() always queries the card.
* set_port() only changes the struct, allowing setup_[input|output] to
  configure the card. Removes some duplication.
* Instead of selecting one audio output, add switches for each, as the
  ware allows >1 dac output to play at the same time.

Now:
In terms of the mixer classes etc, I don't think they are right, so I
was hoping someone could comment:

blade% mixerctl -v
outputs.dac=223,223 volume
outputs.dac.mute=off  [ on off ]
outputs.dac.monomute=on  [ on off ]
outputs.dac.linemute=off  [ on off ]
outputs.dac.hdphmute=off  [ on off ]
inputs.line=0,0 volume
inputs.line.mute=on  [ on off ]
inputs.mic=0 volume
inputs.mic.mute=on  [ on off ]
inputs.cd=0,0 volume
inputs.cd.mute=on  [ on off ]
monitor.monitor=3 volume
outputs.monitor.mute=off  [ on off ]
record.record=0,0 volume
record.record.source=dac  [ line aux mic dac ]

i)   There is only one output from this card, which is the dac. Should
     outputs.dac be outputs.master?
ii)  One of the following is wrong, which is it?:
     monitor.monitor
     outputs.monitor.mute
iii) There is also an AUX1 input, which seems unused on my blade. Should
     I add a mixer control?

As a side note.. First kernel patch.. I expect a lot of things to be
wrong. Be nice :)

--
Best Regards

Edd Barrett
(Freelance software developer / technical writer / open-source developer)

http://students.dec.bmth.ac.uk/ebarrett
Index: ce4231.c
===================================================================
RCS file: /cvs/src/sys/arch/sparc64/dev/ce4231.c,v
retrieving revision 1.22
diff -u -r1.22 ce4231.c
--- ce4231.c    21 Apr 2008 00:32:42 -0000      1.22
+++ ce4231.c    10 Aug 2009 19:19:36 -0000
@@ -57,44 +57,58 @@
 #include <sparc64/dev/ebusvar.h>
 #include <sparc64/dev/ce4231var.h>
 
+/* ad1418 provides basic registers, cs4231 extends with more */
 #include <dev/ic/ad1848reg.h>
 #include <dev/ic/cs4231reg.h>
 
+/* mixer classes and mixer knobs */
 #define        CSAUDIO_DAC_LVL         0
 #define        CSAUDIO_LINE_IN_LVL     1
 #define        CSAUDIO_MIC_LVL         2
 #define        CSAUDIO_CD_LVL          3
 #define        CSAUDIO_MONITOR_LVL     4
-#define        CSAUDIO_OUTPUT_LVL      5
-#define        CSAUDIO_LINE_IN_MUTE    6
-#define        CSAUDIO_DAC_MUTE        7
-#define        CSAUDIO_CD_MUTE         8
-#define        CSAUDIO_MIC_MUTE        9
-#define        CSAUDIO_MONITOR_MUTE    10
-#define        CSAUDIO_OUTPUT_MUTE     11
-#define        CSAUDIO_REC_LVL         12
-#define        CSAUDIO_RECORD_SOURCE   13
-#define        CSAUDIO_OUTPUT          14
-#define        CSAUDIO_INPUT_CLASS     15
-#define        CSAUDIO_OUTPUT_CLASS    16
-#define        CSAUDIO_RECORD_CLASS    17
-#define        CSAUDIO_MONITOR_CLASS   18
-
+#define        CSAUDIO_LINE_IN_MUTE    5
+#define        CSAUDIO_DAC_MUTE        6
+#define        CSAUDIO_CD_MUTE         7
+#define        CSAUDIO_MIC_MUTE        8
+#define        CSAUDIO_MONITOR_MUTE    9
+#define        CSAUDIO_REC_LVL         10
+#define        CSAUDIO_RECORD_SOURCE   11
+#define        CSAUDIO_INPUT_CLASS     12
+#define        CSAUDIO_OUTPUT_CLASS    13
+#define        CSAUDIO_RECORD_CLASS    14
+#define        CSAUDIO_MONITOR_CLASS   15
+/* The dac can output to these destinations, which *do* have mute
+ * controls, but share levels with the main DAC */
+#define CSAUDIO_DAC_MONO_MUTE  16
+#define CSAUDIO_DAC_LINE_MUTE  17
+#define CSAUDIO_DAC_HDPH_MUTE  18
+
+/* physical volume/attenuation registers, array indexes for
+ * sc->sc_volume/sc->sc_mute
+ *
+ * based upon my Sun blade 1000:
+ * AUX2 is usually CD in
+ * MONO is usually a mic
+ * */
 #define        CSPORT_AUX2             0
 #define        CSPORT_AUX1             1
 #define        CSPORT_DAC              2
 #define        CSPORT_LINEIN           3
 #define        CSPORT_MONO             4
 #define        CSPORT_MONITOR          5
-#define        CSPORT_SPEAKER          6
-#define        CSPORT_LINEOUT          7
-#define        CSPORT_HEADPHONE        8
-
-#define MIC_IN_PORT    0
-#define LINE_IN_PORT   1
-#define AUX1_IN_PORT   2
+#define CSPORT_ADC             6
+
+/* recording sources */
+#define LINE_IN_PORT   0
+#define AUX1_IN_PORT   1
+#define MIC_IN_PORT    2
 #define DAC_IN_PORT    3
 
+/* bits on the ADC reg that determine recording source */
+#define CS_REC_SRC_BITS 0xc0
+
+#define AUDIO_DEBUG
 #ifdef AUDIO_DEBUG
 #define        DPRINTF(x)      printf x
 #else
@@ -103,9 +117,11 @@
 
 #define        CS_TIMEOUT      90000
 
-#define        CS_PC_LINEMUTE  XCTL0_ENABLE
+#define        CS_PC_LINEMUTE  XCTL1_ENABLE
 #define        CS_PC_HDPHMUTE  XCTL1_ENABLE
 #define        CS_AFS_PI       0x10
+#define MONO_INPUT_MUTE 0x80
+#define MIX_MUTE       0x00
 
 /* Read/write CS4231 direct registers */
 #define CS_WRITE(sc,r,v)       \
@@ -132,6 +148,7 @@
 
 int    ce4231_set_speed(struct ce4231_softc *, u_long *);
 void   ce4231_setup_output(struct ce4231_softc *sc);
+void   ce4231_setup_input(struct ce4231_softc *sc);
 
 void           ce4231_write(struct ce4231_softc *, u_int8_t, u_int8_t);
 u_int8_t       ce4231_read(struct ce4231_softc *, u_int8_t);
@@ -290,12 +307,13 @@
 
        audio_attach_mi(&ce4231_sa_hw_if, sc, &sc->sc_dev);
 
-       /* Default to speaker, unmuted, reasonable volume */
-       sc->sc_out_port = CSPORT_SPEAKER;
-       sc->sc_mute[CSPORT_SPEAKER] = 1;
-       sc->sc_mute[CSPORT_MONITOR] = 1;
-       sc->sc_volume[CSPORT_SPEAKER].left = 192;
-       sc->sc_volume[CSPORT_SPEAKER].right = 192;
+       /* Default to all dacouts unmuted, reasonable volume */
+       sc->sc_monoout_enable = 1;
+       sc->sc_lineout_enable = 1;
+       sc->sc_hdphout_enable = 1;
+       sc->sc_mute[CSPORT_DAC] = 1; /* dac itself not muted */
+       sc->sc_volume[CSPORT_DAC].left = 192;
+       sc->sc_volume[CSPORT_DAC].right = 192;
 
        /* XXX get real burst... */
        sc->sc_burst = EBDCSR_BURST_8;
@@ -404,8 +422,11 @@
        struct ce4231_softc *sc = addr;
        int tries;
 
+       DPRINTF(("ce4231_open\n"));
+
        if (sc->sc_open)
                return (EBUSY);
+
        sc->sc_open = 1;
        sc->sc_locked = 0;
        sc->sc_rintr = 0;
@@ -431,6 +452,7 @@
            ce4231_read(sc, SP_MISC_INFO) | MODE2);
 
        ce4231_setup_output(sc);
+       ce4231_setup_input(sc);
 
        ce4231_write(sc, SP_PIN_CONTROL,
            ce4231_read(sc, SP_PIN_CONTROL) | INTERRUPT_ENABLE);
@@ -438,50 +460,163 @@
        return (0);
 }
 
+/* Set volume/attenuation values and mute settings for outputs */
 void
 ce4231_setup_output(sc)
        struct ce4231_softc *sc;
 {
-       u_int8_t pc, mi, rm, lm;
+       u_int8_t pc, mi, rm = 0, lm = 0;
 
-       pc = ce4231_read(sc, SP_PIN_CONTROL) | CS_PC_HDPHMUTE | CS_PC_LINEMUTE;
 
-       mi = ce4231_read(sc, CS_MONO_IO_CONTROL) | MONO_OUTPUT_MUTE;
+       /* DAC-output attenuation */
+       DPRINTF(("ce4231_setup_output: DAC out = %d, %d\n",
+           sc->sc_volume[CSPORT_DAC].left,
+           sc->sc_volume[CSPORT_DAC].right));
+       lm = (255 - sc->sc_volume[CSPORT_DAC].left) >> 2;
+       rm = (255 - sc->sc_volume[CSPORT_DAC].right) >> 2;
 
-       lm = ce4231_read(sc, SP_LEFT_OUTPUT_CONTROL);
-       lm &= ~OUTPUT_ATTEN_BITS;
-       lm |= ((~(sc->sc_volume[CSPORT_SPEAKER].left >> 2)) &
-           OUTPUT_ATTEN_BITS) | OUTPUT_MUTE;
+       /* DAC out mute setting */
+       if (!sc->sc_mute[CSPORT_DAC]) {
+               DPRINTF(("ce4231_setup_output: DAC out muted\n"));
+               lm = lm | OUTPUT_MUTE;
+               rm = rm | OUTPUT_MUTE;
+       }
 
-       rm = ce4231_read(sc, SP_RIGHT_OUTPUT_CONTROL);
-       rm &= ~OUTPUT_ATTEN_BITS;
-       rm |= ((~(sc->sc_volume[CSPORT_SPEAKER].right >> 2)) &
-           OUTPUT_ATTEN_BITS) | OUTPUT_MUTE;
+       /* commit DAC-out settings */
+       ce4231_write(sc, SP_LEFT_OUTPUT_CONTROL, lm);
+       ce4231_write(sc, SP_RIGHT_OUTPUT_CONTROL, rm);
 
-       if (sc->sc_mute[CSPORT_MONITOR]) {
-               lm &= ~OUTPUT_MUTE;
-               rm &= ~OUTPUT_MUTE;
+       /* mono DAC-out mute settings */
+       mi = ce4231_read(sc, CS_MONO_IO_CONTROL) & ~MONO_OUTPUT_MUTE;
+       if (!sc->sc_monoout_enable) {
+               DPRINTF(("ce4231_setup_output: DAC mono output is enabled"));
+               mi = mi | MONO_OUTPUT_MUTE;
        }
 
-       switch (sc->sc_out_port) {
-       case CSPORT_HEADPHONE:
-               if (sc->sc_mute[CSPORT_SPEAKER])
-                       pc &= ~CS_PC_HDPHMUTE;
-               break;
-       case CSPORT_SPEAKER:
-               if (sc->sc_mute[CSPORT_SPEAKER])
-                       mi &= ~MONO_OUTPUT_MUTE;
-               break;
-       case CSPORT_LINEOUT:
-               if (sc->sc_mute[CSPORT_SPEAKER])
-                       pc &= ~CS_PC_LINEMUTE;
-               break;
+       /* merge in mono input settings, as in same 8 bits */
+       mi = mi | (ce4231_read(sc, CS_MONO_IO_CONTROL) & MONO_INPUT_MUTE);
+
+       /* commit mono dacout settings */
+       ce4231_write(sc, CS_MONO_IO_CONTROL, mi);
+
+       /* line and headphone dacout mutes */
+       pc = (ce4231_read(sc, SP_PIN_CONTROL) &
+           ~CS_PC_HDPHMUTE) & ~CS_PC_LINEMUTE;
+       if (!sc->sc_lineout_enable) {
+               DPRINTF(("ce4231_setup_output: DAC line output is enabled"));
+               pc = pc | CS_PC_LINEMUTE;
+       }
+       if (!sc->sc_hdphout_enable) {
+               DPRINTF(("ce4231_setup_output: DAC hdph output is enabled"));
+               pc = pc | CS_PC_HDPHMUTE;
        }
 
-       ce4231_write(sc, SP_LEFT_OUTPUT_CONTROL, lm);
-       ce4231_write(sc, SP_RIGHT_OUTPUT_CONTROL, rm);
+       /* commit line/headphone DAC-out settings */
        ce4231_write(sc, SP_PIN_CONTROL, pc);
-       ce4231_write(sc, CS_MONO_IO_CONTROL, mi);
+}
+
+/* Set volume/attenuation values and mute settings for outputs */
+void
+ce4231_setup_input(sc)
+       struct ce4231_softc *sc;
+{
+
+       u_int8_t line_l, line_r, mono, aux2_l, aux2_r, monitor,
+           adc_l, adc_r;
+
+       /* line-in gain */
+       DPRINTF(("ce4231_setup_input: line in gain = %d,%d\n",
+           sc->sc_volume[CSPORT_LINEIN].left,
+           sc->sc_volume[CSPORT_LINEIN].right));
+       line_l = sc->sc_volume[CSPORT_LINEIN].left >> 3;
+       line_r = sc->sc_volume[CSPORT_LINEIN].right >> 3;
+       DPRINTF(("ce4231_setup_input: line-in gain (on card) = %d,%d\n",
+           line_l, line_r));
+
+       /* line-in mute */
+       if (!sc->sc_mute[CSPORT_LINEIN]) {
+               DPRINTF(("ce4231_setup_input: line-in mute is enabled\n"));
+               line_l = line_l | CS_PC_LINEMUTE;
+               line_r = line_r| CS_PC_LINEMUTE;
+       }
+
+       /* commit line-in settings to card */
+       ce4231_write(sc, CS_LEFT_LINE_CONTROL, line_l);
+       ce4231_write(sc, CS_RIGHT_LINE_CONTROL, line_r);
+
+       /* mono-in attenuation */
+       DPRINTF(("ce4231_setup_input: mono-in gain = %d\n",
+           sc->sc_volume[CSPORT_MONO].left));
+       mono = (255 - sc->sc_volume[CSPORT_MONO].left) >> 4;
+       DPRINTF(("ce4231_setup_input: mono-in attenuation (on card) = %d\n",
+           mono));
+
+       /* mono-in mute */
+       if (!sc->sc_mute[CSPORT_MONO]) {
+               DPRINTF(("ce4231_setup_input: mono-in mute is enabled\n"));
+               mono = mono | MONO_INPUT_MUTE;
+       }
+
+       /* merge in mono dacout setting, as in the same 8 bits */
+       mono = mono | (ce4231_read(sc, CS_MONO_IO_CONTROL) & MONO_OUTPUT_MUTE);
+
+       /* commit mono-in settings */
+       ce4231_write(sc, CS_MONO_IO_CONTROL, mono);
+
+       /* cd/aux2 gain */
+       DPRINTF(("ce4231_setup_input: cd/aux2 gain = %d,%d\n",
+           sc->sc_volume[CSPORT_AUX2].left,
+           sc->sc_volume[CSPORT_AUX2].right));
+       aux2_l = sc->sc_volume[CSPORT_AUX2].left >> 3;
+       aux2_r = sc->sc_volume[CSPORT_AUX2].right >> 3;
+       DPRINTF(("ce4231_setup_input: cd/aux2 gain (on card) = %d,%d\n",
+           aux2_l, aux2_r));
+
+       /* cd/aux2-input mute */
+       if (!sc->sc_mute[CSPORT_AUX2]) {
+               DPRINTF(("ce4231_setup_input: cd/aux2-in mute is enabled\n"));
+               aux2_l = aux2_l | AUX_INPUT_MUTE;
+               aux2_r = aux2_r | AUX_INPUT_MUTE;
+       }
+
+       /* commit cd/aux2 settings */
+       ce4231_write(sc, SP_LEFT_AUX2_CONTROL, aux2_l);
+       ce4231_write(sc, SP_RIGHT_AUX2_CONTROL, aux2_r);
+
+       /* monitor attenuation */
+       DPRINTF(("ce4231_setup_input: monitor gain = %d\n",
+           sc->sc_volume[CSPORT_MONITOR].left));
+       monitor = (255 - sc->sc_volume[CSPORT_MONITOR].left) & MIX_ATTEN_MASK;
+       DPRINTF(("ce4231_setup_input: monitor attenuation (on card) = %d\n",
+           monitor >> 2));
+
+       /* monitor mute */
+       if (!sc->sc_mute[CSPORT_MONITOR]) {
+               monitor = monitor | MONO_INPUT_MUTE;
+       }
+
+       /* commit monitor settings */
+       ce4231_write(sc, SP_DIGITAL_MIX, monitor);
+
+       /* ADC-in gain */
+       DPRINTF(("ce4231_setup_input: adc gain = %d,%d\n",
+           sc->sc_volume[CSPORT_ADC].left,
+           sc->sc_volume[CSPORT_ADC].right));
+       adc_l = sc->sc_volume[CSPORT_ADC].left >> 4;
+       adc_r = sc->sc_volume[CSPORT_ADC].right >> 4;
+       DPRINTF(("ce4231_setup_input: adc gain (on card)  = %d,%d\n",
+           adc_l, adc_r));
+
+       /* record source is one of *_INPUT_PORT */
+       adc_l = adc_l | (sc->sc_rec_src << 6);
+       adc_r = adc_r | (sc->sc_rec_src << 6);
+
+
+       ce4231_write(sc, SP_LEFT_INPUT_CONTROL, adc_l);
+       ce4231_write(sc, SP_RIGHT_INPUT_CONTROL, adc_r);
+
+
+       return;
 }
 
 void
@@ -576,75 +711,71 @@
        void (*pswcode)(void *, u_char *, int cnt) = NULL;
        void (*rswcode)(void *, u_char *, int cnt) = NULL;
 
+       if (p->precision > 16)
+               p->precision = 16;
        switch (enc) {
        case AUDIO_ENCODING_ULAW:
                if (p->precision != 8)
-                       return (EINVAL);
+                       p->precision = 8;
                bits = FMT_ULAW >> 5;
                break;
        case AUDIO_ENCODING_ALAW:
                if (p->precision != 8)
-                       return (EINVAL);
+                       p->precision = 8;
                bits = FMT_ALAW >> 5;
                break;
        case AUDIO_ENCODING_SLINEAR_LE:
                if (p->precision == 8) {
                        bits = FMT_PCM8 >> 5;
                        pswcode = rswcode = change_sign8;
-               } else if (p->precision == 16)
+               } else
                        bits = FMT_TWOS_COMP >> 5;
-               else
-                       return (EINVAL);
                break;
        case AUDIO_ENCODING_ULINEAR:
                if (p->precision != 8)
-                       return (EINVAL);
+                       p->precision = 8;
                bits = FMT_PCM8 >> 5;
                break;
        case AUDIO_ENCODING_SLINEAR_BE:
                if (p->precision == 8) {
                        bits = FMT_PCM8 >> 5;
                        pswcode = rswcode = change_sign8;
-               } else if (p->precision == 16)
+               } else
                        bits = FMT_TWOS_COMP_BE >> 5;
-               else
-                       return (EINVAL);
                break;
        case AUDIO_ENCODING_SLINEAR:
                if (p->precision != 8)
-                       return (EINVAL);
+                       p->precision = 8;
                bits = FMT_PCM8 >> 5;
                pswcode = rswcode = change_sign8;
                break;
        case AUDIO_ENCODING_ULINEAR_LE:
                if (p->precision == 8)
                        bits = FMT_PCM8 >> 5;
-               else if (p->precision == 16) {
+               else {
                        bits = FMT_TWOS_COMP >> 5;
                        pswcode = rswcode = change_sign16_le;
-               } else
-                       return (EINVAL);
+               }
                break;
        case AUDIO_ENCODING_ULINEAR_BE:
                if (p->precision == 8)
                        bits = FMT_PCM8 >> 5;
-               else if (p->precision == 16) {
+               else {
                        bits = FMT_TWOS_COMP_BE >> 5;
                        pswcode = rswcode = change_sign16_be;
-               } else
-                       return (EINVAL);
+               }
                break;
        case AUDIO_ENCODING_ADPCM:
                if (p->precision != 8)
-                       return (EINVAL);
+                       p->precision = 8;
                bits = FMT_ADPCM >> 5;
                break;
        default:
                return (EINVAL);
        }
 
-       if (p->channels != 1 && p->channels != 2)
-               return (EINVAL);
+       if (p->channels > 2)
+               p->channels = 2;
 
        err = ce4231_set_speed(sc, &p->sample_rate);
        if (err)
@@ -784,160 +915,185 @@
 
        DPRINTF(("ce4231_set_port: port=%d type=%d\n", cp->dev, cp->type));
 
+       /* XXX a lot of duplicated code here, sometime in the future
+        * make a function like:
+        * set_soft_volume(struct ce4231_softc *sc, mixer_ctrl_t *cp);
+        */
+
        switch (cp->dev) {
        case CSAUDIO_DAC_LVL:
                if (cp->type != AUDIO_MIXER_VALUE)
                        break;
-               if (cp->un.value.num_channels == 1)
-                       ce4231_write(sc, SP_LEFT_AUX1_CONTROL,
-                           cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] &
-                           LINE_INPUT_ATTEN_BITS);
-               else if (cp->un.value.num_channels == 2) {
-                       ce4231_write(sc, SP_LEFT_AUX1_CONTROL,
-                           cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT] &
-                           LINE_INPUT_ATTEN_BITS);
-                       ce4231_write(sc, SP_RIGHT_AUX1_CONTROL,
-                           cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] &
-                           LINE_INPUT_ATTEN_BITS);
+               if (cp->un.value.num_channels == 1) {
+                       sc->sc_volume[CSPORT_DAC].left =
+                               cp->un.value.level[AUDIO_MIXER_LEVEL_MONO];
+                       sc->sc_volume[CSPORT_DAC].right =
+                               cp->un.value.level[AUDIO_MIXER_LEVEL_MONO];
+               } else if (cp->un.value.num_channels == 2) {
+                       sc->sc_volume[CSPORT_DAC].left =
+                               cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT];
+                       sc->sc_volume[CSPORT_DAC].right =
+                               cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT];
                } else
                        break;
+               ce4231_setup_output(sc);
                error = 0;
                break;
        case CSAUDIO_LINE_IN_LVL:
                if (cp->type != AUDIO_MIXER_VALUE)
                        break;
-               if (cp->un.value.num_channels == 1)
-                       ce4231_write(sc, CS_LEFT_LINE_CONTROL,
-                           cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] &
-                           AUX_INPUT_ATTEN_BITS);
-               else if (cp->un.value.num_channels == 2) {
-                       ce4231_write(sc, CS_LEFT_LINE_CONTROL,
-                           cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT] &
-                           AUX_INPUT_ATTEN_BITS);
-                       ce4231_write(sc, CS_RIGHT_LINE_CONTROL,
-                           cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] &
-                           AUX_INPUT_ATTEN_BITS);
+               if (cp->un.value.num_channels == 1) {
+                       sc->sc_volume[CSPORT_LINEIN].left =
+                           cp->un.value.level[AUDIO_MIXER_LEVEL_MONO];
+                       sc->sc_volume[CSPORT_LINEIN].right =
+                           cp->un.value.level[AUDIO_MIXER_LEVEL_MONO];
+               } else if (cp->un.value.num_channels == 2) {
+                       sc->sc_volume[CSPORT_LINEIN].left =
+                           cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT];
+                       sc->sc_volume[CSPORT_LINEIN].right =
+                           cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT];
                } else
                        break;
+               ce4231_setup_input(sc);
                error = 0;
                break;
        case CSAUDIO_MIC_LVL:
                if (cp->type != AUDIO_MIXER_VALUE)
                        break;
                if (cp->un.value.num_channels == 1) {
-#if 0
-                       ce4231_write(sc, CS_MONO_IO_CONTROL,
-                           cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] &
-                           MONO_INPUT_ATTEN_BITS);
-#endif
+                       sc->sc_volume[CSPORT_MONO].left =
+                           cp->un.value.level[AUDIO_MIXER_LEVEL_MONO];
+                       sc->sc_volume[CSPORT_MONO].right =
+                           cp->un.value.level[AUDIO_MIXER_LEVEL_MONO];
+               } else if (cp->un.value.num_channels == 2) {
+                       sc->sc_volume[CSPORT_MONO].left =
+                           cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT];
+                       sc->sc_volume[CSPORT_MONO].right =
+                           cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT];
                } else
                        break;
+               ce4231_setup_input(sc);
                error = 0;
                break;
        case CSAUDIO_CD_LVL:
                if (cp->type != AUDIO_MIXER_VALUE)
                        break;
                if (cp->un.value.num_channels == 1) {
-                       ce4231_write(sc, SP_LEFT_AUX2_CONTROL,
-                           cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] &
-                           LINE_INPUT_ATTEN_BITS);
+                       sc->sc_volume[CSPORT_AUX2].left =
+                           cp->un.value.level[AUDIO_MIXER_LEVEL_MONO];
+                       sc->sc_volume[CSPORT_AUX2].right =
+                           cp->un.value.level[AUDIO_MIXER_LEVEL_MONO];
                } else if (cp->un.value.num_channels == 2) {
-                       ce4231_write(sc, SP_LEFT_AUX2_CONTROL,
-                           cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT] &
-                           LINE_INPUT_ATTEN_BITS);
-                       ce4231_write(sc, SP_RIGHT_AUX2_CONTROL,
-                           cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] &
-                           LINE_INPUT_ATTEN_BITS);
+                       sc->sc_volume[CSPORT_AUX2].left =
+                           cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT];
+                       sc->sc_volume[CSPORT_AUX2].right =
+                           cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT];
                } else
                        break;
+               ce4231_setup_input(sc);
                error = 0;
                break;
        case CSAUDIO_MONITOR_LVL:
                if (cp->type != AUDIO_MIXER_VALUE)
                        break;
-               if (cp->un.value.num_channels == 1)
-                       ce4231_write(sc, SP_DIGITAL_MIX,
-                           cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] << 2);
-               else
-                       break;
-               error = 0;
-               break;
-       case CSAUDIO_OUTPUT_LVL:
-               if (cp->type != AUDIO_MIXER_VALUE)
-                       break;
                if (cp->un.value.num_channels == 1) {
-                       sc->sc_volume[CSPORT_SPEAKER].left =
+                       sc->sc_volume[CSPORT_MONITOR].left =
                            cp->un.value.level[AUDIO_MIXER_LEVEL_MONO];
-                       sc->sc_volume[CSPORT_SPEAKER].right =
+                       sc->sc_volume[CSPORT_MONITOR].right =
                            cp->un.value.level[AUDIO_MIXER_LEVEL_MONO];
-               }
-               else if (cp->un.value.num_channels == 2) {
-                       sc->sc_volume[CSPORT_SPEAKER].left =
+               } else if (cp->un.value.num_channels == 2) {
+                       sc->sc_volume[CSPORT_MONITOR].left =
                            cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT];
-                       sc->sc_volume[CSPORT_SPEAKER].right =
+                       sc->sc_volume[CSPORT_MONITOR].right =
                            cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT];
-               }
-               else
-                       break;
-
-               ce4231_setup_output(sc);
-               error = 0;
-               break;
-       case CSAUDIO_OUTPUT:
-               if (cp->type != AUDIO_MIXER_ENUM)
+               } else
                        break;
-               if (cp->un.ord != CSPORT_LINEOUT &&
-                   cp->un.ord != CSPORT_SPEAKER &&
-                   cp->un.ord != CSPORT_HEADPHONE)
-                       return (EINVAL);
-               sc->sc_out_port = cp->un.ord;
-               ce4231_setup_output(sc);
+               ce4231_setup_input(sc);
                error = 0;
+
                break;
        case CSAUDIO_LINE_IN_MUTE:
                if (cp->type != AUDIO_MIXER_ENUM)
                        break;
                sc->sc_mute[CSPORT_LINEIN] = cp->un.ord ? 1 : 0;
+               ce4231_setup_input(sc);
                error = 0;
                break;
        case CSAUDIO_DAC_MUTE:
                if (cp->type != AUDIO_MIXER_ENUM)
                        break;
-               sc->sc_mute[CSPORT_AUX1] = cp->un.ord ? 1 : 0;
+               sc->sc_mute[CSPORT_DAC] = cp->un.ord ? 1 : 0;
+               ce4231_setup_output(sc);
                error = 0;
                break;
        case CSAUDIO_CD_MUTE:
                if (cp->type != AUDIO_MIXER_ENUM)
                        break;
                sc->sc_mute[CSPORT_AUX2] = cp->un.ord ? 1 : 0;
+               ce4231_setup_input(sc);
                error = 0;
                break;
        case CSAUDIO_MIC_MUTE:
                if (cp->type != AUDIO_MIXER_ENUM)
                        break;
                sc->sc_mute[CSPORT_MONO] = cp->un.ord ? 1 : 0;
+               ce4231_setup_input(sc);
                error = 0;
                break;
        case CSAUDIO_MONITOR_MUTE:
                if (cp->type != AUDIO_MIXER_ENUM)
                        break;
                sc->sc_mute[CSPORT_MONITOR] = cp->un.ord ? 1 : 0;
+               ce4231_setup_input(sc);
                error = 0;
                break;
-       case CSAUDIO_OUTPUT_MUTE:
+       case CSAUDIO_DAC_MONO_MUTE:
                if (cp->type != AUDIO_MIXER_ENUM)
                        break;
-               sc->sc_mute[CSPORT_SPEAKER] = cp->un.ord ? 1 : 0;
+               sc->sc_monoout_enable = cp->un.ord ? 1 : 0;
+               ce4231_setup_output(sc);
+               error = 0;
+               break;
+       case CSAUDIO_DAC_LINE_MUTE:
+               if (cp->type != AUDIO_MIXER_ENUM)
+                       break;
+               sc->sc_lineout_enable = cp->un.ord ? 1 : 0;
+               ce4231_setup_output(sc);
+               error = 0;
+               break;
+       case CSAUDIO_DAC_HDPH_MUTE:
+               if (cp->type != AUDIO_MIXER_ENUM)
+                       break;
+               sc->sc_hdphout_enable = cp->un.ord ? 1 : 0;
                ce4231_setup_output(sc);
                error = 0;
                break;
        case CSAUDIO_REC_LVL:
                if (cp->type != AUDIO_MIXER_VALUE)
                        break;
+               if (cp->un.value.num_channels == 1) {
+                       sc->sc_volume[CSPORT_ADC].left =
+                           cp->un.value.level[AUDIO_MIXER_LEVEL_MONO];
+                       sc->sc_volume[CSPORT_ADC].right =
+                           cp->un.value.level[AUDIO_MIXER_LEVEL_MONO];
+               } else if (cp->un.value.num_channels == 2) {
+                       sc->sc_volume[CSPORT_ADC].left =
+                           cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT];
+                       sc->sc_volume[CSPORT_ADC].right =
+                           cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT];
+               } else
+                       break;
+               ce4231_setup_input(sc);
+               error = 0;
+
                break;
+
        case CSAUDIO_RECORD_SOURCE:
                if (cp->type != AUDIO_MIXER_ENUM)
                        break;
+               sc->sc_rec_src = cp->un.ord;
+               ce4231_setup_input(sc);
+               error = 0;
                break;
        }
 
@@ -952,23 +1108,21 @@
        struct ce4231_softc *sc = (struct ce4231_softc *)addr;
        int error = EINVAL;
 
-       DPRINTF(("ce4231_get_port: port=%d type=%d\n", cp->dev, cp->type));
-
        switch (cp->dev) {
        case CSAUDIO_DAC_LVL:
                if (cp->type != AUDIO_MIXER_VALUE)
                        break;
                if (cp->un.value.num_channels == 1)
-                       cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]=
-                           ce4231_read(sc, SP_LEFT_AUX1_CONTROL) &
-                           LINE_INPUT_ATTEN_BITS;
+                       cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] =
+                           255 - ((ce4231_read(sc, SP_LEFT_OUTPUT_CONTROL) &
+                           OUTPUT_ATTEN_BITS) << 2);
                else if (cp->un.value.num_channels == 2) {
                        cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT] =
-                           ce4231_read(sc, SP_LEFT_AUX1_CONTROL) &
-                           LINE_INPUT_ATTEN_BITS;
+                           255 - ((ce4231_read(sc, SP_LEFT_OUTPUT_CONTROL) &
+                           OUTPUT_ATTEN_BITS) << 2);
                        cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] =
-                           ce4231_read(sc, SP_RIGHT_AUX1_CONTROL) &
-                           LINE_INPUT_ATTEN_BITS;
+                           255 - ((ce4231_read(sc, SP_RIGHT_OUTPUT_CONTROL) &
+                           OUTPUT_ATTEN_BITS) << 2);
                } else
                        break;
                error = 0;
@@ -978,12 +1132,15 @@
                        break;
                if (cp->un.value.num_channels == 1)
                        cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] =
-                           ce4231_read(sc, CS_LEFT_LINE_CONTROL) & 
AUX_INPUT_ATTEN_BITS;
+                           (ce4231_read(sc, CS_LEFT_LINE_CONTROL) &
+                           LINE_INPUT_ATTEN_BITS) << 3;
                else if (cp->un.value.num_channels == 2) {
                        cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT] =
-                           ce4231_read(sc, CS_LEFT_LINE_CONTROL) & 
AUX_INPUT_ATTEN_BITS;
+                           (ce4231_read(sc, CS_LEFT_LINE_CONTROL) &
+                           LINE_INPUT_ATTEN_BITS) << 3;
                        cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] =
-                           ce4231_read(sc, CS_RIGHT_LINE_CONTROL) & 
AUX_INPUT_ATTEN_BITS;
+                           (ce4231_read(sc, CS_RIGHT_LINE_CONTROL) &
+                           LINE_INPUT_ATTEN_BITS) << 3;
                } else
                        break;
                error = 0;
@@ -992,11 +1149,9 @@
                if (cp->type != AUDIO_MIXER_VALUE)
                        break;
                if (cp->un.value.num_channels == 1) {
-#if 0
                        cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] =
-                           ce4231_read(sc, CS_MONO_IO_CONTROL) &
-                           MONO_INPUT_ATTEN_BITS;
-#endif
+                           (255 - (ce4231_read(sc, CS_MONO_IO_CONTROL) &
+                           MONO_INPUT_ATTEN_BITS)) << 4;
                } else
                        break;
                error = 0;
@@ -1006,17 +1161,16 @@
                        break;
                if (cp->un.value.num_channels == 1)
                        cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] =
-                           ce4231_read(sc, SP_LEFT_AUX2_CONTROL) &
-                           LINE_INPUT_ATTEN_BITS;
+                           (ce4231_read(sc, SP_LEFT_AUX2_CONTROL) &
+                           LINE_INPUT_ATTEN_BITS) << 3;
                else if (cp->un.value.num_channels == 2) {
                        cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT] =
-                           ce4231_read(sc, SP_LEFT_AUX2_CONTROL) &
-                           LINE_INPUT_ATTEN_BITS;
+                           (ce4231_read(sc, SP_LEFT_AUX2_CONTROL) &
+                           LINE_INPUT_ATTEN_BITS) << 3;
                        cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] =
-                           ce4231_read(sc, SP_RIGHT_AUX2_CONTROL) &
-                           LINE_INPUT_ATTEN_BITS;
-               }
-               else
+                           (ce4231_read(sc, SP_RIGHT_AUX2_CONTROL) &
+                           LINE_INPUT_ATTEN_BITS) << 3;
+               } else
                        break;
                error = 0;
                break;
@@ -1026,59 +1180,69 @@
                if (cp->un.value.num_channels != 1)
                        break;
                cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] =
-                   ce4231_read(sc, SP_DIGITAL_MIX) >> 2;
-               error = 0;
-               break;
-       case CSAUDIO_OUTPUT_LVL:
-               if (cp->type != AUDIO_MIXER_VALUE)
-                       break;
-               if (cp->un.value.num_channels == 1)
-                       cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] =
-                           sc->sc_volume[CSPORT_SPEAKER].left;
-               else if (cp->un.value.num_channels == 2) {
-                       cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT] =
-                           sc->sc_volume[CSPORT_SPEAKER].left;
-                       cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] =
-                           sc->sc_volume[CSPORT_SPEAKER].right;
-               }
-               else
-                       break;
+                   255 - (ce4231_read(sc, SP_DIGITAL_MIX) & MIX_ATTEN_MASK);
                error = 0;
                break;
        case CSAUDIO_LINE_IN_MUTE:
                if (cp->type != AUDIO_MIXER_ENUM)
                        break;
-               cp->un.ord = sc->sc_mute[CSPORT_LINEIN] ? 1 : 0;
+               cp->un.ord = ce4231_read(sc, CS_LEFT_LINE_CONTROL) &
+                   CS_PC_LINEMUTE ? 0 : 1;
                error = 0;
                break;
        case CSAUDIO_DAC_MUTE:
                if (cp->type != AUDIO_MIXER_ENUM)
                        break;
-               cp->un.ord = sc->sc_mute[CSPORT_AUX1] ? 1 : 0;
+               cp->un.ord = ce4231_read(sc, SP_LEFT_OUTPUT_CONTROL) &
+                   OUTPUT_MUTE ? 0 : 1;
                error = 0;
                break;
        case CSAUDIO_CD_MUTE:
                if (cp->type != AUDIO_MIXER_ENUM)
                        break;
-               cp->un.ord = sc->sc_mute[CSPORT_AUX2] ? 1 : 0;
+               //cp->un.ord = sc->sc_mute[CSPORT_AUX2] ? 1 : 0;
+               cp->un.ord = ce4231_read(sc, SP_LEFT_AUX2_CONTROL) &
+                   AUX_INPUT_MUTE ? 0 : 1;
                error = 0;
                break;
        case CSAUDIO_MIC_MUTE:
                if (cp->type != AUDIO_MIXER_ENUM)
                        break;
-               cp->un.ord = sc->sc_mute[CSPORT_MONO] ? 1 : 0;
+               //cp->un.ord = sc->sc_mute[CSPORT_MONO] ? 1 : 0;
+               cp->un.ord = ce4231_read(sc, CS_MONO_IO_CONTROL) &
+                   MONO_INPUT_MUTE ? 0 : 1;
                error = 0;
                break;
        case CSAUDIO_MONITOR_MUTE:
                if (cp->type != AUDIO_MIXER_ENUM)
                        break;
-               cp->un.ord = sc->sc_mute[CSPORT_MONITOR] ? 1 : 0;
+               //cp->un.ord = sc->sc_mute[CSPORT_MONITOR] ? 1 : 0;
+               cp->un.ord = ce4231_read(sc, SP_DIGITAL_MIX) &
+                MIX_MUTE ? 0 : 1;
+               error = 0;
+               break;
+       case CSAUDIO_DAC_MONO_MUTE:
+               if (cp->type != AUDIO_MIXER_ENUM)
+                       break;
+               //cp->un.ord = sc->sc_monoout_enable ? 1 : 0;
+               cp->un.ord = ce4231_read(sc, CS_MONO_IO_CONTROL) &
+                   MONO_OUTPUT_MUTE ? 0 : 1;
+               error = 0;
+               break;
+       case CSAUDIO_DAC_LINE_MUTE:
+               if (cp->type != AUDIO_MIXER_ENUM)
+                       break;
+               //cp->un.ord = sc->sc_lineout_enable ? 1 : 0;
+               cp->un.ord = ce4231_read(sc, SP_PIN_CONTROL) & CS_PC_LINEMUTE
+                   ? 0 : 1;
                error = 0;
                break;
-       case CSAUDIO_OUTPUT_MUTE:
+       case CSAUDIO_DAC_HDPH_MUTE:
                if (cp->type != AUDIO_MIXER_ENUM)
                        break;
-               cp->un.ord = sc->sc_mute[CSPORT_SPEAKER] ? 1 : 0;
+               //cp->un.ord = sc->sc_hdphout_enable ? 1 : 0;
+               cp->un.ord = ce4231_read(sc, SP_PIN_CONTROL) & CS_PC_HDPHMUTE
+                   ? 0 : 1;
                error = 0;
                break;
        case CSAUDIO_REC_LVL:
@@ -1086,12 +1250,12 @@
                        break;
                if (cp->un.value.num_channels == 1) {
                        cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] =
-                           AUDIO_MIN_GAIN;
+                           ce4231_read(sc, SP_LEFT_INPUT_CONTROL) << 4;
                } else if (cp->un.value.num_channels == 2) {
                        cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT] =
-                           AUDIO_MIN_GAIN;
+                           ce4231_read(sc, SP_LEFT_INPUT_CONTROL) << 4;
                        cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] =
-                           AUDIO_MIN_GAIN;
+                           ce4231_read(sc, SP_RIGHT_INPUT_CONTROL) << 4;
                } else
                        break;
                error = 0;
@@ -1099,13 +1263,13 @@
        case CSAUDIO_RECORD_SOURCE:
                if (cp->type != AUDIO_MIXER_ENUM)
                        break;
-               cp->un.ord = MIC_IN_PORT;
-               error = 0;
-               break;
-       case CSAUDIO_OUTPUT:
-               if (cp->type != AUDIO_MIXER_ENUM)
+
+               /* AUX in disabled for now until we know what it does */
+               if (cp->un.ord == AUX1_IN_PORT)
                        break;
-               cp->un.ord = sc->sc_out_port;
+
+               cp->un.ord = ce4231_read(sc, SP_LEFT_INPUT_CONTROL &
+                   CS_REC_SRC_BITS) >> 6;
                error = 0;
                break;
        }
@@ -1132,7 +1296,7 @@
                break;
        case CSAUDIO_DAC_LVL:           /* dacout */
                dip->type = AUDIO_MIXER_VALUE;
-               dip->mixer_class = CSAUDIO_INPUT_CLASS;
+               dip->mixer_class = CSAUDIO_OUTPUT_CLASS;
                dip->prev = AUDIO_MIXER_LAST;
                dip->next = CSAUDIO_DAC_MUTE;
                strlcpy(dip->label.name, AudioNdac, sizeof dip->label.name);
@@ -1170,16 +1334,6 @@
                strlcpy(dip->un.v.units.name, AudioNvolume,
                    sizeof dip->un.v.units.name);
                break;
-       case CSAUDIO_OUTPUT_LVL:
-               dip->type = AUDIO_MIXER_VALUE;
-               dip->mixer_class = CSAUDIO_OUTPUT_CLASS;
-               dip->prev = AUDIO_MIXER_LAST;
-               dip->next = CSAUDIO_OUTPUT_MUTE;
-               strlcpy(dip->label.name, AudioNoutput, sizeof dip->label.name);
-               dip->un.v.num_channels = 2;
-               strlcpy(dip->un.v.units.name, AudioNvolume,
-                   sizeof dip->un.v.units.name);
-               break;
        case CSAUDIO_LINE_IN_MUTE:
                dip->type = AUDIO_MIXER_ENUM;
                dip->mixer_class = CSAUDIO_INPUT_CLASS;
@@ -1188,9 +1342,9 @@
                goto mute;
        case CSAUDIO_DAC_MUTE:
                dip->type = AUDIO_MIXER_ENUM;
-               dip->mixer_class = CSAUDIO_INPUT_CLASS;
+               dip->mixer_class = CSAUDIO_OUTPUT_CLASS;
                dip->prev = CSAUDIO_DAC_LVL;
-               dip->next = AUDIO_MIXER_LAST;
+               dip->next = CSAUDIO_DAC_MONO_MUTE;
                goto mute;
        case CSAUDIO_CD_MUTE:
                dip->type = AUDIO_MIXER_ENUM;
@@ -1210,15 +1364,33 @@
                dip->prev = CSAUDIO_MONITOR_LVL;
                dip->next = AUDIO_MIXER_LAST;
                goto mute;
-       case CSAUDIO_OUTPUT_MUTE:
+       case CSAUDIO_DAC_MONO_MUTE: /* The dac has a mono out, usually spkr */
+               dip->type = AUDIO_MIXER_ENUM;
+               dip->mixer_class = CSAUDIO_OUTPUT_CLASS;
+               dip->prev = CSAUDIO_DAC_MUTE;
+               dip->next = CSAUDIO_DAC_LINE_MUTE;
+               /* custom name, as we already have a mute in this class */
+               strlcpy(dip->label.name, "monomute", sizeof "monomute");
+               goto mute1;
+       case CSAUDIO_DAC_LINE_MUTE:
+               dip->type = AUDIO_MIXER_ENUM;
+               dip->mixer_class = CSAUDIO_OUTPUT_CLASS;
+               dip->prev = CSAUDIO_DAC_MONO_MUTE;
+               dip->next = CSAUDIO_DAC_HDPH_MUTE;
+               /* custom name */
+               strlcpy(dip->label.name, "linemute", sizeof "linemute");
+               goto mute1;
+       case CSAUDIO_DAC_HDPH_MUTE:
                dip->type = AUDIO_MIXER_ENUM;
                dip->mixer_class = CSAUDIO_OUTPUT_CLASS;
-               dip->prev = CSAUDIO_OUTPUT_LVL;
+               dip->prev = CSAUDIO_DAC_LINE_MUTE;
                dip->next = AUDIO_MIXER_LAST;
-               goto mute;
-
+               /* custom name */
+               strlcpy(dip->label.name, "hdphmute", sizeof "hdphmute");
+               goto mute1;
        mute:
                strlcpy(dip->label.name, AudioNmute, sizeof dip->label.name);
+       mute1:
                dip->un.e.num_mem = 2;
                strlcpy(dip->un.e.member[0].label.name, AudioNon,
                    sizeof dip->un.e.member[0].label.name);
@@ -1227,7 +1399,7 @@
                    sizeof dip->un.e.member[1].label.name);
                dip->un.e.member[1].ord = 1;
                break;
-       case CSAUDIO_REC_LVL:           /* record level */
+       case CSAUDIO_REC_LVL:
                dip->type = AUDIO_MIXER_VALUE;
                dip->mixer_class = CSAUDIO_RECORD_CLASS;
                dip->prev = AUDIO_MIXER_LAST;
@@ -1243,35 +1415,24 @@
                dip->prev = CSAUDIO_REC_LVL;
                dip->next = AUDIO_MIXER_LAST;
                strlcpy(dip->label.name, AudioNsource, sizeof dip->label.name);
-               dip->un.e.num_mem = 3;
-               strlcpy(dip->un.e.member[0].label.name, AudioNcd,
+               dip->un.e.num_mem = 4;
+
+               strlcpy(dip->un.e.member[0].label.name, AudioNline,
                    sizeof dip->un.e.member[0].label.name);
-               dip->un.e.member[0].ord = DAC_IN_PORT;
-               strlcpy(dip->un.e.member[1].label.name, AudioNmicrophone,
+               dip->un.e.member[0].ord = LINE_IN_PORT;
+
+               strlcpy(dip->un.e.member[1].label.name, "aux",
                    sizeof dip->un.e.member[1].label.name);
-               dip->un.e.member[1].ord = MIC_IN_PORT;
-               strlcpy(dip->un.e.member[2].label.name, AudioNdac,
+               dip->un.e.member[1].ord = AUX1_IN_PORT;
+
+               strlcpy(dip->un.e.member[2].label.name, AudioNmicrophone,
                    sizeof dip->un.e.member[2].label.name);
-               dip->un.e.member[2].ord = AUX1_IN_PORT;
-               strlcpy(dip->un.e.member[3].label.name, AudioNline,
+               dip->un.e.member[2].ord = MIC_IN_PORT;
+
+               strlcpy(dip->un.e.member[3].label.name, AudioNdac,
                    sizeof dip->un.e.member[3].label.name);
-               dip->un.e.member[3].ord = LINE_IN_PORT;
-               break;
-       case CSAUDIO_OUTPUT:
-               dip->type = AUDIO_MIXER_ENUM;
-               dip->mixer_class = CSAUDIO_MONITOR_CLASS;
-               dip->prev = dip->next = AUDIO_MIXER_LAST;
-               strlcpy(dip->label.name, AudioNoutput, sizeof dip->label.name);
-               dip->un.e.num_mem = 3;
-               strlcpy(dip->un.e.member[0].label.name, AudioNspeaker,
-                   sizeof dip->un.e.member[0].label.name);
-               dip->un.e.member[0].ord = CSPORT_SPEAKER;
-               strlcpy(dip->un.e.member[1].label.name, AudioNline,
-                   sizeof dip->un.e.member[1].label.name);
-               dip->un.e.member[1].ord = CSPORT_LINEOUT;
-               strlcpy(dip->un.e.member[2].label.name, AudioNheadphone,
-                   sizeof dip->un.e.member[2].label.name);
-               dip->un.e.member[2].ord = CSPORT_HEADPHONE;
+               dip->un.e.member[3].ord = DAC_IN_PORT;
+
                break;
        case CSAUDIO_INPUT_CLASS:       /* input class descriptor */
                dip->type = AUDIO_MIXER_CLASS;
Index: ce4231var.h
===================================================================
RCS file: /cvs/src/sys/arch/sparc64/dev/ce4231var.h,v
retrieving revision 1.8
diff -u -r1.8 ce4231var.h
--- ce4231var.h 2 Jun 2006 20:00:56 -0000       1.8
+++ ce4231var.h 10 Aug 2009 19:19:36 -0000
@@ -52,6 +52,9 @@
        u_int8_t        right;
 };
 
+/* number of levels on the card, these relate to CSPORT_* */
+#define CS4231_LVLS    7
+
 struct ce4231_softc {
        struct  device sc_dev;          /* base device */
        struct  intrhand sc_ih;         /* interrupt vectoring */
@@ -69,9 +72,12 @@
        void    (*sc_pintr)(void *);    /* output completion intr handler */
        void    *sc_parg;               /* arg for sc_pintr() */
 
-       char            sc_mute[9];     /* which devs are muted */
-       u_int8_t        sc_out_port;    /* output port */
-       struct  cs_volume sc_volume[9]; /* software volume */
+       char            sc_mute[CS4231_LVLS];   /* which devs are muted */
+       u_int8_t        sc_monoout_enable; /* whether the mono dacout is on */
+       u_int8_t        sc_lineout_enable; /* whether the line dacout is on */
+       u_int8_t        sc_hdphout_enable; /* whether the cans dacout is on */
+       u_int8_t        sc_rec_src;        /* recording src */
+       struct  cs_volume sc_volume[CS4231_LVLS];       /* software volume */
 
        int sc_format_bits;
        int sc_speed_bits;

Reply via email to