diff options
Diffstat (limited to 'sys')
-rw-r--r-- | sys/arch/hppa/gsc/harmony.c | 135 | ||||
-rw-r--r-- | sys/arch/hppa/gsc/harmonyvar.h | 111 |
2 files changed, 166 insertions, 80 deletions
diff --git a/sys/arch/hppa/gsc/harmony.c b/sys/arch/hppa/gsc/harmony.c index f5add0e333f..40ef48fe29e 100644 --- a/sys/arch/hppa/gsc/harmony.c +++ b/sys/arch/hppa/gsc/harmony.c @@ -1,4 +1,4 @@ -/* $OpenBSD: harmony.c,v 1.8 2003/01/27 23:12:41 jason Exp $ */ +/* $OpenBSD: harmony.c,v 1.9 2003/01/28 04:20:49 jason Exp $ */ /* * Copyright (c) 2003 Jason L. Wright (jason@thought.net) @@ -56,80 +56,7 @@ #include <hppa/dev/cpudevs.h> #include <hppa/gsc/gscbusvar.h> #include <hppa/gsc/harmonyreg.h> - -#define HARMONY_PORT_INPUT_LVL 0 -#define HARMONY_PORT_OUTPUT_LVL 1 -#define HARMONY_PORT_MONITOR_LVL 2 -#define HARMONY_PORT_RECORD_SOURCE 3 -#define HARMONY_PORT_INPUT_CLASS 4 -#define HARMONY_PORT_OUTPUT_CLASS 5 -#define HARMONY_PORT_MONITOR_CLASS 6 -#define HARMONY_PORT_RECORD_CLASS 7 - -#define HARMONY_IN_MIC 0 -#define HARMONY_IN_LINE 1 - -#define PLAYBACK_EMPTYS 3 /* playback empty buffers */ -#define CAPTURE_EMPTYS 3 /* capture empty buffers */ -#define HARMONY_BUFSIZE 4096 - -struct harmony_volume { - u_char left, right; -}; - -struct harmony_empty { - u_int8_t playback[PLAYBACK_EMPTYS][HARMONY_BUFSIZE]; - u_int8_t capture[CAPTURE_EMPTYS][HARMONY_BUFSIZE]; -}; - -struct harmony_dma { - struct harmony_dma *d_next; - bus_dmamap_t d_map; - bus_dma_segment_t d_seg; - caddr_t d_kva; - size_t d_size; -}; - -struct harmony_channel { - struct harmony_dma *c_current; - bus_size_t c_segsz; - bus_size_t c_cnt; - bus_size_t c_blksz; - bus_addr_t c_lastaddr; - void (*c_intr)(void *); - void *c_intrarg; -}; - -struct harmony_softc { - struct device sc_dv; - bus_dma_tag_t sc_dmat; - bus_space_tag_t sc_bt; - bus_space_handle_t sc_bh; - int sc_open; - u_int32_t sc_cntlbits; - int sc_need_commit; - int sc_playback_empty; - bus_addr_t sc_playback_paddrs[PLAYBACK_EMPTYS]; - int sc_capture_empty; - bus_addr_t sc_capture_paddrs[CAPTURE_EMPTYS]; - bus_dmamap_t sc_empty_map; - bus_dma_segment_t sc_empty_seg; - int sc_empty_rseg; - struct harmony_empty *sc_empty_kva; - struct harmony_dma *sc_dmas; - int sc_playing, sc_capturing; - struct harmony_channel sc_playback, sc_capture; - struct harmony_volume sc_monitor_lvl, sc_input_lvl, sc_output_lvl; - int sc_in_port; -}; - -#define READ_REG(sc, reg) \ - bus_space_read_4((sc)->sc_bt, (sc)->sc_bh, (reg)) -#define WRITE_REG(sc, reg, val) \ - bus_space_write_4((sc)->sc_bt, (sc)->sc_bh, (reg), (val)) -#define SYNC_REG(sc, reg, flags) \ - bus_space_barrier((sc)->sc_bt, (sc)->sc_bh, (reg), sizeof(u_int32_t), \ - (flags)) +#include <hppa/gsc/harmonyvar.h> int harmony_open(void *, int); void harmony_close(void *); @@ -290,6 +217,7 @@ harmony_attach(parent, self, aux) /* set defaults */ sc->sc_in_port = HARMONY_IN_LINE; + sc->sc_out_port = HARMONY_OUT_SPEAKER; sc->sc_input_lvl.left = sc->sc_input_lvl.right = 240; sc->sc_output_lvl.left = sc->sc_output_lvl.right = 244; sc->sc_monitor_lvl.left = sc->sc_monitor_lvl.right = 208; @@ -653,6 +581,17 @@ harmony_set_port(void *vsc, mixer_ctrl_t *cp) err = 0; sc->sc_need_commit = 1; break; + case HARMONY_PORT_OUTPUT_SOURCE: + if (cp->type != AUDIO_MIXER_ENUM) + break; + if (cp->un.ord != HARMONY_OUT_LINE && + cp->un.ord != HARMONY_OUT_SPEAKER && + cp->un.ord != HARMONY_OUT_HEADPHONE) + break; + sc->sc_out_port = cp->un.ord; + err = 0; + sc->sc_need_commit = 1; + break; } return (err); @@ -710,6 +649,12 @@ harmony_get_port(void *vsc, mixer_ctrl_t *cp) cp->un.ord = sc->sc_in_port; err = 0; break; + case HARMONY_PORT_OUTPUT_SOURCE: + if (cp->type != AUDIO_MIXER_ENUM) + break; + cp->un.ord = sc->sc_out_port; + err = 0; + break; } return (0); } @@ -740,7 +685,7 @@ harmony_query_devinfo(void *vsc, mixer_devinfo_t *dip) dip->type = AUDIO_MIXER_VALUE; dip->mixer_class = HARMONY_PORT_MONITOR_CLASS; dip->prev = dip->next = AUDIO_MIXER_LAST; - strcpy(dip->label.name, AudioNoutput); + strcpy(dip->label.name, AudioNmonitor); dip->un.v.num_channels = 1; strcpy(dip->un.v.units.name, AudioNvolume); break; @@ -755,6 +700,19 @@ harmony_query_devinfo(void *vsc, mixer_devinfo_t *dip) strcpy(dip->un.e.member[1].label.name, AudioNline); dip->un.e.member[1].ord = HARMONY_IN_LINE; break; + case HARMONY_PORT_OUTPUT_SOURCE: + dip->type = AUDIO_MIXER_ENUM; + dip->mixer_class = HARMONY_PORT_MONITOR_CLASS; + dip->prev = dip->next = AUDIO_MIXER_LAST; + strcpy(dip->label.name, AudioNoutput); + dip->un.e.num_mem = 3; + strcpy(dip->un.e.member[0].label.name, AudioNline); + dip->un.e.member[0].ord = HARMONY_OUT_LINE; + strcpy(dip->un.e.member[1].label.name, AudioNspeaker); + dip->un.e.member[1].ord = HARMONY_OUT_SPEAKER; + strcpy(dip->un.e.member[2].label.name, AudioNheadphone); + dip->un.e.member[2].ord = HARMONY_OUT_HEADPHONE; + break; case HARMONY_PORT_INPUT_CLASS: dip->type = AUDIO_MIXER_CLASS; dip->mixer_class = HARMONY_PORT_INPUT_CLASS; @@ -962,9 +920,7 @@ harmony_start_cp(struct harmony_softc *sc) c->c_blksz, BUS_DMASYNC_PREWRITE); WRITE_REG(sc, HARMONY_RNXTADD, nextaddr); - bus_space_barrier(sc->sc_bt, sc->sc_bh, - HARMONY_RNXTADD, sizeof(u_int32_t), - BUS_SPACE_BARRIER_WRITE); + SYNC_REG(sc, HARMONY_RNXTADD, BUS_SPACE_BARRIER_WRITE); c->c_lastaddr = nextaddr + togo; } } @@ -1062,7 +1018,7 @@ harmony_set_gainctl(struct harmony_softc *sc) u_int32_t bits, mask, val; /* XXX leave these bits alone or the chip will not come out of CNTL */ - bits = GAINCTL_HE | GAINCTL_LE | GAINCTL_SE | GAINCTL_IS_MASK; + bits = GAINCTL_LE | GAINCTL_HE | GAINCTL_SE | GAINCTL_IS_MASK; /* input level */ bits |= ((sc->sc_input_lvl.left >> (8 - GAINCTL_INPUT_BITS)) << @@ -1082,6 +1038,25 @@ harmony_set_gainctl(struct harmony_softc *sc) val = mask - (sc->sc_monitor_lvl.left >> (8 - GAINCTL_MONITOR_BITS)); bits |= (val << GAINCTL_MONITOR_S) & GAINCTL_MONITOR_M; +#if 0 + /* XXX messing with these causes CNTL_C to get stuck... grr. */ + bits &= ~GAINCTL_IS_MASK; + if (sc->sc_in_port == HARMONY_IN_MIC) + bits |= GAINCTL_IS_LINE; + else + bits |= GAINCTL_IS_MIC; + + /* XXX messing with these causes CNTL_C to get stuck... grr. */ + bits = ~(GAINCTL_LE | GAINCTL_HE | GAINCTL_SE); + if (sc->sc_out_port == HARMONY_OUT_LINE) + bits |= GAINCTL_LE; + else if (sc->sc_out_port == HARMONY_OUT_SPEAKER) + bits |= GAINCTL_SE; + else + bits |= GAINCTL_HE; + +#endif + bus_space_write_4(sc->sc_bt, sc->sc_bh, HARMONY_GAINCTL, bits); } diff --git a/sys/arch/hppa/gsc/harmonyvar.h b/sys/arch/hppa/gsc/harmonyvar.h new file mode 100644 index 00000000000..de1466a34a9 --- /dev/null +++ b/sys/arch/hppa/gsc/harmonyvar.h @@ -0,0 +1,111 @@ +/* $OpenBSD: harmonyvar.h,v 1.1 2003/01/28 04:20:49 jason Exp $ */ + +/* + * Copyright (c) 2003 Jason L. Wright (jason@thought.net) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Jason L. Wright + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#define HARMONY_PORT_INPUT_LVL 0 +#define HARMONY_PORT_OUTPUT_LVL 1 +#define HARMONY_PORT_MONITOR_LVL 2 +#define HARMONY_PORT_RECORD_SOURCE 3 +#define HARMONY_PORT_OUTPUT_SOURCE 4 +#define HARMONY_PORT_INPUT_CLASS 5 +#define HARMONY_PORT_OUTPUT_CLASS 6 +#define HARMONY_PORT_MONITOR_CLASS 7 +#define HARMONY_PORT_RECORD_CLASS 8 + +#define HARMONY_IN_MIC 0 +#define HARMONY_IN_LINE 1 + +#define HARMONY_OUT_LINE 0 +#define HARMONY_OUT_SPEAKER 1 +#define HARMONY_OUT_HEADPHONE 2 + +#define PLAYBACK_EMPTYS 3 /* playback empty buffers */ +#define CAPTURE_EMPTYS 3 /* capture empty buffers */ +#define HARMONY_BUFSIZE 4096 + +struct harmony_volume { + u_char left, right; +}; + +struct harmony_empty { + u_int8_t playback[PLAYBACK_EMPTYS][HARMONY_BUFSIZE]; + u_int8_t capture[CAPTURE_EMPTYS][HARMONY_BUFSIZE]; +}; + +struct harmony_dma { + struct harmony_dma *d_next; + bus_dmamap_t d_map; + bus_dma_segment_t d_seg; + caddr_t d_kva; + size_t d_size; +}; + +struct harmony_channel { + struct harmony_dma *c_current; + bus_size_t c_segsz; + bus_size_t c_cnt; + bus_size_t c_blksz; + bus_addr_t c_lastaddr; + void (*c_intr)(void *); + void *c_intrarg; +}; + +struct harmony_softc { + struct device sc_dv; + bus_dma_tag_t sc_dmat; + bus_space_tag_t sc_bt; + bus_space_handle_t sc_bh; + int sc_open; + u_int32_t sc_cntlbits; + int sc_need_commit; + int sc_playback_empty; + bus_addr_t sc_playback_paddrs[PLAYBACK_EMPTYS]; + int sc_capture_empty; + bus_addr_t sc_capture_paddrs[CAPTURE_EMPTYS]; + bus_dmamap_t sc_empty_map; + bus_dma_segment_t sc_empty_seg; + int sc_empty_rseg; + struct harmony_empty *sc_empty_kva; + struct harmony_dma *sc_dmas; + int sc_playing, sc_capturing; + struct harmony_channel sc_playback, sc_capture; + struct harmony_volume sc_monitor_lvl, sc_input_lvl, sc_output_lvl; + int sc_in_port, sc_out_port; +}; + +#define READ_REG(sc, reg) \ + bus_space_read_4((sc)->sc_bt, (sc)->sc_bh, (reg)) +#define WRITE_REG(sc, reg, val) \ + bus_space_write_4((sc)->sc_bt, (sc)->sc_bh, (reg), (val)) +#define SYNC_REG(sc, reg, flags) \ + bus_space_barrier((sc)->sc_bt, (sc)->sc_bh, (reg), sizeof(u_int32_t), \ + (flags)) |