root/dev/pci/maestro.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. salloc_t
  2. maestro_get_flags
  3. maestro_match
  4. maestro_attach
  5. maestro_init
  6. maestro_round_blocksize
  7. maestro_malloc
  8. maestro_free
  9. maestro_mappage
  10. maestro_get_props
  11. maestro_getdev
  12. maestro_set_port
  13. maestro_get_port
  14. maestro_query_devinfo
  15. maestro_query_encoding
  16. maestro_set_speed
  17. maestro_calc_timer_freq
  18. maestro_update_timer
  19. maestro_set_params
  20. maestro_open
  21. maestro_close
  22. maestro_channel_stop
  23. maestro_halt_input
  24. maestro_halt_output
  25. maestro_trigger_input
  26. maestro_channel_start
  27. maestro_trigger_output
  28. maestro_read_codec
  29. maestro_write_codec
  30. maestro_attach_codec
  31. maestro_reset_codec
  32. maestro_initcodec
  33. maestro_powerhook
  34. maestro_power
  35. maestro_channel_advance_dma
  36. maestro_channel_suppress_jitter
  37. maestro_intr
  38. ringbus_setdest
  39. wp_reg_read
  40. wp_reg_write
  41. apu_setindex
  42. wp_apu_read
  43. wp_apu_write
  44. wp_settimer
  45. wp_starttimer
  46. wp_stoptimer
  47. wc_reg_read
  48. wc_reg_write
  49. wc_ctrl_read
  50. wc_ctrl_write
  51. salloc_new
  52. salloc_destroy
  53. salloc_insert
  54. salloc_alloc
  55. salloc_free

    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 }

/* [<][>][^][v][top][bottom][index][help] */