The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/pci/esa.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /* $NetBSD: esa.c,v 1.22.2.1 2004/09/22 20:58:34 jmc Exp $ */
    2 
    3 /*
    4  * Copyright (c) 2001, 2002 Jared D. McNeill <jmcneill@invisible.ca>
    5  * All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. The name of the author may not be used to endorse or promote products
   13  *    derived from this software without specific prior written permission.
   14  *
   15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   17  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   18  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   19  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
   20  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
   21  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
   22  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   23  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   25  * SUCH DAMAGE.
   26  */
   27 
   28 /*
   29  * ESS Allegro-1 / Maestro3 Audio Driver
   30  * 
   31  * Based on the FreeBSD maestro3 driver and the NetBSD eap driver.
   32  * Original driver by Don Kim.
   33  *
   34  * The list management code could possibly be written better, but what
   35  * we have right now does the job nicely. Thanks to Zach Brown <zab@zabbo.net>
   36  * and Andrew MacDonald <amac@epsilon.yi.org> for helping me debug the
   37  * problems with the original list management code present in the Linux
   38  * driver.
   39  */
   40 
   41 #include <sys/cdefs.h>
   42 __KERNEL_RCSID(0, "$NetBSD: esa.c,v 1.22.2.1 2004/09/22 20:58:34 jmc Exp $");
   43 
   44 #include <sys/types.h>
   45 #include <sys/errno.h>
   46 #include <sys/null.h>
   47 #include <sys/param.h>
   48 #include <sys/systm.h>
   49 #include <sys/malloc.h>
   50 #include <sys/device.h>
   51 #include <sys/conf.h>
   52 #include <sys/exec.h>
   53 #include <sys/select.h>
   54 #include <sys/audioio.h>
   55 
   56 #include <machine/bus.h>
   57 #include <machine/intr.h>
   58 
   59 #include <dev/pci/pcidevs.h>
   60 #include <dev/pci/pcivar.h>
   61 
   62 #include <dev/audio_if.h>
   63 #include <dev/mulaw.h>
   64 #include <dev/auconv.h>
   65 #include <dev/ic/ac97var.h>
   66 #include <dev/ic/ac97reg.h>
   67 
   68 #include <dev/pci/esareg.h>
   69 #include <dev/pci/esadsp.h>
   70 #include <dev/pci/esavar.h>
   71 
   72 #define PCI_CBIO        0x10
   73 
   74 #define ESA_DAC_DATA    0x1100
   75 
   76 enum {
   77         ESS_ALLEGRO1,
   78         ESS_MAESTRO3
   79 };
   80 
   81 static struct esa_card_type {
   82         u_int16_t pci_vendor_id;
   83         u_int16_t pci_product_id;
   84         int type;
   85         int delay1, delay2;
   86 } esa_card_types[] = {
   87         { PCI_VENDOR_ESSTECH, PCI_PRODUCT_ESSTECH_ALLEGRO1,
   88           ESS_ALLEGRO1, 50, 800 },
   89         { PCI_VENDOR_ESSTECH, PCI_PRODUCT_ESSTECH_MAESTRO3,
   90           ESS_MAESTRO3, 20, 500 },
   91         { PCI_VENDOR_ESSTECH, PCI_PRODUCT_ESSTECH_MAESTRO3_2,
   92           ESS_MAESTRO3, 20, 500 },
   93         { 0, 0, 0, 0, 0 }
   94 };
   95 
   96 struct audio_device esa_device = {
   97         "ESS Allegro",
   98         "",
   99         "esa"
  100 };
  101 
  102 int             esa_match(struct device *, struct cfdata *, void *);
  103 void            esa_attach(struct device *, struct device *, void *);
  104 int             esa_detach(struct device *, int);
  105 
  106 /* audio(9) functions */
  107 int             esa_open(void *, int);
  108 void            esa_close(void *);
  109 int             esa_query_encoding(void *, struct audio_encoding *);
  110 int             esa_set_params(void *, int, int, struct audio_params *,
  111                                struct audio_params *);
  112 int             esa_round_blocksize(void *, int);
  113 int             esa_commit_settings(void *);
  114 int             esa_halt_output(void *);
  115 int             esa_halt_input(void *);
  116 int             esa_set_port(void *, mixer_ctrl_t *);
  117 int             esa_get_port(void *, mixer_ctrl_t *);
  118 int             esa_query_devinfo(void *, mixer_devinfo_t *);
  119 void *          esa_malloc(void *, int, size_t, struct malloc_type *, int);
  120 void            esa_free(void *, void *, struct malloc_type *);
  121 int             esa_getdev(void *, struct audio_device *);
  122 size_t          esa_round_buffersize(void *, int, size_t);
  123 int             esa_get_props(void *);
  124 int             esa_trigger_output(void *, void *, void *, int,
  125                                    void (*)(void *), void *,
  126                                    struct audio_params *);
  127 int             esa_trigger_input(void *, void *, void *, int,
  128                                   void (*)(void *), void *,
  129                                   struct audio_params *);
  130 
  131 int             esa_intr(void *);
  132 int             esa_allocmem(struct esa_softc *, size_t, size_t,
  133                              struct esa_dma *);
  134 int             esa_freemem(struct esa_softc *, struct esa_dma *);
  135 paddr_t         esa_mappage(void *addr, void *mem, off_t off, int prot);
  136 
  137 /* Supporting subroutines */
  138 u_int16_t       esa_read_assp(struct esa_softc *, u_int16_t, u_int16_t);
  139 void            esa_write_assp(struct esa_softc *, u_int16_t, u_int16_t,
  140                                u_int16_t);
  141 int             esa_init_codec(struct esa_softc *);
  142 int             esa_attach_codec(void *, struct ac97_codec_if *);
  143 int             esa_read_codec(void *, u_int8_t, u_int16_t *);
  144 int             esa_write_codec(void *, u_int8_t, u_int16_t);
  145 int             esa_reset_codec(void *);
  146 enum ac97_host_flags    esa_flags_codec(void *);
  147 int             esa_wait(struct esa_softc *);
  148 int             esa_init(struct esa_softc *);
  149 void            esa_config(struct esa_softc *);
  150 u_int8_t        esa_assp_halt(struct esa_softc *);
  151 void            esa_codec_reset(struct esa_softc *);
  152 int             esa_amp_enable(struct esa_softc *);
  153 void            esa_enable_interrupts(struct esa_softc *);
  154 u_int32_t       esa_get_pointer(struct esa_softc *, struct esa_channel *);
  155 
  156 /* list management */
  157 int             esa_add_list(struct esa_voice *, struct esa_list *, u_int16_t,
  158                              int);
  159 void            esa_remove_list(struct esa_voice *, struct esa_list *, int);
  160 
  161 /* power management */
  162 int             esa_power(struct esa_softc *, int);
  163 void            esa_powerhook(int, void *);
  164 int             esa_suspend(struct esa_softc *);
  165 int             esa_resume(struct esa_softc *);
  166 
  167 static audio_encoding_t esa_encoding[] = {
  168         { 0, AudioEulinear, AUDIO_ENCODING_ULINEAR, 8, 0 },
  169         { 1, AudioEmulaw, AUDIO_ENCODING_ULAW, 8,
  170                 AUDIO_ENCODINGFLAG_EMULATED },
  171         { 2, AudioEalaw, AUDIO_ENCODING_ALAW, 8, AUDIO_ENCODINGFLAG_EMULATED },
  172         { 3, AudioEslinear, AUDIO_ENCODING_SLINEAR, 8,
  173                 AUDIO_ENCODINGFLAG_EMULATED }, /* XXX: Are you sure? */
  174         { 4, AudioEslinear_le, AUDIO_ENCODING_SLINEAR_LE, 16, 0 },
  175         { 5, AudioEulinear_le, AUDIO_ENCODING_ULINEAR_LE, 16,
  176                 AUDIO_ENCODINGFLAG_EMULATED },
  177         { 6, AudioEslinear_be, AUDIO_ENCODING_SLINEAR_BE, 16,
  178                 AUDIO_ENCODINGFLAG_EMULATED },
  179         { 7, AudioEulinear_be, AUDIO_ENCODING_ULINEAR_BE, 16,
  180                 AUDIO_ENCODINGFLAG_EMULATED }
  181 };
  182 
  183 #define ESA_NENCODINGS 8
  184 
  185 struct audio_hw_if esa_hw_if = {
  186         esa_open,
  187         esa_close,
  188         NULL,                   /* drain */
  189         esa_query_encoding,
  190         esa_set_params,
  191         esa_round_blocksize,
  192         esa_commit_settings,
  193         NULL,                   /* init_output */
  194         NULL,                   /* init_input */
  195         NULL,                   /* start_output */
  196         NULL,                   /* start_input */
  197         esa_halt_output,
  198         esa_halt_input,
  199         NULL,                   /* speaker_ctl */
  200         esa_getdev,
  201         NULL,                   /* getfd */
  202         esa_set_port,
  203         esa_get_port,
  204         esa_query_devinfo,
  205         esa_malloc,
  206         esa_free,
  207         esa_round_buffersize,
  208         esa_mappage,
  209         esa_get_props,
  210         esa_trigger_output,
  211         esa_trigger_input
  212 };
  213 
  214 CFATTACH_DECL(esa, sizeof(struct esa_softc), esa_match, esa_attach,
  215     esa_detach, NULL);
  216 
  217 /*
  218  * audio(9) functions
  219  */
  220 
  221 int
  222 esa_open(void *hdl, int flags)
  223 {
  224 
  225         return (0);
  226 }
  227 
  228 void
  229 esa_close(void *hdl)
  230 {
  231 
  232         return;
  233 }
  234 
  235 int
  236 esa_query_encoding(void *hdl, struct audio_encoding *ae)
  237 {
  238 
  239         if (ae->index < 0 || ae->index >= ESA_NENCODINGS)
  240                 return (EINVAL);
  241         *ae = esa_encoding[ae->index];
  242 
  243         return (0);
  244 }
  245 
  246 int
  247 esa_set_params(void *hdl, int setmode, int usemode, struct audio_params *play,
  248                struct audio_params *rec)
  249 {
  250         struct esa_voice *vc = hdl;
  251         //struct esa_softc *sc = (struct esa_softc *)vc->parent;
  252         struct esa_channel *ch;
  253         struct audio_params *p;
  254         int mode;
  255 
  256         for (mode = AUMODE_RECORD; mode != -1;
  257              mode = (mode == AUMODE_RECORD) ? AUMODE_PLAY : -1) {
  258                 if ((setmode & mode) == 0)
  259                         continue;
  260 
  261                 switch (mode) {
  262                 case AUMODE_PLAY:
  263                         p = play;
  264                         ch = &vc->play;
  265                         break;
  266                 case AUMODE_RECORD:
  267                         p = rec;
  268                         ch = &vc->rec;
  269                         break;
  270                 default:
  271                         return EINVAL;
  272                 }
  273 
  274                 if (p->sample_rate < ESA_MINRATE ||
  275                     p->sample_rate > ESA_MAXRATE ||
  276                     (p->precision != 8 && p->precision != 16) ||
  277                     (p->channels < 1 && p->channels > 2))
  278                         return (EINVAL);
  279 
  280                 p->factor = 1;
  281                 p->sw_code = 0;
  282 
  283                 switch(p->encoding) {
  284                 case AUDIO_ENCODING_SLINEAR_BE:
  285                         if (p->precision == 16)
  286                                 p->sw_code = swap_bytes;
  287                         else
  288                                 p->sw_code = change_sign8;
  289                         break;
  290                 case AUDIO_ENCODING_SLINEAR_LE:
  291                         if (p->precision != 16)
  292                                 p->sw_code = change_sign8;
  293                         break;
  294                 case AUDIO_ENCODING_ULINEAR_BE:
  295                         if (p->precision == 16) {
  296                                 if (mode == AUMODE_PLAY)
  297                                         p->sw_code =
  298                                             swap_bytes_change_sign16_le;
  299                                 else
  300                                         p->sw_code =
  301                                             change_sign16_swap_bytes_le;
  302                         }
  303                         break;
  304                 case AUDIO_ENCODING_ULINEAR_LE:
  305                         if (p->precision == 16)
  306                                 p->sw_code = change_sign16_le;
  307                         break;
  308                 case AUDIO_ENCODING_ULAW:
  309                         if (mode == AUMODE_PLAY) {
  310                                 p->factor = 2;
  311                                 p->sw_code = mulaw_to_slinear16_le;
  312                         } else
  313                                 p->sw_code = ulinear8_to_mulaw;
  314                         break;
  315                 case AUDIO_ENCODING_ALAW:
  316                         if (mode == AUMODE_PLAY) {
  317                                 p->factor = 2;
  318                                 p->sw_code = alaw_to_slinear16_le;
  319                         } else
  320                                 p->sw_code = ulinear8_to_alaw;
  321                         break;
  322                 default:
  323                         return (EINVAL);
  324                 }
  325 
  326                 ch->mode = *p;
  327         }
  328 
  329         return (0);
  330 }
  331 
  332 int
  333 esa_commit_settings(void *hdl)
  334 {
  335         struct esa_voice *vc = hdl;
  336         struct esa_softc *sc = (struct esa_softc *)vc->parent;
  337         struct audio_params *p = &vc->play.mode;
  338         struct audio_params *r = &vc->rec.mode;
  339         u_int32_t data;
  340         u_int32_t freq;
  341         int data_bytes = (((ESA_MINISRC_TMP_BUFFER_SIZE & ~1) +
  342                            (ESA_MINISRC_IN_BUFFER_SIZE & ~1) +
  343                            (ESA_MINISRC_OUT_BUFFER_SIZE & ~1) + 4) + 255)
  344                            &~ 255;
  345 
  346         /* playback */
  347         vc->play.data_offset = ESA_DAC_DATA + (data_bytes * vc->index);
  348         if (p->channels == 1)
  349                 data = 1;
  350         else
  351                 data = 0;
  352         esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA,
  353                        vc->play.data_offset + ESA_SRC3_MODE_OFFSET,
  354                        data);
  355         if (p->precision * p->factor == 8)
  356                 data = 1;
  357         else
  358                 data = 0;
  359         esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA,
  360                        vc->play.data_offset + ESA_SRC3_WORD_LENGTH_OFFSET,
  361                        data);
  362         if ((freq = ((p->sample_rate << 15) + 24000) / 48000) != 0) {
  363                 freq--;
  364         }
  365         esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA,
  366                        vc->play.data_offset + ESA_CDATA_FREQUENCY, freq);
  367 
  368         /* recording */
  369         vc->rec.data_offset = ESA_DAC_DATA + (data_bytes * vc->index) +
  370                               (data_bytes / 2);
  371         if (r->channels == 1)
  372                 data = 1;
  373         else
  374                 data = 0;
  375         esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA,
  376                        vc->rec.data_offset + ESA_SRC3_MODE_OFFSET,
  377                        data);
  378         if (r->precision * r->factor == 8)
  379                 data = 1;
  380         else
  381                 data = 0;
  382         esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA,
  383                        vc->rec.data_offset + ESA_SRC3_WORD_LENGTH_OFFSET,
  384                        data);
  385         if ((freq = ((r->sample_rate << 15) + 24000) / 48000) != 0) {
  386                 freq--;
  387         }
  388         esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA,
  389                        vc->rec.data_offset + ESA_CDATA_FREQUENCY, freq);
  390 
  391         return (0);
  392 };
  393 
  394 int
  395 esa_round_blocksize(void *hdl, int bs)
  396 {
  397         struct esa_voice *vc = hdl;
  398 
  399         /*
  400          * Surely there has to be a better solution...
  401          */
  402         vc->play.blksize = vc->rec.blksize = 4096;
  403 
  404         return (vc->play.blksize);
  405 }
  406 
  407 int
  408 esa_halt_output(void *hdl)
  409 {
  410         struct esa_voice *vc = hdl;
  411         struct esa_softc *sc = (struct esa_softc *)vc->parent;
  412         bus_space_tag_t iot = sc->sc_iot;
  413         bus_space_handle_t ioh = sc->sc_ioh;
  414         u_int16_t data;
  415 
  416         if (vc->play.active == 0)
  417                 return (0);
  418 
  419         vc->play.active = 0;
  420 
  421         esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA,
  422                        ESA_CDATA_INSTANCE_READY + vc->play.data_offset, 0);
  423 
  424         sc->sc_ntimers--;
  425         if (sc->sc_ntimers == 0) {
  426                 esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA,
  427                                ESA_KDATA_TIMER_COUNT_RELOAD, 0);
  428                 esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA,
  429                                ESA_KDATA_TIMER_COUNT_CURRENT, 0);
  430                 data = bus_space_read_2(iot, ioh, ESA_HOST_INT_CTRL);
  431                 bus_space_write_2(iot, ioh, ESA_HOST_INT_CTRL,
  432                     data & ~ESA_CLKRUN_GEN_ENABLE);
  433         }
  434 
  435         esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA,
  436                        ESA_KDATA_MIXER_TASK_NUMBER,
  437                        sc->mixer_list.indexmap[vc->index]);
  438         /* remove ourselves from the packed lists */
  439         esa_remove_list(vc, &sc->mixer_list, vc->index);
  440         esa_remove_list(vc, &sc->dma_list, vc->index);
  441         esa_remove_list(vc, &sc->msrc_list, vc->index);
  442 
  443         return (0);
  444 }
  445 
  446 int
  447 esa_halt_input(void *hdl)
  448 {
  449         struct esa_voice *vc = hdl;
  450         struct esa_softc *sc = (struct esa_softc *)vc->parent;
  451         bus_space_tag_t iot = sc->sc_iot;
  452         bus_space_handle_t ioh = sc->sc_ioh;
  453         u_int32_t data;
  454         
  455         if (vc->rec.active == 0)
  456                 return (0);
  457                 
  458         vc->rec.active = 0;
  459         
  460         sc->sc_ntimers--;
  461         if (sc->sc_ntimers == 0) {
  462                 esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA,
  463                                ESA_KDATA_TIMER_COUNT_RELOAD, 0);
  464                 esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA,
  465                                ESA_KDATA_TIMER_COUNT_CURRENT, 0);
  466                 data = bus_space_read_2(iot, ioh, ESA_HOST_INT_CTRL);
  467                 bus_space_write_2(iot, ioh, ESA_HOST_INT_CTRL,
  468                                   data & ~ESA_CLKRUN_GEN_ENABLE);
  469         }
  470 
  471         esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA, vc->rec.data_offset +
  472                        ESA_CDATA_INSTANCE_READY, 0);
  473         esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA, ESA_KDATA_ADC1_REQUEST,
  474                        0);
  475 
  476         /* remove ourselves from the packed lists */
  477         esa_remove_list(vc, &sc->adc1_list, vc->index + ESA_NUM_VOICES);
  478         esa_remove_list(vc, &sc->dma_list, vc->index + ESA_NUM_VOICES);
  479         esa_remove_list(vc, &sc->msrc_list, vc->index + ESA_NUM_VOICES);
  480 
  481         return (0);
  482 }
  483 
  484 void *
  485 esa_malloc(void *hdl, int direction, size_t size, struct malloc_type *type,
  486     int flags)
  487 {
  488         struct esa_voice *vc = hdl;
  489         struct esa_softc *sc = (struct esa_softc *)vc->parent;
  490         struct esa_dma *p;
  491         int error;
  492 
  493         p = malloc(sizeof(*p), type, flags);
  494         if (!p)
  495                 return (0);
  496         error = esa_allocmem(sc, size, 16, p);
  497         if (error) {
  498                 free(p, type);
  499                 printf("%s: esa_malloc: not enough memory\n",
  500                     sc->sc_dev.dv_xname);
  501                 return (0);
  502         }
  503         p->next = vc->dma;
  504         vc->dma = p;
  505 
  506         return (KERNADDR(p));
  507 }
  508 
  509 void
  510 esa_free(void *hdl, void *addr, struct malloc_type *type)
  511 {
  512         struct esa_voice *vc = hdl;
  513         struct esa_softc *sc = (struct esa_softc *)vc->parent;
  514         struct esa_dma *p;
  515         struct esa_dma **pp;
  516 
  517         for (pp = &vc->dma; (p = *pp) != NULL; pp = &p->next)
  518                 if (KERNADDR(p) == addr) {
  519                         esa_freemem(sc, p);
  520                         *pp = p->next;
  521                         free(p, type);
  522                         return;
  523                 }
  524 }
  525 
  526 int
  527 esa_getdev(void *hdl, struct audio_device *ret)
  528 {
  529 
  530         *ret = esa_device;
  531 
  532         return (0);
  533 }
  534 
  535 int
  536 esa_set_port(void *hdl, mixer_ctrl_t *mc)
  537 {
  538         struct esa_voice *vc = hdl;
  539         struct esa_softc *sc = (struct esa_softc *)vc->parent;
  540 
  541         return (sc->codec_if->vtbl->mixer_set_port(sc->codec_if, mc));
  542 }
  543 
  544 int
  545 esa_get_port(void *hdl, mixer_ctrl_t *mc)
  546 {
  547         struct esa_voice *vc = hdl;
  548         struct esa_softc *sc = (struct esa_softc *)vc->parent;
  549 
  550         return (sc->codec_if->vtbl->mixer_get_port(sc->codec_if, mc));
  551 }
  552 
  553 int
  554 esa_query_devinfo(void *hdl, mixer_devinfo_t *di)
  555 {
  556         struct esa_voice *vc = hdl;
  557         struct esa_softc *sc = (struct esa_softc *)vc->parent;
  558 
  559         return (sc->codec_if->vtbl->query_devinfo(sc->codec_if, di));
  560 }
  561 
  562 size_t
  563 esa_round_buffersize(void *hdl, int direction, size_t bufsize)
  564 {
  565         struct esa_voice *vc = hdl;
  566 
  567         /*
  568          * We must be able to do better than this...
  569          */
  570         vc->play.bufsize = vc->rec.bufsize = 65536;
  571 
  572         return (vc->play.bufsize);
  573 }
  574 
  575 int
  576 esa_get_props(void *hdl)
  577 {
  578 
  579         return (AUDIO_PROP_MMAP | AUDIO_PROP_INDEPENDENT | AUDIO_PROP_FULLDUPLEX);
  580 }
  581 
  582 int
  583 esa_trigger_output(void *hdl, void *start, void *end, int blksize,
  584                         void (*intr)(void *), void *intrarg,
  585                         struct audio_params *param)
  586 {
  587         struct esa_voice *vc = hdl;
  588         struct esa_softc *sc = (struct esa_softc *)vc->parent;
  589         struct esa_dma *p;
  590         bus_space_tag_t iot = sc->sc_iot;
  591         bus_space_handle_t ioh = sc->sc_ioh;
  592         u_int32_t data;
  593         u_int32_t bufaddr;
  594         u_int32_t i;
  595         size_t size;
  596 
  597         int data_bytes = (((ESA_MINISRC_TMP_BUFFER_SIZE & ~1) +
  598                            (ESA_MINISRC_IN_BUFFER_SIZE & ~1) +
  599                            (ESA_MINISRC_OUT_BUFFER_SIZE & ~1) + 4) + 255)
  600                            &~ 255;
  601         int dac_data = ESA_DAC_DATA + (data_bytes * vc->index);
  602         int dsp_in_size = ESA_MINISRC_IN_BUFFER_SIZE - (0x20 * 2);
  603         int dsp_out_size = ESA_MINISRC_OUT_BUFFER_SIZE - (0x20 * 2);
  604         int dsp_in_buf = dac_data + (ESA_MINISRC_TMP_BUFFER_SIZE / 2);
  605         int dsp_out_buf = dsp_in_buf + (dsp_in_size / 2) + 1;
  606 
  607         if (vc->play.active)
  608                 return (EINVAL);
  609 
  610         for (p = vc->dma; p && KERNADDR(p) != start; p = p->next)
  611                 ;
  612         if (!p) {
  613                 printf("%s: esa_trigger_output: bad addr %p\n",
  614                     sc->sc_dev.dv_xname, start);
  615                 return (EINVAL);
  616         }
  617 
  618         vc->play.active = 1;
  619         vc->play.intr = intr;
  620         vc->play.arg = intrarg;
  621         vc->play.pos = 0;
  622         vc->play.count = 0;
  623         vc->play.buf = start;
  624         size = (size_t)(((caddr_t)end - (caddr_t)start));
  625         bufaddr = DMAADDR(p);
  626         vc->play.start = bufaddr;
  627 
  628 #define LO(x) ((x) & 0x0000ffff)
  629 #define HI(x) ((x) >> 16)
  630 
  631         esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA, dac_data +
  632             ESA_CDATA_HOST_SRC_ADDRL, LO(bufaddr));
  633         esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA, dac_data +
  634             ESA_CDATA_HOST_SRC_ADDRH, HI(bufaddr));
  635         esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA, dac_data +
  636             ESA_CDATA_HOST_SRC_END_PLUS_1L, LO(bufaddr + size));
  637         esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA, dac_data +
  638             ESA_CDATA_HOST_SRC_END_PLUS_1H, HI(bufaddr + size));
  639         esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA, dac_data +
  640             ESA_CDATA_HOST_SRC_CURRENTL, LO(bufaddr));
  641         esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA, dac_data +
  642             ESA_CDATA_HOST_SRC_CURRENTH, HI(bufaddr));
  643 
  644         /* DSP buffers */
  645         esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA, dac_data +
  646             ESA_CDATA_IN_BUF_BEGIN, dsp_in_buf);
  647         esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA, dac_data +
  648             ESA_CDATA_IN_BUF_END_PLUS_1, dsp_in_buf + (dsp_in_size / 2));
  649         esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA, dac_data +
  650             ESA_CDATA_IN_BUF_HEAD, dsp_in_buf);
  651         esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA, dac_data +
  652             ESA_CDATA_IN_BUF_TAIL, dsp_in_buf);
  653         esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA, dac_data +
  654             ESA_CDATA_OUT_BUF_BEGIN, dsp_out_buf);
  655         esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA, dac_data +
  656             ESA_CDATA_OUT_BUF_END_PLUS_1, dsp_out_buf + (dsp_out_size / 2));
  657         esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA, dac_data +
  658             ESA_CDATA_OUT_BUF_HEAD, dsp_out_buf);
  659         esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA, dac_data +
  660             ESA_CDATA_OUT_BUF_TAIL, dsp_out_buf);
  661 
  662         /* Some per-client initializers */
  663         esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA, dac_data +
  664             ESA_SRC3_DIRECTION_OFFSET + 12, dac_data + 40 + 8);
  665         esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA, dac_data +
  666             ESA_SRC3_DIRECTION_OFFSET + 19, 0x400 + ESA_MINISRC_COEF_LOC);
  667         /* Enable or disable low-pass filter? (0xff if rate > 45000) */
  668         esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA, dac_data +
  669             ESA_SRC3_DIRECTION_OFFSET + 22,
  670             vc->play.mode.sample_rate > 45000 ? 0xff : 0);
  671         /* Tell it which way DMA is going */
  672         esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA, dac_data +
  673             ESA_CDATA_DMA_CONTROL,
  674             ESA_DMACONTROL_AUTOREPEAT + ESA_DMAC_PAGE3_SELECTOR +
  675             ESA_DMAC_BLOCKF_SELECTOR);
  676 
  677         /* Set an armload of static initializers */
  678         for (i = 0; i < (sizeof(esa_playvals) / sizeof(esa_playvals[0])); i++)
  679                 esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA, dac_data +
  680                     esa_playvals[i].addr, esa_playvals[i].val);
  681 
  682         /* Put us in the packed task lists */
  683         esa_add_list(vc, &sc->msrc_list, dac_data >> ESA_DP_SHIFT_COUNT,
  684                      vc->index);
  685         esa_add_list(vc, &sc->dma_list, dac_data >> ESA_DP_SHIFT_COUNT,
  686                      vc->index);
  687         esa_add_list(vc, &sc->mixer_list, dac_data >> ESA_DP_SHIFT_COUNT,
  688                      vc->index);
  689 #undef LO
  690 #undef HI
  691 
  692         /* XXX */
  693         //esa_commit_settings(vc);
  694 
  695         sc->sc_ntimers++;
  696 
  697         if (sc->sc_ntimers == 1) {
  698                 esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA,
  699                     ESA_KDATA_TIMER_COUNT_RELOAD, 240);
  700                 esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA,
  701                     ESA_KDATA_TIMER_COUNT_CURRENT, 240);
  702                 data = bus_space_read_2(iot, ioh, ESA_HOST_INT_CTRL);
  703                 bus_space_write_2(iot, ioh, ESA_HOST_INT_CTRL,
  704                     data | ESA_CLKRUN_GEN_ENABLE);
  705         }
  706 
  707         esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA, dac_data +
  708             ESA_CDATA_INSTANCE_READY, 1);
  709         esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA,
  710             ESA_KDATA_MIXER_TASK_NUMBER,
  711             sc->mixer_list.indexmap[vc->index]);
  712 
  713         return (0);
  714 }
  715 
  716 int
  717 esa_trigger_input(void *hdl, void *start, void *end, int blksize,
  718                         void (*intr)(void *), void *intrarg,
  719                         struct audio_params *param)
  720 {
  721         struct esa_voice *vc = hdl;
  722         struct esa_softc *sc = (struct esa_softc *)vc->parent;
  723         struct esa_dma *p;
  724         bus_space_tag_t iot = sc->sc_iot;
  725         bus_space_handle_t ioh = sc->sc_ioh;
  726         u_int32_t data;
  727         u_int32_t bufaddr;
  728         u_int32_t i;
  729         size_t size;
  730         int data_bytes = (((ESA_MINISRC_TMP_BUFFER_SIZE & ~1) +
  731                            (ESA_MINISRC_IN_BUFFER_SIZE & ~1) +
  732                            (ESA_MINISRC_OUT_BUFFER_SIZE & ~1) + 4) + 255)
  733                            &~ 255;
  734         int adc_data = ESA_DAC_DATA + (data_bytes * vc->index) +
  735                        (data_bytes / 2);
  736         int dsp_in_size = ESA_MINISRC_IN_BUFFER_SIZE - (0x10 * 2);
  737         int dsp_out_size = ESA_MINISRC_OUT_BUFFER_SIZE - (0x10 * 2);
  738         int dsp_in_buf = adc_data + (ESA_MINISRC_TMP_BUFFER_SIZE / 2);
  739         int dsp_out_buf = dsp_in_buf + (dsp_in_size / 2) + 1;
  740         vc->rec.data_offset = adc_data;
  741 
  742         /* We only support 1 recording channel */
  743         if (vc->index > 0)
  744                 return (ENODEV);
  745 
  746         if (vc->rec.active)
  747                 return (EINVAL);
  748 
  749         for (p = vc->dma; p && KERNADDR(p) != start; p = p->next)
  750                 ;
  751         if (!p) {
  752                 printf("%s: esa_trigger_input: bad addr %p\n",
  753                     sc->sc_dev.dv_xname, start);
  754                 return (EINVAL);
  755         }
  756 
  757         vc->rec.active = 1;
  758         vc->rec.intr = intr;
  759         vc->rec.arg = intrarg;
  760         vc->rec.pos = 0;
  761         vc->rec.count = 0;
  762         vc->rec.buf = start;
  763         size = (size_t)(((caddr_t)end - (caddr_t)start));
  764         bufaddr = DMAADDR(p);
  765         vc->rec.start = bufaddr;
  766 
  767 #define LO(x) ((x) & 0x0000ffff)
  768 #define HI(x) ((x) >> 16)
  769 
  770         esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA, adc_data +
  771             ESA_CDATA_HOST_SRC_ADDRL, LO(bufaddr));
  772         esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA, adc_data +
  773             ESA_CDATA_HOST_SRC_ADDRH, HI(bufaddr));
  774         esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA, adc_data +
  775             ESA_CDATA_HOST_SRC_END_PLUS_1L, LO(bufaddr + size));
  776         esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA, adc_data +
  777             ESA_CDATA_HOST_SRC_END_PLUS_1H, HI(bufaddr + size));
  778         esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA, adc_data +
  779             ESA_CDATA_HOST_SRC_CURRENTL, LO(bufaddr));
  780         esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA, adc_data +
  781             ESA_CDATA_HOST_SRC_CURRENTH, HI(bufaddr));
  782 
  783         /* DSP buffers */
  784         esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA, adc_data +
  785             ESA_CDATA_IN_BUF_BEGIN, dsp_in_buf);
  786         esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA, adc_data +
  787             ESA_CDATA_IN_BUF_END_PLUS_1, dsp_in_buf + (dsp_in_size / 2));
  788         esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA, adc_data +
  789             ESA_CDATA_IN_BUF_HEAD, dsp_in_buf);
  790         esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA, adc_data +
  791             ESA_CDATA_IN_BUF_TAIL, dsp_in_buf);
  792         esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA, adc_data +
  793             ESA_CDATA_OUT_BUF_BEGIN, dsp_out_buf);
  794         esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA, adc_data +
  795             ESA_CDATA_OUT_BUF_END_PLUS_1, dsp_out_buf + (dsp_out_size / 2));
  796         esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA, adc_data +
  797             ESA_CDATA_OUT_BUF_HEAD, dsp_out_buf);
  798         esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA, adc_data +
  799             ESA_CDATA_OUT_BUF_TAIL, dsp_out_buf);
  800 
  801         /* Some per-client initializers */
  802         esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA, adc_data +
  803             ESA_SRC3_DIRECTION_OFFSET + 12, adc_data + 40 + 8);
  804         /* Tell it which way DMA is going */
  805         esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA, adc_data +
  806             ESA_CDATA_DMA_CONTROL,
  807             ESA_DMACONTROL_DIRECTION + ESA_DMACONTROL_AUTOREPEAT +
  808             ESA_DMAC_PAGE3_SELECTOR + ESA_DMAC_BLOCKF_SELECTOR);
  809 
  810         /* Set an armload of static initializers */
  811         for (i = 0; i < (sizeof(esa_recvals) / sizeof(esa_recvals[0])); i++)
  812                 esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA, adc_data +
  813                     esa_recvals[i].addr, esa_recvals[i].val);
  814 
  815         /* Put us in the packed task lists */
  816         esa_add_list(vc, &sc->adc1_list, adc_data >> ESA_DP_SHIFT_COUNT,
  817                      vc->index + ESA_NUM_VOICES);
  818         esa_add_list(vc, &sc->msrc_list, adc_data >> ESA_DP_SHIFT_COUNT,
  819                      vc->index + ESA_NUM_VOICES);
  820         esa_add_list(vc, &sc->dma_list, adc_data >> ESA_DP_SHIFT_COUNT,
  821                      vc->index + ESA_NUM_VOICES);
  822 #undef LO
  823 #undef HI
  824 
  825         /* XXX */
  826         //esa_commit_settings(vc);
  827 
  828         sc->sc_ntimers++;
  829         if (sc->sc_ntimers == 1) {
  830                 esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA,
  831                     ESA_KDATA_TIMER_COUNT_RELOAD, 240);
  832                 esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA,
  833                     ESA_KDATA_TIMER_COUNT_CURRENT, 240);
  834                 data = bus_space_read_2(iot, ioh, ESA_HOST_INT_CTRL);
  835                 bus_space_write_2(iot, ioh, ESA_HOST_INT_CTRL,
  836                     data | ESA_CLKRUN_GEN_ENABLE);
  837         }
  838 
  839         esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA, adc_data +
  840             ESA_CDATA_INSTANCE_READY, 1);
  841         esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA, ESA_KDATA_ADC1_REQUEST,
  842             1);
  843 
  844         return (0);
  845 }
  846 
  847 /* Interrupt handler */
  848 
  849 int
  850 esa_intr(void *hdl)
  851 {
  852         struct esa_softc *sc = hdl;
  853         struct esa_voice *vc;
  854         bus_space_tag_t iot = sc->sc_iot;
  855         bus_space_handle_t ioh = sc->sc_ioh;
  856         u_int8_t status, ctl;
  857         u_int32_t pos;
  858         u_int32_t diff;
  859         u_int32_t play_blksize, play_bufsize;
  860         u_int32_t rec_blksize, rec_bufsize;
  861         int i;
  862 
  863         status = bus_space_read_1(iot, ioh, ESA_HOST_INT_STATUS);
  864         if (status == 0xff)
  865                 return (0);
  866 
  867         /* ack the interrupt */
  868         bus_space_write_1(iot, ioh, ESA_HOST_INT_STATUS, status);
  869 
  870         if (status & ESA_HV_INT_PENDING) {
  871                 u_int8_t event;
  872 
  873                 printf("%s: hardware volume interrupt\n", sc->sc_dev.dv_xname);
  874                 event = bus_space_read_1(iot, ioh, ESA_HW_VOL_COUNTER_MASTER);
  875                 switch(event) {
  876                 case 0x99:
  877                 case 0xaa:
  878                 case 0x66:
  879                 case 0x88:      
  880                         printf("%s: esa_intr: FIXME\n", sc->sc_dev.dv_xname);
  881                         break;
  882                 default:
  883                         printf("%s: unknown hwvol event 0x%02x\n",
  884                             sc->sc_dev.dv_xname, event);
  885                         break;
  886                 }
  887                 bus_space_write_1(iot, ioh, ESA_HW_VOL_COUNTER_MASTER, 0x88);
  888         }
  889 
  890         if (status & ESA_ASSP_INT_PENDING) {
  891                 ctl = bus_space_read_1(iot, ioh, ESA_ASSP_CONTROL_B);
  892                 if (!(ctl & ESA_STOP_ASSP_CLOCK)) {
  893                         ctl = bus_space_read_1(iot, ioh,
  894                                                ESA_ASSP_HOST_INT_STATUS);
  895                         if (ctl & ESA_DSP2HOST_REQ_TIMER) {
  896                                 bus_space_write_1(iot, ioh,
  897                                     ESA_ASSP_HOST_INT_STATUS,
  898                                     ESA_DSP2HOST_REQ_TIMER);
  899                                 for (i = 0; i < ESA_NUM_VOICES; i++) {
  900                                         vc = &sc->voice[i];
  901                                         if (vc->play.active) {
  902                                                 play_blksize = vc->play.blksize;
  903                                                 play_bufsize = vc->play.bufsize;
  904                                                 pos = esa_get_pointer(sc, &vc->play)
  905                                                     % play_bufsize;
  906                                                 diff = (play_bufsize + pos - vc->play.pos)
  907                                                     % play_bufsize;
  908                                                 vc->play.pos = pos;
  909                                                 vc->play.count += diff;
  910                                                 while(vc->play.count >= play_blksize) {
  911                                                         vc->play.count -= play_blksize;
  912                                                         (*vc->play.intr)(vc->play.arg);
  913                                                 }
  914                                         }
  915                                         if (vc->rec.active) {
  916                                                 rec_blksize = vc->rec.blksize;
  917                                                 rec_bufsize = vc->rec.bufsize;
  918                                                 pos = esa_get_pointer(sc, &vc->rec)
  919                                                     % rec_bufsize;
  920                                                 diff = (rec_bufsize + pos - vc->rec.pos)
  921                                                     % rec_bufsize;
  922                                                 vc->rec.pos = pos;
  923                                                 vc->rec.count += diff;
  924                                                 while(vc->rec.count >= rec_blksize) {
  925                                                         vc->rec.count -= rec_blksize;
  926                                                         (*vc->rec.intr)(vc->rec.arg);
  927                                                 }
  928                                         }
  929                                 }
  930                         }
  931                 }
  932         }
  933 
  934         return (1);
  935 }
  936 
  937 int
  938 esa_allocmem(struct esa_softc *sc, size_t size, size_t align,
  939                 struct esa_dma *p)
  940 {
  941         int error;
  942 
  943         p->size = size;
  944         error = bus_dmamem_alloc(sc->sc_dmat, p->size, align, 0,
  945                                  p->segs, sizeof(p->segs) / sizeof(p->segs[0]),
  946                                  &p->nsegs, BUS_DMA_NOWAIT);
  947         if (error)
  948                 return (error);
  949 
  950         error = bus_dmamem_map(sc->sc_dmat, p->segs, p->nsegs, p->size,
  951                                 &p->addr, BUS_DMA_NOWAIT | BUS_DMA_COHERENT);
  952         if (error)
  953                 goto free;
  954 
  955         error = bus_dmamap_create(sc->sc_dmat, p->size, 1, p->size, 0,
  956                                   BUS_DMA_NOWAIT, &p->map);
  957         if (error)
  958                 goto unmap;
  959 
  960         error = bus_dmamap_load(sc->sc_dmat, p->map, p->addr, p->size, NULL,
  961                                 BUS_DMA_NOWAIT);
  962         if (error)
  963                 goto destroy;
  964 
  965         return (0);
  966 
  967 destroy:
  968         bus_dmamap_destroy(sc->sc_dmat, p->map);
  969 unmap:
  970         bus_dmamem_unmap(sc->sc_dmat, p->addr, p->size);
  971 free:
  972         bus_dmamem_free(sc->sc_dmat, p->segs, p->nsegs);
  973 
  974         return (error); 
  975 }
  976 
  977 int
  978 esa_freemem(struct esa_softc *sc, struct esa_dma *p)
  979 {
  980 
  981         bus_dmamap_unload(sc->sc_dmat, p->map);
  982         bus_dmamap_destroy(sc->sc_dmat, p->map);
  983         bus_dmamem_unmap(sc->sc_dmat, p->addr, p->size);
  984         bus_dmamem_free(sc->sc_dmat, p->segs, p->nsegs);
  985 
  986         return (0);
  987 }
  988 
  989 /*
  990  * Supporting Subroutines
  991  */
  992 
  993 int
  994 esa_match(struct device *dev, struct cfdata *match, void *aux)
  995 {
  996         struct pci_attach_args *pa = (struct pci_attach_args *)aux;
  997 
  998         switch(PCI_VENDOR(pa->pa_id)) {
  999         case PCI_VENDOR_ESSTECH:
 1000                 switch(PCI_PRODUCT(pa->pa_id)) {
 1001                 case PCI_PRODUCT_ESSTECH_ALLEGRO1:
 1002                 case PCI_PRODUCT_ESSTECH_MAESTRO3:
 1003                 case PCI_PRODUCT_ESSTECH_MAESTRO3_2:
 1004                         return (1);
 1005                 }
 1006         }
 1007 
 1008         return (0);
 1009 }
 1010 
 1011 void
 1012 esa_attach(struct device *parent, struct device *self, void *aux)
 1013 {
 1014         struct esa_softc *sc = (struct esa_softc *)self;
 1015         struct pci_attach_args *pa = (struct pci_attach_args *)aux;
 1016         pcitag_t tag = pa->pa_tag;
 1017         pci_chipset_tag_t pc = pa->pa_pc;
 1018         pci_intr_handle_t ih;
 1019         struct esa_card_type *card;
 1020         const char *intrstr;
 1021         u_int32_t data;
 1022         char devinfo[256];
 1023         int revision, len;
 1024         int i;
 1025 
 1026         aprint_naive(": Audio controller\n");
 1027 
 1028         pci_devinfo(pa->pa_id, pa->pa_class, 0, devinfo);
 1029         revision = PCI_REVISION(pa->pa_class);
 1030         aprint_normal(": %s (rev. 0x%02x)\n", devinfo, revision);
 1031 
 1032         for (card = esa_card_types; card->pci_vendor_id; card++)
 1033                 if (PCI_VENDOR(pa->pa_id) == card->pci_vendor_id &&
 1034                     PCI_PRODUCT(pa->pa_id) == card->pci_product_id) {
 1035                         sc->type = card->type;
 1036                         sc->delay1 = card->delay1;
 1037                         sc->delay2 = card->delay2;
 1038                         break;
 1039                 }
 1040 
 1041         data = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG);
 1042         data |= (PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE
 1043             | PCI_COMMAND_MASTER_ENABLE);
 1044         pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG, data);
 1045 
 1046         /* Map I/O register */
 1047         if (pci_mapreg_map(pa, PCI_CBIO, PCI_MAPREG_TYPE_IO, 0,
 1048             &sc->sc_iot, &sc->sc_ioh, &sc->sc_iob, &sc->sc_ios)) {
 1049                 aprint_error("%s: can't map i/o space\n", sc->sc_dev.dv_xname);
 1050                 return;
 1051         }
 1052 
 1053         /* Initialize softc */
 1054         sc->sc_tag = tag;
 1055         sc->sc_pct = pc;
 1056         sc->sc_dmat = pa->pa_dmat;
 1057 
 1058         /* Map and establish an interrupt */
 1059         if (pci_intr_map(pa, &ih)) {
 1060                 aprint_error("%s: can't map interrupt\n", sc->sc_dev.dv_xname);
 1061                 return;
 1062         }
 1063         intrstr = pci_intr_string(pc, ih);
 1064         sc->sc_ih = pci_intr_establish(pc, ih, IPL_AUDIO, esa_intr, self);
 1065         if (sc->sc_ih == NULL) {
 1066                 aprint_error("%s: can't establish interrupt",
 1067                     sc->sc_dev.dv_xname);
 1068                 if (intrstr != NULL)
 1069                         aprint_normal(" at %s", intrstr);
 1070                 aprint_normal("\n");
 1071                 return;
 1072         }
 1073         aprint_normal("%s: interrupting at %s\n", sc->sc_dev.dv_xname, intrstr);
 1074 
 1075         /* Power up chip */
 1076         esa_power(sc, PCI_PMCSR_STATE_D0);
 1077 
 1078         /* Init chip */
 1079         if (esa_init(sc) == -1) {
 1080                 aprint_error("%s: esa_attach: unable to initialize the card\n",
 1081                     sc->sc_dev.dv_xname);
 1082                 return;
 1083         }
 1084 
 1085         /* create suspend save area */
 1086         len = sizeof(u_int16_t) * (ESA_REV_B_CODE_MEMORY_LENGTH
 1087             + ESA_REV_B_DATA_MEMORY_LENGTH + 1);
 1088         sc->savemem = (u_int16_t *)malloc(len, M_DEVBUF, M_NOWAIT | M_ZERO);
 1089         if (sc->savemem == NULL) {
 1090                 aprint_error("%s: unable to allocate suspend buffer\n",
 1091                     sc->sc_dev.dv_xname);
 1092                 return;
 1093         }
 1094 
 1095         /*
 1096          * Every card I've seen has had their channels swapped with respect
 1097          * to the mixer. Ie:
 1098          *  $ mixerctl -w outputs.master=0,191
 1099          * Would result in the _right_ speaker being turned off.
 1100          * 
 1101          * So, we will swap the left and right mixer channels to compensate
 1102          * for this.
 1103          */ 
 1104         sc->codec_flags = AC97_HOST_SWAPPED_CHANNELS;
 1105 
 1106         /* Attach AC97 host interface */
 1107         sc->host_if.arg = self;
 1108         sc->host_if.attach = esa_attach_codec;
 1109         sc->host_if.read = esa_read_codec;
 1110         sc->host_if.write = esa_write_codec;
 1111         sc->host_if.reset = esa_reset_codec;
 1112         sc->host_if.flags = esa_flags_codec;
 1113 
 1114         if (ac97_attach(&sc->host_if) != 0)
 1115                 return;
 1116 
 1117         /* initialize list management structures */
 1118         sc->mixer_list.mem_addr = ESA_KDATA_MIXER_XFER0;
 1119         sc->mixer_list.max = ESA_MAX_VIRTUAL_MIXER_CHANNELS;
 1120         sc->adc1_list.mem_addr = ESA_KDATA_ADC1_XFER0;
 1121         sc->adc1_list.max = ESA_MAX_VIRTUAL_ADC1_CHANNELS;
 1122         sc->dma_list.mem_addr = ESA_KDATA_DMA_XFER0;
 1123         sc->dma_list.max = ESA_MAX_VIRTUAL_DMA_CHANNELS;
 1124         sc->msrc_list.mem_addr = ESA_KDATA_INSTANCE0_MINISRC;
 1125         sc->msrc_list.max = ESA_MAX_INSTANCE_MINISRC;
 1126 
 1127         /* initialize index maps */
 1128         for (i = 0; i < ESA_NUM_VOICES * 2; i++) {
 1129                 sc->mixer_list.indexmap[i] = -1;
 1130                 sc->msrc_list.indexmap[i] = -1;
 1131                 sc->dma_list.indexmap[i] = -1;
 1132                 sc->adc1_list.indexmap[i] = -1;
 1133         }
 1134         for (i = 0; i < ESA_NUM_VOICES; i++) {
 1135                 sc->voice[i].parent = (struct device *)sc;
 1136                 sc->voice[i].index = i;
 1137                 sc->sc_audiodev[i] =
 1138                     audio_attach_mi(&esa_hw_if, &sc->voice[i], &sc->sc_dev);
 1139         }
 1140 
 1141         sc->powerhook = powerhook_establish(esa_powerhook, sc);
 1142         if (sc->powerhook == NULL)
 1143                 aprint_error("%s: WARNING: unable to establish powerhook\n",
 1144                     sc->sc_dev.dv_xname);
 1145 
 1146         return;
 1147 }
 1148 
 1149 int
 1150 esa_detach(struct device *self, int flags)
 1151 {
 1152         struct esa_softc *sc = (struct esa_softc *)self;
 1153         int i;
 1154 
 1155         for (i = 0; i < ESA_NUM_VOICES; i++) {
 1156                 if (sc->sc_audiodev[i] != NULL)
 1157                         config_detach(sc->sc_audiodev[i], flags);
 1158         }
 1159 
 1160         if (sc->sc_ih != NULL)
 1161                 pci_intr_disestablish(sc->sc_pct, sc->sc_ih);
 1162         if (sc->sc_ios)
 1163                 bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_ios);
 1164 
 1165         free(sc->savemem, M_DEVBUF);
 1166 
 1167         return (0);
 1168 }
 1169 
 1170 u_int16_t
 1171 esa_read_assp(struct esa_softc *sc, u_int16_t region, u_int16_t index)
 1172 {
 1173         u_int16_t data;
 1174         bus_space_tag_t iot = sc->sc_iot;
 1175         bus_space_handle_t ioh = sc->sc_ioh;
 1176 
 1177         bus_space_write_2(iot, ioh, ESA_DSP_PORT_MEMORY_TYPE,
 1178             region & ESA_MEMTYPE_MASK);
 1179         bus_space_write_2(iot, ioh, ESA_DSP_PORT_MEMORY_INDEX, index);
 1180         data = bus_space_read_2(iot, ioh, ESA_DSP_PORT_MEMORY_DATA);
 1181 
 1182         return (data);
 1183 }
 1184 
 1185 void
 1186 esa_write_assp(struct esa_softc *sc, u_int16_t region, u_int16_t index,
 1187                 u_int16_t data)
 1188 {
 1189         bus_space_tag_t iot = sc->sc_iot;
 1190         bus_space_handle_t ioh = sc->sc_ioh;
 1191 
 1192         bus_space_write_2(iot, ioh, ESA_DSP_PORT_MEMORY_TYPE,
 1193             region & ESA_MEMTYPE_MASK);
 1194         bus_space_write_2(iot, ioh, ESA_DSP_PORT_MEMORY_INDEX, index);
 1195         bus_space_write_2(iot, ioh, ESA_DSP_PORT_MEMORY_DATA, data);
 1196 
 1197         return;
 1198 }
 1199 
 1200 int
 1201 esa_init_codec(struct esa_softc *sc)
 1202 {
 1203         bus_space_tag_t iot = sc->sc_iot;
 1204         bus_space_handle_t ioh = sc->sc_ioh;
 1205         u_int32_t data;
 1206 
 1207         data = bus_space_read_1(iot, ioh, ESA_CODEC_COMMAND);
 1208 
 1209         return ((data & 0x1) ? 0 : 1);
 1210 }
 1211 
 1212 int
 1213 esa_attach_codec(void *aux, struct ac97_codec_if *codec_if)
 1214 {
 1215         struct esa_softc *sc = aux;
 1216 
 1217         sc->codec_if = codec_if;
 1218 
 1219         return (0);
 1220 }
 1221 
 1222 int
 1223 esa_read_codec(void *aux, u_int8_t reg, u_int16_t *result)
 1224 {
 1225         struct esa_softc *sc = aux;
 1226         bus_space_tag_t iot = sc->sc_iot;
 1227         bus_space_handle_t ioh = sc->sc_ioh;
 1228 
 1229         if (esa_wait(sc))
 1230                 printf("%s: esa_read_codec: timed out\n", sc->sc_dev.dv_xname);
 1231         bus_space_write_1(iot, ioh, ESA_CODEC_COMMAND, (reg & 0x7f) | 0x80);
 1232         delay(50);
 1233         if (esa_wait(sc))
 1234                 printf("%s: esa_read_codec: timed out\n", sc->sc_dev.dv_xname);
 1235         *result = bus_space_read_2(iot, ioh, ESA_CODEC_DATA);
 1236 
 1237         return (0);
 1238 }
 1239 
 1240 int
 1241 esa_write_codec(void *aux, u_int8_t reg, u_int16_t data)
 1242 {
 1243         struct esa_softc *sc = aux;
 1244         bus_space_tag_t iot = sc->sc_iot;
 1245         bus_space_handle_t ioh = sc->sc_ioh;
 1246 
 1247         if (esa_wait(sc)) {
 1248                 printf("%s: esa_write_codec: timed out\n", sc->sc_dev.dv_xname);
 1249                 return (-1);
 1250         }
 1251         bus_space_write_2(iot, ioh, ESA_CODEC_DATA, data);
 1252         bus_space_write_1(iot, ioh, ESA_CODEC_COMMAND, reg & 0x7f);
 1253         delay(50);
 1254 
 1255         return (0);
 1256 }
 1257 
 1258 int
 1259 esa_reset_codec(void *aux)
 1260 {
 1261 
 1262         return 0;
 1263 }
 1264 
 1265 enum ac97_host_flags
 1266 esa_flags_codec(void *aux)
 1267 {
 1268         struct esa_softc *sc = aux;
 1269 
 1270         return (sc->codec_flags);
 1271 }
 1272 
 1273 int
 1274 esa_wait(struct esa_softc *sc)
 1275 {
 1276         int i, val;
 1277         bus_space_tag_t iot = sc->sc_iot;
 1278         bus_space_handle_t ioh = sc->sc_ioh;
 1279 
 1280         for (i = 0; i < 20; i++) {
 1281                 val = bus_space_read_1(iot, ioh, ESA_CODEC_STATUS);
 1282                 if ((val & 1) == 0)
 1283                         return (0);
 1284                 delay(2);
 1285         }
 1286 
 1287         return (-1);
 1288 }
 1289 
 1290 int
 1291 esa_init(struct esa_softc *sc)
 1292 {
 1293         struct esa_voice *vc;
 1294         bus_space_tag_t iot = sc->sc_iot;
 1295         bus_space_handle_t ioh = sc->sc_ioh;
 1296         pcitag_t tag = sc->sc_tag;
 1297         pci_chipset_tag_t pc = sc->sc_pct;
 1298         u_int32_t data, i, size;
 1299         u_int8_t reset_state;
 1300         int data_bytes = (((ESA_MINISRC_TMP_BUFFER_SIZE & ~1) +
 1301                            (ESA_MINISRC_IN_BUFFER_SIZE & ~1) +
 1302                            (ESA_MINISRC_OUT_BUFFER_SIZE & ~1) + 4) + 255)
 1303                            &~ 255;
 1304 
 1305         /* Disable legacy emulation */
 1306         data = pci_conf_read(pc, tag, PCI_LEGACY_AUDIO_CTRL);
 1307         data |= DISABLE_LEGACY;
 1308         pci_conf_write(pc, tag, PCI_LEGACY_AUDIO_CTRL, data);
 1309 
 1310         esa_config(sc);
 1311 
 1312         reset_state = esa_assp_halt(sc);
 1313 
 1314         esa_init_codec(sc);
 1315         esa_codec_reset(sc);
 1316 
 1317         /* Zero kernel and mixer data */
 1318         size = ESA_REV_B_DATA_MEMORY_UNIT_LENGTH * ESA_NUM_UNITS_KERNEL_DATA;
 1319         for (i = 0; i < size / 2; i++) {
 1320                 esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA,
 1321                     ESA_KDATA_BASE_ADDR + i, 0);
 1322                 esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA,
 1323                     ESA_KDATA_BASE_ADDR2 + i, 0);
 1324         }
 1325 
 1326         /* Init DMA pointer */
 1327         esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA, ESA_KDATA_CURRENT_DMA,
 1328             ESA_KDATA_DMA_XFER0);
 1329 
 1330         /* Write kernel code into memory */
 1331         size = sizeof(esa_assp_kernel_image);
 1332         for (i = 0; i < size / 2; i++)
 1333                 esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_CODE,
 1334                     ESA_REV_B_CODE_MEMORY_BEGIN + i, esa_assp_kernel_image[i]);
 1335 
 1336         size = sizeof(esa_assp_minisrc_image);
 1337         for (i = 0; i < size / 2; i++)
 1338                 esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_CODE, 0x400 + i,
 1339                     esa_assp_minisrc_image[i]);
 1340 
 1341         /* Write the coefficients for the low pass filter */
 1342         size = sizeof(esa_minisrc_lpf_image);
 1343         for (i = 0; i < size / 2; i++)
 1344                 esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_CODE,
 1345                     0x400 + ESA_MINISRC_COEF_LOC + i, esa_minisrc_lpf_image[i]);
 1346         esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_CODE,
 1347             0x400 + ESA_MINISRC_COEF_LOC + size, 0x8000);
 1348         esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA, ESA_KDATA_TASK0, 0x400);
 1349         /* Init the mixer number */
 1350         esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA,
 1351              ESA_KDATA_MIXER_TASK_NUMBER, 0);
 1352         /* Extreme kernel master volume */
 1353         esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA,
 1354             ESA_KDATA_DAC_LEFT_VOLUME, ESA_ARB_VOLUME);
 1355         esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA,
 1356             ESA_KDATA_DAC_RIGHT_VOLUME, ESA_ARB_VOLUME);
 1357 
 1358         if (esa_amp_enable(sc))
 1359                 return (-1);
 1360 
 1361         /* Zero entire DAC/ADC area */
 1362         for (i = 0x1100; i < 0x1c00; i++)
 1363                 esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA, i, 0);
 1364 
 1365         /* set some sane defaults */
 1366         for (i = 0; i < ESA_NUM_VOICES; i++) {
 1367                 vc = &sc->voice[i];
 1368                 vc->play.data_offset = ESA_DAC_DATA + (data_bytes * i);
 1369                 vc->rec.data_offset = ESA_DAC_DATA + (data_bytes * i * 2);
 1370         }
 1371 
 1372         esa_enable_interrupts(sc);
 1373 
 1374         bus_space_write_1(iot, ioh, ESA_DSP_PORT_CONTROL_REG_B,
 1375             reset_state | ESA_REGB_ENABLE_RESET);
 1376 
 1377         return (0);
 1378 }
 1379 
 1380 void
 1381 esa_config(struct esa_softc *sc)
 1382 {
 1383         bus_space_tag_t iot = sc->sc_iot;
 1384         bus_space_handle_t ioh = sc->sc_ioh;
 1385         pcitag_t tag = sc->sc_tag;
 1386         pci_chipset_tag_t pc = sc->sc_pct;
 1387         u_int32_t data;
 1388 
 1389         data = pci_conf_read(pc, tag, ESA_PCI_ALLEGRO_CONFIG);
 1390         data &= ESA_REDUCED_DEBOUNCE;
 1391         data |= ESA_PM_CTRL_ENABLE | ESA_CLK_DIV_BY_49 | ESA_USE_PCI_TIMING;
 1392         pci_conf_write(pc, tag, ESA_PCI_ALLEGRO_CONFIG, data);
 1393 
 1394         bus_space_write_1(iot, ioh, ESA_ASSP_CONTROL_B, ESA_RESET_ASSP);
 1395         data = pci_conf_read(pc, tag, ESA_PCI_ALLEGRO_CONFIG);
 1396         data &= ~ESA_INT_CLK_SELECT;
 1397         if (sc->type == ESS_MAESTRO3) {
 1398                 data &= ~ESA_INT_CLK_MULT_ENABLE;
 1399                 data |= ESA_INT_CLK_SRC_NOT_PCI;
 1400         }
 1401         data &= ~(ESA_CLK_MULT_MODE_SELECT | ESA_CLK_MULT_MODE_SELECT_2);
 1402         pci_conf_write(pc, tag, ESA_PCI_ALLEGRO_CONFIG, data);
 1403 
 1404         if (sc->type == ESS_ALLEGRO1) {
 1405                 data = pci_conf_read(pc, tag, ESA_PCI_USER_CONFIG);
 1406                 data |= ESA_IN_CLK_12MHZ_SELECT;
 1407                 pci_conf_write(pc, tag, ESA_PCI_USER_CONFIG, data);
 1408         }
 1409 
 1410         data = bus_space_read_1(iot, ioh, ESA_ASSP_CONTROL_A);
 1411         data &= ~(ESA_DSP_CLK_36MHZ_SELECT | ESA_ASSP_CLK_49MHZ_SELECT);
 1412         data |= ESA_ASSP_CLK_49MHZ_SELECT;      /* XXX: Assumes 49MHz DSP */
 1413         data |= ESA_ASSP_0_WS_ENABLE;
 1414         bus_space_write_1(iot, ioh, ESA_ASSP_CONTROL_A, data);
 1415 
 1416         bus_space_write_1(iot, ioh, ESA_ASSP_CONTROL_B, ESA_RUN_ASSP);
 1417 
 1418         return;
 1419 }
 1420 
 1421 u_int8_t
 1422 esa_assp_halt(struct esa_softc *sc)
 1423 {
 1424         bus_space_tag_t iot = sc->sc_iot;
 1425         bus_space_handle_t ioh = sc->sc_ioh;
 1426         u_int8_t data, reset_state;
 1427 
 1428         data = bus_space_read_1(iot, ioh, ESA_DSP_PORT_CONTROL_REG_B);
 1429         reset_state = data & ~ESA_REGB_STOP_CLOCK;
 1430         delay(10000);           /* XXX use tsleep */
 1431         bus_space_write_1(iot, ioh, ESA_DSP_PORT_CONTROL_REG_B,
 1432                         reset_state & ~ESA_REGB_ENABLE_RESET);
 1433         delay(10000);           /* XXX use tsleep */
 1434 
 1435         return (reset_state);
 1436 }
 1437 
 1438 void
 1439 esa_codec_reset(struct esa_softc *sc)
 1440 {
 1441         bus_space_tag_t iot = sc->sc_iot;
 1442         bus_space_handle_t ioh = sc->sc_ioh;
 1443         u_int16_t data, dir;
 1444         int retry = 0;
 1445 
 1446         do {
 1447                 data = bus_space_read_2(iot, ioh, ESA_GPIO_DIRECTION);
 1448                 dir = data | 0x10; /* assuming pci bus master? */
 1449 
 1450                 /* remote codec config */
 1451                 data = bus_space_read_2(iot, ioh, ESA_RING_BUS_CTRL_B);
 1452                 bus_space_write_2(iot, ioh, ESA_RING_BUS_CTRL_B,
 1453                     data & ~ESA_SECOND_CODEC_ID_MASK);
 1454                 data = bus_space_read_2(iot, ioh, ESA_SDO_OUT_DEST_CTRL);
 1455                 bus_space_write_2(iot, ioh, ESA_SDO_OUT_DEST_CTRL,
 1456                     data & ~ESA_COMMAND_ADDR_OUT);
 1457                 data = bus_space_read_2(iot, ioh, ESA_SDO_IN_DEST_CTRL);
 1458                 bus_space_write_2(iot, ioh, ESA_SDO_IN_DEST_CTRL,
 1459                     data & ~ESA_STATUS_ADDR_IN);
 1460 
 1461                 bus_space_write_2(iot, ioh, ESA_RING_BUS_CTRL_A,
 1462                                   ESA_IO_SRAM_ENABLE);
 1463                 delay(20);
 1464 
 1465                 bus_space_write_2(iot, ioh, ESA_GPIO_DIRECTION,
 1466                     dir & ~ESA_GPO_PRIMARY_AC97);
 1467                 bus_space_write_2(iot, ioh, ESA_GPIO_MASK,
 1468                                   ~ESA_GPO_PRIMARY_AC97);
 1469                 bus_space_write_2(iot, ioh, ESA_GPIO_DATA, 0);
 1470                 bus_space_write_2(iot, ioh, ESA_GPIO_DIRECTION,
 1471                     dir | ESA_GPO_PRIMARY_AC97);
 1472                 delay(sc->delay1 * 1000);
 1473                 bus_space_write_2(iot, ioh, ESA_GPIO_DATA,
 1474                                   ESA_GPO_PRIMARY_AC97);
 1475                 delay(5);
 1476                 bus_space_write_2(iot, ioh, ESA_RING_BUS_CTRL_A,
 1477                     ESA_IO_SRAM_ENABLE | ESA_SERIAL_AC_LINK_ENABLE);
 1478                 bus_space_write_2(iot, ioh, ESA_GPIO_MASK, ~0);
 1479                 delay(sc->delay2 * 1000);
 1480 
 1481                 esa_read_codec(sc, 0x7c, &data);
 1482                 if ((data == 0) || (data == 0xffff)) {
 1483                         retry++;
 1484                         if (retry > 3) {
 1485                                 printf("%s: esa_codec_reset: failed\n",
 1486                                     sc->sc_dev.dv_xname);
 1487                                 break;
 1488                         }
 1489                         printf("%s: esa_codec_reset: retrying\n",
 1490                             sc->sc_dev.dv_xname);
 1491                 } else
 1492                         retry = 0;
 1493         } while (retry);
 1494 
 1495         return;
 1496 }
 1497 
 1498 int
 1499 esa_amp_enable(struct esa_softc *sc)
 1500 {
 1501         bus_space_tag_t iot = sc->sc_iot;
 1502         bus_space_handle_t ioh = sc->sc_ioh;
 1503         u_int32_t gpo, polarity_port, polarity;
 1504         u_int16_t data;
 1505 
 1506         switch (sc->type) {
 1507         case ESS_ALLEGRO1:
 1508                 polarity_port = 0x1800;
 1509                 break;
 1510         case ESS_MAESTRO3:
 1511                 polarity_port = 0x1100;
 1512                 break;
 1513         default:
 1514                 printf("%s: esa_amp_enable: Unknown chip type!!!\n",
 1515                     sc->sc_dev.dv_xname);
 1516                 return (1);
 1517         }
 1518 
 1519         gpo = (polarity_port >> 8) & 0x0f;
 1520         polarity = polarity_port >> 12;
 1521         polarity = !polarity;   /* Enable */
 1522         polarity = polarity << gpo;
 1523         gpo = 1 << gpo;
 1524         bus_space_write_2(iot, ioh, ESA_GPIO_MASK, ~gpo);
 1525         data = bus_space_read_2(iot, ioh, ESA_GPIO_DIRECTION);
 1526         bus_space_write_2(iot, ioh, ESA_GPIO_DIRECTION, data | gpo);
 1527         data = ESA_GPO_SECONDARY_AC97 | ESA_GPO_PRIMARY_AC97 | polarity;
 1528         bus_space_write_2(iot, ioh, ESA_GPIO_DATA, data);
 1529         bus_space_write_2(iot, ioh, ESA_GPIO_MASK, ~0);
 1530 
 1531         return (0);
 1532 }
 1533 
 1534 void
 1535 esa_enable_interrupts(struct esa_softc *sc)
 1536 {
 1537         bus_space_tag_t iot = sc->sc_iot;
 1538         bus_space_handle_t ioh = sc->sc_ioh;
 1539         u_int8_t data;
 1540 
 1541         bus_space_write_2(iot, ioh, ESA_HOST_INT_CTRL,
 1542             ESA_ASSP_INT_ENABLE | ESA_HV_INT_ENABLE);
 1543         data = bus_space_read_1(iot, ioh, ESA_ASSP_CONTROL_C);
 1544         bus_space_write_1(iot, ioh, ESA_ASSP_CONTROL_C,
 1545             data | ESA_ASSP_HOST_INT_ENABLE);
 1546 }
 1547 
 1548 /*
 1549  * List management
 1550  */
 1551 int
 1552 esa_add_list(struct esa_voice *vc, struct esa_list *el,
 1553              u_int16_t val, int index)
 1554 {
 1555         struct esa_softc *sc = (struct esa_softc *)vc->parent;
 1556 
 1557         el->indexmap[index] = el->currlen;
 1558         esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA,
 1559                        el->mem_addr + el->currlen,
 1560                        val);
 1561 
 1562         return (el->currlen++); 
 1563 }
 1564 
 1565 void
 1566 esa_remove_list(struct esa_voice *vc, struct esa_list *el, int index)
 1567 {
 1568         struct esa_softc *sc = (struct esa_softc *)vc->parent;
 1569         u_int16_t val;
 1570         int lastindex = el->currlen - 1;
 1571         int vindex = el->indexmap[index];
 1572         int i;
 1573 
 1574         /* reset our virtual index */
 1575         el->indexmap[index] = -1;
 1576 
 1577         if (vindex != lastindex) {
 1578                 val = esa_read_assp(sc, ESA_MEMTYPE_INTERNAL_DATA,
 1579                                     el->mem_addr + lastindex);
 1580                 esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA,
 1581                                el->mem_addr + vindex,
 1582                                val);
 1583                 for (i = 0; i < ESA_NUM_VOICES * 2; i++)
 1584                         if (el->indexmap[i] == lastindex)
 1585                                 break;
 1586                 if (i >= ESA_NUM_VOICES * 2)
 1587                         printf("%s: esa_remove_list: invalid task index\n",
 1588                                sc->sc_dev.dv_xname);
 1589                 else
 1590                         el->indexmap[i] = vindex;
 1591         }
 1592 
 1593         esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA,
 1594                        el->mem_addr + lastindex, 0);
 1595         el->currlen--;
 1596 
 1597         return;
 1598 }
 1599 
 1600 int
 1601 esa_power(struct esa_softc *sc, int state)
 1602 {
 1603         pcitag_t tag = sc->sc_tag;
 1604         pci_chipset_tag_t pc = sc->sc_pct;
 1605         pcireg_t data;
 1606         int pmcapreg;
 1607 
 1608         if (pci_get_capability(pc, tag, PCI_CAP_PWRMGMT, &pmcapreg, 0)) {
 1609                 data = pci_conf_read(pc, tag, pmcapreg + PCI_PMCSR);
 1610                 if ((data & PCI_PMCSR_STATE_MASK) != state)
 1611                         pci_conf_write(pc, tag, pmcapreg + PCI_PMCSR, state);
 1612         }
 1613                 
 1614         return (0);
 1615 }
 1616 
 1617 void
 1618 esa_powerhook(int why, void *hdl)
 1619 {
 1620         struct esa_softc *sc = (struct esa_softc *)hdl;
 1621 
 1622         switch (why) {
 1623         case PWR_SUSPEND:
 1624         case PWR_STANDBY:
 1625                 esa_suspend(sc);
 1626                 break;
 1627         case PWR_RESUME:
 1628                 esa_resume(sc);
 1629                 (sc->codec_if->vtbl->restore_ports)(sc->codec_if);
 1630                 break;
 1631         }
 1632 }
 1633 
 1634 int
 1635 esa_suspend(struct esa_softc *sc)
 1636 {
 1637         bus_space_tag_t iot = sc->sc_iot;
 1638         bus_space_handle_t ioh = sc->sc_ioh;
 1639         int i, index;
 1640         
 1641         index = 0;
 1642 
 1643         bus_space_write_2(iot, ioh, ESA_HOST_INT_CTRL, 0);
 1644         bus_space_write_1(iot, ioh, ESA_ASSP_CONTROL_C, 0);
 1645 
 1646         esa_assp_halt(sc);
 1647 
 1648         /* Save ASSP state */
 1649         for (i = ESA_REV_B_CODE_MEMORY_BEGIN; i <= ESA_REV_B_CODE_MEMORY_END;
 1650             i++)
 1651                 sc->savemem[index++] = esa_read_assp(sc,
 1652                     ESA_MEMTYPE_INTERNAL_CODE, i);
 1653         for (i = ESA_REV_B_DATA_MEMORY_BEGIN; i <= ESA_REV_B_DATA_MEMORY_END;
 1654             i++)
 1655                 sc->savemem[index++] = esa_read_assp(sc,
 1656                     ESA_MEMTYPE_INTERNAL_DATA, i);
 1657 
 1658         esa_power(sc, PCI_PMCSR_STATE_D3);
 1659 
 1660         return (0);
 1661 }
 1662 
 1663 int
 1664 esa_resume(struct esa_softc *sc) {
 1665         bus_space_tag_t iot = sc->sc_iot;
 1666         bus_space_handle_t ioh = sc->sc_ioh;
 1667         int i, index;
 1668         u_int8_t reset_state;
 1669 
 1670         index = 0;
 1671 
 1672         esa_power(sc, PCI_PMCSR_STATE_D0);
 1673         delay(10000);
 1674 
 1675         esa_config(sc);
 1676 
 1677         reset_state = esa_assp_halt(sc);
 1678 
 1679         esa_codec_reset(sc);
 1680 
 1681         /* restore ASSP */
 1682         for (i = ESA_REV_B_CODE_MEMORY_BEGIN; i <= ESA_REV_B_CODE_MEMORY_END;
 1683             i++)
 1684                 esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_CODE, i,
 1685                     sc->savemem[index++]);
 1686         for (i = ESA_REV_B_DATA_MEMORY_BEGIN; i <= ESA_REV_B_DATA_MEMORY_END;
 1687             i++)
 1688                 esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA, i,
 1689                     sc->savemem[index++]);
 1690 
 1691         esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA, ESA_KDATA_DMA_ACTIVE, 0);
 1692         bus_space_write_1(iot, ioh, ESA_DSP_PORT_CONTROL_REG_B,
 1693             reset_state | ESA_REGB_ENABLE_RESET);
 1694         
 1695         esa_enable_interrupts(sc);
 1696         esa_amp_enable(sc);
 1697 
 1698         return (0);
 1699 }
 1700 
 1701 u_int32_t
 1702 esa_get_pointer(struct esa_softc *sc, struct esa_channel *ch)
 1703 {
 1704         u_int16_t hi = 0, lo = 0;
 1705         u_int32_t addr;
 1706         int data_offset = ch->data_offset;
 1707 
 1708         hi = esa_read_assp(sc, ESA_MEMTYPE_INTERNAL_DATA, data_offset +
 1709             ESA_CDATA_HOST_SRC_CURRENTH);
 1710         lo = esa_read_assp(sc, ESA_MEMTYPE_INTERNAL_DATA, data_offset +
 1711             ESA_CDATA_HOST_SRC_CURRENTL);
 1712 
 1713         addr = lo | ((u_int32_t)hi << 16);
 1714         return (addr - ch->start);
 1715 }
 1716 
 1717 paddr_t
 1718 esa_mappage(void *addr, void *mem, off_t off, int prot)
 1719 {
 1720         struct esa_voice *vc = addr;
 1721         struct esa_softc *sc = (struct esa_softc *)vc->parent;
 1722         struct esa_dma *p;
 1723 
 1724         if (off < 0)
 1725                 return (-1);
 1726         for (p = vc->dma; p && KERNADDR(p) != mem; p = p->next)
 1727                 ;
 1728         if (!p)
 1729                 return (-1);
 1730         return (bus_dmamem_mmap(sc->sc_dmat, p->segs, p->nsegs, 
 1731                                 off, prot, BUS_DMA_WAITOK));
 1732 }

Cache object: 1a627f07feaca3afc11a40b18d7669d3


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.