[BACK]Return to maestro.c CVS log [TXT][DIR] Up to [local] / sys / dev / pci

Annotation of sys/dev/pci/maestro.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: maestro.c,v 1.21 2006/12/29 13:04:37 pedro Exp $      */
                      2: /* $FreeBSD: /c/ncvs/src/sys/dev/sound/pci/maestro.c,v 1.3 2000/11/21 12:22:11 julian Exp $ */
                      3: /*
                      4:  * FreeBSD's ESS Agogo/Maestro driver
                      5:  * Converted from FreeBSD's pcm to OpenBSD's audio.
                      6:  * Copyright (c) 2000, 2001 David Leonard & Marc Espie
                      7:  * All rights reserved.
                      8:  *
                      9:  * Redistribution and use in source and binary forms, with or without
                     10:  * modification, are permitted provided that the following conditions
                     11:  * are met:
                     12:  * 1. Redistributions of source code must retain the above copyright
                     13:  *    notice, this list of conditions and the following disclaimer.
                     14:  * 2. Redistributions in binary form must reproduce the above copyright
                     15:  *    notice, this list of conditions and the following disclaimer in the
                     16:  *    documentation and/or other materials provided with the distribution.
                     17:  *
                     18:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
                     19:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     20:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     21:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
                     22:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     23:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     24:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     25:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     26:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     27:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     28:  * SUCH DAMAGE.
                     29:  */
                     30: /*-
                     31:  * (FreeBSD) Credits:
                     32:  * Copyright (c) 2000 Taku YAMAMOTO <taku@cent.saitama-u.ac.jp>
                     33:  *
                     34:  * Part of this code (especially in many magic numbers) was heavily inspired
                     35:  * by the Linux driver originally written by
                     36:  * Alan Cox <alan.cox@linux.org>, modified heavily by
                     37:  * Zach Brown <zab@zabbo.net>.
                     38:  *
                     39:  * busdma()-ize and buffer size reduction were suggested by
                     40:  * Cameron Grant <gandalf@vilnya.demon.co.uk>.
                     41:  * Also he showed me the way to use busdma() suite.
                     42:  *
                     43:  * Internal speaker problems on NEC VersaPro's and Dell Inspiron 7500
                     44:  * were looked at by
                     45:  * Munehiro Matsuda <haro@tk.kubota.co.jp>,
                     46:  * who brought patches based on the Linux driver with some simplification.
                     47:  */
                     48:
                     49: #include <sys/param.h>
                     50: #include <sys/systm.h>
                     51: #include <sys/kernel.h>
                     52: #include <sys/malloc.h>
                     53: #include <sys/device.h>
                     54: #include <sys/proc.h>
                     55: #include <sys/queue.h>
                     56: #include <sys/fcntl.h>
                     57:
                     58: #include <dev/pci/pcidevs.h>
                     59: #include <dev/pci/pcivar.h>
                     60:
                     61: #include <sys/audioio.h>
                     62: #include <dev/audio_if.h>
                     63: #include <dev/mulaw.h>
                     64: #include <dev/auconv.h>
                     65:
                     66: #include <dev/ic/ac97.h>
                     67:
                     68: /* -----------------------------
                     69:  * PCI config registers
                     70:  */
                     71:
                     72: /* Legacy emulation */
                     73: #define CONF_LEGACY    0x40
                     74:
                     75: #define LEGACY_DISABLED        0x8000
                     76:
                     77: /* Chip configurations */
                     78: #define CONF_MAESTRO   0x50
                     79: #define MAESTRO_CHIBUS         0x00100000
                     80: #define MAESTRO_POSTEDWRITE    0x00000080
                     81: #define MAESTRO_DMA_PCITIMING  0x00000040
                     82: #define MAESTRO_SWAP_LR                0x00000010
                     83:
                     84: /* ACPI configurations */
                     85: #define CONF_ACPI_STOPCLOCK    0x54
                     86: #define ACPI_PART_2ndC_CLOCK   15
                     87: #define ACPI_PART_CODEC_CLOCK  14
                     88: #define ACPI_PART_978          13 /* Docking station or something */
                     89: #define ACPI_PART_SPDIF                12
                     90: #define ACPI_PART_GLUE         11 /* What? */
                     91: #define ACPI_PART_DAA          10
                     92: #define ACPI_PART_PCI_IF       9
                     93: #define ACPI_PART_HW_VOL       8
                     94: #define ACPI_PART_GPIO         7
                     95: #define ACPI_PART_ASSP         6
                     96: #define ACPI_PART_SB           5
                     97: #define ACPI_PART_FM           4
                     98: #define ACPI_PART_RINGBUS      3
                     99: #define ACPI_PART_MIDI         2
                    100: #define ACPI_PART_GAME_PORT    1
                    101: #define ACPI_PART_WP           0
                    102:
                    103: /* Power management */
                    104: #define        CONF_PM_PTR     0x34    /* BYTE R */
                    105: #define        PM_CID          0       /* BYTE R */
                    106: #define        PPMI_CID        1
                    107: #define        PM_CTRL         4       /* BYTE RW */
                    108: #define        PPMI_D0         0       /* Full power */
                    109: #define        PPMI_D1         1       /* Medium power */
                    110: #define        PPMI_D2         2       /* Low power */
                    111: #define        PPMI_D3         3       /* Turned off */
                    112:
                    113:
                    114: /* -----------------------------
                    115:  * I/O ports
                    116:  */
                    117:
                    118: /* Direct Sound Processor (aka Wave Processor) */
                    119: #define PORT_DSP_DATA  0x00    /* WORD RW */
                    120: #define PORT_DSP_INDEX 0x02    /* WORD RW */
                    121: #define PORT_INT_STAT  0x04    /* WORD RW */
                    122: #define PORT_SAMPLE_CNT        0x06    /* WORD RO */
                    123:
                    124: /* WaveCache */
                    125: #define PORT_WAVCACHE_INDEX    0x10    /* WORD RW */
                    126: #define PORT_WAVCACHE_DATA     0x12    /* WORD RW */
                    127: #define WAVCACHE_PCMBAR                0x1fc
                    128: #define WAVCACHE_WTBAR         0x1f0
                    129: #define WAVCACHE_BASEADDR_SHIFT        12
                    130:
                    131: #define WAVCACHE_CHCTL_ADDRTAG_MASK    0xfff8
                    132: #define WAVCACHE_CHCTL_U8              0x0004
                    133: #define WAVCACHE_CHCTL_STEREO          0x0002
                    134: #define WAVCACHE_CHCTL_DECREMENTAL     0x0001
                    135:
                    136: #define PORT_WAVCACHE_CTRL     0x14    /* WORD RW */
                    137: #define WAVCACHE_EXTRA_CH_ENABLED      0x0200
                    138: #define WAVCACHE_ENABLED               0x0100
                    139: #define WAVCACHE_CH_60_ENABLED         0x0080
                    140: #define WAVCACHE_WTSIZE_MASK   0x0060
                    141: #define WAVCACHE_WTSIZE_1MB    0x0000
                    142: #define WAVCACHE_WTSIZE_2MB    0x0020
                    143: #define WAVCACHE_WTSIZE_4MB    0x0040
                    144: #define WAVCACHE_WTSIZE_8MB    0x0060
                    145: #define WAVCACHE_SGC_MASK              0x000c
                    146: #define WAVCACHE_SGC_DISABLED          0x0000
                    147: #define WAVCACHE_SGC_40_47             0x0004
                    148: #define WAVCACHE_SGC_32_47             0x0008
                    149: #define WAVCACHE_TESTMODE              0x0001
                    150:
                    151: /* Host Interruption */
                    152: #define PORT_HOSTINT_CTRL      0x18    /* WORD RW */
                    153: #define HOSTINT_CTRL_SOFT_RESET                0x8000
                    154: #define HOSTINT_CTRL_DSOUND_RESET      0x4000
                    155: #define HOSTINT_CTRL_HW_VOL_TO_PME     0x0400
                    156: #define HOSTINT_CTRL_CLKRUN_ENABLED    0x0100
                    157: #define HOSTINT_CTRL_HWVOL_ENABLED     0x0040
                    158: #define HOSTINT_CTRL_ASSP_INT_ENABLED  0x0010
                    159: #define HOSTINT_CTRL_ISDN_INT_ENABLED  0x0008
                    160: #define HOSTINT_CTRL_DSOUND_INT_ENABLED        0x0004
                    161: #define HOSTINT_CTRL_MPU401_INT_ENABLED        0x0002
                    162: #define HOSTINT_CTRL_SB_INT_ENABLED    0x0001
                    163:
                    164: #define PORT_HOSTINT_STAT      0x1a    /* BYTE RW */
                    165: #define HOSTINT_STAT_HWVOL     0x40
                    166: #define HOSTINT_STAT_ASSP      0x10
                    167: #define HOSTINT_STAT_ISDN      0x08
                    168: #define HOSTINT_STAT_DSOUND    0x04
                    169: #define HOSTINT_STAT_MPU401    0x02
                    170: #define HOSTINT_STAT_SB                0x01
                    171:
                    172: /* Hardware volume */
                    173: #define PORT_HWVOL_VOICE_SHADOW        0x1c    /* BYTE RW */
                    174: #define PORT_HWVOL_VOICE       0x1d    /* BYTE RW */
                    175: #define PORT_HWVOL_MASTER_SHADOW 0x1e  /* BYTE RW */
                    176: #define PORT_HWVOL_MASTER      0x1f    /* BYTE RW */
                    177:
                    178: /* CODEC */
                    179: #define        PORT_CODEC_CMD  0x30    /* BYTE W */
                    180: #define CODEC_CMD_READ 0x80
                    181: #define        CODEC_CMD_WRITE 0x00
                    182: #define        CODEC_CMD_ADDR_MASK     0x7f
                    183:
                    184: #define PORT_CODEC_STAT        0x30    /* BYTE R */
                    185: #define CODEC_STAT_MASK        0x01
                    186: #define CODEC_STAT_RW_DONE     0x00
                    187: #define CODEC_STAT_PROGLESS    0x01
                    188:
                    189: #define PORT_CODEC_REG 0x32    /* WORD RW */
                    190:
                    191: /* Ring bus control */
                    192: #define PORT_RINGBUS_CTRL      0x34    /* DWORD RW */
                    193: #define RINGBUS_CTRL_I2S_ENABLED       0x80000000
                    194: #define RINGBUS_CTRL_RINGBUS_ENABLED   0x20000000
                    195: #define RINGBUS_CTRL_ACLINK_ENABLED    0x10000000
                    196: #define RINGBUS_CTRL_AC97_SWRESET      0x08000000
                    197: #define RINGBUS_CTRL_IODMA_PLAYBACK_ENABLED    0x04000000
                    198: #define RINGBUS_CTRL_IODMA_RECORD_ENABLED      0x02000000
                    199:
                    200: #define RINGBUS_SRC_MIC                20
                    201: #define RINGBUS_SRC_I2S                16
                    202: #define RINGBUS_SRC_ADC                12
                    203: #define RINGBUS_SRC_MODEM      8
                    204: #define RINGBUS_SRC_DSOUND     4
                    205: #define RINGBUS_SRC_ASSP       0
                    206:
                    207: #define RINGBUS_DEST_MONORAL   000
                    208: #define RINGBUS_DEST_STEREO    010
                    209: #define RINGBUS_DEST_NONE      0
                    210: #define RINGBUS_DEST_DAC       1
                    211: #define RINGBUS_DEST_MODEM_IN  2
                    212: #define RINGBUS_DEST_RESERVED3 3
                    213: #define RINGBUS_DEST_DSOUND_IN 4
                    214: #define RINGBUS_DEST_ASSP_IN   5
                    215:
                    216: /* General Purpose I/O */
                    217: #define PORT_GPIO_DATA 0x60    /* WORD RW */
                    218: #define PORT_GPIO_MASK 0x64    /* WORD RW */
                    219: #define PORT_GPIO_DIR  0x68    /* WORD RW */
                    220:
                    221: /* Application Specific Signal Processor */
                    222: #define PORT_ASSP_MEM_INDEX    0x80    /* DWORD RW */
                    223: #define PORT_ASSP_MEM_DATA     0x84    /* WORD RW */
                    224: #define PORT_ASSP_CTRL_A       0xa2    /* BYTE RW */
                    225: #define PORT_ASSP_CTRL_B       0xa4    /* BYTE RW */
                    226: #define PORT_ASSP_CTRL_C       0xa6    /* BYTE RW */
                    227: #define PORT_ASSP_HOST_WR_INDEX        0xa8    /* BYTE W */
                    228: #define PORT_ASSP_HOST_WR_DATA 0xaa    /* BYTE RW */
                    229: #define PORT_ASSP_INT_STAT     0xac    /* BYTE RW */
                    230:
                    231:
                    232: /* -----------------------------
                    233:  * Wave Processor Indexed Data Registers.
                    234:  */
                    235:
                    236: #define WPREG_DATA_PORT                0
                    237: #define WPREG_CRAM_PTR         1
                    238: #define WPREG_CRAM_DATA                2
                    239: #define WPREG_WAVE_DATA                3
                    240: #define WPREG_WAVE_PTR_LOW     4
                    241: #define WPREG_WAVE_PTR_HIGH    5
                    242:
                    243: #define WPREG_TIMER_FREQ       6
                    244: #define WP_TIMER_FREQ_PRESCALE_MASK    0x00e0  /* actual - 9 */
                    245: #define WP_TIMER_FREQ_PRESCALE_SHIFT   5
                    246: #define WP_TIMER_FREQ_DIVIDE_MASK      0x001f
                    247: #define WP_TIMER_FREQ_DIVIDE_SHIFT     0
                    248:
                    249: #define WPREG_WAVE_ROMRAM      7
                    250: #define WP_WAVE_VIRTUAL_ENABLED        0x0400
                    251: #define WP_WAVE_8BITRAM_ENABLED        0x0200
                    252: #define WP_WAVE_DRAM_ENABLED   0x0100
                    253: #define WP_WAVE_RAMSPLIT_MASK  0x00ff
                    254: #define WP_WAVE_RAMSPLIT_SHIFT 0
                    255:
                    256: #define WPREG_BASE             12
                    257: #define WP_PARAOUT_BASE_MASK   0xf000
                    258: #define WP_PARAOUT_BASE_SHIFT  12
                    259: #define WP_PARAIN_BASE_MASK    0x0f00
                    260: #define WP_PARAIN_BASE_SHIFT   8
                    261: #define WP_SERIAL0_BASE_MASK   0x00f0
                    262: #define WP_SERIAL0_BASE_SHIFT  4
                    263: #define WP_SERIAL1_BASE_MASK   0x000f
                    264: #define WP_SERIAL1_BASE_SHIFT  0
                    265:
                    266: #define WPREG_TIMER_ENABLE     17
                    267: #define WPREG_TIMER_START      23
                    268:
                    269:
                    270: /* -----------------------------
                    271:  * Audio Processing Unit.
                    272:  */
                    273: #define APUREG_APUTYPE 0
                    274: #define APU_DMA_ENABLED        0x4000
                    275: #define APU_INT_ON_LOOP        0x2000
                    276: #define APU_ENDCURVE   0x1000
                    277: #define APU_APUTYPE_MASK       0x00f0
                    278: #define APU_FILTERTYPE_MASK    0x000c
                    279: #define APU_FILTERQ_MASK       0x0003
                    280:
                    281: /* APU types */
                    282: #define APU_APUTYPE_SHIFT      4
                    283:
                    284: #define APUTYPE_INACTIVE       0
                    285: #define APUTYPE_16BITLINEAR    1
                    286: #define APUTYPE_16BITSTEREO    2
                    287: #define APUTYPE_8BITLINEAR     3
                    288: #define APUTYPE_8BITSTEREO     4
                    289: #define APUTYPE_8BITDIFF       5
                    290: #define APUTYPE_DIGITALDELAY   6
                    291: #define APUTYPE_DUALTAP_READER 7
                    292: #define APUTYPE_CORRELATOR     8
                    293: #define APUTYPE_INPUTMIXER     9
                    294: #define APUTYPE_WAVETABLE      10
                    295: #define APUTYPE_RATECONV       11
                    296: #define APUTYPE_16BITPINGPONG  12
                    297: /* APU type 13 through 15 are reserved. */
                    298:
                    299: /* Filter types */
                    300: #define APU_FILTERTYPE_SHIFT   2
                    301:
                    302: #define FILTERTYPE_2POLE_LOPASS                0
                    303: #define FILTERTYPE_2POLE_BANDPASS      1
                    304: #define FILTERTYPE_2POLE_HIPASS                2
                    305: #define FILTERTYPE_1POLE_LOPASS                3
                    306: #define FILTERTYPE_1POLE_HIPASS                4
                    307: #define FILTERTYPE_PASSTHROUGH         5
                    308:
                    309: /* Filter Q */
                    310: #define APU_FILTERQ_SHIFT      0
                    311:
                    312: #define FILTERQ_LESSQ  0
                    313: #define FILTERQ_MOREQ  3
                    314:
                    315: /* APU register 2 */
                    316: #define APUREG_FREQ_LOBYTE     2
                    317: #define APU_FREQ_LOBYTE_MASK   0xff00
                    318: #define APU_plus6dB            0x0010
                    319:
                    320: /* APU register 3 */
                    321: #define APUREG_FREQ_HIWORD     3
                    322: #define APU_FREQ_HIWORD_MASK   0x0fff
                    323:
                    324: /* Frequency */
                    325: #define APU_FREQ_LOBYTE_SHIFT  8
                    326: #define APU_FREQ_HIWORD_SHIFT  0
                    327: #define FREQ_Hz2DIV(freq)      (((u_int64_t)(freq) << 16) / 48000)
                    328:
                    329: /* APU register 4 */
                    330: #define APUREG_WAVESPACE       4
                    331: #define APU_STEREO             0x8000
                    332: #define APU_USE_SYSMEM         0x4000
                    333: #define APU_PCMBAR_MASK                0x6000
                    334: #define APU_64KPAGE_MASK       0xff00
                    335:
                    336: /* PCM Base Address Register selection */
                    337: #define APU_PCMBAR_SHIFT       13
                    338:
                    339: /* 64KW (==128KB) Page */
                    340: #define APU_64KPAGE_SHIFT      8
                    341:
                    342: /* APU register 5 - 7 */
                    343: #define APUREG_CURPTR  5
                    344: #define APUREG_ENDPTR  6
                    345: #define APUREG_LOOPLEN 7
                    346:
                    347: /* APU register 9 */
                    348: #define APUREG_AMPLITUDE       9
                    349: #define APU_AMPLITUDE_NOW_MASK 0xff00
                    350: #define APU_AMPLITUDE_DEST_MASK        0x00ff
                    351:
                    352: /* Amplitude now? */
                    353: #define APU_AMPLITUDE_NOW_SHIFT        8
                    354:
                    355: /* APU register 10 */
                    356: #define APUREG_POSITION        10
                    357: #define APU_RADIUS_MASK        0x00c0
                    358: #define APU_PAN_MASK   0x003f
                    359:
                    360: /* Radius control. */
                    361: #define APU_RADIUS_SHIFT       6
                    362: #define RADIUS_CENTERCIRCLE    0
                    363: #define RADIUS_MIDDLE          1
                    364: #define RADIUS_OUTSIDE         2
                    365:
                    366: /* Polar pan. */
                    367: #define APU_PAN_SHIFT  0
                    368: #define PAN_RIGHT      0x00
                    369: #define PAN_FRONT      0x08
                    370: #define PAN_LEFT       0x10
                    371:
                    372:
                    373: /* -----------------------------
                    374:  * Limits.
                    375:  */
                    376: #define WPWA_MAX       ((1 << 22) - 1)
                    377: #define WPWA_MAXADDR   ((1 << 23) - 1)
                    378: #define MAESTRO_MAXADDR        ((1 << 28) - 1)
                    379:
                    380:
                    381:
                    382: #ifdef AUDIO_DEBUG
                    383: #define DPRINTF(x)     if (maestrodebug) printf x
                    384: #define DLPRINTF(i, x) if (maestrodebug & i) printf x
                    385: int    maestrodebug = 0;
                    386: u_long maestrointr_called;
                    387: u_long maestrodma_effective;
                    388:
                    389: #define MAESTRODEBUG_INTR 1
                    390: #define MAESTRODEBUG_TIMER 2
                    391: #else
                    392: #define DPRINTF(x)
                    393: #define DLPRINTF(i, x)
                    394: #endif
                    395:
                    396: #define MAESTRO_BUFSIZ         0x4000
                    397: #define lengthof(array)                (sizeof (array) / sizeof (array)[0])
                    398:
                    399: #define STEP_VOLUME            0x22
                    400: #define MIDDLE_VOLUME          (STEP_VOLUME * 4)
                    401:
                    402: typedef struct salloc_pool {
                    403:        struct salloc_zone {
                    404:                SLIST_ENTRY(salloc_zone) link;
                    405:                caddr_t         addr;
                    406:                size_t          size;
                    407:        } *zones;
                    408:        SLIST_HEAD(salloc_head, salloc_zone) free, used, spare;
                    409: } *salloc_t;
                    410:
                    411: struct maestro_softc;
                    412:
                    413: #define MAESTRO_PLAY   1
                    414: #define MAESTRO_STEREO 2
                    415: #define MAESTRO_8BIT   4
                    416: #define MAESTRO_UNSIGNED       8
                    417: #define MAESTRO_RUNNING        16
                    418:
                    419: struct maestro_channel {
                    420:        struct maestro_softc    *sc;
                    421:        int                     num;
                    422:        u_int32_t               blocksize;
                    423:        u_int16_t               mode;
                    424:        u_int32_t               speed;
                    425:        u_int32_t               dv;
                    426:        u_int16_t               start;
                    427:        u_int16_t               threshold;
                    428:        u_int16_t               end;
                    429:        u_int16_t               current;
                    430:        u_int                   wpwa;
                    431:        void                    (*intr)(void *);
                    432:        void                    *intr_arg;
                    433: };
                    434:
                    435: struct maestro_softc {
                    436:        struct device           dev;
                    437:
                    438:        void                    *ih;
                    439:        pci_chipset_tag_t       pc;
                    440:        pcitag_t                pt;
                    441:
                    442: #define MAESTRO_FLAG_SETUPGPIO 0x0001
                    443:        int                     flags;
                    444:        bus_space_tag_t         iot;
                    445:        bus_space_handle_t      ioh;
                    446:        bus_dma_tag_t           dmat;
                    447:
                    448:        caddr_t                 dmabase;
                    449:        bus_addr_t              physaddr;
                    450:        size_t                  dmasize;
                    451:        bus_dmamap_t            dmamap;
                    452:        bus_dma_segment_t       dmaseg;
                    453:        salloc_t                dmapool;
                    454:
                    455:        struct ac97_codec_if    *codec_if;
                    456:        struct ac97_host_if     host_if;
                    457:        struct audio_device     *sc_audev;
                    458:
                    459:        void                    *powerhook;
                    460:        int                     suspend;
                    461:
                    462:        struct maestro_channel  play;
                    463:        struct maestro_channel  record;
                    464: };
                    465:
                    466:
                    467: typedef        u_int16_t wpreg_t;
                    468: typedef        u_int16_t wcreg_t;
                    469:
                    470: salloc_t salloc_new(caddr_t, size_t, int);
                    471: void   salloc_destroy(salloc_t);
                    472: caddr_t        salloc_alloc(salloc_t, size_t);
                    473: void   salloc_free(salloc_t, caddr_t);
                    474: void   salloc_insert(salloc_t, struct salloc_head *,
                    475:                struct salloc_zone *, int);
                    476:
                    477: int    maestro_match(struct device *, void *, void *);
                    478: void   maestro_attach(struct device *, struct device *, void *);
                    479: int    maestro_intr(void *);
                    480:
                    481: int    maestro_open(void *, int);
                    482: void   maestro_close(void *);
                    483: int    maestro_query_encoding(void *, struct audio_encoding *);
                    484: int    maestro_set_params(void *, int, int, struct audio_params *,
                    485:                            struct audio_params *);
                    486: int    maestro_round_blocksize(void *, int);
                    487: int    maestro_halt_output(void *);
                    488: int    maestro_halt_input(void *);
                    489: int    maestro_getdev(void *, struct audio_device *);
                    490: int    maestro_set_port(void *, mixer_ctrl_t *);
                    491: int    maestro_get_port(void *, mixer_ctrl_t *);
                    492: int    maestro_query_devinfo(void *, mixer_devinfo_t *);
                    493: void   *maestro_malloc(void *, int, size_t, int, int);
                    494: void   maestro_free(void *, void *, int);
                    495: paddr_t        maestro_mappage(void *, void *, off_t, int);
                    496: int    maestro_get_props(void *);
                    497: int    maestro_trigger_output(void *, void *, void *, int, void (*)(void *),
                    498:                                void *, struct audio_params *);
                    499: int    maestro_trigger_input(void *, void *, void *, int, void (*)(void *),
                    500:                               void *, struct audio_params *);
                    501:
                    502: int    maestro_attach_codec(void *, struct ac97_codec_if *);
                    503: int    maestro_read_codec(void *, u_int8_t, u_int16_t *);
                    504: int    maestro_write_codec(void *, u_int8_t, u_int16_t);
                    505: void   maestro_reset_codec(void *);
                    506:
                    507: void   maestro_initcodec(void *);
                    508:
                    509: void   maestro_set_speed(struct maestro_channel *, u_long *);
                    510: void   maestro_init(struct maestro_softc *);
                    511: void   maestro_power(struct maestro_softc *, int);
                    512: void   maestro_powerhook(int, void *);
                    513:
                    514: void   maestro_channel_start(struct maestro_channel *);
                    515: void   maestro_channel_stop(struct maestro_channel *);
                    516: void   maestro_channel_advance_dma(struct maestro_channel *);
                    517: void   maestro_channel_suppress_jitter(struct maestro_channel *);
                    518:
                    519: int    maestro_get_flags(struct pci_attach_args *);
                    520:
                    521: void   ringbus_setdest(struct maestro_softc *, int, int);
                    522:
                    523: wpreg_t        wp_reg_read(struct maestro_softc *, int);
                    524: void   wp_reg_write(struct maestro_softc *, int, wpreg_t);
                    525: wpreg_t        wp_apu_read(struct maestro_softc *, int, int);
                    526: void   wp_apu_write(struct maestro_softc *, int, int, wpreg_t);
                    527: void   wp_settimer(struct maestro_softc *, u_int);
                    528: void   wp_starttimer(struct maestro_softc *);
                    529: void   wp_stoptimer(struct maestro_softc *);
                    530:
                    531: wcreg_t        wc_reg_read(struct maestro_softc *, int);
                    532: void   wc_reg_write(struct maestro_softc *, int, wcreg_t);
                    533: wcreg_t        wc_ctrl_read(struct maestro_softc *, int);
                    534: void   wc_ctrl_write(struct maestro_softc *, int, wcreg_t);
                    535:
                    536: u_int maestro_calc_timer_freq(struct maestro_channel *);
                    537: void maestro_update_timer(struct maestro_softc *);
                    538:
                    539: struct cfdriver maestro_cd = {
                    540:        NULL, "maestro", DV_DULL
                    541: };
                    542:
                    543: struct cfattach maestro_ca = {
                    544:        sizeof (struct maestro_softc), maestro_match, maestro_attach
                    545: };
                    546:
                    547: struct audio_hw_if maestro_hw_if = {
                    548:        maestro_open,
                    549:        maestro_close,
                    550:        NULL,
                    551:        maestro_query_encoding,
                    552:        maestro_set_params,
                    553:        maestro_round_blocksize,
                    554:        NULL,
                    555:        NULL,
                    556:        NULL,
                    557:        NULL,
                    558:        NULL,
                    559:        maestro_halt_output,
                    560:        maestro_halt_input,
                    561:        NULL,
                    562:        maestro_getdev,
                    563:        NULL,
                    564:        maestro_set_port,
                    565:        maestro_get_port,
                    566:        maestro_query_devinfo,
                    567:        maestro_malloc,
                    568:        maestro_free,
                    569:        NULL,
                    570:        maestro_mappage,
                    571:        maestro_get_props,
                    572:        maestro_trigger_output,
                    573:        maestro_trigger_input
                    574: };
                    575:
                    576: struct audio_device maestro_audev = {
                    577:        "ESS Maestro", "", "maestro"
                    578: };
                    579:
                    580: struct {
                    581:        u_short vendor, product;
                    582:        int flags;
                    583: } maestro_pcitab[] = {
                    584:        { PCI_VENDOR_ESSTECH, PCI_PRODUCT_ESSTECH_MAESTROII,    0 },
                    585:        { PCI_VENDOR_ESSTECH, PCI_PRODUCT_ESSTECH_MAESTRO2E,    0 },
                    586:        { PCI_VENDOR_PLATFORM, PCI_PRODUCT_PLATFORM_ES1849,     0 },
                    587:        { PCI_VENDOR_NEC, PCI_PRODUCT_NEC_VERSAMAESTRO,         MAESTRO_FLAG_SETUPGPIO },
                    588:        { PCI_VENDOR_NEC, PCI_PRODUCT_NEC_VERSAPRONXVA26D,      MAESTRO_FLAG_SETUPGPIO }
                    589: };
                    590: #define NMAESTRO_PCITAB        lengthof(maestro_pcitab)
                    591:
                    592: int
                    593: maestro_get_flags(pa)
                    594:        struct pci_attach_args *pa;
                    595: {
                    596:        int i;
                    597:
                    598:        /* Distinguish audio devices from modems with the same manfid */
                    599:        if (PCI_CLASS(pa->pa_class) != PCI_CLASS_MULTIMEDIA)
                    600:                return (-1);
                    601:        if (PCI_SUBCLASS(pa->pa_class) != PCI_SUBCLASS_MULTIMEDIA_AUDIO)
                    602:                return (-1);
                    603:        for (i = 0; i < NMAESTRO_PCITAB; i++)
                    604:                if (PCI_VENDOR(pa->pa_id) == maestro_pcitab[i].vendor &&
                    605:                    PCI_PRODUCT(pa->pa_id) == maestro_pcitab[i].product)
                    606:                        return (maestro_pcitab[i].flags);
                    607:        return (-1);
                    608: }
                    609:
                    610: /* -----------------------------
                    611:  * Driver interface.
                    612:  */
                    613:
                    614: int
                    615: maestro_match(parent, match, aux)
                    616:        struct device *parent;
                    617:        void *match;
                    618:        void *aux;
                    619: {
                    620:        struct pci_attach_args *pa = (struct pci_attach_args *)aux;
                    621:
                    622:        if (maestro_get_flags(pa) == -1)
                    623:                return (0);
                    624:        else
                    625:                return (1);
                    626: }
                    627:
                    628: void
                    629: maestro_attach(parent, self, aux)
                    630:        struct device *parent;
                    631:        struct device *self;
                    632:        void *aux;
                    633: {
                    634:        struct maestro_softc *sc = (struct maestro_softc *)self;
                    635:        struct pci_attach_args *pa = (struct pci_attach_args *)aux;
                    636:        pci_chipset_tag_t pc = pa->pa_pc;
                    637:        char const *intrstr;
                    638:        pci_intr_handle_t ih;
                    639:        int error;
                    640:        u_int16_t cdata;
                    641:        int dmastage = 0;
                    642:        int rseg;
                    643:
                    644:        sc->sc_audev = &maestro_audev;
                    645:        sc->flags = maestro_get_flags(pa);
                    646:
                    647:        sc->pc = pa->pa_pc;
                    648:        sc->pt = pa->pa_tag;
                    649:        sc->dmat = pa->pa_dmat;
                    650:
                    651:        /* Map interrupt */
                    652:        if (pci_intr_map(pa, &ih)) {
                    653:                printf(": couldn't map interrupt\n");
                    654:                return;
                    655:        }
                    656:        intrstr = pci_intr_string(pc, ih);
                    657:        sc->ih = pci_intr_establish(pc, ih, IPL_AUDIO, maestro_intr, sc,
                    658:            sc->dev.dv_xname);
                    659:        if (sc->ih == NULL) {
                    660:                printf(": couldn't establish interrupt");
                    661:                if (intrstr != NULL)
                    662:                        printf(" at %s\n", intrstr);
                    663:                return;
                    664:        }
                    665:        printf(": %s", intrstr);
                    666:
                    667:        /* Rangers, power up */
                    668:        maestro_power(sc, PPMI_D0);
                    669:        DELAY(100000);
                    670:
                    671:        /* Map i/o */
                    672:        if ((error = pci_mapreg_map(pa, PCI_MAPS, PCI_MAPREG_TYPE_IO,
                    673:            0, &sc->iot, &sc->ioh, NULL, NULL, 0)) != 0) {
                    674:                printf(", couldn't map i/o space\n");
                    675:                goto bad;
                    676:        };
                    677:
                    678:        /* Allocate fixed DMA segment :-( */
                    679:        sc->dmasize = MAESTRO_BUFSIZ * 16;
                    680:        if ((error = bus_dmamem_alloc(sc->dmat, sc->dmasize, NBPG, 0,
                    681:            &sc->dmaseg, 1, &rseg, BUS_DMA_NOWAIT)) != 0) {
                    682:                printf(", unable to alloc dma, error %d\n", error);
                    683:                goto bad;
                    684:        }
                    685:        dmastage = 1;
                    686:        if ((error = bus_dmamem_map(sc->dmat, &sc->dmaseg, 1,
                    687:            sc->dmasize, &sc->dmabase, BUS_DMA_NOWAIT |
                    688:            BUS_DMA_COHERENT)) != 0) {
                    689:                printf(", unable to map dma, error %d\n", error);
                    690:                goto bad;
                    691:        }
                    692:        dmastage = 2;
                    693:        if ((error = bus_dmamap_create(sc->dmat, sc->dmasize, 1,
                    694:            sc->dmasize, 0, BUS_DMA_NOWAIT, &sc->dmamap)) != 0) {
                    695:                printf(", unable to create dma map, error %d\n", error);
                    696:                goto bad;
                    697:        }
                    698:        dmastage = 3;
                    699:        if ((error = bus_dmamap_load(sc->dmat, sc->dmamap,
                    700:            sc->dmabase, sc->dmasize, NULL, BUS_DMA_NOWAIT)) != 0) {
                    701:                printf(", unable to load dma map, error %d\n", error);
                    702:                goto bad;
                    703:        }
                    704:
                    705:        /* XXX
                    706:         * The first byte of the allocated memory is not usable,
                    707:         * the WP sometimes uses it to store status.
                    708:         */
                    709:        /* Make DMA memory pool */
                    710:        if ((sc->dmapool = salloc_new(sc->dmabase+16, sc->dmasize-16,
                    711:            128/*overkill?*/)) == NULL) {
                    712:                printf(", unable to make dma pool\n");
                    713:                goto bad;
                    714:        }
                    715:
                    716:        sc->physaddr = sc->dmamap->dm_segs[0].ds_addr;
                    717:
                    718:        printf("\n");
                    719:
                    720:        /* Kick device */
                    721:        maestro_init(sc);
                    722:        maestro_read_codec(sc, 0, &cdata);
                    723:        if (cdata == 0x80) {
                    724:                printf("%s: PT101 codec unsupported, no mixer\n",
                    725:                    sc->dev.dv_xname);
                    726:                /* Init values from Linux, no idea what this does. */
                    727:                maestro_write_codec(sc, 0x2a, 0x0001);
                    728:                maestro_write_codec(sc, 0x2C, 0x0000);
                    729:                maestro_write_codec(sc, 0x2C, 0xFFFF);
                    730:                maestro_write_codec(sc, 0x10, 0x9F1F);
                    731:                maestro_write_codec(sc, 0x12, 0x0808);
                    732:                maestro_write_codec(sc, 0x14, 0x9F1F);
                    733:                maestro_write_codec(sc, 0x16, 0x9F1F);
                    734:                maestro_write_codec(sc, 0x18, 0x0404);
                    735:                maestro_write_codec(sc, 0x1A, 0x0000);
                    736:                maestro_write_codec(sc, 0x1C, 0x0000);
                    737:                maestro_write_codec(sc, 0x02, 0x0404);
                    738:                maestro_write_codec(sc, 0x04, 0x0808);
                    739:                maestro_write_codec(sc, 0x0C, 0x801F);
                    740:                maestro_write_codec(sc, 0x0E, 0x801F);
                    741:                /* no control over the mixer, sorry */
                    742:                sc->codec_if = NULL;
                    743:        } else {
                    744:                /* Attach the AC'97 */
                    745:                sc->host_if.arg = sc;
                    746:                sc->host_if.attach = maestro_attach_codec;
                    747:                sc->host_if.read = maestro_read_codec;
                    748:                sc->host_if.write = maestro_write_codec;
                    749:                sc->host_if.reset = maestro_reset_codec;
                    750:                if (ac97_attach(&sc->host_if) != 0) {
                    751:                        printf("%s: couldn't attach codec\n", sc->dev.dv_xname);
                    752:                        goto bad;
                    753:                }
                    754:        }
                    755:
                    756:        sc->play.mode = MAESTRO_PLAY;
                    757:        sc->play.sc = sc;
                    758:        sc->play.num = 0;
                    759:        sc->record.sc = sc;
                    760:        sc->record.num = 2;
                    761:        sc->record.mode = 0;
                    762:
                    763:        /* Attach audio */
                    764:        audio_attach_mi(&maestro_hw_if, sc, &sc->dev);
                    765:
                    766:        /* Hook power changes */
                    767:        sc->suspend = PWR_RESUME;
                    768:        sc->powerhook = powerhook_establish(maestro_powerhook, sc);
                    769:
                    770:        return;
                    771:
                    772:  bad:
                    773:        /* Power down. */
                    774:        maestro_power(sc, PPMI_D3);
                    775:        if (sc->ih)
                    776:                pci_intr_disestablish(pc, sc->ih);
                    777:        printf("%s: disabled\n", sc->dev.dv_xname);
                    778:        if (sc->dmapool)
                    779:                salloc_destroy(sc->dmapool);
                    780:        if (dmastage >= 3)
                    781:                bus_dmamap_destroy(sc->dmat, sc->dmamap);
                    782:        if (dmastage >= 2)
                    783:                bus_dmamem_unmap(sc->dmat, sc->dmabase, sc->dmasize);
                    784:        if (dmastage >= 1)
                    785:                bus_dmamem_free(sc->dmat, &sc->dmaseg, 1);
                    786: }
                    787:
                    788: void
                    789: maestro_init(sc)
                    790:        struct maestro_softc *sc;
                    791: {
                    792:        int reg;
                    793:        pcireg_t data;
                    794:
                    795:        /* Disable all legacy emulations. */
                    796:        data = pci_conf_read(sc->pc, sc->pt, CONF_LEGACY);
                    797:        data |= LEGACY_DISABLED;
                    798:        pci_conf_write(sc->pc, sc->pt, CONF_LEGACY, data);
                    799:
                    800:        /* Disconnect from CHI. (Makes Dell inspiron 7500 work?)
                    801:         * Enable posted write.
                    802:         * Prefer PCI timing rather than that of ISA.
                    803:         * Don't swap L/R. */
                    804:        data = pci_conf_read(sc->pc, sc->pt, CONF_MAESTRO);
                    805:        data |= MAESTRO_CHIBUS | MAESTRO_POSTEDWRITE | MAESTRO_DMA_PCITIMING;
                    806:        data &= ~MAESTRO_SWAP_LR;
                    807:        pci_conf_write(sc->pc, sc->pt, CONF_MAESTRO, data);
                    808:        /* Reset direct sound. */
                    809:        bus_space_write_2(sc->iot, sc->ioh, PORT_HOSTINT_CTRL,
                    810:            HOSTINT_CTRL_DSOUND_RESET);
                    811:        DELAY(10000);   /* XXX - too long? */
                    812:        bus_space_write_2(sc->iot, sc->ioh, PORT_HOSTINT_CTRL, 0);
                    813:        DELAY(10000);
                    814:
                    815:        /* Enable direct sound and hardware volume control interruptions. */
                    816:        bus_space_write_2(sc->iot, sc->ioh, PORT_HOSTINT_CTRL,
                    817:            HOSTINT_CTRL_DSOUND_INT_ENABLED | HOSTINT_CTRL_HWVOL_ENABLED);
                    818:
                    819:        /* Setup Wave Processor. */
                    820:
                    821:        /* Enable WaveCache, set DMA base address. */
                    822:        wp_reg_write(sc, WPREG_WAVE_ROMRAM,
                    823:            WP_WAVE_VIRTUAL_ENABLED | WP_WAVE_DRAM_ENABLED);
                    824:        bus_space_write_2(sc->iot, sc->ioh, PORT_WAVCACHE_CTRL,
                    825:            WAVCACHE_ENABLED | WAVCACHE_WTSIZE_4MB);
                    826:
                    827:        for (reg = WAVCACHE_PCMBAR; reg < WAVCACHE_PCMBAR + 4; reg++)
                    828:                wc_reg_write(sc, reg,
                    829:                        sc->physaddr >> WAVCACHE_BASEADDR_SHIFT);
                    830:
                    831:        /* Setup Codec/Ringbus. */
                    832:        maestro_initcodec(sc);
                    833:        bus_space_write_4(sc->iot, sc->ioh, PORT_RINGBUS_CTRL,
                    834:            RINGBUS_CTRL_RINGBUS_ENABLED | RINGBUS_CTRL_ACLINK_ENABLED);
                    835:
                    836:        wp_reg_write(sc, WPREG_BASE, 0x8500);   /* Parallel I/O */
                    837:        ringbus_setdest(sc, RINGBUS_SRC_ADC,
                    838:            RINGBUS_DEST_STEREO | RINGBUS_DEST_DSOUND_IN);
                    839:        ringbus_setdest(sc, RINGBUS_SRC_DSOUND,
                    840:            RINGBUS_DEST_STEREO | RINGBUS_DEST_DAC);
                    841:
                    842:        /* Setup ASSP. Needed for Dell Inspiron 7500? */
                    843:        bus_space_write_1(sc->iot, sc->ioh, PORT_ASSP_CTRL_B, 0x00);
                    844:        bus_space_write_1(sc->iot, sc->ioh, PORT_ASSP_CTRL_A, 0x03);
                    845:        bus_space_write_1(sc->iot, sc->ioh, PORT_ASSP_CTRL_C, 0x00);
                    846:
                    847:        /*
                    848:         * Reset hw volume to a known value so that we may handle diffs
                    849:         * off to AC'97.
                    850:         */
                    851:
                    852:        bus_space_write_1(sc->iot, sc->ioh, PORT_HWVOL_MASTER, MIDDLE_VOLUME);
                    853:        /* Setup GPIO if needed (NEC systems) */
                    854:        if (sc->flags & MAESTRO_FLAG_SETUPGPIO) {
                    855:                /* Matthew Braithwaite <matt@braithwaite.net> reported that
                    856:                 * NEC Versa LX doesn't need GPIO operation. */
                    857:                bus_space_write_2(sc->iot, sc->ioh,
                    858:                    PORT_GPIO_MASK, 0x9ff);
                    859:                bus_space_write_2(sc->iot, sc->ioh, PORT_GPIO_DIR,
                    860:                    bus_space_read_2(sc->iot, sc->ioh, PORT_GPIO_DIR) | 0x600);
                    861:                bus_space_write_2(sc->iot, sc->ioh,
                    862:                    PORT_GPIO_DATA, 0x200);
                    863:        }
                    864: }
                    865:
                    866: /* -----------------------------
                    867:  * Audio interface
                    868:  */
                    869:
                    870: int
                    871: maestro_round_blocksize(self, blk)
                    872:        void *self;
                    873:        int blk;
                    874: {
                    875:        return ((blk + 0xf) & ~0xf);
                    876: }
                    877:
                    878: void *
                    879: maestro_malloc(arg, dir, size, pool, flags)
                    880:        void *arg;
                    881:        int dir;
                    882:        size_t size;
                    883:        int pool, flags;
                    884: {
                    885:        struct maestro_softc *sc = (struct maestro_softc *)arg;
                    886:
                    887:        return (salloc_alloc(sc->dmapool, size));
                    888: }
                    889:
                    890: void
                    891: maestro_free(self, ptr, pool)
                    892:        void *self, *ptr;
                    893:        int pool;
                    894: {
                    895:        struct maestro_softc *sc = (struct maestro_softc *)self;
                    896:
                    897:        salloc_free(sc->dmapool, ptr);
                    898: }
                    899:
                    900: paddr_t
                    901: maestro_mappage(self, mem, off, prot)
                    902:        void *self, *mem;
                    903:        off_t off;
                    904:        int prot;
                    905: {
                    906:        struct maestro_softc *sc = (struct maestro_softc *)self;
                    907:
                    908:        if (off < 0)
                    909:                return -1;
                    910:        return bus_dmamem_mmap(sc->dmat, &sc->dmaseg, 1,
                    911:                off, prot, BUS_DMA_WAITOK);
                    912: }
                    913:
                    914: int
                    915: maestro_get_props(self)
                    916:        void *self;
                    917: {
                    918:        /* struct maestro_softc *sc = (struct maestro_softc *)self; */
                    919:
                    920:        return (AUDIO_PROP_MMAP | AUDIO_PROP_INDEPENDENT); /* XXX */
                    921: }
                    922:
                    923: int
                    924: maestro_getdev(self, retp)
                    925:        void *self;
                    926:        struct audio_device *retp;
                    927: {
                    928:        struct maestro_softc *sc = (struct maestro_softc *)self;
                    929:
                    930:        *retp = *sc->sc_audev;
                    931:        return 0;
                    932: }
                    933:
                    934: int
                    935: maestro_set_port(self, cp)
                    936:        void *self;
                    937:        mixer_ctrl_t *cp;
                    938: {
                    939:        struct ac97_codec_if *c = ((struct maestro_softc *)self)->codec_if;
                    940:
                    941:        if (c)
                    942:                return (c->vtbl->mixer_set_port(c, cp));
                    943:        else
                    944:                return (ENXIO);
                    945: }
                    946:
                    947: int
                    948: maestro_get_port(self, cp)
                    949:        void *self;
                    950:        mixer_ctrl_t *cp;
                    951: {
                    952:        struct ac97_codec_if *c = ((struct maestro_softc *)self)->codec_if;
                    953:
                    954:        if (c)
                    955:                return (c->vtbl->mixer_get_port(c, cp));
                    956:        else
                    957:                return (ENXIO);
                    958: }
                    959:
                    960: int
                    961: maestro_query_devinfo(self, cp)
                    962:        void *self;
                    963:        mixer_devinfo_t *cp;
                    964: {
                    965:        struct ac97_codec_if *c = ((struct maestro_softc *)self)->codec_if;
                    966:
                    967:        if (c)
                    968:                return (c->vtbl->query_devinfo(c, cp));
                    969:        else
                    970:                return (ENXIO);
                    971: }
                    972:
                    973: struct audio_encoding maestro_tab[] = {
                    974:        {0, AudioEslinear_le, AUDIO_ENCODING_SLINEAR_LE, 16, 0},
                    975:        {1, AudioEslinear, AUDIO_ENCODING_SLINEAR, 8, 0},
                    976:        {2, AudioEulinear, AUDIO_ENCODING_ULINEAR, 8, 0},
                    977:        {3, AudioEslinear_be, AUDIO_ENCODING_SLINEAR_BE, 16,
                    978:            AUDIO_ENCODINGFLAG_EMULATED},
                    979:        {4, AudioEulinear_le, AUDIO_ENCODING_ULINEAR_LE, 16,
                    980:            AUDIO_ENCODINGFLAG_EMULATED},
                    981:        {5, AudioEulinear_be, AUDIO_ENCODING_ULINEAR_BE, 16,
                    982:            AUDIO_ENCODINGFLAG_EMULATED},
                    983:        {6, AudioEmulaw, AUDIO_ENCODING_ULAW, 8,
                    984:            AUDIO_ENCODINGFLAG_EMULATED},
                    985:        {7, AudioEalaw, AUDIO_ENCODING_ALAW, 8,
                    986:            AUDIO_ENCODINGFLAG_EMULATED}
                    987: };
                    988:
                    989: int
                    990: maestro_query_encoding(hdl, fp)
                    991:        void *hdl;
                    992:        struct audio_encoding *fp;
                    993: {
                    994:        if (fp->index < 0 || fp->index >= lengthof(maestro_tab))
                    995:                return (EINVAL);
                    996:        *fp = maestro_tab[fp->index];
                    997:        return (0);
                    998: }
                    999:
                   1000: #define UNUSED __attribute__((unused))
                   1001:
                   1002: void
                   1003: maestro_set_speed(ch, prate)
                   1004:        struct maestro_channel *ch;
                   1005:        u_long *prate;
                   1006: {
                   1007:        ch->speed = *prate;
                   1008:        if ((ch->mode & (MAESTRO_8BIT | MAESTRO_STEREO)) == MAESTRO_8BIT)
                   1009:                ch->speed /= 2;
                   1010:
                   1011:        /* special common case */
                   1012:        if (ch->speed == 48000) {
                   1013:                ch->dv = 0x10000;
                   1014:        } else {
                   1015:                /* compute 16 bits fixed point value of speed/48000,
                   1016:                 * being careful not to overflow */
                   1017:                 ch->dv = (((ch->speed % 48000) << 16U) + 24000) / 48000
                   1018:                    + ((ch->speed / 48000) << 16U);
                   1019:                /* And this is the real rate obtained */
                   1020:                ch->speed = (ch->dv >> 16U) * 48000 +
                   1021:                    (((ch->dv & 0xffff)*48000)>>16U);
                   1022:        }
                   1023:        *prate = ch->speed;
                   1024:        if ((ch->mode & (MAESTRO_8BIT | MAESTRO_STEREO)) == MAESTRO_8BIT)
                   1025:                *prate *= 2;
                   1026: }
                   1027:
                   1028: u_int
                   1029: maestro_calc_timer_freq(ch)
                   1030:        struct maestro_channel *ch;
                   1031: {
                   1032:        u_int   ss = 2;
                   1033:
                   1034:        if (ch->mode & MAESTRO_8BIT)
                   1035:                ss = 1;
                   1036:        return (ch->speed * ss) / ch->blocksize;
                   1037: }
                   1038:
                   1039: void
                   1040: maestro_update_timer(sc)
                   1041:        struct maestro_softc *sc;
                   1042: {
                   1043:        u_int freq = 0;
                   1044:        u_int n;
                   1045:
                   1046:        if (sc->play.mode & MAESTRO_RUNNING)
                   1047:                freq = maestro_calc_timer_freq(&sc->play);
                   1048:        if (sc->record.mode & MAESTRO_RUNNING) {
                   1049:                n = maestro_calc_timer_freq(&sc->record);
                   1050:                if (freq < n)
                   1051:                        freq = n;
                   1052:        }
                   1053:        if (freq) {
                   1054:                wp_settimer(sc, freq);
                   1055:                wp_starttimer(sc);
                   1056:        } else
                   1057:                wp_stoptimer(sc);
                   1058: }
                   1059:
                   1060:
                   1061: int
                   1062: maestro_set_params(hdl, setmode, usemode, play, rec)
                   1063:        void *hdl;
                   1064:        int setmode, usemode;
                   1065:        struct audio_params *play, *rec;
                   1066: {
                   1067:        struct maestro_softc *sc = (struct maestro_softc *)hdl;
                   1068:
                   1069:        if ((setmode & AUMODE_PLAY) == 0)
                   1070:                return (0);
                   1071:
                   1072:        /* Disallow parameter change on a running audio for now */
                   1073:        if (sc->play.mode & MAESTRO_RUNNING)
                   1074:                return (EINVAL);
                   1075:
                   1076:        if (play->sample_rate < 4000)
                   1077:                play->sample_rate = 4000;
                   1078:        else if (play->sample_rate > 48000)
                   1079:                play->sample_rate = 48000;
                   1080:
                   1081:        play->factor = 1;
                   1082:        play->sw_code = NULL;
                   1083:        if (play->channels != 1 && play->channels != 2)
                   1084:                return (EINVAL);
                   1085:
                   1086:
                   1087:        sc->play.mode = MAESTRO_PLAY;
                   1088:        if (play->channels == 2)
                   1089:                sc->play.mode |= MAESTRO_STEREO;
                   1090:
                   1091:        if (play->encoding == AUDIO_ENCODING_ULAW) {
                   1092:                play->factor = 2;
                   1093:                play->sw_code = mulaw_to_slinear16_le;
                   1094:        } else if (play->encoding == AUDIO_ENCODING_ALAW) {
                   1095:                play->factor = 2;
                   1096:                play->sw_code = alaw_to_slinear16_le;
                   1097:        } else if (play->precision == 8) {
                   1098:                sc->play.mode |= MAESTRO_8BIT;
                   1099:                if (play->encoding == AUDIO_ENCODING_ULINEAR_LE ||
                   1100:                    play->encoding == AUDIO_ENCODING_ULINEAR_BE)
                   1101:                    sc->play.mode |= MAESTRO_UNSIGNED;
                   1102:        }
                   1103:        else if (play->encoding == AUDIO_ENCODING_ULINEAR_LE)
                   1104:                play->sw_code = change_sign16_le;
                   1105:        else if (play->encoding == AUDIO_ENCODING_SLINEAR_BE)
                   1106:                play->sw_code = swap_bytes;
                   1107:        else if (play->encoding == AUDIO_ENCODING_ULINEAR_BE)
                   1108:                play->sw_code = change_sign16_swap_bytes_le;
                   1109:        else if (play->encoding != AUDIO_ENCODING_SLINEAR_LE)
                   1110:                return (EINVAL);
                   1111:
                   1112:        maestro_set_speed(&sc->play, &play->sample_rate);
                   1113:        return (0);
                   1114: }
                   1115:
                   1116: int
                   1117: maestro_open(hdl, flags)
                   1118:        void *hdl;
                   1119:        int flags;
                   1120: {
                   1121:        struct maestro_softc *sc = (struct maestro_softc *)hdl;
                   1122:        DPRINTF(("%s: open(%d)\n", sc->dev.dv_xname, flags));
                   1123:
                   1124: /* XXX work around VM brokeness */
                   1125: #if 0
                   1126:        if ((OFLAGS(flags) & O_ACCMODE) != O_WRONLY)
                   1127:                return (EINVAL);
                   1128: #endif
                   1129:        sc->play.mode = MAESTRO_PLAY;
                   1130:        sc->record.mode = 0;
                   1131: #ifdef AUDIO_DEBUG
                   1132:        maestrointr_called = 0;
                   1133:        maestrodma_effective = 0;
                   1134: #endif
                   1135:        return (0);
                   1136: }
                   1137:
                   1138: void
                   1139: maestro_close(hdl)
                   1140:        void *hdl;
                   1141: {
                   1142:        struct maestro_softc *sc UNUSED = (struct maestro_softc *)hdl;
                   1143:        /* nothing to do */
                   1144: }
                   1145:
                   1146:
                   1147: void
                   1148: maestro_channel_stop(ch)
                   1149:        struct maestro_channel *ch;
                   1150: {
                   1151:        wp_apu_write(ch->sc, ch->num, APUREG_APUTYPE,
                   1152:            APUTYPE_INACTIVE << APU_APUTYPE_SHIFT);
                   1153:        if (ch->mode & MAESTRO_STEREO)
                   1154:            wp_apu_write(ch->sc, ch->num+1, APUREG_APUTYPE,
                   1155:                APUTYPE_INACTIVE << APU_APUTYPE_SHIFT);
                   1156:        /* four channels for record... */
                   1157:        if (ch->mode & MAESTRO_PLAY)
                   1158:                return;
                   1159:        wp_apu_write(ch->sc, ch->num+2, APUREG_APUTYPE,
                   1160:            APUTYPE_INACTIVE << APU_APUTYPE_SHIFT);
                   1161:        if (ch->mode & MAESTRO_STEREO)
                   1162:            wp_apu_write(ch->sc, ch->num+3, APUREG_APUTYPE,
                   1163:                APUTYPE_INACTIVE << APU_APUTYPE_SHIFT);
                   1164:
                   1165: }
                   1166:
                   1167: int
                   1168: maestro_halt_input(hdl)
                   1169:        void *hdl;
                   1170: {
                   1171:        struct maestro_softc *sc = (struct maestro_softc *)hdl;
                   1172:        maestro_channel_stop(&sc->record);
                   1173:        sc->record.mode &= ~MAESTRO_RUNNING;
                   1174:        maestro_update_timer(sc);
                   1175:        return 0;
                   1176: }
                   1177:
                   1178: int
                   1179: maestro_halt_output(hdl)
                   1180:        void *hdl;
                   1181: {
                   1182:        struct maestro_softc *sc = (struct maestro_softc *)hdl;
                   1183:
                   1184:        maestro_channel_stop(&sc->play);
                   1185:        sc->play.mode &= ~MAESTRO_RUNNING;
                   1186:        maestro_update_timer(sc);
                   1187:        return 0;
                   1188: }
                   1189:
                   1190: int
                   1191: maestro_trigger_input(hdl, start, end, blksize, intr, arg, param)
                   1192:        void *hdl;
                   1193:        void *start, *end;
                   1194:        int blksize;
                   1195:        void (*intr)(void *);
                   1196:        void *arg;
                   1197:        struct audio_params *param;
                   1198: {
                   1199:        struct maestro_softc *sc = (struct maestro_softc *)hdl;
                   1200:
                   1201:        sc->record.mode |= MAESTRO_RUNNING;
                   1202:        sc->record.blocksize = blksize;
                   1203:
                   1204:        maestro_channel_start(&sc->record);
                   1205:
                   1206:        sc->record.threshold = sc->record.start;
                   1207:        maestro_update_timer(sc);
                   1208:        return 0;
                   1209: }
                   1210:
                   1211: void
                   1212: maestro_channel_start(ch)
                   1213:        struct maestro_channel *ch;
                   1214: {
                   1215:        struct maestro_softc *sc = ch->sc;
                   1216:        int n = ch->num;
                   1217:        int aputype;
                   1218:        wcreg_t wcreg = (sc->physaddr - 16) & WAVCACHE_CHCTL_ADDRTAG_MASK;
                   1219:
                   1220:        switch(ch->mode & (MAESTRO_STEREO | MAESTRO_8BIT)) {
                   1221:        case 0:
                   1222:                aputype = APUTYPE_16BITLINEAR;
                   1223:                break;
                   1224:        case MAESTRO_STEREO:
                   1225:                aputype = APUTYPE_16BITSTEREO;
                   1226:                break;
                   1227:        case MAESTRO_8BIT:
                   1228:                aputype = APUTYPE_8BITLINEAR;
                   1229:                break;
                   1230:        case MAESTRO_8BIT|MAESTRO_STEREO:
                   1231:                aputype = APUTYPE_8BITSTEREO;
                   1232:                break;
                   1233:        }
                   1234:        if (ch->mode & MAESTRO_UNSIGNED)
                   1235:                wcreg |= WAVCACHE_CHCTL_U8;
                   1236:        if ((ch->mode & MAESTRO_STEREO) == 0) {
                   1237:                DPRINTF(("Setting mono parameters\n"));
                   1238:                wp_apu_write(sc, n, APUREG_WAVESPACE, ch->wpwa & 0xff00);
                   1239:                wp_apu_write(sc, n, APUREG_CURPTR, ch->current);
                   1240:                wp_apu_write(sc, n, APUREG_ENDPTR, ch->end);
                   1241:                wp_apu_write(sc, n, APUREG_LOOPLEN, ch->end - ch->start);
                   1242:                wp_apu_write(sc, n, APUREG_AMPLITUDE, 0xe800);
                   1243:                wp_apu_write(sc, n, APUREG_POSITION, 0x8f00
                   1244:                    | (RADIUS_CENTERCIRCLE << APU_RADIUS_SHIFT)
                   1245:                    | (PAN_FRONT << APU_PAN_SHIFT));
                   1246:                wp_apu_write(sc, n, APUREG_FREQ_LOBYTE, APU_plus6dB
                   1247:                    | ((ch->dv & 0xff) << APU_FREQ_LOBYTE_SHIFT));
                   1248:                wp_apu_write(sc, n, APUREG_FREQ_HIWORD, ch->dv >> 8);
                   1249:                wc_ctrl_write(sc, n, wcreg);
                   1250:                wp_apu_write(sc, n, APUREG_APUTYPE,
                   1251:                    (aputype << APU_APUTYPE_SHIFT) | APU_DMA_ENABLED | 0xf);
                   1252:        } else {
                   1253:                wcreg |= WAVCACHE_CHCTL_STEREO;
                   1254:                DPRINTF(("Setting stereo parameters\n"));
                   1255:                wp_apu_write(sc, n+1, APUREG_WAVESPACE, ch->wpwa & 0xff00);
                   1256:                wp_apu_write(sc, n+1, APUREG_CURPTR, ch->current);
                   1257:                wp_apu_write(sc, n+1, APUREG_ENDPTR, ch->end);
                   1258:                wp_apu_write(sc, n+1, APUREG_LOOPLEN, ch->end - ch->start);
                   1259:                wp_apu_write(sc, n+1, APUREG_AMPLITUDE, 0xe800);
                   1260:                wp_apu_write(sc, n+1, APUREG_POSITION, 0x8f00
                   1261:                    | (RADIUS_CENTERCIRCLE << APU_RADIUS_SHIFT)
                   1262:                    | (PAN_LEFT << APU_PAN_SHIFT));
                   1263:                wp_apu_write(sc, n+1, APUREG_FREQ_LOBYTE, APU_plus6dB
                   1264:                    | ((ch->dv & 0xff) << APU_FREQ_LOBYTE_SHIFT));
                   1265:                wp_apu_write(sc, n+1, APUREG_FREQ_HIWORD, ch->dv >> 8);
                   1266:                if (ch->mode & MAESTRO_8BIT)
                   1267:                        wp_apu_write(sc, n, APUREG_WAVESPACE,
                   1268:                            ch->wpwa & 0xff00);
                   1269:                    else
                   1270:                        wp_apu_write(sc, n, APUREG_WAVESPACE,
                   1271:                            (ch->wpwa|(APU_STEREO >> 1)) & 0xff00);
                   1272:                wp_apu_write(sc, n, APUREG_CURPTR, ch->current);
                   1273:                wp_apu_write(sc, n, APUREG_ENDPTR, ch->end);
                   1274:                wp_apu_write(sc, n, APUREG_LOOPLEN, ch->end - ch->start);
                   1275:                wp_apu_write(sc, n, APUREG_AMPLITUDE, 0xe800);
                   1276:                wp_apu_write(sc, n, APUREG_POSITION, 0x8f00
                   1277:                    | (RADIUS_CENTERCIRCLE << APU_RADIUS_SHIFT)
                   1278:                    | (PAN_RIGHT << APU_PAN_SHIFT));
                   1279:                wp_apu_write(sc, n, APUREG_FREQ_LOBYTE, APU_plus6dB
                   1280:                    | ((ch->dv & 0xff) << APU_FREQ_LOBYTE_SHIFT));
                   1281:                wp_apu_write(sc, n, APUREG_FREQ_HIWORD, ch->dv >> 8);
                   1282:                wc_ctrl_write(sc, n, wcreg);
                   1283:                wc_ctrl_write(sc, n+1, wcreg);
                   1284:                wp_apu_write(sc, n, APUREG_APUTYPE,
                   1285:                    (aputype << APU_APUTYPE_SHIFT) | APU_DMA_ENABLED | 0xf);
                   1286:                wp_apu_write(sc, n+1, APUREG_APUTYPE,
                   1287:                    (aputype << APU_APUTYPE_SHIFT) | APU_DMA_ENABLED | 0xf);
                   1288:        }
                   1289: }
                   1290:
                   1291: int
                   1292: maestro_trigger_output(hdl, start, end, blksize, intr, arg, param)
                   1293:        void *hdl;
                   1294:        void *start, *end;
                   1295:        int blksize;
                   1296:        void (*intr)(void *);
                   1297:        void *arg;
                   1298:        struct audio_params *param;
                   1299: {
                   1300:        struct maestro_softc *sc = (struct maestro_softc *)hdl;
                   1301:
                   1302:        u_int offset = ((caddr_t)start - sc->dmabase) >> 1;
                   1303:        u_int size = ((char *)end - (char *)start) >> 1;
                   1304:        sc->play.mode |= MAESTRO_RUNNING;
                   1305:        sc->play.wpwa = APU_USE_SYSMEM | (offset >> 8);
                   1306:        DPRINTF(("maestro_trigger_output: start=%x, end=%x, blksize=%x ",
                   1307:                start, end, blksize));
                   1308:        DPRINTF(("offset = %x, size=%x\n", offset, size));
                   1309:
                   1310:        sc->play.intr = intr;
                   1311:        sc->play.intr_arg = arg;
                   1312:        sc->play.blocksize = blksize;
                   1313:        sc->play.end = offset+size;
                   1314:        sc->play.start = offset;
                   1315:        sc->play.current = sc->play.start;
                   1316:        if ((sc->play.mode & (MAESTRO_STEREO | MAESTRO_8BIT)) == MAESTRO_STEREO) {
                   1317:                sc->play.wpwa >>= 1;
                   1318:                sc->play.start >>= 1;
                   1319:                sc->play.end >>= 1;
                   1320:                sc->play.blocksize >>= 1;
                   1321:        }
                   1322:        maestro_channel_start(&sc->play);
                   1323:
                   1324:        sc->play.threshold = sc->play.start;
                   1325:        maestro_update_timer(sc);
                   1326:
                   1327:        return 0;
                   1328: }
                   1329:
                   1330: /* -----------------------------
                   1331:  * Codec interface
                   1332:  */
                   1333:
                   1334: int
                   1335: maestro_read_codec(self, regno, datap)
                   1336:        void *self;
                   1337:        u_int8_t regno;
                   1338:        u_int16_t *datap;
                   1339: {
                   1340:        struct maestro_softc *sc = (struct maestro_softc *)self;
                   1341:        int t;
                   1342:
                   1343:        /* We have to wait for a SAFE time to write addr/data */
                   1344:        for (t = 0; t < 20; t++) {
                   1345:                if ((bus_space_read_1(sc->iot, sc->ioh, PORT_CODEC_STAT)
                   1346:                    & CODEC_STAT_MASK) != CODEC_STAT_PROGLESS)
                   1347:                        break;
                   1348:                DELAY(2);       /* 20.8us / 13 */
                   1349:        }
                   1350:        if (t == 20)
                   1351:                printf("%s: maestro_read_codec() PROGLESS timed out.\n",
                   1352:                    sc->dev.dv_xname);
                   1353:                /* XXX return 1 */
                   1354:
                   1355:        bus_space_write_1(sc->iot, sc->ioh, PORT_CODEC_CMD,
                   1356:            CODEC_CMD_READ | regno);
                   1357:        DELAY(21);      /* AC97 cycle = 20.8usec */
                   1358:
                   1359:        /* Wait for data retrieve */
                   1360:        for (t = 0; t < 20; t++) {
                   1361:                if ((bus_space_read_1(sc->iot, sc->ioh, PORT_CODEC_STAT)
                   1362:                    & CODEC_STAT_MASK) == CODEC_STAT_RW_DONE)
                   1363:                        break;
                   1364:                DELAY(2);       /* 20.8us / 13 */
                   1365:        }
                   1366:        if (t == 20)
                   1367:                /* Timed out, but perform dummy read. */
                   1368:                printf("%s: maestro_read_codec() RW_DONE timed out.\n",
                   1369:                    sc->dev.dv_xname);
                   1370:
                   1371:        *datap = bus_space_read_2(sc->iot, sc->ioh, PORT_CODEC_REG);
                   1372:        return 0;
                   1373: }
                   1374:
                   1375: int
                   1376: maestro_write_codec(self, regno, data)
                   1377:        void *self;
                   1378:        u_int8_t regno;
                   1379:        u_int16_t data;
                   1380: {
                   1381:        struct maestro_softc *sc = (struct maestro_softc *)self;
                   1382:        int t;
                   1383:
                   1384:        /* We have to wait for a SAFE time to write addr/data */
                   1385:        for (t = 0; t < 20; t++) {
                   1386:                if ((bus_space_read_1(sc->iot, sc->ioh, PORT_CODEC_STAT)
                   1387:                    & CODEC_STAT_MASK) != CODEC_STAT_PROGLESS)
                   1388:                        break;
                   1389:                DELAY(2);       /* 20.8us / 13 */
                   1390:        }
                   1391:        if (t == 20) {
                   1392:                /* Timed out. Abort writing. */
                   1393:                printf("%s: maestro_write_codec() PROGLESS timed out.\n",
                   1394:                    sc->dev.dv_xname);
                   1395:                return 1;
                   1396:        }
                   1397:
                   1398:        bus_space_write_2(sc->iot, sc->ioh, PORT_CODEC_REG, data);
                   1399:        bus_space_write_1(sc->iot, sc->ioh, PORT_CODEC_CMD,
                   1400:            CODEC_CMD_WRITE | regno);
                   1401:
                   1402:        return 0;
                   1403: }
                   1404:
                   1405: int
                   1406: maestro_attach_codec(self, cif)
                   1407:        void *self;
                   1408:        struct ac97_codec_if *cif;
                   1409: {
                   1410:        struct maestro_softc *sc = (struct maestro_softc *)self;
                   1411:
                   1412:        sc->codec_if = cif;
                   1413:        return 0;
                   1414: }
                   1415:
                   1416: void
                   1417: maestro_reset_codec(self)
                   1418:        void *self UNUSED;
                   1419: {
                   1420: }
                   1421:
                   1422: void
                   1423: maestro_initcodec(self)
                   1424:        void *self;
                   1425: {
                   1426:        struct maestro_softc *sc = (struct maestro_softc *)self;
                   1427:        u_int16_t data;
                   1428:
                   1429:        if (bus_space_read_4(sc->iot, sc->ioh, PORT_RINGBUS_CTRL)
                   1430:            & RINGBUS_CTRL_ACLINK_ENABLED) {
                   1431:                bus_space_write_4(sc->iot, sc->ioh, PORT_RINGBUS_CTRL, 0);
                   1432:                DELAY(104);     /* 20.8us * (4 + 1) */
                   1433:        }
                   1434:        /* XXX - 2nd codec should be looked at. */
                   1435:        bus_space_write_4(sc->iot, sc->ioh,
                   1436:            PORT_RINGBUS_CTRL, RINGBUS_CTRL_AC97_SWRESET);
                   1437:        DELAY(2);
                   1438:        bus_space_write_4(sc->iot, sc->ioh,
                   1439:            PORT_RINGBUS_CTRL, RINGBUS_CTRL_ACLINK_ENABLED);
                   1440:        DELAY(21);
                   1441:
                   1442:        maestro_read_codec(sc, 0, &data);
                   1443:        if ((bus_space_read_1(sc->iot, sc->ioh, PORT_CODEC_STAT)
                   1444:            & CODEC_STAT_MASK) != 0) {
                   1445:                bus_space_write_4(sc->iot, sc->ioh,
                   1446:                    PORT_RINGBUS_CTRL, 0);
                   1447:                DELAY(21);
                   1448:
                   1449:                /* Try cold reset. */
                   1450:                printf("%s: resetting codec\n", sc->dev.dv_xname);
                   1451:
                   1452:                data = bus_space_read_2(sc->iot, sc->ioh, PORT_GPIO_DIR);
                   1453:                if (pci_conf_read(sc->pc, sc->pt, 0x58) & 1)
                   1454:                        data |= 0x10;
                   1455:                data |= 0x009 &
                   1456:                    ~bus_space_read_2(sc->iot, sc->ioh, PORT_GPIO_DATA);
                   1457:                bus_space_write_2(sc->iot, sc->ioh,
                   1458:                    PORT_GPIO_MASK, 0xff6);
                   1459:                bus_space_write_2(sc->iot, sc->ioh,
                   1460:                    PORT_GPIO_DIR, data | 0x009);
                   1461:                bus_space_write_2(sc->iot, sc->ioh,
                   1462:                    PORT_GPIO_DATA, 0x000);
                   1463:                DELAY(2);
                   1464:                bus_space_write_2(sc->iot, sc->ioh,
                   1465:                    PORT_GPIO_DATA, 0x001);
                   1466:                DELAY(1);
                   1467:                bus_space_write_2(sc->iot, sc->ioh,
                   1468:                    PORT_GPIO_DATA, 0x009);
                   1469:                DELAY(500000);
                   1470:                bus_space_write_2(sc->iot, sc->ioh,
                   1471:                    PORT_GPIO_DIR, data);
                   1472:                DELAY(84);      /* 20.8us * 4 */
                   1473:                bus_space_write_4(sc->iot, sc->ioh,
                   1474:                    PORT_RINGBUS_CTRL, RINGBUS_CTRL_ACLINK_ENABLED);
                   1475:                DELAY(21);
                   1476:        }
                   1477:
                   1478:        /* Check the codec to see is still busy */
                   1479:        if ((bus_space_read_1(sc->iot, sc->ioh, PORT_CODEC_STAT) &
                   1480:            CODEC_STAT_MASK) != 0) {
                   1481:                printf("%s: codec failure\n", sc->dev.dv_xname);
                   1482:        }
                   1483: }
                   1484:
                   1485: /* -----------------------------
                   1486:  * Power management interface
                   1487:  */
                   1488:
                   1489: void
                   1490: maestro_powerhook(why, self)
                   1491:        int why;
                   1492:        void *self;
                   1493: {
                   1494:        struct maestro_softc *sc = (struct maestro_softc *)self;
                   1495:
                   1496:        if (why != PWR_RESUME) {
                   1497:                /* Power down device on shutdown. */
                   1498:                DPRINTF(("maestro: power down\n"));
                   1499:                sc->suspend = why;
                   1500:                if (sc->record.mode & MAESTRO_RUNNING) {
                   1501:                        sc->record.current = wp_apu_read(sc, sc->record.num, APUREG_CURPTR);
                   1502:                        maestro_channel_stop(&sc->record);
                   1503:                }
                   1504:                if (sc->play.mode & MAESTRO_RUNNING) {
                   1505:                        sc->play.current = wp_apu_read(sc, sc->play.num, APUREG_CURPTR);
                   1506:                        maestro_channel_stop(&sc->play);
                   1507:                }
                   1508:
                   1509:                wp_stoptimer(sc);
                   1510:
                   1511:                /* Power down everything except clock. */
                   1512:                bus_space_write_2(sc->iot, sc->ioh, PORT_HOSTINT_CTRL, 0);
                   1513:                maestro_write_codec(sc, AC97_REG_POWER, 0xdf00);
                   1514:                DELAY(20);
                   1515:                bus_space_write_4(sc->iot, sc->ioh, PORT_RINGBUS_CTRL, 0);
                   1516:                DELAY(1);
                   1517:                maestro_power(sc, PPMI_D3);
                   1518:        } else {
                   1519:                /* Power up device on resume. */
                   1520:                DPRINTF(("maestro: power resume\n"));
                   1521:                if (sc->suspend == PWR_RESUME) {
                   1522:                        printf("%s: resume without suspend?\n",
                   1523:                            sc->dev.dv_xname);
                   1524:                        sc->suspend = why;
                   1525:                        return;
                   1526:                }
                   1527:                sc->suspend = why;
                   1528:                maestro_power(sc, PPMI_D0);
                   1529:                DELAY(100000);
                   1530:                maestro_init(sc);
                   1531:                /* Restore codec settings */
                   1532:                if (sc->codec_if)
                   1533:                        sc->codec_if->vtbl->restore_ports(sc->codec_if);
                   1534:                if (sc->play.mode & MAESTRO_RUNNING)
                   1535:                        maestro_channel_start(&sc->play);
                   1536:                if (sc->record.mode & MAESTRO_RUNNING)
                   1537:                        maestro_channel_start(&sc->record);
                   1538:                maestro_update_timer(sc);
                   1539:        }
                   1540: }
                   1541:
                   1542: void
                   1543: maestro_power(sc, status)
                   1544:        struct maestro_softc *sc;
                   1545:        int status;
                   1546: {
                   1547:        int data;
                   1548:
                   1549:        /* Set the power state of the device. */
                   1550:        data = pci_conf_read(sc->pc, sc->pt, CONF_PM_PTR);
                   1551:        data = pci_conf_read(sc->pc, sc->pt, data);
                   1552:        if (data == PPMI_CID)
                   1553:                pci_conf_write(sc->pc, sc->pt, data + PM_CTRL, status);
                   1554: }
                   1555:
                   1556: void
                   1557: maestro_channel_advance_dma(ch)
                   1558:        struct maestro_channel *ch;
                   1559: {
                   1560:        wpreg_t pos;
                   1561: #ifdef AUDIO_DEBUG
                   1562:        maestrointr_called++;
                   1563: #endif
                   1564:        for (;;) {
                   1565:                pos = wp_apu_read(ch->sc, ch->num, APUREG_CURPTR);
                   1566:                /* Are we still processing the current dma block ? */
                   1567:                if (pos >= ch->threshold &&
                   1568:                    pos < ch->threshold + ch->blocksize/2)
                   1569:                        break;
                   1570:                ch->threshold += ch->blocksize/2;
                   1571:                if (ch->threshold >= ch->end)
                   1572:                        ch->threshold = ch->start;
                   1573:                (*ch->intr)(ch->intr_arg);
                   1574: #ifdef AUDIO_DEBUG
                   1575:                maestrodma_effective++;
                   1576: #endif
                   1577:        }
                   1578:
                   1579: #ifdef AUDIO_DEBUG
                   1580:        if (maestrodebug && maestrointr_called % 64 == 0)
                   1581:                printf("maestro: dma advanced %lu for %lu calls\n",
                   1582:                        maestrodma_effective, maestrointr_called);
                   1583: #endif
                   1584: }
                   1585:
                   1586: /* Some maestro makes sometimes get desynchronized in stereo mode. */
                   1587: void
                   1588: maestro_channel_suppress_jitter(ch)
                   1589:        struct maestro_channel *ch;
                   1590: {
                   1591:        int cp, diff;
                   1592:
                   1593:        /* Verify that both channels are not too far off. */
                   1594:        cp = wp_apu_read(ch->sc, ch->num, APUREG_CURPTR);
                   1595:        diff = wp_apu_read(ch->sc, ch->num+1, APUREG_CURPTR) - cp;
                   1596:        if (diff > 4 || diff < -4)
                   1597:                /* Otherwise, directly resynch the 2nd channel. */
                   1598:                bus_space_write_2(ch->sc->iot, ch->sc->ioh,
                   1599:                    PORT_DSP_DATA, cp);
                   1600: }
                   1601:
                   1602: /* -----------------------------
                   1603:  * Interrupt handler interface
                   1604:  */
                   1605: int
                   1606: maestro_intr(arg)
                   1607:        void *arg;
                   1608: {
                   1609:        struct maestro_softc *sc = (struct maestro_softc *)arg;
                   1610:        u_int16_t status;
                   1611:
                   1612:        status = bus_space_read_1(sc->iot, sc->ioh, PORT_HOSTINT_STAT);
                   1613:        if (status == 0)
                   1614:                return 0;       /* Not for us? */
                   1615:
                   1616:        /* Acknowledge all. */
                   1617:        bus_space_write_2(sc->iot, sc->ioh, PORT_INT_STAT, 1);
                   1618:        bus_space_write_1(sc->iot, sc->ioh, PORT_HOSTINT_STAT, status);
                   1619:
                   1620:        /* Hardware volume support */
                   1621:        if (status & HOSTINT_STAT_HWVOL && sc->codec_if != NULL) {
                   1622:                int n, i, delta, v;
                   1623:                mixer_ctrl_t hwvol;
                   1624:
                   1625:                n = bus_space_read_1(sc->iot, sc->ioh, PORT_HWVOL_MASTER);
                   1626:                /* Special case: Mute key */
                   1627:                if (n & 0x11) {
                   1628:                        hwvol.type = AUDIO_MIXER_ENUM;
                   1629:                        hwvol.dev =
                   1630:                            sc->codec_if->vtbl->get_portnum_by_name(sc->codec_if,
                   1631:                                AudioCoutputs, AudioNmaster, AudioNmute);
                   1632:                        sc->codec_if->vtbl->mixer_get_port(sc->codec_if, &hwvol);
                   1633:                        hwvol.un.ord = !hwvol.un.ord;
                   1634:                } else {
                   1635:                        hwvol.type = AUDIO_MIXER_VALUE;
                   1636:                        hwvol.un.value.num_channels = 2;
                   1637:                        hwvol.dev =
                   1638:                            sc->codec_if->vtbl->get_portnum_by_name(
                   1639:                                sc->codec_if, AudioCoutputs, AudioNmaster,
                   1640:                                    NULL);
                   1641:                        sc->codec_if->vtbl->mixer_get_port(sc->codec_if, &hwvol);
                   1642:                        /* XXX AC'97 yields five bits for master volume. */
                   1643:                        delta = (n - MIDDLE_VOLUME)/STEP_VOLUME * 8;
                   1644:                        for (i = 0; i < hwvol.un.value.num_channels; i++) {
                   1645:                                v = ((int)hwvol.un.value.level[i]) + delta;
                   1646:                                if (v < 0)
                   1647:                                        v = 0;
                   1648:                                else if (v > 255)
                   1649:                                        v = 255;
                   1650:                                hwvol.un.value.level[i] = v;
                   1651:                        }
                   1652:                }
                   1653:                sc->codec_if->vtbl->mixer_set_port(sc->codec_if, &hwvol);
                   1654:                /* Reset to compute next diffs */
                   1655:                bus_space_write_1(sc->iot, sc->ioh, PORT_HWVOL_MASTER,
                   1656:                    MIDDLE_VOLUME);
                   1657:        }
                   1658:
                   1659:        if (sc->play.mode & MAESTRO_RUNNING) {
                   1660:                maestro_channel_advance_dma(&sc->play);
                   1661:                if (sc->play.mode & MAESTRO_STEREO)
                   1662:                        maestro_channel_suppress_jitter(&sc->play);
                   1663:        }
                   1664:
                   1665:        if (sc->record.mode & MAESTRO_RUNNING)
                   1666:                maestro_channel_advance_dma(&sc->record);
                   1667:
                   1668:        return 1;
                   1669: }
                   1670:
                   1671: /* -----------------------------
                   1672:  * Hardware interface
                   1673:  */
                   1674:
                   1675: /* Codec/Ringbus */
                   1676:
                   1677: void
                   1678: ringbus_setdest(struct maestro_softc *sc, int src, int dest)
                   1679: {
                   1680:        u_int32_t       data;
                   1681:
                   1682:        data = bus_space_read_4(sc->iot, sc->ioh, PORT_RINGBUS_CTRL);
                   1683:        data &= ~(0xfU << src);
                   1684:        data |= (0xfU & dest) << src;
                   1685:        bus_space_write_4(sc->iot, sc->ioh, PORT_RINGBUS_CTRL, data);
                   1686: }
                   1687:
                   1688: /* Wave Processor */
                   1689:
                   1690: wpreg_t
                   1691: wp_reg_read(struct maestro_softc *sc, int reg)
                   1692: {
                   1693:        bus_space_write_2(sc->iot, sc->ioh, PORT_DSP_INDEX, reg);
                   1694:        return bus_space_read_2(sc->iot, sc->ioh, PORT_DSP_DATA);
                   1695: }
                   1696:
                   1697: void
                   1698: wp_reg_write(struct maestro_softc *sc, int reg, wpreg_t data)
                   1699: {
                   1700:        bus_space_write_2(sc->iot, sc->ioh, PORT_DSP_INDEX, reg);
                   1701:        bus_space_write_2(sc->iot, sc->ioh, PORT_DSP_DATA, data);
                   1702: }
                   1703:
                   1704: static void
                   1705: apu_setindex(struct maestro_softc *sc, int reg)
                   1706: {
                   1707:        int t;
                   1708:
                   1709:        wp_reg_write(sc, WPREG_CRAM_PTR, reg);
                   1710:        /* Sometimes WP fails to set apu register index. */
                   1711:        for (t = 0; t < 1000; t++) {
                   1712:                if (bus_space_read_2(sc->iot, sc->ioh,
                   1713:                    PORT_DSP_DATA) == reg)
                   1714:                        break;
                   1715:                bus_space_write_2(sc->iot, sc->ioh, PORT_DSP_DATA, reg);
                   1716:        }
                   1717:        if (t == 1000)
                   1718:                printf("%s: apu_setindex() timeout\n", sc->dev.dv_xname);
                   1719: }
                   1720:
                   1721: wpreg_t
                   1722: wp_apu_read(struct maestro_softc *sc, int ch, int reg)
                   1723: {
                   1724:        wpreg_t ret;
                   1725:
                   1726:        apu_setindex(sc, ((unsigned)ch << 4) + reg);
                   1727:        ret = wp_reg_read(sc, WPREG_DATA_PORT);
                   1728:        return ret;
                   1729: }
                   1730:
                   1731: void
                   1732: wp_apu_write(struct maestro_softc *sc, int ch, int reg, wpreg_t data)
                   1733: {
                   1734:        int t;
                   1735:
                   1736:        apu_setindex(sc, ((unsigned)ch << 4) + reg);
                   1737:        wp_reg_write(sc, WPREG_DATA_PORT, data);
                   1738:        for (t = 0; t < 1000; t++) {
                   1739:                if (bus_space_read_2(sc->iot, sc->ioh, PORT_DSP_DATA) == data)
                   1740:                        break;
                   1741:                bus_space_write_2(sc->iot, sc->ioh, PORT_DSP_DATA, data);
                   1742:        }
                   1743:        if (t == 1000)
                   1744:                printf("%s: wp_apu_write() timeout\n", sc->dev.dv_xname);
                   1745: }
                   1746:
                   1747: void
                   1748: wp_settimer(struct maestro_softc *sc, u_int freq)
                   1749: {
                   1750:        u_int clock = 48000 << 2;
                   1751:        u_int prescale = 0, divide = (freq != 0) ? (clock / freq) : ~0;
                   1752:
                   1753:        if (divide < 4)
                   1754:                divide = 4;
                   1755:        else if (divide > 32 << 8)
                   1756:                divide = 32 << 8;
                   1757:
                   1758:        for (; divide > 32 << 1; divide >>= 1)
                   1759:                prescale++;
                   1760:        divide = (divide + 1) >> 1;
                   1761:
                   1762:        for (; prescale < 7 && divide > 2 && !(divide & 1); divide >>= 1)
                   1763:                prescale++;
                   1764:
                   1765:        wp_reg_write(sc, WPREG_TIMER_ENABLE, 0);
                   1766:        wp_reg_write(sc, WPREG_TIMER_FREQ,
                   1767:            (prescale << WP_TIMER_FREQ_PRESCALE_SHIFT) | (divide - 1));
                   1768:        wp_reg_write(sc, WPREG_TIMER_ENABLE, 1);
                   1769: }
                   1770:
                   1771: void
                   1772: wp_starttimer(struct maestro_softc *sc)
                   1773: {
                   1774:        wp_reg_write(sc, WPREG_TIMER_START, 1);
                   1775: }
                   1776:
                   1777: void
                   1778: wp_stoptimer(struct maestro_softc *sc)
                   1779: {
                   1780:        wp_reg_write(sc, WPREG_TIMER_START, 0);
                   1781:        bus_space_write_2(sc->iot, sc->ioh, PORT_INT_STAT, 1);
                   1782: }
                   1783:
                   1784: /* WaveCache */
                   1785:
                   1786: wcreg_t
                   1787: wc_reg_read(struct maestro_softc *sc, int reg)
                   1788: {
                   1789:        bus_space_write_2(sc->iot, sc->ioh, PORT_WAVCACHE_INDEX, reg);
                   1790:        return bus_space_read_2(sc->iot, sc->ioh, PORT_WAVCACHE_DATA);
                   1791: }
                   1792:
                   1793: void
                   1794: wc_reg_write(struct maestro_softc *sc, int reg, wcreg_t data)
                   1795: {
                   1796:        bus_space_write_2(sc->iot, sc->ioh, PORT_WAVCACHE_INDEX, reg);
                   1797:        bus_space_write_2(sc->iot, sc->ioh, PORT_WAVCACHE_DATA, data);
                   1798: }
                   1799:
                   1800: u_int16_t
                   1801: wc_ctrl_read(struct maestro_softc *sc, int ch)
                   1802: {
                   1803:        return wc_reg_read(sc, ch << 3);
                   1804: }
                   1805:
                   1806: void
                   1807: wc_ctrl_write(struct maestro_softc *sc, int ch, wcreg_t data)
                   1808: {
                   1809:        wc_reg_write(sc, ch << 3, data);
                   1810: }
                   1811:
                   1812: /* -----------------------------
                   1813:  * Simple zone allocator.
                   1814:  * (All memory allocated in advance)
                   1815:  */
                   1816:
                   1817: salloc_t
                   1818: salloc_new(addr, size, nzones)
                   1819:        caddr_t addr;
                   1820:        size_t size;
                   1821:        int nzones;
                   1822: {
                   1823:        struct salloc_pool *pool;
                   1824:        struct salloc_zone *space;
                   1825:        int i;
                   1826:
                   1827:        MALLOC(pool, salloc_t, sizeof *pool + nzones * sizeof pool->zones[0],
                   1828:            M_TEMP, M_NOWAIT);
                   1829:        if (pool == NULL)
                   1830:                return NULL;
                   1831:        SLIST_INIT(&pool->free);
                   1832:        SLIST_INIT(&pool->used);
                   1833:        SLIST_INIT(&pool->spare);
                   1834:        /* Espie says the following line is obvious */
                   1835:        pool->zones = (struct salloc_zone *)(pool + 1);
                   1836:        for (i = 1; i < nzones; i++)
                   1837:                SLIST_INSERT_HEAD(&pool->spare, &pool->zones[i], link);
                   1838:        space = &pool->zones[0];
                   1839:        space->addr = addr;
                   1840:        space->size = size;
                   1841:        SLIST_INSERT_HEAD(&pool->free, space, link);
                   1842:        return pool;
                   1843: }
                   1844:
                   1845: void
                   1846: salloc_destroy(pool)
                   1847:        salloc_t pool;
                   1848: {
                   1849:        FREE(pool, M_TEMP);
                   1850: }
                   1851:
                   1852: void
                   1853: salloc_insert(pool, head, zone, merge)
                   1854:        salloc_t pool;
                   1855:        struct salloc_head *head;
                   1856:        struct salloc_zone *zone;
                   1857:        int merge;
                   1858: {
                   1859:        struct salloc_zone *prev, *next;
                   1860:
                   1861:        /*
                   1862:         * Insert a zone into an ordered list of zones, possibly
                   1863:         * merging adjacent zones.
                   1864:         */
                   1865:        prev = NULL;
                   1866:        SLIST_FOREACH(next, head, link) {
                   1867:                if (next->addr > zone->addr)
                   1868:                        break;
                   1869:                prev = next;
                   1870:        }
                   1871:
                   1872:        if (merge && prev && prev->addr + prev->size == zone->addr) {
                   1873:                prev->size += zone->size;
                   1874:                SLIST_INSERT_HEAD(&pool->spare, zone, link);
                   1875:                zone = prev;
                   1876:        } else if (prev)
                   1877:                SLIST_INSERT_AFTER(prev, zone, link);
                   1878:        else
                   1879:                SLIST_INSERT_HEAD(head, zone, link);
                   1880:        if (merge && next && zone->addr + zone->size == next->addr) {
                   1881:                zone->size += next->size;
                   1882:                SLIST_REMOVE(head, next, salloc_zone, link);
                   1883:                SLIST_INSERT_HEAD(&pool->spare, next, link);
                   1884:        }
                   1885: }
                   1886:
                   1887: caddr_t
                   1888: salloc_alloc(pool, size)
                   1889:        salloc_t pool;
                   1890:        size_t size;
                   1891: {
                   1892:        struct salloc_zone *zone, *uzone;
                   1893:
                   1894:        SLIST_FOREACH(zone, &pool->free, link)
                   1895:                if (zone->size >= size)
                   1896:                        break;
                   1897:        if (zone == SLIST_END(&pool->free))
                   1898:                return NULL;
                   1899:        if (zone->size == size) {
                   1900:                SLIST_REMOVE(&pool->free, zone, salloc_zone, link);
                   1901:                uzone = zone;
                   1902:        } else {
                   1903:                uzone = SLIST_FIRST(&pool->spare);
                   1904:                if (uzone == NULL)
                   1905:                        return NULL;            /* XXX */
                   1906:                SLIST_REMOVE_HEAD(&pool->spare, link);
                   1907:                uzone->size = size;
                   1908:                uzone->addr = zone->addr;
                   1909:                zone->size -= size;
                   1910:                zone->addr += size;
                   1911:        }
                   1912:        salloc_insert(pool, &pool->used, uzone, 0);
                   1913:        return uzone->addr;
                   1914: }
                   1915:
                   1916: void
                   1917: salloc_free(pool, addr)
                   1918:        salloc_t pool;
                   1919:        caddr_t addr;
                   1920: {
                   1921:        struct salloc_zone *zone;
                   1922:
                   1923:        SLIST_FOREACH(zone, &pool->used, link)
                   1924:                if (zone->addr == addr)
                   1925:                        break;
                   1926: #ifdef DIAGNOSTIC
                   1927:        if (zone == SLIST_END(&pool->used))
                   1928:                panic("salloc_free: freeing unallocated memory");
                   1929: #endif
                   1930:        SLIST_REMOVE(&pool->used, zone, salloc_zone, link);
                   1931:        salloc_insert(pool, &pool->free, zone, 1);
                   1932: }

CVSweb