LCOV - code coverage report
Current view: top level - dev/pci - azalia.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 2008 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 80 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*      $OpenBSD: azalia.c,v 1.244 2018/04/22 10:02:13 ratchov Exp $    */
       2             : /*      $NetBSD: azalia.c,v 1.20 2006/05/07 08:31:44 kent Exp $ */
       3             : 
       4             : /*-
       5             :  * Copyright (c) 2005 The NetBSD Foundation, Inc.
       6             :  * All rights reserved.
       7             :  *
       8             :  * This code is derived from software contributed to The NetBSD Foundation
       9             :  * by TAMURA Kent
      10             :  *
      11             :  * Redistribution and use in source and binary forms, with or without
      12             :  * modification, are permitted provided that the following conditions
      13             :  * are met:
      14             :  * 1. Redistributions of source code must retain the above copyright
      15             :  *    notice, this list of conditions and the following disclaimer.
      16             :  * 2. Redistributions in binary form must reproduce the above copyright
      17             :  *    notice, this list of conditions and the following disclaimer in the
      18             :  *    documentation and/or other materials provided with the distribution.
      19             :  *
      20             :  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
      21             :  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
      22             :  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
      23             :  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
      24             :  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
      25             :  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
      26             :  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
      27             :  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
      28             :  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
      29             :  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
      30             :  * POSSIBILITY OF SUCH DAMAGE.
      31             :  */
      32             : 
      33             : /*
      34             :  * High Definition Audio Specification
      35             :  *
      36             :  * http://www.intel.com/content/dam/www/public/us/en/documents/product-specifications/high-definition-audio-specification.pdf
      37             :  *
      38             :  *
      39             :  * TO DO:
      40             :  *  - multiple codecs (needed?)
      41             :  *  - multiple streams (needed?)
      42             :  */
      43             : 
      44             : #include <sys/param.h>
      45             : #include <sys/fcntl.h>
      46             : #include <sys/device.h>
      47             : #include <sys/malloc.h>
      48             : #include <sys/systm.h>
      49             : #include <sys/timeout.h>
      50             : #include <dev/audio_if.h>
      51             : #include <dev/pci/pcidevs.h>
      52             : #include <dev/pci/pcivar.h>
      53             : 
      54             : #include <dev/pci/azalia.h>
      55             : 
      56             : typedef struct audio_params audio_params_t;
      57             : 
      58             : struct audio_format {
      59             :         void *driver_data;
      60             :         int32_t mode;
      61             :         u_int encoding;
      62             :         u_int precision;
      63             :         u_int channels;
      64             : 
      65             :         /**
      66             :          * 0: frequency[0] is lower limit, and frequency[1] is higher limit.
      67             :          * 1-16: frequency[0] to frequency[frequency_type-1] are valid.
      68             :          */
      69             :         u_int frequency_type;
      70             : 
      71             : #define AUFMT_MAX_FREQUENCIES   16
      72             :         /**
      73             :          * sampling rates
      74             :          */
      75             :         u_int frequency[AUFMT_MAX_FREQUENCIES];
      76             : };
      77             : 
      78             : 
      79             : #ifdef AZALIA_DEBUG
      80             : # define DPRINTFN(n,x)  do { if (az_debug > (n)) printf x; } while (0/*CONSTCOND*/)
      81             : int az_debug = 0;
      82             : #else
      83             : # define DPRINTFN(n,x)  do {} while (0/*CONSTCOND*/)
      84             : #endif
      85             : 
      86             : 
      87             : /* ----------------------------------------------------------------
      88             :  * ICH6/ICH7 constant values
      89             :  * ---------------------------------------------------------------- */
      90             : 
      91             : /* PCI registers */
      92             : #define ICH_PCI_HDBARL  0x10
      93             : #define ICH_PCI_HDBARU  0x14
      94             : #define ICH_PCI_HDCTL   0x40
      95             : #define         ICH_PCI_HDCTL_CLKDETCLR         0x08
      96             : #define         ICH_PCI_HDCTL_CLKDETEN          0x04
      97             : #define         ICH_PCI_HDCTL_CLKDETINV         0x02
      98             : #define         ICH_PCI_HDCTL_SIGNALMODE        0x01
      99             : #define ICH_PCI_HDTCSEL 0x44
     100             : #define         ICH_PCI_HDTCSEL_MASK    0x7
     101             : #define ICH_PCI_MMC     0x62
     102             : #define         ICH_PCI_MMC_ME          0x1
     103             : 
     104             : /* internal types */
     105             : 
     106             : typedef struct {
     107             :         bus_dmamap_t map;
     108             :         caddr_t addr;           /* kernel virtual address */
     109             :         bus_dma_segment_t segments[1];
     110             :         size_t size;
     111             : } azalia_dma_t;
     112             : #define AZALIA_DMA_DMAADDR(p)   ((p)->map->dm_segs[0].ds_addr)
     113             : 
     114             : typedef struct {
     115             :         struct azalia_t *az;
     116             :         int regbase;
     117             :         int number;
     118             :         int dir;                /* AUMODE_PLAY or AUMODE_RECORD */
     119             :         uint32_t intr_bit;
     120             :         azalia_dma_t bdlist;
     121             :         azalia_dma_t buffer;
     122             :         void (*intr)(void*);
     123             :         void *intr_arg;
     124             :         int bufsize;
     125             :         uint16_t fmt;
     126             :         int blk;
     127             :         unsigned int swpos;             /* position in the audio(4) layer */
     128             : } stream_t;
     129             : #define STR_READ_1(s, r)        \
     130             :         bus_space_read_1((s)->az->iot, (s)->az->ioh, (s)->regbase + HDA_SD_##r)
     131             : #define STR_READ_2(s, r)        \
     132             :         bus_space_read_2((s)->az->iot, (s)->az->ioh, (s)->regbase + HDA_SD_##r)
     133             : #define STR_READ_4(s, r)        \
     134             :         bus_space_read_4((s)->az->iot, (s)->az->ioh, (s)->regbase + HDA_SD_##r)
     135             : #define STR_WRITE_1(s, r, v)    \
     136             :         bus_space_write_1((s)->az->iot, (s)->az->ioh, (s)->regbase + HDA_SD_##r, v)
     137             : #define STR_WRITE_2(s, r, v)    \
     138             :         bus_space_write_2((s)->az->iot, (s)->az->ioh, (s)->regbase + HDA_SD_##r, v)
     139             : #define STR_WRITE_4(s, r, v)    \
     140             :         bus_space_write_4((s)->az->iot, (s)->az->ioh, (s)->regbase + HDA_SD_##r, v)
     141             : 
     142             : typedef struct azalia_t {
     143             :         struct device dev;
     144             : 
     145             :         pci_chipset_tag_t pc;
     146             :         pcitag_t tag;
     147             :         void *ih;
     148             :         bus_space_tag_t iot;
     149             :         bus_space_handle_t ioh;
     150             :         bus_size_t map_size;
     151             :         bus_dma_tag_t dmat;
     152             :         pcireg_t pciid;
     153             :         uint32_t subid;
     154             : 
     155             :         codec_t *codecs;
     156             :         int ncodecs;            /* number of codecs */
     157             :         int codecno;            /* index of the using codec */
     158             :         int detached;           /* 1 if failed to initialize, 2 if
     159             :                                  * azalia_pci_detach has run
     160             :                                  */
     161             :         azalia_dma_t corb_dma;
     162             :         int corb_entries;
     163             :         uint8_t corbsize;
     164             :         azalia_dma_t rirb_dma;
     165             :         int rirb_entries;
     166             :         uint8_t rirbsize;
     167             :         int rirb_rp;
     168             : #define UNSOLQ_SIZE     256
     169             :         rirb_entry_t *unsolq;
     170             :         int unsolq_wp;
     171             :         int unsolq_rp;
     172             :         int unsolq_kick;
     173             :         struct timeout unsol_to;
     174             : 
     175             :         int ok64;
     176             :         int nistreams, nostreams, nbstreams;
     177             :         stream_t pstream;
     178             :         stream_t rstream;
     179             : } azalia_t;
     180             : #define XNAME(sc)               ((sc)->dev.dv_xname)
     181             : #define AZ_READ_1(z, r)         bus_space_read_1((z)->iot, (z)->ioh, HDA_##r)
     182             : #define AZ_READ_2(z, r)         bus_space_read_2((z)->iot, (z)->ioh, HDA_##r)
     183             : #define AZ_READ_4(z, r)         bus_space_read_4((z)->iot, (z)->ioh, HDA_##r)
     184             : #define AZ_WRITE_1(z, r, v)     bus_space_write_1((z)->iot, (z)->ioh, HDA_##r, v)
     185             : #define AZ_WRITE_2(z, r, v)     bus_space_write_2((z)->iot, (z)->ioh, HDA_##r, v)
     186             : #define AZ_WRITE_4(z, r, v)     bus_space_write_4((z)->iot, (z)->ioh, HDA_##r, v)
     187             : 
     188             : 
     189             : /* prototypes */
     190             : uint8_t azalia_pci_read(pci_chipset_tag_t, pcitag_t, int);
     191             : void    azalia_pci_write(pci_chipset_tag_t, pcitag_t, int, uint8_t);
     192             : int     azalia_pci_match(struct device *, void *, void *);
     193             : void    azalia_pci_attach(struct device *, struct device *, void *);
     194             : int     azalia_pci_activate(struct device *, int);
     195             : int     azalia_pci_detach(struct device *, int);
     196             : void    azalia_configure_pci(azalia_t *);
     197             : int     azalia_intr(void *);
     198             : void    azalia_print_codec(codec_t *);
     199             : int     azalia_reset(azalia_t *);
     200             : int     azalia_get_ctrlr_caps(azalia_t *);
     201             : int     azalia_init(azalia_t *, int);
     202             : int     azalia_init_codecs(azalia_t *);
     203             : int     azalia_init_streams(azalia_t *);
     204             : void    azalia_shutdown(void *);
     205             : int     azalia_halt_corb(azalia_t *);
     206             : int     azalia_init_corb(azalia_t *, int);
     207             : int     azalia_halt_rirb(azalia_t *);
     208             : int     azalia_init_rirb(azalia_t *, int);
     209             : int     azalia_set_command(azalia_t *, nid_t, int, uint32_t, uint32_t);
     210             : int     azalia_get_response(azalia_t *, uint32_t *);
     211             : void    azalia_rirb_kick_unsol_events(void *);
     212             : void    azalia_rirb_intr(azalia_t *);
     213             : int     azalia_alloc_dmamem(azalia_t *, size_t, size_t, azalia_dma_t *);
     214             : void    azalia_free_dmamem(const azalia_t *, azalia_dma_t*);
     215             : 
     216             : int     azalia_codec_init(codec_t *);
     217             : int     azalia_codec_delete(codec_t *);
     218             : void    azalia_codec_add_bits(codec_t *, int, uint32_t, int);
     219             : void    azalia_codec_add_format(codec_t *, int, int, uint32_t, int32_t);
     220             : int     azalia_codec_connect_stream(stream_t *);
     221             : int     azalia_codec_disconnect_stream(stream_t *);
     222             : void    azalia_codec_print_audiofunc(const codec_t *);
     223             : void    azalia_codec_print_groups(const codec_t *);
     224             : int     azalia_codec_find_defdac(codec_t *, int, int);
     225             : int     azalia_codec_find_defadc(codec_t *, int, int);
     226             : int     azalia_codec_find_defadc_sub(codec_t *, nid_t, int, int);
     227             : int     azalia_codec_init_volgroups(codec_t *);
     228             : int     azalia_codec_sort_pins(codec_t *);
     229             : int     azalia_codec_select_micadc(codec_t *);
     230             : int     azalia_codec_select_dacs(codec_t *);
     231             : int     azalia_codec_select_spkrdac(codec_t *);
     232             : int     azalia_codec_find_inputmixer(codec_t *);
     233             : 
     234             : int     azalia_widget_init(widget_t *, const codec_t *, int);
     235             : int     azalia_widget_label_widgets(codec_t *);
     236             : int     azalia_widget_init_audio(widget_t *, const codec_t *);
     237             : int     azalia_widget_init_pin(widget_t *, const codec_t *);
     238             : int     azalia_widget_init_connection(widget_t *, const codec_t *);
     239             : int     azalia_widget_check_conn(codec_t *, int, int);
     240             : int     azalia_widget_sole_conn(codec_t *, nid_t);
     241             : void    azalia_widget_print_widget(const widget_t *, const codec_t *);
     242             : void    azalia_widget_print_audio(const widget_t *, const char *);
     243             : void    azalia_widget_print_pin(const widget_t *);
     244             : 
     245             : int     azalia_stream_init(stream_t *, azalia_t *, int, int, int);
     246             : int     azalia_stream_reset(stream_t *);
     247             : int     azalia_stream_start(stream_t *);
     248             : int     azalia_stream_halt(stream_t *);
     249             : int     azalia_stream_intr(stream_t *);
     250             : 
     251             : int     azalia_open(void *, int);
     252             : void    azalia_close(void *);
     253             : int     azalia_set_params(void *, int, int, audio_params_t *,
     254             :         audio_params_t *);
     255             : int     azalia_round_blocksize(void *, int);
     256             : int     azalia_halt_output(void *);
     257             : int     azalia_halt_input(void *);
     258             : int     azalia_set_port(void *, mixer_ctrl_t *);
     259             : int     azalia_get_port(void *, mixer_ctrl_t *);
     260             : int     azalia_query_devinfo(void *, mixer_devinfo_t *);
     261             : void    *azalia_allocm(void *, int, size_t, int, int);
     262             : void    azalia_freem(void *, void *, int);
     263             : size_t  azalia_round_buffersize(void *, int, size_t);
     264             : int     azalia_get_props(void *);
     265             : int     azalia_trigger_output(void *, void *, void *, int,
     266             :         void (*)(void *), void *, audio_params_t *);
     267             : int     azalia_trigger_input(void *, void *, void *, int,
     268             :         void (*)(void *), void *, audio_params_t *);
     269             : 
     270             : int     azalia_params2fmt(const audio_params_t *, uint16_t *);
     271             : 
     272             : int     azalia_match_format(codec_t *, int, audio_params_t *);
     273             : int     azalia_set_params_sub(codec_t *, int, audio_params_t *);
     274             : 
     275             : int     azalia_suspend(azalia_t *);
     276             : int     azalia_resume(azalia_t *);
     277             : int     azalia_resume_codec(codec_t *);
     278             : 
     279             : /* variables */
     280             : struct cfattach azalia_ca = {
     281             :         sizeof(azalia_t), azalia_pci_match, azalia_pci_attach,
     282             :         azalia_pci_detach, azalia_pci_activate
     283             : };
     284             : 
     285             : struct cfdriver azalia_cd = {
     286             :         NULL, "azalia", DV_DULL
     287             : };
     288             : 
     289             : struct audio_hw_if azalia_hw_if = {
     290             :         azalia_open,
     291             :         azalia_close,
     292             :         azalia_set_params,
     293             :         azalia_round_blocksize,
     294             :         NULL,                   /* commit_settings */
     295             :         NULL,                   /* init_output */
     296             :         NULL,                   /* init_input */
     297             :         NULL,                   /* start_output */
     298             :         NULL,                   /* start_input */
     299             :         azalia_halt_output,
     300             :         azalia_halt_input,
     301             :         NULL,                   /* speaker_ctl */
     302             :         NULL,                   /* setfd */
     303             :         azalia_set_port,
     304             :         azalia_get_port,
     305             :         azalia_query_devinfo,
     306             :         azalia_allocm,
     307             :         azalia_freem,
     308             :         azalia_round_buffersize,
     309             :         azalia_get_props,
     310             :         azalia_trigger_output,
     311             :         azalia_trigger_input
     312             : };
     313             : 
     314             : static const char *pin_devices[16] = {
     315             :         AudioNline, AudioNspeaker, AudioNheadphone, AudioNcd,
     316             :         "SPDIF", "digital-out", "modem-line", "modem-handset",
     317             :         "line-in", AudioNaux, AudioNmicrophone, "telephony",
     318             :         "SPDIF-in", "digital-in", "beep", "other"};
     319             : static const char *wtypes[16] = {
     320             :         "dac", "adc", "mix", "sel", "pin", "pow", "volume",
     321             :         "beep", "wid08", "wid09", "wid0a", "wid0b", "wid0c",
     322             :         "wid0d", "wid0e", "vendor"};
     323             : static const char *line_colors[16] = {
     324             :         "unk", "blk", "gry", "blu", "grn", "red", "org", "yel",
     325             :         "pur", "pnk", "0xa", "0xb", "0xc", "0xd", "wht", "oth"};
     326             : 
     327             : /* ================================================================
     328             :  * PCI functions
     329             :  * ================================================================ */
     330             : 
     331             : #define ATI_PCIE_SNOOP_REG              0x42
     332             : #define ATI_PCIE_SNOOP_MASK             0xf8
     333             : #define ATI_PCIE_SNOOP_ENABLE           0x02
     334             : #define NVIDIA_PCIE_SNOOP_REG           0x4e
     335             : #define NVIDIA_PCIE_SNOOP_MASK          0xf0
     336             : #define NVIDIA_PCIE_SNOOP_ENABLE        0x0f
     337             : #define NVIDIA_HDA_ISTR_COH_REG         0x4d
     338             : #define NVIDIA_HDA_OSTR_COH_REG         0x4c
     339             : #define NVIDIA_HDA_STR_COH_ENABLE       0x01
     340             : #define INTEL_PCIE_NOSNOOP_REG          0x79
     341             : #define INTEL_PCIE_NOSNOOP_MASK         0xf7
     342             : #define INTEL_PCIE_NOSNOOP_ENABLE       0x08
     343             : 
     344             : uint8_t
     345           0 : azalia_pci_read(pci_chipset_tag_t pc, pcitag_t pa, int reg)
     346             : {
     347           0 :         return (pci_conf_read(pc, pa, (reg & ~0x03)) >>
     348           0 :             ((reg & 0x03) * 8) & 0xff);
     349             : }
     350             : 
     351             : void
     352           0 : azalia_pci_write(pci_chipset_tag_t pc, pcitag_t pa, int reg, uint8_t val)
     353             : {
     354             :         pcireg_t pcival;
     355             : 
     356           0 :         pcival = pci_conf_read(pc, pa, (reg & ~0x03));
     357           0 :         pcival &= ~(0xff << ((reg & 0x03) * 8));
     358           0 :         pcival |= (val << ((reg & 0x03) * 8));
     359           0 :         pci_conf_write(pc, pa, (reg & ~0x03), pcival);
     360           0 : }
     361             : 
     362             : void
     363           0 : azalia_configure_pci(azalia_t *az)
     364             : {
     365             :         pcireg_t v;
     366             :         uint8_t reg;
     367             : 
     368             :         /* enable back-to-back */
     369           0 :         v = pci_conf_read(az->pc, az->tag, PCI_COMMAND_STATUS_REG);
     370           0 :         pci_conf_write(az->pc, az->tag, PCI_COMMAND_STATUS_REG,
     371           0 :             v | PCI_COMMAND_BACKTOBACK_ENABLE);
     372             : 
     373             :         /* traffic class select */
     374           0 :         v = pci_conf_read(az->pc, az->tag, ICH_PCI_HDTCSEL);
     375           0 :         pci_conf_write(az->pc, az->tag, ICH_PCI_HDTCSEL,
     376           0 :             v & ~(ICH_PCI_HDTCSEL_MASK));
     377             : 
     378             :         /* enable PCIe snoop */
     379           0 :         switch (PCI_PRODUCT(az->pciid)) {
     380             :         case PCI_PRODUCT_ATI_SB450_HDA:
     381             :         case PCI_PRODUCT_ATI_SBX00_HDA:
     382             :         case PCI_PRODUCT_AMD_HUDSON2_HDA:
     383           0 :                 reg = azalia_pci_read(az->pc, az->tag, ATI_PCIE_SNOOP_REG);
     384           0 :                 reg &= ATI_PCIE_SNOOP_MASK;
     385           0 :                 reg |= ATI_PCIE_SNOOP_ENABLE;
     386           0 :                 azalia_pci_write(az->pc, az->tag, ATI_PCIE_SNOOP_REG, reg);
     387           0 :                 break;
     388             :         case PCI_PRODUCT_NVIDIA_MCP51_HDA:
     389             :         case PCI_PRODUCT_NVIDIA_MCP55_HDA:
     390             :         case PCI_PRODUCT_NVIDIA_MCP61_HDA_1:
     391             :         case PCI_PRODUCT_NVIDIA_MCP61_HDA_2:
     392             :         case PCI_PRODUCT_NVIDIA_MCP65_HDA_1:
     393             :         case PCI_PRODUCT_NVIDIA_MCP65_HDA_2:
     394             :         case PCI_PRODUCT_NVIDIA_MCP67_HDA_1:
     395             :         case PCI_PRODUCT_NVIDIA_MCP67_HDA_2:
     396             :         case PCI_PRODUCT_NVIDIA_MCP73_HDA_1:
     397             :         case PCI_PRODUCT_NVIDIA_MCP73_HDA_2:
     398             :         case PCI_PRODUCT_NVIDIA_MCP77_HDA_1:
     399             :         case PCI_PRODUCT_NVIDIA_MCP77_HDA_2:
     400             :         case PCI_PRODUCT_NVIDIA_MCP77_HDA_3:
     401             :         case PCI_PRODUCT_NVIDIA_MCP77_HDA_4:
     402             :         case PCI_PRODUCT_NVIDIA_MCP79_HDA_1:
     403             :         case PCI_PRODUCT_NVIDIA_MCP79_HDA_2:
     404             :         case PCI_PRODUCT_NVIDIA_MCP79_HDA_3:
     405             :         case PCI_PRODUCT_NVIDIA_MCP79_HDA_4:
     406             :         case PCI_PRODUCT_NVIDIA_MCP89_HDA_1:
     407             :         case PCI_PRODUCT_NVIDIA_MCP89_HDA_2:
     408             :         case PCI_PRODUCT_NVIDIA_MCP89_HDA_3:
     409             :         case PCI_PRODUCT_NVIDIA_MCP89_HDA_4:
     410           0 :                 reg = azalia_pci_read(az->pc, az->tag,
     411             :                     NVIDIA_HDA_OSTR_COH_REG);
     412           0 :                 reg |= NVIDIA_HDA_STR_COH_ENABLE;
     413           0 :                 azalia_pci_write(az->pc, az->tag,
     414             :                     NVIDIA_HDA_OSTR_COH_REG, reg);
     415             : 
     416           0 :                 reg = azalia_pci_read(az->pc, az->tag,
     417             :                     NVIDIA_HDA_ISTR_COH_REG);
     418           0 :                 reg |= NVIDIA_HDA_STR_COH_ENABLE;
     419           0 :                 azalia_pci_write(az->pc, az->tag,
     420             :                     NVIDIA_HDA_ISTR_COH_REG, reg);
     421             : 
     422           0 :                 reg = azalia_pci_read(az->pc, az->tag,
     423             :                     NVIDIA_PCIE_SNOOP_REG);
     424           0 :                 reg &= NVIDIA_PCIE_SNOOP_MASK;
     425           0 :                 reg |= NVIDIA_PCIE_SNOOP_ENABLE;
     426           0 :                 azalia_pci_write(az->pc, az->tag,
     427             :                     NVIDIA_PCIE_SNOOP_REG, reg);
     428             : 
     429           0 :                 reg = azalia_pci_read(az->pc, az->tag,
     430             :                     NVIDIA_PCIE_SNOOP_REG);
     431           0 :                 if ((reg & NVIDIA_PCIE_SNOOP_ENABLE) !=
     432             :                     NVIDIA_PCIE_SNOOP_ENABLE) {
     433           0 :                         printf(": could not enable PCIe cache snooping!\n");
     434           0 :                 }
     435             :                 break;
     436             :         case PCI_PRODUCT_INTEL_82801FB_HDA:
     437             :         case PCI_PRODUCT_INTEL_82801GB_HDA:
     438             :         case PCI_PRODUCT_INTEL_82801H_HDA:
     439             :         case PCI_PRODUCT_INTEL_82801I_HDA:
     440             :         case PCI_PRODUCT_INTEL_82801JI_HDA:
     441             :         case PCI_PRODUCT_INTEL_82801JD_HDA:
     442             :         case PCI_PRODUCT_INTEL_6321ESB_HDA:
     443             :         case PCI_PRODUCT_INTEL_3400_HDA:
     444             :         case PCI_PRODUCT_INTEL_QS57_HDA:
     445             :         case PCI_PRODUCT_INTEL_6SERIES_HDA:
     446             :         case PCI_PRODUCT_INTEL_7SERIES_HDA:
     447             :         case PCI_PRODUCT_INTEL_8SERIES_HDA:
     448             :         case PCI_PRODUCT_INTEL_8SERIES_LP_HDA:
     449             :         case PCI_PRODUCT_INTEL_9SERIES_HDA:
     450             :         case PCI_PRODUCT_INTEL_9SERIES_LP_HDA:
     451             :         case PCI_PRODUCT_INTEL_BAYTRAIL_HDA:
     452             :         case PCI_PRODUCT_INTEL_100SERIES_HDA:
     453             :         case PCI_PRODUCT_INTEL_100SERIES_LP_HDA:
     454             :         case PCI_PRODUCT_INTEL_200SERIES_HDA:
     455             :         case PCI_PRODUCT_INTEL_200SERIES_U_HDA:
     456             :         case PCI_PRODUCT_INTEL_C600_HDA:
     457             :         case PCI_PRODUCT_INTEL_C610_HDA:
     458             :         case PCI_PRODUCT_INTEL_BSW_HDA:
     459             :         case PCI_PRODUCT_INTEL_APOLLOLAKE_HDA:
     460           0 :                 reg = azalia_pci_read(az->pc, az->tag,
     461             :                     INTEL_PCIE_NOSNOOP_REG);
     462           0 :                 reg &= INTEL_PCIE_NOSNOOP_MASK;
     463           0 :                 azalia_pci_write(az->pc, az->tag,
     464             :                     INTEL_PCIE_NOSNOOP_REG, reg);
     465           0 :                 break;
     466             :         }
     467           0 : }
     468             : 
     469             : int
     470           0 : azalia_pci_match(struct device *parent, void *match, void *aux)
     471             : {
     472             :         struct pci_attach_args *pa;
     473             : 
     474           0 :         pa = aux;
     475           0 :         if (PCI_CLASS(pa->pa_class) == PCI_CLASS_MULTIMEDIA
     476           0 :             && PCI_SUBCLASS(pa->pa_class) == PCI_SUBCLASS_MULTIMEDIA_HDAUDIO)
     477           0 :                 return 1;
     478           0 :         return 0;
     479           0 : }
     480             : 
     481             : void
     482           0 : azalia_pci_attach(struct device *parent, struct device *self, void *aux)
     483             : {
     484             :         azalia_t *sc;
     485             :         struct pci_attach_args *pa;
     486             :         pcireg_t v;
     487             :         uint8_t reg;
     488           0 :         pci_intr_handle_t ih;
     489             :         const char *interrupt_str;
     490             : 
     491           0 :         sc = (azalia_t*)self;
     492           0 :         pa = aux;
     493             : 
     494           0 :         sc->dmat = pa->pa_dmat;
     495             : 
     496           0 :         pci_set_powerstate(pa->pa_pc, pa->pa_tag, PCI_PMCSR_STATE_D0);
     497             : 
     498           0 :         v = pci_conf_read(pa->pa_pc, pa->pa_tag, ICH_PCI_HDBARL);
     499           0 :         v &= PCI_MAPREG_TYPE_MASK | PCI_MAPREG_MEM_TYPE_MASK;
     500           0 :         if (pci_mapreg_map(pa, ICH_PCI_HDBARL, v, 0,
     501           0 :                            &sc->iot, &sc->ioh, NULL, &sc->map_size, 0)) {
     502           0 :                 printf(": can't map device i/o space\n");
     503           0 :                 return;
     504             :         }
     505             : 
     506           0 :         sc->pc = pa->pa_pc;
     507           0 :         sc->tag = pa->pa_tag;
     508           0 :         sc->pciid = pa->pa_id;
     509           0 :         sc->subid = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_SUBSYS_ID_REG);
     510             : 
     511           0 :         azalia_configure_pci(sc);
     512             : 
     513             :         /* disable MSI, use INTx instead */
     514           0 :         if (PCI_VENDOR(sc->pciid) == PCI_VENDOR_INTEL) {
     515           0 :                 reg = azalia_pci_read(sc->pc, sc->tag, ICH_PCI_MMC);
     516           0 :                 reg &= ~(ICH_PCI_MMC_ME);
     517           0 :                 azalia_pci_write(sc->pc, sc->tag, ICH_PCI_MMC, reg);
     518           0 :         }
     519             : 
     520             :         /* interrupt */
     521           0 :         if (pci_intr_map_msi(pa, &ih) && pci_intr_map(pa, &ih)) {
     522           0 :                 printf(": can't map interrupt\n");
     523           0 :                 return;
     524             :         }
     525           0 :         interrupt_str = pci_intr_string(pa->pa_pc, ih);
     526           0 :         sc->ih = pci_intr_establish(pa->pa_pc, ih, IPL_AUDIO | IPL_MPSAFE,
     527           0 :             azalia_intr, sc, sc->dev.dv_xname);
     528           0 :         if (sc->ih == NULL) {
     529           0 :                 printf(": can't establish interrupt");
     530           0 :                 if (interrupt_str != NULL)
     531           0 :                         printf(" at %s", interrupt_str);
     532           0 :                 printf("\n");
     533           0 :                 return;
     534             :         }
     535           0 :         printf(": %s\n", interrupt_str);
     536             : 
     537           0 :         if (azalia_init(sc, 0))
     538             :                 goto err_exit;
     539             : 
     540           0 :         if (azalia_init_codecs(sc))
     541             :                 goto err_exit;
     542             : 
     543           0 :         if (azalia_init_streams(sc))
     544             :                 goto err_exit;
     545             : 
     546           0 :         audio_attach_mi(&azalia_hw_if, sc, &sc->dev);
     547             : 
     548           0 :         return;
     549             : 
     550             : err_exit:
     551           0 :         sc->detached = 1;
     552           0 :         azalia_pci_detach(self, 0);
     553           0 : }
     554             : 
     555             : int
     556           0 : azalia_pci_activate(struct device *self, int act)
     557             : {
     558           0 :         azalia_t *sc = (azalia_t*)self;
     559             :         int rv = 0; 
     560             : 
     561           0 :         switch (act) {
     562             :         case DVACT_SUSPEND:
     563           0 :                 azalia_suspend(sc);
     564           0 :                 break;
     565             :         case DVACT_POWERDOWN:
     566           0 :                 azalia_shutdown(sc);
     567           0 :                 break;
     568             :         case DVACT_RESUME:
     569           0 :                 azalia_resume(sc);
     570           0 :                 rv = config_activate_children(self, act);
     571           0 :                 break;
     572             :         default:
     573           0 :                 rv = config_activate_children(self, act);
     574           0 :                 break;
     575             :         }
     576           0 :         return (rv);
     577             : }
     578             : 
     579             : int
     580           0 : azalia_pci_detach(struct device *self, int flags)
     581             : {
     582           0 :         azalia_t *az = (azalia_t*)self;
     583             :         uint32_t gctl;
     584             :         int i;
     585             : 
     586             :         DPRINTF(("%s\n", __func__));
     587             : 
     588             :         /*
     589             :          * this function is called if the device could not be supported,
     590             :          * in which case az->detached == 1.  check if this function has
     591             :          * already cleaned up.
     592             :          */
     593           0 :         if (az->detached > 1)
     594           0 :                 return 0;
     595             : 
     596           0 :         config_detach_children(self, flags);
     597             : 
     598             :         /* disable unsolicited responses if soft detaching */
     599           0 :         if (az->detached == 1) {
     600           0 :                 gctl = AZ_READ_4(az, GCTL);
     601           0 :                 AZ_WRITE_4(az, GCTL, gctl &~(HDA_GCTL_UNSOL));
     602           0 :         }
     603             : 
     604           0 :         timeout_del(&az->unsol_to);
     605             : 
     606             :         DPRINTF(("%s: delete streams\n", __func__));
     607           0 :         if (az->rstream.bdlist.addr != NULL)
     608           0 :                 azalia_free_dmamem(az, &az->rstream.bdlist);
     609           0 :         if (az->pstream.bdlist.addr != NULL)
     610           0 :                 azalia_free_dmamem(az, &az->pstream.bdlist);
     611             : 
     612             :         DPRINTF(("%s: delete codecs\n", __func__));
     613           0 :         for (i = 0; i < az->ncodecs; i++) {
     614           0 :                 azalia_codec_delete(&az->codecs[i]);
     615             :         }
     616           0 :         az->ncodecs = 0;
     617           0 :         if (az->codecs != NULL) {
     618           0 :                 free(az->codecs, M_DEVBUF, 0);
     619           0 :                 az->codecs = NULL;
     620           0 :         }
     621             : 
     622             :         DPRINTF(("%s: delete CORB and RIRB\n", __func__));
     623           0 :         if (az->corb_dma.addr != NULL)
     624           0 :                 azalia_free_dmamem(az, &az->corb_dma);
     625           0 :         if (az->rirb_dma.addr != NULL)
     626           0 :                 azalia_free_dmamem(az, &az->rirb_dma);
     627           0 :         if (az->unsolq != NULL) {
     628           0 :                 free(az->unsolq, M_DEVBUF, 0);
     629           0 :                 az->unsolq = NULL;
     630           0 :         }
     631             : 
     632             :         /* disable interrupts if soft detaching */
     633           0 :         if (az->detached == 1) {
     634             :                 DPRINTF(("%s: disable interrupts\n", __func__));
     635           0 :                 AZ_WRITE_4(az, INTCTL, 0);
     636             : 
     637             :                 DPRINTF(("%s: clear interrupts\n", __func__));
     638           0 :                 AZ_WRITE_4(az, INTSTS, HDA_INTSTS_CIS | HDA_INTSTS_GIS);
     639           0 :                 AZ_WRITE_2(az, STATESTS, HDA_STATESTS_SDIWAKE);
     640           0 :                 AZ_WRITE_1(az, RIRBSTS, HDA_RIRBSTS_RINTFL | HDA_RIRBSTS_RIRBOIS);
     641           0 :         }
     642             : 
     643             :         DPRINTF(("%s: delete PCI resources\n", __func__));
     644           0 :         if (az->ih != NULL) {
     645           0 :                 pci_intr_disestablish(az->pc, az->ih);
     646           0 :                 az->ih = NULL;
     647           0 :         }
     648           0 :         if (az->map_size != 0) {
     649           0 :                 bus_space_unmap(az->iot, az->ioh, az->map_size);
     650           0 :                 az->map_size = 0;
     651           0 :         }
     652             : 
     653           0 :         az->detached = 2;
     654           0 :         return 0;
     655           0 : }
     656             : 
     657             : int
     658           0 : azalia_intr(void *v)
     659             : {
     660           0 :         azalia_t *az = v;
     661             :         uint32_t intsts;
     662             :         int ret = 0;
     663             : 
     664           0 :         mtx_enter(&audio_lock);
     665           0 :         intsts = AZ_READ_4(az, INTSTS);
     666           0 :         if (intsts == 0 || intsts == 0xffffffff) {
     667           0 :                 mtx_leave(&audio_lock);
     668           0 :                 return (ret);
     669             :         }
     670             : 
     671           0 :         AZ_WRITE_4(az, INTSTS, intsts);
     672             : 
     673           0 :         if (intsts & az->pstream.intr_bit) {
     674           0 :                 azalia_stream_intr(&az->pstream);
     675             :                 ret = 1;
     676           0 :         }
     677             : 
     678           0 :         if (intsts & az->rstream.intr_bit) {
     679           0 :                 azalia_stream_intr(&az->rstream);
     680             :                 ret = 1;
     681           0 :         }
     682             : 
     683           0 :         if ((intsts & HDA_INTSTS_CIS) &&
     684           0 :             (AZ_READ_1(az, RIRBCTL) & HDA_RIRBCTL_RINTCTL) &&
     685           0 :             (AZ_READ_1(az, RIRBSTS) & HDA_RIRBSTS_RINTFL)) {
     686           0 :                 azalia_rirb_intr(az);
     687             :                 ret = 1;
     688           0 :         }
     689           0 :         mtx_leave(&audio_lock);
     690           0 :         return (ret);
     691           0 : }
     692             : 
     693             : void
     694           0 : azalia_shutdown(void *v)
     695             : {
     696           0 :         azalia_t *az = (azalia_t *)v;
     697             :         uint32_t gctl;
     698             : 
     699             :         /* disable unsolicited response */
     700           0 :         gctl = AZ_READ_4(az, GCTL);
     701           0 :         AZ_WRITE_4(az, GCTL, gctl & ~(HDA_GCTL_UNSOL));
     702             : 
     703           0 :         timeout_del(&az->unsol_to);
     704             : 
     705             :         /* halt CORB/RIRB */
     706           0 :         azalia_halt_corb(az);
     707           0 :         azalia_halt_rirb(az);
     708           0 : }
     709             : 
     710             : /* ================================================================
     711             :  * HDA controller functions
     712             :  * ================================================================ */
     713             : 
     714             : void
     715           0 : azalia_print_codec(codec_t *codec)
     716             : {
     717             :         const char *vendor;
     718             : 
     719           0 :         if (codec->name == NULL) {
     720           0 :                 vendor = pci_findvendor(codec->vid >> 16);
     721           0 :                 if (vendor == NULL)
     722           0 :                         printf("0x%04x/0x%04x",
     723           0 :                             codec->vid >> 16, codec->vid & 0xffff);
     724             :                 else
     725           0 :                         printf("%s/0x%04x", vendor, codec->vid & 0xffff);
     726             :         } else
     727           0 :                 printf("%s", codec->name);
     728           0 : }
     729             : 
     730             : int
     731           0 : azalia_reset(azalia_t *az)
     732             : {
     733             :         uint32_t gctl;
     734             :         int i;
     735             : 
     736             :         /* 4.2.2 Starting the High Definition Audio Controller */
     737             :         DPRINTF(("%s: resetting\n", __func__));
     738           0 :         gctl = AZ_READ_4(az, GCTL);
     739           0 :         AZ_WRITE_4(az, GCTL, gctl & ~HDA_GCTL_CRST);
     740           0 :         for (i = 5000; i > 0; i--) {
     741           0 :                 DELAY(10);
     742           0 :                 if ((AZ_READ_4(az, GCTL) & HDA_GCTL_CRST) == 0)
     743             :                         break;
     744             :         }
     745             :         DPRINTF(("%s: reset counter = %d\n", __func__, i));
     746           0 :         if (i == 0) {
     747             :                 DPRINTF(("%s: reset failure\n", XNAME(az)));
     748           0 :                 return(ETIMEDOUT);
     749             :         }
     750           0 :         DELAY(1000);
     751           0 :         gctl = AZ_READ_4(az, GCTL);
     752           0 :         AZ_WRITE_4(az, GCTL, gctl | HDA_GCTL_CRST);
     753           0 :         for (i = 5000; i > 0; i--) {
     754           0 :                 DELAY(10);
     755           0 :                 if (AZ_READ_4(az, GCTL) & HDA_GCTL_CRST)
     756             :                         break;
     757             :         }
     758             :         DPRINTF(("%s: reset counter = %d\n", __func__, i));
     759           0 :         if (i == 0) {
     760             :                 DPRINTF(("%s: reset-exit failure\n", XNAME(az)));
     761           0 :                 return(ETIMEDOUT);
     762             :         }
     763           0 :         DELAY(1000);
     764             : 
     765           0 :         return(0);
     766           0 : }
     767             : 
     768             : int
     769           0 : azalia_get_ctrlr_caps(azalia_t *az)
     770             : {
     771             :         int i, n;
     772             :         uint16_t gcap;
     773             :         uint16_t statests;
     774             :         uint8_t cap;
     775             : 
     776             :         DPRINTF(("%s: host: High Definition Audio rev. %d.%d\n",
     777             :             XNAME(az), AZ_READ_1(az, VMAJ), AZ_READ_1(az, VMIN)));
     778           0 :         gcap = AZ_READ_2(az, GCAP);
     779           0 :         az->nistreams = HDA_GCAP_ISS(gcap);
     780           0 :         az->nostreams = HDA_GCAP_OSS(gcap);
     781           0 :         az->nbstreams = HDA_GCAP_BSS(gcap);
     782           0 :         az->ok64 = (gcap & HDA_GCAP_64OK) != 0;
     783             :         DPRINTF(("%s: host: %d output, %d input, and %d bidi streams\n",
     784             :             XNAME(az), az->nostreams, az->nistreams, az->nbstreams));
     785             : 
     786             :         /* 4.3 Codec discovery */
     787           0 :         statests = AZ_READ_2(az, STATESTS);
     788           0 :         for (i = 0, n = 0; i < HDA_MAX_CODECS; i++) {
     789           0 :                 if ((statests >> i) & 1) {
     790             :                         DPRINTF(("%s: found a codec at #%d\n", XNAME(az), i));
     791           0 :                         n++;
     792           0 :                 }
     793             :         }
     794           0 :         az->ncodecs = n;
     795           0 :         if (az->ncodecs < 1) {
     796           0 :                 printf("%s: no HD-Audio codecs\n", XNAME(az));
     797           0 :                 return -1;
     798             :         }
     799           0 :         az->codecs = mallocarray(az->ncodecs, sizeof(codec_t), M_DEVBUF,
     800             :             M_NOWAIT | M_ZERO);
     801           0 :         if (az->codecs == NULL) {
     802           0 :                 printf("%s: can't allocate memory for codecs\n", XNAME(az));
     803           0 :                 return ENOMEM;
     804             :         }
     805           0 :         for (i = 0, n = 0; n < az->ncodecs; i++) {
     806           0 :                 if ((statests >> i) & 1) {
     807           0 :                         az->codecs[n].address = i;
     808           0 :                         az->codecs[n++].az = az;
     809           0 :                 }
     810             :         }
     811             : 
     812             :         /* determine CORB size */
     813           0 :         az->corbsize = AZ_READ_1(az, CORBSIZE);
     814           0 :         cap = az->corbsize & HDA_CORBSIZE_CORBSZCAP_MASK;
     815           0 :         az->corbsize  &= ~HDA_CORBSIZE_CORBSIZE_MASK;
     816           0 :         if (cap & HDA_CORBSIZE_CORBSZCAP_256) {
     817           0 :                 az->corb_entries = 256;
     818           0 :                 az->corbsize |= HDA_CORBSIZE_CORBSIZE_256;
     819           0 :         } else if (cap & HDA_CORBSIZE_CORBSZCAP_16) {
     820           0 :                 az->corb_entries = 16;
     821           0 :                 az->corbsize |= HDA_CORBSIZE_CORBSIZE_16;
     822           0 :         } else if (cap & HDA_CORBSIZE_CORBSZCAP_2) {
     823           0 :                 az->corb_entries = 2;
     824           0 :                 az->corbsize |= HDA_CORBSIZE_CORBSIZE_2;
     825             :         } else {
     826           0 :                 printf("%s: invalid CORBSZCAP: 0x%2x\n", XNAME(az), cap);
     827           0 :                 return(-1);
     828             :         }
     829             : 
     830             :         /* determine RIRB size */
     831           0 :         az->rirbsize = AZ_READ_1(az, RIRBSIZE);
     832           0 :         cap = az->rirbsize & HDA_RIRBSIZE_RIRBSZCAP_MASK;
     833           0 :         az->rirbsize &= ~HDA_RIRBSIZE_RIRBSIZE_MASK;
     834           0 :         if (cap & HDA_RIRBSIZE_RIRBSZCAP_256) {
     835           0 :                 az->rirb_entries = 256;
     836           0 :                 az->rirbsize |= HDA_RIRBSIZE_RIRBSIZE_256;
     837           0 :         } else if (cap & HDA_RIRBSIZE_RIRBSZCAP_16) {
     838           0 :                 az->rirb_entries = 16;
     839           0 :                 az->rirbsize |= HDA_RIRBSIZE_RIRBSIZE_16;
     840           0 :         } else if (cap & HDA_RIRBSIZE_RIRBSZCAP_2) {
     841           0 :                 az->rirb_entries = 2;
     842           0 :                 az->rirbsize |= HDA_RIRBSIZE_RIRBSIZE_2;
     843             :         } else {
     844           0 :                 printf("%s: invalid RIRBSZCAP: 0x%2x\n", XNAME(az), cap);
     845           0 :                 return(-1);
     846             :         }
     847             : 
     848           0 :         return(0);
     849           0 : }
     850             : 
     851             : int
     852           0 : azalia_init(azalia_t *az, int resuming)
     853             : {
     854             :         int err;
     855             : 
     856           0 :         err = azalia_reset(az);
     857           0 :         if (err)
     858           0 :                 return(err);
     859             : 
     860           0 :         if (!resuming) {
     861           0 :                 err = azalia_get_ctrlr_caps(az);
     862           0 :                 if (err)
     863           0 :                         return(err);
     864             :         }
     865             : 
     866             :         /* clear interrupt status */
     867           0 :         AZ_WRITE_2(az, STATESTS, HDA_STATESTS_SDIWAKE);
     868           0 :         AZ_WRITE_1(az, RIRBSTS, HDA_RIRBSTS_RINTFL | HDA_RIRBSTS_RIRBOIS);
     869           0 :         AZ_WRITE_4(az, INTSTS, HDA_INTSTS_CIS | HDA_INTSTS_GIS);
     870           0 :         AZ_WRITE_4(az, DPLBASE, 0);
     871           0 :         AZ_WRITE_4(az, DPUBASE, 0);
     872             : 
     873             :         /* 4.4.1 Command Outbound Ring Buffer */
     874           0 :         err = azalia_init_corb(az, resuming);
     875           0 :         if (err)
     876           0 :                 return(err);
     877             : 
     878             :         /* 4.4.2 Response Inbound Ring Buffer */
     879           0 :         err = azalia_init_rirb(az, resuming);
     880           0 :         if (err)
     881           0 :                 return(err);
     882             : 
     883           0 :         AZ_WRITE_4(az, INTCTL,
     884             :             AZ_READ_4(az, INTCTL) | HDA_INTCTL_CIE | HDA_INTCTL_GIE);
     885             : 
     886           0 :         return(0);
     887           0 : }
     888             : 
     889             : int
     890           0 : azalia_init_codecs(azalia_t *az)
     891             : {
     892             :         codec_t *codec;
     893             :         int c, i;
     894             : 
     895             :         c = 0;
     896           0 :         for (i = 0; i < az->ncodecs; i++) {
     897           0 :                 if (!azalia_codec_init(&az->codecs[i]))
     898           0 :                         c++;
     899             :         }
     900           0 :         if (c == 0) {
     901           0 :                 printf("%s: No codecs found\n", XNAME(az));
     902           0 :                 return(1);
     903             :         }
     904             : 
     905             :         /* Use the first codec capable of analog I/O.  If there are none,
     906             :          * use the first codec capable of digital I/O.  Skip HDMI codecs.
     907             :          */
     908             :         c = -1;
     909           0 :         for (i = 0; i < az->ncodecs; i++) {
     910           0 :                 codec = &az->codecs[i];
     911           0 :                 if ((codec->audiofunc < 0) ||
     912           0 :                     (codec->codec_type == AZ_CODEC_TYPE_HDMI))
     913             :                         continue;
     914           0 :                 if (codec->codec_type == AZ_CODEC_TYPE_DIGITAL) {
     915           0 :                         if (c < 0)
     916           0 :                                 c = i;
     917             :                 } else {
     918             :                         c = i;
     919           0 :                         break;
     920             :                 }
     921             :         }
     922           0 :         az->codecno = c;
     923           0 :         if (az->codecno < 0) {
     924           0 :                 printf("%s: no supported codecs\n", XNAME(az));
     925           0 :                 return(1);
     926             :         }
     927             : 
     928           0 :         printf("%s: codecs: ", XNAME(az));
     929           0 :         for (i = 0; i < az->ncodecs; i++) {
     930           0 :                 azalia_print_codec(&az->codecs[i]);
     931           0 :                 if (i < az->ncodecs - 1)
     932           0 :                         printf(", ");
     933             :         }
     934           0 :         if (az->ncodecs > 1) {
     935           0 :                 printf(", using ");
     936           0 :                 azalia_print_codec(&az->codecs[az->codecno]);
     937           0 :         }
     938           0 :         printf("\n");
     939             : 
     940             :         /* All codecs with audio are enabled, but only one will be used. */
     941           0 :         for (i = 0; i < az->ncodecs; i++) {
     942           0 :                 codec = &az->codecs[i];
     943           0 :                 if (i != az->codecno) {
     944           0 :                         if (codec->audiofunc < 0)
     945             :                                 continue;
     946           0 :                         azalia_comresp(codec, codec->audiofunc,
     947             :                             CORB_SET_POWER_STATE, CORB_PS_D3, NULL);
     948           0 :                         DELAY(100);
     949           0 :                         azalia_codec_delete(codec);
     950           0 :                 }
     951             :         }
     952             : 
     953             :         /* Enable unsolicited responses now that az->codecno is set. */
     954           0 :         AZ_WRITE_4(az, GCTL, AZ_READ_4(az, GCTL) | HDA_GCTL_UNSOL);
     955             : 
     956           0 :         return(0);
     957           0 : }
     958             : 
     959             : int
     960           0 : azalia_init_streams(azalia_t *az)
     961             : {
     962             :         int err;
     963             : 
     964             :         /* Use stream#1 and #2.  Don't use stream#0. */
     965           0 :         err = azalia_stream_init(&az->pstream, az, az->nistreams + 0,
     966             :             1, AUMODE_PLAY);
     967           0 :         if (err)
     968           0 :                 return(err);
     969           0 :         err = azalia_stream_init(&az->rstream, az, 0, 2, AUMODE_RECORD);
     970           0 :         if (err)
     971           0 :                 return(err);
     972             : 
     973           0 :         return(0);
     974           0 : }
     975             : 
     976             : int
     977           0 : azalia_halt_corb(azalia_t *az)
     978             : {
     979             :         uint8_t corbctl;
     980             :         codec_t *codec;
     981             :         int i;
     982             : 
     983           0 :         corbctl = AZ_READ_1(az, CORBCTL);
     984           0 :         if (corbctl & HDA_CORBCTL_CORBRUN) { /* running? */
     985             :                 /* power off all codecs */
     986           0 :                 for (i = 0; i < az->ncodecs; i++) {
     987           0 :                         codec = &az->codecs[i];
     988           0 :                         if (codec->audiofunc < 0)
     989             :                                 continue;
     990           0 :                         azalia_comresp(codec, codec->audiofunc,
     991             :                             CORB_SET_POWER_STATE, CORB_PS_D3, NULL);
     992           0 :                 }
     993             : 
     994           0 :                 AZ_WRITE_1(az, CORBCTL, corbctl & ~HDA_CORBCTL_CORBRUN);
     995           0 :                 for (i = 5000; i > 0; i--) {
     996           0 :                         DELAY(10);
     997           0 :                         corbctl = AZ_READ_1(az, CORBCTL);
     998           0 :                         if ((corbctl & HDA_CORBCTL_CORBRUN) == 0)
     999             :                                 break;
    1000             :                 }
    1001           0 :                 if (i == 0) {
    1002             :                         DPRINTF(("%s: CORB is running\n", XNAME(az)));
    1003           0 :                         return EBUSY;
    1004             :                 }
    1005             :         }
    1006           0 :         return(0);
    1007           0 : }
    1008             : 
    1009             : int
    1010           0 : azalia_init_corb(azalia_t *az, int resuming)
    1011             : {
    1012             :         int err, i;
    1013             :         uint16_t corbrp, corbwp;
    1014             :         uint8_t corbctl;
    1015             : 
    1016           0 :         err = azalia_halt_corb(az);
    1017           0 :         if (err)
    1018           0 :                 return(err);
    1019             : 
    1020           0 :         if (!resuming) {
    1021           0 :                 err = azalia_alloc_dmamem(az,
    1022           0 :                     az->corb_entries * sizeof(corb_entry_t), 128,
    1023           0 :                     &az->corb_dma);
    1024           0 :                 if (err) {
    1025           0 :                         printf("%s: can't allocate CORB buffer\n", XNAME(az));
    1026           0 :                         return(err);
    1027             :                 }
    1028             :                 DPRINTF(("%s: CORB allocation succeeded.\n", __func__));
    1029             :         }
    1030           0 :         timeout_set(&az->unsol_to, azalia_rirb_kick_unsol_events, az);
    1031             : 
    1032           0 :         AZ_WRITE_4(az, CORBLBASE, (uint32_t)AZALIA_DMA_DMAADDR(&az->corb_dma));
    1033           0 :         AZ_WRITE_4(az, CORBUBASE, PTR_UPPER32(AZALIA_DMA_DMAADDR(&az->corb_dma)));
    1034           0 :         AZ_WRITE_1(az, CORBSIZE, az->corbsize);
    1035             :  
    1036             :         /* reset CORBRP */
    1037           0 :         corbrp = AZ_READ_2(az, CORBRP);
    1038           0 :         AZ_WRITE_2(az, CORBRP, corbrp | HDA_CORBRP_CORBRPRST);
    1039           0 :         AZ_WRITE_2(az, CORBRP, corbrp & ~HDA_CORBRP_CORBRPRST);
    1040           0 :         for (i = 5000; i > 0; i--) {
    1041           0 :                 DELAY(10);
    1042           0 :                 corbrp = AZ_READ_2(az, CORBRP);
    1043           0 :                 if ((corbrp & HDA_CORBRP_CORBRPRST) == 0)
    1044             :                         break;
    1045             :         }
    1046           0 :         if (i == 0) {
    1047             :                 DPRINTF(("%s: CORBRP reset failure\n", XNAME(az)));
    1048           0 :                 return -1;
    1049             :         }
    1050             :         DPRINTF(("%s: CORBWP=%d; size=%d\n", __func__,
    1051             :                  AZ_READ_2(az, CORBRP) & HDA_CORBRP_CORBRP, az->corb_entries));
    1052             : 
    1053             :         /* clear CORBWP */
    1054           0 :         corbwp = AZ_READ_2(az, CORBWP);
    1055           0 :         AZ_WRITE_2(az, CORBWP, corbwp & ~HDA_CORBWP_CORBWP);
    1056             : 
    1057             :         /* Run! */
    1058           0 :         corbctl = AZ_READ_1(az, CORBCTL);
    1059           0 :         AZ_WRITE_1(az, CORBCTL, corbctl | HDA_CORBCTL_CORBRUN);
    1060           0 :         return 0;
    1061           0 : }
    1062             : 
    1063             : int
    1064           0 : azalia_halt_rirb(azalia_t *az)
    1065             : {
    1066             :         int i;
    1067             :         uint8_t rirbctl;
    1068             : 
    1069           0 :         rirbctl = AZ_READ_1(az, RIRBCTL);
    1070           0 :         if (rirbctl & HDA_RIRBCTL_RIRBDMAEN) { /* running? */
    1071           0 :                 AZ_WRITE_1(az, RIRBCTL, rirbctl & ~HDA_RIRBCTL_RIRBDMAEN);
    1072           0 :                 for (i = 5000; i > 0; i--) {
    1073           0 :                         DELAY(10);
    1074           0 :                         rirbctl = AZ_READ_1(az, RIRBCTL);
    1075           0 :                         if ((rirbctl & HDA_RIRBCTL_RIRBDMAEN) == 0)
    1076             :                                 break;
    1077             :                 }
    1078           0 :                 if (i == 0) {
    1079             :                         DPRINTF(("%s: RIRB is running\n", XNAME(az)));
    1080           0 :                         return(EBUSY);
    1081             :                 }
    1082             :         }
    1083           0 :         return(0);
    1084           0 : }
    1085             : 
    1086             : int
    1087           0 : azalia_init_rirb(azalia_t *az, int resuming)
    1088             : {
    1089             :         int err, i;
    1090             :         uint16_t rirbwp;
    1091             :         uint8_t rirbctl;
    1092             : 
    1093           0 :         err = azalia_halt_rirb(az);
    1094           0 :         if (err)
    1095           0 :                 return(err);
    1096             : 
    1097           0 :         if (!resuming) {
    1098           0 :                 err = azalia_alloc_dmamem(az,
    1099           0 :                     az->rirb_entries * sizeof(rirb_entry_t), 128,
    1100           0 :                     &az->rirb_dma);
    1101           0 :                 if (err) {
    1102           0 :                         printf("%s: can't allocate RIRB buffer\n", XNAME(az));
    1103           0 :                         return err;
    1104             :                 }
    1105             :                 DPRINTF(("%s: RIRB allocation succeeded.\n", __func__));
    1106             : 
    1107             :                 /* setup the unsolicited response queue */
    1108           0 :                 az->unsolq = malloc(sizeof(rirb_entry_t) * UNSOLQ_SIZE,
    1109             :                     M_DEVBUF, M_NOWAIT | M_ZERO);
    1110           0 :                 if (az->unsolq == NULL) {
    1111             :                         DPRINTF(("%s: can't allocate unsolicited response queue.\n",
    1112             :                             XNAME(az)));
    1113           0 :                         azalia_free_dmamem(az, &az->rirb_dma);
    1114           0 :                         return ENOMEM;
    1115             :                 }
    1116             :         }
    1117           0 :         AZ_WRITE_4(az, RIRBLBASE, (uint32_t)AZALIA_DMA_DMAADDR(&az->rirb_dma));
    1118           0 :         AZ_WRITE_4(az, RIRBUBASE, PTR_UPPER32(AZALIA_DMA_DMAADDR(&az->rirb_dma)));
    1119           0 :         AZ_WRITE_1(az, RIRBSIZE, az->rirbsize);
    1120             : 
    1121             :         /* reset the write pointer */
    1122           0 :         rirbwp = AZ_READ_2(az, RIRBWP);
    1123           0 :         AZ_WRITE_2(az, RIRBWP, rirbwp | HDA_RIRBWP_RIRBWPRST);
    1124             : 
    1125             :         /* clear the read pointer */
    1126           0 :         az->rirb_rp = AZ_READ_2(az, RIRBWP) & HDA_RIRBWP_RIRBWP;
    1127             :         DPRINTF(("%s: RIRBRP=%d, size=%d\n", __func__, az->rirb_rp,
    1128             :             az->rirb_entries));
    1129             : 
    1130           0 :         az->unsolq_rp = 0;
    1131           0 :         az->unsolq_wp = 0;
    1132           0 :         az->unsolq_kick = 0;
    1133             : 
    1134           0 :         AZ_WRITE_2(az, RINTCNT, 1);
    1135             : 
    1136             :         /* Run! */
    1137           0 :         rirbctl = AZ_READ_1(az, RIRBCTL);
    1138           0 :         AZ_WRITE_1(az, RIRBCTL, rirbctl |
    1139             :             HDA_RIRBCTL_RIRBDMAEN | HDA_RIRBCTL_RINTCTL);
    1140           0 :         for (i = 5000; i > 0; i--) {
    1141           0 :                 DELAY(10);
    1142           0 :                 rirbctl = AZ_READ_1(az, RIRBCTL);
    1143           0 :                 if (rirbctl & HDA_RIRBCTL_RIRBDMAEN)
    1144             :                         break;
    1145             :         }
    1146           0 :         if (i == 0) {
    1147             :                 DPRINTF(("%s: RIRB is not running\n", XNAME(az)));
    1148           0 :                 return(EBUSY);
    1149             :         }
    1150             : 
    1151           0 :         return (0);
    1152           0 : }
    1153             : 
    1154             : int
    1155           0 : azalia_comresp(const codec_t *codec, nid_t nid, uint32_t control,
    1156             :     uint32_t param, uint32_t* result)
    1157             : {
    1158             :         int err;
    1159             : 
    1160           0 :         mtx_enter(&audio_lock);
    1161           0 :         err = azalia_set_command(codec->az, codec->address, nid, control,
    1162             :             param);
    1163           0 :         if (err)
    1164             :                 goto exit;
    1165           0 :         err = azalia_get_response(codec->az, result);
    1166             : exit:
    1167           0 :         mtx_leave(&audio_lock);
    1168           0 :         return(err);
    1169             : }
    1170             : 
    1171             : int
    1172           0 : azalia_set_command(azalia_t *az, int caddr, nid_t nid, uint32_t control,
    1173             :     uint32_t param)
    1174             : {
    1175             :         corb_entry_t *corb;
    1176             :         int  wp;
    1177             :         uint32_t verb;
    1178             :         uint16_t corbwp;
    1179             : 
    1180           0 :         if ((AZ_READ_1(az, CORBCTL) & HDA_CORBCTL_CORBRUN) == 0) {
    1181           0 :                 printf("%s: CORB is not running.\n", XNAME(az));
    1182           0 :                 return(-1);
    1183             :         }
    1184           0 :         verb = (caddr << 28) | (nid << 20) | (control << 8) | param;
    1185           0 :         corbwp = AZ_READ_2(az, CORBWP);
    1186           0 :         wp = corbwp & HDA_CORBWP_CORBWP;
    1187           0 :         corb = (corb_entry_t*)az->corb_dma.addr;
    1188           0 :         if (++wp >= az->corb_entries)
    1189             :                 wp = 0;
    1190           0 :         corb[wp] = verb;
    1191             : 
    1192           0 :         AZ_WRITE_2(az, CORBWP, (corbwp & ~HDA_CORBWP_CORBWP) | wp);
    1193             : 
    1194           0 :         return(0);
    1195           0 : }
    1196             : 
    1197             : int
    1198           0 : azalia_get_response(azalia_t *az, uint32_t *result)
    1199             : {
    1200             :         const rirb_entry_t *rirb;
    1201             :         int i;
    1202             :         uint16_t wp;
    1203             : 
    1204           0 :         if ((AZ_READ_1(az, RIRBCTL) & HDA_RIRBCTL_RIRBDMAEN) == 0) {
    1205           0 :                 printf("%s: RIRB is not running.\n", XNAME(az));
    1206           0 :                 return(-1);
    1207             :         }
    1208             : 
    1209           0 :         rirb = (rirb_entry_t*)az->rirb_dma.addr;
    1210             :         i = 5000;
    1211           0 :         for (;;) {
    1212           0 :                 while (i > 0) {
    1213           0 :                         wp = AZ_READ_2(az, RIRBWP) & HDA_RIRBWP_RIRBWP;
    1214           0 :                         if (az->rirb_rp != wp)
    1215             :                                 break;
    1216           0 :                         DELAY(10);
    1217           0 :                         i--;
    1218             :                 }
    1219           0 :                 if (i == 0) {
    1220             :                         DPRINTF(("%s: RIRB time out\n", XNAME(az)));
    1221           0 :                         return(ETIMEDOUT);
    1222             :                 }
    1223           0 :                 if (++az->rirb_rp >= az->rirb_entries)
    1224           0 :                         az->rirb_rp = 0;
    1225           0 :                 if (rirb[az->rirb_rp].resp_ex & RIRB_RESP_UNSOL) {
    1226           0 :                         az->unsolq[az->unsolq_wp].resp = rirb[az->rirb_rp].resp;
    1227           0 :                         az->unsolq[az->unsolq_wp++].resp_ex = rirb[az->rirb_rp].resp_ex;
    1228           0 :                         az->unsolq_wp %= UNSOLQ_SIZE;
    1229             :                 } else
    1230             :                         break;
    1231             :         }
    1232           0 :         if (result != NULL)
    1233           0 :                 *result = rirb[az->rirb_rp].resp;
    1234             : 
    1235           0 :         return(0);
    1236           0 : }
    1237             : 
    1238             : void
    1239           0 : azalia_rirb_kick_unsol_events(void *v)
    1240             : {
    1241           0 :         azalia_t *az = v;
    1242             :         int addr, tag;
    1243             : 
    1244           0 :         if (az->unsolq_kick)
    1245           0 :                 return;
    1246           0 :         az->unsolq_kick = 1;
    1247           0 :         while (az->unsolq_rp != az->unsolq_wp) {
    1248           0 :                 addr = RIRB_RESP_CODEC(az->unsolq[az->unsolq_rp].resp_ex);
    1249           0 :                 tag = RIRB_UNSOL_TAG(az->unsolq[az->unsolq_rp].resp);
    1250             :                 DPRINTF(("%s: codec address=%d tag=%d\n", __func__, addr, tag));
    1251             : 
    1252           0 :                 az->unsolq_rp++;
    1253           0 :                 az->unsolq_rp %= UNSOLQ_SIZE;
    1254             : 
    1255             :                 /* We only care about events on the using codec. */
    1256           0 :                 if (az->codecs[az->codecno].address == addr)
    1257           0 :                         azalia_unsol_event(&az->codecs[az->codecno], tag);
    1258             :         }
    1259           0 :         az->unsolq_kick = 0;
    1260           0 : }
    1261             : 
    1262             : void
    1263           0 : azalia_rirb_intr(azalia_t *az)
    1264             : {
    1265             :         const rirb_entry_t *rirb;
    1266             :         uint16_t wp;
    1267             :         uint8_t rirbsts;
    1268             : 
    1269           0 :         rirbsts = AZ_READ_1(az, RIRBSTS);
    1270             : 
    1271           0 :         wp = AZ_READ_2(az, RIRBWP) & HDA_RIRBWP_RIRBWP;
    1272           0 :         rirb = (rirb_entry_t*)az->rirb_dma.addr;
    1273           0 :         while (az->rirb_rp != wp) {
    1274           0 :                 if (++az->rirb_rp >= az->rirb_entries)
    1275           0 :                         az->rirb_rp = 0;
    1276           0 :                 if (rirb[az->rirb_rp].resp_ex & RIRB_RESP_UNSOL) {
    1277           0 :                         az->unsolq[az->unsolq_wp].resp = rirb[az->rirb_rp].resp;
    1278           0 :                         az->unsolq[az->unsolq_wp++].resp_ex = rirb[az->rirb_rp].resp_ex;
    1279           0 :                         az->unsolq_wp %= UNSOLQ_SIZE;
    1280           0 :                 } else {
    1281             :                         DPRINTF(("%s: dropped solicited response\n", __func__));
    1282             :                 }
    1283             :         }
    1284           0 :         timeout_add_msec(&az->unsol_to, 1);
    1285             : 
    1286           0 :         AZ_WRITE_1(az, RIRBSTS,
    1287             :             rirbsts | HDA_RIRBSTS_RIRBOIS | HDA_RIRBSTS_RINTFL);
    1288           0 : }
    1289             : 
    1290             : int
    1291           0 : azalia_alloc_dmamem(azalia_t *az, size_t size, size_t align, azalia_dma_t *d)
    1292             : {
    1293             :         int err;
    1294           0 :         int nsegs;
    1295             : 
    1296           0 :         d->size = size;
    1297           0 :         err = bus_dmamem_alloc(az->dmat, size, align, 0, d->segments, 1,
    1298             :             &nsegs, BUS_DMA_NOWAIT);
    1299           0 :         if (err)
    1300           0 :                 return err;
    1301           0 :         if (nsegs != 1)
    1302             :                 goto free;
    1303           0 :         err = bus_dmamem_map(az->dmat, d->segments, 1, size,
    1304             :             &d->addr, BUS_DMA_NOWAIT | BUS_DMA_COHERENT);
    1305           0 :         if (err)
    1306             :                 goto free;
    1307           0 :         err = bus_dmamap_create(az->dmat, size, 1, size, 0,
    1308             :             BUS_DMA_NOWAIT, &d->map);
    1309           0 :         if (err)
    1310             :                 goto unmap;
    1311           0 :         err = bus_dmamap_load(az->dmat, d->map, d->addr, size,
    1312             :             NULL, BUS_DMA_NOWAIT);
    1313           0 :         if (err)
    1314             :                 goto destroy;
    1315             : 
    1316           0 :         if (!az->ok64 && PTR_UPPER32(AZALIA_DMA_DMAADDR(d)) != 0) {
    1317           0 :                 azalia_free_dmamem(az, d);
    1318           0 :                 return -1;
    1319             :         }
    1320           0 :         return 0;
    1321             : 
    1322             : destroy:
    1323           0 :         bus_dmamap_destroy(az->dmat, d->map);
    1324             : unmap:
    1325           0 :         bus_dmamem_unmap(az->dmat, d->addr, size);
    1326             : free:
    1327           0 :         bus_dmamem_free(az->dmat, d->segments, 1);
    1328           0 :         d->addr = NULL;
    1329           0 :         return err;
    1330           0 : }
    1331             : 
    1332             : void
    1333           0 : azalia_free_dmamem(const azalia_t *az, azalia_dma_t* d)
    1334             : {
    1335           0 :         if (d->addr == NULL)
    1336             :                 return;
    1337           0 :         bus_dmamap_unload(az->dmat, d->map);
    1338           0 :         bus_dmamap_destroy(az->dmat, d->map);
    1339           0 :         bus_dmamem_unmap(az->dmat, d->addr, d->size);
    1340           0 :         bus_dmamem_free(az->dmat, d->segments, 1);
    1341           0 :         d->addr = NULL;
    1342           0 : }
    1343             : 
    1344             : int
    1345           0 : azalia_suspend(azalia_t *az)
    1346             : {
    1347             :         int err;
    1348             : 
    1349           0 :         if (az->detached)
    1350           0 :                 return 0;
    1351             : 
    1352             :         /* disable unsolicited responses */
    1353           0 :         AZ_WRITE_4(az, GCTL, AZ_READ_4(az, GCTL) & ~HDA_GCTL_UNSOL);
    1354             : 
    1355           0 :         timeout_del(&az->unsol_to);
    1356             : 
    1357             :         /* azalia_halt_{corb,rirb}() only fail if the {CORB,RIRB} can't
    1358             :          * be stopped and azalia_init_{corb,rirb}(), which starts the
    1359             :          * {CORB,RIRB}, first calls azalia_halt_{corb,rirb}().  If halt
    1360             :          * fails, don't try to restart.
    1361             :          */
    1362           0 :         err = azalia_halt_corb(az);
    1363           0 :         if (err)
    1364             :                 goto corb_fail;
    1365             : 
    1366           0 :         err = azalia_halt_rirb(az);
    1367           0 :         if (err)
    1368             :                 goto rirb_fail;
    1369             : 
    1370             :         /* stop interrupts and clear status registers */
    1371           0 :         AZ_WRITE_4(az, INTCTL, 0);
    1372           0 :         AZ_WRITE_4(az, INTSTS, HDA_INTSTS_CIS | HDA_INTSTS_GIS);
    1373           0 :         AZ_WRITE_2(az, STATESTS, HDA_STATESTS_SDIWAKE);
    1374           0 :         AZ_WRITE_1(az, RIRBSTS, HDA_RIRBSTS_RINTFL | HDA_RIRBSTS_RIRBOIS);
    1375             : 
    1376           0 :         return 0;
    1377             : 
    1378             : rirb_fail:
    1379           0 :         azalia_init_corb(az, 1);
    1380             : corb_fail:
    1381           0 :         AZ_WRITE_4(az, GCTL, AZ_READ_4(az, GCTL) | HDA_GCTL_UNSOL);
    1382             : 
    1383           0 :         return err;
    1384           0 : }
    1385             : 
    1386             : int
    1387           0 : azalia_resume_codec(codec_t *this)
    1388             : {
    1389             :         widget_t *w;
    1390           0 :         uint32_t result;
    1391             :         int i, err;
    1392             : 
    1393           0 :         err = azalia_comresp(this, this->audiofunc, CORB_SET_POWER_STATE,
    1394             :             CORB_PS_D0, &result);
    1395             :         if (err) {
    1396             :                 DPRINTF(("%s: power audio func error: result=0x%8.8x\n",
    1397             :                     __func__, result));
    1398             :         }
    1399           0 :         DELAY(100);
    1400             : 
    1401           0 :         FOR_EACH_WIDGET(this, i) {
    1402           0 :                 w = &this->w[i];
    1403           0 :                 if (w->widgetcap & COP_AWCAP_POWER) {
    1404           0 :                         azalia_comresp(this, w->nid, CORB_SET_POWER_STATE,
    1405             :                             CORB_PS_D0, &result);
    1406           0 :                         DELAY(100);
    1407           0 :                 }
    1408           0 :                 if (w->type == COP_AWTYPE_PIN_COMPLEX)
    1409           0 :                         azalia_widget_init_pin(w, this);
    1410           0 :                 if (this->qrks & AZ_QRK_WID_MASK)
    1411           0 :                         azalia_codec_widget_quirks(this, w->nid);
    1412             :         }
    1413             : 
    1414           0 :         if (this->qrks & AZ_QRK_GPIO_MASK) {
    1415           0 :                 err = azalia_codec_gpio_quirks(this);
    1416           0 :                 if (err)
    1417           0 :                         return err;
    1418             :         }
    1419             : 
    1420           0 :         return(0);
    1421           0 : }
    1422             : 
    1423             : int
    1424           0 : azalia_resume(azalia_t *az)
    1425             : {
    1426             :         int err;
    1427             : 
    1428           0 :         if (az->detached)
    1429           0 :                 return 0;
    1430             : 
    1431           0 :         azalia_configure_pci(az);
    1432             : 
    1433             :         /* is this necessary? */
    1434           0 :         pci_conf_write(az->pc, az->tag, PCI_SUBSYS_ID_REG, az->subid);
    1435             : 
    1436           0 :         err = azalia_init(az, 1);
    1437           0 :         if (err)
    1438           0 :                 return err;
    1439             : 
    1440             :         /* enable unsolicited responses on the controller */
    1441           0 :         AZ_WRITE_4(az, GCTL, AZ_READ_4(az, GCTL) | HDA_GCTL_UNSOL);
    1442             : 
    1443           0 :         err = azalia_resume_codec(&az->codecs[az->codecno]);
    1444           0 :         if (err)
    1445           0 :                 return err;
    1446             : 
    1447           0 :         err = azalia_codec_enable_unsol(&az->codecs[az->codecno]);
    1448           0 :         if (err)
    1449           0 :                 return err;
    1450             : 
    1451           0 :         return 0;
    1452           0 : }
    1453             : 
    1454             : /* ================================================================
    1455             :  * HDA codec functions
    1456             :  * ================================================================ */
    1457             : 
    1458             : int
    1459           0 : azalia_codec_init(codec_t *this)
    1460             : {
    1461             :         widget_t *w;
    1462           0 :         uint32_t rev, id, result;
    1463             :         int err, addr, n, i, nspdif, nhdmi;
    1464             : 
    1465           0 :         addr = this->address;
    1466             :         /* codec vendor/device/revision */
    1467           0 :         err = azalia_comresp(this, CORB_NID_ROOT, CORB_GET_PARAMETER,
    1468             :             COP_REVISION_ID, &rev);
    1469           0 :         if (err)
    1470           0 :                 return err;
    1471           0 :         err = azalia_comresp(this, CORB_NID_ROOT, CORB_GET_PARAMETER,
    1472             :             COP_VENDOR_ID, &id);
    1473           0 :         if (err)
    1474           0 :                 return err;
    1475           0 :         this->vid = id;
    1476           0 :         this->subid = this->az->subid;
    1477           0 :         azalia_codec_init_vtbl(this);
    1478             :         DPRINTF(("%s: codec[%d] vid 0x%8.8x, subid 0x%8.8x, rev. %u.%u,",
    1479             :             XNAME(this->az), addr, this->vid, this->subid,
    1480             :             COP_RID_REVISION(rev), COP_RID_STEPPING(rev)));
    1481             :         DPRINTF((" HDA version %u.%u\n",
    1482             :             COP_RID_MAJ(rev), COP_RID_MIN(rev)));
    1483             : 
    1484             :         /* identify function nodes */
    1485           0 :         err = azalia_comresp(this, CORB_NID_ROOT, CORB_GET_PARAMETER,
    1486             :             COP_SUBORDINATE_NODE_COUNT, &result);
    1487           0 :         if (err)
    1488           0 :                 return err;
    1489           0 :         this->nfunctions = COP_NSUBNODES(result);
    1490           0 :         if (COP_NSUBNODES(result) <= 0) {
    1491             :                 DPRINTF(("%s: codec[%d]: No function groups\n",
    1492             :                     XNAME(this->az), addr));
    1493           0 :                 return -1;
    1494             :         }
    1495             :         /* iterate function nodes and find an audio function */
    1496           0 :         n = COP_START_NID(result);
    1497             :         DPRINTF(("%s: nidstart=%d #functions=%d\n",
    1498             :             XNAME(this->az), n, this->nfunctions));
    1499           0 :         this->audiofunc = -1;
    1500           0 :         for (i = 0; i < this->nfunctions; i++) {
    1501           0 :                 err = azalia_comresp(this, n + i, CORB_GET_PARAMETER,
    1502             :                     COP_FUNCTION_GROUP_TYPE, &result);
    1503           0 :                 if (err)
    1504             :                         continue;
    1505             :                 DPRINTF(("%s: FTYPE result = 0x%8.8x\n", __func__, result));
    1506           0 :                 if (COP_FTYPE(result) == COP_FTYPE_AUDIO) {
    1507           0 :                         this->audiofunc = n + i;
    1508           0 :                         break;  /* XXX multiple audio functions? */
    1509             :                 }
    1510             :         }
    1511           0 :         if (this->audiofunc < 0) {
    1512             :                 DPRINTF(("%s: codec[%d]: No audio function groups\n",
    1513             :                     XNAME(this->az), addr));
    1514           0 :                 return -1;
    1515             :         }
    1516             : 
    1517             :         /* power the audio function */
    1518           0 :         azalia_comresp(this, this->audiofunc, CORB_SET_POWER_STATE,
    1519             :             CORB_PS_D0, &result);
    1520           0 :         DELAY(100);
    1521             : 
    1522             :         /* check widgets in the audio function */
    1523           0 :         err = azalia_comresp(this, this->audiofunc, CORB_GET_PARAMETER,
    1524             :             COP_SUBORDINATE_NODE_COUNT, &result);
    1525           0 :         if (err)
    1526           0 :                 return err;
    1527             :         DPRINTF(("%s: There are %d widgets in the audio function.\n",
    1528             :            __func__, COP_NSUBNODES(result)));
    1529           0 :         this->wstart = COP_START_NID(result);
    1530           0 :         if (this->wstart < 2) {
    1531           0 :                 printf("%s: invalid node structure\n", XNAME(this->az));
    1532           0 :                 return -1;
    1533             :         }
    1534           0 :         this->wend = this->wstart + COP_NSUBNODES(result);
    1535           0 :         this->w = mallocarray(this->wend, sizeof(widget_t), M_DEVBUF,
    1536             :             M_NOWAIT | M_ZERO);
    1537           0 :         if (this->w == NULL) {
    1538           0 :                 printf("%s: out of memory\n", XNAME(this->az));
    1539           0 :                 return ENOMEM;
    1540             :         }
    1541             : 
    1542             :         /* query the base parameters */
    1543           0 :         azalia_comresp(this, this->audiofunc, CORB_GET_PARAMETER,
    1544             :             COP_STREAM_FORMATS, &result);
    1545           0 :         this->w[this->audiofunc].d.audio.encodings = result;
    1546           0 :         azalia_comresp(this, this->audiofunc, CORB_GET_PARAMETER,
    1547             :             COP_PCM, &result);
    1548           0 :         this->w[this->audiofunc].d.audio.bits_rates = result;
    1549           0 :         azalia_comresp(this, this->audiofunc, CORB_GET_PARAMETER,
    1550             :             COP_INPUT_AMPCAP, &result);
    1551           0 :         this->w[this->audiofunc].inamp_cap = result;
    1552           0 :         azalia_comresp(this, this->audiofunc, CORB_GET_PARAMETER,
    1553             :             COP_OUTPUT_AMPCAP, &result);
    1554           0 :         this->w[this->audiofunc].outamp_cap = result;
    1555             : 
    1556           0 :         azalia_codec_print_audiofunc(this);
    1557             : 
    1558           0 :         strlcpy(this->w[CORB_NID_ROOT].name, "root",
    1559             :             sizeof(this->w[CORB_NID_ROOT].name));
    1560           0 :         strlcpy(this->w[this->audiofunc].name, "hdaudio",
    1561             :             sizeof(this->w[this->audiofunc].name));
    1562           0 :         this->w[this->audiofunc].enable = 1;
    1563             : 
    1564           0 :         FOR_EACH_WIDGET(this, i) {
    1565           0 :                 w = &this->w[i];
    1566           0 :                 err = azalia_widget_init(w, this, i);
    1567           0 :                 if (err)
    1568           0 :                         return err;
    1569           0 :                 err = azalia_widget_init_connection(w, this);
    1570           0 :                 if (err)
    1571           0 :                         return err;
    1572             : 
    1573           0 :                 azalia_widget_print_widget(w, this);
    1574             : 
    1575           0 :                 if (this->qrks & AZ_QRK_WID_MASK) {
    1576           0 :                         azalia_codec_widget_quirks(this, i);
    1577           0 :                 }
    1578             :         }
    1579             : 
    1580           0 :         this->na_dacs = this->na_dacs_d = 0;
    1581           0 :         this->na_adcs = this->na_adcs_d = 0;
    1582           0 :         this->speaker = this->speaker2 = this->spkr_dac =
    1583           0 :             this->fhp = this->fhp_dac =
    1584           0 :             this->mic = this->mic_adc = -1;
    1585           0 :         this->nsense_pins = 0;
    1586           0 :         this->nout_jacks = 0;
    1587             :         nspdif = nhdmi = 0;
    1588           0 :         FOR_EACH_WIDGET(this, i) {
    1589           0 :                 w = &this->w[i];
    1590             : 
    1591           0 :                 if (!w->enable)
    1592             :                         continue;
    1593             : 
    1594           0 :                 switch (w->type) {
    1595             : 
    1596             :                 case COP_AWTYPE_AUDIO_MIXER:
    1597             :                 case COP_AWTYPE_AUDIO_SELECTOR:
    1598           0 :                         if (!azalia_widget_check_conn(this, i, 0))
    1599           0 :                                 w->enable = 0;
    1600             :                         break;
    1601             : 
    1602             :                 case COP_AWTYPE_AUDIO_OUTPUT:
    1603           0 :                         if ((w->widgetcap & COP_AWCAP_DIGITAL) == 0) {
    1604           0 :                                 if (this->na_dacs < HDA_MAX_CHANNELS)
    1605           0 :                                         this->a_dacs[this->na_dacs++] = i;
    1606             :                         } else {
    1607           0 :                                 if (this->na_dacs_d < HDA_MAX_CHANNELS)
    1608           0 :                                         this->a_dacs_d[this->na_dacs_d++] = i;
    1609             :                         }
    1610             :                         break;
    1611             : 
    1612             :                 case COP_AWTYPE_AUDIO_INPUT:
    1613           0 :                         if ((w->widgetcap & COP_AWCAP_DIGITAL) == 0) {
    1614           0 :                                 if (this->na_adcs < HDA_MAX_CHANNELS)
    1615           0 :                                         this->a_adcs[this->na_adcs++] = i;
    1616             :                         } else {
    1617           0 :                                 if (this->na_adcs_d < HDA_MAX_CHANNELS)
    1618           0 :                                         this->a_adcs_d[this->na_adcs_d++] = i;
    1619             :                         }
    1620             :                         break;
    1621             : 
    1622             :                 case COP_AWTYPE_PIN_COMPLEX:
    1623           0 :                         switch (CORB_CD_PORT(w->d.pin.config)) {
    1624             :                         case CORB_CD_FIXED:
    1625           0 :                                 switch (w->d.pin.device) {
    1626             :                                 case CORB_CD_SPEAKER:
    1627           0 :                                         if (this->speaker == -1) {
    1628           0 :                                                 this->speaker = i;
    1629           0 :                                         } else if (w->d.pin.association <
    1630           0 :                                             this->w[this->speaker].d.pin.association ||
    1631           0 :                                             (w->d.pin.association ==
    1632           0 :                                             this->w[this->speaker].d.pin.association &&
    1633           0 :                                             w->d.pin.sequence <
    1634           0 :                                             this->w[this->speaker].d.pin.sequence)) {
    1635           0 :                                                 this->speaker2 = this->speaker;
    1636           0 :                                                 this->speaker = i;
    1637           0 :                                         } else {
    1638           0 :                                                 this->speaker2 = i;
    1639             :                                         }
    1640           0 :                                         if (this->speaker == i)
    1641           0 :                                                 this->spkr_dac =
    1642           0 :                                                     azalia_codec_find_defdac(this, i, 0);
    1643             :                                         break;
    1644             :                                 case CORB_CD_MICIN:
    1645           0 :                                         this->mic = i;
    1646           0 :                                         this->mic_adc =
    1647           0 :                                             azalia_codec_find_defadc(this, i, 0);
    1648           0 :                                         break;
    1649             :                                 }
    1650             :                                 break;
    1651             :                         case CORB_CD_JACK:
    1652           0 :                                 if (w->d.pin.device == CORB_CD_LINEOUT)
    1653           0 :                                         this->nout_jacks++;
    1654           0 :                                 else if (w->d.pin.device == CORB_CD_HEADPHONE &&
    1655           0 :                                     CORB_CD_LOC_GEO(w->d.pin.config) ==
    1656             :                                     CORB_CD_FRONT) {
    1657           0 :                                         this->fhp = i;
    1658           0 :                                         this->fhp_dac =
    1659           0 :                                             azalia_codec_find_defdac(this, i, 0);
    1660           0 :                                 }
    1661           0 :                                 if (this->nsense_pins >= HDA_MAX_SENSE_PINS ||
    1662           0 :                                     !(w->d.pin.cap & COP_PINCAP_PRESENCE))
    1663             :                                         break;
    1664             :                                 /* check override bit */
    1665           0 :                                 err = azalia_comresp(this, i,
    1666             :                                     CORB_GET_CONFIGURATION_DEFAULT, 0, &result);
    1667           0 :                                 if (err)
    1668             :                                         break;
    1669           0 :                                 if (!(CORB_CD_MISC(result) & CORB_CD_PRESENCEOV)) {
    1670           0 :                                         this->sense_pins[this->nsense_pins++] = i;
    1671           0 :                                 }
    1672             :                                 break;
    1673             :                         }
    1674           0 :                         if ((w->d.pin.device == CORB_CD_DIGITALOUT) &&
    1675           0 :                             (w->d.pin.cap & COP_PINCAP_HDMI))
    1676           0 :                                 nhdmi++;
    1677           0 :                         else if (w->d.pin.device == CORB_CD_SPDIFOUT ||
    1678           0 :                             w->d.pin.device == CORB_CD_SPDIFIN)
    1679           0 :                                 nspdif++;
    1680             :                         break;
    1681             :                 }
    1682             :         }
    1683           0 :         this->codec_type = AZ_CODEC_TYPE_ANALOG;
    1684           0 :         if ((this->na_dacs == 0) && (this->na_adcs == 0)) {
    1685           0 :                 this->codec_type = AZ_CODEC_TYPE_DIGITAL;
    1686           0 :                 if (nspdif == 0 && nhdmi > 0)
    1687           0 :                         this->codec_type = AZ_CODEC_TYPE_HDMI;
    1688             :         }
    1689             : 
    1690             :         /* make sure built-in mic is connected to an adc */
    1691           0 :         if (this->mic != -1 && this->mic_adc == -1) {
    1692           0 :                 if (azalia_codec_select_micadc(this)) {
    1693             :                         DPRINTF(("%s: cound not select mic adc\n", __func__));
    1694             :                 }
    1695           0 :         }
    1696             : 
    1697           0 :         err = azalia_codec_sort_pins(this);
    1698           0 :         if (err)
    1699           0 :                 return err;
    1700             : 
    1701           0 :         err = azalia_codec_find_inputmixer(this);
    1702           0 :         if (err)
    1703           0 :                 return err;
    1704             : 
    1705             :         /* If the codec can do multichannel, select different DACs for
    1706             :          * the multichannel jack group.  Also be sure to keep track of
    1707             :          * which DAC the front headphone is connected to.
    1708             :          */
    1709           0 :         if (this->na_dacs >= 3 && this->nopins >= 3) {
    1710           0 :                 err = azalia_codec_select_dacs(this);
    1711           0 :                 if (err)
    1712           0 :                         return err;
    1713             :         }
    1714             : 
    1715           0 :         err = azalia_codec_select_spkrdac(this);
    1716           0 :         if (err)
    1717           0 :                 return err;
    1718             : 
    1719           0 :         err = azalia_init_dacgroup(this);
    1720           0 :         if (err)
    1721           0 :                 return err;
    1722             : 
    1723           0 :         azalia_codec_print_groups(this);
    1724             : 
    1725           0 :         err = azalia_widget_label_widgets(this);
    1726           0 :         if (err)
    1727           0 :                 return err;
    1728             : 
    1729           0 :         err = azalia_codec_construct_format(this, 0, 0);
    1730           0 :         if (err)
    1731           0 :                 return err;
    1732             : 
    1733           0 :         err = azalia_codec_init_volgroups(this);
    1734           0 :         if (err)
    1735           0 :                 return err;
    1736             : 
    1737           0 :         if (this->qrks & AZ_QRK_GPIO_MASK) {
    1738           0 :                 err = azalia_codec_gpio_quirks(this);
    1739           0 :                 if (err)
    1740           0 :                         return err;
    1741             :         }
    1742             : 
    1743           0 :         err = azalia_mixer_init(this);
    1744           0 :         if (err)
    1745           0 :                 return err;
    1746             : 
    1747           0 :         return 0;
    1748           0 : }
    1749             : 
    1750             : int
    1751           0 : azalia_codec_find_inputmixer(codec_t *this)
    1752             : {
    1753             :         widget_t *w;
    1754             :         int i, j;
    1755             : 
    1756           0 :         this->input_mixer = -1;
    1757             : 
    1758           0 :         FOR_EACH_WIDGET(this, i) {
    1759           0 :                 w = &this->w[i];
    1760           0 :                 if (w->type != COP_AWTYPE_AUDIO_MIXER)
    1761             :                         continue;
    1762             : 
    1763             :                 /* can input from a pin */
    1764           0 :                 for (j = 0; j < this->nipins; j++) {
    1765           0 :                         if (azalia_codec_fnode(this, this->ipins[j].nid,
    1766           0 :                             w->nid, 0) != -1)
    1767             :                                 break;
    1768             :                 }
    1769           0 :                 if (j == this->nipins)
    1770             :                         continue;
    1771             : 
    1772             :                 /* can output to a pin */
    1773           0 :                 for (j = 0; j < this->nopins; j++) {
    1774           0 :                         if (azalia_codec_fnode(this, w->nid,
    1775           0 :                             this->opins[j].nid, 0) != -1)
    1776             :                                 break;
    1777             :                 }
    1778           0 :                 if (j == this->nopins)
    1779             :                         continue;
    1780             : 
    1781             :                 /* can output to an ADC */
    1782           0 :                 for (j = 0; j < this->na_adcs; j++) {
    1783           0 :                         if (azalia_codec_fnode(this, w->nid,
    1784           0 :                             this->a_adcs[j], 0) != -1)
    1785             :                                 break;
    1786             :                 }
    1787           0 :                 if (j == this->na_adcs)
    1788             :                         continue;
    1789             : 
    1790           0 :                 this->input_mixer = i;
    1791           0 :                 break;
    1792             :         }
    1793           0 :         return(0);
    1794             : }
    1795             : 
    1796             : int
    1797           0 : azalia_codec_select_micadc(codec_t *this)
    1798             : {
    1799             :         widget_t *w;
    1800             :         int i, j, conv, err;
    1801             : 
    1802           0 :         for (i = 0; i < this->na_adcs; i++) {
    1803           0 :                 if (azalia_codec_fnode(this, this->mic,
    1804           0 :                     this->a_adcs[i], 0) >= 0)
    1805             :                         break;
    1806             :         }
    1807           0 :         if (i >= this->na_adcs)
    1808           0 :                 return(-1);
    1809           0 :         conv = this->a_adcs[i];
    1810             : 
    1811           0 :         w = &this->w[conv];
    1812           0 :         for (j = 0; j < 10; j++) {
    1813           0 :                 for (i = 0; i < w->nconnections; i++) {
    1814           0 :                         if (!azalia_widget_enabled(this, w->connections[i]))
    1815             :                                 continue;
    1816           0 :                         if (azalia_codec_fnode(this, this->mic,
    1817           0 :                             w->connections[i], j + 1) >= 0) {
    1818             :                                 break;
    1819             :                         }
    1820             :                 }
    1821           0 :                 if (i >= w->nconnections)
    1822           0 :                         return(-1);
    1823           0 :                 err = azalia_comresp(this, w->nid,
    1824             :                     CORB_SET_CONNECTION_SELECT_CONTROL, i, 0);
    1825           0 :                 if (err)
    1826           0 :                         return(err);
    1827           0 :                 w->selected = i;
    1828           0 :                 if (w->connections[i] == this->mic) {
    1829           0 :                         this->mic_adc = conv;
    1830           0 :                         return(0);
    1831             :                 }
    1832           0 :                 w = &this->w[w->connections[i]];
    1833             :         }
    1834           0 :         return(-1);
    1835           0 : }
    1836             : 
    1837             : int
    1838           0 : azalia_codec_sort_pins(codec_t *this)
    1839             : {
    1840             : #define MAX_PINS        16
    1841             :         const widget_t *w;
    1842           0 :         struct io_pin opins[MAX_PINS], opins_d[MAX_PINS];
    1843           0 :         struct io_pin ipins[MAX_PINS], ipins_d[MAX_PINS];
    1844             :         int nopins, nopins_d, nipins, nipins_d;
    1845             :         int prio, loc, add, nd, conv;
    1846             :         int i, j, k;
    1847             : 
    1848             :         nopins = nopins_d = nipins = nipins_d = 0;
    1849             : 
    1850           0 :         FOR_EACH_WIDGET(this, i) {
    1851           0 :                 w = &this->w[i];
    1852           0 :                 if (!w->enable || w->type != COP_AWTYPE_PIN_COMPLEX)
    1853             :                         continue;
    1854             : 
    1855             :                 loc = 0;
    1856           0 :                 if (this->na_dacs >= 3 && this->nout_jacks < 3)
    1857           0 :                         loc = CORB_CD_LOC_GEO(w->d.pin.config);
    1858             : 
    1859           0 :                 prio = w->d.pin.association << 4 | w->d.pin.sequence;
    1860             :                 conv = -1;
    1861             : 
    1862             :                 /* analog out */
    1863           0 :                 if ((w->d.pin.cap & COP_PINCAP_OUTPUT) && 
    1864           0 :                     !(w->widgetcap & COP_AWCAP_DIGITAL)) {
    1865             :                         add = nd = 0;
    1866           0 :                         conv = azalia_codec_find_defdac(this, w->nid, 0);
    1867           0 :                         switch(w->d.pin.device) {
    1868             :                         /* primary - output by default */
    1869             :                         case CORB_CD_SPEAKER:
    1870           0 :                                 if (w->nid == this->speaker ||
    1871           0 :                                     w->nid == this->speaker2)
    1872             :                                         break;
    1873             :                                 /* FALLTHROUGH */
    1874             :                         case CORB_CD_HEADPHONE:
    1875             :                         case CORB_CD_LINEOUT:
    1876             :                                 add = 1;
    1877           0 :                                 break;
    1878             :                         /* secondary - input by default */
    1879             :                         case CORB_CD_MICIN:
    1880           0 :                                 if (w->nid == this->mic)
    1881             :                                         break;
    1882             :                                 /* FALLTHROUGH */
    1883             :                         case CORB_CD_LINEIN:
    1884             :                                 add = nd = 1;
    1885           0 :                                 break;
    1886             :                         }
    1887           0 :                         if (add && nopins < MAX_PINS) {
    1888           0 :                                 opins[nopins].nid = w->nid;
    1889           0 :                                 opins[nopins].conv = conv;
    1890           0 :                                 prio |= (nd << 8) | (loc << 9);
    1891           0 :                                 opins[nopins].prio = prio;
    1892           0 :                                 nopins++;
    1893           0 :                         }
    1894             :                 }
    1895             :                 /* digital out */
    1896           0 :                 if ((w->d.pin.cap & COP_PINCAP_OUTPUT) && 
    1897           0 :                     (w->widgetcap & COP_AWCAP_DIGITAL)) {
    1898           0 :                         conv = azalia_codec_find_defdac(this, w->nid, 0);
    1899           0 :                         switch(w->d.pin.device) {
    1900             :                         case CORB_CD_SPDIFOUT:
    1901             :                         case CORB_CD_DIGITALOUT:
    1902           0 :                                 if (nopins_d < MAX_PINS) {
    1903           0 :                                         opins_d[nopins_d].nid = w->nid;
    1904           0 :                                         opins_d[nopins_d].conv = conv;
    1905           0 :                                         opins_d[nopins_d].prio = prio;
    1906           0 :                                         nopins_d++;
    1907           0 :                                 }
    1908             :                                 break;
    1909             :                         }
    1910             :                 }
    1911             :                 /* analog in */
    1912           0 :                 if ((w->d.pin.cap & COP_PINCAP_INPUT) &&
    1913           0 :                     !(w->widgetcap & COP_AWCAP_DIGITAL)) {
    1914             :                         add = nd = 0;
    1915           0 :                         conv = azalia_codec_find_defadc(this, w->nid, 0);
    1916           0 :                         switch(w->d.pin.device) {
    1917             :                         /* primary - input by default */
    1918             :                         case CORB_CD_MICIN:
    1919             :                         case CORB_CD_LINEIN:
    1920             :                                 add = 1;
    1921           0 :                                 break;
    1922             :                         /* secondary - output by default */
    1923             :                         case CORB_CD_SPEAKER:
    1924           0 :                                 if (w->nid == this->speaker ||
    1925           0 :                                     w->nid == this->speaker2)
    1926             :                                         break;
    1927             :                                 /* FALLTHROUGH */
    1928             :                         case CORB_CD_HEADPHONE:
    1929             :                         case CORB_CD_LINEOUT:
    1930             :                                 add = nd = 1;
    1931           0 :                                 break;
    1932             :                         }
    1933           0 :                         if (add && nipins < MAX_PINS) {
    1934           0 :                                 ipins[nipins].nid = w->nid;
    1935           0 :                                 ipins[nipins].prio = prio | (nd << 8);
    1936           0 :                                 ipins[nipins].conv = conv;
    1937           0 :                                 nipins++;
    1938           0 :                         }
    1939             :                 }
    1940             :                 /* digital in */
    1941           0 :                 if ((w->d.pin.cap & COP_PINCAP_INPUT) && 
    1942           0 :                     (w->widgetcap & COP_AWCAP_DIGITAL)) {
    1943           0 :                         conv = azalia_codec_find_defadc(this, w->nid, 0);
    1944           0 :                         switch(w->d.pin.device) {
    1945             :                         case CORB_CD_SPDIFIN:
    1946             :                         case CORB_CD_DIGITALIN:
    1947             :                         case CORB_CD_MICIN:
    1948           0 :                                 if (nipins_d < MAX_PINS) {
    1949           0 :                                         ipins_d[nipins_d].nid = w->nid;
    1950           0 :                                         ipins_d[nipins_d].prio = prio;
    1951           0 :                                         ipins_d[nipins_d].conv = conv;
    1952           0 :                                         nipins_d++;
    1953           0 :                                 }
    1954             :                                 break;
    1955             :                         }
    1956             :                 }
    1957             :         }
    1958             : 
    1959           0 :         this->opins = mallocarray(nopins, sizeof(struct io_pin), M_DEVBUF,
    1960             :             M_NOWAIT | M_ZERO);
    1961           0 :         if (this->opins == NULL)
    1962           0 :                 return(ENOMEM);
    1963           0 :         this->nopins = 0;
    1964           0 :         for (i = 0; i < nopins; i++) {
    1965           0 :                 for (j = 0; j < this->nopins; j++)
    1966           0 :                         if (this->opins[j].prio > opins[i].prio)
    1967             :                                 break;
    1968           0 :                 for (k = this->nopins; k > j; k--)
    1969           0 :                         this->opins[k] = this->opins[k - 1];
    1970           0 :                 if (j < nopins)
    1971           0 :                         this->opins[j] = opins[i];
    1972           0 :                 this->nopins++;
    1973           0 :                 if (this->nopins == nopins)
    1974             :                         break;
    1975             :         }
    1976             : 
    1977           0 :         this->opins_d = mallocarray(nopins_d, sizeof(struct io_pin), M_DEVBUF,
    1978             :             M_NOWAIT | M_ZERO);
    1979           0 :         if (this->opins_d == NULL)
    1980           0 :                 return(ENOMEM);
    1981           0 :         this->nopins_d = 0;
    1982           0 :         for (i = 0; i < nopins_d; i++) {
    1983           0 :                 for (j = 0; j < this->nopins_d; j++)
    1984           0 :                         if (this->opins_d[j].prio > opins_d[i].prio)
    1985             :                                 break;
    1986           0 :                 for (k = this->nopins_d; k > j; k--)
    1987           0 :                         this->opins_d[k] = this->opins_d[k - 1];
    1988           0 :                 if (j < nopins_d)
    1989           0 :                         this->opins_d[j] = opins_d[i];
    1990           0 :                 this->nopins_d++;
    1991           0 :                 if (this->nopins_d == nopins_d)
    1992             :                         break;
    1993             :         }
    1994             : 
    1995           0 :         this->ipins = mallocarray(nipins, sizeof(struct io_pin), M_DEVBUF,
    1996             :             M_NOWAIT | M_ZERO);
    1997           0 :         if (this->ipins == NULL)
    1998           0 :                 return(ENOMEM);
    1999           0 :         this->nipins = 0;
    2000           0 :         for (i = 0; i < nipins; i++) {
    2001           0 :                 for (j = 0; j < this->nipins; j++)
    2002           0 :                         if (this->ipins[j].prio > ipins[i].prio)
    2003             :                                 break;
    2004           0 :                 for (k = this->nipins; k > j; k--)
    2005           0 :                         this->ipins[k] = this->ipins[k - 1];
    2006           0 :                 if (j < nipins)
    2007           0 :                         this->ipins[j] = ipins[i];
    2008           0 :                 this->nipins++;
    2009           0 :                 if (this->nipins == nipins)
    2010             :                         break;
    2011             :         }
    2012             : 
    2013           0 :         this->ipins_d = mallocarray(nipins_d, sizeof(struct io_pin), M_DEVBUF,
    2014             :             M_NOWAIT | M_ZERO);
    2015           0 :         if (this->ipins_d == NULL)
    2016           0 :                 return(ENOMEM);
    2017           0 :         this->nipins_d = 0;
    2018           0 :         for (i = 0; i < nipins_d; i++) {
    2019           0 :                 for (j = 0; j < this->nipins_d; j++)
    2020           0 :                         if (this->ipins_d[j].prio > ipins_d[i].prio)
    2021             :                                 break;
    2022           0 :                 for (k = this->nipins_d; k > j; k--)
    2023           0 :                         this->ipins_d[k] = this->ipins_d[k - 1];
    2024           0 :                 if (j < nipins_d)
    2025           0 :                         this->ipins_d[j] = ipins_d[i];
    2026           0 :                 this->nipins_d++;
    2027           0 :                 if (this->nipins_d == nipins_d)
    2028             :                         break;
    2029             :         }
    2030             : 
    2031             : #ifdef AZALIA_DEBUG
    2032             :         printf("%s: analog out pins:", __func__);
    2033             :         for (i = 0; i < this->nopins; i++)
    2034             :                 printf(" 0x%2.2x->0x%2.2x", this->opins[i].nid,
    2035             :                     this->opins[i].conv);
    2036             :         printf("\n");
    2037             :         printf("%s: digital out pins:", __func__);
    2038             :         for (i = 0; i < this->nopins_d; i++)
    2039             :                 printf(" 0x%2.2x->0x%2.2x", this->opins_d[i].nid,
    2040             :                     this->opins_d[i].conv);
    2041             :         printf("\n");
    2042             :         printf("%s: analog in pins:", __func__);
    2043             :         for (i = 0; i < this->nipins; i++)
    2044             :                 printf(" 0x%2.2x->0x%2.2x", this->ipins[i].nid,
    2045             :                     this->ipins[i].conv);
    2046             :         printf("\n");
    2047             :         printf("%s: digital in pins:", __func__);
    2048             :         for (i = 0; i < this->nipins_d; i++)
    2049             :                 printf(" 0x%2.2x->0x%2.2x", this->ipins_d[i].nid,
    2050             :                     this->ipins_d[i].conv);
    2051             :         printf("\n");
    2052             : #endif
    2053             : 
    2054           0 :         return 0;
    2055             : #undef MAX_PINS
    2056           0 : }
    2057             : 
    2058             : int
    2059           0 : azalia_codec_select_dacs(codec_t *this)
    2060             : {
    2061             :         widget_t *w;
    2062             :         nid_t *convs;
    2063             :         int nconv, conv;
    2064             :         int i, j, k, err;
    2065             : 
    2066           0 :         convs = mallocarray(this->na_dacs, sizeof(nid_t), M_DEVBUF,
    2067             :             M_NOWAIT | M_ZERO);
    2068           0 :         if (convs == NULL)
    2069           0 :                 return(ENOMEM);
    2070             : 
    2071             :         err = 0;
    2072             :         nconv = 0;
    2073           0 :         for (i = 0; i < this->nopins; i++) {
    2074           0 :                 w = &this->w[this->opins[i].nid];
    2075             : 
    2076           0 :                 conv = this->opins[i].conv;
    2077           0 :                 for (j = 0; j < nconv; j++) {
    2078           0 :                         if (conv == convs[j])
    2079             :                                 break;
    2080             :                 }
    2081           0 :                 if (j == nconv) {
    2082           0 :                         convs[nconv++] = conv;
    2083           0 :                         if (w->nid == this->fhp)
    2084           0 :                                 this->fhp_dac = conv;
    2085           0 :                         if (nconv >= this->na_dacs) {
    2086             :                                 break;
    2087             :                         }
    2088             :                 } else {
    2089             :                         /* find a different dac */
    2090             :                         conv = -1;
    2091           0 :                         for (j = 0; j < w->nconnections; j++) {
    2092           0 :                                 if (!azalia_widget_enabled(this,
    2093           0 :                                     w->connections[j]))
    2094             :                                         continue;
    2095           0 :                                 conv = azalia_codec_find_defdac(this,
    2096           0 :                                     w->connections[j], 1);
    2097           0 :                                 if (conv == -1)
    2098             :                                         continue;
    2099           0 :                                 for (k = 0; k < nconv; k++) {
    2100           0 :                                         if (conv == convs[k])
    2101             :                                                 break;
    2102             :                                 }
    2103           0 :                                 if (k == nconv)
    2104             :                                         break;
    2105             :                         }
    2106           0 :                         if (j < w->nconnections && conv != -1) {
    2107           0 :                                 err = azalia_comresp(this, w->nid,
    2108             :                                     CORB_SET_CONNECTION_SELECT_CONTROL, j, 0);
    2109           0 :                                 if (err)
    2110             :                                         break;
    2111           0 :                                 w->selected = j;
    2112           0 :                                 this->opins[i].conv = conv;
    2113           0 :                                 if (w->nid == this->fhp)
    2114           0 :                                         this->fhp_dac = conv;
    2115           0 :                                 convs[nconv++] = conv;
    2116           0 :                                 if (nconv >= this->na_dacs)
    2117             :                                         break;
    2118             :                         }
    2119             :                 }
    2120             :         }
    2121             : 
    2122           0 :         free(convs, M_DEVBUF, this->na_dacs * sizeof(nid_t));
    2123           0 :         return(err);
    2124           0 : }
    2125             : 
    2126             : /* Connect the speaker to a DAC that no other output pin is connected
    2127             :  * to by default.  If that is not possible, connect to a DAC other
    2128             :  * than the one the first output pin is connected to. 
    2129             :  */
    2130             : int
    2131           0 : azalia_codec_select_spkrdac(codec_t *this)
    2132             : {
    2133             :         widget_t *w;
    2134           0 :         nid_t convs[HDA_MAX_CHANNELS];
    2135             :         int nconv, conv;
    2136             :         int i, j, err, fspkr, conn;
    2137             : 
    2138             :         nconv = fspkr = 0;
    2139           0 :         for (i = 0; i < this->nopins; i++) {
    2140           0 :                 conv = this->opins[i].conv;
    2141           0 :                 for (j = 0; j < nconv; j++) {
    2142           0 :                         if (conv == convs[j])
    2143             :                                 break;
    2144             :                 }
    2145           0 :                 if (j == nconv) {
    2146           0 :                         if (conv == this->spkr_dac)
    2147           0 :                                 fspkr = 1;
    2148           0 :                         convs[nconv++] = conv;
    2149           0 :                         if (nconv == this->na_dacs)
    2150             :                                 break;
    2151             :                 }
    2152             :         }
    2153             : 
    2154           0 :         if (fspkr) {
    2155             :                 conn = conv = -1;
    2156           0 :                 w = &this->w[this->speaker];
    2157           0 :                 for (i = 0; i < w->nconnections; i++) {
    2158           0 :                         conv = azalia_codec_find_defdac(this,
    2159           0 :                             w->connections[i], 1);
    2160           0 :                         for (j = 0; j < nconv; j++)
    2161           0 :                                 if (conv == convs[j])
    2162             :                                         break;
    2163           0 :                         if (j == nconv)
    2164             :                                 break;
    2165             :                 }
    2166           0 :                 if (i < w->nconnections) {
    2167             :                         conn = i;
    2168           0 :                 } else {
    2169             :                         /* Couldn't get a unique DAC.  Try to get a diferent
    2170             :                          * DAC than the first pin's DAC.
    2171             :                          */
    2172           0 :                         if (this->spkr_dac == this->opins[0].conv) {
    2173             :                                 /* If the speaker connection can't be changed,
    2174             :                                  * change the first pin's connection.
    2175             :                                  */
    2176           0 :                                 if (w->nconnections == 1)
    2177           0 :                                         w = &this->w[this->opins[0].nid];
    2178           0 :                                 for (j = 0; j < w->nconnections; j++) {
    2179           0 :                                         conv = azalia_codec_find_defdac(this,
    2180           0 :                                             w->connections[j], 1);
    2181           0 :                                         if (conv != this->opins[0].conv) {
    2182             :                                                 conn = j;
    2183           0 :                                                 break;
    2184             :                                         }
    2185             :                                 }
    2186             :                         }
    2187             :                 }
    2188           0 :                 if (conn != -1 && conv != -1) {
    2189           0 :                         err = azalia_comresp(this, w->nid,
    2190             :                             CORB_SET_CONNECTION_SELECT_CONTROL, conn, 0);
    2191           0 :                         if (err)
    2192           0 :                                 return(err);
    2193           0 :                         w->selected = conn;
    2194           0 :                         if (w->nid == this->speaker)
    2195           0 :                                 this->spkr_dac = conv;
    2196             :                         else
    2197           0 :                                 this->opins[0].conv = conv;
    2198             :                 }
    2199             :         }
    2200             : 
    2201             :         /* If there is a speaker2, try to connect it to spkr_dac. */
    2202           0 :         if (this->speaker2 != -1) {
    2203             :                 conn = conv = -1;
    2204           0 :                 w = &this->w[this->speaker2];
    2205           0 :                 for (i = 0; i < w->nconnections; i++) {
    2206           0 :                         conv = azalia_codec_find_defdac(this,
    2207           0 :                             w->connections[i], 1);
    2208           0 :                         if (conv == this->spkr_dac) {
    2209             :                                 conn = i;
    2210           0 :                                 break;
    2211             :                         }
    2212             :                 }
    2213           0 :                 if (conn != -1) {
    2214           0 :                         err = azalia_comresp(this, w->nid,
    2215             :                             CORB_SET_CONNECTION_SELECT_CONTROL, conn, 0);
    2216           0 :                         if (err)
    2217           0 :                                 return(err);
    2218           0 :                         w->selected = conn;
    2219           0 :                 }
    2220             :         }
    2221             : 
    2222           0 :         return(0);
    2223           0 : }
    2224             : 
    2225             : int
    2226           0 : azalia_codec_find_defdac(codec_t *this, int index, int depth)
    2227             : {
    2228             :         const widget_t *w;
    2229             :         int i, ret;
    2230             : 
    2231           0 :         w = &this->w[index];
    2232           0 :         if (w->enable == 0)
    2233           0 :                 return -1;
    2234             : 
    2235           0 :         if (w->type == COP_AWTYPE_AUDIO_OUTPUT)
    2236           0 :                 return index;
    2237             : 
    2238           0 :         if (depth > 0 &&
    2239           0 :             (w->type == COP_AWTYPE_PIN_COMPLEX ||
    2240           0 :             w->type == COP_AWTYPE_BEEP_GENERATOR ||
    2241           0 :             w->type == COP_AWTYPE_AUDIO_INPUT))
    2242           0 :                 return -1;
    2243           0 :         if (++depth >= 10)
    2244           0 :                 return -1;
    2245             : 
    2246           0 :         if (w->nconnections > 0) {
    2247             :                 /* by default, all mixer connections are active */
    2248           0 :                 if (w->type == COP_AWTYPE_AUDIO_MIXER) {
    2249           0 :                         for (i = 0; i < w->nconnections; i++) {
    2250           0 :                                 index = w->connections[i];
    2251           0 :                                 if (!azalia_widget_enabled(this, index))
    2252             :                                         continue;
    2253           0 :                                 ret = azalia_codec_find_defdac(this, index,
    2254             :                                     depth);
    2255           0 :                                 if (ret >= 0)
    2256           0 :                                         return ret;
    2257             :                         }
    2258             :                 /* 7.3.3.2 Connection Select Control
    2259             :                  * If an attempt is made to Set an index value greater than
    2260             :                  * the number of list entries (index is equal to or greater
    2261             :                  * than the Connection List Length property for the widget)
    2262             :                  * the behavior is not predictable.
    2263             :                  */
    2264             : 
    2265             :                 /* negative index values are wrong too */
    2266           0 :                 } else if (w->selected >= 0 &&
    2267           0 :                         w->selected < sizeof(w->connections)) {
    2268           0 :                                 index = w->connections[w->selected];
    2269           0 :                                 if (VALID_WIDGET_NID(index, this)) {
    2270           0 :                                         ret = azalia_codec_find_defdac(this,
    2271             :                                                 index, depth);
    2272           0 :                                         if (ret >= 0)
    2273           0 :                                                 return ret;
    2274             :                                 }
    2275             :                 }
    2276             :         }
    2277             : 
    2278           0 :         return -1;
    2279           0 : }
    2280             : 
    2281             : int
    2282           0 : azalia_codec_find_defadc_sub(codec_t *this, nid_t node, int index, int depth)
    2283             : {
    2284             :         const widget_t *w;
    2285             :         int i, ret;
    2286             : 
    2287           0 :         w = &this->w[index];
    2288           0 :         if (w->nid == node) {
    2289           0 :                 return index;
    2290             :         }
    2291             :         /* back at the beginning or a bad end */
    2292           0 :         if (depth > 0 &&
    2293           0 :             (w->type == COP_AWTYPE_PIN_COMPLEX ||
    2294           0 :             w->type == COP_AWTYPE_BEEP_GENERATOR ||
    2295           0 :             w->type == COP_AWTYPE_AUDIO_OUTPUT ||
    2296           0 :             w->type == COP_AWTYPE_AUDIO_INPUT))
    2297           0 :                 return -1;
    2298           0 :         if (++depth >= 10)
    2299           0 :                 return -1;
    2300             : 
    2301           0 :         if (w->nconnections > 0) {
    2302             :                 /* by default, all mixer connections are active */
    2303           0 :                 if (w->type == COP_AWTYPE_AUDIO_MIXER) {
    2304           0 :                         for (i = 0; i < w->nconnections; i++) {
    2305           0 :                                 if (!azalia_widget_enabled(this, w->connections[i]))
    2306             :                                         continue;
    2307           0 :                                 ret = azalia_codec_find_defadc_sub(this, node,
    2308           0 :                                     w->connections[i], depth);
    2309           0 :                                 if (ret >= 0)
    2310           0 :                                         return ret;
    2311             :                         }
    2312             :                 /* 7.3.3.2 Connection Select Control
    2313             :                  * If an attempt is made to Set an index value greater than
    2314             :                  * the number of list entries (index is equal to or greater
    2315             :                  * than the Connection List Length property for the widget)
    2316             :                  * the behavior is not predictable.
    2317             :                  */
    2318             : 
    2319             :                 /* negative index values are wrong too */
    2320           0 :                 } else if (w->selected >= 0 &&
    2321           0 :                         w->selected < sizeof(w->connections)) {
    2322           0 :                                 index = w->connections[w->selected];
    2323           0 :                                 if (VALID_WIDGET_NID(index, this)) {
    2324           0 :                                         ret = azalia_codec_find_defadc_sub(this,
    2325             :                                                 node, index, depth);
    2326           0 :                                         if (ret >= 0)
    2327           0 :                                                 return ret;
    2328             :                                 }
    2329             :                 }
    2330             :         }
    2331           0 :         return -1;
    2332           0 : }
    2333             : 
    2334             : int
    2335           0 : azalia_codec_find_defadc(codec_t *this, int index, int depth)
    2336             : {
    2337             :         int i, j, conv;
    2338             : 
    2339             :         conv = -1;
    2340           0 :         for (i = 0; i < this->na_adcs; i++) {
    2341           0 :                 j = azalia_codec_find_defadc_sub(this, index,
    2342           0 :                     this->a_adcs[i], 0);
    2343           0 :                 if (j >= 0) {
    2344           0 :                         conv = this->a_adcs[i];
    2345           0 :                         break;
    2346             :                 }
    2347             :         }
    2348           0 :         return(conv);
    2349             : }
    2350             : 
    2351             : int
    2352           0 : azalia_codec_init_volgroups(codec_t *this)
    2353             : {
    2354             :         const widget_t *w;
    2355           0 :         uint32_t cap, result;
    2356             :         int i, j, dac, err;
    2357             : 
    2358             :         j = 0;
    2359           0 :         this->playvols.mask = 0;
    2360           0 :         FOR_EACH_WIDGET(this, i) {
    2361           0 :                 w = &this->w[i];
    2362           0 :                 if (w->enable == 0)
    2363             :                         continue;
    2364           0 :                 if (w->mixer_class == AZ_CLASS_RECORD)
    2365             :                         continue;
    2366           0 :                 if (!(w->widgetcap & COP_AWCAP_OUTAMP))
    2367             :                         continue;
    2368           0 :                 if ((COP_AMPCAP_NUMSTEPS(w->outamp_cap) == 0) &&
    2369           0 :                     !(w->outamp_cap & COP_AMPCAP_MUTE))
    2370             :                         continue;
    2371           0 :                 this->playvols.mask |= (1 << j);
    2372           0 :                 this->playvols.slaves[j++] = w->nid;
    2373           0 :                 if (j >= AZ_MAX_VOL_SLAVES)
    2374             :                         break;
    2375             :         }
    2376           0 :         this->playvols.nslaves = j;
    2377             : 
    2378           0 :         this->playvols.cur = 0;
    2379           0 :         for (i = 0; i < this->playvols.nslaves; i++) {
    2380           0 :                 w = &this->w[this->playvols.slaves[i]];
    2381           0 :                 if (w->nid == this->input_mixer ||
    2382           0 :                     w->parent == this->input_mixer ||
    2383           0 :                     WIDGET_CHANNELS(w) < 2)
    2384             :                         continue;
    2385             :                 j = 0;
    2386             :                 /* azalia_codec_find_defdac only goes 10 connections deep.
    2387             :                  * Start the connection depth at 7 so it doesn't go more
    2388             :                  * than 3 connections deep.
    2389             :                  */
    2390           0 :                 if (w->type == COP_AWTYPE_AUDIO_MIXER ||
    2391           0 :                     w->type == COP_AWTYPE_AUDIO_SELECTOR)
    2392           0 :                         j = 7;
    2393           0 :                 dac = azalia_codec_find_defdac(this, w->nid, j);
    2394           0 :                 if (dac == -1)
    2395             :                         continue;
    2396           0 :                 if (dac != this->dacs.groups[this->dacs.cur].conv[0] &&
    2397           0 :                     dac != this->spkr_dac && dac != this->fhp_dac)
    2398             :                         continue;
    2399           0 :                 cap = w->outamp_cap;
    2400           0 :                 if ((cap & COP_AMPCAP_MUTE) && COP_AMPCAP_NUMSTEPS(cap)) {
    2401           0 :                         if (w->type == COP_AWTYPE_BEEP_GENERATOR) {
    2402             :                                 continue;
    2403           0 :                         } else if (w->type == COP_AWTYPE_PIN_COMPLEX) {
    2404           0 :                                 err = azalia_comresp(this, w->nid,
    2405             :                                     CORB_GET_PIN_WIDGET_CONTROL, 0, &result);
    2406           0 :                                 if (!err && (result & CORB_PWC_OUTPUT))
    2407           0 :                                         this->playvols.cur |= (1 << i);
    2408             :                         } else
    2409           0 :                                 this->playvols.cur |= (1 << i);
    2410             :                 }
    2411             :         }
    2412           0 :         if (this->playvols.cur == 0) {
    2413           0 :                 for (i = 0; i < this->playvols.nslaves; i++) {
    2414           0 :                         w = &this->w[this->playvols.slaves[i]];
    2415             :                         j = 0;
    2416           0 :                         if (w->type == COP_AWTYPE_AUDIO_MIXER ||
    2417           0 :                             w->type == COP_AWTYPE_AUDIO_SELECTOR)
    2418           0 :                                 j = 7;
    2419           0 :                         dac = azalia_codec_find_defdac(this, w->nid, j);
    2420           0 :                         if (dac == -1)
    2421             :                                 continue;
    2422           0 :                         if (dac != this->dacs.groups[this->dacs.cur].conv[0] &&
    2423           0 :                             dac != this->spkr_dac && dac != this->fhp_dac)
    2424             :                                 continue;
    2425           0 :                         if (w->type == COP_AWTYPE_BEEP_GENERATOR)
    2426             :                                 continue;
    2427           0 :                         if (w->type == COP_AWTYPE_PIN_COMPLEX) {
    2428           0 :                                 err = azalia_comresp(this, w->nid,
    2429             :                                     CORB_GET_PIN_WIDGET_CONTROL, 0, &result);
    2430           0 :                                 if (!err && (result & CORB_PWC_OUTPUT))
    2431           0 :                                         this->playvols.cur |= (1 << i);
    2432             :                         } else {
    2433           0 :                                 this->playvols.cur |= (1 << i);
    2434             :                         }
    2435             :                 }
    2436             :         }
    2437             : 
    2438           0 :         this->playvols.master = this->audiofunc;
    2439           0 :         if (this->playvols.nslaves > 0) {
    2440           0 :                 FOR_EACH_WIDGET(this, i) {
    2441           0 :                         w = &this->w[i];
    2442           0 :                         if (w->type != COP_AWTYPE_VOLUME_KNOB)
    2443             :                                 continue;
    2444           0 :                         if (!COP_VKCAP_NUMSTEPS(w->d.volume.cap))
    2445             :                                 continue;
    2446           0 :                         this->playvols.master = w->nid;
    2447           0 :                         break;
    2448             :                 }
    2449             :         }
    2450             : 
    2451             :         j = 0;
    2452           0 :         this->recvols.mask = 0;
    2453           0 :         FOR_EACH_WIDGET(this, i) {
    2454           0 :                 w = &this->w[i];
    2455           0 :                 if (w->enable == 0)
    2456             :                         continue;
    2457           0 :                 if (w->type == COP_AWTYPE_AUDIO_INPUT ||
    2458           0 :                     w->type == COP_AWTYPE_PIN_COMPLEX) {
    2459           0 :                         if (!(w->widgetcap & COP_AWCAP_INAMP))
    2460             :                                 continue;
    2461           0 :                         if ((COP_AMPCAP_NUMSTEPS(w->inamp_cap) == 0) &&
    2462           0 :                             !(w->inamp_cap & COP_AMPCAP_MUTE))
    2463             :                                 continue;
    2464           0 :                 } else if (w->type == COP_AWTYPE_AUDIO_MIXER ||
    2465           0 :                     w->type == COP_AWTYPE_AUDIO_SELECTOR) {
    2466           0 :                         if (w->mixer_class != AZ_CLASS_RECORD)
    2467             :                                 continue;
    2468           0 :                         if (!(w->widgetcap & COP_AWCAP_OUTAMP))
    2469             :                                 continue;
    2470           0 :                         if ((COP_AMPCAP_NUMSTEPS(w->outamp_cap) == 0) &&
    2471           0 :                             !(w->outamp_cap & COP_AMPCAP_MUTE))
    2472             :                                 continue;
    2473             :                 } else {
    2474             :                         continue;
    2475             :                 }
    2476           0 :                 this->recvols.mask |= (1 << j);
    2477           0 :                 this->recvols.slaves[j++] = w->nid;
    2478           0 :                 if (j >= AZ_MAX_VOL_SLAVES)
    2479             :                         break;
    2480             :         }
    2481           0 :         this->recvols.nslaves = j;
    2482             : 
    2483           0 :         this->recvols.cur = 0;
    2484           0 :         for (i = 0; i < this->recvols.nslaves; i++) {
    2485           0 :                 w = &this->w[this->recvols.slaves[i]];
    2486           0 :                 cap = w->outamp_cap;
    2487           0 :                 if (w->type == COP_AWTYPE_AUDIO_INPUT ||
    2488           0 :                     w->type != COP_AWTYPE_PIN_COMPLEX)
    2489           0 :                         cap = w->inamp_cap;
    2490             :                  else
    2491           0 :                         if (w->mixer_class != AZ_CLASS_RECORD)
    2492             :                                 continue;
    2493           0 :                 if ((cap & COP_AMPCAP_MUTE) && COP_AMPCAP_NUMSTEPS(cap)) {
    2494           0 :                         if (w->type == COP_AWTYPE_PIN_COMPLEX) {
    2495           0 :                                 err = azalia_comresp(this, w->nid,
    2496             :                                     CORB_GET_PIN_WIDGET_CONTROL, 0, &result);
    2497           0 :                                 if (!err && !(result & CORB_PWC_OUTPUT))
    2498           0 :                                         this->recvols.cur |= (1 << i);
    2499             :                         } else
    2500           0 :                                 this->recvols.cur |= (1 << i);
    2501             :                 }
    2502             :         }
    2503           0 :         if (this->recvols.cur == 0) {
    2504           0 :                 for (i = 0; i < this->recvols.nslaves; i++) {
    2505           0 :                         w = &this->w[this->recvols.slaves[i]];
    2506           0 :                         cap = w->outamp_cap;
    2507           0 :                         if (w->type == COP_AWTYPE_AUDIO_INPUT ||
    2508           0 :                             w->type != COP_AWTYPE_PIN_COMPLEX)
    2509           0 :                                 cap = w->inamp_cap;
    2510             :                          else
    2511           0 :                                 if (w->mixer_class != AZ_CLASS_RECORD)
    2512             :                                         continue;
    2513           0 :                         if (w->type == COP_AWTYPE_PIN_COMPLEX) {
    2514           0 :                                 err = azalia_comresp(this, w->nid,
    2515             :                                     CORB_GET_PIN_WIDGET_CONTROL, 0, &result);
    2516           0 :                                 if (!err && !(result & CORB_PWC_OUTPUT))
    2517           0 :                                         this->recvols.cur |= (1 << i);
    2518             :                         } else {
    2519           0 :                                 this->recvols.cur |= (1 << i);
    2520             :                         }
    2521             :                 }
    2522             :         }
    2523             : 
    2524           0 :         this->recvols.master = this->audiofunc;
    2525             : 
    2526           0 :         return 0;
    2527           0 : }
    2528             : 
    2529             : int
    2530           0 : azalia_codec_delete(codec_t *this)
    2531             : {
    2532           0 :         azalia_mixer_delete(this);
    2533             : 
    2534           0 :         if (this->formats != NULL) {
    2535           0 :                 free(this->formats, M_DEVBUF, 0);
    2536           0 :                 this->formats = NULL;
    2537           0 :         }
    2538           0 :         this->nformats = 0;
    2539             : 
    2540           0 :         if (this->opins != NULL) {
    2541           0 :                 free(this->opins, M_DEVBUF, 0);
    2542           0 :                 this->opins = NULL;
    2543           0 :         }
    2544           0 :         this->nopins = 0;
    2545             : 
    2546           0 :         if (this->opins_d != NULL) {
    2547           0 :                 free(this->opins_d, M_DEVBUF, 0);
    2548           0 :                 this->opins_d = NULL;
    2549           0 :         }
    2550           0 :         this->nopins_d = 0;
    2551             : 
    2552           0 :         if (this->ipins != NULL) {
    2553           0 :                 free(this->ipins, M_DEVBUF, 0);
    2554           0 :                 this->ipins = NULL;
    2555           0 :         }
    2556           0 :         this->nipins = 0;
    2557             : 
    2558           0 :         if (this->ipins_d != NULL) {
    2559           0 :                 free(this->ipins_d, M_DEVBUF, 0);
    2560           0 :                 this->ipins_d = NULL;
    2561           0 :         }
    2562           0 :         this->nipins_d = 0;
    2563             : 
    2564           0 :         if (this->w != NULL) {
    2565           0 :                 free(this->w, M_DEVBUF, 0);
    2566           0 :                 this->w = NULL;
    2567           0 :         }
    2568             : 
    2569           0 :         return 0;
    2570             : }
    2571             : 
    2572             : int
    2573           0 : azalia_codec_construct_format(codec_t *this, int newdac, int newadc)
    2574             : {
    2575             :         const convgroup_t *group;
    2576             :         uint32_t bits_rates;
    2577             :         int variation;
    2578             :         int nbits, c, chan, i;
    2579             :         nid_t nid;
    2580             : 
    2581             :         variation = 0;
    2582             : 
    2583           0 :         if (this->dacs.ngroups > 0 && newdac < this->dacs.ngroups &&
    2584           0 :             newdac >= 0) {
    2585           0 :                 this->dacs.cur = newdac;
    2586           0 :                 group = &this->dacs.groups[this->dacs.cur];
    2587           0 :                 bits_rates = this->w[group->conv[0]].d.audio.bits_rates;
    2588             :                 nbits = 0;
    2589           0 :                 if (bits_rates & COP_PCM_B8)
    2590           0 :                         nbits++;
    2591           0 :                 if (bits_rates & COP_PCM_B16)
    2592           0 :                         nbits++;
    2593           0 :                 if (bits_rates & COP_PCM_B20)
    2594           0 :                         nbits++;
    2595           0 :                 if (bits_rates & COP_PCM_B24)
    2596           0 :                         nbits++;
    2597           0 :                 if ((bits_rates & COP_PCM_B32) &&
    2598           0 :                     !(this->w[group->conv[0]].widgetcap & COP_AWCAP_DIGITAL))
    2599           0 :                         nbits++;
    2600           0 :                 if (nbits == 0) {
    2601           0 :                         printf("%s: invalid DAC PCM format: 0x%8.8x\n",
    2602           0 :                             XNAME(this->az), bits_rates);
    2603           0 :                         return -1;
    2604             :                 }
    2605           0 :                 variation += group->nconv * nbits;
    2606           0 :         }
    2607             : 
    2608           0 :         if (this->adcs.ngroups > 0 && newadc < this->adcs.ngroups &&
    2609           0 :             newadc >= 0) {
    2610           0 :                 this->adcs.cur = newadc;
    2611           0 :                 group = &this->adcs.groups[this->adcs.cur];
    2612           0 :                 bits_rates = this->w[group->conv[0]].d.audio.bits_rates;
    2613             :                 nbits = 0;
    2614           0 :                 if (bits_rates & COP_PCM_B8)
    2615           0 :                         nbits++;
    2616           0 :                 if (bits_rates & COP_PCM_B16)
    2617           0 :                         nbits++;
    2618           0 :                 if (bits_rates & COP_PCM_B20)
    2619           0 :                         nbits++;
    2620           0 :                 if (bits_rates & COP_PCM_B24)
    2621           0 :                         nbits++;
    2622           0 :                 if ((bits_rates & COP_PCM_B32) &&
    2623           0 :                     !(this->w[group->conv[0]].widgetcap & COP_AWCAP_DIGITAL))
    2624           0 :                         nbits++;
    2625           0 :                 if (nbits == 0) {
    2626           0 :                         printf("%s: invalid ADC PCM format: 0x%8.8x\n",
    2627           0 :                             XNAME(this->az), bits_rates);
    2628           0 :                         return -1;
    2629             :                 }
    2630           0 :                 variation += group->nconv * nbits;
    2631           0 :         }
    2632             : 
    2633           0 :         if (variation == 0) {
    2634             :                 DPRINTF(("%s: no converter groups\n", XNAME(this->az)));
    2635           0 :                 return -1;
    2636             :         }
    2637             : 
    2638           0 :         if (this->formats != NULL)
    2639           0 :                 free(this->formats, M_DEVBUF, 0);
    2640           0 :         this->nformats = 0;
    2641           0 :         this->formats = mallocarray(variation, sizeof(struct audio_format),
    2642             :             M_DEVBUF, M_NOWAIT | M_ZERO);
    2643           0 :         if (this->formats == NULL) {
    2644           0 :                 printf("%s: out of memory in %s\n",
    2645           0 :                     XNAME(this->az), __func__);
    2646           0 :                 return ENOMEM;
    2647             :         }
    2648             : 
    2649             :         /* register formats for playback */
    2650           0 :         if (this->dacs.ngroups > 0) {
    2651           0 :                 group = &this->dacs.groups[this->dacs.cur];
    2652           0 :                 for (c = 0; c < group->nconv; c++) {
    2653             :                         chan = 0;
    2654             :                         bits_rates = ~0;
    2655           0 :                         if (this->w[group->conv[0]].widgetcap &
    2656             :                             COP_AWCAP_DIGITAL)
    2657           0 :                                 bits_rates &= ~(COP_PCM_B32);
    2658           0 :                         for (i = 0; i <= c; i++) {
    2659           0 :                                 nid = group->conv[i];
    2660           0 :                                 chan += WIDGET_CHANNELS(&this->w[nid]);
    2661           0 :                                 bits_rates &= this->w[nid].d.audio.bits_rates;
    2662             :                         }
    2663           0 :                         azalia_codec_add_bits(this, chan, bits_rates,
    2664             :                             AUMODE_PLAY);
    2665             :                 }
    2666             :         }
    2667             : 
    2668             :         /* register formats for recording */
    2669           0 :         if (this->adcs.ngroups > 0) {
    2670           0 :                 group = &this->adcs.groups[this->adcs.cur];
    2671           0 :                 for (c = 0; c < group->nconv; c++) {
    2672             :                         chan = 0;
    2673             :                         bits_rates = ~0;
    2674           0 :                         if (this->w[group->conv[0]].widgetcap &
    2675             :                             COP_AWCAP_DIGITAL)
    2676           0 :                                 bits_rates &= ~(COP_PCM_B32);
    2677           0 :                         for (i = 0; i <= c; i++) {
    2678           0 :                                 nid = group->conv[i];
    2679           0 :                                 chan += WIDGET_CHANNELS(&this->w[nid]);
    2680           0 :                                 bits_rates &= this->w[nid].d.audio.bits_rates;
    2681             :                         }
    2682           0 :                         azalia_codec_add_bits(this, chan, bits_rates,
    2683             :                             AUMODE_RECORD);
    2684             :                 }
    2685             :         }
    2686             : 
    2687           0 :         return 0;
    2688           0 : }
    2689             : 
    2690             : void
    2691           0 : azalia_codec_add_bits(codec_t *this, int chan, uint32_t bits_rates, int mode)
    2692             : {
    2693           0 :         if (bits_rates & COP_PCM_B8)
    2694           0 :                 azalia_codec_add_format(this, chan, 8, bits_rates, mode);
    2695           0 :         if (bits_rates & COP_PCM_B16)
    2696           0 :                 azalia_codec_add_format(this, chan, 16, bits_rates, mode);
    2697           0 :         if (bits_rates & COP_PCM_B20)
    2698           0 :                 azalia_codec_add_format(this, chan, 20, bits_rates, mode);
    2699           0 :         if (bits_rates & COP_PCM_B24)
    2700           0 :                 azalia_codec_add_format(this, chan, 24, bits_rates, mode);
    2701           0 :         if (bits_rates & COP_PCM_B32)
    2702           0 :                 azalia_codec_add_format(this, chan, 32, bits_rates, mode);
    2703           0 : }
    2704             : 
    2705             : void
    2706           0 : azalia_codec_add_format(codec_t *this, int chan, int prec, uint32_t rates,
    2707             :     int32_t mode)
    2708             : {
    2709             :         struct audio_format *f;
    2710             : 
    2711           0 :         f = &this->formats[this->nformats++];
    2712           0 :         f->mode = mode;
    2713           0 :         f->encoding = AUDIO_ENCODING_SLINEAR_LE;
    2714           0 :         if (prec == 8)
    2715           0 :                 f->encoding = AUDIO_ENCODING_ULINEAR_LE;
    2716           0 :         f->precision = prec;
    2717           0 :         f->channels = chan;
    2718           0 :         f->frequency_type = 0;
    2719           0 :         if (rates & COP_PCM_R80)
    2720           0 :                 f->frequency[f->frequency_type++] = 8000;
    2721           0 :         if (rates & COP_PCM_R110)
    2722           0 :                 f->frequency[f->frequency_type++] = 11025;
    2723           0 :         if (rates & COP_PCM_R160)
    2724           0 :                 f->frequency[f->frequency_type++] = 16000;
    2725           0 :         if (rates & COP_PCM_R220)
    2726           0 :                 f->frequency[f->frequency_type++] = 22050;
    2727           0 :         if (rates & COP_PCM_R320)
    2728           0 :                 f->frequency[f->frequency_type++] = 32000;
    2729           0 :         if (rates & COP_PCM_R441)
    2730           0 :                 f->frequency[f->frequency_type++] = 44100;
    2731           0 :         if (rates & COP_PCM_R480)
    2732           0 :                 f->frequency[f->frequency_type++] = 48000;
    2733           0 :         if (rates & COP_PCM_R882)
    2734           0 :                 f->frequency[f->frequency_type++] = 88200;
    2735           0 :         if (rates & COP_PCM_R960)
    2736           0 :                 f->frequency[f->frequency_type++] = 96000;
    2737           0 :         if (rates & COP_PCM_R1764)
    2738           0 :                 f->frequency[f->frequency_type++] = 176400;
    2739           0 :         if (rates & COP_PCM_R1920)
    2740           0 :                 f->frequency[f->frequency_type++] = 192000;
    2741           0 :         if (rates & COP_PCM_R3840)
    2742           0 :                 f->frequency[f->frequency_type++] = 384000;
    2743           0 : }
    2744             : 
    2745             : int
    2746           0 : azalia_codec_connect_stream(stream_t *this)
    2747             : {
    2748           0 :         const codec_t *codec = &this->az->codecs[this->az->codecno];
    2749             :         const convgroup_t *group;
    2750             :         widget_t *w;
    2751           0 :         uint32_t digital, stream_chan;
    2752             :         int i, err, curchan, nchan, widchan;
    2753             : 
    2754             :         err = 0;
    2755           0 :         nchan = (this->fmt & HDA_SD_FMT_CHAN) + 1;
    2756             : 
    2757           0 :         if (this->dir == AUMODE_RECORD)
    2758           0 :                 group = &codec->adcs.groups[codec->adcs.cur];
    2759             :         else
    2760           0 :                 group = &codec->dacs.groups[codec->dacs.cur];
    2761             : 
    2762             :         curchan = 0;
    2763           0 :         for (i = 0; i < group->nconv; i++) {
    2764           0 :                 w = &codec->w[group->conv[i]];
    2765           0 :                 widchan = WIDGET_CHANNELS(w);
    2766             : 
    2767           0 :                 stream_chan = (this->number << 4);
    2768           0 :                 if (curchan < nchan) {
    2769           0 :                         stream_chan |= curchan;
    2770           0 :                 } else if (w->nid == codec->spkr_dac ||
    2771           0 :                     w->nid == codec->fhp_dac) {
    2772             :                         stream_chan |= 0;       /* first channel(s) */
    2773           0 :                 } else
    2774             :                         stream_chan = 0;        /* idle stream */
    2775             : 
    2776             :                 if (stream_chan == 0) {
    2777             :                         DPRINTFN(0, ("%s: %2.2x is idle\n", __func__, w->nid));
    2778             :                 } else {
    2779             :                         DPRINTFN(0, ("%s: %2.2x on stream chan %d\n", __func__,
    2780             :                             w->nid, stream_chan & ~(this->number << 4)));
    2781             :                 }
    2782             : 
    2783           0 :                 err = azalia_comresp(codec, w->nid, CORB_SET_CONVERTER_FORMAT,
    2784           0 :                     this->fmt, NULL);
    2785           0 :                 if (err) {
    2786             :                         DPRINTF(("%s: nid %2.2x fmt %2.2x: %d\n",
    2787             :                             __func__, w->nid, this->fmt, err));
    2788             :                         break;
    2789             :                 }
    2790           0 :                 err = azalia_comresp(codec, w->nid,
    2791             :                     CORB_SET_CONVERTER_STREAM_CHANNEL, stream_chan, NULL);
    2792           0 :                 if (err) {
    2793             :                         DPRINTF(("%s: nid %2.2x chan %d: %d\n",
    2794             :                             __func__, w->nid, stream_chan, err));
    2795             :                         break;
    2796             :                 }
    2797             : 
    2798           0 :                 if (w->widgetcap & COP_AWCAP_DIGITAL) {
    2799           0 :                         err = azalia_comresp(codec, w->nid,
    2800             :                             CORB_GET_DIGITAL_CONTROL, 0, &digital);
    2801           0 :                         if (err) {
    2802             :                                 DPRINTF(("%s: nid %2.2x get digital: %d\n",
    2803             :                                     __func__, w->nid, err));
    2804             :                                 break;
    2805             :                         }
    2806           0 :                         digital = (digital & 0xff) | CORB_DCC_DIGEN;
    2807           0 :                         err = azalia_comresp(codec, w->nid,
    2808             :                             CORB_SET_DIGITAL_CONTROL_L, digital, NULL);
    2809           0 :                         if (err) {
    2810             :                                 DPRINTF(("%s: nid %2.2x set digital: %d\n",
    2811             :                                     __func__, w->nid, err));
    2812             :                                 break;
    2813             :                         }
    2814             :                 }
    2815           0 :                 curchan += widchan;
    2816             :         }
    2817             : 
    2818           0 :         return err;
    2819           0 : }
    2820             : 
    2821             : int
    2822           0 : azalia_codec_disconnect_stream(stream_t *this)
    2823             : {
    2824           0 :         const codec_t *codec = &this->az->codecs[this->az->codecno];
    2825             :         const convgroup_t *group;
    2826           0 :         uint32_t v;
    2827             :         int i;
    2828             :         nid_t nid;
    2829             : 
    2830           0 :         if (this->dir == AUMODE_RECORD)
    2831           0 :                 group = &codec->adcs.groups[codec->adcs.cur];
    2832             :         else
    2833           0 :                 group = &codec->dacs.groups[codec->dacs.cur];
    2834           0 :         for (i = 0; i < group->nconv; i++) {
    2835           0 :                 nid = group->conv[i];
    2836           0 :                 azalia_comresp(codec, nid, CORB_SET_CONVERTER_STREAM_CHANNEL,
    2837             :                     0, NULL);   /* stream#0 */
    2838           0 :                 if (codec->w[nid].widgetcap & COP_AWCAP_DIGITAL) {
    2839             :                         /* disable S/PDIF */
    2840           0 :                         azalia_comresp(codec, nid, CORB_GET_DIGITAL_CONTROL,
    2841             :                             0, &v);
    2842           0 :                         v = (v & ~CORB_DCC_DIGEN) & 0xff;
    2843           0 :                         azalia_comresp(codec, nid, CORB_SET_DIGITAL_CONTROL_L,
    2844             :                             v, NULL);
    2845           0 :                 }
    2846             :         }
    2847           0 :         return 0;
    2848           0 : }
    2849             : 
    2850             : /* ================================================================
    2851             :  * HDA widget functions
    2852             :  * ================================================================ */
    2853             : 
    2854             : int
    2855           0 : azalia_widget_init(widget_t *this, const codec_t *codec, nid_t nid)
    2856             : {
    2857           0 :         uint32_t result;
    2858             :         int err;
    2859             : 
    2860           0 :         err = azalia_comresp(codec, nid, CORB_GET_PARAMETER,
    2861             :             COP_AUDIO_WIDGET_CAP, &result);
    2862           0 :         if (err)
    2863           0 :                 return err;
    2864           0 :         this->nid = nid;
    2865           0 :         this->widgetcap = result;
    2866           0 :         this->type = COP_AWCAP_TYPE(result);
    2867           0 :         if (this->widgetcap & COP_AWCAP_POWER) {
    2868           0 :                 azalia_comresp(codec, nid, CORB_SET_POWER_STATE, CORB_PS_D0,
    2869             :                     &result);
    2870           0 :                 DELAY(100);
    2871           0 :         }
    2872             : 
    2873           0 :         this->enable = 1;
    2874           0 :         this->mixer_class = -1;
    2875           0 :         this->parent = codec->audiofunc;
    2876             : 
    2877           0 :         switch (this->type) {
    2878             :         case COP_AWTYPE_AUDIO_OUTPUT:
    2879             :                 /* FALLTHROUGH */
    2880             :         case COP_AWTYPE_AUDIO_INPUT:
    2881           0 :                 azalia_widget_init_audio(this, codec);
    2882           0 :                 break;
    2883             :         case COP_AWTYPE_PIN_COMPLEX:
    2884           0 :                 azalia_widget_init_pin(this, codec);
    2885           0 :                 break;
    2886             :         case COP_AWTYPE_VOLUME_KNOB:
    2887           0 :                 err = azalia_comresp(codec, this->nid, CORB_GET_PARAMETER,
    2888             :                     COP_VOLUME_KNOB_CAPABILITIES, &result);
    2889           0 :                 if (err)
    2890           0 :                         return err;
    2891           0 :                 this->d.volume.cap = result;
    2892           0 :                 break;
    2893             :         case COP_AWTYPE_POWER:
    2894             :                 /* FALLTHROUGH */
    2895             :         case COP_AWTYPE_VENDOR_DEFINED:
    2896           0 :                 this->enable = 0;
    2897           0 :                 break;
    2898             :         }
    2899             : 
    2900             :         /* amplifier information */
    2901             :         /* XXX (ab)use bits 24-30 to store the "control offset", which is
    2902             :          * the number of steps, starting at 0, that have no effect.  these
    2903             :          * bits are reserved in HDA 1.0.
    2904             :          */
    2905           0 :         if (this->widgetcap & COP_AWCAP_INAMP) {
    2906           0 :                 if (this->widgetcap & COP_AWCAP_AMPOV)
    2907           0 :                         azalia_comresp(codec, nid, CORB_GET_PARAMETER,
    2908           0 :                             COP_INPUT_AMPCAP, &this->inamp_cap);
    2909             :                 else
    2910           0 :                         this->inamp_cap = codec->w[codec->audiofunc].inamp_cap;
    2911           0 :                 this->inamp_cap &= ~(0x7f << 24);
    2912           0 :         }
    2913           0 :         if (this->widgetcap & COP_AWCAP_OUTAMP) {
    2914           0 :                 if (this->widgetcap & COP_AWCAP_AMPOV)
    2915           0 :                         azalia_comresp(codec, nid, CORB_GET_PARAMETER,
    2916           0 :                             COP_OUTPUT_AMPCAP, &this->outamp_cap);
    2917             :                 else
    2918           0 :                         this->outamp_cap = codec->w[codec->audiofunc].outamp_cap;
    2919           0 :                 this->outamp_cap &= ~(0x7f << 24);
    2920           0 :         }
    2921           0 :         return 0;
    2922           0 : }
    2923             : 
    2924             : int
    2925           0 : azalia_widget_sole_conn(codec_t *this, nid_t nid)
    2926             : {
    2927             :         int i, j, target, nconn, has_target;
    2928             : 
    2929             :         /* connected to ADC */
    2930           0 :         for (i = 0; i < this->adcs.ngroups; i++) {
    2931           0 :                 for (j = 0; j < this->adcs.groups[i].nconv; j++) {
    2932           0 :                         target = this->adcs.groups[i].conv[j];
    2933           0 :                         if (this->w[target].nconnections == 1 &&
    2934           0 :                             this->w[target].connections[0] == nid) {
    2935           0 :                                 return target;
    2936             :                         }
    2937             :                 }
    2938             :         }
    2939             :         /* connected to DAC */
    2940           0 :         for (i = 0; i < this->dacs.ngroups; i++) {
    2941           0 :                 for (j = 0; j < this->dacs.groups[i].nconv; j++) {
    2942           0 :                         target = this->dacs.groups[i].conv[j];
    2943           0 :                         if (this->w[target].nconnections == 1 &&
    2944           0 :                             this->w[target].connections[0] == nid) {
    2945           0 :                                 return target;
    2946             :                         }
    2947             :                 }
    2948             :         }
    2949             :         /* connected to pin complex */
    2950             :         target = -1;
    2951           0 :         FOR_EACH_WIDGET(this, i) {
    2952           0 :                 if (this->w[i].type != COP_AWTYPE_PIN_COMPLEX)
    2953             :                         continue;
    2954           0 :                 if (this->w[i].nconnections == 1 &&
    2955           0 :                     this->w[i].connections[0] == nid) {
    2956           0 :                         if (target != -1)
    2957           0 :                                 return -1;
    2958             :                         target = i;
    2959           0 :                 } else {
    2960             :                         nconn = 0;
    2961             :                         has_target = 0;
    2962           0 :                         for (j = 0; j < this->w[i].nconnections; j++) {
    2963           0 :                                 if (!this->w[this->w[i].connections[j]].enable)
    2964             :                                         continue;
    2965           0 :                                 nconn++;
    2966           0 :                                 if (this->w[i].connections[j] == nid)
    2967           0 :                                         has_target = 1;
    2968             :                         }
    2969           0 :                         if (has_target == 1) {
    2970           0 :                                 if (nconn == 1) {
    2971           0 :                                         if (target != -1)
    2972           0 :                                                 return -1;
    2973             :                                         target = i;
    2974             :                                 } else {
    2975             :                                         /* not sole connection at least once */
    2976           0 :                                         return -1;
    2977             :                                 }
    2978           0 :                         }
    2979             :                 }
    2980             :         }
    2981           0 :         if (target != -1)
    2982           0 :                 return target;
    2983             : 
    2984           0 :         return -1;
    2985           0 : }
    2986             : 
    2987             : int
    2988           0 : azalia_widget_label_widgets(codec_t *codec)
    2989             : {
    2990             :         widget_t *w;
    2991             :         convgroup_t *group;
    2992           0 :         int types[16];
    2993           0 :         int pins[16];
    2994             :         int colors_used, use_colors, schan;
    2995             :         int i, j;
    2996             : 
    2997           0 :         bzero(&pins, sizeof(pins));
    2998           0 :         bzero(&types, sizeof(types));
    2999             : 
    3000             :         /* If codec has more than one line-out jack, check if the jacks
    3001             :          * have unique colors.  If so, use the colors in the mixer names.
    3002             :          */
    3003             :         use_colors = 1;
    3004             :         colors_used = 0;
    3005           0 :         if (codec->nout_jacks < 2)
    3006           0 :                 use_colors = 0;
    3007           0 :         for (i = 0; use_colors && i < codec->nopins; i++) {
    3008           0 :                 w = &codec->w[codec->opins[i].nid];
    3009           0 :                 if (w->d.pin.device != CORB_CD_LINEOUT)
    3010             :                         continue;
    3011           0 :                 if (colors_used & (1 << w->d.pin.color))
    3012           0 :                         use_colors = 0;
    3013             :                 else
    3014           0 :                         colors_used |= (1 << w->d.pin.color);
    3015             :         }
    3016             : 
    3017           0 :         FOR_EACH_WIDGET(codec, i) {
    3018           0 :                 w = &codec->w[i];
    3019             :                 /* default for disabled/unused widgets */
    3020           0 :                 snprintf(w->name, sizeof(w->name), "u-wid%2.2x", w->nid);
    3021           0 :                 if (w->enable == 0)
    3022             :                         continue;
    3023           0 :                 switch (w->type) {
    3024             :                 case COP_AWTYPE_PIN_COMPLEX:
    3025           0 :                         pins[w->d.pin.device]++;
    3026           0 :                         if (use_colors && w->d.pin.device == CORB_CD_LINEOUT) {
    3027           0 :                                 snprintf(w->name, sizeof(w->name), "%s-%s",
    3028           0 :                                     pin_devices[w->d.pin.device],
    3029           0 :                                     line_colors[w->d.pin.color]);
    3030           0 :                         } else if (pins[w->d.pin.device] > 1) {
    3031           0 :                                 snprintf(w->name, sizeof(w->name), "%s%d",
    3032             :                                     pin_devices[w->d.pin.device],
    3033             :                                     pins[w->d.pin.device]);
    3034           0 :                         } else {
    3035           0 :                                 snprintf(w->name, sizeof(w->name), "%s",
    3036             :                                     pin_devices[w->d.pin.device]);
    3037             :                         }
    3038             :                         break;
    3039             :                 case COP_AWTYPE_AUDIO_OUTPUT:
    3040           0 :                         if (codec->dacs.ngroups < 1)
    3041             :                                 break;
    3042           0 :                         group = &codec->dacs.groups[0];
    3043             :                         schan = 0;
    3044           0 :                         for (j = 0; j < group->nconv; j++) {
    3045           0 :                                 if (w->nid == group->conv[j]) {
    3046           0 :                                         snprintf(w->name, sizeof(w->name),
    3047           0 :                                             "%s-%d:%d", wtypes[w->type], schan,
    3048           0 :                                             schan + WIDGET_CHANNELS(w) - 1);
    3049           0 :                                 }
    3050           0 :                                 schan += WIDGET_CHANNELS(w);
    3051             :                         }
    3052           0 :                         if (codec->dacs.ngroups < 2)
    3053             :                                 break;
    3054           0 :                         group = &codec->dacs.groups[1];
    3055             :                         schan = 0;
    3056           0 :                         for (j = 0; j < group->nconv; j++) {
    3057           0 :                                 if (w->nid == group->conv[j]) {
    3058           0 :                                         snprintf(w->name, sizeof(w->name),
    3059           0 :                                             "dig-%s-%d:%d", wtypes[w->type],
    3060             :                                             schan,
    3061           0 :                                             schan + WIDGET_CHANNELS(w) - 1);
    3062           0 :                                 }
    3063           0 :                                 schan += WIDGET_CHANNELS(w);
    3064             :                         }
    3065             :                         break;
    3066             :                 case COP_AWTYPE_AUDIO_INPUT:
    3067           0 :                         w->mixer_class = AZ_CLASS_RECORD;
    3068           0 :                         if (codec->adcs.ngroups < 1)
    3069             :                                 break;
    3070           0 :                         group = &codec->adcs.groups[0];
    3071             :                         schan = 0;
    3072           0 :                         for (j = 0; j < group->nconv; j++) {
    3073           0 :                                 if (w->nid == group->conv[j]) {
    3074           0 :                                         snprintf(w->name, sizeof(w->name),
    3075           0 :                                             "%s-%d:%d", wtypes[w->type], schan,
    3076           0 :                                             schan + WIDGET_CHANNELS(w) - 1);
    3077           0 :                                 }
    3078           0 :                                 schan += WIDGET_CHANNELS(w);
    3079             :                         }
    3080           0 :                         if (codec->adcs.ngroups < 2)
    3081             :                                 break;
    3082           0 :                         group = &codec->adcs.groups[1];
    3083             :                         schan = 0;
    3084           0 :                         for (j = 0; j < group->nconv; j++) {
    3085           0 :                                 if (w->nid == group->conv[j]) {
    3086           0 :                                         snprintf(w->name, sizeof(w->name),
    3087           0 :                                             "dig-%s-%d:%d", wtypes[w->type],
    3088             :                                             schan,
    3089           0 :                                             schan + WIDGET_CHANNELS(w) - 1);
    3090           0 :                                 }
    3091           0 :                                 schan += WIDGET_CHANNELS(w);
    3092             :                         }
    3093             :                         break;
    3094             :                 default:
    3095           0 :                         types[w->type]++;
    3096           0 :                         if (types[w->type] > 1)
    3097           0 :                                 snprintf(w->name, sizeof(w->name), "%s%d",
    3098             :                                     wtypes[w->type], types[w->type]);
    3099             :                         else
    3100           0 :                                 snprintf(w->name, sizeof(w->name), "%s",
    3101             :                                     wtypes[w->type]);
    3102             :                         break;
    3103             :                 }
    3104             :         }
    3105             : 
    3106             :         /* Mixers and selectors that connect to only one other widget are
    3107             :          * functionally part of the widget they are connected to.  Show that
    3108             :          * relationship in the name.
    3109             :          */
    3110           0 :         FOR_EACH_WIDGET(codec, i) {
    3111           0 :                 if (codec->w[i].type != COP_AWTYPE_AUDIO_MIXER &&
    3112           0 :                     codec->w[i].type != COP_AWTYPE_AUDIO_SELECTOR)
    3113             :                         continue;
    3114           0 :                 if (codec->w[i].enable == 0)
    3115             :                         continue;
    3116           0 :                 j = azalia_widget_sole_conn(codec, i);
    3117           0 :                 if (j == -1) {
    3118             :                         /* Special case.  A selector with outamp capabilities
    3119             :                          * and is connected to a single widget that has either
    3120             :                          * no input or no output capabilities.  This widget
    3121             :                          * serves as the input or output amp for the widget
    3122             :                          * it is connected to.
    3123             :                          */
    3124           0 :                         if (codec->w[i].type == COP_AWTYPE_AUDIO_SELECTOR &&
    3125           0 :                             (codec->w[i].widgetcap & COP_AWCAP_OUTAMP) &&
    3126           0 :                             codec->w[i].nconnections == 1) {
    3127           0 :                                 j = codec->w[i].connections[0];
    3128           0 :                                 if (!azalia_widget_enabled(codec, j))
    3129             :                                         continue;
    3130           0 :                                 if (!(codec->w[j].widgetcap & COP_AWCAP_INAMP))
    3131           0 :                                         codec->w[i].mixer_class =
    3132             :                                             AZ_CLASS_INPUT;
    3133           0 :                                 else if (!(codec->w[j].widgetcap & COP_AWCAP_OUTAMP))
    3134           0 :                                         codec->w[i].mixer_class =
    3135             :                                             AZ_CLASS_OUTPUT;
    3136             :                                 else
    3137             :                                         continue;
    3138             :                         }
    3139             :                 }
    3140           0 :                 if (j >= 0) {
    3141             :                         /* As part of a disabled widget, this widget
    3142             :                          * should be disabled as well.
    3143             :                          */
    3144           0 :                         if (codec->w[j].enable == 0) {
    3145           0 :                                 codec->w[i].enable = 0;
    3146           0 :                                 snprintf(codec->w[i].name,
    3147             :                                     sizeof(codec->w[i].name),
    3148             :                                     "u-wid%2.2x", i);
    3149           0 :                                 continue;
    3150             :                         }
    3151           0 :                         snprintf(codec->w[i].name, sizeof(codec->w[i].name),
    3152           0 :                             "%s", codec->w[j].name);
    3153           0 :                         if (codec->w[j].mixer_class == AZ_CLASS_RECORD)
    3154           0 :                                 codec->w[i].mixer_class = AZ_CLASS_RECORD;
    3155           0 :                         codec->w[i].parent = j;
    3156           0 :                 }
    3157             :         }
    3158             : 
    3159           0 :         return 0;
    3160           0 : }
    3161             : 
    3162             : int
    3163           0 : azalia_widget_init_audio(widget_t *this, const codec_t *codec)
    3164             : {
    3165           0 :         uint32_t result;
    3166             :         int err;
    3167             : 
    3168             :         /* check audio format */
    3169           0 :         if (this->widgetcap & COP_AWCAP_FORMATOV) {
    3170           0 :                 err = azalia_comresp(codec, this->nid, CORB_GET_PARAMETER,
    3171             :                     COP_STREAM_FORMATS, &result);
    3172           0 :                 if (err)
    3173           0 :                         return err;
    3174           0 :                 this->d.audio.encodings = result;
    3175           0 :                 if (result == 0) { /* quirk for CMI9880.
    3176             :                                     * This must not occur usually... */
    3177           0 :                         this->d.audio.encodings =
    3178           0 :                             codec->w[codec->audiofunc].d.audio.encodings;
    3179           0 :                         this->d.audio.bits_rates =
    3180           0 :                             codec->w[codec->audiofunc].d.audio.bits_rates;
    3181           0 :                 } else {
    3182           0 :                         if ((result & COP_STREAM_FORMAT_PCM) == 0) {
    3183           0 :                                 printf("%s: %s: No PCM support: %x\n",
    3184           0 :                                     XNAME(codec->az), this->name, result);
    3185           0 :                                 return -1;
    3186             :                         }
    3187           0 :                         err = azalia_comresp(codec, this->nid,
    3188             :                             CORB_GET_PARAMETER, COP_PCM, &result);
    3189           0 :                         if (err)
    3190           0 :                                 return err;
    3191           0 :                         this->d.audio.bits_rates = result;
    3192             :                 }
    3193             :         } else {
    3194           0 :                 this->d.audio.encodings =
    3195           0 :                     codec->w[codec->audiofunc].d.audio.encodings;
    3196           0 :                 this->d.audio.bits_rates =
    3197           0 :                     codec->w[codec->audiofunc].d.audio.bits_rates;
    3198             :         }
    3199           0 :         return 0;
    3200           0 : }
    3201             : 
    3202             : int
    3203           0 : azalia_widget_init_pin(widget_t *this, const codec_t *codec)
    3204             : {
    3205           0 :         uint32_t result, dir;
    3206             :         int err;
    3207             : 
    3208           0 :         err = azalia_comresp(codec, this->nid, CORB_GET_CONFIGURATION_DEFAULT,
    3209             :             0, &result);
    3210           0 :         if (err)
    3211           0 :                 return err;
    3212           0 :         this->d.pin.config = result;
    3213           0 :         this->d.pin.sequence = CORB_CD_SEQUENCE(result);
    3214           0 :         this->d.pin.association = CORB_CD_ASSOCIATION(result);
    3215           0 :         this->d.pin.color = CORB_CD_COLOR(result);
    3216           0 :         this->d.pin.device = CORB_CD_DEVICE(result);
    3217             : 
    3218           0 :         err = azalia_comresp(codec, this->nid, CORB_GET_PARAMETER,
    3219             :             COP_PINCAP, &result);
    3220           0 :         if (err)
    3221           0 :                 return err;
    3222           0 :         this->d.pin.cap = result;
    3223             : 
    3224             :         dir = CORB_PWC_INPUT;
    3225           0 :         switch (this->d.pin.device) {
    3226             :         case CORB_CD_LINEOUT:
    3227             :         case CORB_CD_SPEAKER:
    3228             :         case CORB_CD_HEADPHONE:
    3229             :         case CORB_CD_SPDIFOUT:
    3230             :         case CORB_CD_DIGITALOUT:
    3231             :                 dir = CORB_PWC_OUTPUT;
    3232           0 :                 break;
    3233             :         }
    3234             : 
    3235           0 :         if (dir == CORB_PWC_INPUT && !(this->d.pin.cap & COP_PINCAP_INPUT))
    3236           0 :                 dir = CORB_PWC_OUTPUT;
    3237           0 :         if (dir == CORB_PWC_OUTPUT && !(this->d.pin.cap & COP_PINCAP_OUTPUT))
    3238           0 :                 dir = CORB_PWC_INPUT;
    3239             : 
    3240           0 :         if (dir == CORB_PWC_INPUT && this->d.pin.device == CORB_CD_MICIN) {
    3241           0 :                 if (COP_PINCAP_VREF(this->d.pin.cap) & (1 << CORB_PWC_VREF_80))
    3242           0 :                         dir |= CORB_PWC_VREF_80;
    3243           0 :                 else if (COP_PINCAP_VREF(this->d.pin.cap) &
    3244             :                     (1 << CORB_PWC_VREF_50))
    3245           0 :                         dir |= CORB_PWC_VREF_50;
    3246             :         }
    3247             : 
    3248           0 :         if ((codec->qrks & AZ_QRK_WID_OVREF50) && (dir == CORB_PWC_OUTPUT))
    3249           0 :                 dir |= CORB_PWC_VREF_50;
    3250             : 
    3251           0 :         azalia_comresp(codec, this->nid, CORB_SET_PIN_WIDGET_CONTROL,
    3252             :             dir, NULL);
    3253             : 
    3254           0 :         if (this->d.pin.cap & COP_PINCAP_EAPD) {
    3255           0 :                 err = azalia_comresp(codec, this->nid,
    3256             :                     CORB_GET_EAPD_BTL_ENABLE, 0, &result);
    3257           0 :                 if (err)
    3258           0 :                         return err;
    3259           0 :                 result &= 0xff;
    3260           0 :                 result |= CORB_EAPD_EAPD;
    3261           0 :                 err = azalia_comresp(codec, this->nid,
    3262             :                     CORB_SET_EAPD_BTL_ENABLE, result, &result);
    3263           0 :                 if (err)
    3264           0 :                         return err;
    3265             :         }
    3266             : 
    3267             :         /* Disable unconnected pins */
    3268           0 :         if (CORB_CD_PORT(this->d.pin.config) == CORB_CD_NONE)
    3269           0 :                 this->enable = 0;
    3270             : 
    3271           0 :         return 0;
    3272           0 : }
    3273             : 
    3274             : int
    3275           0 : azalia_widget_init_connection(widget_t *this, const codec_t *codec)
    3276             : {
    3277           0 :         uint32_t result;
    3278             :         int err;
    3279             :         int i, j, k;
    3280             :         int length, nconn, bits, conn, last;
    3281             : 
    3282           0 :         this->selected = -1;
    3283           0 :         if ((this->widgetcap & COP_AWCAP_CONNLIST) == 0)
    3284           0 :                 return 0;
    3285             : 
    3286           0 :         err = azalia_comresp(codec, this->nid, CORB_GET_PARAMETER,
    3287             :             COP_CONNECTION_LIST_LENGTH, &result);
    3288           0 :         if (err)
    3289           0 :                 return err;
    3290             : 
    3291             :         bits = 8;
    3292           0 :         if (result & COP_CLL_LONG)
    3293             :                 bits = 16;
    3294             : 
    3295           0 :         length = COP_CLL_LENGTH(result);
    3296           0 :         if (length == 0)
    3297           0 :                 return 0;
    3298             : 
    3299             :         /*
    3300             :          * 'length' is the number of entries, not the number of
    3301             :          * connections.  Find the number of connections, 'nconn', so
    3302             :          * enough space can be allocated for the list of connected
    3303             :          * nids.
    3304             :          */
    3305             :         nconn = last = 0;
    3306           0 :         for (i = 0; i < length;) {
    3307           0 :                 err = azalia_comresp(codec, this->nid,
    3308             :                     CORB_GET_CONNECTION_LIST_ENTRY, i, &result);
    3309           0 :                 if (err)
    3310           0 :                         return err;
    3311           0 :                 for (k = 0; i < length && (k < 32 / bits); k++) {
    3312           0 :                         conn = (result >> (k * bits)) & ((1 << bits) - 1);
    3313             :                         /* If high bit is set, this is the end of a continuous
    3314             :                          * list that started with the last connection.
    3315             :                          */
    3316           0 :                         if ((nconn > 0) && (conn & (1 << (bits - 1))))
    3317           0 :                                 nconn += (conn & ~(1 << (bits - 1))) - last;
    3318             :                         else
    3319           0 :                                 nconn++;
    3320             :                         last = conn;
    3321           0 :                         i++;
    3322             :                 }
    3323             :         }
    3324             : 
    3325           0 :         this->connections = mallocarray(nconn, sizeof(nid_t), M_DEVBUF, M_NOWAIT);
    3326           0 :         if (this->connections == NULL) {
    3327           0 :                 printf("%s: out of memory\n", XNAME(codec->az));
    3328           0 :                 return ENOMEM;
    3329             :         }
    3330           0 :         for (i = 0; i < nconn;) {
    3331           0 :                 err = azalia_comresp(codec, this->nid,
    3332             :                     CORB_GET_CONNECTION_LIST_ENTRY, i, &result);
    3333           0 :                 if (err)
    3334           0 :                         return err;
    3335           0 :                 for (k = 0; i < nconn && (k < 32 / bits); k++) {
    3336           0 :                         conn = (result >> (k * bits)) & ((1 << bits) - 1);
    3337             :                         /* If high bit is set, this is the end of a continuous
    3338             :                          * list that started with the last connection.
    3339             :                          */
    3340           0 :                         if ((i > 0) && (conn & (1 << (bits - 1)))) {
    3341           0 :                                 for (j = 1; i < nconn && j <= conn - last; j++)
    3342           0 :                                         this->connections[i++] = last + j;
    3343             :                         } else {
    3344           0 :                                 this->connections[i++] = conn;
    3345             :                         }
    3346             :                         last = conn;
    3347             :                 }
    3348             :         }
    3349           0 :         this->nconnections = nconn;
    3350             : 
    3351           0 :         if (nconn > 0) {
    3352           0 :                 err = azalia_comresp(codec, this->nid,
    3353             :                     CORB_GET_CONNECTION_SELECT_CONTROL, 0, &result);
    3354           0 :                 if (err)
    3355           0 :                         return err;
    3356           0 :                 this->selected = CORB_CSC_INDEX(result);
    3357           0 :         }
    3358           0 :         return 0;
    3359           0 : }
    3360             : 
    3361             : int
    3362           0 : azalia_widget_check_conn(codec_t *codec, int index, int depth)
    3363             : {
    3364             :         const widget_t *w;
    3365             :         int i;
    3366             : 
    3367           0 :         w = &codec->w[index];
    3368             : 
    3369           0 :         if (w->type == COP_AWTYPE_BEEP_GENERATOR)
    3370           0 :                 return 0;
    3371             : 
    3372           0 :         if (depth > 0 &&
    3373           0 :             (w->type == COP_AWTYPE_PIN_COMPLEX ||
    3374           0 :             w->type == COP_AWTYPE_AUDIO_OUTPUT ||
    3375           0 :             w->type == COP_AWTYPE_AUDIO_INPUT)) {
    3376           0 :                 if (w->enable)
    3377           0 :                         return 1;
    3378             :                 else
    3379           0 :                         return 0;
    3380             :         }
    3381           0 :         if (++depth >= 10)
    3382           0 :                 return 0;
    3383           0 :         for (i = 0; i < w->nconnections; i++) {
    3384           0 :                 if (!azalia_widget_enabled(codec, w->connections[i]))
    3385             :                         continue;
    3386           0 :                 if (azalia_widget_check_conn(codec, w->connections[i], depth))
    3387           0 :                         return 1;
    3388             :         }
    3389           0 :         return 0;
    3390           0 : }
    3391             : 
    3392             : #ifdef AZALIA_DEBUG
    3393             : 
    3394             : #define WIDGETCAP_BITS                                                  \
    3395             :     "\20\014LRSWAP\013POWER\012DIGITAL"                                       \
    3396             :     "\011CONNLIST\010UNSOL\07PROC\06STRIPE\05FORMATOV\04AMPOV\03OUTAMP"       \
    3397             :     "\02INAMP\01STEREO"
    3398             : 
    3399             : #define PINCAP_BITS     "\20\021EAPD\16VREF100\15VREF80" \
    3400             :     "\13VREFGND\12VREF50\11VREFHIZ\07BALANCE\06INPUT" \
    3401             :     "\05OUTPUT\04HEADPHONE\03PRESENCE\02TRIGGER\01IMPEDANCE"
    3402             : 
    3403             : #define ENCODING_BITS   "\20\3AC3\2FLOAT32\1PCM"
    3404             : 
    3405             : #define BITSRATES_BITS  "\20\x15""32bit\x14""24bit\x13""20bit"          \
    3406             :     "\x12""16bit\x11""8bit""\x0c""384kHz\x0b""192kHz\x0a""176.4kHz"       \
    3407             :     "\x09""96kHz\x08""88.2kHz\x07""48kHz\x06""44.1kHz\x05""32kHz\x04"       \
    3408             :     "22.05kHz\x03""16kHz\x02""11.025kHz\x01""8kHz"
    3409             : 
    3410             : static const char *pin_colors[16] = {
    3411             :         "unknown", "black", "gray", "blue",
    3412             :         "green", "red", "orange", "yellow",
    3413             :         "purple", "pink", "col0a", "col0b",
    3414             :         "col0c", "col0d", "white", "other"};
    3415             : static const char *pin_conn[4] = {
    3416             :         "jack", "none", "fixed", "combined"};
    3417             : static const char *pin_conntype[16] = {
    3418             :         "unknown", "1/8", "1/4", "atapi", "rca", "optical",
    3419             :         "digital", "analog", "din", "xlr", "rj-11", "combination",
    3420             :         "con0c", "con0d", "con0e", "other"};
    3421             : static const char *pin_geo[15] = {
    3422             :         "n/a", "rear", "front", "left",
    3423             :         "right", "top", "bottom", "spec0", "spec1", "spec2",
    3424             :         "loc0a", "loc0b", "loc0c", "loc0d", "loc0f"};
    3425             : static const char *pin_chass[4] = {
    3426             :         "external", "internal", "separate", "other"};
    3427             : 
    3428             : void
    3429             : azalia_codec_print_audiofunc(const codec_t *this)
    3430             : {
    3431             :         uint32_t result;
    3432             : 
    3433             :         azalia_widget_print_audio(&this->w[this->audiofunc], "\t");
    3434             : 
    3435             :         result = this->w[this->audiofunc].inamp_cap;
    3436             :         DPRINTF(("\tinamp: mute=%u size=%u steps=%u offset=%u\n",
    3437             :             (result & COP_AMPCAP_MUTE) != 0, COP_AMPCAP_STEPSIZE(result),
    3438             :             COP_AMPCAP_NUMSTEPS(result), COP_AMPCAP_OFFSET(result)));
    3439             :         result = this->w[this->audiofunc].outamp_cap;
    3440             :         DPRINTF(("\toutamp: mute=%u size=%u steps=%u offset=%u\n",
    3441             :             (result & COP_AMPCAP_MUTE) != 0, COP_AMPCAP_STEPSIZE(result),
    3442             :             COP_AMPCAP_NUMSTEPS(result), COP_AMPCAP_OFFSET(result)));
    3443             :         azalia_comresp(this, this->audiofunc, CORB_GET_PARAMETER,
    3444             :             COP_GPIO_COUNT, &result);
    3445             :         DPRINTF(("\tgpio: wake=%u unsol=%u gpis=%u gpos=%u gpios=%u\n",
    3446             :             (result & COP_GPIO_WAKE) != 0, (result & COP_GPIO_UNSOL) != 0,
    3447             :             COP_GPIO_GPIS(result), COP_GPIO_GPOS(result),
    3448             :             COP_GPIO_GPIOS(result)));
    3449             : }
    3450             : 
    3451             : void
    3452             : azalia_codec_print_groups(const codec_t *this)
    3453             : {
    3454             :         int i, n;
    3455             : 
    3456             :         for (i = 0; i < this->dacs.ngroups; i++) {
    3457             :                 printf("%s: dacgroup[%d]:", XNAME(this->az), i);
    3458             :                 for (n = 0; n < this->dacs.groups[i].nconv; n++) {
    3459             :                         printf(" %2.2x", this->dacs.groups[i].conv[n]);
    3460             :                 }
    3461             :                 printf("\n");
    3462             :         }
    3463             :         for (i = 0; i < this->adcs.ngroups; i++) {
    3464             :                 printf("%s: adcgroup[%d]:", XNAME(this->az), i);
    3465             :                 for (n = 0; n < this->adcs.groups[i].nconv; n++) {
    3466             :                         printf(" %2.2x", this->adcs.groups[i].conv[n]);
    3467             :                 }
    3468             :                 printf("\n");
    3469             :         }
    3470             : }
    3471             : 
    3472             : void
    3473             : azalia_widget_print_audio(const widget_t *this, const char *lead)
    3474             : {
    3475             :         printf("%sencodings=%b\n", lead, this->d.audio.encodings,
    3476             :             ENCODING_BITS);
    3477             :         printf("%sPCM formats=%b\n", lead, this->d.audio.bits_rates,
    3478             :             BITSRATES_BITS);
    3479             : }
    3480             : 
    3481             : void
    3482             : azalia_widget_print_widget(const widget_t *w, const codec_t *codec)
    3483             : {
    3484             :         int i;
    3485             : 
    3486             :         printf("%s: ", XNAME(codec->az));
    3487             :         printf("%s%2.2x wcap=%b\n", w->type == COP_AWTYPE_PIN_COMPLEX ?
    3488             :             pin_colors[w->d.pin.color] : wtypes[w->type],
    3489             :             w->nid, w->widgetcap, WIDGETCAP_BITS);
    3490             :         if (w->widgetcap & COP_AWCAP_FORMATOV)
    3491             :                 azalia_widget_print_audio(w, "\t");
    3492             :         if (w->type == COP_AWTYPE_PIN_COMPLEX)
    3493             :                 azalia_widget_print_pin(w);
    3494             : 
    3495             :         if (w->type == COP_AWTYPE_VOLUME_KNOB)
    3496             :                 printf("\tdelta=%d steps=%d\n",
    3497             :                     !!(w->d.volume.cap & COP_VKCAP_DELTA),
    3498             :                     COP_VKCAP_NUMSTEPS(w->d.volume.cap));
    3499             : 
    3500             :         if ((w->widgetcap & COP_AWCAP_INAMP) &&
    3501             :             (w->widgetcap & COP_AWCAP_AMPOV))
    3502             :                 printf("\tinamp: mute=%u size=%u steps=%u offset=%u\n",
    3503             :                     (w->inamp_cap & COP_AMPCAP_MUTE) != 0,
    3504             :                     COP_AMPCAP_STEPSIZE(w->inamp_cap),
    3505             :                     COP_AMPCAP_NUMSTEPS(w->inamp_cap),
    3506             :                     COP_AMPCAP_OFFSET(w->inamp_cap));
    3507             : 
    3508             :         if ((w->widgetcap & COP_AWCAP_OUTAMP) &&
    3509             :             (w->widgetcap & COP_AWCAP_AMPOV))
    3510             :                 printf("\toutamp: mute=%u size=%u steps=%u offset=%u\n",
    3511             :                     (w->outamp_cap & COP_AMPCAP_MUTE) != 0,
    3512             :                     COP_AMPCAP_STEPSIZE(w->outamp_cap),
    3513             :                     COP_AMPCAP_NUMSTEPS(w->outamp_cap),
    3514             :                     COP_AMPCAP_OFFSET(w->outamp_cap));
    3515             : 
    3516             :         if (w->nconnections > 0) {
    3517             :                 printf("\tconnections=0x%x", w->connections[0]);
    3518             :                 for (i = 1; i < w->nconnections; i++)
    3519             :                         printf(",0x%x", w->connections[i]);
    3520             :                 printf("; selected=0x%x\n", w->connections[w->selected]);
    3521             :         }
    3522             : }
    3523             : 
    3524             : void
    3525             : azalia_widget_print_pin(const widget_t *this)
    3526             : {
    3527             :         printf("\tcap=%b\n", this->d.pin.cap, PINCAP_BITS);
    3528             :         printf("\t[%2.2d/%2.2d] ", CORB_CD_ASSOCIATION(this->d.pin.config),
    3529             :             CORB_CD_SEQUENCE(this->d.pin.config));
    3530             :         printf("color=%s ", pin_colors[CORB_CD_COLOR(this->d.pin.config)]);
    3531             :         printf("device=%s ", pin_devices[CORB_CD_DEVICE(this->d.pin.config)]);
    3532             :         printf("conn=%s ", pin_conn[CORB_CD_PORT(this->d.pin.config)]);
    3533             :         printf("conntype=%s\n", pin_conntype[CORB_CD_CONNECTION(this->d.pin.config)]);
    3534             :         printf("\tlocation=%s ", pin_geo[CORB_CD_LOC_GEO(this->d.pin.config)]);
    3535             :         printf("chassis=%s ", pin_chass[CORB_CD_LOC_CHASS(this->d.pin.config)]);
    3536             :         printf("special=");
    3537             :         if (CORB_CD_LOC_GEO(this->d.pin.config) == CORB_CD_LOC_SPEC0) {
    3538             :                 if (CORB_CD_LOC_CHASS(this->d.pin.config) == CORB_CD_EXTERNAL)
    3539             :                         printf("rear-panel");
    3540             :                 else if (CORB_CD_LOC_CHASS(this->d.pin.config) == CORB_CD_INTERNAL)
    3541             :                         printf("riser");
    3542             :                 else if (CORB_CD_LOC_CHASS(this->d.pin.config) == CORB_CD_LOC_OTHER)
    3543             :                         printf("mobile-lid-internal");
    3544             :         } else if (CORB_CD_LOC_GEO(this->d.pin.config) == CORB_CD_LOC_SPEC1) {
    3545             :                 if (CORB_CD_LOC_CHASS(this->d.pin.config) == CORB_CD_EXTERNAL)
    3546             :                         printf("drive-bay");
    3547             :                 else if (CORB_CD_LOC_CHASS(this->d.pin.config) == CORB_CD_INTERNAL)
    3548             :                         printf("hdmi");
    3549             :                 else if (CORB_CD_LOC_CHASS(this->d.pin.config) == CORB_CD_LOC_OTHER)
    3550             :                         printf("mobile-lid-external");
    3551             :         } else if (CORB_CD_LOC_GEO(this->d.pin.config) == CORB_CD_LOC_SPEC2) {
    3552             :                 if (CORB_CD_LOC_CHASS(this->d.pin.config) == CORB_CD_INTERNAL)
    3553             :                         printf("atapi");
    3554             :         } else
    3555             :                 printf("none");
    3556             :         printf("\n");
    3557             : }
    3558             : 
    3559             : #else   /* AZALIA_DEBUG */
    3560             : 
    3561             : void
    3562           0 : azalia_codec_print_audiofunc(const codec_t *this) {}
    3563             : 
    3564             : void
    3565           0 : azalia_codec_print_groups(const codec_t *this) {}
    3566             : 
    3567             : void
    3568           0 : azalia_widget_print_audio(const widget_t *this, const char *lead) {}
    3569             : 
    3570             : void
    3571           0 : azalia_widget_print_widget(const widget_t *w, const codec_t *codec) {}
    3572             : 
    3573             : void
    3574           0 : azalia_widget_print_pin(const widget_t *this) {}
    3575             : 
    3576             : #endif  /* AZALIA_DEBUG */
    3577             : 
    3578             : /* ================================================================
    3579             :  * Stream functions
    3580             :  * ================================================================ */
    3581             : 
    3582             : int
    3583           0 : azalia_stream_init(stream_t *this, azalia_t *az, int regindex, int strnum,
    3584             :     int dir)
    3585             : {
    3586             :         int err;
    3587             : 
    3588           0 :         this->az = az;
    3589           0 :         this->regbase = HDA_SD_BASE + regindex * HDA_SD_SIZE;
    3590           0 :         this->intr_bit = 1 << regindex;
    3591           0 :         this->number = strnum;
    3592           0 :         this->dir = dir;
    3593             : 
    3594             :         /* setup BDL buffers */
    3595           0 :         err = azalia_alloc_dmamem(az, sizeof(bdlist_entry_t) * HDA_BDL_MAX,
    3596           0 :                                   128, &this->bdlist);
    3597           0 :         if (err) {
    3598           0 :                 printf("%s: can't allocate a BDL buffer\n", XNAME(az));
    3599           0 :                 return err;
    3600             :         }
    3601           0 :         return 0;
    3602           0 : }
    3603             : 
    3604             : int
    3605           0 : azalia_stream_reset(stream_t *this)
    3606             : {
    3607             :         int i;
    3608             :         uint16_t ctl;
    3609             :         uint8_t sts;
    3610             : 
    3611             :         /* Make sure RUN bit is zero before resetting */
    3612           0 :         ctl = STR_READ_2(this, CTL);
    3613           0 :         ctl &= ~HDA_SD_CTL_RUN;
    3614           0 :         STR_WRITE_2(this, CTL, ctl);
    3615           0 :         DELAY(40);
    3616             : 
    3617             :         /* Start reset and wait for chip to enter. */
    3618           0 :         ctl = STR_READ_2(this, CTL);
    3619           0 :         STR_WRITE_2(this, CTL, ctl | HDA_SD_CTL_SRST);
    3620           0 :         for (i = 5000; i > 0; i--) {
    3621           0 :                 DELAY(10);
    3622           0 :                 ctl = STR_READ_2(this, CTL);
    3623           0 :                 if (ctl & HDA_SD_CTL_SRST)
    3624             :                         break;
    3625             :         }
    3626           0 :         if (i == 0) {
    3627             :                 DPRINTF(("%s: stream reset failure 1\n", XNAME(this->az)));
    3628           0 :                 return -1;
    3629             :         }
    3630             : 
    3631             :         /* Clear reset and wait for chip to finish */
    3632           0 :         STR_WRITE_2(this, CTL, ctl & ~HDA_SD_CTL_SRST);
    3633           0 :         for (i = 5000; i > 0; i--) {
    3634           0 :                 DELAY(10);
    3635           0 :                 ctl = STR_READ_2(this, CTL);
    3636           0 :                 if ((ctl & HDA_SD_CTL_SRST) == 0)
    3637             :                         break;
    3638             :         }
    3639           0 :         if (i == 0) {
    3640             :                 DPRINTF(("%s: stream reset failure 2\n", XNAME(this->az)));
    3641           0 :                 return -1;
    3642             :         }
    3643             : 
    3644           0 :         sts = STR_READ_1(this, STS);
    3645           0 :         sts |= HDA_SD_STS_DESE | HDA_SD_STS_FIFOE | HDA_SD_STS_BCIS;
    3646           0 :         STR_WRITE_1(this, STS, sts);
    3647             : 
    3648           0 :         return (0);
    3649           0 : }
    3650             : 
    3651             : int
    3652           0 : azalia_stream_start(stream_t *this)
    3653             : {
    3654             :         bdlist_entry_t *bdlist;
    3655             :         bus_addr_t dmaaddr, dmaend;
    3656             :         int err, index;
    3657             :         uint32_t intctl;
    3658             :         uint8_t ctl2;
    3659             : 
    3660           0 :         err = azalia_stream_reset(this);
    3661           0 :         if (err) {
    3662             :                 DPRINTF(("%s: stream reset failed\n", "azalia"));
    3663           0 :                 return err;
    3664             :         }
    3665             : 
    3666           0 :         STR_WRITE_4(this, BDPL, 0);
    3667           0 :         STR_WRITE_4(this, BDPU, 0);
    3668             : 
    3669             :         /* setup BDL */
    3670           0 :         dmaaddr = AZALIA_DMA_DMAADDR(&this->buffer);
    3671           0 :         dmaend = dmaaddr + this->bufsize;
    3672           0 :         bdlist = (bdlist_entry_t*)this->bdlist.addr;
    3673           0 :         for (index = 0; index < HDA_BDL_MAX; index++) {
    3674           0 :                 bdlist[index].low = htole32(dmaaddr);
    3675           0 :                 bdlist[index].high = htole32(PTR_UPPER32(dmaaddr));
    3676           0 :                 bdlist[index].length = htole32(this->blk);
    3677           0 :                 bdlist[index].flags = htole32(BDLIST_ENTRY_IOC);
    3678           0 :                 dmaaddr += this->blk;
    3679           0 :                 if (dmaaddr >= dmaend) {
    3680             :                         index++;
    3681             :                         break;
    3682             :                 }
    3683             :         }
    3684             : 
    3685             :         DPRINTFN(1, ("%s: size=%d fmt=0x%4.4x index=%d\n",
    3686             :             __func__, this->bufsize, this->fmt, index));
    3687             : 
    3688           0 :         dmaaddr = AZALIA_DMA_DMAADDR(&this->bdlist);
    3689           0 :         STR_WRITE_4(this, BDPL, dmaaddr);
    3690           0 :         STR_WRITE_4(this, BDPU, PTR_UPPER32(dmaaddr));
    3691           0 :         STR_WRITE_2(this, LVI, (index - 1) & HDA_SD_LVI_LVI);
    3692           0 :         ctl2 = STR_READ_1(this, CTL2);
    3693           0 :         STR_WRITE_1(this, CTL2,
    3694             :             (ctl2 & ~HDA_SD_CTL2_STRM) | (this->number << HDA_SD_CTL2_STRM_SHIFT));
    3695           0 :         STR_WRITE_4(this, CBL, this->bufsize);
    3696           0 :         STR_WRITE_2(this, FMT, this->fmt);
    3697             : 
    3698           0 :         err = azalia_codec_connect_stream(this);
    3699           0 :         if (err)
    3700           0 :                 return EINVAL;
    3701             : 
    3702           0 :         intctl = AZ_READ_4(this->az, INTCTL);
    3703           0 :         intctl |= this->intr_bit;
    3704           0 :         AZ_WRITE_4(this->az, INTCTL, intctl);
    3705             : 
    3706           0 :         STR_WRITE_1(this, CTL, STR_READ_1(this, CTL) |
    3707             :             HDA_SD_CTL_DEIE | HDA_SD_CTL_FEIE | HDA_SD_CTL_IOCE |
    3708             :             HDA_SD_CTL_RUN);
    3709           0 :         return (0);
    3710           0 : }
    3711             : 
    3712             : int
    3713           0 : azalia_stream_halt(stream_t *this)
    3714             : {
    3715             :         uint16_t ctl;
    3716             : 
    3717           0 :         ctl = STR_READ_2(this, CTL);
    3718           0 :         ctl &= ~(HDA_SD_CTL_DEIE | HDA_SD_CTL_FEIE | HDA_SD_CTL_IOCE | HDA_SD_CTL_RUN);
    3719           0 :         STR_WRITE_2(this, CTL, ctl);
    3720           0 :         AZ_WRITE_4(this->az, INTCTL,
    3721             :             AZ_READ_4(this->az, INTCTL) & ~this->intr_bit);
    3722           0 :         azalia_codec_disconnect_stream(this);
    3723             : 
    3724           0 :         return (0);
    3725             : }
    3726             : 
    3727             : #define HDA_SD_STS_BITS "\20\3BCIS\4FIFOE\5DESE\6FIFORDY"
    3728             : 
    3729             : int
    3730           0 : azalia_stream_intr(stream_t *this)
    3731             : {
    3732             :         unsigned int lpib, fifos, hwpos, cnt;
    3733             :         u_int8_t sts;
    3734             : 
    3735           0 :         sts = STR_READ_1(this, STS);
    3736           0 :         STR_WRITE_1(this, STS, sts |
    3737             :             HDA_SD_STS_DESE | HDA_SD_STS_FIFOE | HDA_SD_STS_BCIS);
    3738             : 
    3739           0 :         if (sts & (HDA_SD_STS_DESE | HDA_SD_STS_FIFOE))
    3740             :                 DPRINTF(("%s: stream %d: sts=%b\n", XNAME(this->az),
    3741             :                     this->number, sts, HDA_SD_STS_BITS));
    3742             : 
    3743           0 :         if (sts & HDA_SD_STS_BCIS) {
    3744           0 :                 lpib = STR_READ_4(this, LPIB);
    3745           0 :                 fifos = STR_READ_2(this, FIFOS);
    3746           0 :                 if (fifos & 1)
    3747           0 :                         fifos++;
    3748             :                 hwpos = lpib;
    3749           0 :                 if (this->dir == AUMODE_PLAY)
    3750           0 :                         hwpos += fifos + 1;
    3751           0 :                 if (hwpos >= this->bufsize)
    3752           0 :                         hwpos -= this->bufsize;
    3753             :                 DPRINTFN(2, ("%s: stream %d, pos = %d -> %d, "
    3754             :                     "lpib = %u, fifos = %u\n", __func__,
    3755             :                     this->number, this->swpos, hwpos, lpib, fifos));
    3756             :                 cnt = 0;
    3757           0 :                 while (hwpos - this->swpos >= this->blk) {
    3758           0 :                         this->intr(this->intr_arg);
    3759           0 :                         this->swpos += this->blk;
    3760           0 :                         if (this->swpos == this->bufsize)
    3761           0 :                                 this->swpos = 0;
    3762           0 :                         cnt++;
    3763             :                 }
    3764             :                 if (cnt != 1) {
    3765             :                         DPRINTF(("%s: stream %d: hwpos %u, %u intrs\n",
    3766             :                             __func__, this->number, this->swpos, cnt));
    3767             :                 }
    3768           0 :         }
    3769           0 :         return (1);
    3770             : }
    3771             : 
    3772             : /* ================================================================
    3773             :  * MI audio entries
    3774             :  * ================================================================ */
    3775             : 
    3776             : int
    3777           0 : azalia_open(void *v, int flags)
    3778             : {
    3779             :         azalia_t *az;
    3780             :         codec_t *codec;
    3781             : 
    3782             :         DPRINTFN(1, ("%s: flags=0x%x\n", __func__, flags));
    3783           0 :         az = v;
    3784           0 :         codec = &az->codecs[az->codecno];
    3785           0 :         if ((flags & FWRITE) && codec->dacs.ngroups == 0)
    3786           0 :                 return ENODEV;
    3787           0 :         if ((flags & FREAD) && codec->adcs.ngroups == 0)
    3788           0 :                 return ENODEV;
    3789           0 :         codec->running++;
    3790           0 :         return 0;
    3791           0 : }
    3792             : 
    3793             : void
    3794           0 : azalia_close(void *v)
    3795             : {
    3796             :         azalia_t *az;
    3797             :         codec_t *codec;
    3798             : 
    3799             :         DPRINTFN(1, ("%s\n", __func__));
    3800           0 :         az = v;
    3801           0 :         codec = &az->codecs[az->codecno];
    3802           0 :         codec->running--;
    3803           0 : }
    3804             : 
    3805             : int
    3806           0 : azalia_match_format(codec_t *codec, int mode, audio_params_t *par)
    3807             : {
    3808             :         int i;
    3809             : 
    3810             :         DPRINTFN(1, ("%s: mode=%d, want: enc=%d, prec=%d, chans=%d\n", __func__,
    3811             :             mode, par->encoding, par->precision, par->channels));
    3812             : 
    3813           0 :         for (i = 0; i < codec->nformats; i++) {
    3814           0 :                 if (mode != codec->formats[i].mode)
    3815             :                         continue;
    3816           0 :                 if (par->encoding != codec->formats[i].encoding)
    3817             :                         continue;
    3818           0 :                 if (par->precision != codec->formats[i].precision)
    3819             :                         continue;
    3820           0 :                 if (par->channels != codec->formats[i].channels)
    3821             :                         continue;
    3822             :                 break;
    3823             :         }
    3824             : 
    3825             :         DPRINTFN(1, ("%s: return: enc=%d, prec=%d, chans=%d\n", __func__,
    3826             :             codec->formats[i].encoding, codec->formats[i].precision,
    3827             :             codec->formats[i].channels));
    3828             : 
    3829           0 :         return (i);
    3830             : }
    3831             : 
    3832             : int
    3833           0 : azalia_set_params_sub(codec_t *codec, int mode, audio_params_t *par)
    3834             : {
    3835             :         int i, j;
    3836             :         uint ochan, oenc, opre;
    3837             : #ifdef AZALIA_DEBUG
    3838             :         char *cmode = (mode == AUMODE_PLAY) ? "play" : "record";
    3839             : #endif
    3840             : 
    3841           0 :         ochan = par->channels;
    3842           0 :         oenc = par->encoding;
    3843           0 :         opre = par->precision;
    3844             : 
    3845           0 :         if ((mode == AUMODE_PLAY && codec->dacs.ngroups == 0) ||
    3846           0 :             (mode == AUMODE_RECORD && codec->adcs.ngroups == 0))
    3847           0 :                 return 0;
    3848             : 
    3849           0 :         i = azalia_match_format(codec, mode, par);
    3850           0 :         if (i == codec->nformats && (par->precision != 16 || par->encoding !=
    3851             :             AUDIO_ENCODING_SLINEAR_LE)) {
    3852             :                 /* try with default encoding/precision */
    3853           0 :                 par->encoding = AUDIO_ENCODING_SLINEAR_LE;
    3854           0 :                 par->precision = 16;
    3855           0 :                 i = azalia_match_format(codec, mode, par);
    3856           0 :         }
    3857           0 :         if (i == codec->nformats && par->channels != 2) {
    3858             :                 /* try with default channels */
    3859           0 :                 par->encoding = oenc;
    3860           0 :                 par->precision = opre;
    3861           0 :                 par->channels = 2;
    3862           0 :                 i = azalia_match_format(codec, mode, par);
    3863           0 :         }
    3864             :         /* try with default everything */
    3865           0 :         if (i == codec->nformats) {
    3866           0 :                 par->encoding = AUDIO_ENCODING_SLINEAR_LE;
    3867           0 :                 par->precision = 16;
    3868           0 :                 par->channels = 2;
    3869           0 :                 i = azalia_match_format(codec, mode, par);
    3870           0 :                 if (i == codec->nformats) {
    3871             :                         DPRINTF(("%s: can't find %s format %u/%u/%u\n",
    3872             :                             __func__, cmode, par->encoding,
    3873             :                             par->precision, par->channels));
    3874           0 :                         return EINVAL;
    3875             :                 }
    3876             :         }
    3877           0 :         if (codec->formats[i].frequency_type == 0) {
    3878             :                 DPRINTF(("%s: matched %s format %d has 0 frequencies\n",
    3879             :                     __func__, cmode, i));
    3880           0 :                 return EINVAL;
    3881             :         }
    3882             : 
    3883           0 :         for (j = 0; j < codec->formats[i].frequency_type; j++) {
    3884           0 :                 if (par->sample_rate != codec->formats[i].frequency[j])
    3885             :                         continue;
    3886             :                 break;
    3887             :         }
    3888           0 :         if (j == codec->formats[i].frequency_type) {
    3889             :                 /* try again with default */
    3890           0 :                 par->sample_rate = 48000;
    3891           0 :                 for (j = 0; j < codec->formats[i].frequency_type; j++) {
    3892           0 :                         if (par->sample_rate != codec->formats[i].frequency[j])
    3893             :                                 continue;
    3894             :                         break;
    3895             :                 }
    3896           0 :                 if (j == codec->formats[i].frequency_type) {
    3897             :                         DPRINTF(("%s: can't find %s rate %lu\n",
    3898             :                             __func__, cmode, par->sample_rate));
    3899           0 :                         return EINVAL;
    3900             :                 }
    3901             :         }
    3902           0 :         par->bps = AUDIO_BPS(par->precision);
    3903           0 :         par->msb = 1;
    3904             : 
    3905           0 :         return (0);
    3906           0 : }
    3907             : 
    3908             : int
    3909           0 : azalia_set_params(void *v, int smode, int umode, audio_params_t *p,
    3910             :     audio_params_t *r)
    3911             : {
    3912             :         azalia_t *az;
    3913             :         codec_t *codec;
    3914             :         int ret;
    3915             : 
    3916           0 :         az = v;
    3917           0 :         codec = &az->codecs[az->codecno];
    3918           0 :         if (codec->nformats == 0) {
    3919             :                 DPRINTF(("%s: codec has no formats\n", __func__));
    3920           0 :                 return EINVAL;
    3921             :         }
    3922             : 
    3923           0 :         if (smode & AUMODE_RECORD && r != NULL) {
    3924           0 :                 ret = azalia_set_params_sub(codec, AUMODE_RECORD, r);
    3925           0 :                 if (ret)
    3926           0 :                         return (ret);
    3927             :         }
    3928             : 
    3929           0 :         if (smode & AUMODE_PLAY && p != NULL) {
    3930           0 :                 ret = azalia_set_params_sub(codec, AUMODE_PLAY, p);
    3931           0 :                 if (ret)
    3932           0 :                         return (ret);
    3933             :         }
    3934             : 
    3935           0 :         return (0);
    3936           0 : }
    3937             : 
    3938             : int
    3939           0 : azalia_round_blocksize(void *v, int blk)
    3940             : {
    3941             :         azalia_t *az;
    3942             :         size_t size;
    3943             : 
    3944           0 :         blk &= ~0x7f;               /* must be multiple of 128 */
    3945           0 :         if (blk <= 0)
    3946             :                 blk = 128;
    3947             :         /* number of blocks must be <= HDA_BDL_MAX */
    3948           0 :         az = v;
    3949           0 :         size = az->pstream.buffer.size;
    3950           0 :         if (size > HDA_BDL_MAX * blk) {
    3951           0 :                 blk = size / HDA_BDL_MAX;
    3952           0 :                 if (blk & 0x7f)
    3953           0 :                         blk = (blk + 0x7f) & ~0x7f;
    3954             :         }
    3955             :         DPRINTFN(1,("%s: resultant block size = %d\n", __func__, blk));
    3956           0 :         return blk;
    3957             : }
    3958             : 
    3959             : int
    3960           0 : azalia_halt_output(void *v)
    3961             : {
    3962             :         azalia_t *az;
    3963             : 
    3964             :         DPRINTFN(1, ("%s\n", __func__));
    3965           0 :         az = v;
    3966           0 :         return azalia_stream_halt(&az->pstream);
    3967             : }
    3968             : 
    3969             : int
    3970           0 : azalia_halt_input(void *v)
    3971             : {
    3972             :         azalia_t *az;
    3973             : 
    3974             :         DPRINTFN(1, ("%s\n", __func__));
    3975           0 :         az = v;
    3976           0 :         return azalia_stream_halt(&az->rstream);
    3977             : }
    3978             : 
    3979             : int
    3980           0 : azalia_set_port(void *v, mixer_ctrl_t *mc)
    3981             : {
    3982             :         azalia_t *az;
    3983             :         codec_t *co;
    3984             :         const mixer_item_t *m;
    3985             : 
    3986           0 :         az = v;
    3987           0 :         co = &az->codecs[az->codecno];
    3988           0 :         if (mc->dev < 0 || mc->dev >= co->nmixers)
    3989           0 :                 return EINVAL;
    3990             : 
    3991           0 :         m = &co->mixers[mc->dev];
    3992           0 :         if (mc->type != m->devinfo.type)
    3993           0 :                 return EINVAL;
    3994             : 
    3995           0 :         return azalia_mixer_set(co, m->nid, m->target, mc);
    3996           0 : }
    3997             : 
    3998             : int
    3999           0 : azalia_get_port(void *v, mixer_ctrl_t *mc)
    4000             : {
    4001             :         azalia_t *az;
    4002             :         codec_t *co;
    4003             :         const mixer_item_t *m;
    4004             : 
    4005           0 :         az = v;
    4006           0 :         co = &az->codecs[az->codecno];
    4007           0 :         if (mc->dev < 0 || mc->dev >= co->nmixers)
    4008           0 :                 return EINVAL;
    4009             : 
    4010           0 :         m = &co->mixers[mc->dev];
    4011           0 :         mc->type = m->devinfo.type;
    4012             : 
    4013           0 :         return azalia_mixer_get(co, m->nid, m->target, mc);
    4014           0 : }
    4015             : 
    4016             : int
    4017           0 : azalia_query_devinfo(void *v, mixer_devinfo_t *mdev)
    4018             : {
    4019             :         azalia_t *az;
    4020             :         const codec_t *co;
    4021             : 
    4022           0 :         az = v;
    4023           0 :         co = &az->codecs[az->codecno];
    4024           0 :         if (mdev->index < 0 || mdev->index >= co->nmixers)
    4025           0 :                 return ENXIO;
    4026           0 :         *mdev = co->mixers[mdev->index].devinfo;
    4027           0 :         return 0;
    4028           0 : }
    4029             : 
    4030             : void *
    4031           0 : azalia_allocm(void *v, int dir, size_t size, int pool, int flags)
    4032             : {
    4033             :         azalia_t *az;
    4034             :         stream_t *stream;
    4035             :         int err;
    4036             : 
    4037           0 :         az = v;
    4038           0 :         stream = dir == AUMODE_PLAY ? &az->pstream : &az->rstream;
    4039           0 :         err = azalia_alloc_dmamem(az, size, 128, &stream->buffer);
    4040           0 :         if (err) {
    4041           0 :                 printf("%s: allocm failed\n", az->dev.dv_xname);
    4042           0 :                 return NULL;
    4043             :         }
    4044           0 :         return stream->buffer.addr;
    4045           0 : }
    4046             : 
    4047             : void
    4048           0 : azalia_freem(void *v, void *addr, int pool)
    4049             : {
    4050             :         azalia_t *az;
    4051             :         stream_t *stream;
    4052             : 
    4053           0 :         az = v;
    4054           0 :         if (addr == az->pstream.buffer.addr) {
    4055             :                 stream = &az->pstream;
    4056           0 :         } else if (addr == az->rstream.buffer.addr) {
    4057             :                 stream = &az->rstream;
    4058             :         } else {
    4059           0 :                 return;
    4060             :         }
    4061           0 :         azalia_free_dmamem(az, &stream->buffer);
    4062           0 : }
    4063             : 
    4064             : size_t
    4065           0 : azalia_round_buffersize(void *v, int dir, size_t size)
    4066             : {
    4067           0 :         size &= ~0x7f;              /* must be multiple of 128 */
    4068           0 :         if (size <= 0)
    4069             :                 size = 128;
    4070           0 :         return size;
    4071             : }
    4072             : 
    4073             : int
    4074           0 : azalia_get_props(void *v)
    4075             : {
    4076           0 :         return AUDIO_PROP_INDEPENDENT | AUDIO_PROP_FULLDUPLEX;
    4077             : }
    4078             : 
    4079             : int
    4080           0 : azalia_trigger_output(void *v, void *start, void *end, int blk,
    4081             :     void (*intr)(void *), void *arg, audio_params_t *param)
    4082             : {
    4083             :         azalia_t *az;
    4084             :         int err;
    4085           0 :         uint16_t fmt;
    4086             : 
    4087           0 :         az = v;
    4088             : 
    4089           0 :         if (az->codecs[az->codecno].dacs.ngroups == 0) {
    4090             :                 DPRINTF(("%s: can't play without a DAC\n", __func__));
    4091           0 :                 return ENXIO;
    4092             :         }
    4093             : 
    4094           0 :         err = azalia_params2fmt(param, &fmt);
    4095           0 :         if (err)
    4096           0 :                 return(EINVAL);
    4097             : 
    4098           0 :         az->pstream.bufsize = (caddr_t)end - (caddr_t)start;
    4099           0 :         az->pstream.blk = blk;
    4100           0 :         az->pstream.fmt = fmt;
    4101           0 :         az->pstream.intr = intr;
    4102           0 :         az->pstream.intr_arg = arg;
    4103           0 :         az->pstream.swpos = 0;
    4104             : 
    4105           0 :         return azalia_stream_start(&az->pstream);
    4106           0 : }
    4107             : 
    4108             : int
    4109           0 : azalia_trigger_input(void *v, void *start, void *end, int blk,
    4110             :     void (*intr)(void *), void *arg, audio_params_t *param)
    4111             : {
    4112             :         azalia_t *az;
    4113             :         int err;
    4114           0 :         uint16_t fmt;
    4115             : 
    4116             :         DPRINTFN(1, ("%s: this=%p start=%p end=%p blk=%d {enc=%u %uch %ubit %luHz}\n",
    4117             :             __func__, v, start, end, blk, param->encoding, param->channels,
    4118             :             param->precision, param->sample_rate));
    4119             : 
    4120           0 :         az = v;
    4121             : 
    4122           0 :         if (az->codecs[az->codecno].adcs.ngroups == 0) {
    4123             :                 DPRINTF(("%s: can't record without an ADC\n", __func__));
    4124           0 :                 return ENXIO;
    4125             :         }
    4126             : 
    4127           0 :         err = azalia_params2fmt(param, &fmt);
    4128           0 :         if (err)
    4129           0 :                 return(EINVAL);
    4130             : 
    4131           0 :         az->rstream.bufsize = (caddr_t)end - (caddr_t)start;
    4132           0 :         az->rstream.blk = blk;
    4133           0 :         az->rstream.fmt = fmt;
    4134           0 :         az->rstream.intr = intr;
    4135           0 :         az->rstream.intr_arg = arg;
    4136           0 :         az->rstream.swpos = 0;
    4137             : 
    4138           0 :         return azalia_stream_start(&az->rstream);
    4139           0 : }
    4140             : 
    4141             : /* --------------------------------
    4142             :  * helpers for MI audio functions
    4143             :  * -------------------------------- */
    4144             : int
    4145           0 : azalia_params2fmt(const audio_params_t *param, uint16_t *fmt)
    4146             : {
    4147             :         uint16_t ret;
    4148             : 
    4149             :         ret = 0;
    4150           0 :         if (param->channels > HDA_MAX_CHANNELS) {
    4151           0 :                 printf("%s: too many channels: %u\n", __func__,
    4152             :                     param->channels);
    4153           0 :                 return EINVAL;
    4154             :         }
    4155             : 
    4156             :         DPRINTFN(1, ("%s: prec=%d, chan=%d, rate=%ld\n", __func__,
    4157             :             param->precision, param->channels, param->sample_rate));
    4158             : 
    4159             :         /* XXX: can channels be >2 ? */
    4160           0 :         ret |= param->channels - 1;
    4161             : 
    4162           0 :         switch (param->precision) {
    4163             :         case 8:
    4164           0 :                 ret |= HDA_SD_FMT_BITS_8_16;
    4165           0 :                 break;
    4166             :         case 16:
    4167           0 :                 ret |= HDA_SD_FMT_BITS_16_16;
    4168           0 :                 break;
    4169             :         case 20:
    4170           0 :                 ret |= HDA_SD_FMT_BITS_20_32;
    4171           0 :                 break;
    4172             :         case 24:
    4173           0 :                 ret |= HDA_SD_FMT_BITS_24_32;
    4174           0 :                 break;
    4175             :         case 32:
    4176           0 :                 ret |= HDA_SD_FMT_BITS_32_32;
    4177           0 :                 break;
    4178             :         }
    4179             : 
    4180           0 :         switch (param->sample_rate) {
    4181             :         default:
    4182             :         case 384000:
    4183           0 :                 printf("%s: invalid sample_rate: %lu\n", __func__,
    4184             :                     param->sample_rate);
    4185           0 :                 return EINVAL;
    4186             :         case 192000:
    4187           0 :                 ret |= HDA_SD_FMT_BASE_48 | HDA_SD_FMT_MULT_X4 | HDA_SD_FMT_DIV_BY1;
    4188           0 :                 break;
    4189             :         case 176400:
    4190           0 :                 ret |= HDA_SD_FMT_BASE_44 | HDA_SD_FMT_MULT_X4 | HDA_SD_FMT_DIV_BY1;
    4191           0 :                 break;
    4192             :         case 96000:
    4193           0 :                 ret |= HDA_SD_FMT_BASE_48 | HDA_SD_FMT_MULT_X2 | HDA_SD_FMT_DIV_BY1;
    4194           0 :                 break;
    4195             :         case 88200:
    4196           0 :                 ret |= HDA_SD_FMT_BASE_44 | HDA_SD_FMT_MULT_X2 | HDA_SD_FMT_DIV_BY1;
    4197           0 :                 break;
    4198             :         case 48000:
    4199           0 :                 ret |= HDA_SD_FMT_BASE_48 | HDA_SD_FMT_MULT_X1 | HDA_SD_FMT_DIV_BY1;
    4200           0 :                 break;
    4201             :         case 44100:
    4202           0 :                 ret |= HDA_SD_FMT_BASE_44 | HDA_SD_FMT_MULT_X1 | HDA_SD_FMT_DIV_BY1;
    4203           0 :                 break;
    4204             :         case 32000:
    4205           0 :                 ret |= HDA_SD_FMT_BASE_48 | HDA_SD_FMT_MULT_X2 | HDA_SD_FMT_DIV_BY3;
    4206           0 :                 break;
    4207             :         case 22050:
    4208           0 :                 ret |= HDA_SD_FMT_BASE_44 | HDA_SD_FMT_MULT_X1 | HDA_SD_FMT_DIV_BY2;
    4209           0 :                 break;
    4210             :         case 16000:
    4211           0 :                 ret |= HDA_SD_FMT_BASE_48 | HDA_SD_FMT_MULT_X1 | HDA_SD_FMT_DIV_BY3;
    4212           0 :                 break;
    4213             :         case 11025:
    4214           0 :                 ret |= HDA_SD_FMT_BASE_44 | HDA_SD_FMT_MULT_X1 | HDA_SD_FMT_DIV_BY4;
    4215           0 :                 break;
    4216             :         case 8000:
    4217           0 :                 ret |= HDA_SD_FMT_BASE_48 | HDA_SD_FMT_MULT_X1 | HDA_SD_FMT_DIV_BY6;
    4218           0 :                 break;
    4219             :         }
    4220           0 :         *fmt = ret;
    4221           0 :         return 0;
    4222           0 : }

Generated by: LCOV version 1.13