summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authorjmcneill <jmcneill@NetBSD.org>2020-02-09 16:06:17 +0000
committerjmcneill <jmcneill@NetBSD.org>2020-02-09 16:06:17 +0000
commit41eed51bcd4f205bc6fc7926b3380043ffd78b4f (patch)
tree65f5b9e00630a32783690334551c5db14a8bf8a7 /sys/dev
parent80f479d86218ae5e2acf27865a7860eb18c4417a (diff)
Retire azalia(4).
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/DEVNAMES3
-rw-r--r--sys/dev/pci/azalia.c2436
-rw-r--r--sys/dev/pci/azalia.h594
-rw-r--r--sys/dev/pci/azalia_codec.c4278
-rw-r--r--sys/dev/pci/files.pci8
5 files changed, 2 insertions, 7317 deletions
diff --git a/sys/dev/DEVNAMES b/sys/dev/DEVNAMES
index b1c753bb950..48b620e312c 100644
--- a/sys/dev/DEVNAMES
+++ b/sys/dev/DEVNAMES
@@ -1,4 +1,4 @@
-# $NetBSD: DEVNAMES,v 1.326 2020/01/17 15:00:20 maya Exp $
+# $NetBSD: DEVNAMES,v 1.327 2020/02/09 16:06:18 jmcneill Exp $
#
# This file contains all used device names and defined attributes in
# alphabetical order. New devices added to the system somewhere should first
@@ -150,7 +150,6 @@ avmebus atari
awi MI
axe MI
az MI
-azalia MI
bah MI
bandit macppc
bba MI
diff --git a/sys/dev/pci/azalia.c b/sys/dev/pci/azalia.c
deleted file mode 100644
index 48ba674171c..00000000000
--- a/sys/dev/pci/azalia.c
+++ /dev/null
@@ -1,2436 +0,0 @@
-/* $NetBSD: azalia.c,v 1.88 2019/06/08 08:02:38 isaki Exp $ */
-
-/*-
- * Copyright (c) 2005, 2008 The NetBSD Foundation, Inc.
- * All rights reserved.
- *
- * This code is derived from software contributed to The NetBSD Foundation
- * by TAMURA Kent
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * High Definition Audio Specification
- * ftp://download.intel.com/standards/hdaudio/pdf/HDAudio_03.pdf
- *
- *
- * TO DO:
- * - power hook
- * - multiple codecs (needed?)
- * - multiple streams (needed?)
- */
-
-#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: azalia.c,v 1.88 2019/06/08 08:02:38 isaki Exp $");
-
-#include <sys/param.h>
-#include <sys/device.h>
-#include <sys/fcntl.h>
-#include <sys/kmem.h>
-#include <sys/systm.h>
-#include <sys/module.h>
-
-#include <dev/audio/audio_if.h>
-
-#include <dev/pci/pcidevs.h>
-#include <dev/pci/pcivar.h>
-#include <dev/pci/azalia.h>
-
-/* ----------------------------------------------------------------
- * ICH6/ICH7 constant values
- * ---------------------------------------------------------------- */
-
-/* PCI registers */
-#define ICH_PCI_HDBARL 0x10
-#define ICH_PCI_HDBARU 0x14
-#define ICH_PCI_HDCTL 0x40
-#define ICH_PCI_HDCTL_CLKDETCLR 0x08
-#define ICH_PCI_HDCTL_CLKDETEN 0x04
-#define ICH_PCI_HDCTL_CLKDETINV 0x02
-#define ICH_PCI_HDCTL_SIGNALMODE 0x01
-
-/* internal types */
-
-typedef struct {
- bus_dmamap_t map;
- void *addr; /* kernel virtual address */
- bus_dma_segment_t segments[1];
- size_t size;
-} azalia_dma_t;
-
-#define AZALIA_DMA_DMAADDR(p) ((p)->map->dm_segs[0].ds_addr)
-
-typedef struct {
- struct azalia_t *az;
- int regbase;
- int number;
- int dir; /* AUMODE_PLAY or AUMODE_RECORD */
- uint32_t intr_bit;
- azalia_dma_t bdlist;
- azalia_dma_t buffer;
- void (*intr)(void*);
- void *intr_arg;
- bus_addr_t dmaend, dmanext; /* XXX needed? */
-} stream_t;
-
-/* XXXfreza use bus_space_subregion() instead of adding 'regbase' offset */
-#define STR_READ_1(s, r) \
- bus_space_read_1((s)->az->iot, (s)->az->ioh, (s)->regbase + HDA_SD_##r)
-#define STR_READ_2(s, r) \
- bus_space_read_2((s)->az->iot, (s)->az->ioh, (s)->regbase + HDA_SD_##r)
-#define STR_READ_4(s, r) \
- bus_space_read_4((s)->az->iot, (s)->az->ioh, (s)->regbase + HDA_SD_##r)
-#define STR_WRITE_1(s, r, v) \
- bus_space_write_1((s)->az->iot, (s)->az->ioh, (s)->regbase + HDA_SD_##r, v)
-#define STR_WRITE_2(s, r, v) \
- bus_space_write_2((s)->az->iot, (s)->az->ioh, (s)->regbase + HDA_SD_##r, v)
-#define STR_WRITE_4(s, r, v) \
- bus_space_write_4((s)->az->iot, (s)->az->ioh, (s)->regbase + HDA_SD_##r, v)
-
-typedef struct azalia_t {
- device_t dev;
- device_t audiodev;
- kmutex_t lock;
- kmutex_t intr_lock;
-
- pci_chipset_tag_t pc;
- pcitag_t tag;
- void *ih;
- bus_space_tag_t iot;
- bus_space_handle_t ioh;
- bus_size_t map_size;
- bus_dma_tag_t dmat;
- pcireg_t pciid;
- uint32_t subid;
-
- codec_t codecs[15];
- int ncodecs; /* number of codecs */
- int codecno; /* index of the using codec */
-
- azalia_dma_t corb_dma;
- int corb_size;
- azalia_dma_t rirb_dma;
- int rirb_size;
- int rirb_rp;
-#define UNSOLQ_SIZE 256
- rirb_entry_t *unsolq;
- int unsolq_wp;
- int unsolq_rp;
- bool unsolq_kick;
-
- bool ok64;
- int nistreams, nostreams, nbstreams;
- stream_t pstream;
- stream_t rstream;
-
- int mode_cap;
-} azalia_t;
-
-#define AZ_READ_1(z, r) bus_space_read_1((z)->iot, (z)->ioh, HDA_##r)
-#define AZ_READ_2(z, r) bus_space_read_2((z)->iot, (z)->ioh, HDA_##r)
-#define AZ_READ_4(z, r) bus_space_read_4((z)->iot, (z)->ioh, HDA_##r)
-#define AZ_WRITE_1(z, r, v) bus_space_write_1((z)->iot, (z)->ioh, HDA_##r, v)
-#define AZ_WRITE_2(z, r, v) bus_space_write_2((z)->iot, (z)->ioh, HDA_##r, v)
-#define AZ_WRITE_4(z, r, v) bus_space_write_4((z)->iot, (z)->ioh, HDA_##r, v)
-
-
-/* prototypes */
-static int azalia_pci_match(device_t, cfdata_t, void *);
-static void azalia_pci_attach(device_t, device_t, void *);
-static int azalia_pci_detach(device_t, int);
-static bool azalia_pci_resume(device_t, const pmf_qual_t *);
-static void azalia_childdet(device_t, device_t);
-static int azalia_intr(void *);
-static int azalia_attach(azalia_t *);
-static void azalia_attach_intr(device_t);
-static int azalia_init_corb(azalia_t *, int);
-static int azalia_delete_corb(azalia_t *);
-static int azalia_init_rirb(azalia_t *, int);
-static int azalia_delete_rirb(azalia_t *);
-static int azalia_set_command(const azalia_t *, nid_t, int, uint32_t,
- uint32_t);
-static int azalia_get_response(azalia_t *, uint32_t *);
-static void azalia_rirb_kick_unsol_events(azalia_t *);
-static void azalia_rirb_intr(azalia_t *);
-static int azalia_alloc_dmamem(azalia_t *, size_t, size_t, azalia_dma_t *);
-static int azalia_free_dmamem(const azalia_t *, azalia_dma_t*);
-
-static int azalia_codec_init(codec_t *, int, uint32_t);
-static int azalia_codec_delete(codec_t *);
-static void azalia_codec_add_bits(codec_t *, int, uint32_t, int);
-static void azalia_codec_add_format(codec_t *, int, int, int, uint32_t,
- int32_t);
-static int azalia_codec_comresp(const codec_t *, nid_t, uint32_t,
- uint32_t, uint32_t *);
-static int azalia_codec_connect_stream(codec_t *, int, uint16_t, int);
-static int azalia_codec_disconnect_stream(codec_t *, int);
-
-static int azalia_widget_init(widget_t *, const codec_t *, int, const char *);
-static int azalia_widget_init_audio(widget_t *, const codec_t *, const char *);
-#ifdef AZALIA_DEBUG
-static int azalia_widget_print_audio(const widget_t *, const char *, int);
-#endif
-static int azalia_widget_init_pin(widget_t *, const codec_t *);
-static int azalia_widget_print_pin(const widget_t *, const char *);
-static int azalia_widget_init_connection(widget_t *, const codec_t *, const char *);
-
-static int azalia_stream_init(stream_t *, azalia_t *, int, int, int);
-static int azalia_stream_delete(stream_t *, azalia_t *);
-static int azalia_stream_reset(stream_t *);
-static int azalia_stream_start(stream_t *, void *, void *, int,
- void (*)(void *), void *, uint16_t);
-static int azalia_stream_halt(stream_t *);
-static int azalia_stream_intr(stream_t *, uint32_t);
-
-static int azalia_open(void *, int);
-static void azalia_close(void *);
-static int azalia_query_format(void *, audio_format_query_t *);
-static int azalia_set_format(void *, int,
- const audio_params_t *, const audio_params_t *,
- audio_filter_reg_t *, audio_filter_reg_t *);
-static int azalia_round_blocksize(void *, int, int, const audio_params_t *);
-static int azalia_halt_output(void *);
-static int azalia_halt_input(void *);
-static int azalia_getdev(void *, struct audio_device *);
-static int azalia_set_port(void *, mixer_ctrl_t *);
-static int azalia_get_port(void *, mixer_ctrl_t *);
-static int azalia_query_devinfo(void *, mixer_devinfo_t *);
-static void *azalia_allocm(void *, int, size_t);
-static void azalia_freem(void *, void *, size_t);
-static size_t azalia_round_buffersize(void *, int, size_t);
-static int azalia_get_props(void *);
-static int azalia_trigger_output(void *, void *, void *, int,
- void (*)(void *), void *, const audio_params_t *);
-static int azalia_trigger_input(void *, void *, void *, int,
- void (*)(void *), void *, const audio_params_t *);
-static void azalia_get_locks(void *, kmutex_t **, kmutex_t **);
-
-static int azalia_params2fmt(const audio_params_t *, uint16_t *);
-
-/* variables */
-CFATTACH_DECL2_NEW(azalia, sizeof(azalia_t),
- azalia_pci_match, azalia_pci_attach, azalia_pci_detach, NULL,
- NULL, azalia_childdet);
-
-static const struct audio_hw_if azalia_hw_if = {
- .open = azalia_open,
- .close = azalia_close,
- .query_format = azalia_query_format,
- .set_format = azalia_set_format,
- .round_blocksize = azalia_round_blocksize,
- .halt_output = azalia_halt_output,
- .halt_input = azalia_halt_input,
- .getdev = azalia_getdev,
- .set_port = azalia_set_port,
- .get_port = azalia_get_port,
- .query_devinfo = azalia_query_devinfo,
- .allocm = azalia_allocm,
- .freem = azalia_freem,
- .round_buffersize = azalia_round_buffersize,
- .get_props = azalia_get_props,
- .trigger_output = azalia_trigger_output,
- .trigger_input = azalia_trigger_input,
- .get_locks = azalia_get_locks,
-};
-
-static const char *pin_colors[16] = {
- "unknown", "black", "gray", "blue",
- "green", "red", "orange", "yellow",
- "purple", "pink", "col0a", "col0b",
- "col0c", "col0d", "white", "other"
-};
-
-#ifdef AZALIA_DEBUG
-static const char *pin_devices[16] = {
- "line-out", AudioNspeaker, AudioNheadphone, AudioNcd,
- "SPDIF-out", "digital-out", "modem-line", "modem-handset",
- "line-in", AudioNaux, AudioNmicrophone, "telephony",
- "SPDIF-in", "digital-in", "dev0e", "other"
-};
-#endif
-
-/* ================================================================
- * PCI functions
- * ================================================================ */
-
-static int
-azalia_pci_match(device_t parent, cfdata_t match, void *aux)
-{
- struct pci_attach_args *pa;
-
- pa = aux;
- if (PCI_CLASS(pa->pa_class) == PCI_CLASS_MULTIMEDIA
- && PCI_SUBCLASS(pa->pa_class) == PCI_SUBCLASS_MULTIMEDIA_HDAUDIO)
- return 1;
- return 0;
-}
-
-static void
-azalia_pci_attach(device_t parent, device_t self, void *aux)
-{
- azalia_t *sc = device_private(self);
- struct pci_attach_args *pa = aux;
- pcireg_t v;
- pci_intr_handle_t ih;
- const char *intrrupt_str;
- char vendor[PCI_VENDORSTR_LEN];
- char product[PCI_PRODUCTSTR_LEN];
- char intrbuf[PCI_INTRSTR_LEN];
-
- sc->dev = self;
- sc->dmat = pa->pa_dmat;
-
- aprint_normal(": Generic High Definition Audio Controller\n");
-
- v = pci_conf_read(pa->pa_pc, pa->pa_tag, ICH_PCI_HDBARL);
- v &= PCI_MAPREG_TYPE_MASK | PCI_MAPREG_MEM_TYPE_MASK;
- if (pci_mapreg_map(pa, ICH_PCI_HDBARL, v, 0,
- &sc->iot, &sc->ioh, NULL, &sc->map_size)) {
- aprint_error_dev(self, "can't map device i/o space\n");
- return;
- }
-
- /* enable bus mastering */
- v = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG);
- pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG,
- v | PCI_COMMAND_MASTER_ENABLE | PCI_COMMAND_BACKTOBACK_ENABLE);
-
- /* interrupt */
- if (pci_intr_map(pa, &ih)) {
- aprint_error_dev(self, "can't map interrupt\n");
- return;
- }
-
- mutex_init(&sc->lock, MUTEX_DEFAULT, IPL_NONE);
- mutex_init(&sc->intr_lock, MUTEX_DEFAULT, IPL_AUDIO);
-
- sc->pc = pa->pa_pc;
- sc->tag = pa->pa_tag;
- intrrupt_str = pci_intr_string(pa->pa_pc, ih, intrbuf, sizeof(intrbuf));
- sc->ih = pci_intr_establish_xname(pa->pa_pc, ih, IPL_AUDIO, azalia_intr,
- sc, device_xname(self));
- if (sc->ih == NULL) {
- aprint_error_dev(self, "can't establish interrupt");
- if (intrrupt_str != NULL)
- aprint_error(" at %s", intrrupt_str);
- aprint_error("\n");
- mutex_destroy(&sc->lock);
- mutex_destroy(&sc->intr_lock);
- return;
- }
- aprint_normal_dev(self, "interrupting at %s\n", intrrupt_str);
-
- if (!pmf_device_register(self, NULL, azalia_pci_resume))
- aprint_error_dev(self, "couldn't establish power handler\n");
-
- sc->pciid = pa->pa_id;
- pci_findvendor(vendor, sizeof(vendor), PCI_VENDOR(pa->pa_id));
- pci_findproduct(product, sizeof(product), PCI_VENDOR(pa->pa_id),
- PCI_PRODUCT(pa->pa_id));
- aprint_normal_dev(self, "host: %s %s (rev. %d)",
- vendor, product, PCI_REVISION(pa->pa_class));
-
- if (azalia_attach(sc)) {
- aprint_error_dev(self, "initialization failure\n");
- azalia_pci_detach(self, 0);
- mutex_destroy(&sc->lock);
- mutex_destroy(&sc->intr_lock);
- return;
- }
- sc->subid = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_SUBSYS_ID_REG);
-
- config_interrupts(self, azalia_attach_intr);
-}
-
-static void
-azalia_childdet(device_t self, device_t child)
-{
- azalia_t *az = device_private(self);
-
- KASSERT(az->audiodev == child);
- az->audiodev = NULL;
-}
-
-static int
-azalia_pci_detach(device_t self, int flags)
-{
- azalia_t *az;
- int i;
-
- DPRINTF(("%s\n", __func__));
- az = device_private(self);
- if (az->audiodev != NULL)
- config_detach(az->audiodev, flags);
-
- mutex_enter(&az->lock);
-
-#if notyet
- DPRINTF(("%s: halt streams\n", __func__));
- azalia_stream_halt(&az->rstream);
- azalia_stream_halt(&az->pstream);
-#endif
-
-
- DPRINTF(("%s: delete streams\n", __func__));
- azalia_stream_delete(&az->rstream, az);
- azalia_stream_delete(&az->pstream, az);
-
- DPRINTF(("%s: delete codecs\n", __func__));
- for (i = 0; i < az->ncodecs; i++) {
- azalia_codec_delete(&az->codecs[i]);
- }
- az->ncodecs = 0;
-
- DPRINTF(("%s: delete CORB and RIRB\n", __func__));
- azalia_delete_corb(az);
- azalia_delete_rirb(az);
-
- mutex_exit(&az->lock);
- mutex_destroy(&az->lock);
- mutex_destroy(&az->intr_lock);
-
- DPRINTF(("%s: delete PCI resources\n", __func__));
- if (az->ih != NULL) {
- pci_intr_disestablish(az->pc, az->ih);
- az->ih = NULL;
- }
- if (az->map_size != 0) {
- bus_space_unmap(az->iot, az->ioh, az->map_size);
- az->map_size = 0;
- }
- return 0;
-}
-
-static bool
-azalia_pci_resume(device_t dv, const pmf_qual_t *qual)
-{
- azalia_t *az = device_private(dv);
-
- mutex_enter(&az->lock);
- mutex_spin_enter(&az->intr_lock);
- azalia_attach(az);
- azalia_attach_intr(az->dev);
- mutex_spin_exit(&az->intr_lock);
- mutex_exit(&az->lock);
-
- return true;
-}
-
-static int
-azalia_intr(void *v)
-{
- azalia_t *az;
- int ret;
- uint32_t intsts;
- uint8_t rirbsts;
-
- az = v;
-
- if (!device_has_power(az->dev))
- return 0;
-
- mutex_spin_enter(&az->intr_lock);
-
- intsts = AZ_READ_4(az, INTSTS);
- if (intsts == 0) {
- mutex_spin_exit(&az->intr_lock);
- return 0;
- }
-
- ret = azalia_stream_intr(&az->pstream, intsts) +
- azalia_stream_intr(&az->rstream, intsts);
-
- rirbsts = AZ_READ_1(az, RIRBSTS);
- if (rirbsts & (HDA_RIRBSTS_RIRBOIS | HDA_RIRBSTS_RINTFL)) {
- if (rirbsts & HDA_RIRBSTS_RINTFL) {
- azalia_rirb_intr(az);
- } else {
- /*printf("[Overflow!]");*/
- }
- AZ_WRITE_1(az, RIRBSTS,
- rirbsts | HDA_RIRBSTS_RIRBOIS | HDA_RIRBSTS_RINTFL);
- ret++;
- }
-
- mutex_spin_exit(&az->intr_lock);
- return ret;
-}
-
-/* ================================================================
- * HDA controller functions
- * ================================================================ */
-
-static int
-azalia_attach(azalia_t *az)
-{
- int i, n;
- uint32_t gctl;
- uint16_t gcap;
- uint16_t statests;
-
- if (az->audiodev == NULL)
- aprint_normal(", HDA rev. %d.%d\n",
- AZ_READ_1(az, VMAJ), AZ_READ_1(az, VMIN));
-
- gcap = AZ_READ_2(az, GCAP);
- az->nistreams = HDA_GCAP_ISS(gcap);
- az->nostreams = HDA_GCAP_OSS(gcap);
- az->nbstreams = HDA_GCAP_BSS(gcap);
- az->ok64 = (gcap & HDA_GCAP_64OK) != 0;
- DPRINTF(("%s: host: %d output, %d input, and %d bidi streams\n",
- device_xname(az->dev), az->nostreams, az->nistreams, az->nbstreams));
- if (az->nistreams > 0)
- az->mode_cap |= AUMODE_RECORD;
- if (az->nostreams > 0)
- az->mode_cap |= AUMODE_PLAY;
-
- /* 4.2.2 Starting the High Definition Audio Controller */
- DPRINTF(("%s: resetting\n", __func__));
- gctl = AZ_READ_4(az, GCTL);
- AZ_WRITE_4(az, GCTL, gctl & ~HDA_GCTL_CRST);
- for (i = 5000; i >= 0; i--) {
- DELAY(10);
- if ((AZ_READ_4(az, GCTL) & HDA_GCTL_CRST) == 0)
- break;
- }
- DPRINTF(("%s: reset counter = %d\n", __func__, i));
- if (i <= 0) {
- aprint_error_dev(az->dev, "reset failure\n");
- return ETIMEDOUT;
- }
- DELAY(1000);
- gctl = AZ_READ_4(az, GCTL);
- AZ_WRITE_4(az, GCTL, gctl | HDA_GCTL_CRST);
- for (i = 5000; i >= 0; i--) {
- DELAY(10);
- if (AZ_READ_4(az, GCTL) & HDA_GCTL_CRST)
- break;
- }
- DPRINTF(("%s: reset counter = %d\n", __func__, i));
- if (i <= 0) {
- aprint_error_dev(az->dev, "reset-exit failure\n");
- return ETIMEDOUT;
- }
-
- /* enable unsolicited response */
- gctl = AZ_READ_4(az, GCTL);
- AZ_WRITE_4(az, GCTL, gctl | HDA_GCTL_UNSOL);
-
- /* 4.3 Codec discovery */
- DELAY(1000);
- statests = AZ_READ_2(az, STATESTS);
- for (i = 0, n = 0; i < 15; i++) {
- if ((statests >> i) & 1) {
- DPRINTF(("%s: found a codec at #%d\n",
- device_xname(az->dev), i));
- az->codecs[n].address = i;
- az->codecs[n++].dev = az->dev;
- }
- }
- az->ncodecs = n;
- if (az->ncodecs < 1) {
- aprint_error_dev(az->dev, "No HD-Audio codecs\n");
- return -1;
- }
- return 0;
-}
-
-static void
-azalia_attach_intr(device_t self)
-{
- azalia_t *az;
- int err, i, c, reinit;
-
- az = device_private(self);
- reinit = az->audiodev == NULL ? 0 : 1;
-
- AZ_WRITE_2(az, STATESTS, HDA_STATESTS_SDIWAKE);
- AZ_WRITE_1(az, RIRBSTS, HDA_RIRBSTS_RINTFL | HDA_RIRBSTS_RIRBOIS);
- AZ_WRITE_4(az, INTSTS, HDA_INTSTS_CIS | HDA_INTSTS_GIS);
- AZ_WRITE_4(az, DPLBASE, 0);
- AZ_WRITE_4(az, DPUBASE, 0);
-
- /* 4.4.1 Command Outbound Ring Buffer */
- if (azalia_init_corb(az, reinit))
- goto err_exit;
- /* 4.4.2 Response Inbound Ring Buffer */
- if (azalia_init_rirb(az, reinit))
- goto err_exit;
-
- AZ_WRITE_4(az, INTCTL,
- AZ_READ_4(az, INTCTL) | HDA_INTCTL_CIE | HDA_INTCTL_GIE);
-
- c = -1;
- for (i = 0; i < az->ncodecs; i++) {
- err = azalia_codec_init(&az->codecs[i], reinit, az->subid);
- if (!err && c < 0)
- c = i;
- }
- if (c < 0)
- goto err_exit;
- /* Use the first audio codec */
- az->codecno = c;
- DPRINTF(("%s: using the #%d codec\n",
- device_xname(az->dev), az->codecno));
- if (az->codecs[c].dacs.ngroups <= 0)
- az->mode_cap &= ~AUMODE_PLAY;
- if (az->codecs[c].adcs.ngroups <= 0)
- az->mode_cap &= ~AUMODE_RECORD;
-
- /* Use stream#1 and #2. Don't use stream#0. */
- if (reinit == 0) {
- if (azalia_stream_init(&az->pstream, az, az->nistreams + 0,
- 1, AUMODE_PLAY))
- goto err_exit;
- if (azalia_stream_init(&az->rstream, az, 0, 2, AUMODE_RECORD))
- goto err_exit;
-
- az->audiodev = audio_attach_mi(&azalia_hw_if, az, az->dev);
- }
- return;
-err_exit:
- azalia_pci_detach(self, 0);
- return;
-}
-
-static int
-azalia_init_corb(azalia_t *az, int reinit)
-{
- int entries, err, i;
- uint16_t corbrp, corbwp;
- uint8_t corbsize, cap, corbctl;
-
- /* stop the CORB */
- corbctl = AZ_READ_1(az, CORBCTL);
- if (corbctl & HDA_CORBCTL_CORBRUN) { /* running? */
- AZ_WRITE_1(az, CORBCTL, corbctl & ~HDA_CORBCTL_CORBRUN);
- for (i = 5000; i >= 0; i--) {
- DELAY(10);
- corbctl = AZ_READ_1(az, CORBCTL);
- if ((corbctl & HDA_CORBCTL_CORBRUN) == 0)
- break;
- }
- if (i <= 0) {
- aprint_error_dev(az->dev, "CORB is running\n");
- return EBUSY;
- }
- }
-
- /* determine CORB size */
- corbsize = AZ_READ_1(az, CORBSIZE);
- cap = corbsize & HDA_CORBSIZE_CORBSZCAP_MASK;
- corbsize &= ~HDA_CORBSIZE_CORBSIZE_MASK;
- if (cap & HDA_CORBSIZE_CORBSZCAP_256) {
- entries = 256;
- corbsize |= HDA_CORBSIZE_CORBSIZE_256;
- } else if (cap & HDA_CORBSIZE_CORBSZCAP_16) {
- entries = 16;
- corbsize |= HDA_CORBSIZE_CORBSIZE_16;
- } else if (cap & HDA_CORBSIZE_CORBSZCAP_2) {
- entries = 2;
- corbsize |= HDA_CORBSIZE_CORBSIZE_2;
- } else {
- aprint_error_dev(az->dev, "Invalid CORBSZCAP: 0x%2x\n", cap);
- return -1;
- }
-
- if (reinit == 0) {
- err = azalia_alloc_dmamem(az, entries * sizeof(corb_entry_t),
- 128, &az->corb_dma);
- if (err) {
- aprint_error_dev(az->dev, "can't allocate CORB buffer\n");
- return err;
- }
- }
- AZ_WRITE_4(az, CORBLBASE, (uint32_t)AZALIA_DMA_DMAADDR(&az->corb_dma));
- AZ_WRITE_4(az, CORBUBASE, PTR_UPPER32(AZALIA_DMA_DMAADDR(&az->corb_dma)));
- AZ_WRITE_1(az, CORBSIZE, corbsize);
- az->corb_size = entries;
-
- DPRINTF(("%s: CORB allocation succeeded.\n", __func__));
-
- /* reset CORBRP */
- corbrp = AZ_READ_2(az, CORBRP);
- AZ_WRITE_2(az, CORBRP, corbrp | HDA_CORBRP_CORBRPRST);
- AZ_WRITE_2(az, CORBRP, corbrp & ~HDA_CORBRP_CORBRPRST);
- for (i = 5000; i >= 0; i--) {
- DELAY(10);
- corbrp = AZ_READ_2(az, CORBRP);
- if ((corbrp & HDA_CORBRP_CORBRPRST) == 0)
- break;
- }
- if (i <= 0) {
- aprint_error_dev(az->dev, "CORBRP reset failure\n");
- return -1;
- }
- DPRINTF(("%s: CORBWP=%d; size=%d\n", __func__,
- AZ_READ_2(az, CORBRP) & HDA_CORBRP_CORBRP, az->corb_size));
-
- /* clear CORBWP */
- corbwp = AZ_READ_2(az, CORBWP);
- AZ_WRITE_2(az, CORBWP, corbwp & ~HDA_CORBWP_CORBWP);
-
- /* Run! */
- corbctl = AZ_READ_1(az, CORBCTL);
- AZ_WRITE_1(az, CORBCTL, corbctl | HDA_CORBCTL_CORBRUN);
- return 0;
-}
-
-static int
-azalia_delete_corb(azalia_t *az)
-{
- int i;
- uint8_t corbctl;
-
- if (az->corb_dma.addr == NULL)
- return 0;
- /* stop the CORB */
- corbctl = AZ_READ_1(az, CORBCTL);
- AZ_WRITE_1(az, CORBCTL, corbctl & ~HDA_CORBCTL_CORBRUN);
- for (i = 5000; i >= 0; i--) {
- DELAY(10);
- corbctl = AZ_READ_1(az, CORBCTL);
- if ((corbctl & HDA_CORBCTL_CORBRUN) == 0)
- break;
- }
- azalia_free_dmamem(az, &az->corb_dma);
- return 0;
-}
-
-static int
-azalia_init_rirb(azalia_t *az, int reinit)
-{
- int entries, err, i;
- uint16_t rirbwp;
- uint8_t rirbsize, cap, rirbctl;
-
- /* stop the RIRB */
- rirbctl = AZ_READ_1(az, RIRBCTL);
- if (rirbctl & HDA_RIRBCTL_RIRBDMAEN) { /* running? */
- AZ_WRITE_1(az, RIRBCTL, rirbctl & ~HDA_RIRBCTL_RIRBDMAEN);
- for (i = 5000; i >= 0; i--) {
- DELAY(10);
- rirbctl = AZ_READ_1(az, RIRBCTL);
- if ((rirbctl & HDA_RIRBCTL_RIRBDMAEN) == 0)
- break;
- }
- if (i <= 0) {
- aprint_error_dev(az->dev, "RIRB is running\n");
- return EBUSY;
- }
- }
-
- /* determine RIRB size */
- rirbsize = AZ_READ_1(az, RIRBSIZE);
- cap = rirbsize & HDA_RIRBSIZE_RIRBSZCAP_MASK;
- rirbsize &= ~HDA_RIRBSIZE_RIRBSIZE_MASK;
- if (cap & HDA_RIRBSIZE_RIRBSZCAP_256) {
- entries = 256;
- rirbsize |= HDA_RIRBSIZE_RIRBSIZE_256;
- } else if (cap & HDA_RIRBSIZE_RIRBSZCAP_16) {
- entries = 16;
- rirbsize |= HDA_RIRBSIZE_RIRBSIZE_16;
- } else if (cap & HDA_RIRBSIZE_RIRBSZCAP_2) {
- entries = 2;
- rirbsize |= HDA_RIRBSIZE_RIRBSIZE_2;
- } else {
- aprint_error_dev(az->dev, "Invalid RIRBSZCAP: 0x%2x\n", cap);
- return -1;
- }
-
- if (reinit == 0) {
- err = azalia_alloc_dmamem(az, entries * sizeof(rirb_entry_t),
- 128, &az->rirb_dma);
- if (err) {
- aprint_error_dev(az->dev, "can't allocate RIRB buffer\n");
- return err;
- }
- }
- AZ_WRITE_4(az, RIRBLBASE, (uint32_t)AZALIA_DMA_DMAADDR(&az->rirb_dma));
- AZ_WRITE_4(az, RIRBUBASE, PTR_UPPER32(AZALIA_DMA_DMAADDR(&az->rirb_dma)));
- AZ_WRITE_1(az, RIRBSIZE, rirbsize);
- az->rirb_size = entries;
-
- DPRINTF(("%s: RIRB allocation succeeded.\n", __func__));
-
- /* setup the unsolicited response queue */
- az->unsolq_rp = 0;
- az->unsolq_wp = 0;
- az->unsolq_kick = FALSE;
- if (reinit == 0) {
- az->unsolq = kmem_zalloc(sizeof(rirb_entry_t) * UNSOLQ_SIZE,
- KM_SLEEP);
- } else {
- memset(az->unsolq, 0, sizeof(rirb_entry_t) * UNSOLQ_SIZE);
- }
- if (az->unsolq == NULL) {
- aprint_error_dev(az->dev, "can't allocate unsolicited response queue.\n");
- azalia_free_dmamem(az, &az->rirb_dma);
- return ENOMEM;
- }
-
-#if notyet
- rirbctl = AZ_READ_1(az, RIRBCTL);
- AZ_WRITE_1(az, RIRBCTL, rirbctl & ~HDA_RIRBCTL_RINTCTL);
-#endif
-
- /* reset the write pointer */
- rirbwp = AZ_READ_2(az, RIRBWP);
- AZ_WRITE_2(az, RIRBWP, rirbwp | HDA_RIRBWP_RIRBWPRST);
-
- /* clear the read pointer */
- az->rirb_rp = AZ_READ_2(az, RIRBWP) & HDA_RIRBWP_RIRBWP;
- DPRINTF(("%s: RIRBRP=%d, size=%d\n", __func__, az->rirb_rp, az->rirb_size));
-
- AZ_WRITE_2(az, RINTCNT, 1);
-
- /* Run! */
- rirbctl = AZ_READ_1(az, RIRBCTL);
- AZ_WRITE_1(az, RIRBCTL, rirbctl | HDA_RIRBCTL_RIRBDMAEN | HDA_RIRBCTL_RINTCTL);
- for (i = 5000; i >= 0; i--) {
- DELAY(10);
- rirbctl = AZ_READ_1(az, RIRBCTL);
- if (rirbctl & HDA_RIRBCTL_RIRBDMAEN)
- break;
- }
- if (i <= 0) {
- aprint_error_dev(az->dev, "RIRB is not running\n");
- return EBUSY;
- }
-
- return 0;
-}
-
-static int
-azalia_delete_rirb(azalia_t *az)
-{
- int i;
- uint8_t rirbctl;
-
- if (az->unsolq != NULL) {
- kmem_free(az->unsolq, UNSOLQ_SIZE);
- az->unsolq = NULL;
- }
- if (az->rirb_dma.addr == NULL)
- return 0;
- /* stop the RIRB */
- rirbctl = AZ_READ_1(az, RIRBCTL);
- AZ_WRITE_1(az, RIRBCTL, rirbctl & ~HDA_RIRBCTL_RIRBDMAEN);
- for (i = 5000; i >= 0; i--) {
- DELAY(10);
- rirbctl = AZ_READ_1(az, RIRBCTL);
- if ((rirbctl & HDA_RIRBCTL_RIRBDMAEN) == 0)
- break;
- }
- azalia_free_dmamem(az, &az->rirb_dma);
- return 0;
-}
-
-static int
-azalia_set_command(const azalia_t *az, int caddr, nid_t nid, uint32_t control,
- uint32_t param)
-{
- corb_entry_t *corb;
- int wp;
- uint32_t verb;
- uint16_t corbwp;
-
-#ifdef DIAGNOSTIC
- if ((AZ_READ_1(az, CORBCTL) & HDA_CORBCTL_CORBRUN) == 0) {
- aprint_error_dev(az->dev, "CORB is not running.\n");
- return -1;
- }
-#endif
- verb = (caddr << 28) | (nid << 20) | (control << 8) | param;
- corbwp = AZ_READ_2(az, CORBWP);
- wp = corbwp & HDA_CORBWP_CORBWP;
- corb = (corb_entry_t*)az->corb_dma.addr;
- if (++wp >= az->corb_size)
- wp = 0;
- corb[wp] = verb;
- AZ_WRITE_2(az, CORBWP, (corbwp & ~HDA_CORBWP_CORBWP) | wp);
-#if 0
- DPRINTF(("%s: caddr=%d nid=%d control=0x%x param=0x%x verb=0x%8.8x wp=%d\n",
- __func__, caddr, nid, control, param, verb, wp));
-#endif
- return 0;
-}
-
-static int
-azalia_get_response(azalia_t *az, uint32_t *result)
-{
- const rirb_entry_t *rirb;
- int i;
- uint16_t wp;
-
-#ifdef DIAGNOSTIC
- if ((AZ_READ_1(az, RIRBCTL) & HDA_RIRBCTL_RIRBDMAEN) == 0) {
- aprint_error_dev(az->dev, "RIRB is not running.\n");
- return -1;
- }
-#endif
- for (i = 5000; i >= 0; i--) {
- wp = AZ_READ_2(az, RIRBWP) & HDA_RIRBWP_RIRBWP;
- if (az->rirb_rp != wp)
- break;
- DELAY(10);
- }
- if (i <= 0) {
- aprint_error_dev(az->dev, "RIRB time out\n");
- return ETIMEDOUT;
- }
- rirb = (rirb_entry_t*)az->rirb_dma.addr;
- for (;;) {
- if (++az->rirb_rp >= az->rirb_size)
- az->rirb_rp = 0;
- if (rirb[az->rirb_rp].resp_ex & RIRB_RESP_UNSOL) {
- az->unsolq[az->unsolq_wp].resp = rirb[az->rirb_rp].resp;
- az->unsolq[az->unsolq_wp++].resp_ex = rirb[az->rirb_rp].resp_ex;
- az->unsolq_wp %= UNSOLQ_SIZE;
- } else
- break;
- }
- if (result != NULL)
- *result = rirb[az->rirb_rp].resp;
- azalia_rirb_kick_unsol_events(az);
-#if 0
- DPRINTF(("%s: rirbwp=%d rp=%d resp1=0x%8.8x resp2=0x%8.8x\n",
- __func__, wp, az->rirb_rp, rirb[az->rirb_rp].resp,
- rirb[az->rirb_rp].resp_ex));
- for (i = 0; i < 16 /*az->rirb_size*/; i++) {
- DPRINTF(("rirb[%d] 0x%8.8x:0x%8.8x ", i, rirb[i].resp, rirb[i].resp_ex));
- if ((i % 2) == 1)
- DPRINTF(("\n"));
- }
-#endif
- return 0;
-}
-
-static void
-azalia_rirb_kick_unsol_events(azalia_t *az)
-{
- if (az->unsolq_kick)
- return;
- az->unsolq_kick = TRUE;
- while (az->unsolq_rp != az->unsolq_wp) {
- int i;
- int tag;
- codec_t *codec;
- i = RIRB_RESP_CODEC(az->unsolq[az->unsolq_rp].resp_ex);
- tag = RIRB_UNSOL_TAG(az->unsolq[az->unsolq_rp].resp);
- codec = &az->codecs[i];
- DPRINTF(("%s: codec#=%d tag=%d\n", __func__, i, tag));
- az->unsolq_rp++;
- az->unsolq_rp %= UNSOLQ_SIZE;
- if (codec->unsol_event != NULL)
- codec->unsol_event(codec, tag);
- }
- az->unsolq_kick = FALSE;
-}
-
-static void
-azalia_rirb_intr(azalia_t *az)
-{
- const rirb_entry_t *rirb;
- uint16_t wp, newrp;
-
- wp = AZ_READ_2(az, RIRBWP) & HDA_RIRBWP_RIRBWP;
- if (az->rirb_rp == wp)
- return; /* interrupted but no data in RIRB */
- /* Copy the first sequence of unsolicited reponses in the RIRB to
- * unsolq. Don't consume non-unsolicited responses. */
- rirb = (rirb_entry_t*)az->rirb_dma.addr;
- while (az->rirb_rp != wp) {
- newrp = az->rirb_rp + 1;
- if (newrp >= az->rirb_size)
- newrp = 0;
- if (rirb[newrp].resp_ex & RIRB_RESP_UNSOL) {
- az->unsolq[az->unsolq_wp].resp = rirb[newrp].resp;
- az->unsolq[az->unsolq_wp++].resp_ex = rirb[newrp].resp_ex;
- az->unsolq_wp %= UNSOLQ_SIZE;
- az->rirb_rp = newrp;
- } else {
- break;
- }
- }
- azalia_rirb_kick_unsol_events(az);
-}
-
-static int
-azalia_alloc_dmamem(azalia_t *az, size_t size, size_t align, azalia_dma_t *d)
-{
- int err;
- int nsegs;
-
- d->size = size;
- err = bus_dmamem_alloc(az->dmat, size, align, 0, d->segments, 1,
- &nsegs, BUS_DMA_WAITOK);
- if (err)
- return err;
- if (nsegs != 1)
- goto free;
- err = bus_dmamem_map(az->dmat, d->segments, 1, size,
- &d->addr, BUS_DMA_WAITOK | BUS_DMA_COHERENT | BUS_DMA_NOCACHE);
- if (err)
- goto free;
- err = bus_dmamap_create(az->dmat, size, 1, size, 0,
- BUS_DMA_WAITOK, &d->map);
- if (err)
- goto unmap;
- err = bus_dmamap_load(az->dmat, d->map, d->addr, size,
- NULL, BUS_DMA_WAITOK);
- if (err)
- goto destroy;
-
- if (!az->ok64 && PTR_UPPER32(AZALIA_DMA_DMAADDR(d)) != 0) {
- azalia_free_dmamem(az, d);
- return -1;
- }
- return 0;
-
-destroy:
- bus_dmamap_destroy(az->dmat, d->map);
-unmap:
- bus_dmamem_unmap(az->dmat, d->addr, size);
-free:
- bus_dmamem_free(az->dmat, d->segments, 1);
- d->addr = NULL;
- return err;
-}
-
-static int
-azalia_free_dmamem(const azalia_t *az, azalia_dma_t* d)
-{
- if (d->addr == NULL)
- return 0;
- bus_dmamap_unload(az->dmat, d->map);
- bus_dmamap_destroy(az->dmat, d->map);
- bus_dmamem_unmap(az->dmat, d->addr, d->size);
- bus_dmamem_free(az->dmat, d->segments, 1);
- d->addr = NULL;
- return 0;
-}
-
-/* ================================================================
- * HDA coodec functions
- * ================================================================ */
-
-static int
-azalia_codec_init(codec_t *this, int reinit, uint32_t subid)
-{
-#define LEAD_LEN 100
- char lead[LEAD_LEN];
- uint32_t rev, id, result;
- int err, addr, n, i;
-
- this->comresp = azalia_codec_comresp;
- addr = this->address;
- DPRINTF(("%s: information of codec[%d] follows:\n",
- device_xname(this->dev), addr));
- /* codec vendor/device/revision */
- err = this->comresp(this, CORB_NID_ROOT, CORB_GET_PARAMETER,
- COP_REVISION_ID, &rev);
- if (err)
- return err;
- err = this->comresp(this, CORB_NID_ROOT, CORB_GET_PARAMETER,
- COP_VENDOR_ID, &id);
- if (err)
- return err;
- this->vid = id;
- this->subid = subid;
-
- if (!reinit) {
- err = azalia_codec_init_vtbl(this);
- if (err)
- return err;
- }
-
- if (!reinit) {
- aprint_normal("%s: codec[%d]: ", device_xname(this->dev), addr);
- if (this->name == NULL) {
- aprint_normal("0x%4.4x/0x%4.4x (rev. %u.%u)",
- id >> 16, id & 0xffff,
- COP_RID_REVISION(rev), COP_RID_STEPPING(rev));
- } else {
- aprint_normal("%s (rev. %u.%u)", this->name,
- COP_RID_REVISION(rev), COP_RID_STEPPING(rev));
- }
- aprint_normal(", HDA rev. %u.%u\n",
- COP_RID_MAJ(rev), COP_RID_MIN(rev));
- }
-
- /* identify function nodes */
- err = this->comresp(this, CORB_NID_ROOT, CORB_GET_PARAMETER,
- COP_SUBORDINATE_NODE_COUNT, &result);
- if (err)
- return err;
- this->nfunctions = COP_NSUBNODES(result);
- if (COP_NSUBNODES(result) <= 0) {
- aprint_error("%s: No function groups\n",
- device_xname(this->dev));
- return -1;
- }
- /* iterate function nodes and find an audio function */
- n = COP_START_NID(result);
- DPRINTF(("%s: nidstart=%d #functions=%d\n",
- __func__, n, this->nfunctions));
- this->audiofunc = -1;
- for (i = 0; i < this->nfunctions; i++) {
- err = this->comresp(this, n + i, CORB_GET_PARAMETER,
- COP_FUNCTION_GROUP_TYPE, &result);
- if (err)
- continue;
- DPRINTF(("%s: FTYPE result = 0x%8.8x\n", __func__, result));
- if (COP_FTYPE(result) == COP_FTYPE_AUDIO) {
- this->audiofunc = n + i;
- break; /* XXX multiple audio functions? */
- } else if (COP_FTYPE(result) == COP_FTYPE_MODEM && !reinit) {
- aprint_normal("%s: codec[%d]: No support for modem "
- "function groups\n",
- device_xname(this->dev), addr);
- }
- }
- if (this->audiofunc < 0 && !reinit) {
- aprint_verbose("%s: codec[%d] has no audio function groups\n",
- device_xname(this->dev), addr);
- return -1;
- }
-
- /* power the audio function */
- this->comresp(this, this->audiofunc, CORB_SET_POWER_STATE, CORB_PS_D0, &result);
- DELAY(100);
-
- /* check widgets in the audio function */
- err = this->comresp(this, this->audiofunc,
- CORB_GET_PARAMETER, COP_SUBORDINATE_NODE_COUNT, &result);
- if (err)
- return err;
- DPRINTF(("%s: There are %d widgets in the audio function.\n",
- __func__, COP_NSUBNODES(result)));
- this->wstart = COP_START_NID(result);
- if (this->wstart < 2) {
- if (!reinit)
- aprint_error("%s: invalid node structure\n",
- device_xname(this->dev));
- return -1;
- }
- this->wend = this->wstart + COP_NSUBNODES(result);
- if (!reinit) {
- this->w = kmem_zalloc(sizeof(widget_t) * this->wend,
- KM_SLEEP);
- if (this->w == NULL) {
- aprint_error("%s: out of memory\n",
- device_xname(this->dev));
- return ENOMEM;
- }
- } else
- memset(this->w, 0, sizeof(widget_t) * this->wend);
-
- /* query the base parameters */
- this->comresp(this, this->audiofunc, CORB_GET_PARAMETER,
- COP_STREAM_FORMATS, &result);
- this->w[this->audiofunc].d.audio.encodings = result;
- this->comresp(this, this->audiofunc, CORB_GET_PARAMETER,
- COP_PCM, &result);
- this->w[this->audiofunc].d.audio.bits_rates = result;
- this->comresp(this, this->audiofunc, CORB_GET_PARAMETER,
- COP_INPUT_AMPCAP, &result);
- this->w[this->audiofunc].inamp_cap = result;
- this->comresp(this, this->audiofunc, CORB_GET_PARAMETER,
- COP_OUTPUT_AMPCAP, &result);
- this->w[this->audiofunc].outamp_cap = result;
- lead[0] = 0;
-#ifdef AZALIA_DEBUG
- snprintf(lead, LEAD_LEN, "%s: ", device_xname(this->dev));
- azalia_widget_print_audio(&this->w[this->audiofunc], lead, -1);
- result = this->w[this->audiofunc].inamp_cap;
- DPRINTF(("%sinamp: mute=%u size=%u steps=%u offset=%u\n", lead,
- (result & COP_AMPCAP_MUTE) != 0, COP_AMPCAP_STEPSIZE(result),
- COP_AMPCAP_NUMSTEPS(result), COP_AMPCAP_OFFSET(result)));
- result = this->w[this->audiofunc].outamp_cap;
- DPRINTF(("%soutamp: mute=%u size=%u steps=%u offset=%u\n", lead,
- (result & COP_AMPCAP_MUTE) != 0, COP_AMPCAP_STEPSIZE(result),
- COP_AMPCAP_NUMSTEPS(result), COP_AMPCAP_OFFSET(result)));
-#endif
-
- strlcpy(this->w[CORB_NID_ROOT].name, "root",
- sizeof(this->w[CORB_NID_ROOT].name));
- strlcpy(this->w[this->audiofunc].name, "hdaudio",
- sizeof(this->w[this->audiofunc].name));
- FOR_EACH_WIDGET(this, i) {
- err = azalia_widget_init(&this->w[i], this, i, lead);
- if (err)
- return err;
- }
-#if defined(AZALIA_DEBUG) && defined(AZALIA_DEBUG_DOT)
- DPRINTF(("-------- Graphviz DOT starts\n"));
- if (this->name == NULL) {
- DPRINTF(("digraph \"0x%4.4x/0x%4.4x (rev. %u.%u)\" {\n",
- id >> 16, id & 0xffff,
- COP_RID_REVISION(rev), COP_RID_STEPPING(rev)));
- } else {
- DPRINTF(("digraph \"%s (rev. %u.%u)\" {\n", this->name,
- COP_RID_REVISION(rev), COP_RID_STEPPING(rev)));
- }
- FOR_EACH_WIDGET(this, i) {
- const widget_t *w;
- int j;
- w = &this->w[i];
- switch (w->type) {
- case COP_AWTYPE_AUDIO_OUTPUT:
- DPRINTF((" %s [shape=box,style=filled,fillcolor=\""
- "#88ff88\"];\n", w->name));
- break;
- case COP_AWTYPE_AUDIO_INPUT:
- DPRINTF((" %s [shape=box,style=filled,fillcolor=\""
- "#ff8888\"];\n", w->name));
- break;
- case COP_AWTYPE_AUDIO_MIXER:
- DPRINTF((" %s [shape=invhouse];\n", w->name));
- break;
- case COP_AWTYPE_AUDIO_SELECTOR:
- DPRINTF((" %s [shape=invtrapezium];\n", w->name));
- break;
- case COP_AWTYPE_PIN_COMPLEX:
- DPRINTF((" %s [label=\"%s\\ndevice=%s\",style=filled",
- w->name, w->name, pin_devices[w->d.pin.device]));
- if (w->d.pin.cap & COP_PINCAP_OUTPUT &&
- w->d.pin.cap & COP_PINCAP_INPUT)
- DPRINTF((",shape=doublecircle,fillcolor=\""
- "#ffff88\"];\n"));
- else if (w->d.pin.cap & COP_PINCAP_OUTPUT)
- DPRINTF((",shape=circle,fillcolor=\"#88ff88\"];\n"));
- else
- DPRINTF((",shape=circle,fillcolor=\"#ff8888\"];\n"));
- break;
- }
- if ((w->widgetcap & COP_AWCAP_CONNLIST) == 0)
- continue;
- for (j = 0; j < w->nconnections; j++) {
- int src = w->connections[j];
- if (!VALID_WIDGET_NID(src, this))
- continue;
- DPRINTF((" %s -> %s [sametail=%s];\n",
- this->w[src].name, w->name, this->w[src].name));
- }
- }
-
- DPRINTF((" {rank=min;"));
- FOR_EACH_WIDGET(this, i) {
- const widget_t *w;
- w = &this->w[i];
- switch (w->type) {
- case COP_AWTYPE_AUDIO_OUTPUT:
- case COP_AWTYPE_AUDIO_INPUT:
- DPRINTF((" %s;", w->name));
- break;
- }
- }
- DPRINTF(("}\n"));
-
- DPRINTF((" {rank=max;"));
- FOR_EACH_WIDGET(this, i) {
- const widget_t *w;
- w = &this->w[i];
- switch (w->type) {
- case COP_AWTYPE_PIN_COMPLEX:
- DPRINTF((" %s;", w->name));
- break;
- }
- }
- DPRINTF(("}\n"));
-
- DPRINTF(("}\n"));
- DPRINTF(("-------- Graphviz DOT ends\n"));
-#endif /* AZALIA_DEBUG && AZALIA_DEBUG_DOT */
-
- err = this->init_dacgroup(this);
- if (err)
- return err;
-#ifdef AZALIA_DEBUG
- for (i = 0; i < this->dacs.ngroups; i++) {
- DPRINTF(("%s: dacgroup[%d]:", __func__, i));
- for (n = 0; n < this->dacs.groups[i].nconv; n++) {
- DPRINTF((" %2.2x", this->dacs.groups[i].conv[n]));
- }
- DPRINTF(("\n"));
- }
-#endif
-
- /* set invalid values for azalia_codec_construct_format() to work */
- this->dacs.cur = -1;
- this->adcs.cur = -1;
- err = azalia_codec_construct_format(this,
- this->dacs.ngroups > 0 ? 0 : -1,
- this->adcs.ngroups > 0 ? 0 : -1);
- if (err)
- return err;
-
- return this->mixer_init(this);
-}
-
-static int
-azalia_codec_delete(codec_t *this)
-{
- if (this->mixer_delete != NULL)
- this->mixer_delete(this);
- if (this->formats != NULL) {
- kmem_free(this->formats, this->szformats);
- this->formats = NULL;
- }
- if (this->extra != NULL) {
- kmem_free(this->extra, this->szextra);
- this->extra = NULL;
- }
- return 0;
-}
-
-int
-azalia_codec_construct_format(codec_t *this, int newdac, int newadc)
-{
-#ifdef AZALIA_DEBUG
- char flagbuf[FLAGBUFLEN];
- int prev_dac = this->dacs.cur;
- int prev_adc = this->adcs.cur;
-#endif
- const convgroup_t *group;
- uint32_t bits_rates;
- int variation;
- int nbits, c, chan, i;
- nid_t nid;
-
- variation = 0;
- chan = 0;
-
- if (newdac >= 0 && newdac < this->dacs.ngroups) {
- this->dacs.cur = newdac;
- group = &this->dacs.groups[this->dacs.cur];
- bits_rates = this->w[group->conv[0]].d.audio.bits_rates;
- nbits = 0;
- if (bits_rates & COP_PCM_B8)
- nbits++;
- if (bits_rates & COP_PCM_B16)
- nbits++;
- if (bits_rates & COP_PCM_B20)
- nbits++;
- if (bits_rates & COP_PCM_B24)
- nbits++;
- if (bits_rates & COP_PCM_B32)
- nbits++;
- if (nbits == 0) {
- aprint_error("%s: invalid PCM format: 0x%8.8x\n",
- device_xname(this->dev), bits_rates);
- return -1;
- }
- variation = group->nconv * nbits;
- }
-
- if (newadc >= 0 && newadc < this->adcs.ngroups) {
- this->adcs.cur = newadc;
- group = &this->adcs.groups[this->adcs.cur];
- bits_rates = this->w[group->conv[0]].d.audio.bits_rates;
- nbits = 0;
- if (bits_rates & COP_PCM_B8)
- nbits++;
- if (bits_rates & COP_PCM_B16)
- nbits++;
- if (bits_rates & COP_PCM_B20)
- nbits++;
- if (bits_rates & COP_PCM_B24)
- nbits++;
- if (bits_rates & COP_PCM_B32)
- nbits++;
- if (nbits == 0) {
- aprint_error("%s: invalid PCM format: 0x%8.8x\n",
- device_xname(this->dev), bits_rates);
- return -1;
- }
- variation += group->nconv * nbits;
- }
-
- if (this->formats != NULL)
- kmem_free(this->formats, this->szformats);
- this->nformats = 0;
- this->szformats = sizeof(struct audio_format) * variation;
- this->formats = kmem_zalloc(this->szformats, KM_SLEEP);
-
- /* register formats for playback */
- if (this->dacs.cur >= 0 && this->dacs.cur < this->dacs.ngroups) {
- group = &this->dacs.groups[this->dacs.cur];
- for (c = 0; c < group->nconv; c++) {
- chan = 0;
- bits_rates = ~0;
- for (i = 0; i <= c; i++) {
- nid = group->conv[i];
- chan += WIDGET_CHANNELS(&this->w[nid]);
- bits_rates &= this->w[nid].d.audio.bits_rates;
- }
- azalia_codec_add_bits(this, chan,
- bits_rates, AUMODE_PLAY);
- }
-#ifdef AZALIA_DEBUG
- /* print playback capability */
- if (prev_dac != this->dacs.cur) {
- snprintf(flagbuf, FLAGBUFLEN, "%s: playback: ",
- device_xname(this->dev));
- azalia_widget_print_audio(&this->w[group->conv[0]],
- flagbuf, chan);
- }
-#endif
- }
-
- /* register formats for recording */
- if (this->adcs.cur >= 0 && this->adcs.cur < this->adcs.ngroups) {
- group = &this->adcs.groups[this->adcs.cur];
- for (c = 0; c < group->nconv; c++) {
- chan = 0;
- bits_rates = ~0;
- for (i = 0; i <= c; i++) {
- nid = group->conv[i];
- chan += WIDGET_CHANNELS(&this->w[nid]);
- bits_rates &= this->w[nid].d.audio.bits_rates;
- }
- azalia_codec_add_bits(this, chan,
- bits_rates, AUMODE_RECORD);
- }
-#ifdef AZALIA_DEBUG
- /* print recording capability */
- if (prev_adc != this->adcs.cur) {
- snprintf(flagbuf, FLAGBUFLEN, "%s: recording: ",
- device_xname(this->dev));
- azalia_widget_print_audio(&this->w[group->conv[0]],
- flagbuf, chan);
- }
-#endif
- }
-
-#ifdef DIAGNOSTIC
- if (this->nformats > variation) {
- aprint_error("%s: Internal error: the format buffer is too small: "
- "nformats=%d variation=%d\n", device_xname(this->dev),
- this->nformats, variation);
- return ENOMEM;
- }
-#endif
-
- return 0;
-}
-
-static void
-azalia_codec_add_bits(codec_t *this, int chan, uint32_t bits_rates, int mode)
-{
- if (bits_rates & COP_PCM_B8)
- azalia_codec_add_format(this, chan, 8, 16, bits_rates, mode);
- if (bits_rates & COP_PCM_B16)
- azalia_codec_add_format(this, chan, 16, 16, bits_rates, mode);
- if (bits_rates & COP_PCM_B20)
- azalia_codec_add_format(this, chan, 20, 32, bits_rates, mode);
- if (bits_rates & COP_PCM_B24)
- azalia_codec_add_format(this, chan, 24, 32, bits_rates, mode);
- if (bits_rates & COP_PCM_B32)
- azalia_codec_add_format(this, chan, 32, 32, bits_rates, mode);
-}
-
-static void
-azalia_codec_add_format(codec_t *this, int chan, int valid, int prec,
- uint32_t rates, int32_t mode)
-{
- struct audio_format *f;
-
- f = &this->formats[this->nformats++];
- f->mode = mode;
- f->encoding = AUDIO_ENCODING_SLINEAR_LE;
- if (valid == 8 && prec == 8)
- f->encoding = AUDIO_ENCODING_ULINEAR_LE;
- f->validbits = valid;
- f->precision = prec;
- f->channels = chan;
- switch (chan) {
- case 1:
- f->channel_mask = AUFMT_MONAURAL;
- break;
- case 2:
- f->channel_mask = AUFMT_STEREO;
- break;
- case 4:
- f->channel_mask = AUFMT_SURROUND4;
- break;
- case 6:
- f->channel_mask = AUFMT_DOLBY_5_1;
- break;
- case 8:
- f->channel_mask = AUFMT_DOLBY_5_1
- | AUFMT_SIDE_LEFT | AUFMT_SIDE_RIGHT;
- break;
- default:
- f->channel_mask = 0;
- }
- f->frequency_type = 0;
- if (rates & COP_PCM_R80)
- f->frequency[f->frequency_type++] = 8000;
- if (rates & COP_PCM_R110)
- f->frequency[f->frequency_type++] = 11025;
- if (rates & COP_PCM_R160)
- f->frequency[f->frequency_type++] = 16000;
- if (rates & COP_PCM_R220)
- f->frequency[f->frequency_type++] = 22050;
- if (rates & COP_PCM_R320)
- f->frequency[f->frequency_type++] = 32000;
- if (rates & COP_PCM_R441)
- f->frequency[f->frequency_type++] = 44100;
- if (rates & COP_PCM_R480)
- f->frequency[f->frequency_type++] = 48000;
- if (rates & COP_PCM_R882)
- f->frequency[f->frequency_type++] = 88200;
- if (rates & COP_PCM_R960)
- f->frequency[f->frequency_type++] = 96000;
- if (rates & COP_PCM_R1764)
- f->frequency[f->frequency_type++] = 176400;
- if (rates & COP_PCM_R1920)
- f->frequency[f->frequency_type++] = 192000;
- if (rates & COP_PCM_R3840)
- f->frequency[f->frequency_type++] = 384000;
-}
-
-static int
-azalia_codec_comresp(const codec_t *codec, nid_t nid, uint32_t control,
- uint32_t param, uint32_t* result)
-{
- azalia_t *az = device_private(codec->dev);
- int err;
-
- err = azalia_set_command(az, codec->address, nid, control, param);
- if (err == 0)
- err = azalia_get_response(az, result);
- return err;
-}
-
-static int
-azalia_codec_connect_stream(codec_t *this, int dir, uint16_t fmt, int number)
-{
- const convgroup_t *group;
- uint32_t v;
- int i, err, startchan, nchan;
- nid_t nid;
- bool flag222;
-
- DPRINTF(("%s: fmt=0x%4.4x number=%d\n", __func__, fmt, number));
- err = 0;
- if (dir == AUMODE_RECORD)
- group = &this->adcs.groups[this->adcs.cur];
- else
- group = &this->dacs.groups[this->dacs.cur];
- flag222 = group->nconv >= 3 &&
- (WIDGET_CHANNELS(&this->w[group->conv[0]]) == 2) &&
- (WIDGET_CHANNELS(&this->w[group->conv[1]]) == 2) &&
- (WIDGET_CHANNELS(&this->w[group->conv[2]]) == 2);
- nchan = (fmt & HDA_SD_FMT_CHAN) + 1;
- startchan = 0;
- for (i = 0; i < group->nconv; i++) {
- uint32_t stream_chan;
- nid = group->conv[i];
-
- /* surround and c/lfe handling */
- if (nchan >= 6 && flag222 && i == 1) {
- nid = group->conv[2];
- } else if (nchan >= 6 && flag222 && i == 2) {
- nid = group->conv[1];
- }
-
- err = this->comresp(this, nid, CORB_SET_CONVERTER_FORMAT, fmt, NULL);
- if (err)
- goto exit;
- stream_chan = (number << 4) | startchan;
- if (startchan >= nchan)
- stream_chan = 0; /* stream#0 */
- err = this->comresp(this, nid, CORB_SET_CONVERTER_STREAM_CHANNEL,
- stream_chan, NULL);
- if (err)
- goto exit;
- if (this->w[nid].widgetcap & COP_AWCAP_DIGITAL) {
- /* enable S/PDIF */
- this->comresp(this, nid, CORB_GET_DIGITAL_CONTROL,
- 0, &v);
- v = (v & 0xff) | CORB_DCC_DIGEN;
- this->comresp(this, nid, CORB_SET_DIGITAL_CONTROL_L,
- v, NULL);
- }
- startchan += WIDGET_CHANNELS(&this->w[nid]);
- }
-
-exit:
- DPRINTF(("%s: leave with %d\n", __func__, err));
- return err;
-}
-
-static int
-azalia_codec_disconnect_stream(codec_t *this, int dir)
-{
- const convgroup_t *group;
- uint32_t v;
- int i;
- nid_t nid;
-
- if (dir == AUMODE_RECORD)
- group = &this->adcs.groups[this->adcs.cur];
- else
- group = &this->dacs.groups[this->dacs.cur];
- for (i = 0; i < group->nconv; i++) {
- nid = group->conv[i];
- this->comresp(this, nid,
- CORB_SET_CONVERTER_STREAM_CHANNEL, 0, NULL);/* stream#0 */
- if (this->w[nid].widgetcap & COP_AWCAP_DIGITAL) {
- /* disable S/PDIF */
- this->comresp(this, nid,
- CORB_GET_DIGITAL_CONTROL, 0, &v);
- v = (v & ~CORB_DCC_DIGEN) & 0xff;
- this->comresp(this, nid,
- CORB_SET_DIGITAL_CONTROL_L, v, NULL);
- }
- }
- return 0;
-}
-
-/* ================================================================
- * HDA widget functions
- * ================================================================ */
-
-static int
-azalia_widget_init(widget_t *this, const codec_t *codec,
- nid_t nid, const char *lead)
-{
- char flagbuf[FLAGBUFLEN];
- uint32_t result;
- int err;
-
- err = codec->comresp(codec, nid, CORB_GET_PARAMETER,
- COP_AUDIO_WIDGET_CAP, &result);
- if (err)
- return err;
- this->nid = nid;
- this->widgetcap = result;
- this->type = COP_AWCAP_TYPE(result);
- snprintb(flagbuf, sizeof(flagbuf),
- "\20\014LRSWAP\013POWER\012DIGITAL"
- "\011CONNLIST\010UNSOL\07PROC\06STRIPE\05FORMATOV\04AMPOV\03OUTAMP"
- "\02INAMP\01STEREO", this->widgetcap);
- DPRINTF(("%s: ", device_xname(codec->dev)));
- if (this->widgetcap & COP_AWCAP_POWER) {
- codec->comresp(codec, nid, CORB_SET_POWER_STATE, CORB_PS_D0, &result);
- DELAY(100);
- }
- switch (this->type) {
- case COP_AWTYPE_AUDIO_OUTPUT:
- snprintf(this->name, sizeof(this->name), "dac%2.2x", nid);
- DPRINTF(("%s wcap=%s\n", this->name, flagbuf));
- azalia_widget_init_audio(this, codec, lead);
- break;
- case COP_AWTYPE_AUDIO_INPUT:
- snprintf(this->name, sizeof(this->name), "adc%2.2x", nid);
- DPRINTF(("%s wcap=%s\n", this->name, flagbuf));
- azalia_widget_init_audio(this, codec, lead);
- break;
- case COP_AWTYPE_AUDIO_MIXER:
- snprintf(this->name, sizeof(this->name), "mix%2.2x", nid);
- DPRINTF(("%s wcap=%s\n", this->name, flagbuf));
- break;
- case COP_AWTYPE_AUDIO_SELECTOR:
- snprintf(this->name, sizeof(this->name), "sel%2.2x", nid);
- DPRINTF(("%s wcap=%s\n", this->name, flagbuf));
- break;
- case COP_AWTYPE_PIN_COMPLEX:
- azalia_widget_init_pin(this, codec);
- snprintf(this->name, sizeof(this->name), "%s%2.2x",
- pin_colors[this->d.pin.color], nid);
- DPRINTF(("%s wcap=%s\n", this->name, flagbuf));
- azalia_widget_print_pin(this, lead);
- break;
- case COP_AWTYPE_POWER:
- snprintf(this->name, sizeof(this->name), "pow%2.2x", nid);
- DPRINTF(("%s wcap=%s\n", this->name, flagbuf));
- break;
- case COP_AWTYPE_VOLUME_KNOB:
- snprintf(this->name, sizeof(this->name), "volume%2.2x", nid);
- DPRINTF(("%s wcap=%s\n", this->name, flagbuf));
- err = codec->comresp(codec, nid, CORB_GET_PARAMETER,
- COP_VOLUME_KNOB_CAPABILITIES, &result);
- if (!err) {
- this->d.volume.cap = result;
- DPRINTF(("%sdelta=%d steps=%d\n", lead,
- !!(result & COP_VKCAP_DELTA),
- COP_VKCAP_NUMSTEPS(result)));
- }
- break;
- case COP_AWTYPE_BEEP_GENERATOR:
- snprintf(this->name, sizeof(this->name), "beep%2.2x", nid);
- DPRINTF(("%s wcap=%s\n", this->name, flagbuf));
- break;
- default:
- snprintf(this->name, sizeof(this->name), "widget%2.2x", nid);
- DPRINTF(("%s wcap=%s\n", this->name, flagbuf));
- break;
- }
- azalia_widget_init_connection(this, codec, lead);
-
- /* amplifier information */
- if (this->widgetcap & COP_AWCAP_INAMP) {
- if (this->widgetcap & COP_AWCAP_AMPOV)
- codec->comresp(codec, nid, CORB_GET_PARAMETER,
- COP_INPUT_AMPCAP, &this->inamp_cap);
- else
- this->inamp_cap = codec->w[codec->audiofunc].inamp_cap;
- DPRINTF(("%sinamp: mute=%u size=%u steps=%u offset=%u\n",
- lead, (this->inamp_cap & COP_AMPCAP_MUTE) != 0,
- COP_AMPCAP_STEPSIZE(this->inamp_cap),
- COP_AMPCAP_NUMSTEPS(this->inamp_cap),
- COP_AMPCAP_OFFSET(this->inamp_cap)));
- }
- if (this->widgetcap & COP_AWCAP_OUTAMP) {
- if (this->widgetcap & COP_AWCAP_AMPOV)
- codec->comresp(codec, nid, CORB_GET_PARAMETER,
- COP_OUTPUT_AMPCAP, &this->outamp_cap);
- else
- this->outamp_cap = codec->w[codec->audiofunc].outamp_cap;
- DPRINTF(("%soutamp: mute=%u size=%u steps=%u offset=%u\n",
- lead, (this->outamp_cap & COP_AMPCAP_MUTE) != 0,
- COP_AMPCAP_STEPSIZE(this->outamp_cap),
- COP_AMPCAP_NUMSTEPS(this->outamp_cap),
- COP_AMPCAP_OFFSET(this->outamp_cap)));
- }
- if (codec->init_widget != NULL)
- codec->init_widget(codec, this, nid);
- return 0;
-}
-
-static int
-azalia_widget_init_audio(widget_t *this, const codec_t *codec, const char *lead)
-{
- uint32_t result;
- int err;
-
- /* check audio format */
- if (this->widgetcap & COP_AWCAP_FORMATOV) {
- err = codec->comresp(codec, this->nid,
- CORB_GET_PARAMETER, COP_STREAM_FORMATS, &result);
- if (err)
- return err;
- this->d.audio.encodings = result;
- if (result == 0) { /* quirk for CMI9880.
- * This must not occuur usually... */
- this->d.audio.encodings =
- codec->w[codec->audiofunc].d.audio.encodings;
- this->d.audio.bits_rates =
- codec->w[codec->audiofunc].d.audio.bits_rates;
- } else {
- if ((result & COP_STREAM_FORMAT_PCM) == 0) {
- aprint_error("%s: %s: No PCM support: %x\n",
- device_xname(codec->dev), this->name, result);
- return -1;
- }
- err = codec->comresp(codec, this->nid, CORB_GET_PARAMETER,
- COP_PCM, &result);
- if (err)
- return err;
- this->d.audio.bits_rates = result;
- }
- } else {
- this->d.audio.encodings =
- codec->w[codec->audiofunc].d.audio.encodings;
- this->d.audio.bits_rates =
- codec->w[codec->audiofunc].d.audio.bits_rates;
- }
-#ifdef AZALIA_DEBUG
- azalia_widget_print_audio(this, lead, -1);
-#endif
- return 0;
-}
-
-#ifdef AZALIA_DEBUG
-static int
-azalia_widget_print_audio(const widget_t *this, const char *lead, int channels)
-{
- char flagbuf[FLAGBUFLEN];
-
- snprintb(flagbuf, sizeof(flagbuf),
- "\20\3AC3\2FLOAT32\1PCM", this->d.audio.encodings);
- if (channels < 0) {
- aprint_normal("%sencodings=%s\n", lead, flagbuf);
- } else if (this->widgetcap & COP_AWCAP_DIGITAL) {
- aprint_normal("%smax channels=%d, DIGITAL, encodings=%s\n",
- lead, channels, flagbuf);
- } else {
- aprint_normal("%smax channels=%d, encodings=%s\n",
- lead, channels, flagbuf);
- }
- snprintb(flagbuf, sizeof(flagbuf),
- "\20\x15""32bit\x14""24bit\x13""20bit"
- "\x12""16bit\x11""8bit""\x0c""384kHz\x0b""192kHz\x0a""176.4kHz"
- "\x09""96kHz\x08""88.2kHz\x07""48kHz\x06""44.1kHz\x05""32kHz\x04"
- "22.05kHz\x03""16kHz\x02""11.025kHz\x01""8kHz",
- this->d.audio.bits_rates);
- aprint_normal("%sPCM formats=%s\n", lead, flagbuf);
- return 0;
-}
-#endif
-
-static int
-azalia_widget_init_pin(widget_t *this, const codec_t *codec)
-{
- uint32_t result;
- int err;
-
- err = codec->comresp(codec, this->nid, CORB_GET_CONFIGURATION_DEFAULT,
- 0, &result);
- if (err)
- return err;
- this->d.pin.config = result;
- this->d.pin.sequence = CORB_CD_SEQUENCE(result);
- this->d.pin.association = CORB_CD_ASSOCIATION(result);
- this->d.pin.color = CORB_CD_COLOR(result);
- this->d.pin.device = CORB_CD_DEVICE(result);
-
- err = codec->comresp(codec, this->nid, CORB_GET_PARAMETER,
- COP_PINCAP, &result);
- if (err)
- return err;
- this->d.pin.cap = result;
-
- /* input pin */
- if ((this->d.pin.cap & COP_PINCAP_INPUT) &&
- (this->d.pin.cap & COP_PINCAP_OUTPUT) == 0) {
- err = codec->comresp(codec, this->nid,
- CORB_GET_PIN_WIDGET_CONTROL, 0, &result);
- if (err == 0) {
- result &= ~CORB_PWC_OUTPUT;
- result |= CORB_PWC_INPUT;
- codec->comresp(codec, this->nid,
- CORB_SET_PIN_WIDGET_CONTROL, result, NULL);
- }
- }
- /* output pin, or bidirectional pin */
- if (this->d.pin.cap & COP_PINCAP_OUTPUT) {
- err = codec->comresp(codec, this->nid,
- CORB_GET_PIN_WIDGET_CONTROL, 0, &result);
- if (err == 0) {
- result &= ~CORB_PWC_INPUT;
- result |= CORB_PWC_OUTPUT;
- codec->comresp(codec, this->nid,
- CORB_SET_PIN_WIDGET_CONTROL, result, NULL);
- }
- }
- return 0;
-}
-
-static int
-azalia_widget_print_pin(const widget_t *this, const char *lead)
-{
- char flagbuf[FLAGBUFLEN];
-
- DPRINTF(("%spin config; device=%s color=%s assoc=%d seq=%d", lead,
- pin_devices[this->d.pin.device], pin_colors[this->d.pin.color],
- this->d.pin.association, this->d.pin.sequence));
- snprintb(flagbuf, sizeof(flagbuf),
- "\20\021EAPD\07BALANCE\06INPUT"
- "\05OUTPUT\04HEADPHONE\03PRESENCE\02TRIGGER\01IMPEDANCE",
- this->d.pin.cap);
- DPRINTF((" cap=%s\n", flagbuf));
- return 0;
-}
-
-static int
-azalia_widget_init_connection(widget_t *this, const codec_t *codec,
- const char *lead)
-{
- uint32_t result;
- int err;
- bool longform;
- int length, i;
-
- this->selected = -1;
- if ((this->widgetcap & COP_AWCAP_CONNLIST) == 0)
- return 0;
-
- err = codec->comresp(codec, this->nid, CORB_GET_PARAMETER,
- COP_CONNECTION_LIST_LENGTH, &result);
- if (err)
- return err;
- longform = (result & COP_CLL_LONG) != 0;
- length = COP_CLL_LENGTH(result);
- if (length == 0)
- return 0;
- this->nconnections = length;
- this->connections = kmem_alloc(sizeof(nid_t) * (length + 3), KM_SLEEP);
- if (longform) {
- for (i = 0; i < length;) {
- err = codec->comresp(codec, this->nid,
- CORB_GET_CONNECTION_LIST_ENTRY, i, &result);
- if (err)
- return err;
- this->connections[i++] = CORB_CLE_LONG_0(result);
- this->connections[i++] = CORB_CLE_LONG_1(result);
- }
- } else {
- for (i = 0; i < length;) {
- err = codec->comresp(codec, this->nid,
- CORB_GET_CONNECTION_LIST_ENTRY, i, &result);
- if (err)
- return err;
- this->connections[i++] = CORB_CLE_SHORT_0(result);
- this->connections[i++] = CORB_CLE_SHORT_1(result);
- this->connections[i++] = CORB_CLE_SHORT_2(result);
- this->connections[i++] = CORB_CLE_SHORT_3(result);
- }
- }
- if (length > 0) {
- DPRINTF(("%sconnections=0x%x", lead, this->connections[0]));
- for (i = 1; i < length; i++) {
- DPRINTF((",0x%x", this->connections[i]));
- }
-
- err = codec->comresp(codec, this->nid,
- CORB_GET_CONNECTION_SELECT_CONTROL, 0, &result);
- if (err)
- return err;
- this->selected = CORB_CSC_INDEX(result);
- DPRINTF(("; selected=0x%x\n", this->connections[result]));
- }
- return 0;
-}
-
-/* ================================================================
- * Stream functions
- * ================================================================ */
-
-static int
-azalia_stream_init(stream_t *this, azalia_t *az, int regindex, int strnum, int dir)
-{
- int err;
-
- this->az = az;
- this->regbase = HDA_SD_BASE + regindex * HDA_SD_SIZE;
- this->intr_bit = 1 << regindex;
- this->number = strnum;
- this->dir = dir;
-
- /* setup BDL buffers */
- err = azalia_alloc_dmamem(az, sizeof(bdlist_entry_t) * HDA_BDL_MAX,
- 128, &this->bdlist);
- if (err) {
- aprint_error_dev(az->dev, "can't allocate a BDL buffer\n");
- return err;
- }
- return 0;
-}
-
-static int
-azalia_stream_delete(stream_t *this, azalia_t *az)
-{
- if (this->bdlist.addr == NULL)
- return 0;
- azalia_free_dmamem(az, &this->bdlist);
- return 0;
-}
-
-static int
-azalia_stream_reset(stream_t *this)
-{
- int i;
- uint16_t ctl;
-
- if (this->bdlist.addr == NULL)
- return EINVAL;
- ctl = STR_READ_2(this, CTL);
- STR_WRITE_2(this, CTL, ctl | HDA_SD_CTL_SRST);
- for (i = 5000; i >= 0; i--) {
- DELAY(10);
- ctl = STR_READ_2(this, CTL);
- if (ctl & HDA_SD_CTL_SRST)
- break;
- }
- if (i <= 0) {
- aprint_error_dev(this->az->dev, "stream reset failure 1\n");
- return -1;
- }
- STR_WRITE_2(this, CTL, ctl & ~HDA_SD_CTL_SRST);
- for (i = 5000; i >= 0; i--) {
- DELAY(10);
- ctl = STR_READ_2(this, CTL);
- if ((ctl & HDA_SD_CTL_SRST) == 0)
- break;
- }
- if (i <= 0) {
- aprint_error_dev(this->az->dev, "stream reset failure 2\n");
- return -1;
- }
- return 0;
-}
-
-static int
-azalia_stream_start(stream_t *this, void *start, void *end, int blk,
- void (*intr)(void *), void *arg, uint16_t fmt)
-{
- bdlist_entry_t *bdlist;
- bus_addr_t dmaaddr;
- int err, index;
- uint32_t intctl;
- uint8_t ctl, ctl2;
-
- DPRINTF(("%s: start=%p end=%p\n", __func__, start, end));
- if (this->bdlist.addr == NULL)
- return EINVAL;
- this->intr = intr;
- this->intr_arg = arg;
-
- err = azalia_stream_reset(this);
- if (err)
- return err;
-
- /* setup BDL */
- dmaaddr = AZALIA_DMA_DMAADDR(&this->buffer);
- this->dmaend = dmaaddr + ((char *)end - (char *)start);
- bdlist = (bdlist_entry_t*)this->bdlist.addr;
- for (index = 0; index < HDA_BDL_MAX; index++) {
- bdlist[index].low = dmaaddr;
- bdlist[index].high = PTR_UPPER32(dmaaddr);
- bdlist[index].length = blk;
- bdlist[index].flags = BDLIST_ENTRY_IOC;
- dmaaddr += blk;
- if (dmaaddr >= this->dmaend) {
- index++;
- break;
- }
- }
- /* The BDL covers the whole of the buffer. */
- this->dmanext = AZALIA_DMA_DMAADDR(&this->buffer);
-
- dmaaddr = AZALIA_DMA_DMAADDR(&this->bdlist);
- STR_WRITE_4(this, BDPL, dmaaddr);
- STR_WRITE_4(this, BDPU, PTR_UPPER32(dmaaddr));
- STR_WRITE_2(this, LVI, (index - 1) & HDA_SD_LVI_LVI);
- ctl2 = STR_READ_1(this, CTL2);
- STR_WRITE_1(this, CTL2,
- (ctl2 & ~HDA_SD_CTL2_STRM) | (this->number << HDA_SD_CTL2_STRM_SHIFT));
- STR_WRITE_4(this, CBL, ((char *)end - (char *)start));
-
- STR_WRITE_2(this, FMT, fmt);
-
- err = azalia_codec_connect_stream(&this->az->codecs[this->az->codecno],
- this->dir, fmt, this->number);
- if (err)
- return EINVAL;
-
- intctl = AZ_READ_4(this->az, INTCTL);
- intctl |= this->intr_bit;
- AZ_WRITE_4(this->az, INTCTL, intctl);
-
- ctl = STR_READ_1(this, CTL);
- ctl |= ctl | HDA_SD_CTL_DEIE | HDA_SD_CTL_FEIE | HDA_SD_CTL_IOCE | HDA_SD_CTL_RUN;
- STR_WRITE_1(this, CTL, ctl);
- return 0;
-}
-
-static int
-azalia_stream_halt(stream_t *this)
-{
- uint16_t ctl;
-
- if (this->bdlist.addr == NULL)
- return EINVAL;
- this->intr = this->intr_arg = NULL;
- ctl = STR_READ_2(this, CTL);
- ctl &= ~(HDA_SD_CTL_DEIE | HDA_SD_CTL_FEIE | HDA_SD_CTL_IOCE | HDA_SD_CTL_RUN);
- STR_WRITE_2(this, CTL, ctl);
- AZ_WRITE_4(this->az, INTCTL, AZ_READ_4(this->az, INTCTL) & ~this->intr_bit);
- azalia_codec_disconnect_stream
- (&this->az->codecs[this->az->codecno], this->dir);
- return 0;
-}
-
-static int
-azalia_stream_intr(stream_t *this, uint32_t intsts)
-{
- if (this->bdlist.addr == NULL)
- return 0;
- if ((intsts & this->intr_bit) == 0)
- return 0;
- STR_WRITE_1(this, STS, HDA_SD_STS_DESE
- | HDA_SD_STS_FIFOE | HDA_SD_STS_BCIS);
-
- if (this->intr != NULL)
- this->intr(this->intr_arg);
- return 1;
-}
-
-/* ================================================================
- * MI audio entries
- * ================================================================ */
-
-static int
-azalia_open(void *v, int flags)
-{
- azalia_t *az;
- codec_t *codec;
-
- DPRINTF(("%s: flags=0x%x\n", __func__, flags));
- az = v;
- codec = &az->codecs[az->codecno];
- if (flags & FWRITE && (az->mode_cap & AUMODE_PLAY) == 0)
- return EACCES;
- if (flags & FREAD && (az->mode_cap & AUMODE_RECORD) == 0)
- return EACCES;
- codec->running++;
- return 0;
-}
-
-static void
-azalia_close(void *v)
-{
- azalia_t *az;
- codec_t *codec;
-
- DPRINTF(("%s\n", __func__));
- az = v;
- codec = &az->codecs[az->codecno];
- codec->running--;
-}
-
-static int
-azalia_query_format(void *v, audio_format_query_t *afp)
-{
- azalia_t *az;
- codec_t *codec;
-
- az = v;
- codec = &az->codecs[az->codecno];
- return audio_query_format(codec->formats, codec->nformats, afp);
-}
-
-static int
-azalia_set_format(void *v, int setmode,
- const audio_params_t *p, const audio_params_t *r,
- audio_filter_reg_t *pfil, audio_filter_reg_t *rfil)
-{
-
- return 0;
-}
-
-static int
-azalia_round_blocksize(void *v, int blk, int mode,
- const audio_params_t *param)
-{
- azalia_t *az;
- size_t size;
-
- blk &= ~0x7f; /* must be multiple of 128 */
- if (blk <= 0)
- blk = 128;
- /* number of blocks must be <= HDA_BDL_MAX */
- az = v;
- size = mode == AUMODE_PLAY ? az->pstream.buffer.size : az->rstream.buffer.size;
-#ifdef DIAGNOSTIC
- if (size <= 0) {
- aprint_error("%s: size is 0", __func__);
- return 256;
- }
-#endif
- if (size > HDA_BDL_MAX * blk) {
- blk = size / HDA_BDL_MAX;
- if (blk & 0x7f)
- blk = (blk + 0x7f) & ~0x7f;
- }
- DPRINTF(("%s: resultant block size = %d\n", __func__, blk));
- return blk;
-}
-
-static int
-azalia_halt_output(void *v)
-{
- azalia_t *az;
-
- DPRINTF(("%s\n", __func__));
- az = v;
- return azalia_stream_halt(&az->pstream);
-}
-
-static int
-azalia_halt_input(void *v)
-{
- azalia_t *az;
-
- DPRINTF(("%s\n", __func__));
- az = v;
- return azalia_stream_halt(&az->rstream);
-}
-
-static int
-azalia_getdev(void *v, struct audio_device *dev)
-{
- azalia_t *az;
-
- az = v;
- strlcpy(dev->name, "HD-Audio", MAX_AUDIO_DEV_LEN);
- snprintf(dev->version, MAX_AUDIO_DEV_LEN,
- "%d.%d", AZ_READ_1(az, VMAJ), AZ_READ_1(az, VMIN));
- strlcpy(dev->config, device_xname(az->dev), MAX_AUDIO_DEV_LEN);
- return 0;
-}
-
-static int
-azalia_set_port(void *v, mixer_ctrl_t *mc)
-{
- azalia_t *az;
- codec_t *co;
-
- az = v;
- co = &az->codecs[az->codecno];
- return co->set_port(co, mc);
-}
-
-static int
-azalia_get_port(void *v, mixer_ctrl_t *mc)
-{
- azalia_t *az;
- codec_t *co;
-
- az = v;
- co = &az->codecs[az->codecno];
- return co->get_port(co, mc);
-}
-
-static int
-azalia_query_devinfo(void *v, mixer_devinfo_t *mdev)
-{
- azalia_t *az;
- const codec_t *co;
-
- az = v;
- co = &az->codecs[az->codecno];
- if (mdev->index < 0 || mdev->index >= co->nmixers)
- return ENXIO;
- *mdev = co->mixers[mdev->index].devinfo;
- return 0;
-}
-
-static void *
-azalia_allocm(void *v, int dir, size_t size)
-{
- azalia_t *az;
- stream_t *stream;
- int err;
-
- az = v;
- stream = dir == AUMODE_PLAY ? &az->pstream : &az->rstream;
- err = azalia_alloc_dmamem(az, size, 128, &stream->buffer);
- if (err)
- return NULL;
- return stream->buffer.addr;
-}
-
-static void
-azalia_freem(void *v, void *addr, size_t size)
-{
- azalia_t *az;
- stream_t *stream;
-
- az = v;
- if (addr == az->pstream.buffer.addr) {
- stream = &az->pstream;
- } else if (addr == az->rstream.buffer.addr) {
- stream = &az->rstream;
- } else {
- return;
- }
- azalia_free_dmamem(az, &stream->buffer);
-}
-
-static size_t
-azalia_round_buffersize(void *v, int dir, size_t size)
-{
- size &= ~0x7f; /* must be multiple of 128 */
- if (size <= 0)
- size = 128;
- return size;
-}
-
-static int
-azalia_get_props(void *v)
-{
-
- return AUDIO_PROP_PLAYBACK | AUDIO_PROP_CAPTURE |
- AUDIO_PROP_INDEPENDENT | AUDIO_PROP_FULLDUPLEX;
-}
-
-static int
-azalia_trigger_output(void *v, void *start, void *end, int blk,
- void (*intr)(void *), void *arg, const audio_params_t *param)
-{
- azalia_t *az;
- int err;
- uint16_t fmt;
-
- DPRINTF(("%s: this=%p start=%p end=%p blk=%d {enc=%u %uch %u/%ubit %uHz}\n",
- __func__, v, start, end, blk, param->encoding, param->channels,
- param->validbits, param->precision, param->sample_rate));
-
- err = azalia_params2fmt(param, &fmt);
- if (err)
- return EINVAL;
-
- az = v;
- return azalia_stream_start(&az->pstream, start, end, blk, intr, arg, fmt);
-}
-
-static int
-azalia_trigger_input(void *v, void *start, void *end, int blk,
- void (*intr)(void *), void *arg, const audio_params_t *param)
-{
- azalia_t *az;
- int err;
- uint16_t fmt;
-
- DPRINTF(("%s: this=%p start=%p end=%p blk=%d {enc=%u %uch %u/%ubit %uHz}\n",
- __func__, v, start, end, blk, param->encoding, param->channels,
- param->validbits, param->precision, param->sample_rate));
-
- err = azalia_params2fmt(param, &fmt);
- if (err)
- return EINVAL;
-
- az = v;
- return azalia_stream_start(&az->rstream, start, end, blk, intr, arg, fmt);
-}
-
-/* --------------------------------
- * helpers for MI audio functions
- * -------------------------------- */
-static int
-azalia_params2fmt(const audio_params_t *param, uint16_t *fmt)
-{
- uint16_t ret;
-
- ret = 0;
-#ifdef DIAGNOSTIC
- if (param->channels > HDA_MAX_CHANNELS) {
- aprint_error("%s: too many channels: %u\n", __func__,
- param->channels);
- return EINVAL;
- }
-#endif
- ret |= param->channels - 1;
-
- switch (param->validbits) {
- case 8:
- ret |= HDA_SD_FMT_BITS_8_16;
- break;
- case 16:
- ret |= HDA_SD_FMT_BITS_16_16;
- break;
- case 20:
- ret |= HDA_SD_FMT_BITS_20_32;
- break;
- case 24:
- ret |= HDA_SD_FMT_BITS_24_32;
- break;
- case 32:
- ret |= HDA_SD_FMT_BITS_32_32;
- break;
- default:
- aprint_error("%s: invalid validbits: %u\n", __func__,
- param->validbits);
- }
-
- if (param->sample_rate == 384000) {
- aprint_error("%s: invalid sample_rate: %u\n", __func__,
- param->sample_rate);
- return EINVAL;
- } else if (param->sample_rate == 192000) {
- ret |= HDA_SD_FMT_BASE_48 | HDA_SD_FMT_MULT_X4 | HDA_SD_FMT_DIV_BY1;
- } else if (param->sample_rate == 176400) {
- ret |= HDA_SD_FMT_BASE_44 | HDA_SD_FMT_MULT_X4 | HDA_SD_FMT_DIV_BY1;
- } else if (param->sample_rate == 96000) {
- ret |= HDA_SD_FMT_BASE_48 | HDA_SD_FMT_MULT_X2 | HDA_SD_FMT_DIV_BY1;
- } else if (param->sample_rate == 88200) {
- ret |= HDA_SD_FMT_BASE_44 | HDA_SD_FMT_MULT_X2 | HDA_SD_FMT_DIV_BY1;
- } else if (param->sample_rate == 48000) {
- ret |= HDA_SD_FMT_BASE_48 | HDA_SD_FMT_MULT_X1 | HDA_SD_FMT_DIV_BY1;
- } else if (param->sample_rate == 44100) {
- ret |= HDA_SD_FMT_BASE_44 | HDA_SD_FMT_MULT_X1 | HDA_SD_FMT_DIV_BY1;
- } else if (param->sample_rate == 32000) {
- ret |= HDA_SD_FMT_BASE_48 | HDA_SD_FMT_MULT_X2 | HDA_SD_FMT_DIV_BY3;
- } else if (param->sample_rate == 22050) {
- ret |= HDA_SD_FMT_BASE_44 | HDA_SD_FMT_MULT_X1 | HDA_SD_FMT_DIV_BY2;
- } else if (param->sample_rate == 16000) {
- ret |= HDA_SD_FMT_BASE_48 | HDA_SD_FMT_MULT_X1 | HDA_SD_FMT_DIV_BY3;
- } else if (param->sample_rate == 11025) {
- ret |= HDA_SD_FMT_BASE_44 | HDA_SD_FMT_MULT_X1 | HDA_SD_FMT_DIV_BY4;
- } else if (param->sample_rate == 8000) {
- ret |= HDA_SD_FMT_BASE_48 | HDA_SD_FMT_MULT_X1 | HDA_SD_FMT_DIV_BY6;
- } else {
- aprint_error("%s: invalid sample_rate: %u\n", __func__,
- param->sample_rate);
- return EINVAL;
- }
- *fmt = ret;
- return 0;
-}
-
-MODULE(MODULE_CLASS_DRIVER, azalia, "pci");
-
-static void
-azalia_get_locks(void *addr, kmutex_t **intr, kmutex_t **thread)
-{
- azalia_t *az;
-
- az = addr;
- *intr = &az->intr_lock;
- *thread = &az->lock;
-}
-
-#ifdef _MODULE
-#include "ioconf.c"
-#endif
-
-static int
-azalia_modcmd(modcmd_t cmd, void *arg)
-{
- int error = 0;
-
- switch (cmd) {
- case MODULE_CMD_INIT:
-#ifdef _MODULE
- error = config_init_component(cfdriver_ioconf_azalia,
- cfattach_ioconf_azalia, cfdata_ioconf_azalia);
-#endif
- break;
- case MODULE_CMD_FINI:
-#ifdef _MODULE
- error = config_fini_component(cfdriver_ioconf_azalia,
- cfattach_ioconf_azalia, cfdata_ioconf_azalia);
-#endif
- break;
- default:
- return ENOTTY;
- }
-
- return error;
-}
diff --git a/sys/dev/pci/azalia.h b/sys/dev/pci/azalia.h
deleted file mode 100644
index 2b89c31b4ad..00000000000
--- a/sys/dev/pci/azalia.h
+++ /dev/null
@@ -1,594 +0,0 @@
-/* $NetBSD: azalia.h,v 1.22 2019/05/08 13:40:18 isaki Exp $ */
-
-/*-
- * Copyright (c) 2005, 2008 The NetBSD Foundation, Inc.
- * All rights reserved.
- *
- * This code is derived from software contributed to The NetBSD Foundation
- * by TAMURA Kent
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <sys/types.h>
-#include <sys/audioio.h>
-
-/* ----------------------------------------------------------------
- * High Definition Audio constant values
- * ---------------------------------------------------------------- */
-
-/* High Definition Audio registers */
-#define HDA_GCAP 0x000 /* 2 */
-#define HDA_GCAP_OSS(x) ((x & 0xf000) >> 12)
-#define HDA_GCAP_ISS(x) ((x & 0x0f00) >> 8)
-#define HDA_GCAP_BSS(x) ((x & 0x00f8) >> 3)
-#define HDA_GCAP_NSDO_MASK 0x0006
-#define HDA_GCAP_NSDO_1 0x0000
-#define HDA_GCAP_NSDO_2 0x0002
-#define HDA_GCAP_NSDO_4 0x0004
-#define HDA_GCAP_NSDO_RESERVED 0x0006
-#define HDA_GCAP_64OK 0x0001
-#define HDA_VMIN 0x002 /* 1 */
-#define HDA_VMAJ 0x003 /* 1 */
-#define HDA_OUTPAY 0x004 /* 2 */
-#define HDA_INPAY 0x006 /* 2 */
-#define HDA_GCTL 0x008 /* 4 */
-#define HDA_GCTL_UNSOL 0x00000100
-#define HDA_GCTL_FCNTRL 0x00000002
-#define HDA_GCTL_CRST 0x00000001
-#define HDA_WAKEEN 0x00c /* 2 */
-#define HDA_WAKEEN_SDIWEN 0x7fff
-#define HDA_STATESTS 0x00e /* 2 */
-#define HDA_STATESTS_SDIWAKE 0x7fff
-#define HDA_GSTS 0x010 /* 2 */
-#define HDA_GSTS_FSTS 0x0002
-#define HDA_OUTSTRMPAY 0x018 /* 2 */
-#define HDA_INSTRMPAY 0x01a /* 2 */
-#define HDA_INTCTL 0x020 /* 4 */
-#define HDA_INTCTL_GIE 0x80000000
-#define HDA_INTCTL_CIE 0x40000000
-#define HDA_INTCTL_SIE 0x3fffffff
-#define HDA_INTSTS 0x024 /* 4 */
-#define HDA_INTSTS_GIS 0x80000000
-#define HDA_INTSTS_CIS 0x40000000
-#define HDA_INTSTS_SIS 0x3fffffff
-#define HDA_WALCLK 0x030 /* 4 */
-#define HDA_SSYNC 0x034 /* 4 */
-#define HDA_SSYNC_SSYNC 0x3fffffff
-#define HDA_CORBLBASE 0x040 /* 4 */
-#define HDA_CORBUBASE 0x044 /* 4 */
-#define HDA_CORBWP 0x048 /* 2 */
-#define HDA_CORBWP_CORBWP 0x00ff
-#define HDA_CORBRP 0x04a /* 2 */
-#define HDA_CORBRP_CORBRPRST 0x8000
-#define HDA_CORBRP_CORBRP 0x00ff
-#define HDA_CORBCTL 0x04c /* 1 */
-#define HDA_CORBCTL_CORBRUN 0x02
-#define HDA_CORBCTL_CMEIE 0x01
-#define HDA_CORBSTS 0x04d /* 1 */
-#define HDA_CORBSTS_CMEI 0x01
-#define HDA_CORBSIZE 0x04e /* 1 */
-#define HDA_CORBSIZE_CORBSZCAP_MASK 0xf0
-#define HDA_CORBSIZE_CORBSZCAP_2 0x10
-#define HDA_CORBSIZE_CORBSZCAP_16 0x20
-#define HDA_CORBSIZE_CORBSZCAP_256 0x40
-#define HDA_CORBSIZE_CORBSIZE_MASK 0x03
-#define HDA_CORBSIZE_CORBSIZE_2 0x00
-#define HDA_CORBSIZE_CORBSIZE_16 0x01
-#define HDA_CORBSIZE_CORBSIZE_256 0x02
-#define HDA_RIRBLBASE 0x050 /* 4 */
-#define HDA_RIRBUBASE 0x054 /* 4 */
-#define HDA_RIRBWP 0x058 /* 2 */
-#define HDA_RIRBWP_RIRBWPRST 0x8000
-#define HDA_RIRBWP_RIRBWP 0x00ff
-#define HDA_RINTCNT 0x05a /* 2 */
-#define HDA_RINTCNT_RINTCNT 0x00ff
-#define HDA_RIRBCTL 0x05c /* 1 */
-#define HDA_RIRBCTL_RIRBOIC 0x04
-#define HDA_RIRBCTL_RIRBDMAEN 0x02
-#define HDA_RIRBCTL_RINTCTL 0x01
-#define HDA_RIRBSTS 0x05d /* 1 */
-#define HDA_RIRBSTS_RIRBOIS 0x04
-#define HDA_RIRBSTS_RINTFL 0x01
-#define HDA_RIRBSIZE 0x05e /* 1 */
-#define HDA_RIRBSIZE_RIRBSZCAP_MASK 0xf0
-#define HDA_RIRBSIZE_RIRBSZCAP_2 0x10
-#define HDA_RIRBSIZE_RIRBSZCAP_16 0x20
-#define HDA_RIRBSIZE_RIRBSZCAP_256 0x40
-#define HDA_RIRBSIZE_RIRBSIZE_MASK 0x03
-#define HDA_RIRBSIZE_RIRBSIZE_2 0x00
-#define HDA_RIRBSIZE_RIRBSIZE_16 0x01
-#define HDA_RIRBSIZE_RIRBSIZE_256 0x02
-#define HDA_IC 0x060 /* 4 */
-#define HDA_IR 0x064 /* 4 */
-#define HDA_IRS 0x068 /* 2 */
-#define HDA_IRS_IRRADD 0x00f0
-#define HDA_IRS_IRRUNSOL 0x0008
-#define HDA_IRS_IRV 0x0002
-#define HDA_IRS_ICB 0x0001
-#define HDA_DPLBASE 0x070 /* 4 */
-#define HDA_DPLBASE_DPLBASE 0xffffff80
-#define HDA_DPLBASE_ENABLE 0x00000001
-#define HDA_DPUBASE 0x074
-
-#define HDA_SD_BASE 0x080
-#define HDA_SD_CTL 0x00 /* 2 */
-#define HDA_SD_CTL_DEIE 0x0010
-#define HDA_SD_CTL_FEIE 0x0008
-#define HDA_SD_CTL_IOCE 0x0004
-#define HDA_SD_CTL_RUN 0x0002
-#define HDA_SD_CTL_SRST 0x0001
-#define HDA_SD_CTL2 0x02 /* 1 */
-#define HDA_SD_CTL2_STRM 0xf0
-#define HDA_SD_CTL2_STRM_SHIFT 4
-#define HDA_SD_CTL2_DIR 0x08
-#define HDA_SD_CTL2_TP 0x04
-#define HDA_SD_CTL2_STRIPE 0x03
-#define HDA_SD_STS 0x03 /* 1 */
-#define HDA_SD_STS_FIFORDY 0x20
-#define HDA_SD_STS_DESE 0x10
-#define HDA_SD_STS_FIFOE 0x08
-#define HDA_SD_STS_BCIS 0x04
-#define HDA_SD_LPIB 0x04 /* 4 */
-#define HDA_SD_CBL 0x08 /* 4 */
-#define HDA_SD_LVI 0x0c /* 2 */
-#define HDA_SD_LVI_LVI 0x00ff
-#define HDA_SD_FIFOW 0x0e /* 2 */
-#define HDA_SD_FIFOS 0x10 /* 2 */
-#define HDA_SD_FMT 0x12 /* 2 */
-#define HDA_SD_FMT_BASE 0x4000
-#define HDA_SD_FMT_BASE_48 0x0000
-#define HDA_SD_FMT_BASE_44 0x4000
-#define HDA_SD_FMT_MULT 0x3800
-#define HDA_SD_FMT_MULT_X1 0x0000
-#define HDA_SD_FMT_MULT_X2 0x0800
-#define HDA_SD_FMT_MULT_X3 0x1000
-#define HDA_SD_FMT_MULT_X4 0x1800
-#define HDA_SD_FMT_DIV 0x0700
-#define HDA_SD_FMT_DIV_BY1 0x0000
-#define HDA_SD_FMT_DIV_BY2 0x0100
-#define HDA_SD_FMT_DIV_BY3 0x0200
-#define HDA_SD_FMT_DIV_BY4 0x0300
-#define HDA_SD_FMT_DIV_BY5 0x0400
-#define HDA_SD_FMT_DIV_BY6 0x0500
-#define HDA_SD_FMT_DIV_BY7 0x0600
-#define HDA_SD_FMT_DIV_BY8 0x0700
-#define HDA_SD_FMT_BITS 0x0070
-#define HDA_SD_FMT_BITS_8_16 0x0000
-#define HDA_SD_FMT_BITS_16_16 0x0010
-#define HDA_SD_FMT_BITS_20_32 0x0020
-#define HDA_SD_FMT_BITS_24_32 0x0030
-#define HDA_SD_FMT_BITS_32_32 0x0040
-#define HDA_SD_FMT_CHAN 0x000f
-#define HDA_SD_BDPL 0x18 /* 4 */
-#define HDA_SD_BDPU 0x1c /* 4 */
-#define HDA_SD_SIZE 0x20
-
-/* CORB commands */
-#define CORB_GET_PARAMETER 0xf00
-#define COP_VENDOR_ID 0x00
-#define COP_VID_VENDOR(x) (x >> 16)
-#define COP_VID_DEVICE(x) (x & 0xffff)
-#define COP_REVISION_ID 0x02
-#define COP_RID_MAJ(x) ((x >> 20) & 0x0f)
-#define COP_RID_MIN(x) ((x >> 16) & 0x0f)
-#define COP_RID_REVISION(x) ((x >> 8) & 0xff)
-#define COP_RID_STEPPING(x) (x & 0xff)
-#define COP_SUBORDINATE_NODE_COUNT 0x04
-#define COP_START_NID(x) ((x & 0x00ff0000) >> 16)
-#define COP_NSUBNODES(x) (x & 0x000000ff)
-#define COP_FUNCTION_GROUP_TYPE 0x05
-#define COP_FTYPE(x) (x & 0x000000ff)
-#define COP_FTYPE_RESERVED 0x01
-#define COP_FTYPE_AUDIO 0x01
-#define COP_FTYPE_MODEM 0x02
-#define COP_AUDIO_FUNCTION_GROUP_CAPABILITY 0x08
-#define COP_AUDIO_WIDGET_CAP 0x09
-#define COP_AWCAP_TYPE(x) ((x >> 20) & 0xf)
-#define COP_AWTYPE_AUDIO_OUTPUT 0x0
-#define COP_AWTYPE_AUDIO_INPUT 0x1
-#define COP_AWTYPE_AUDIO_MIXER 0x2
-#define COP_AWTYPE_AUDIO_SELECTOR 0x3
-#define COP_AWTYPE_PIN_COMPLEX 0x4
-#define COP_AWTYPE_POWER 0x5
-#define COP_AWTYPE_VOLUME_KNOB 0x6
-#define COP_AWTYPE_BEEP_GENERATOR 0x7
-#define COP_AWTYPE_VENDOR_DEFINED 0xf
-#define COP_AWCAP_STEREO 0x001
-#define COP_AWCAP_INAMP 0x002
-#define COP_AWCAP_OUTAMP 0x004
-#define COP_AWCAP_AMPOV 0x008
-#define COP_AWCAP_FORMATOV 0x010
-#define COP_AWCAP_STRIPE 0x020
-#define COP_AWCAP_PROC 0x040
-#define COP_AWCAP_UNSOL 0x080
-#define COP_AWCAP_CONNLIST 0x100
-#define COP_AWCAP_DIGITAL 0x200
-#define COP_AWCAP_POWER 0x400
-#define COP_AWCAP_LRSWAP 0x800
-#define COP_AWCAP_DELAY(x) ((x >> 16) & 0xf)
-#define COP_PCM 0x0a
-#define COP_PCM_B32 0x00100000
-#define COP_PCM_B24 0x00080000
-#define COP_PCM_B20 0x00040000
-#define COP_PCM_B16 0x00020000
-#define COP_PCM_B8 0x00010000
-#define COP_PCM_R3840 0x00000800
-#define COP_PCM_R1920 0x00000400
-#define COP_PCM_R1764 0x00000200
-#define COP_PCM_R960 0x00000100
-#define COP_PCM_R882 0x00000080
-#define COP_PCM_R480 0x00000040
-#define COP_PCM_R441 0x00000020
-#define COP_PCM_R320 0x00000010
-#define COP_PCM_R220 0x00000008
-#define COP_PCM_R160 0x00000004
-#define COP_PCM_R110 0x00000002
-#define COP_PCM_R80 0x00000001
-#define COP_STREAM_FORMATS 0x0b
-#define COP_STREAM_FORMAT_PCM 0x00000001
-#define COP_STREAM_FORMAT_FLOAT32 0x00000002
-#define COP_STREAM_FORMAT_AC3 0x00000003
-#define COP_PINCAP 0x0c
-#define COP_PINCAP_IMPEDANCE 0x00000001
-#define COP_PINCAP_TRIGGER 0x00000002
-#define COP_PINCAP_PRESENCE 0x00000004
-#define COP_PINCAP_HEADPHONE 0x00000008
-#define COP_PINCAP_OUTPUT 0x00000010
-#define COP_PINCAP_INPUT 0x00000020
-#define COP_PINCAP_BALANCE 0x00000040
-#define COP_PINCAP_VREF(x) ((x >> 8) & 0xff)
-#define COP_PINCAP_EAPD 0x00010000
-#define COP_INPUT_AMPCAP 0x0d
-#define COP_AMPCAP_OFFSET(x) (x & 0x0000007f)
-#define COP_AMPCAP_NUMSTEPS(x) ((x >> 8) & 0x7f)
-#define COP_AMPCAP_STEPSIZE(x) ((x >> 16) & 0x7f)
-#define COP_AMPCAP_MUTE 0x80000000
-#define COP_CONNECTION_LIST_LENGTH 0x0e
-#define COP_CLL_LONG 0x00000080
-#define COP_CLL_LENGTH(x) (x & 0x0000007f)
-#define COP_SUPPORTED_POWER_STATES 0x0f
-#define COP_PROCESSING_CAPABILITIES 0x10
-#define COP_GPIO_COUNT 0x11
-#define COP_OUTPUT_AMPCAP 0x12
-#define COP_VOLUME_KNOB_CAPABILITIES 0x13
-#define COP_VKCAP_DELTA 0x00000080
-#define COP_VKCAP_NUMSTEPS(x) (x & 0x7f)
-#define CORB_GET_CONNECTION_SELECT_CONTROL 0xf01
-#define CORB_CSC_INDEX(x) (x & 0xff)
-#define CORB_SET_CONNECTION_SELECT_CONTROL 0x701
-#define CORB_GET_CONNECTION_LIST_ENTRY 0xf02
-#define CORB_CLE_LONG_0(x) (x & 0x0000ffff)
-#define CORB_CLE_LONG_1(x) ((x & 0xffff0000) >> 16)
-#define CORB_CLE_SHORT_0(x) (x & 0xff)
-#define CORB_CLE_SHORT_1(x) ((x >> 8) & 0xff)
-#define CORB_CLE_SHORT_2(x) ((x >> 16) & 0xff)
-#define CORB_CLE_SHORT_3(x) ((x >> 24) & 0xff)
-#define CORB_GET_PROCESSING_STATE 0xf03
-#define CORB_SET_PROCESSING_STATE 0x703
-#define CORB_GET_COEFFICIENT_INDEX 0xd00
-#define CORB_SET_COEFFICIENT_INDEX 0x500
-#define CORB_GET_PROCESSING_COEFFICIENT 0xc00
-#define CORB_SET_PROCESSING_COEFFICIENT 0x400
-#define CORB_GET_AMPLIFIER_GAIN_MUTE 0xb00
-#define CORB_GAGM_INPUT 0x0000
-#define CORB_GAGM_OUTPUT 0x8000
-#define CORB_GAGM_RIGHT 0x0000
-#define CORB_GAGM_LEFT 0x2000
-#define CORB_GAGM_MUTE 0x00000080
-#define CORB_GAGM_GAIN(x) (x & 0x0000007f)
-#define CORB_SET_AMPLIFIER_GAIN_MUTE 0x300
-#define CORB_AGM_GAIN_MASK 0x007f
-#define CORB_AGM_MUTE 0x0080
-#define CORB_AGM_INDEX_SHIFT 8
-#define CORB_AGM_RIGHT 0x1000
-#define CORB_AGM_LEFT 0x2000
-#define CORB_AGM_INPUT 0x4000
-#define CORB_AGM_OUTPUT 0x8000
-#define CORB_GET_CONVERTER_FORMAT 0xa00
-#define CORB_SET_CONVERTER_FORMAT 0x200
-#define CORB_GET_DIGITAL_CONTROL 0xf0d
-#define CORB_SET_DIGITAL_CONTROL_L 0x70d
-#define CORB_SET_DIGITAL_CONTROL_H 0x70e
-#define CORB_DCC_DIGEN 0x01
-#define CORB_DCC_V 0x02
-#define CORB_DCC_VCFG 0x04
-#define CORB_DCC_PRE 0x08
-#define CORB_DCC_COPY 0x10
-#define CORB_DCC_NAUDIO 0x20
-#define CORB_DCC_PRO 0x40
-#define CORB_DCC_L 0x80
-#define CORB_DCC_CC(x) ((x >> 8) & 0x7f)
-#define CORB_GET_POWER_STATE 0xf05
-#define CORB_SET_POWER_STATE 0x705
-#define CORB_PS_D0 0x0
-#define CORB_PS_D1 0x1
-#define CORB_PS_D2 0x2
-#define CORB_PS_D3 0x3
-#define CORB_GET_CONVERTER_STREAM_CHANNEL 0xf06
-#define CORB_SET_CONVERTER_STREAM_CHANNEL 0x706
-#define CORB_GET_INPUT_CONVERTER_SDI_SELECT 0xf04
-#define CORB_SET_INPUT_CONVERTER_SDI_SELECT 0x704
-#define CORB_GET_PIN_WIDGET_CONTROL 0xf07
-#define CORB_SET_PIN_WIDGET_CONTROL 0x707
-#define CORB_PWC_HEADPHONE 0x80
-#define CORB_PWC_OUTPUT 0x40
-#define CORB_PWC_INPUT 0x20
-#define CORB_PWC_VREF_HIZ 0x00
-#define CORB_PWC_VREF_50 0x01
-#define CORB_PWC_VREF_GND 0x02
-#define CORB_PWC_VREF_80 0x04
-#define CORB_PWC_VREF_100 0x05
-#define CORB_GET_UNSOLICITED_RESPONSE 0xf08
-#define CORB_SET_UNSOLICITED_RESPONSE 0x708
-#define CORB_UNSOL_ENABLE 0x80
-#define CORB_UNSOL_TAG(x) (x & 0x3f)
-#define CORB_GET_PIN_SENSE 0xf09
-#define CORB_PS_PRESENCE 0x80000000
-#define CORB_PS_IMPEDANCE(x) (x & 0x7fffffff)
-#define CORB_EXECUTE_PIN_SENSE 0x709
-#define CORB_PS_RIGHT 0x1
-#define CORB_GET_EAPD_BTL_ENABLE 0xf0c
-#define CORB_SET_EAPD_BTL_ENABLE 0x70c
-#define CORB_EAPD_BTL 0x01
-#define CORB_EAPD_EAPD 0x02
-#define CORB_EAPD_LRSWAP 0x04
-#define CORB_GET_GPI_DATA 0xf10
-#define CORB_SET_GPI_DATA 0x710
-#define CORB_GET_GPI_WAKE_ENABLE_MASK 0xf11
-#define CORB_SET_GPI_WAKE_ENABLE_MASK 0x711
-#define CORB_GET_GPI_UNSOLICITED_ENABLE_MASK 0xf12
-#define CORB_SET_GPI_UNSOLICITED_ENABLE_MASK 0x712
-#define CORB_GET_GPI_STICKY_MASK 0xf13
-#define CORB_SET_GPI_STICKY_MASK 0x713
-#define CORB_GET_GPO_DATA 0xf14
-#define CORB_SET_GPO_DATA 0x714
-#define CORB_GET_GPIO_DATA 0xf15
-#define CORB_SET_GPIO_DATA 0x715
-#define CORB_GET_GPIO_ENABLE_MASK 0xf16
-#define CORB_SET_GPIO_ENABLE_MASK 0x716
-#define CORB_GET_GPIO_DIRECTION 0xf17
-#define CORB_SET_GPIO_DIRECTION 0x717
-#define CORB_GET_GPIO_WAKE_ENABLE_MASK 0xf18
-#define CORB_SET_GPIO_WAKE_ENABLE_MASK 0x718
-#define CORB_GET_GPIO_UNSOLICITED_ENABLE_MASK 0xf19
-#define CORB_SET_GPIO_UNSOLICITED_ENABLE_MASK 0x719
-#define CORB_GET_GPIO_STICKY_MASK 0xf1a
-#define CORB_SET_GPIO_STICKY_MASK 0x71a
-#define CORB_GET_BEEP_GENERATION 0xf0a
-#define CORB_SET_BEEP_GENERATION 0x70a
-#define CORB_GET_VOLUME_KNOB 0xf0f
-#define CORB_SET_VOLUME_KNOB 0x70f
-#define CORB_VKNOB_DIRECT 0x80
-#define CORB_VKNOB_VOLUME(x) (x & 0x7f)
-#define CORB_GET_SUBSYSTEM_ID 0xf20
-#define CORB_SET_SUBSYSTEM_ID_1 0x720
-#define CORB_SET_SUBSYSTEM_ID_2 0x721
-#define CORB_SET_SUBSYSTEM_ID_3 0x722
-#define CORB_SET_SUBSYSTEM_ID_4 0x723
-#define CORB_GET_CONFIGURATION_DEFAULT 0xf1c
-#define CORB_SET_CONFIGURATION_DEFAULT_1 0x71c
-#define CORB_SET_CONFIGURATION_DEFAULT_2 0x71d
-#define CORB_SET_CONFIGURATION_DEFAULT_3 0x71e
-#define CORB_SET_CONFIGURATION_DEFAULT_4 0x71f
-#define CORB_CD_SEQUENCE(x) (x & 0x0000000f)
-#define CORB_CD_SEQUENCE_MAX 0x0f
-#define CORB_CD_ASSOCIATION(x) ((x >> 4) & 0xf)
-#define CORB_CD_ASSOCIATION_MAX 0x0f
-#define CORB_CD_MISC_MASK 0x00000f00
-#define CORB_CD_COLOR(x) ((x >> 12) & 0xf)
-#define CORB_CD_COLOR_UNKNOWN 0x0
-#define CORB_CD_BLACK 0x1
-#define CORB_CD_GRAY 0x2
-#define CORB_CD_BLUE 0x3
-#define CORB_CD_GREEN 0x4
-#define CORB_CD_RED 0x5
-#define CORB_CD_ORANGE 0x6
-#define CORB_CD_YELLOW 0x7
-#define CORB_CD_PURPLE 0x8
-#define CORB_CD_PINK 0x9
-#define CORB_CD_WHITE 0xe
-#define CORB_CD_COLOR_OTHER 0xf
-#define CORB_CD_CONNECTION_MASK 0x000f0000
-#define CORB_CD_DEVICE(x) ((x >> 20) & 0xf)
-#define CORB_CD_LINEOUT 0x0
-#define CORB_CD_SPEAKER 0x1
-#define CORB_CD_HEADPHONE 0x2
-#define CORB_CD_CD 0x3
-#define CORB_CD_SPDIFOUT 0x4
-#define CORB_CD_DIGITALOUT 0x5
-#define CORB_CD_MODEMLINE 0x6
-#define CORB_CD_MODEMHANDSET 0x7
-#define CORB_CD_LINEIN 0x8
-#define CORB_CD_AUX 0x9
-#define CORB_CD_MICIN 0xa
-#define CORB_CD_TELEPHONY 0xb
-#define CORB_CD_SPDIFIN 0xc
-#define CORB_CD_DIGITALIN 0xd
-#define CORB_CD_DEVICE_OTHER 0xf
-#define CORB_CD_LOCATION_MASK 0x3f000000
-#define CORB_CD_PORT_MASK 0xc0000000
-#define CORB_GET_STRIPE_CONTROL 0xf24
-#define CORB_SET_STRIPE_CONTROL 0x720 /* XXX typo in the spec? */
-#define CORB_EXECUTE_FUNCTION_RESET 0x7ff
-
-#define CORB_NID_ROOT 0
-#define HDA_MAX_CHANNELS 16
-
-
-#ifndef PCI_SUBCLASS_MULTIMEDIA_HDAUDIO
-#define PCI_SUBCLASS_MULTIMEDIA_HDAUDIO 0x03
-#endif
-
-/* memory-mapped types */
-typedef struct {
- uint32_t low;
- uint32_t high;
- uint32_t length;
- uint32_t flags;
-#define BDLIST_ENTRY_IOC 0x00000001
-} __packed bdlist_entry_t;
-#define HDA_BDL_MAX 256
-
-typedef struct {
- uint32_t position;
- uint32_t reserved;
-} __packed dmaposition_t;
-
-typedef uint32_t corb_entry_t;
-typedef struct {
- uint32_t resp;
- uint32_t resp_ex;
-#define RIRB_UNSOL_TAG(resp) ((resp) >> 26)
-#define RIRB_RESP_UNSOL (1 << 4)
-#define RIRB_RESP_CODEC(ex) ((ex) & 0xf)
-} __packed rirb_entry_t;
-
-
-/* #define AZALIA_DEBUG */
-/* #define AZALIA_DEBUG_DOT */
-#ifdef AZALIA_DEBUG
-# define DPRINTF(x) do { printf x; } while (0/*CONSTCOND*/)
-#else
-# define DPRINTF(x) do {} while (0/*CONSTCOND*/)
-#endif
-#define PTR_UPPER32(x) ((uint64_t)(uintptr_t)(x) >> 32)
-#define FLAGBUFLEN 256
-#define MAX_VOLUME_255 1
-
-typedef int nid_t;
-
-typedef struct {
- nid_t nid;
- uint32_t widgetcap;
- int type; /* = bit20-24 of widgetcap */
- int nconnections;
- nid_t *connections;
- int selected;
- uint32_t inamp_cap;
- uint32_t outamp_cap;
- char name[MAX_AUDIO_DEV_LEN];
- union {
- struct { /* for AUDIO_INPUT/OUTPUT */
- uint32_t encodings;
- uint32_t bits_rates;
- } audio;
- struct { /* for PIN */
- uint32_t cap;
- uint32_t config;
- int sequence;
- int association;
- int color;
- int device;
- } pin;
- struct { /* for VOLUME_KNOB */
- uint32_t cap;
- } volume;
- } d;
-} widget_t;
-#define WIDGET_CHANNELS(w) ((w)->widgetcap & COP_AWCAP_STEREO ? 2 : 1)
-
-typedef struct {
- mixer_devinfo_t devinfo;
- nid_t nid; /* target NID; 0 is invalid. */
- int target; /* 0-15: inamp index, 0x100: outamp, ... */
-#define IS_MI_TARGET_INAMP(x) ((x) <= 15)
-#define MI_TARGET_INAMP(x) (x)
-#define MI_TARGET_OUTAMP 0x100
-#define MI_TARGET_CONNLIST 0x101
-#define MI_TARGET_PINDIR 0x102 /* for bidirectional pin */
-#define MI_TARGET_PINBOOST 0x103 /* for headphone pin */
-#define MI_TARGET_DAC 0x104
-#define MI_TARGET_ADC 0x105
-#define MI_TARGET_VOLUME 0x106
-#define MI_TARGET_SPDIF 0x107
-#define MI_TARGET_SPDIF_CC 0x108
-#define MI_TARGET_EAPD 0x109
-#define MI_TARGET_BALANCE 0x10a
-#define MI_TARGET_LRSWAP 0x10b
-} mixer_item_t;
-
-#define VALID_WIDGET_NID(nid, codec) (nid == (codec)->audiofunc || \
- (nid >= (codec)->wstart && \
- nid < (codec)->wend))
-
-#define PIN_STATUS(wid, conn) \
- do { \
- if ((wid)->type != COP_AWTYPE_PIN_COMPLEX) \
- (conn) = 0; \
- else \
- (conn) = \
- ((wid)->d.pin.config & CORB_CD_PORT_MASK) >> 30; \
- } while (0)
-
-typedef struct {
- int nconv;
- nid_t conv[HDA_MAX_CHANNELS]; /* front, surround, clfe, side, ... */
-} convgroup_t;
-typedef struct {
- int cur;
- int ngroups;
- convgroup_t groups[32];
-} convgroupset_t;
-
-typedef struct codec_t {
- int (*comresp)(const struct codec_t *, nid_t, uint32_t, uint32_t, uint32_t *);
- int (*init_dacgroup)(struct codec_t *);
- int (*init_widget)(const struct codec_t *, widget_t *, nid_t);
- int (*mixer_init)(struct codec_t *);
- int (*mixer_delete)(struct codec_t *);
- int (*set_port)(struct codec_t *, mixer_ctrl_t *);
- int (*get_port)(struct codec_t *, mixer_ctrl_t *);
- int (*unsol_event)(struct codec_t *, int);
-
- device_t dev; /* parent azalia(4) instance */
- uint32_t vid; /* codec vendor/device ID */
- uint32_t subid; /* PCI subvendor/device ID */
- const char *name;
- int address;
- int nfunctions;
- nid_t audiofunc; /* NID of an audio function node */
- nid_t wstart; /* start NID of audio widgets */
- nid_t wend; /* the last NID of audio widgets + 1 */
- widget_t *w; /* widgets in the audio function.
- * w[0] to w[wstart-1] are unused. */
-#define FOR_EACH_WIDGET(this, i) for (i = (this)->wstart; i < (this)->wend; i++)
-
- convgroupset_t dacs;
- convgroupset_t adcs;
- int running;
-
- int nmixers, maxmixers;
- size_t szmixers;
- mixer_item_t *mixers;
-
- struct audio_format *formats;
- int nformats;
- size_t szformats;
-
- uint32_t *extra;
- size_t szextra;
-} codec_t;
-
-
-int azalia_codec_init_vtbl(codec_t *);
-int azalia_codec_construct_format(codec_t *, int, int);
diff --git a/sys/dev/pci/azalia_codec.c b/sys/dev/pci/azalia_codec.c
deleted file mode 100644
index 5dad5e644c6..00000000000
--- a/sys/dev/pci/azalia_codec.c
+++ /dev/null
@@ -1,4278 +0,0 @@
-/* $NetBSD: azalia_codec.c,v 1.81 2017/07/28 01:36:41 nat Exp $ */
-
-/*-
- * Copyright (c) 2005, 2008 The NetBSD Foundation, Inc.
- * All rights reserved.
- *
- * This code is derived from software contributed to The NetBSD Foundation
- * by TAMURA Kent
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: azalia_codec.c,v 1.81 2017/07/28 01:36:41 nat Exp $");
-
-#include <sys/param.h>
-#include <sys/device.h>
-#include <sys/kmem.h>
-#include <sys/null.h>
-#include <sys/systm.h>
-
-#include <dev/pci/azalia.h>
-
-#ifdef MAX_VOLUME_255
-# define MIXER_DELTA(n) (AUDIO_MAX_GAIN / (n))
-#else
-# define MIXER_DELTA(n) (1)
-#endif
-#define AZ_CLASS_INPUT 0
-#define AZ_CLASS_OUTPUT 1
-#define AZ_CLASS_RECORD 2
-#define AZ_CLASS_PLAYBACK 3
-#define AZ_CLASS_MIXER 4
-#define AzaliaCplayback "playback"
-#define AzaliaCmixer "mix"
-#define AzaliaNfront "front"
-#define AzaliaNclfe "clfe"
-#define AzaliaNside "side"
-#define AzaliaNdigital "spdif"
-#define ENUM_OFFON .un.e={2, {{{AudioNoff, 0}, 0}, {{AudioNon, 0}, 1}}}
-#define ENUM_IO .un.e={2, {{{AudioNinput, 0}, 0}, {{AudioNoutput, 0}, 1}}}
-#define ENUM_V .un.v={{ "", 0 }, 0, 0 }
-#define AZ_MIXER_CLASSES \
- {{AZ_CLASS_INPUT, {AudioCinputs, 0}, AUDIO_MIXER_CLASS, \
- AZ_CLASS_INPUT, 0, 0, ENUM_V }, 0, 0, }, \
- {{AZ_CLASS_OUTPUT, {AudioCoutputs, 0}, AUDIO_MIXER_CLASS, \
- AZ_CLASS_OUTPUT, 0, 0, ENUM_V }, 0, 0, }, \
- {{AZ_CLASS_RECORD, {AudioCrecord, 0}, AUDIO_MIXER_CLASS, \
- AZ_CLASS_RECORD, 0, 0, ENUM_V }, 0, 0, }, \
- {{AZ_CLASS_PLAYBACK, {AzaliaCplayback, 0}, AUDIO_MIXER_CLASS, \
- AZ_CLASS_PLAYBACK, 0, 0, ENUM_V }, 0, 0, }, \
- {{AZ_CLASS_MIXER, {AzaliaCmixer, 0}, AUDIO_MIXER_CLASS, \
- AZ_CLASS_MIXER, 0, 0, ENUM_V }, 0, 0, }
-#define AZ_MIXER_SPDIF(cl, nid) \
- {{0, {AzaliaNdigital, 0}, AUDIO_MIXER_SET, cl, 0, 0, \
- .un.s={6, {{{"v", 0}, CORB_DCC_V}, {{"vcfg", 0}, CORB_DCC_VCFG}, \
- {{"pre", 0}, CORB_DCC_PRE}, {{"copy", 0}, CORB_DCC_COPY}, \
- {{"pro", 0}, CORB_DCC_PRO}, {{"l", 0}, CORB_DCC_L}}}}, \
- nid, MI_TARGET_SPDIF}, \
- {{0, {AzaliaNdigital".cc", 0}, AUDIO_MIXER_VALUE, cl, 0, 0, \
- .un.v={{"", 0}, 1, 1}}, nid, MI_TARGET_SPDIF_CC}
-
-
-static int generic_codec_init_dacgroup(codec_t *);
-static int generic_codec_add_dacgroup(codec_t *, int, uint32_t);
-static int generic_codec_find_pin(const codec_t *, int, int, uint32_t);
-static int generic_codec_find_dac(const codec_t *, int, int);
-
-static int generic_mixer_init(codec_t *);
-static int generic_mixer_autoinit(codec_t *);
-static int generic_mixer_init_widget(const codec_t *, widget_t *, nid_t);
-
-static int generic_mixer_fix_indexes(codec_t *);
-static int generic_mixer_default(codec_t *);
-static int generic_mixer_pin_sense(codec_t *);
-static int generic_mixer_widget_name(const codec_t *, widget_t *);
-static int generic_mixer_create_virtual(codec_t *);
-static int generic_mixer_delete(codec_t *);
-static void generic_mixer_cat_names
- (char *, size_t, const char *, const char *, const char *);
-static int generic_mixer_ensure_capacity(codec_t *, size_t);
-static int generic_mixer_get(const codec_t *, nid_t, int, mixer_ctrl_t *);
-static int generic_mixer_set(codec_t *, nid_t, int, const mixer_ctrl_t *);
-static int generic_mixer_pinctrl(codec_t *, nid_t, uint32_t);
-static u_char generic_mixer_from_device_value
- (const codec_t *, nid_t, int, uint32_t );
-static uint32_t generic_mixer_to_device_value
- (const codec_t *, nid_t, int, u_char);
-static uint32_t generic_mixer_max(const codec_t *, nid_t, int);
-static bool generic_mixer_validate_value
- (const codec_t *, nid_t, int, u_char);
-static int generic_set_port(codec_t *, mixer_ctrl_t *);
-static int generic_get_port(codec_t *, mixer_ctrl_t *);
-
-static int alc260_init_dacgroup(codec_t *);
-static int alc260_mixer_init(codec_t *);
-static int alc260_set_port(codec_t *, mixer_ctrl_t *);
-static int alc260_get_port(codec_t *, mixer_ctrl_t *);
-static int alc260_unsol_event(codec_t *, int);
-static int alc262_init_widget(const codec_t *, widget_t *, nid_t);
-static int alc268_init_dacgroup(codec_t *);
-static int alc662_init_dacgroup(codec_t *);
-static int alc861_init_dacgroup(codec_t *);
-static int alc861vdgr_init_dacgroup(codec_t *);
-static int alc880_init_dacgroup(codec_t *);
-static int alc880_mixer_init(codec_t *);
-static int alc882_init_dacgroup(codec_t *);
-static int alc882_mixer_init(codec_t *);
-static int alc882_set_port(codec_t *, mixer_ctrl_t *);
-static int alc882_get_port(codec_t *, mixer_ctrl_t *);
-static int alc883_init_dacgroup(codec_t *);
-static int alc883_mixer_init(codec_t *);
-static int alc885_init_dacgroup(codec_t *);
-static int alc888_init_dacgroup(codec_t *);
-static int alc888_init_widget(const codec_t *, widget_t *, nid_t);
-static int alc888_mixer_init(codec_t *);
-static int ad1981hd_init_widget(const codec_t *, widget_t *, nid_t);
-static int ad1981hd_mixer_init(codec_t *);
-static int ad1983_mixer_init(codec_t *);
-static int ad1983_unsol_event(codec_t *, int);
-static int ad1984_init_dacgroup(codec_t *);
-static int ad1984_init_widget(const codec_t *, widget_t *, nid_t);
-static int ad1984_mixer_init(codec_t *);
-static int ad1984_unsol_event(codec_t *, int);
-static int ad1986a_init_dacgroup(codec_t *);
-static int ad1986a_mixer_init(codec_t *);
-static int ad1988_init_dacgroup(codec_t *);
-static int cmi9880_init_dacgroup(codec_t *);
-static int cmi9880_mixer_init(codec_t *);
-static int stac9221_init_dacgroup(codec_t *);
-static int stac9221_mixer_init(codec_t *);
-static int stac9221_gpio_unmute(codec_t *, int);
-static int stac9200_mixer_init(codec_t *);
-static int stac9200_unsol_event(codec_t *, int);
-static int atihdmi_init_dacgroup(codec_t *);
-
-
-int
-azalia_codec_init_vtbl(codec_t *this)
-{
- size_t extra_size;
-
- /**
- * We can refer this->vid and this->subid.
- */
- DPRINTF(("%s: vid=%08x subid=%08x\n", __func__, this->vid, this->subid));
- extra_size = 0;
- this->name = NULL;
- this->init_dacgroup = generic_codec_init_dacgroup;
- this->mixer_init = generic_mixer_init;
- this->mixer_delete = generic_mixer_delete;
- this->set_port = generic_set_port;
- this->get_port = generic_get_port;
- this->unsol_event = NULL;
- switch (this->vid) {
- case 0x10027919:
- case 0x1002793c:
- this->name = "ATI RS600 HDMI";
- this->init_dacgroup = atihdmi_init_dacgroup;
- break;
- case 0x1002791a:
- this->name = "ATI RS690/780 HDMI";
- this->init_dacgroup = atihdmi_init_dacgroup;
- break;
- case 0x1002aa01:
- this->name = "ATI R600 HDMI";
- this->init_dacgroup = atihdmi_init_dacgroup;
- break;
- case 0x10ec0260:
- this->name = "Realtek ALC260";
- this->mixer_init = alc260_mixer_init;
- this->init_dacgroup = alc260_init_dacgroup;
- this->set_port = alc260_set_port;
- this->unsol_event = alc260_unsol_event;
- extra_size = 1;
- break;
- case 0x10ec0262:
- this->name = "Realtek ALC262";
- this->init_widget = alc262_init_widget;
- break;
- case 0x10ec0268:
- this->name = "Realtek ALC268";
- this->init_dacgroup = alc268_init_dacgroup;
- this->mixer_init = generic_mixer_autoinit;
- this->init_widget = generic_mixer_init_widget;
- break;
- case 0x10ec0269:
- this->name = "Realtek ALC269";
- this->mixer_init = generic_mixer_autoinit;
- this->init_widget = generic_mixer_init_widget;
- break;
- case 0x10ec0662:
- this->name = "Realtek ALC662-GR";
- this->init_dacgroup = alc662_init_dacgroup;
- this->mixer_init = generic_mixer_autoinit;
- this->init_widget = generic_mixer_init_widget;
- break;
- case 0x10ec0663:
- this->name = "Realtek ALC663";
- this->init_dacgroup = alc662_init_dacgroup;
- this->mixer_init = generic_mixer_autoinit;
- this->init_widget = generic_mixer_init_widget;
- break;
- case 0x10ec0861:
- this->name = "Realtek ALC861";
- this->init_dacgroup = alc861_init_dacgroup;
- break;
- case 0x10ec0862:
- this->name = "Realtek ALC861-VD-GR";
- this->init_dacgroup = alc861vdgr_init_dacgroup;
- break;
- case 0x10ec0880:
- this->name = "Realtek ALC880";
- this->init_dacgroup = alc880_init_dacgroup;
- this->mixer_init = alc880_mixer_init;
- break;
- case 0x10ec0882:
- this->name = "Realtek ALC882";
- this->init_dacgroup = alc882_init_dacgroup;
- this->mixer_init = alc882_mixer_init;
- this->get_port = alc882_get_port;
- this->set_port = alc882_set_port;
- break;
- case 0x10ec0883:
- /* ftp://209.216.61.149/pc/audio/ALC883_DataSheet_1.3.pdf */
- this->name = "Realtek ALC883";
- this->init_dacgroup = alc883_init_dacgroup;
- this->mixer_init = alc883_mixer_init;
- this->get_port = alc882_get_port;
- this->set_port = alc882_set_port;
- break;
- case 0x10ec0885:
- this->name = "Realtek ALC885";
- this->init_dacgroup = alc885_init_dacgroup;
- this->mixer_init = generic_mixer_autoinit;
- this->init_widget = generic_mixer_init_widget;
- break;
- case 0x10ec0888:
- this->name = "Realtek ALC888";
- this->init_dacgroup = alc888_init_dacgroup;
- this->init_widget = alc888_init_widget;
- this->mixer_init = alc888_mixer_init;
- break;
- case 0x11d41981:
- /* http://www.analog.com/en/prod/0,2877,AD1981HD,00.html */
- this->name = "Analog Devices AD1981HD";
- this->init_widget = ad1981hd_init_widget;
- this->mixer_init = ad1981hd_mixer_init;
- break;
- case 0x11d41983:
- /* http://www.analog.com/en/prod/0,2877,AD1983,00.html */
- this->name = "Analog Devices AD1983";
- this->mixer_init = ad1983_mixer_init;
- this->unsol_event = ad1983_unsol_event;
- break;
- case 0x11d41984:
- /* http://www.analog.com/en/prod/0,2877,AD1984,00.html */
- this->name = "Analog Devices AD1984";
- this->init_dacgroup = ad1984_init_dacgroup;
- this->init_widget = ad1984_init_widget;
- this->mixer_init = ad1984_mixer_init;
- this->unsol_event = ad1984_unsol_event;
- break;
- case 0x11d4194a:
- /* http://www.analog.com/static/imported-files/data_sheets/AD1984A.pdf */
- this->name = "Analog Devices AD1984A";
- this->init_dacgroup = ad1984_init_dacgroup;
- this->init_widget = ad1984_init_widget;
- this->mixer_init = ad1984_mixer_init;
- this->unsol_event = ad1984_unsol_event;
- break;
- case 0x11d41986:
- /* http://www.analog.com/en/prod/0,2877,AD1986A,00.html */
- this->name = "Analog Devices AD1986A";
- this->init_dacgroup = ad1986a_init_dacgroup;
- this->mixer_init = ad1986a_mixer_init;
- break;
- case 0x11d41988:
- /* http://www.analog.com/en/prod/0,2877,AD1988A,00.html */
- this->name = "Analog Devices AD1988A";
- this->init_dacgroup = ad1988_init_dacgroup;
- break;
- case 0x11d4198b:
- /* http://www.analog.com/en/prod/0,2877,AD1988B,00.html */
- this->name = "Analog Devices AD1988B";
- this->init_dacgroup = ad1988_init_dacgroup;
- break;
- case 0x434d4980:
- this->name = "CMedia CMI9880";
- this->init_dacgroup = cmi9880_init_dacgroup;
- this->mixer_init = cmi9880_mixer_init;
- break;
- case 0x83847612:
- /* http://www.idt.com/products/getDoc.cfm?docID=17122893 */
- this->name = "Sigmatel STAC9230X";
- break;
- case 0x83847613:
- /* http://www.idt.com/products/getDoc.cfm?docID=17122893 */
- this->name = "Sigmatel STAC9230D";
- break;
- case 0x83847614:
- /* http://www.idt.com/products/getDoc.cfm?docID=17122893 */
- this->name = "Sigmatel STAC9229X";
- break;
- case 0x83847615:
- /* http://www.idt.com/products/getDoc.cfm?docID=17122893 */
- this->name = "Sigmatel STAC9229D";
- break;
- case 0x83847616:
- /* http://www.idt.com/products/getDoc.cfm?docID=17122893 */
- this->name = "Sigmatel STAC9228X";
- break;
- case 0x83847617:
- /* http://www.idt.com/products/getDoc.cfm?docID=17122893 */
- this->name = "Sigmatel STAC9228D";
- break;
- case 0x83847618:
- /* http://www.idt.com/products/getDoc.cfm?docID=17122893 */
- this->name = "Sigmatel STAC9227X";
- break;
- case 0x83847619:
- /* http://www.idt.com/products/getDoc.cfm?docID=17122893 */
- this->name = "Sigmatel STAC9227D";
- break;
- case 0x83847680:
- this->name = "Sigmatel STAC9221";
- this->init_dacgroup = stac9221_init_dacgroup;
- this->mixer_init = stac9221_mixer_init;
- break;
- case 0x83847683:
- this->name = "Sigmatel STAC9221D";
- this->init_dacgroup = stac9221_init_dacgroup;
- break;
- case 0x83847690:
- /* http://www.idt.com/products/getDoc.cfm?docID=17812077 */
- this->name = "Sigmatel STAC9200";
- this->mixer_init = stac9200_mixer_init;
- this->unsol_event = stac9200_unsol_event;
- break;
- case 0x83847691:
- /* http://www.idt.com/products/getDoc.cfm?docID=17812077 */
- this->name = "Sigmatel STAC9200D";
- this->mixer_init = stac9200_mixer_init;
- this->unsol_event = stac9200_unsol_event;
- break;
- }
- if (extra_size > 0) {
- this->szextra = sizeof(uint32_t) * extra_size;
- this->extra = kmem_zalloc(this->szextra, KM_SLEEP);
- }
- return 0;
-}
-
-/* ----------------------------------------------------------------
- * functions for generic codecs
- * ---------------------------------------------------------------- */
-
-static int
-generic_codec_init_dacgroup(codec_t *this)
-{
- int i, j, assoc, group;
-
- /*
- * grouping DACs
- * [0] the lowest assoc DACs
- * [1] the lowest assoc digital outputs
- * [2] the 2nd assoc DACs
- * :
- */
- this->dacs.ngroups = 0;
- for (assoc = 0; assoc < CORB_CD_ASSOCIATION_MAX; assoc++) {
- generic_codec_add_dacgroup(this, assoc, 0);
- generic_codec_add_dacgroup(this, assoc, COP_AWCAP_DIGITAL);
- }
-
- /* find DACs which do not connect with any pins by default */
- DPRINTF(("%s: find non-connected DACs\n", __func__));
- FOR_EACH_WIDGET(this, i) {
- bool found;
-
- if (this->w[i].type != COP_AWTYPE_AUDIO_OUTPUT)
- continue;
- found = FALSE;
- for (group = 0; group < this->dacs.ngroups; group++) {
- for (j = 0; j < this->dacs.groups[group].nconv; j++) {
- if (i == this->dacs.groups[group].conv[j]) {
- found = TRUE;
- group = this->dacs.ngroups;
- break;
- }
- }
- }
- if (found)
- continue;
- if (this->dacs.ngroups >= 32)
- break;
- this->dacs.groups[this->dacs.ngroups].nconv = 1;
- this->dacs.groups[this->dacs.ngroups].conv[0] = i;
- this->dacs.ngroups++;
- }
- this->dacs.cur = 0;
-
- /* enumerate ADCs */
- this->adcs.ngroups = 0;
- FOR_EACH_WIDGET(this, i) {
- if (this->w[i].type != COP_AWTYPE_AUDIO_INPUT)
- continue;
- this->adcs.groups[this->adcs.ngroups].nconv = 1;
- this->adcs.groups[this->adcs.ngroups].conv[0] = i;
- this->adcs.ngroups++;
- if (this->adcs.ngroups >= 32)
- break;
- }
- this->adcs.cur = 0;
- return 0;
-}
-
-static int
-generic_codec_add_dacgroup(codec_t *this, int assoc, uint32_t digital)
-{
- int i, j, n, dac, seq;
-
- n = 0;
- for (seq = 0 ; seq < CORB_CD_SEQUENCE_MAX; seq++) {
- i = generic_codec_find_pin(this, assoc, seq, digital);
- if (i < 0)
- continue;
- dac = generic_codec_find_dac(this, i, 0);
- if (dac < 0)
- continue;
- /* duplication check */
- for (j = 0; j < n; j++) {
- if (this->dacs.groups[this->dacs.ngroups].conv[j] == dac)
- break;
- }
- if (j < n) /* this group already has <dac> */
- continue;
- this->dacs.groups[this->dacs.ngroups].conv[n++] = dac;
- DPRINTF(("%s: assoc=%d seq=%d ==> g=%d n=%d\n",
- __func__, assoc, seq, this->dacs.ngroups, n-1));
- }
- if (n <= 0) /* no such DACs */
- return 0;
- this->dacs.groups[this->dacs.ngroups].nconv = n;
-
- /* check if the same combination is already registered */
- for (i = 0; i < this->dacs.ngroups; i++) {
- if (n != this->dacs.groups[i].nconv)
- continue;
- for (j = 0; j < n; j++) {
- if (this->dacs.groups[this->dacs.ngroups].conv[j] !=
- this->dacs.groups[i].conv[j])
- break;
- }
- if (j >= n) /* matched */
- return 0;
- }
- /* found no equivalent group */
- this->dacs.ngroups++;
- return 0;
-}
-
-static int
-generic_codec_find_pin(const codec_t *this, int assoc, int seq, uint32_t digital)
-{
- int i;
-
- FOR_EACH_WIDGET(this, i) {
- if (this->w[i].type != COP_AWTYPE_PIN_COMPLEX)
- continue;
- if ((this->w[i].d.pin.cap & COP_PINCAP_OUTPUT) == 0)
- continue;
- if ((this->w[i].widgetcap & COP_AWCAP_DIGITAL) != digital)
- continue;
- if (this->w[i].d.pin.association != assoc)
- continue;
- if (this->w[i].d.pin.sequence == seq) {
- return i;
- }
- }
- return -1;
-}
-
-static int
-generic_codec_find_dac(const codec_t *this, int index, int depth)
-{
- const widget_t *w;
- int i, j, ret;
-
- w = &this->w[index];
- if (w->type == COP_AWTYPE_AUDIO_OUTPUT) {
- DPRINTF(("%s: DAC: nid=0x%x index=%d\n",
- __func__, w->nid, index));
- return index;
- }
- if (++depth > 50) {
- return -1;
- }
- if (w->selected >= 0) {
- j = w->connections[w->selected];
- if (VALID_WIDGET_NID(j, this)) {
- ret = generic_codec_find_dac(this, j, depth);
- if (ret >= 0) {
- DPRINTF(("%s: DAC path: nid=0x%x index=%d\n",
- __func__, w->nid, index));
- return ret;
- }
- }
- }
- for (i = 0; i < w->nconnections; i++) {
- j = w->connections[i];
- if (!VALID_WIDGET_NID(j, this))
- continue;
- ret = generic_codec_find_dac(this, j, depth);
- if (ret >= 0) {
- DPRINTF(("%s: DAC path: nid=0x%x index=%d\n",
- __func__, w->nid, index));
- return ret;
- }
- }
- return -1;
-}
-
-/* ----------------------------------------------------------------
- * Generic mixer functions
- * ---------------------------------------------------------------- */
-
-#define GMIDPRINTF(x) do {} while (0/*CONSTCOND*/)
-
-static int
-generic_mixer_init(codec_t *this)
-{
- /*
- * pin "<color>%2.2x"
- * audio output "dac%2.2x"
- * audio input "adc%2.2x"
- * mixer "mixer%2.2x"
- * selector "sel%2.2x"
- */
- mixer_item_t *m;
- int err, i, j, k;
-
- this->maxmixers = 10;
- this->nmixers = 0;
- this->szmixers = sizeof(mixer_item_t) * this->maxmixers;
- this->mixers = kmem_zalloc(this->szmixers, KM_SLEEP);
-
- /* register classes */
- DPRINTF(("%s: register classes\n", __func__));
- m = &this->mixers[AZ_CLASS_INPUT];
- m->devinfo.index = AZ_CLASS_INPUT;
- strlcpy(m->devinfo.label.name, AudioCinputs,
- sizeof(m->devinfo.label.name));
- m->devinfo.type = AUDIO_MIXER_CLASS;
- m->devinfo.mixer_class = AZ_CLASS_INPUT;
- m->devinfo.next = AUDIO_MIXER_LAST;
- m->devinfo.prev = AUDIO_MIXER_LAST;
- m->nid = 0;
-
- m = &this->mixers[AZ_CLASS_OUTPUT];
- m->devinfo.index = AZ_CLASS_OUTPUT;
- strlcpy(m->devinfo.label.name, AudioCoutputs,
- sizeof(m->devinfo.label.name));
- m->devinfo.type = AUDIO_MIXER_CLASS;
- m->devinfo.mixer_class = AZ_CLASS_OUTPUT;
- m->devinfo.next = AUDIO_MIXER_LAST;
- m->devinfo.prev = AUDIO_MIXER_LAST;
- m->nid = 0;
-
- m = &this->mixers[AZ_CLASS_RECORD];
- m->devinfo.index = AZ_CLASS_RECORD;
- strlcpy(m->devinfo.label.name, AudioCrecord,
- sizeof(m->devinfo.label.name));
- m->devinfo.type = AUDIO_MIXER_CLASS;
- m->devinfo.mixer_class = AZ_CLASS_RECORD;
- m->devinfo.next = AUDIO_MIXER_LAST;
- m->devinfo.prev = AUDIO_MIXER_LAST;
- m->nid = 0;
-
- m = &this->mixers[AZ_CLASS_PLAYBACK];
- m->devinfo.index = AZ_CLASS_PLAYBACK;
- strlcpy(m->devinfo.label.name, AzaliaCplayback,
- sizeof(m->devinfo.label.name));
- m->devinfo.type = AUDIO_MIXER_CLASS;
- m->devinfo.mixer_class = AZ_CLASS_PLAYBACK;
- m->devinfo.next = AUDIO_MIXER_LAST;
- m->devinfo.prev = AUDIO_MIXER_LAST;
- m->nid = 0;
-
- m = &this->mixers[AZ_CLASS_MIXER];
- m->devinfo.index = AZ_CLASS_MIXER;
- strlcpy(m->devinfo.label.name, AzaliaCmixer,
- sizeof(m->devinfo.label.name));
- m->devinfo.type = AUDIO_MIXER_CLASS;
- m->devinfo.mixer_class = AZ_CLASS_MIXER;
- m->devinfo.next = AUDIO_MIXER_LAST;
- m->devinfo.prev = AUDIO_MIXER_LAST;
- m->nid = 0;
-
- this->nmixers = AZ_CLASS_MIXER + 1;
-
-#define MIXER_REG_PROLOG \
- mixer_devinfo_t *d; \
- err = generic_mixer_ensure_capacity(this, this->nmixers + 1); \
- if (err) \
- return err; \
- m = &this->mixers[this->nmixers]; \
- d = &m->devinfo; \
- m->nid = i
-
- FOR_EACH_WIDGET(this, i) {
- const widget_t *w;
-
- w = &this->w[i];
-
- /* skip unconnected pins */
- if (w->type == COP_AWTYPE_PIN_COMPLEX) {
- uint8_t conn =
- (w->d.pin.config & CORB_CD_PORT_MASK) >> 30;
- if (conn == 1) /* no physical connection */
- continue;
- }
-
- /* selector */
- if (w->type != COP_AWTYPE_AUDIO_MIXER &&
- w->type != COP_AWTYPE_POWER && w->nconnections >= 2) {
- MIXER_REG_PROLOG;
- GMIDPRINTF(("%s: selector %s\n", __func__, w->name));
- snprintf(d->label.name, sizeof(d->label.name),
- "%s.source", w->name);
- d->type = AUDIO_MIXER_ENUM;
- if (w->type == COP_AWTYPE_AUDIO_MIXER)
- d->mixer_class = AZ_CLASS_RECORD;
- else if (w->type == COP_AWTYPE_AUDIO_SELECTOR)
- d->mixer_class = AZ_CLASS_INPUT;
- else
- d->mixer_class = AZ_CLASS_OUTPUT;
- m->target = MI_TARGET_CONNLIST;
- for (j = 0, k = 0; j < w->nconnections && k < 32; j++) {
- uint8_t conn;
-
- if (!VALID_WIDGET_NID(w->connections[j], this))
- continue;
- /* skip unconnected pins */
- PIN_STATUS(&this->w[w->connections[j]],
- conn);
- if (conn == 1)
- continue;
- GMIDPRINTF(("%s: selector %d=%s\n", __func__, j,
- this->w[w->connections[j]].name));
- d->un.e.member[k].ord = j;
- strlcpy(d->un.e.member[k].label.name,
- this->w[w->connections[j]].name,
- MAX_AUDIO_DEV_LEN);
- k++;
- }
- d->un.e.num_mem = k;
- this->nmixers++;
- }
-
- /* output mute */
- if (w->widgetcap & COP_AWCAP_OUTAMP &&
- w->outamp_cap & COP_AMPCAP_MUTE) {
- MIXER_REG_PROLOG;
- GMIDPRINTF(("%s: output mute %s\n", __func__, w->name));
- snprintf(d->label.name, sizeof(d->label.name),
- "%s.mute", w->name);
- d->type = AUDIO_MIXER_ENUM;
- if (w->type == COP_AWTYPE_AUDIO_MIXER)
- d->mixer_class = AZ_CLASS_MIXER;
- else if (w->type == COP_AWTYPE_AUDIO_SELECTOR)
- d->mixer_class = AZ_CLASS_OUTPUT;
- else if (w->type == COP_AWTYPE_PIN_COMPLEX)
- d->mixer_class = AZ_CLASS_OUTPUT;
- else
- d->mixer_class = AZ_CLASS_INPUT;
- m->target = MI_TARGET_OUTAMP;
- d->un.e.num_mem = 2;
- d->un.e.member[0].ord = 0;
- strlcpy(d->un.e.member[0].label.name, AudioNoff,
- MAX_AUDIO_DEV_LEN);
- d->un.e.member[1].ord = 1;
- strlcpy(d->un.e.member[1].label.name, AudioNon,
- MAX_AUDIO_DEV_LEN);
- this->nmixers++;
- }
-
- /* output gain */
- if (w->widgetcap & COP_AWCAP_OUTAMP
- && COP_AMPCAP_NUMSTEPS(w->outamp_cap)) {
- MIXER_REG_PROLOG;
- GMIDPRINTF(("%s: output gain %s\n", __func__, w->name));
- snprintf(d->label.name, sizeof(d->label.name),
- "%s", w->name);
- d->type = AUDIO_MIXER_VALUE;
- if (w->type == COP_AWTYPE_AUDIO_MIXER)
- d->mixer_class = AZ_CLASS_MIXER;
- else if (w->type == COP_AWTYPE_AUDIO_SELECTOR)
- d->mixer_class = AZ_CLASS_OUTPUT;
- else if (w->type == COP_AWTYPE_PIN_COMPLEX)
- d->mixer_class = AZ_CLASS_OUTPUT;
- else
- d->mixer_class = AZ_CLASS_INPUT;
- m->target = MI_TARGET_OUTAMP;
- d->un.v.num_channels = WIDGET_CHANNELS(w);
-#ifdef MAX_VOLUME_255
- d->un.v.units.name[0] = 0;
-#else
- snprintf(d->un.v.units.name, sizeof(d->un.v.units.name),
- "0.25x%ddB", COP_AMPCAP_STEPSIZE(w->outamp_cap)+1);
-#endif
- d->un.v.delta =
- MIXER_DELTA(COP_AMPCAP_NUMSTEPS(w->outamp_cap));
- this->nmixers++;
- }
-
- /* input mute */
- if (w->widgetcap & COP_AWCAP_INAMP &&
- w->inamp_cap & COP_AMPCAP_MUTE) {
- GMIDPRINTF(("%s: input mute %s\n", __func__, w->name));
- if (w->type != COP_AWTYPE_AUDIO_SELECTOR &&
- w->type != COP_AWTYPE_AUDIO_MIXER) {
- MIXER_REG_PROLOG;
- snprintf(d->label.name, sizeof(d->label.name),
- "%s.mute", w->name);
- d->type = AUDIO_MIXER_ENUM;
- if (w->type == COP_AWTYPE_PIN_COMPLEX)
- d->mixer_class = AZ_CLASS_OUTPUT;
- else if (w->type == COP_AWTYPE_AUDIO_INPUT)
- d->mixer_class = AZ_CLASS_RECORD;
- else
- d->mixer_class = AZ_CLASS_INPUT;
- m->target = 0;
- d->un.e.num_mem = 2;
- d->un.e.member[0].ord = 0;
- strlcpy(d->un.e.member[0].label.name,
- AudioNoff, MAX_AUDIO_DEV_LEN);
- d->un.e.member[1].ord = 1;
- strlcpy(d->un.e.member[1].label.name,
- AudioNon, MAX_AUDIO_DEV_LEN);
- this->nmixers++;
- } else {
- uint8_t conn;
-
- for (j = 0; j < w->nconnections; j++) {
- MIXER_REG_PROLOG;
- if (!VALID_WIDGET_NID(w->connections[j], this))
- continue;
-
- /* skip unconnected pins */
- PIN_STATUS(&this->w[w->connections[j]],
- conn);
- if (conn == 1)
- continue;
-
- GMIDPRINTF(("%s: input mute %s.%s\n", __func__,
- w->name, this->w[w->connections[j]].name));
- generic_mixer_cat_names(
- d->label.name,
- sizeof(d->label.name),
- w->name, this->w[w->connections[j]].name,
- "mute");
- d->type = AUDIO_MIXER_ENUM;
- if (w->type == COP_AWTYPE_PIN_COMPLEX)
- d->mixer_class = AZ_CLASS_OUTPUT;
- else if (w->type == COP_AWTYPE_AUDIO_INPUT)
- d->mixer_class = AZ_CLASS_RECORD;
- else if (w->type == COP_AWTYPE_AUDIO_MIXER)
- d->mixer_class = AZ_CLASS_MIXER;
- else
- d->mixer_class = AZ_CLASS_INPUT;
- m->target = j;
- d->un.e.num_mem = 2;
- d->un.e.member[0].ord = 0;
- strlcpy(d->un.e.member[0].label.name,
- AudioNoff, MAX_AUDIO_DEV_LEN);
- d->un.e.member[1].ord = 1;
- strlcpy(d->un.e.member[1].label.name,
- AudioNon, MAX_AUDIO_DEV_LEN);
- this->nmixers++;
- }
- }
- }
-
- /* input gain */
- if (w->widgetcap & COP_AWCAP_INAMP
- && COP_AMPCAP_NUMSTEPS(w->inamp_cap)) {
- GMIDPRINTF(("%s: input gain %s\n", __func__, w->name));
- if (w->type != COP_AWTYPE_AUDIO_SELECTOR &&
- w->type != COP_AWTYPE_AUDIO_MIXER) {
- MIXER_REG_PROLOG;
- snprintf(d->label.name, sizeof(d->label.name),
- "%s", w->name);
- d->type = AUDIO_MIXER_VALUE;
- if (w->type == COP_AWTYPE_PIN_COMPLEX)
- d->mixer_class = AZ_CLASS_OUTPUT;
- else if (w->type == COP_AWTYPE_AUDIO_INPUT)
- d->mixer_class = AZ_CLASS_RECORD;
- else
- d->mixer_class = AZ_CLASS_INPUT;
- m->target = 0;
- d->un.v.num_channels = WIDGET_CHANNELS(w);
-#ifdef MAX_VOLUME_255
- d->un.v.units.name[0] = 0;
-#else
- snprintf(d->un.v.units.name,
- sizeof(d->un.v.units.name), "0.25x%ddB",
- COP_AMPCAP_STEPSIZE(w->inamp_cap)+1);
-#endif
- d->un.v.delta =
- MIXER_DELTA(COP_AMPCAP_NUMSTEPS(w->inamp_cap));
- this->nmixers++;
- } else {
- uint8_t conn;
-
- for (j = 0; j < w->nconnections; j++) {
- MIXER_REG_PROLOG;
- if (!VALID_WIDGET_NID(w->connections[j], this))
- continue;
- /* skip unconnected pins */
- PIN_STATUS(&this->w[w->connections[j]],
- conn);
- if (conn == 1)
- continue;
- GMIDPRINTF(("%s: input gain %s.%s\n", __func__,
- w->name, this->w[w->connections[j]].name));
- snprintf(d->label.name, sizeof(d->label.name),
- "%s.%s", w->name,
- this->w[w->connections[j]].name);
- d->type = AUDIO_MIXER_VALUE;
- if (w->type == COP_AWTYPE_PIN_COMPLEX)
- d->mixer_class = AZ_CLASS_OUTPUT;
- else if (w->type == COP_AWTYPE_AUDIO_INPUT)
- d->mixer_class = AZ_CLASS_RECORD;
- else if (w->type == COP_AWTYPE_AUDIO_MIXER)
- d->mixer_class = AZ_CLASS_MIXER;
- else
- d->mixer_class = AZ_CLASS_INPUT;
- m->target = j;
- d->un.v.num_channels = WIDGET_CHANNELS(w);
-#ifdef MAX_VOLUME_255
- d->un.v.units.name[0] = 0;
-#else
- snprintf(d->un.v.units.name,
- sizeof(d->un.v.units.name), "0.25x%ddB",
- COP_AMPCAP_STEPSIZE(w->inamp_cap)+1);
-#endif
- d->un.v.delta =
- MIXER_DELTA(COP_AMPCAP_NUMSTEPS(w->inamp_cap));
- this->nmixers++;
- }
- }
- }
-
- /* pin direction */
- if (w->type == COP_AWTYPE_PIN_COMPLEX &&
- w->d.pin.cap & COP_PINCAP_OUTPUT &&
- w->d.pin.cap & COP_PINCAP_INPUT) {
- MIXER_REG_PROLOG;
- GMIDPRINTF(("%s: pin dir %s\n", __func__, w->name));
- snprintf(d->label.name, sizeof(d->label.name),
- "%s.dir", w->name);
- d->type = AUDIO_MIXER_ENUM;
- d->mixer_class = AZ_CLASS_OUTPUT;
- m->target = MI_TARGET_PINDIR;
- d->un.e.num_mem = 2;
- d->un.e.member[0].ord = 0;
- strlcpy(d->un.e.member[0].label.name, AudioNinput,
- MAX_AUDIO_DEV_LEN);
- d->un.e.member[1].ord = 1;
- strlcpy(d->un.e.member[1].label.name, AudioNoutput,
- MAX_AUDIO_DEV_LEN);
- this->nmixers++;
- }
-
- /* pin headphone-boost */
- if (w->type == COP_AWTYPE_PIN_COMPLEX &&
- w->d.pin.cap & COP_PINCAP_HEADPHONE) {
- MIXER_REG_PROLOG;
- GMIDPRINTF(("%s: hpboost %s\n", __func__, w->name));
- snprintf(d->label.name, sizeof(d->label.name),
- "%s.boost", w->name);
- d->type = AUDIO_MIXER_ENUM;
- d->mixer_class = AZ_CLASS_OUTPUT;
- m->target = MI_TARGET_PINBOOST;
- d->un.e.num_mem = 2;
- d->un.e.member[0].ord = 0;
- strlcpy(d->un.e.member[0].label.name, AudioNoff,
- MAX_AUDIO_DEV_LEN);
- d->un.e.member[1].ord = 1;
- strlcpy(d->un.e.member[1].label.name, AudioNon,
- MAX_AUDIO_DEV_LEN);
- this->nmixers++;
- }
-
- if (w->type == COP_AWTYPE_PIN_COMPLEX &&
- w->d.pin.cap & COP_PINCAP_EAPD) {
- MIXER_REG_PROLOG;
- GMIDPRINTF(("%s: eapd %s\n", __func__, w->name));
- snprintf(d->label.name, sizeof(d->label.name),
- "%s.eapd", w->name);
- d->type = AUDIO_MIXER_ENUM;
- d->mixer_class = AZ_CLASS_OUTPUT;
- m->target = MI_TARGET_EAPD;
- d->un.e.num_mem = 2;
- d->un.e.member[0].ord = 0;
- strlcpy(d->un.e.member[0].label.name, AudioNoff,
- MAX_AUDIO_DEV_LEN);
- d->un.e.member[1].ord = 1;
- strlcpy(d->un.e.member[1].label.name, AudioNon,
- MAX_AUDIO_DEV_LEN);
- this->nmixers++;
- }
-
- if (w->type == COP_AWTYPE_PIN_COMPLEX &&
- w->d.pin.cap & COP_PINCAP_BALANCE) {
- MIXER_REG_PROLOG;
- GMIDPRINTF(("%s: balance %s\n", __func__, w->name));
- snprintf(d->label.name, sizeof(d->label.name),
- "%s.balance", w->name);
- d->type = AUDIO_MIXER_ENUM;
- if (w->type == COP_AWTYPE_PIN_COMPLEX)
- d->mixer_class = AZ_CLASS_OUTPUT;
- else if (w->type == COP_AWTYPE_AUDIO_INPUT)
- d->mixer_class = AZ_CLASS_RECORD;
- else
- d->mixer_class = AZ_CLASS_INPUT;
- m->target = MI_TARGET_BALANCE;
- d->un.e.num_mem = 2;
- d->un.e.member[0].ord = 0;
- strlcpy(d->un.e.member[0].label.name, AudioNoff,
- MAX_AUDIO_DEV_LEN);
- d->un.e.member[1].ord = 1;
- strlcpy(d->un.e.member[1].label.name, AudioNon,
- MAX_AUDIO_DEV_LEN);
- this->nmixers++;
- }
-
- if (w->widgetcap & COP_AWCAP_LRSWAP) {
- MIXER_REG_PROLOG;
- GMIDPRINTF(("%s: lrswap %s\n", __func__, w->name));
- snprintf(d->label.name, sizeof(d->label.name),
- "%s.lrswap", w->name);
- d->type = AUDIO_MIXER_ENUM;
- if (w->type == COP_AWTYPE_PIN_COMPLEX)
- d->mixer_class = AZ_CLASS_OUTPUT;
- else if (w->type == COP_AWTYPE_AUDIO_INPUT)
- d->mixer_class = AZ_CLASS_RECORD;
- else
- d->mixer_class = AZ_CLASS_INPUT;
- m->target = MI_TARGET_LRSWAP;
- d->un.e.num_mem = 2;
- d->un.e.member[0].ord = 0;
- strlcpy(d->un.e.member[0].label.name, AudioNoff,
- MAX_AUDIO_DEV_LEN);
- d->un.e.member[1].ord = 1;
- strlcpy(d->un.e.member[1].label.name, AudioNon,
- MAX_AUDIO_DEV_LEN);
- this->nmixers++;
- }
-
- /* volume knob */
- if (w->type == COP_AWTYPE_VOLUME_KNOB &&
- w->d.volume.cap & COP_VKCAP_DELTA) {
- MIXER_REG_PROLOG;
- GMIDPRINTF(("%s: volume knob %s\n", __func__, w->name));
- strlcpy(d->label.name, w->name, sizeof(d->label.name));
- d->type = AUDIO_MIXER_VALUE;
- d->mixer_class = AZ_CLASS_OUTPUT;
- m->target = MI_TARGET_VOLUME;
- d->un.v.num_channels = 1;
- d->un.v.units.name[0] = 0;
- d->un.v.delta =
- MIXER_DELTA(COP_VKCAP_NUMSTEPS(w->d.volume.cap));
- this->nmixers++;
- }
- }
-
- /* if the codec has multiple DAC groups, create "playback.mode" */
- if (this->dacs.ngroups > 1) {
- MIXER_REG_PROLOG;
- GMIDPRINTF(("%s: create playback.mode\n", __func__));
- strlcpy(d->label.name, AudioNmode, sizeof(d->label.name));
- d->type = AUDIO_MIXER_ENUM;
- d->mixer_class = AZ_CLASS_PLAYBACK;
- m->target = MI_TARGET_DAC;
- for (i = 0; i < this->dacs.ngroups && i < 32; i++) {
- d->un.e.member[i].ord = i;
- for (j = 0; j < this->dacs.groups[i].nconv; j++) {
- if (j * 2 >= MAX_AUDIO_DEV_LEN)
- break;
- snprintf(d->un.e.member[i].label.name + j*2,
- MAX_AUDIO_DEV_LEN - j*2, "%2.2x",
- this->dacs.groups[i].conv[j]);
- }
- }
- d->un.e.num_mem = i;
- this->nmixers++;
- }
-
- /* if the codec has multiple ADC groups, create "record.mode" */
- if (this->adcs.ngroups > 1) {
- MIXER_REG_PROLOG;
- GMIDPRINTF(("%s: create record.mode\n", __func__));
- strlcpy(d->label.name, AudioNmode, sizeof(d->label.name));
- d->type = AUDIO_MIXER_ENUM;
- d->mixer_class = AZ_CLASS_RECORD;
- m->target = MI_TARGET_ADC;
- for (i = 0; i < this->adcs.ngroups && i < 32; i++) {
- d->un.e.member[i].ord = i;
- for (j = 0; j < this->adcs.groups[i].nconv; j++) {
- if (j * 2 >= MAX_AUDIO_DEV_LEN)
- break;
- snprintf(d->un.e.member[i].label.name + j*2,
- MAX_AUDIO_DEV_LEN - j*2, "%2.2x",
- this->adcs.groups[i].conv[j]);
- }
- }
- d->un.e.num_mem = i;
- this->nmixers++;
- }
-
- generic_mixer_fix_indexes(this);
- generic_mixer_default(this);
- return 0;
-}
-
-static void
-generic_mixer_cat_names(char *dst, size_t dstsize,
- const char *str1, const char *str2, const char *str3)
-{
- const char *last2;
- size_t len1, len2, len3, total;
-
- len1 = strlen(str1);
- len2 = strlen(str2);
- len3 = strlen(str3);
- total = len1 + 1 + len2 + 1 + len3 + 1;
- if (total - (len3 - 1) <= dstsize) {
- snprintf(dst, dstsize, "%s.%s.%s", str1, str2, str3);
- return;
- }
- last2 = len2 > 2 ? str2 + len2 - 2 : str2;
- if (len2 > 4) {
- snprintf(dst, dstsize, "%s.%.2s%s.%s", str1, str2, last2, str3);
- return;
- }
- snprintf(dst, dstsize, "%s.%s.%s", str1, last2, str3);
-}
-
-static int
-generic_mixer_ensure_capacity(codec_t *this, size_t newsize)
-{
- size_t newmax;
- size_t newsz;
- void *newbuf;
-
- if (this->maxmixers >= newsize)
- return 0;
- newmax = this->maxmixers + 10;
- if (newmax < newsize)
- newmax = newsize;
- newsz = sizeof(mixer_item_t) * newmax;
- newbuf = kmem_zalloc(newsz, KM_SLEEP);
- memcpy(newbuf, this->mixers, this->szmixers);
- kmem_free(this->mixers, this->szmixers);
- this->mixers = newbuf;
- this->szmixers = newsize;
- this->maxmixers = newmax;
- return 0;
-}
-
-static int
-generic_mixer_fix_indexes(codec_t *this)
-{
- int i;
- mixer_devinfo_t *d;
-
- for (i = 0; i < this->nmixers; i++) {
- d = &this->mixers[i].devinfo;
-#ifdef DIAGNOSTIC
- if (d->index != 0 && d->index != i)
- aprint_error("%s: index mismatch %d %d\n", __func__,
- d->index, i);
-#endif
- d->index = i;
- if (d->prev == 0)
- d->prev = AUDIO_MIXER_LAST;
- if (d->next == 0)
- d->next = AUDIO_MIXER_LAST;
- }
- return 0;
-}
-
-static int
-generic_mixer_default(codec_t *this)
-{
- int i;
- mixer_item_t *m;
- /* unmute all */
- DPRINTF(("%s: unmute\n", __func__));
- for (i = 0; i < this->nmixers; i++) {
- mixer_ctrl_t mc;
-
- m = &this->mixers[i];
- if (!IS_MI_TARGET_INAMP(m->target) &&
- m->target != MI_TARGET_OUTAMP)
- continue;
- if (m->devinfo.type != AUDIO_MIXER_ENUM)
- continue;
- mc.dev = i;
- mc.type = AUDIO_MIXER_ENUM;
- mc.un.ord = 0;
- generic_mixer_set(this, m->nid, m->target, &mc);
- }
-
- /*
- * For bidirectional pins, make the default `output'
- */
- DPRINTF(("%s: process bidirectional pins\n", __func__));
- for (i = 0; i < this->nmixers; i++) {
- mixer_ctrl_t mc;
-
- m = &this->mixers[i];
- if (m->target != MI_TARGET_PINDIR)
- continue;
- mc.dev = i;
- mc.type = AUDIO_MIXER_ENUM;
- mc.un.ord = 1; /* output */
- generic_mixer_set(this, m->nid, m->target, &mc);
- }
-
- /* set unextreme volume */
- DPRINTF(("%s: set volume\n", __func__));
- for (i = 0; i < this->nmixers; i++) {
- mixer_ctrl_t mc;
-
- m = &this->mixers[i];
- if (!IS_MI_TARGET_INAMP(m->target) &&
- m->target != MI_TARGET_OUTAMP &&
- m->target != MI_TARGET_VOLUME)
- continue;
- if (m->devinfo.type != AUDIO_MIXER_VALUE)
- continue;
- mc.dev = i;
- mc.type = AUDIO_MIXER_VALUE;
- mc.un.value.num_channels = 1;
- mc.un.value.level[0] = AUDIO_MAX_GAIN / 2;
- if (m->target != MI_TARGET_VOLUME &&
- WIDGET_CHANNELS(&this->w[m->nid]) == 2) {
- mc.un.value.num_channels = 2;
- mc.un.value.level[1] = AUDIO_MAX_GAIN / 2;
- }
- generic_mixer_set(this, m->nid, m->target, &mc);
- }
-
- return 0;
-}
-
-static int
-generic_mixer_pin_sense(codec_t *this)
-{
- typedef enum {
- PIN_DIR_IN,
- PIN_DIR_OUT,
- PIN_DIR_MIC
- } pintype_t;
- const widget_t *w;
- int i;
-
- FOR_EACH_WIDGET(this, i) {
- pintype_t pintype = PIN_DIR_IN;
-
- w = &this->w[i];
- if (w->type != COP_AWTYPE_PIN_COMPLEX)
- continue;
- if (!(w->d.pin.cap & COP_PINCAP_INPUT))
- pintype = PIN_DIR_OUT;
- if (!(w->d.pin.cap & COP_PINCAP_OUTPUT))
- pintype = PIN_DIR_IN;
-
- switch (w->d.pin.device) {
- case CORB_CD_LINEOUT:
- case CORB_CD_SPEAKER:
- case CORB_CD_HEADPHONE:
- case CORB_CD_SPDIFOUT:
- case CORB_CD_DIGITALOUT:
- pintype = PIN_DIR_OUT;
- break;
- case CORB_CD_CD:
- case CORB_CD_LINEIN:
- pintype = PIN_DIR_IN;
- break;
- case CORB_CD_MICIN:
- pintype = PIN_DIR_MIC;
- break;
- }
-
- switch (pintype) {
- case PIN_DIR_IN:
- this->comresp(this, w->nid,
- CORB_SET_PIN_WIDGET_CONTROL,
- CORB_PWC_INPUT, NULL);
- break;
- case PIN_DIR_OUT:
- this->comresp(this, w->nid,
- CORB_SET_PIN_WIDGET_CONTROL,
- CORB_PWC_OUTPUT, NULL);
- break;
- case PIN_DIR_MIC:
- this->comresp(this, w->nid,
- CORB_SET_PIN_WIDGET_CONTROL,
- CORB_PWC_INPUT|CORB_PWC_VREF_80, NULL);
- break;
- }
-
- if (w->d.pin.cap & COP_PINCAP_EAPD) {
- uint32_t result;
- int err;
-
- err = this->comresp(this, w->nid,
- CORB_GET_EAPD_BTL_ENABLE, 0, &result);
- if (err)
- continue;
- result &= 0xff;
- result |= CORB_EAPD_EAPD;
- err = this->comresp(this, w->nid,
- CORB_SET_EAPD_BTL_ENABLE, result, &result);
- if (err)
- continue;
- }
- }
-
- return 0;
-}
-
-static int
-generic_mixer_widget_name(const codec_t *this, widget_t *w)
-{
- const char *name = NULL, *grossloc = "", *geoloc = "";
- uint8_t grosslocval, geolocval;
-
- if (w->type != COP_AWTYPE_PIN_COMPLEX)
- return 0;
-
- switch (w->d.pin.device) {
- case CORB_CD_LINEOUT: name = "lineout"; break;
- case CORB_CD_SPEAKER: name = "spkr"; break;
- case CORB_CD_HEADPHONE: name = "hp"; break;
- case CORB_CD_CD: name = AudioNcd; break;
- case CORB_CD_SPDIFOUT: name = "spdifout"; break;
- case CORB_CD_DIGITALOUT: name = "digout"; break;
- case CORB_CD_MODEMLINE: name = "modemline"; break;
- case CORB_CD_MODEMHANDSET: name = "modemhset"; break;
- case CORB_CD_LINEIN: name = "linein"; break;
- case CORB_CD_AUX: name = AudioNaux; break;
- case CORB_CD_MICIN: name = AudioNmicrophone; break;
- case CORB_CD_TELEPHONY: name = "telephony"; break;
- case CORB_CD_SPDIFIN: name = "spdifin"; break;
- case CORB_CD_DIGITALIN: name = "digin"; break;
- case CORB_CD_DEVICE_OTHER: name = "reserved"; break;
- default: name = "unused"; break;
- }
-
- grosslocval = ((w->d.pin.config & CORB_CD_LOCATION_MASK) >> 24) & 0xf;
- geolocval = (w->d.pin.config & CORB_CD_LOCATION_MASK) >> 28;
-
- switch (geolocval) {
- case 0x00: /* external on primary chassis */
- case 0x10: /* external on separate chassis */
- geoloc = (geolocval == 0x00 ? "" : "d");
- switch (grosslocval) {
- case 0x00: grossloc = ""; break; /* N/A */
- case 0x01: grossloc = ""; break; /* rear */
- case 0x02: grossloc = ".front"; break; /* front */
- case 0x03: grossloc = ".left"; break; /* left */
- case 0x04: grossloc = ".right"; break; /* right */
- case 0x05: grossloc = ".top"; break; /* top */
- case 0x06: grossloc = ".bottom"; break; /* bottom */
- case 0x07: grossloc = ".rearpnl"; break; /* rear panel */
- case 0x08: grossloc = ".drivebay"; break; /* drive bay */
- default: grossloc = ""; break;
- }
- break;
- case 0x01:
- geoloc = "i";
- switch (grosslocval) {
- case 0x00: grossloc = ""; break; /* N/A */
- case 0x07: grossloc = ".riser"; break; /* riser */
- case 0x08: grossloc = ".hdmi"; break; /* hdmi */
- default: grossloc = ""; break;
- }
- break;
- default:
- geoloc = "o";
- switch (grosslocval) {
- case 0x00: grossloc = ""; break; /* N/A */
- case 0x06: grossloc = ".bottom"; break; /* bottom */
- case 0x07: grossloc = ".lidin"; break; /* lid inside */
- case 0x08: grossloc = ".lidout"; break; /* lid outside */
- default: grossloc = ""; break;
- }
- break;
- }
-
- snprintf(w->name, sizeof(w->name), "%s%s%s", geoloc, name, grossloc);
- return 0;
-}
-
-static int
-generic_mixer_create_virtual(codec_t *this)
-{
- mixer_item_t *m;
- mixer_devinfo_t *d;
- convgroup_t *cgdac = &this->dacs.groups[0];
- convgroup_t *cgadc = &this->adcs.groups[0];
- int i, err, mdac, madc, mmaster;
-
- /* Clear mixer indexes, to make generic_mixer_fix_index happy */
- for (i = 0; i < this->nmixers; i++) {
- d = &this->mixers[i].devinfo;
- d->index = d->prev = d->next = 0;
- }
-
- mdac = madc = mmaster = -1;
- for (i = 0; i < this->nmixers; i++) {
- if (this->mixers[i].devinfo.type != AUDIO_MIXER_VALUE)
- continue;
- if (mdac < 0 && this->dacs.ngroups > 0 && cgdac->nconv > 0) {
- if (this->mixers[i].nid == cgdac->conv[0])
- mdac = mmaster = i;
- }
- if (madc < 0 && this->adcs.ngroups > 0 && cgadc->nconv > 0) {
- if (this->mixers[i].nid == cgadc->conv[0])
- madc = i;
- }
- }
-
- if (mdac == -1) {
- /*
- * no volume mixer found on the DAC; enumerate peer widgets
- * and try to find a volume mixer on them
- */
- widget_t *w;
- int j;
- FOR_EACH_WIDGET(this, i) {
- w = &this->w[i];
- for (j = 0; j < w->nconnections; j++)
- if (w->connections[j] == cgdac->conv[0])
- break;
-
- if (j == w->nconnections)
- continue;
-
- for (j = 0; j < this->nmixers; j++) {
- if (this->mixers[j].devinfo.type !=
- AUDIO_MIXER_VALUE)
- continue;
- if (this->mixers[j].nid == w->nid) {
- mdac = mmaster = j;
- break;
- }
- }
-
- if (mdac == -1)
- break;
- }
- }
-
- if (mdac >= 0) {
- err = generic_mixer_ensure_capacity(this, this->nmixers + 1);
- if (err)
- return err;
- m = &this->mixers[this->nmixers];
- d = &m->devinfo;
- memcpy(m, &this->mixers[mmaster], sizeof(*m));
- d->mixer_class = AZ_CLASS_OUTPUT;
- snprintf(d->label.name, sizeof(d->label.name), AudioNmaster);
- this->nmixers++;
-
- err = generic_mixer_ensure_capacity(this, this->nmixers + 1);
- if (err)
- return err;
- m = &this->mixers[this->nmixers];
- d = &m->devinfo;
- memcpy(m, &this->mixers[mdac], sizeof(*m));
- d->mixer_class = AZ_CLASS_INPUT;
- snprintf(d->label.name, sizeof(d->label.name), AudioNdac);
- this->nmixers++;
- }
-
- if (madc >= 0) {
- err = generic_mixer_ensure_capacity(this, this->nmixers + 1);
- if (err)
- return err;
- m = &this->mixers[this->nmixers];
- d = &m->devinfo;
- memcpy(m, &this->mixers[madc], sizeof(*m));
- d->mixer_class = AZ_CLASS_RECORD;
- snprintf(d->label.name, sizeof(d->label.name), AudioNvolume);
- this->nmixers++;
- }
-
- generic_mixer_fix_indexes(this);
-
- return 0;
-}
-
-static int
-generic_mixer_autoinit(codec_t *this)
-{
- generic_mixer_init(this);
- generic_mixer_create_virtual(this);
- generic_mixer_pin_sense(this);
-
- return 0;
-}
-
-static int
-generic_mixer_init_widget(const codec_t *this, widget_t *w, nid_t nid)
-{
- return generic_mixer_widget_name(this, w);
-}
-
-static int
-generic_mixer_delete(codec_t *this)
-{
- if (this->mixers == NULL)
- return 0;
- kmem_free(this->mixers, this->szmixers);
- this->mixers = NULL;
- return 0;
-}
-
-/**
- * @param mc mc->type must be set by the caller before the call
- */
-static int
-generic_mixer_get(const codec_t *this, nid_t nid, int target, mixer_ctrl_t *mc)
-{
- uint32_t result;
- nid_t n;
- int err;
-
- /* inamp mute */
- if (IS_MI_TARGET_INAMP(target) && mc->type == AUDIO_MIXER_ENUM) {
- err = this->comresp(this, nid, CORB_GET_AMPLIFIER_GAIN_MUTE,
- CORB_GAGM_INPUT | CORB_GAGM_LEFT |
- MI_TARGET_INAMP(target), &result);
- if (err)
- return err;
- mc->un.ord = result & CORB_GAGM_MUTE ? 1 : 0;
- }
-
- /* inamp gain */
- else if (IS_MI_TARGET_INAMP(target) && mc->type == AUDIO_MIXER_VALUE) {
- err = this->comresp(this, nid, CORB_GET_AMPLIFIER_GAIN_MUTE,
- CORB_GAGM_INPUT | CORB_GAGM_LEFT |
- MI_TARGET_INAMP(target), &result);
- if (err)
- return err;
- mc->un.value.level[0] = generic_mixer_from_device_value(this,
- nid, target, CORB_GAGM_GAIN(result));
- if (this->w[nid].type == COP_AWTYPE_AUDIO_SELECTOR ||
- this->w[nid].type == COP_AWTYPE_AUDIO_MIXER) {
- n = this->w[nid].connections[MI_TARGET_INAMP(target)];
-#ifdef AZALIA_DEBUG
- if (!VALID_WIDGET_NID(n, this)) {
- DPRINTF(("%s: invalid target: nid=%d nconn=%d index=%d\n",
- __func__, nid, this->w[nid].nconnections,
- MI_TARGET_INAMP(target)));
- return EINVAL;
- }
-#endif
- } else {
- n = nid;
- }
- mc->un.value.num_channels = WIDGET_CHANNELS(&this->w[n]);
- if (mc->un.value.num_channels == 2) {
- err = this->comresp(this, nid,
- CORB_GET_AMPLIFIER_GAIN_MUTE, CORB_GAGM_INPUT |
- CORB_GAGM_RIGHT | MI_TARGET_INAMP(target),
- &result);
- if (err)
- return err;
- mc->un.value.level[1] = generic_mixer_from_device_value
- (this, nid, target, CORB_GAGM_GAIN(result));
- }
- }
-
- /* outamp mute */
- else if (target == MI_TARGET_OUTAMP && mc->type == AUDIO_MIXER_ENUM) {
- err = this->comresp(this, nid, CORB_GET_AMPLIFIER_GAIN_MUTE,
- CORB_GAGM_OUTPUT | CORB_GAGM_LEFT | 0, &result);
- if (err)
- return err;
- mc->un.ord = result & CORB_GAGM_MUTE ? 1 : 0;
- }
-
- /* outamp gain */
- else if (target == MI_TARGET_OUTAMP && mc->type == AUDIO_MIXER_VALUE) {
- err = this->comresp(this, nid, CORB_GET_AMPLIFIER_GAIN_MUTE,
- CORB_GAGM_OUTPUT | CORB_GAGM_LEFT | 0, &result);
- if (err)
- return err;
- mc->un.value.level[0] = generic_mixer_from_device_value(this,
- nid, target, CORB_GAGM_GAIN(result));
- mc->un.value.num_channels = WIDGET_CHANNELS(&this->w[nid]);
- if (mc->un.value.num_channels == 2) {
- err = this->comresp(this, nid,
- CORB_GET_AMPLIFIER_GAIN_MUTE,
- CORB_GAGM_OUTPUT | CORB_GAGM_RIGHT | 0, &result);
- if (err)
- return err;
- mc->un.value.level[1] = generic_mixer_from_device_value
- (this, nid, target, CORB_GAGM_GAIN(result));
- }
- }
-
- /* selection */
- else if (target == MI_TARGET_CONNLIST) {
- err = this->comresp(this, nid,
- CORB_GET_CONNECTION_SELECT_CONTROL, 0, &result);
- if (err)
- return err;
- result = CORB_CSC_INDEX(result);
- if (!VALID_WIDGET_NID(this->w[nid].connections[result], this))
- mc->un.ord = -1;
- else
- mc->un.ord = result;
- }
-
- /* pin I/O */
- else if (target == MI_TARGET_PINDIR) {
- err = this->comresp(this, nid,
- CORB_GET_PIN_WIDGET_CONTROL, 0, &result);
- if (err)
- return err;
- mc->un.ord = result & CORB_PWC_OUTPUT ? 1 : 0;
- }
-
- /* pin headphone-boost */
- else if (target == MI_TARGET_PINBOOST) {
- err = this->comresp(this, nid,
- CORB_GET_PIN_WIDGET_CONTROL, 0, &result);
- if (err)
- return err;
- mc->un.ord = result & CORB_PWC_HEADPHONE ? 1 : 0;
- }
-
- /* DAC group selection */
- else if (target == MI_TARGET_DAC) {
- mc->un.ord = this->dacs.cur;
- }
-
- /* ADC selection */
- else if (target == MI_TARGET_ADC) {
- mc->un.ord = this->adcs.cur;
- }
-
- /* Volume knob */
- else if (target == MI_TARGET_VOLUME) {
- err = this->comresp(this, nid, CORB_GET_VOLUME_KNOB,
- 0, &result);
- if (err)
- return err;
- mc->un.value.level[0] = generic_mixer_from_device_value(this,
- nid, target, CORB_VKNOB_VOLUME(result));
- mc->un.value.num_channels = 1;
- }
-
- /* S/PDIF */
- else if (target == MI_TARGET_SPDIF) {
- err = this->comresp(this, nid, CORB_GET_DIGITAL_CONTROL,
- 0, &result);
- if (err)
- return err;
- mc->un.mask = result & 0xff & ~(CORB_DCC_DIGEN | CORB_DCC_NAUDIO);
- } else if (target == MI_TARGET_SPDIF_CC) {
- err = this->comresp(this, nid, CORB_GET_DIGITAL_CONTROL,
- 0, &result);
- if (err)
- return err;
- mc->un.value.num_channels = 1;
- mc->un.value.level[0] = CORB_DCC_CC(result);
- }
-
- /* EAPD */
- else if (target == MI_TARGET_EAPD) {
- err = this->comresp(this, nid,
- CORB_GET_EAPD_BTL_ENABLE, 0, &result);
- if (err)
- return err;
- mc->un.ord = result & CORB_EAPD_EAPD ? 1 : 0;
- }
-
- /* Balanced I/O */
- else if (target == MI_TARGET_BALANCE) {
- err = this->comresp(this, nid,
- CORB_GET_EAPD_BTL_ENABLE, 0, &result);
- if (err)
- return err;
- mc->un.ord = result & CORB_EAPD_BTL ? 1 : 0;
- }
-
- /* LR-Swap */
- else if (target == MI_TARGET_LRSWAP) {
- err = this->comresp(this, nid,
- CORB_GET_EAPD_BTL_ENABLE, 0, &result);
- if (err)
- return err;
- mc->un.ord = result & CORB_EAPD_LRSWAP ? 1 : 0;
- }
-
- else {
- aprint_error_dev(this->dev, "internal error in %s: target=%x\n",
- __func__, target);
- return -1;
- }
- return 0;
-}
-
-static int
-generic_mixer_set(codec_t *this, nid_t nid, int target, const mixer_ctrl_t *mc)
-{
- uint32_t result, value;
- int err;
-
- /* inamp mute */
- if (IS_MI_TARGET_INAMP(target) && mc->type == AUDIO_MIXER_ENUM) {
- /* We have to set stereo mute separately to keep each gain value. */
- err = this->comresp(this, nid, CORB_GET_AMPLIFIER_GAIN_MUTE,
- CORB_GAGM_INPUT | CORB_GAGM_LEFT |
- MI_TARGET_INAMP(target), &result);
- if (err)
- return err;
- value = CORB_AGM_INPUT | CORB_AGM_LEFT |
- (target << CORB_AGM_INDEX_SHIFT) |
- CORB_GAGM_GAIN(result);
- if (mc->un.ord)
- value |= CORB_AGM_MUTE;
- err = this->comresp(this, nid, CORB_SET_AMPLIFIER_GAIN_MUTE,
- value, &result);
- if (err)
- return err;
- if (WIDGET_CHANNELS(&this->w[nid]) == 2) {
- err = this->comresp(this, nid,
- CORB_GET_AMPLIFIER_GAIN_MUTE, CORB_GAGM_INPUT |
- CORB_GAGM_RIGHT | MI_TARGET_INAMP(target),
- &result);
- if (err)
- return err;
- value = CORB_AGM_INPUT | CORB_AGM_RIGHT |
- (target << CORB_AGM_INDEX_SHIFT) |
- CORB_GAGM_GAIN(result);
- if (mc->un.ord)
- value |= CORB_AGM_MUTE;
- err = this->comresp(this, nid,
- CORB_SET_AMPLIFIER_GAIN_MUTE, value, &result);
- if (err)
- return err;
- }
- }
-
- /* inamp gain */
- else if (IS_MI_TARGET_INAMP(target) && mc->type == AUDIO_MIXER_VALUE) {
- if (mc->un.value.num_channels < 1)
- return EINVAL;
- if (!generic_mixer_validate_value(this, nid, target,
- mc->un.value.level[0]))
- return EINVAL;
- err = this->comresp(this, nid, CORB_GET_AMPLIFIER_GAIN_MUTE,
- CORB_GAGM_INPUT | CORB_GAGM_LEFT |
- MI_TARGET_INAMP(target), &result);
- if (err)
- return err;
- value = generic_mixer_to_device_value(this, nid, target,
- mc->un.value.level[0]);
- value = CORB_AGM_INPUT | CORB_AGM_LEFT |
- (target << CORB_AGM_INDEX_SHIFT) |
- (result & CORB_GAGM_MUTE ? CORB_AGM_MUTE : 0) |
- (value & CORB_AGM_GAIN_MASK);
- err = this->comresp(this, nid, CORB_SET_AMPLIFIER_GAIN_MUTE,
- value, &result);
- if (err)
- return err;
- if (mc->un.value.num_channels >= 2 &&
- WIDGET_CHANNELS(&this->w[nid]) == 2) {
- if (!generic_mixer_validate_value(this, nid, target,
- mc->un.value.level[1]))
- return EINVAL;
- err = this->comresp(this, nid,
- CORB_GET_AMPLIFIER_GAIN_MUTE, CORB_GAGM_INPUT |
- CORB_GAGM_RIGHT | MI_TARGET_INAMP(target),
- &result);
- if (err)
- return err;
- value = generic_mixer_to_device_value(this, nid, target,
- mc->un.value.level[1]);
- value = CORB_AGM_INPUT | CORB_AGM_RIGHT |
- (target << CORB_AGM_INDEX_SHIFT) |
- (result & CORB_GAGM_MUTE ? CORB_AGM_MUTE : 0) |
- (value & CORB_AGM_GAIN_MASK);
- err = this->comresp(this, nid,
- CORB_SET_AMPLIFIER_GAIN_MUTE, value, &result);
- if (err)
- return err;
- }
- }
-
- /* outamp mute */
- else if (target == MI_TARGET_OUTAMP && mc->type == AUDIO_MIXER_ENUM) {
- err = this->comresp(this, nid, CORB_GET_AMPLIFIER_GAIN_MUTE,
- CORB_GAGM_OUTPUT | CORB_GAGM_LEFT, &result);
- if (err)
- return err;
- value = CORB_AGM_OUTPUT | CORB_AGM_LEFT | CORB_GAGM_GAIN(result);
- if (mc->un.ord)
- value |= CORB_AGM_MUTE;
- err = this->comresp(this, nid, CORB_SET_AMPLIFIER_GAIN_MUTE,
- value, &result);
- if (err)
- return err;
- if (WIDGET_CHANNELS(&this->w[nid]) == 2) {
- err = this->comresp(this, nid,
- CORB_GET_AMPLIFIER_GAIN_MUTE,
- CORB_GAGM_OUTPUT | CORB_GAGM_RIGHT, &result);
- if (err)
- return err;
- value = CORB_AGM_OUTPUT | CORB_AGM_RIGHT |
- CORB_GAGM_GAIN(result);
- if (mc->un.ord)
- value |= CORB_AGM_MUTE;
- err = this->comresp(this, nid,
- CORB_SET_AMPLIFIER_GAIN_MUTE, value, &result);
- if (err)
- return err;
- }
- }
-
- /* outamp gain */
- else if (target == MI_TARGET_OUTAMP && mc->type == AUDIO_MIXER_VALUE) {
- if (mc->un.value.num_channels < 1)
- return EINVAL;
- if (!generic_mixer_validate_value(this, nid, target,
- mc->un.value.level[0]))
- return EINVAL;
- err = this->comresp(this, nid, CORB_GET_AMPLIFIER_GAIN_MUTE,
- CORB_GAGM_OUTPUT | CORB_GAGM_LEFT, &result);
- if (err)
- return err;
- value = generic_mixer_to_device_value(this, nid, target,
- mc->un.value.level[0]);
- value = CORB_AGM_OUTPUT | CORB_AGM_LEFT |
- (result & CORB_GAGM_MUTE ? CORB_AGM_MUTE : 0) |
- (value & CORB_AGM_GAIN_MASK);
- err = this->comresp(this, nid, CORB_SET_AMPLIFIER_GAIN_MUTE,
- value, &result);
- if (err)
- return err;
- if (mc->un.value.num_channels >= 2 &&
- WIDGET_CHANNELS(&this->w[nid]) == 2) {
- if (!generic_mixer_validate_value(this, nid, target,
- mc->un.value.level[1]))
- return EINVAL;
- err = this->comresp(this, nid,
- CORB_GET_AMPLIFIER_GAIN_MUTE, CORB_GAGM_OUTPUT |
- CORB_GAGM_RIGHT, &result);
- if (err)
- return err;
- value = generic_mixer_to_device_value(this, nid, target,
- mc->un.value.level[1]);
- value = CORB_AGM_OUTPUT | CORB_AGM_RIGHT |
- (result & CORB_GAGM_MUTE ? CORB_AGM_MUTE : 0) |
- (value & CORB_AGM_GAIN_MASK);
- err = this->comresp(this, nid,
- CORB_SET_AMPLIFIER_GAIN_MUTE, value, &result);
- if (err)
- return err;
- }
- }
-
- /* selection */
- else if (target == MI_TARGET_CONNLIST) {
- if (mc->un.ord < 0 ||
- mc->un.ord >= this->w[nid].nconnections ||
- !VALID_WIDGET_NID(this->w[nid].connections[mc->un.ord], this))
- return EINVAL;
- err = this->comresp(this, nid,
- CORB_SET_CONNECTION_SELECT_CONTROL, mc->un.ord, &result);
- if (err)
- return err;
- }
-
- /* pin I/O */
- else if (target == MI_TARGET_PINDIR) {
- if (mc->un.ord >= 2)
- return EINVAL;
- if (mc->un.ord == 0) {
- return generic_mixer_pinctrl(this, nid, CORB_PWC_INPUT);
- } else {
- return generic_mixer_pinctrl(
- this, nid, CORB_PWC_OUTPUT);
- }
- }
-
- /* pin headphone-boost */
- else if (target == MI_TARGET_PINBOOST) {
- if (mc->un.ord >= 2)
- return EINVAL;
- err = this->comresp(this, nid,
- CORB_GET_PIN_WIDGET_CONTROL, 0, &result);
- if (err)
- return err;
- if (mc->un.ord == 0) {
- result &= ~CORB_PWC_HEADPHONE;
- } else {
- result |= CORB_PWC_HEADPHONE;
- }
- err = this->comresp(this, nid,
- CORB_SET_PIN_WIDGET_CONTROL, result, &result);
- if (err)
- return err;
- }
-
- /* DAC group selection */
- else if (target == MI_TARGET_DAC) {
- if (this->running)
- return EBUSY;
- if (mc->un.ord >= this->dacs.ngroups)
- return EINVAL;
- return azalia_codec_construct_format(this,
- mc->un.ord, this->adcs.cur);
- }
-
- /* ADC selection */
- else if (target == MI_TARGET_ADC) {
- if (this->running)
- return EBUSY;
- if (mc->un.ord >= this->adcs.ngroups)
- return EINVAL;
- return azalia_codec_construct_format(this,
- this->dacs.cur, mc->un.ord);
- }
-
- /* Volume knob */
- else if (target == MI_TARGET_VOLUME) {
- if (mc->un.value.num_channels != 1)
- return EINVAL;
- if (!generic_mixer_validate_value(this, nid,
- target, mc->un.value.level[0]))
- return EINVAL;
- value = generic_mixer_to_device_value(this, nid, target,
- mc->un.value.level[0]) | CORB_VKNOB_DIRECT;
- err = this->comresp(this, nid, CORB_SET_VOLUME_KNOB,
- value, &result);
- if (err)
- return err;
- }
-
- /* S/PDIF */
- else if (target == MI_TARGET_SPDIF) {
- err = this->comresp(this, nid, CORB_GET_DIGITAL_CONTROL,
- 0, &result);
- result &= CORB_DCC_DIGEN | CORB_DCC_NAUDIO;
- result |= mc->un.mask & 0xff & ~CORB_DCC_DIGEN;
- err = this->comresp(this, nid, CORB_SET_DIGITAL_CONTROL_L,
- result, NULL);
- if (err)
- return err;
- } else if (target == MI_TARGET_SPDIF_CC) {
- if (mc->un.value.num_channels != 1)
- return EINVAL;
- if (mc->un.value.level[0] > 127)
- return EINVAL;
- err = this->comresp(this, nid, CORB_SET_DIGITAL_CONTROL_H,
- mc->un.value.level[0], NULL);
- if (err)
- return err;
- }
-
- /* EAPD */
- else if (target == MI_TARGET_EAPD) {
- if (mc->un.ord >= 2)
- return EINVAL;
- err = this->comresp(this, nid,
- CORB_GET_EAPD_BTL_ENABLE, 0, &result);
- if (err)
- return err;
- result &= 0xff;
- if (mc->un.ord == 0) {
- result &= ~CORB_EAPD_EAPD;
- } else {
- result |= CORB_EAPD_EAPD;
- }
- err = this->comresp(this, nid,
- CORB_SET_EAPD_BTL_ENABLE, result, &result);
- if (err)
- return err;
- }
-
- /* Balanced I/O */
- else if (target == MI_TARGET_BALANCE) {
- if (mc->un.ord >= 2)
- return EINVAL;
- err = this->comresp(this, nid,
- CORB_GET_EAPD_BTL_ENABLE, 0, &result);
- if (err)
- return err;
- result &= 0xff;
- if (mc->un.ord == 0) {
- result &= ~CORB_EAPD_BTL;
- } else {
- result |= CORB_EAPD_BTL;
- }
- err = this->comresp(this, nid,
- CORB_SET_EAPD_BTL_ENABLE, result, &result);
- if (err)
- return err;
- }
-
- /* LR-Swap */
- else if (target == MI_TARGET_LRSWAP) {
- if (mc->un.ord >= 2)
- return EINVAL;
- err = this->comresp(this, nid,
- CORB_GET_EAPD_BTL_ENABLE, 0, &result);
- if (err)
- return err;
- result &= 0xff;
- if (mc->un.ord == 0) {
- result &= ~CORB_EAPD_LRSWAP;
- } else {
- result |= CORB_EAPD_LRSWAP;
- }
- err = this->comresp(this, nid,
- CORB_SET_EAPD_BTL_ENABLE, result, &result);
- if (err)
- return err;
- }
-
- else {
- aprint_error_dev(this->dev, "internal error in %s: target=%x\n",
- __func__, target);
- return -1;
- }
- return 0;
-}
-
-static int
-generic_mixer_pinctrl(codec_t *this, nid_t nid, uint32_t value)
-{
- int err;
- uint32_t result;
-
- err = this->comresp(this, nid, CORB_GET_PIN_WIDGET_CONTROL, 0, &result);
- if (err)
- return err;
- result &= ~(CORB_PWC_OUTPUT | CORB_PWC_INPUT);
- result |= value & (CORB_PWC_OUTPUT | CORB_PWC_INPUT);
- return this->comresp(this, nid,
- CORB_SET_PIN_WIDGET_CONTROL, result, NULL);
-}
-
-static u_char
-generic_mixer_from_device_value(const codec_t *this, nid_t nid, int target,
- uint32_t dv)
-{
-#ifdef MAX_VOLUME_255
- uint32_t dmax;
-
- if (IS_MI_TARGET_INAMP(target))
- dmax = COP_AMPCAP_NUMSTEPS(this->w[nid].inamp_cap);
- else if (target == MI_TARGET_OUTAMP)
- dmax = COP_AMPCAP_NUMSTEPS(this->w[nid].outamp_cap);
- else if (target == MI_TARGET_VOLUME)
- dmax = COP_VKCAP_NUMSTEPS(this->w[nid].d.volume.cap);
- else {
- printf("unknown target: %d\n", target);
- dmax = 127;
- }
- return dv * MIXER_DELTA(dmax);
-#else
- return dv;
-#endif
-}
-
-static uint32_t
-generic_mixer_to_device_value(const codec_t *this, nid_t nid, int target,
- u_char uv)
-{
-#ifdef MAX_VOLUME_255
- uint32_t dmax;
-
- if (IS_MI_TARGET_INAMP(target))
- dmax = COP_AMPCAP_NUMSTEPS(this->w[nid].inamp_cap);
- else if (target == MI_TARGET_OUTAMP)
- dmax = COP_AMPCAP_NUMSTEPS(this->w[nid].outamp_cap);
- else if (target == MI_TARGET_VOLUME)
- dmax = COP_VKCAP_NUMSTEPS(this->w[nid].d.volume.cap);
- else {
- printf("unknown target: %d\n", target);
- dmax = 127;
- }
- return uv / MIXER_DELTA(dmax);
-#else
- return uv;
-#endif
-}
-
-static uint32_t
-generic_mixer_max(const codec_t *this, nid_t nid,
- int target)
-{
-#ifdef MAX_VOLUME_255
- return AUDIO_MAX_GAIN;
-#else
- uint32_t dmax;
-
- if (IS_MI_TARGET_INAMP(target))
- dmax = COP_AMPCAP_NUMSTEPS(this->w[nid].inamp_cap);
- else if (target == MI_TARGET_OUTAMP)
- dmax = COP_AMPCAP_NUMSTEPS(this->w[nid].outamp_cap);
- else if (target == MI_TARGET_VOLUME)
- dmax = COP_VKCAP_NUMSTEPS(this->w[nid].d.volume.cap);
- return dmax;
-#endif
-}
-
-static bool
-generic_mixer_validate_value(const codec_t *this, nid_t nid,
- int target, u_char uv)
-{
-#ifdef MAX_VOLUME_255
- return TRUE;
-#else
- return uv <= generic_mixer_max(this, nid, target);
-#endif
-}
-
-static int
-generic_set_port(codec_t *this, mixer_ctrl_t *mc)
-{
- const mixer_item_t *m;
-
- if (mc->dev < 0 || mc->dev >= this->nmixers)
- return ENXIO;
- m = &this->mixers[mc->dev];
- if (mc->type != m->devinfo.type)
- return EINVAL;
- if (mc->type == AUDIO_MIXER_CLASS)
- return 0; /* nothing to do */
- return generic_mixer_set(this, m->nid, m->target, mc);
-}
-
-static int
-generic_get_port(codec_t *this, mixer_ctrl_t *mc)
-{
- const mixer_item_t *m;
-
- if (mc->dev < 0 || mc->dev >= this->nmixers)
- return ENXIO;
- m = &this->mixers[mc->dev];
- mc->type = m->devinfo.type;
- if (mc->type == AUDIO_MIXER_CLASS)
- return 0; /* nothing to do */
- return generic_mixer_get(this, m->nid, m->target, mc);
-}
-
-
-/* ----------------------------------------------------------------
- * Realtek ALC260
- *
- * Fujitsu LOOX T70M/T
- * Internal Speaker: 0x10
- * Front Headphone: 0x14
- * Front mic: 0x12
- * ---------------------------------------------------------------- */
-
-#define ALC260_FUJITSU_ID 0x132610cf
-#define ALC260_EVENT_HP 0
-#define ALC260_EXTRA_MASTER 0
-static const mixer_item_t alc260_mixer_items[] = {
- AZ_MIXER_CLASSES,
- {{0, {AudioNmaster, 0}, AUDIO_MIXER_VALUE, AZ_CLASS_OUTPUT,
- 0, 0, .un.v={{"", 0}, 2, 3}}, 0x08, MI_TARGET_OUTAMP}, /* and 0x09, 0x0a(mono) */
- {{0, {AudioNmaster".mute", 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
- 0, 0, ENUM_OFFON}, 0x0f, MI_TARGET_OUTAMP},
- {{0, {AudioNheadphone".mute", 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
- 0, 0, ENUM_OFFON}, 0x10, MI_TARGET_OUTAMP},
- {{0, {AudioNheadphone".boost", 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
- 0, 0, ENUM_OFFON}, 0x10, MI_TARGET_PINBOOST},
- {{0, {AudioNmono".mute", 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
- 0, 0, ENUM_OFFON}, 0x11, MI_TARGET_OUTAMP},
- {{0, {"mic1.mute", 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
- 0, 0, ENUM_OFFON}, 0x12, MI_TARGET_OUTAMP},
- {{0, {"mic1", 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
- 0, 0, ENUM_IO}, 0x12, MI_TARGET_PINDIR},
- {{0, {"mic2.mute", 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
- 0, 0, ENUM_OFFON}, 0x13, MI_TARGET_OUTAMP},
- {{0, {"mic2", 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
- 0, 0, ENUM_IO}, 0x13, MI_TARGET_PINDIR},
- {{0, {"line1.mute", 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
- 0, 0, ENUM_OFFON}, 0x14, MI_TARGET_OUTAMP},
- {{0, {"line1", 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
- 0, 0, ENUM_IO}, 0x14, MI_TARGET_PINDIR},
- {{0, {"line2.mute", 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
- 0, 0, ENUM_OFFON}, 0x15, MI_TARGET_OUTAMP},
- {{0, {"line2", 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
- 0, 0, ENUM_IO}, 0x15, MI_TARGET_PINDIR},
-
- {{0, {AudioNdac".mute", 0}, AUDIO_MIXER_ENUM, AZ_CLASS_INPUT,
- 0, 0, ENUM_OFFON}, 0x08, MI_TARGET_INAMP(0)}, /* and 0x09, 0x0a(mono) */
- {{0, {"mic1.mute", 0}, AUDIO_MIXER_ENUM, AZ_CLASS_INPUT,
- 0, 0, ENUM_OFFON}, 0x07, MI_TARGET_INAMP(0)},
- {{0, {"mic1", 0}, AUDIO_MIXER_VALUE, AZ_CLASS_INPUT,
- 0, 0, .un.v={{"", 0}, 2, MIXER_DELTA(65)}}, 0x07, MI_TARGET_INAMP(0)},
- {{0, {"mic2.mute", 0}, AUDIO_MIXER_ENUM, AZ_CLASS_INPUT,
- 0, 0, ENUM_OFFON}, 0x07, MI_TARGET_INAMP(1)},
- {{0, {"mic2", 0}, AUDIO_MIXER_VALUE, AZ_CLASS_INPUT,
- 0, 0, .un.v={{"", 0}, 2, MIXER_DELTA(65)}}, 0x07, MI_TARGET_INAMP(1)},
- {{0, {"line1.mute", 0}, AUDIO_MIXER_ENUM, AZ_CLASS_INPUT,
- 0, 0, ENUM_OFFON}, 0x07, MI_TARGET_INAMP(2)},
- {{0, {"line1", 0}, AUDIO_MIXER_VALUE, AZ_CLASS_INPUT,
- 0, 0, .un.v={{"", 0}, 2, MIXER_DELTA(65)}}, 0x07, MI_TARGET_INAMP(2)},
- {{0, {"line2.mute", 0}, AUDIO_MIXER_ENUM, AZ_CLASS_INPUT,
- 0, 0, ENUM_OFFON}, 0x07, MI_TARGET_INAMP(3)},
- {{0, {"line2", 0}, AUDIO_MIXER_VALUE, AZ_CLASS_INPUT,
- 0, 0, .un.v={{"", 0}, 2, MIXER_DELTA(65)}}, 0x07, MI_TARGET_INAMP(3)},
- {{0, {AudioNcd".mute", 0}, AUDIO_MIXER_ENUM, AZ_CLASS_INPUT,
- 0, 0, ENUM_OFFON}, 0x07, MI_TARGET_INAMP(4)},
- {{0, {AudioNcd, 0}, AUDIO_MIXER_VALUE, AZ_CLASS_INPUT,
- 0, 0, .un.v={{"", 0}, 2, MIXER_DELTA(65)}}, 0x07, MI_TARGET_INAMP(4)},
- {{0, {AudioNspeaker".mute", 0}, AUDIO_MIXER_ENUM, AZ_CLASS_INPUT,
- 0, 0, ENUM_OFFON}, 0x07, MI_TARGET_INAMP(5)},
- {{0, {AudioNspeaker, 0}, AUDIO_MIXER_VALUE, AZ_CLASS_INPUT,
- 0, 0, .un.v={{"", 0}, 2, MIXER_DELTA(65)}}, 0x07, MI_TARGET_INAMP(5)},
-
- {{0, {"adc04.source", 0}, AUDIO_MIXER_ENUM, AZ_CLASS_RECORD, 0, 0,
- .un.e={5, {{{"mic1", 0}, 0}, {{"mic2", 0}, 1}, {{"line1", 0}, 2},
- {{"line2", 0}, 3}, {{AudioNcd, 0}, 4}}}},
- 0x04, MI_TARGET_CONNLIST},
- {{0, {"adc04.mute", 0}, AUDIO_MIXER_ENUM, AZ_CLASS_RECORD, 0, 0,
- ENUM_OFFON}, 0x04, MI_TARGET_INAMP(0)},
- {{0, {"adc04", 0}, AUDIO_MIXER_VALUE, AZ_CLASS_RECORD, 0, 0,
- .un.v={{"", 0}, 2, MIXER_DELTA(35)}}, 0x04, MI_TARGET_INAMP(0)},
- {{0, {"adc05.source", 0}, AUDIO_MIXER_ENUM, AZ_CLASS_RECORD, 0, 0,
- .un.e={6, {{{"mic1", 0}, 0}, {{"mic2", 0}, 1}, {{"line1", 0}, 2},
- {{"line2", 0}, 3}, {{AudioNcd, 0}, 4}, {{AudioNmixerout, 0}, 5}}}},
- 0x05, MI_TARGET_CONNLIST},
- {{0, {"adc05.mute", 0}, AUDIO_MIXER_ENUM, AZ_CLASS_RECORD, 0, 0,
- ENUM_OFFON}, 0x05, MI_TARGET_INAMP(0)},
- {{0, {"adc05", 0}, AUDIO_MIXER_VALUE, AZ_CLASS_RECORD, 0, 0,
- .un.v={{"", 0}, 2, MIXER_DELTA(35)}}, 0x05, MI_TARGET_INAMP(0)},
-
- {{0, {AudioNmode, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_PLAYBACK, 0, 0,
- .un.e={2, {{{"analog", 0}, 0}, {{AzaliaNdigital, 0}, 1}}}}, 0, MI_TARGET_DAC},
- {{0, {AudioNmode, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_RECORD, 0, 0,
- .un.e={3, {{{"adc04", 0}, 0}, {{"adc05", 0}, 1}, {{AzaliaNdigital, 0}, 2}}}},
- 0, MI_TARGET_ADC},
-};
-
-static const mixer_item_t alc260_loox_mixer_items[] = {
- AZ_MIXER_CLASSES,
-
- {{0, {AudioNmaster, 0}, AUDIO_MIXER_VALUE, AZ_CLASS_OUTPUT,
- 0, 0, .un.v={{"", 0}, 2, 3}}, 0x08, MI_TARGET_OUTAMP}, /* and 0x09, 0x0a(mono) */
- {{0, {AudioNmaster".mute", 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
- 0, 0, ENUM_OFFON}, 0x10, MI_TARGET_OUTAMP},
- {{0, {AudioNmaster".boost", 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
- 0, 0, ENUM_OFFON}, 0x10, MI_TARGET_PINBOOST},
- {{0, {AudioNheadphone".mute", 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
- 0, 0, ENUM_OFFON}, 0x14, MI_TARGET_OUTAMP},
- {{0, {AudioNheadphone".boost", 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
- 0, 0, ENUM_OFFON}, 0x14, MI_TARGET_PINBOOST},
-
- {{0, {AudioNdac".mute", 0}, AUDIO_MIXER_ENUM, AZ_CLASS_INPUT,
- 0, 0, ENUM_OFFON}, 0x08, MI_TARGET_INAMP(0)}, /* and 0x09, 0x0a(mono) */
- {{0, {AudioNmicrophone".mute", 0}, AUDIO_MIXER_ENUM, AZ_CLASS_INPUT,
- 0, 0, ENUM_OFFON}, 0x07, MI_TARGET_INAMP(0)},
- {{0, {AudioNmicrophone, 0}, AUDIO_MIXER_VALUE, AZ_CLASS_INPUT,
- 0, 0, .un.v={{"", 0}, 2, MIXER_DELTA(65)}}, 0x07, MI_TARGET_INAMP(0)},
- {{0, {AudioNcd".mute", 0}, AUDIO_MIXER_ENUM, AZ_CLASS_INPUT,
- 0, 0, ENUM_OFFON}, 0x07, MI_TARGET_INAMP(4)},
- {{0, {AudioNcd, 0}, AUDIO_MIXER_VALUE, AZ_CLASS_INPUT,
- 0, 0, .un.v={{"", 0}, 2, MIXER_DELTA(65)}}, 0x07, MI_TARGET_INAMP(4)},
- {{0, {AudioNspeaker".mute", 0}, AUDIO_MIXER_ENUM, AZ_CLASS_INPUT,
- 0, 0, ENUM_OFFON}, 0x07, MI_TARGET_INAMP(5)},
- {{0, {AudioNspeaker, 0}, AUDIO_MIXER_VALUE, AZ_CLASS_INPUT,
- 0, 0, .un.v={{"", 0}, 2, MIXER_DELTA(65)}}, 0x07, MI_TARGET_INAMP(5)},
-
- {{0, {"adc04.source", 0}, AUDIO_MIXER_ENUM, AZ_CLASS_RECORD, 0, 0,
- .un.e={2, {{{AudioNmicrophone, 0}, 0}, {{AudioNcd, 0}, 4}}}}, 0x04, MI_TARGET_CONNLIST},
- {{0, {"adc04.mute", 0}, AUDIO_MIXER_ENUM, AZ_CLASS_RECORD, 0, 0,
- ENUM_OFFON}, 0x04, MI_TARGET_INAMP(0)},
- {{0, {"adc04", 0}, AUDIO_MIXER_VALUE, AZ_CLASS_RECORD, 0, 0,
- .un.v={{"", 0}, 2, MIXER_DELTA(35)}}, 0x04, MI_TARGET_INAMP(0)},
- {{0, {"adc05.source", 0}, AUDIO_MIXER_ENUM, AZ_CLASS_RECORD, 0, 0,
- .un.e={3, {{{AudioNmicrophone, 0}, 0}, {{AudioNcd, 0}, 4}, {{AudioNmixerout, 0}, 5}}}},
- 0x05, MI_TARGET_CONNLIST},
- {{0, {"adc05.mute", 0}, AUDIO_MIXER_ENUM, AZ_CLASS_RECORD, 0, 0,
- ENUM_OFFON}, 0x05, MI_TARGET_INAMP(0)},
- {{0, {"adc05", 0}, AUDIO_MIXER_VALUE, AZ_CLASS_RECORD, 0, 0,
- .un.v={{"", 0}, 2, MIXER_DELTA(35)}}, 0x05, MI_TARGET_INAMP(0)},
-
- {{0, {AudioNmode, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_PLAYBACK, 0, 0,
- .un.e={2, {{{"analog", 0}, 0}, {{AzaliaNdigital, 0}, 1}}}}, 0, MI_TARGET_DAC},
- {{0, {AudioNmode, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_RECORD, 0, 0,
- .un.e={3, {{{"adc04", 0}, 0}, {{"adc05", 0}, 1}, {{AzaliaNdigital, 0}, 2}}}},
- 0, MI_TARGET_ADC},
-};
-
-static int
-alc260_mixer_init(codec_t *this)
-{
- const mixer_item_t *mi;
- mixer_ctrl_t mc;
- uint32_t value;
-
- switch (this->subid) {
- case ALC260_FUJITSU_ID:
- this->nmixers = __arraycount(alc260_loox_mixer_items);
- mi = alc260_loox_mixer_items;
- break;
- default:
- this->nmixers = __arraycount(alc260_mixer_items);
- mi = alc260_mixer_items;
- }
- this->szmixers = sizeof(mixer_item_t) * this->nmixers;
- this->mixers = kmem_alloc(this->szmixers, KM_SLEEP);
- memcpy(this->mixers, mi, sizeof(mixer_item_t) * this->nmixers);
- generic_mixer_fix_indexes(this);
- generic_mixer_default(this);
-
- mc.dev = -1; /* no need for generic_mixer_set() */
- mc.type = AUDIO_MIXER_ENUM;
- mc.un.ord = 1; /* pindir: output */
- generic_mixer_set(this, 0x0f, MI_TARGET_PINDIR, &mc); /* lineout */
- generic_mixer_set(this, 0x10, MI_TARGET_PINDIR, &mc); /* headphones */
- mc.un.ord = 0; /* pindir: input */
- generic_mixer_set(this, 0x12, MI_TARGET_PINDIR, &mc); /* mic1 */
- generic_mixer_set(this, 0x13, MI_TARGET_PINDIR, &mc); /* mic2 */
- generic_mixer_set(this, 0x14, MI_TARGET_PINDIR, &mc); /* line1 */
- generic_mixer_set(this, 0x15, MI_TARGET_PINDIR, &mc); /* line2 */
- mc.un.ord = 0; /* mute: off */
- generic_mixer_set(this, 0x08, MI_TARGET_INAMP(0), &mc);
- generic_mixer_set(this, 0x08, MI_TARGET_INAMP(1), &mc);
- generic_mixer_set(this, 0x09, MI_TARGET_INAMP(0), &mc);
- generic_mixer_set(this, 0x09, MI_TARGET_INAMP(1), &mc);
- generic_mixer_set(this, 0x0a, MI_TARGET_INAMP(0), &mc);
- generic_mixer_set(this, 0x0a, MI_TARGET_INAMP(1), &mc);
- if (this->subid == ALC260_FUJITSU_ID) {
- mc.un.ord = 1; /* pindir: output */
- generic_mixer_set(this, 0x14, MI_TARGET_PINDIR, &mc); /* line1 */
- mc.un.ord = 4; /* connlist: cd */
- generic_mixer_set(this, 0x05, MI_TARGET_CONNLIST, &mc);
- /* setup a unsolicited event for the headphones */
- this->comresp(this, 0x14, CORB_SET_UNSOLICITED_RESPONSE,
- CORB_UNSOL_ENABLE | ALC260_EVENT_HP, NULL);
- this->extra[ALC260_EXTRA_MASTER] = 0; /* unmute */
- /* If the headphone presents, mute the internal speaker */
- this->comresp(this, 0x14, CORB_GET_PIN_SENSE, 0, &value);
- mc.un.ord = value & CORB_PS_PRESENCE ? 1 : 0;
- generic_mixer_set(this, 0x10, MI_TARGET_OUTAMP, &mc);
- this->get_port = alc260_get_port;
- }
- return 0;
-}
-
-static int
-alc260_init_dacgroup(codec_t *this)
-{
- static const convgroupset_t dacs = {
- -1, 2,
- {{1, {0x02}}, /* analog 2ch */
- {1, {0x03}}}}; /* digital */
- static const convgroupset_t adcs = {
- -1, 3,
- {{1, {0x04}}, /* analog 2ch */
- {1, {0x05}}, /* analog 2ch */
- {1, {0x06}}}}; /* digital */
-
- this->dacs = dacs;
- this->adcs = adcs;
- return 0;
-}
-
-static int
-alc260_set_port(codec_t *this, mixer_ctrl_t *mc)
-{
- const mixer_item_t *m;
- mixer_ctrl_t mc2;
- uint32_t value;
- int err;
-
- if (mc->dev < 0 || mc->dev >= this->nmixers)
- return ENXIO;
- m = &this->mixers[mc->dev];
- if (mc->type != m->devinfo.type)
- return EINVAL;
- if (mc->type == AUDIO_MIXER_CLASS)
- return 0;
- if (m->nid == 0x08 && m->target == MI_TARGET_OUTAMP) {
- DPRINTF(("%s: hook for outputs.master\n", __func__));
- err = generic_mixer_set(this, m->nid, m->target, mc);
- if (!err) {
- generic_mixer_set(this, 0x09, m->target, mc);
- mc2 = *mc;
- mc2.un.value.num_channels = 1;
- mc2.un.value.level[0] = (mc2.un.value.level[0]
- + mc2.un.value.level[1]) / 2;
- generic_mixer_set(this, 0x0a, m->target, &mc2);
- }
- return err;
- } else if (m->nid == 0x08 && m->target == MI_TARGET_INAMP(0)) {
- DPRINTF(("%s: hook for inputs.dac.mute\n", __func__));
- err = generic_mixer_set(this, m->nid, m->target, mc);
- if (!err) {
- generic_mixer_set(this, 0x09, m->target, mc);
- generic_mixer_set(this, 0x0a, m->target, mc);
- }
- return err;
- } else if (m->nid == 0x04 &&
- m->target == MI_TARGET_CONNLIST &&
- m->devinfo.un.e.num_mem == 2) {
- if (1 <= mc->un.ord && mc->un.ord <= 3)
- return EINVAL;
- } else if (m->nid == 0x05 &&
- m->target == MI_TARGET_CONNLIST &&
- m->devinfo.un.e.num_mem == 3) {
- if (1 <= mc->un.ord && mc->un.ord <= 3)
- return EINVAL;
- } else if (this->subid == ALC260_FUJITSU_ID && m->nid == 0x10 &&
- m->target == MI_TARGET_OUTAMP) {
- if (mc->un.ord != 0 && mc->un.ord != 1)
- return EINVAL;
- this->extra[ALC260_EXTRA_MASTER] = mc->un.ord;
- err = this->comresp(this, 0x14, CORB_GET_PIN_SENSE, 0, &value);
- if (err)
- return err;
- if (!(value & CORB_PS_PRESENCE)) {
- return generic_mixer_set(this, m->nid, m->target, mc);
- }
- return 0;
- }
- return generic_mixer_set(this, m->nid, m->target, mc);
-}
-
-static int
-alc260_get_port(codec_t *this, mixer_ctrl_t *mc)
-{
- const mixer_item_t *m;
-
- if (mc->dev < 0 || mc->dev >= this->nmixers)
- return ENXIO;
- m = &this->mixers[mc->dev];
- mc->type = m->devinfo.type;
- if (mc->type == AUDIO_MIXER_CLASS)
- return 0;
- if (this->subid == ALC260_FUJITSU_ID && m->nid == 0x10 &&
- m->target == MI_TARGET_OUTAMP) {
- mc->un.ord = this->extra[ALC260_EXTRA_MASTER];
- return 0;
- }
- return generic_mixer_get(this, m->nid, m->target, mc);
-}
-
-static int
-alc260_unsol_event(codec_t *this, int tag)
-{
- int err;
- uint32_t value;
- mixer_ctrl_t mc;
-
- switch (tag) {
- case ALC260_EVENT_HP:
- err = this->comresp(this, 0x14, CORB_GET_PIN_SENSE, 0, &value);
- if (err)
- break;
- mc.dev = -1;
- mc.type = AUDIO_MIXER_ENUM;
- if (value & CORB_PS_PRESENCE) {
- DPRINTF(("%s: headphone has been inserted.\n", __func__));
- mc.un.ord = 1; /* mute */
- generic_mixer_set(this, 0x10, MI_TARGET_OUTAMP, &mc);
- } else {
- DPRINTF(("%s: headphone has been pulled out.\n", __func__));
- mc.un.ord = this->extra[ALC260_EXTRA_MASTER];
- generic_mixer_set(this, 0x10, MI_TARGET_OUTAMP, &mc);
- }
- break;
- default:
- printf("%s: unknown tag: %d\n", __func__, tag);
- }
- return 0;
-}
-
-/* ----------------------------------------------------------------
- * Realtek ALC262
- * ---------------------------------------------------------------- */
-
-static int
-alc262_init_widget(const codec_t *this, widget_t *w, nid_t nid)
-{
- switch (nid) {
- case 0x0c:
- strlcpy(w->name, AudioNmaster, sizeof(w->name));
- break;
- }
-
- return 0;
-}
-
-/* ----------------------------------------------------------------
- * Realtek ALC268
- * ---------------------------------------------------------------- */
-
-static int
-alc268_init_dacgroup(codec_t *this)
-{
- static const convgroupset_t dacs = {
- -1, 1,
- {{2, {0x02, 0x03}}}}; /* analog 4ch */
- static const convgroupset_t adcs = {
- -1, 1,
- {{2, {0x08, 0x07}}}}; /* analog 4ch */
-
- this->dacs = dacs;
- this->adcs = adcs;
- return 0;
-}
-
-/* ----------------------------------------------------------------
- * Realtek ALC662-GR
- * ---------------------------------------------------------------- */
-
-static int
-alc662_init_dacgroup(codec_t *this)
-{
- static const convgroupset_t dacs = {
- -1, 1,
- {{3, {0x02, 0x03, 0x04}}}}; /* analog 6ch */
- static const convgroupset_t adcs = {
- -1, 1,
- {{2, {0x09, 0x08}}}}; /* analog 4ch */
-
- this->dacs = dacs;
- this->adcs = adcs;
- return 0;
-}
-
-/* ----------------------------------------------------------------
- * Realtek ALC861
- * ---------------------------------------------------------------- */
-
-static int
-alc861_init_dacgroup(codec_t *this)
-{
- static const convgroupset_t dacs = {
- -1, 2,
- {{4, {0x03, 0x04, 0x05, 0x06}}, /* analog 8ch */
- {1, {0x07}}}}; /* digital */
- static const convgroupset_t adcs = {
- -1, 1,
- {{1, {0x08}}}}; /* analog 2ch */
-
- this->dacs = dacs;
- this->adcs = adcs;
- return 0;
-}
-
-/* ----------------------------------------------------------------
- * Realtek ALC861-VD-GR
- * ---------------------------------------------------------------- */
-
-static int
-alc861vdgr_init_dacgroup(codec_t *this)
-{
- static const convgroupset_t dacs = {
- -1, 2,
- {{4, {0x02, 0x03, 0x04, 0x05}}, /* analog 8ch */
- {1, {0x06}}}}; /* digital */
- static const convgroupset_t adcs = {
- -1, 1,
- {{1, {0x09}}}}; /* analog 2ch */
-
- this->dacs = dacs;
- this->adcs = adcs;
- return 0;
-}
-
-/* ----------------------------------------------------------------
- * Realtek ALC880
- * ---------------------------------------------------------------- */
-
-static const mixer_item_t alc880_mixer_items[] = {
- AZ_MIXER_CLASSES,
-
- {{0, {AudioNsurround"."AudioNsource, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_RECORD,
- 0, 0, .un.e={5, {{{"mic1", 0}, 0}, {{"mic2", 0}, 1}, {{"line1", 0}, 2},
- {{"line2", 0}, 3}, {{AudioNcd, 0}, 4}}}}, 0x08, MI_TARGET_CONNLIST},
- {{0, {AudioNsurround"."AudioNmute, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_RECORD,
- 0, 0, ENUM_OFFON}, 0x08, MI_TARGET_INAMP(0)},
- {{0, {AudioNsurround, 0}, AUDIO_MIXER_VALUE, AZ_CLASS_RECORD,
- 0, 0, .un.v={{"", 0}, 2, MIXER_DELTA(35)}}, 0x08, MI_TARGET_INAMP(0)},
-
- {{0, {AzaliaNfront"."AudioNsource, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_RECORD,
- 0, 0, .un.e={5, {{{"mic1", 0}, 0}, {{"mic2", 0}, 1}, {{"line1", 0}, 2},
- {{"line2", 0}, 3}, {{AudioNcd, 0}, 4},
- {{AudioNmixerout, 0}, 5}}}}, 0x09, MI_TARGET_CONNLIST},
- {{0, {AzaliaNfront"."AudioNmute, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_RECORD,
- 0, 0, ENUM_OFFON}, 0x08, MI_TARGET_INAMP(0)},
- {{0, {AzaliaNfront, 0}, AUDIO_MIXER_VALUE, AZ_CLASS_RECORD,
- 0, 0, .un.v={{"", 0}, 2, MIXER_DELTA(35)}}, 0x09, MI_TARGET_INAMP(0)},
-
- {{0, {"mic1."AudioNmute, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_INPUT,
- 0, 0, ENUM_OFFON}, 0x0b, MI_TARGET_INAMP(0)},
- {{0, {"mic1", 0}, AUDIO_MIXER_VALUE, AZ_CLASS_INPUT,
- 0, 0, .un.v={{"", 0}, 2, MIXER_DELTA(65)}}, 0x0b, MI_TARGET_INAMP(0)},
- {{0, {"mic2."AudioNmute, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_INPUT,
- 0, 0, ENUM_OFFON}, 0x0b, MI_TARGET_INAMP(1)},
- {{0, {"mic2", 0}, AUDIO_MIXER_VALUE, AZ_CLASS_INPUT,
- 0, 0, .un.v={{"", 0}, 2, MIXER_DELTA(65)}}, 0x0b, MI_TARGET_INAMP(1)},
- {{0, {"line1."AudioNmute, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_INPUT,
- 0, 0, ENUM_OFFON}, 0x0b, MI_TARGET_INAMP(2)},
- {{0, {"line1", 0}, AUDIO_MIXER_VALUE, AZ_CLASS_INPUT,
- 0, 0, .un.v={{"", 0}, 2, MIXER_DELTA(65)}}, 0x0b, MI_TARGET_INAMP(2)},
- {{0, {"line2."AudioNmute, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_INPUT,
- 0, 0, ENUM_OFFON}, 0x0b, MI_TARGET_INAMP(3)},
- {{0, {"line2", 0}, AUDIO_MIXER_VALUE, AZ_CLASS_INPUT,
- 0, 0, .un.v={{"", 0}, 2, MIXER_DELTA(65)}}, 0x0b, MI_TARGET_INAMP(3)},
- {{0, {AudioNcd"."AudioNmute, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_INPUT,
- 0, 0, ENUM_OFFON}, 0x0b, MI_TARGET_INAMP(4)},
- {{0, {AudioNcd, 0}, AUDIO_MIXER_VALUE, AZ_CLASS_INPUT,
- 0, 0, .un.v={{"", 0}, 2, MIXER_DELTA(65)}}, 0x0b, MI_TARGET_INAMP(4)},
- {{0, {AudioNspeaker"."AudioNmute, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_INPUT,
- 0, 0, ENUM_OFFON}, 0x0b, MI_TARGET_INAMP(5)},
- {{0, {AudioNspeaker, 0}, AUDIO_MIXER_VALUE, AZ_CLASS_INPUT,
- 0, 0, .un.v={{"", 0}, 1, MIXER_DELTA(65)}}, 0x0b, MI_TARGET_INAMP(5)},
-
- {{0, {AudioNmaster, 0}, AUDIO_MIXER_VALUE, AZ_CLASS_OUTPUT,
- 0, 0, .un.v={{"", 0}, 2, MIXER_DELTA(64)}}, 0x0c, MI_TARGET_OUTAMP},
- {{0, {AzaliaNfront".dac.mute", 0}, AUDIO_MIXER_ENUM, AZ_CLASS_INPUT,
- 0, 0, ENUM_OFFON}, 0x0c, MI_TARGET_INAMP(0)},
- {{0, {AzaliaNfront".mixer.mute", 0}, AUDIO_MIXER_ENUM, AZ_CLASS_INPUT,
- 0, 0, ENUM_OFFON}, 0x0c, MI_TARGET_INAMP(1)},
- {{0, {AudioNsurround, 0}, AUDIO_MIXER_VALUE, AZ_CLASS_OUTPUT,
- 0, 0, .un.v={{"", 0}, 2, MIXER_DELTA(64)}}, 0x0d, MI_TARGET_OUTAMP},
- {{0, {AzaliaNclfe, 0}, AUDIO_MIXER_VALUE, AZ_CLASS_OUTPUT,
- 0, 0, .un.v={{"", 0}, 2, MIXER_DELTA(64)}}, 0x0e, MI_TARGET_OUTAMP},
- {{0, {AzaliaNside, 0}, AUDIO_MIXER_VALUE, AZ_CLASS_OUTPUT,
- 0, 0, .un.v={{"", 0}, 2, MIXER_DELTA(64)}}, 0x0f, MI_TARGET_OUTAMP},
-#if 0 /* The followings are useless. */
- {{0, {AudioNsurround".dac.mute", 0}, AUDIO_MIXER_ENUM, AZ_CLASS_INPUT,
- 0, 0, ENUM_OFFON}, 0x0d, MI_TARGET_INAMP(0)},
- {{0, {AudioNsurround".mixer.mute", 0}, AUDIO_MIXER_ENUM, AZ_CLASS_INPUT,
- 0, 0, ENUM_OFFON}, 0x0d, MI_TARGET_INAMP(1)},
- {{0, {AzaliaNclfe".dac.mute", 0}, AUDIO_MIXER_ENUM, AZ_CLASS_INPUT,
- 0, 0, ENUM_OFFON}, 0x0e, MI_TARGET_INAMP(0)},
- {{0, {AzaliaNclfe".mixer.mute", 0}, AUDIO_MIXER_ENUM, AZ_CLASS_INPUT,
- 0, 0, ENUM_OFFON}, 0x0e, MI_TARGET_INAMP(1)},
- {{0, {AzaliaNside".dac.mute", 0}, AUDIO_MIXER_ENUM, AZ_CLASS_INPUT,
- 0, 0, ENUM_OFFON}, 0x0f, MI_TARGET_INAMP(0)},
- {{0, {AzaliaNside".mixer.mute", 0}, AUDIO_MIXER_ENUM, AZ_CLASS_INPUT,
- 0, 0, ENUM_OFFON}, 0x0f, MI_TARGET_INAMP(1)},
-#endif
-
- {{0, {AudioNmaster"."AudioNmute, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
- 0, 0, ENUM_OFFON}, 0x14, MI_TARGET_OUTAMP},
- {{0, {AudioNmaster".boost", 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
- 0, 0, ENUM_OFFON}, 0x14, MI_TARGET_PINBOOST},
- {{0, {AudioNsurround"."AudioNmute, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
- 0, 0, ENUM_OFFON}, 0x15, MI_TARGET_OUTAMP},
- {{0, {AudioNsurround".boost", 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
- 0, 0, ENUM_OFFON}, 0x15, MI_TARGET_PINBOOST},
- {{0, {AzaliaNclfe"."AudioNmute, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
- 0, 0, ENUM_OFFON}, 0x16, MI_TARGET_OUTAMP},
- {{0, {AzaliaNclfe".boost", 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
- 0, 0, ENUM_OFFON}, 0x16, MI_TARGET_PINBOOST},
- {{0, {AzaliaNside"."AudioNmute, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
- 0, 0, ENUM_OFFON}, 0x17, MI_TARGET_OUTAMP},
- {{0, {AzaliaNside".boost", 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
- 0, 0, ENUM_OFFON}, 0x17, MI_TARGET_PINBOOST},
-
- {{0, {"mic2."AudioNmute, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
- 0, 0, ENUM_OFFON}, 0x19, MI_TARGET_OUTAMP},
- {{0, {"mic2.boost", 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
- 0, 0, ENUM_OFFON}, 0x19, MI_TARGET_PINBOOST},
- {{0, {"mic2.dir", 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
- 0, 0, ENUM_IO}, 0x19, MI_TARGET_PINDIR},
- {{0, {"line1."AudioNmute, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
- 0, 0, ENUM_OFFON}, 0x1a, MI_TARGET_OUTAMP},
- {{0, {"line1.boost", 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
- 0, 0, ENUM_OFFON}, 0x1a, MI_TARGET_PINBOOST},
- {{0, {"line1.dir", 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
- 0, 0, ENUM_IO}, 0x1a, MI_TARGET_PINDIR},
- {{0, {"line2."AudioNmute, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
- 0, 0, ENUM_OFFON}, 0x1b, MI_TARGET_OUTAMP},
- {{0, {"line2.boost", 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
- 0, 0, ENUM_OFFON}, 0x1b, MI_TARGET_PINBOOST},
- {{0, {"line2.dir", 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
- 0, 0, ENUM_IO}, 0x1b, MI_TARGET_PINDIR},
-
- {{0, {AudioNmode, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_PLAYBACK, 0, 0,
- .un.e={2, {{{"analog", 0}, 0}, {{AzaliaNdigital, 0}, 1}}}}, 0, MI_TARGET_DAC},
- {{0, {AudioNmode, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_RECORD, 0, 0,
- .un.e={2, {{{"analog", 0}, 0}, {{AzaliaNdigital, 0}, 1}}}}, 0, MI_TARGET_ADC},
-};
-
-static int
-alc880_mixer_init(codec_t *this)
-{
- mixer_ctrl_t mc;
-
- this->nmixers = __arraycount(alc880_mixer_items);
- this->szmixers = sizeof(alc880_mixer_items);
- this->mixers = kmem_alloc(this->szmixers, KM_SLEEP);
- memcpy(this->mixers, alc880_mixer_items, sizeof(alc880_mixer_items));
- generic_mixer_fix_indexes(this);
- generic_mixer_default(this);
-
- mc.dev = -1;
- mc.type = AUDIO_MIXER_ENUM;
- mc.un.ord = 0; /* mute: off */
- generic_mixer_set(this, 0x0c, MI_TARGET_INAMP(0), &mc); /* dac->front */
- generic_mixer_set(this, 0x0c, MI_TARGET_INAMP(1), &mc); /* mixer->front */
- generic_mixer_set(this, 0x0d, MI_TARGET_INAMP(0), &mc); /* dac->surround */
- generic_mixer_set(this, 0x0e, MI_TARGET_INAMP(0), &mc); /* dac->clfe */
- generic_mixer_set(this, 0x0f, MI_TARGET_INAMP(0), &mc); /* dac->side */
- mc.un.ord = 1; /* mute: on */
- generic_mixer_set(this, 0x0d, MI_TARGET_INAMP(1), &mc); /* mixer->surround */
- generic_mixer_set(this, 0x0e, MI_TARGET_INAMP(1), &mc); /* mixer->clfe */
- generic_mixer_set(this, 0x0f, MI_TARGET_INAMP(1), &mc); /* mixer->side */
- mc.un.ord = 1; /* pindir: output */
- generic_mixer_set(this, 0x14, MI_TARGET_PINDIR, &mc); /* front */
- generic_mixer_set(this, 0x15, MI_TARGET_PINDIR, &mc); /* surround */
- generic_mixer_set(this, 0x16, MI_TARGET_PINDIR, &mc); /* clfe */
- generic_mixer_set(this, 0x17, MI_TARGET_PINDIR, &mc); /* side */
- generic_mixer_set(this, 0x19, MI_TARGET_PINDIR, &mc); /* mic2 */
- generic_mixer_set(this, 0x1b, MI_TARGET_PINDIR, &mc); /* line2 */
- mc.un.ord = 0; /* pindir: input */
- generic_mixer_set(this, 0x18, MI_TARGET_PINDIR, &mc); /* mic1 */
- generic_mixer_set(this, 0x1a, MI_TARGET_PINDIR, &mc); /* line1 */
- return 0;
-}
-
-static int
-alc880_init_dacgroup(codec_t *this)
-{
- static const convgroupset_t dacs = {
- -1, 2,
- {{4, {0x02, 0x03, 0x04, 0x05}}, /* analog 8ch */
- {1, {0x06}}}}; /* digital */
- static const convgroupset_t adcs = {
- -1, 2,
- {{2, {0x08, 0x09}}, /* analog 4ch */
- {1, {0x0a}}}}; /* digital */
-
- this->dacs = dacs;
- this->adcs = adcs;
- return 0;
-}
-
-/* ----------------------------------------------------------------
- * Realtek ALC882
- * ---------------------------------------------------------------- */
-
-static const mixer_item_t alc882_mixer_items[] = {
- AZ_MIXER_CLASSES,
-
- /* 0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x14,0x15,0x16,0x17 */
- {{0, {"mic1."AudioNmute, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_INPUT,
- 0, 0, ENUM_OFFON}, 0x0b, MI_TARGET_INAMP(0)},
- {{0, {"mic1", 0}, AUDIO_MIXER_VALUE, AZ_CLASS_INPUT,
- 0, 0, .un.v={{"", 0}, 2, MIXER_DELTA(31)}}, 0x0b, MI_TARGET_INAMP(0)},
- {{0, {"mic2."AudioNmute, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_INPUT,
- 0, 0, ENUM_OFFON}, 0x0b, MI_TARGET_INAMP(1)},
- {{0, {"mic2", 0}, AUDIO_MIXER_VALUE, AZ_CLASS_INPUT,
- 0, 0, .un.v={{"", 0}, 2, MIXER_DELTA(31)}}, 0x0b, MI_TARGET_INAMP(1)},
- {{0, {AudioNline"."AudioNmute, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_INPUT,
- 0, 0, ENUM_OFFON}, 0x0b, MI_TARGET_INAMP(2)},
- {{0, {AudioNline, 0}, AUDIO_MIXER_VALUE, AZ_CLASS_INPUT,
- 0, 0, .un.v={{"", 0}, 2, MIXER_DELTA(31)}}, 0x0b, MI_TARGET_INAMP(2)},
- {{0, {AudioNcd"."AudioNmute, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_INPUT,
- 0, 0, ENUM_OFFON}, 0x0b, MI_TARGET_INAMP(4)},
- {{0, {AudioNcd, 0}, AUDIO_MIXER_VALUE, AZ_CLASS_INPUT,
- 0, 0, .un.v={{"", 0}, 2, MIXER_DELTA(31)}}, 0x0b, MI_TARGET_INAMP(4)},
- {{0, {AudioNspeaker"."AudioNmute, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_INPUT,
- 0, 0, ENUM_OFFON}, 0x0b, MI_TARGET_INAMP(5)},
- {{0, {AudioNspeaker, 0}, AUDIO_MIXER_VALUE, AZ_CLASS_INPUT,
- 0, 0, .un.v={{"", 0}, 1, MIXER_DELTA(31)}}, 0x0b, MI_TARGET_INAMP(5)},
-
- {{0, {AudioNmaster, 0}, AUDIO_MIXER_VALUE, AZ_CLASS_OUTPUT,
- 0, 0, .un.v={{"", 0}, 2, MIXER_DELTA(31)}}, 0x0c, MI_TARGET_OUTAMP},
- {{0, {AudioNmaster"."AudioNmute, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
- 0, 0, ENUM_OFFON}, 0x14, MI_TARGET_OUTAMP},
- {{0, {AudioNmaster".boost", 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
- 0, 0, ENUM_OFFON}, 0x14, MI_TARGET_PINBOOST},
- {{0, {AudioNheadphone"."AudioNmute, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
- 0, 0, ENUM_OFFON}, 0x1b, MI_TARGET_OUTAMP},
- {{0, {AudioNheadphone".boost", 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
- 0, 0, ENUM_OFFON}, 0x1b, MI_TARGET_PINBOOST},
- {{0, {AzaliaNfront".dac.mute", 0}, AUDIO_MIXER_ENUM, AZ_CLASS_INPUT,
- 0, 0, ENUM_OFFON}, 0x0c, MI_TARGET_INAMP(0)},
- {{0, {AzaliaNfront".mixer.mute", 0}, AUDIO_MIXER_ENUM, AZ_CLASS_INPUT,
- 0, 0, ENUM_OFFON}, 0x0c, MI_TARGET_INAMP(1)},
-
- {{0, {AudioNsurround, 0}, AUDIO_MIXER_VALUE, AZ_CLASS_OUTPUT,
- 0, 0, .un.v={{"", 0}, 2, MIXER_DELTA(31)}}, 0x0d, MI_TARGET_OUTAMP},
- {{0, {AudioNsurround"."AudioNmute, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
- 0, 0, ENUM_OFFON}, 0x15, MI_TARGET_OUTAMP},
- {{0, {AudioNsurround".boost", 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
- 0, 0, ENUM_OFFON}, 0x15, MI_TARGET_PINBOOST},
-
- {{0, {AzaliaNclfe, 0}, AUDIO_MIXER_VALUE, AZ_CLASS_OUTPUT,
- 0, 0, .un.v={{"", 0}, 2, MIXER_DELTA(31)}}, 0x0e, MI_TARGET_OUTAMP},
- {{0, {AzaliaNclfe"."AudioNmute, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
- 0, 0, ENUM_OFFON}, 0x16, MI_TARGET_OUTAMP},
- {{0, {AzaliaNclfe".boost", 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
- 0, 0, ENUM_OFFON}, 0x16, MI_TARGET_PINBOOST},
-
- {{0, {AzaliaNside, 0}, AUDIO_MIXER_VALUE, AZ_CLASS_OUTPUT,
- 0, 0, .un.v={{"", 0}, 2, MIXER_DELTA(31)}}, 0x0f, MI_TARGET_OUTAMP},
- {{0, {AzaliaNside"."AudioNmute, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
- 0, 0, ENUM_OFFON}, 0x17, MI_TARGET_OUTAMP},
- {{0, {AzaliaNside".boost", 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
- 0, 0, ENUM_OFFON}, 0x17, MI_TARGET_PINBOOST},
-
- /* 0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x14,0x15,0x16,0x17,0xb */
-#define ALC882_MIC1 0x001
-#define ALC882_MIC2 0x002
-#define ALC882_LINE 0x004
-#define ALC882_CD 0x010
-#define ALC882_BEEP 0x020
-#define ALC882_MIX 0x400
-#define ALC882_MASK 0x437
- {{0, {AzaliaNfront"."AudioNmute, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_RECORD,
- 0, 0, ENUM_OFFON}, 0x07, MI_TARGET_INAMP(0)},
- {{0, {AzaliaNfront, 0}, AUDIO_MIXER_VALUE, AZ_CLASS_RECORD,
- 0, 0, .un.v={{"", 0}, 2, MIXER_DELTA(31)}}, 0x07, MI_TARGET_INAMP(0)},
- {{0, {AzaliaNfront"."AudioNsource, 0}, AUDIO_MIXER_SET, AZ_CLASS_RECORD,
- 0, 0, .un.s={6, {{{"mic1", 0}, ALC882_MIC1}, {{"mic2", 0}, ALC882_MIC2},
- {{AudioNline, 0}, ALC882_LINE}, {{AudioNcd, 0}, ALC882_CD},
- {{AudioNspeaker, 0}, ALC882_BEEP},
- {{AudioNmixerout, 0}, ALC882_MIX}}}}, 0x24, -1},
- {{0, {AudioNsurround"."AudioNmute, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_RECORD,
- 0, 0, ENUM_OFFON}, 0x08, MI_TARGET_INAMP(0)},
- {{0, {AudioNsurround, 0}, AUDIO_MIXER_VALUE, AZ_CLASS_RECORD,
- 0, 0, .un.v={{"", 0}, 2, MIXER_DELTA(31)}}, 0x08, MI_TARGET_INAMP(0)},
- {{0, {AudioNsurround"."AudioNsource, 0}, AUDIO_MIXER_SET, AZ_CLASS_RECORD,
- 0, 0, .un.s={6, {{{"mic1", 0}, ALC882_MIC1}, {{"mic2", 0}, ALC882_MIC2},
- {{AudioNline, 0}, ALC882_LINE}, {{AudioNcd, 0}, ALC882_CD},
- {{AudioNspeaker, 0}, ALC882_BEEP},
- {{AudioNmixerout, 0}, ALC882_MIX}}}}, 0x23, -1},
- {{0, {AzaliaNclfe"."AudioNmute, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_RECORD,
- 0, 0, ENUM_OFFON}, 0x09, MI_TARGET_INAMP(0)},
- {{0, {AzaliaNclfe, 0}, AUDIO_MIXER_VALUE, AZ_CLASS_RECORD,
- 0, 0, .un.v={{"", 0}, 2, MIXER_DELTA(31)}}, 0x09, MI_TARGET_INAMP(0)},
- {{0, {AzaliaNclfe"."AudioNsource, 0}, AUDIO_MIXER_SET, AZ_CLASS_RECORD,
- 0, 0, .un.s={6, {{{"mic1", 0}, ALC882_MIC1}, {{"mic2", 0}, ALC882_MIC2},
- {{AudioNline, 0}, ALC882_LINE}, {{AudioNcd, 0}, ALC882_CD},
- {{AudioNspeaker, 0}, ALC882_BEEP},
- {{AudioNmixerout, 0}, ALC882_MIX}}}}, 0x22, -1},
-
- {{0, {AudioNmode, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_PLAYBACK, 0, 0,
- .un.e={2, {{{"analog", 0}, 0}, {{AzaliaNdigital, 0}, 1}}}}, 0, MI_TARGET_DAC},
- {{0, {AudioNmode, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_RECORD, 0, 0,
- .un.e={2, {{{"analog", 0}, 0}, {{AzaliaNdigital, 0}, 1}}}}, 0, MI_TARGET_ADC},
-/* AZ_MIXER_SPDIF(AZ_CLASS_PLAYBACK, 0x06),*/
-};
-
-static int
-alc882_mixer_init(codec_t *this)
-{
- mixer_ctrl_t mc;
-
- this->nmixers = __arraycount(alc882_mixer_items);
- this->szmixers = sizeof(alc882_mixer_items);
- this->mixers = kmem_alloc(this->szmixers, KM_SLEEP);
- memcpy(this->mixers, alc882_mixer_items, sizeof(alc882_mixer_items));
- generic_mixer_fix_indexes(this);
- generic_mixer_default(this);
-
- mc.dev = -1;
- mc.type = AUDIO_MIXER_ENUM;
- mc.un.ord = 1; /* pindir: output */
- generic_mixer_set(this, 0x14, MI_TARGET_PINDIR, &mc);
- generic_mixer_set(this, 0x1b, MI_TARGET_PINDIR, &mc);
- generic_mixer_set(this, 0x15, MI_TARGET_PINDIR, &mc);
- generic_mixer_set(this, 0x16, MI_TARGET_PINDIR, &mc);
- generic_mixer_set(this, 0x17, MI_TARGET_PINDIR, &mc);
- mc.un.ord = 0; /* [0] 0x0c */
- generic_mixer_set(this, 0x14, MI_TARGET_CONNLIST, &mc);
- generic_mixer_set(this, 0x1b, MI_TARGET_CONNLIST, &mc);
- mc.un.ord = 1; /* [1] 0x0d */
- generic_mixer_set(this, 0x15, MI_TARGET_CONNLIST, &mc);
- mc.un.ord = 2; /* [2] 0x0e */
- generic_mixer_set(this, 0x16, MI_TARGET_CONNLIST, &mc);
- mc.un.ord = 2; /* [3] 0x0fb */
- generic_mixer_set(this, 0x17, MI_TARGET_CONNLIST, &mc);
-
- mc.un.ord = 0; /* pindir: input */
- generic_mixer_set(this, 0x18, MI_TARGET_PINDIR, &mc);
- generic_mixer_set(this, 0x19, MI_TARGET_PINDIR, &mc);
- generic_mixer_set(this, 0x1a, MI_TARGET_PINDIR, &mc);
- /* XXX: inamp for 18/19/1a */
-
- mc.un.ord = 0; /* unmute */
- generic_mixer_set(this, 0x24, MI_TARGET_INAMP(0), &mc);
- generic_mixer_set(this, 0x23, MI_TARGET_INAMP(1), &mc);
- generic_mixer_set(this, 0x22, MI_TARGET_INAMP(2), &mc);
- generic_mixer_set(this, 0x0d, MI_TARGET_INAMP(0), &mc);
- generic_mixer_set(this, 0x0e, MI_TARGET_INAMP(0), &mc);
- generic_mixer_set(this, 0x0f, MI_TARGET_INAMP(0), &mc);
- mc.un.ord = 1; /* mute */
- generic_mixer_set(this, 0x0d, MI_TARGET_INAMP(1), &mc);
- generic_mixer_set(this, 0x0e, MI_TARGET_INAMP(1), &mc);
- generic_mixer_set(this, 0x0f, MI_TARGET_INAMP(1), &mc);
- return 0;
-}
-
-static int
-alc882_init_dacgroup(codec_t *this)
-{
-#if 0 /* makes no sense to support for 0x25 node */
- static const convgroupset_t dacs = {
- -1, 3,
- {{4, {0x02, 0x03, 0x04, 0x05}}, /* analog 8ch */
- {1, {0x06}}, /* digital */
- {1, {0x25}}}}; /* another analog */
-#else
- static const convgroupset_t dacs = {
- -1, 2,
- {{4, {0x02, 0x03, 0x04, 0x05}}, /* analog 8ch */
- {1, {0x06}}}}; /* digital */
-#endif
- static const convgroupset_t adcs = {
- -1, 2,
- {{3, {0x07, 0x08, 0x09}}, /* analog 6ch */
- {1, {0x0a}}}}; /* digital */
-
- this->dacs = dacs;
- this->adcs = adcs;
- return 0;
-}
-
-static int
-alc882_set_port(codec_t *this, mixer_ctrl_t *mc)
-{
- const mixer_item_t *m;
- mixer_ctrl_t mc2;
- uint32_t mask, bit;
- int i, err;
-
- if (mc->dev < 0 || mc->dev >= this->nmixers)
- return ENXIO;
- m = &this->mixers[mc->dev];
- if (mc->type != m->devinfo.type)
- return EINVAL;
- if (mc->type == AUDIO_MIXER_CLASS)
- return 0;
- if ((m->nid == 0x22 || m->nid == 0x23 || m->nid == 0x24)
- && m->target == -1) {
- DPRINTF(("%s: hook for record.*.source\n", __func__));
- mc2.dev = -1;
- mc2.type = AUDIO_MIXER_ENUM;
- bit = 1;
- mask = mc->un.mask & ALC882_MASK;
- for (i = 0; i < this->w[m->nid].nconnections && i < 32; i++) {
- mc2.un.ord = (mask & bit) ? 0 : 1;
- err = generic_mixer_set(this, m->nid,
- MI_TARGET_INAMP(i), &mc2);
- if (err)
- return err;
- bit = bit << 1;
- }
- return 0;
- }
- return generic_mixer_set(this, m->nid, m->target, mc);
-}
-
-static int
-alc882_get_port(codec_t *this, mixer_ctrl_t *mc)
-{
- const mixer_item_t *m;
- uint32_t mask, bit, result;
- int i, err;
-
- if (mc->dev < 0 || mc->dev >= this->nmixers)
- return ENXIO;
- m = &this->mixers[mc->dev];
- mc->type = m->devinfo.type;
- if (mc->type == AUDIO_MIXER_CLASS)
- return 0;
- if ((m->nid == 0x22 || m->nid == 0x23 || m->nid == 0x24)
- && m->target == -1) {
- DPRINTF(("%s: hook for record.*.source\n", __func__));
- mask = 0;
- bit = 1;
- for (i = 0; i < this->w[m->nid].nconnections && i < 32; i++) {
- err = this->comresp(this, m->nid, CORB_GET_AMPLIFIER_GAIN_MUTE,
- CORB_GAGM_INPUT | CORB_GAGM_LEFT |
- i, &result);
- if (err)
- return err;
- if ((result & CORB_GAGM_MUTE) == 0)
- mask |= bit;
- bit = bit << 1;
- }
- mc->un.mask = mask & ALC882_MASK;
- return 0;
- }
- return generic_mixer_get(this, m->nid, m->target, mc);
-}
-
-/* ----------------------------------------------------------------
- * Realtek ALC883
- * ALC882 without adc07 and mix24.
- * ---------------------------------------------------------------- */
-
-static int
-alc883_init_dacgroup(codec_t *this)
-{
- static const convgroupset_t dacs = {
- -1, 2,
- {{4, {0x02, 0x03, 0x04, 0x05}}, /* analog 8ch */
- {1, {0x06}}}}; /* digital */
- /* don't support for 0x25 dac */
- static const convgroupset_t adcs = {
- -1, 2,
- {{2, {0x08, 0x09}}, /* analog 4ch */
- {1, {0x0a}}}}; /* digital */
-
- this->dacs = dacs;
- this->adcs = adcs;
- return 0;
-}
-
-static const mixer_item_t alc883_mixer_items[] = {
- AZ_MIXER_CLASSES,
-
- /* 0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x14,0x15,0x16,0x17 */
- {{0, {"mic1."AudioNmute, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_INPUT,
- 0, 0, ENUM_OFFON}, 0x0b, MI_TARGET_INAMP(0)},
- {{0, {"mic1", 0}, AUDIO_MIXER_VALUE, AZ_CLASS_INPUT,
- 0, 0, .un.v={{"", 0}, 2, MIXER_DELTA(31)}}, 0x0b, MI_TARGET_INAMP(0)},
- {{0, {"mic2."AudioNmute, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_INPUT,
- 0, 0, ENUM_OFFON}, 0x0b, MI_TARGET_INAMP(1)},
- {{0, {"mic2", 0}, AUDIO_MIXER_VALUE, AZ_CLASS_INPUT,
- 0, 0, .un.v={{"", 0}, 2, MIXER_DELTA(31)}}, 0x0b, MI_TARGET_INAMP(1)},
- {{0, {AudioNline"."AudioNmute, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_INPUT,
- 0, 0, ENUM_OFFON}, 0x0b, MI_TARGET_INAMP(2)},
- {{0, {AudioNline, 0}, AUDIO_MIXER_VALUE, AZ_CLASS_INPUT,
- 0, 0, .un.v={{"", 0}, 2, MIXER_DELTA(31)}}, 0x0b, MI_TARGET_INAMP(2)},
- {{0, {AudioNcd"."AudioNmute, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_INPUT,
- 0, 0, ENUM_OFFON}, 0x0b, MI_TARGET_INAMP(4)},
- {{0, {AudioNcd, 0}, AUDIO_MIXER_VALUE, AZ_CLASS_INPUT,
- 0, 0, .un.v={{"", 0}, 2, MIXER_DELTA(31)}}, 0x0b, MI_TARGET_INAMP(4)},
- {{0, {AudioNspeaker"."AudioNmute, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_INPUT,
- 0, 0, ENUM_OFFON}, 0x0b, MI_TARGET_INAMP(5)},
- {{0, {AudioNspeaker, 0}, AUDIO_MIXER_VALUE, AZ_CLASS_INPUT,
- 0, 0, .un.v={{"", 0}, 1, MIXER_DELTA(31)}}, 0x0b, MI_TARGET_INAMP(5)},
-
- {{0, {AudioNmaster, 0}, AUDIO_MIXER_VALUE, AZ_CLASS_OUTPUT,
- 0, 0, .un.v={{"", 0}, 2, MIXER_DELTA(31)}}, 0x0c, MI_TARGET_OUTAMP},
- {{0, {AudioNmaster"."AudioNmute, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
- 0, 0, ENUM_OFFON}, 0x14, MI_TARGET_OUTAMP},
- {{0, {AudioNmaster".boost", 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
- 0, 0, ENUM_OFFON}, 0x14, MI_TARGET_PINBOOST},
- {{0, {AudioNheadphone"."AudioNmute, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
- 0, 0, ENUM_OFFON}, 0x1b, MI_TARGET_OUTAMP},
- {{0, {AudioNheadphone".boost", 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
- 0, 0, ENUM_OFFON}, 0x1b, MI_TARGET_PINBOOST},
- {{0, {AzaliaNfront".dac.mute", 0}, AUDIO_MIXER_ENUM, AZ_CLASS_INPUT,
- 0, 0, ENUM_OFFON}, 0x0c, MI_TARGET_INAMP(0)},
- {{0, {AzaliaNfront".mixer.mute", 0}, AUDIO_MIXER_ENUM, AZ_CLASS_INPUT,
- 0, 0, ENUM_OFFON}, 0x0c, MI_TARGET_INAMP(1)},
- {{0, {AudioNsurround, 0}, AUDIO_MIXER_VALUE, AZ_CLASS_OUTPUT,
- 0, 0, .un.v={{"", 0}, 2, MIXER_DELTA(31)}}, 0x0d, MI_TARGET_OUTAMP},
- {{0, {AudioNsurround"."AudioNmute, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
- 0, 0, ENUM_OFFON}, 0x15, MI_TARGET_OUTAMP},
- {{0, {AudioNsurround".boost", 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
- 0, 0, ENUM_OFFON}, 0x15, MI_TARGET_PINBOOST},
- {{0, {AudioNsurround".dac.mut", 0}, AUDIO_MIXER_ENUM, AZ_CLASS_INPUT,
- 0, 0, ENUM_OFFON}, 0x0d, MI_TARGET_INAMP(0)},
- {{0, {AudioNsurround".mixer.m", 0}, AUDIO_MIXER_ENUM, AZ_CLASS_INPUT,
- 0, 0, ENUM_OFFON}, 0x0d, MI_TARGET_INAMP(1)},
-
- {{0, {AzaliaNclfe, 0}, AUDIO_MIXER_VALUE, AZ_CLASS_OUTPUT,
- 0, 0, .un.v={{"", 0}, 2, MIXER_DELTA(31)}}, 0x0e, MI_TARGET_OUTAMP},
- {{0, {AzaliaNclfe"."AudioNmute, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
- 0, 0, ENUM_OFFON}, 0x16, MI_TARGET_OUTAMP},
- {{0, {AzaliaNclfe".boost", 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
- 0, 0, ENUM_OFFON}, 0x16, MI_TARGET_PINBOOST},
- {{0, {AzaliaNclfe".dac.mute", 0}, AUDIO_MIXER_ENUM, AZ_CLASS_INPUT,
- 0, 0, ENUM_OFFON}, 0x0e, MI_TARGET_INAMP(0)},
- {{0, {AzaliaNclfe".mixer.mute", 0}, AUDIO_MIXER_ENUM, AZ_CLASS_INPUT,
- 0, 0, ENUM_OFFON}, 0x0e, MI_TARGET_INAMP(1)},
-
- {{0, {AzaliaNside, 0}, AUDIO_MIXER_VALUE, AZ_CLASS_OUTPUT,
- 0, 0, .un.v={{"", 0}, 2, MIXER_DELTA(31)}}, 0x0f, MI_TARGET_OUTAMP},
- {{0, {AzaliaNside"."AudioNmute, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
- 0, 0, ENUM_OFFON}, 0x17, MI_TARGET_OUTAMP},
- {{0, {AzaliaNside".boost", 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
- 0, 0, ENUM_OFFON}, 0x17, MI_TARGET_PINBOOST},
- {{0, {AzaliaNside".dac.mute", 0}, AUDIO_MIXER_ENUM, AZ_CLASS_INPUT,
- 0, 0, ENUM_OFFON}, 0x0f, MI_TARGET_INAMP(0)},
- {{0, {AzaliaNside".mixer.mute", 0}, AUDIO_MIXER_ENUM, AZ_CLASS_INPUT,
- 0, 0, ENUM_OFFON}, 0x0f, MI_TARGET_INAMP(1)},
-
- {{0, {AudioNsurround"."AudioNmute, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_RECORD,
- 0, 0, ENUM_OFFON}, 0x08, MI_TARGET_INAMP(0)},
- {{0, {AudioNsurround, 0}, AUDIO_MIXER_VALUE, AZ_CLASS_RECORD,
- 0, 0, .un.v={{"", 0}, 2, MIXER_DELTA(31)}}, 0x08, MI_TARGET_INAMP(0)},
- {{0, {AudioNsurround"."AudioNsource, 0}, AUDIO_MIXER_SET, AZ_CLASS_RECORD,
- 0, 0, .un.s={6, {{{"mic1", 0}, ALC882_MIC1}, {{"mic2", 0}, ALC882_MIC2},
- {{AudioNline, 0}, ALC882_LINE}, {{AudioNcd, 0}, ALC882_CD},
- {{AudioNspeaker, 0}, ALC882_BEEP},
- {{AudioNmixerout, 0}, ALC882_MIX}}}}, 0x23, -1},
-
- {{0, {AzaliaNclfe"."AudioNmute, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_RECORD,
- 0, 0, ENUM_OFFON}, 0x09, MI_TARGET_INAMP(0)},
- {{0, {AzaliaNclfe, 0}, AUDIO_MIXER_VALUE, AZ_CLASS_RECORD,
- 0, 0, .un.v={{"", 0}, 2, MIXER_DELTA(31)}}, 0x09, MI_TARGET_INAMP(0)},
- {{0, {AzaliaNclfe"."AudioNsource, 0}, AUDIO_MIXER_SET, AZ_CLASS_RECORD,
- 0, 0, .un.s={6, {{{"mic1", 0}, ALC882_MIC1}, {{"mic2", 0}, ALC882_MIC2},
- {{AudioNline, 0}, ALC882_LINE}, {{AudioNcd, 0}, ALC882_CD},
- {{AudioNspeaker, 0}, ALC882_BEEP},
- {{AudioNmixerout, 0}, ALC882_MIX}}}}, 0x22, -1},
-
- {{0, {"usingdac", 0}, AUDIO_MIXER_ENUM, AZ_CLASS_INPUT, 0, 0,
- .un.e={2, {{{"analog", 0}, 0}, {{"digital", 0}, 1}}}}, 0, MI_TARGET_DAC},
- {{0, {"usingadc", 0}, AUDIO_MIXER_ENUM, AZ_CLASS_RECORD, 0, 0,
- .un.e={2, {{{"analog", 0}, 0}, {{"digital", 0}, 1}}}}, 0, MI_TARGET_ADC},
-};
-
-int
-alc883_mixer_init(codec_t *this)
-{
- mixer_ctrl_t mc;
-
- this->nmixers = __arraycount(alc883_mixer_items);
- this->szmixers = sizeof(alc883_mixer_items);
- this->mixers = kmem_alloc(this->szmixers, KM_SLEEP);
- memcpy(this->mixers, alc883_mixer_items, sizeof(alc883_mixer_items));
- generic_mixer_fix_indexes(this);
- generic_mixer_default(this);
-
- mc.dev = -1;
- mc.type = AUDIO_MIXER_ENUM;
- mc.un.ord = 1; /* pindir: output */
- generic_mixer_set(this, 0x14, MI_TARGET_PINDIR, &mc);
- generic_mixer_set(this, 0x1b, MI_TARGET_PINDIR, &mc);
- generic_mixer_set(this, 0x15, MI_TARGET_PINDIR, &mc);
- generic_mixer_set(this, 0x16, MI_TARGET_PINDIR, &mc);
- generic_mixer_set(this, 0x17, MI_TARGET_PINDIR, &mc);
- mc.un.ord = 0; /* [0] 0x0c */
- generic_mixer_set(this, 0x14, MI_TARGET_CONNLIST, &mc);
- generic_mixer_set(this, 0x1b, MI_TARGET_CONNLIST, &mc);
- mc.un.ord = 1; /* [1] 0x0d */
- generic_mixer_set(this, 0x15, MI_TARGET_CONNLIST, &mc);
- mc.un.ord = 2; /* [2] 0x0e */
- generic_mixer_set(this, 0x16, MI_TARGET_CONNLIST, &mc);
- mc.un.ord = 2; /* [3] 0x0fb */
- generic_mixer_set(this, 0x17, MI_TARGET_CONNLIST, &mc);
-
- mc.un.ord = 0; /* pindir: input */
- generic_mixer_set(this, 0x18, MI_TARGET_PINDIR, &mc);
- generic_mixer_set(this, 0x19, MI_TARGET_PINDIR, &mc);
- generic_mixer_set(this, 0x1a, MI_TARGET_PINDIR, &mc);
- /* XXX: inamp for 18/19/1a */
-
- mc.un.ord = 0; /* unmute */
- generic_mixer_set(this, 0x23, MI_TARGET_INAMP(1), &mc);
- generic_mixer_set(this, 0x22, MI_TARGET_INAMP(2), &mc);
- return 0;
-}
-/* ----------------------------------------------------------------
- * Realtek ALC885
- * ---------------------------------------------------------------- */
-
-static int
-alc885_init_dacgroup(codec_t *this)
-{
- static const convgroupset_t dacs = {
- -1, 2,
- {{4, {0x02, 0x03, 0x04, 0x05}}, /* analog 8ch */
- {1, {0x06}}}}; /* digital */
- /* don't support for 0x25 dac */
- static const convgroupset_t adcs = {
- -1, 2,
- {{3, {0x07, 0x08, 0x09}}, /* analog 6ch */
- {1, {0x0a}}}}; /* digital */
-
- this->dacs = dacs;
- this->adcs = adcs;
- return 0;
-}
-
-/* ----------------------------------------------------------------
- * Realtek ALC888
- * ---------------------------------------------------------------- */
-
-static int
-alc888_init_dacgroup(codec_t *this)
-{
- static const convgroupset_t dacs = {
- -1, 2,
- {{4, {0x02, 0x03, 0x04, 0x05}}, /* analog 8ch */
- {1, {0x06}}}}; /* digital */
- /* don't support for 0x25 dac */
- /* ALC888S has another SPDIF-out 0x10 */
- static const convgroupset_t adcs = {
- -1, 2,
- {{2, {0x08, 0x09}}, /* analog 4ch */
- {1, {0x0a}}}}; /* digital */
-
- this->dacs = dacs;
- this->adcs = adcs;
- return 0;
-}
-
-static int
-alc888_init_widget(const codec_t *this, widget_t *w, nid_t nid)
-{
- switch (nid) {
- case 0x0c:
- strlcpy(w->name, AudioNmaster, sizeof(w->name));
- break;
- }
- return 0;
-}
-
-static int
-alc888_mixer_init(codec_t *this)
-{
- mixer_item_t *m = NULL;
- mixer_devinfo_t *d;
- int err, i, mdac_index = -1;
-
- err = generic_mixer_init(this);
- if (err)
- return err;
-
- /* Clear mixer indexes, to make generic_mixer_fix_indexes happy */
- for (i = 0; i < this->nmixers; i++) {
- d = &this->mixers[i].devinfo;
- d->index = d->prev = d->next = 0;
- }
-
- /* We're looking for front l/r mixer, which we know is nid 0x0c */
- for (i = 0; i < this->nmixers; i++)
- if (this->mixers[i].nid == 0x0c) {
- mdac_index = i;
- break;
- }
- if (mdac_index >= 0) {
- /*
- * ALC888 doesn't have a master mixer, so create a fake
- * inputs.dac that mirrors outputs.master
- */
- err = generic_mixer_ensure_capacity(this, this->nmixers + 1);
- if (err)
- return err;
-
- m = &this->mixers[this->nmixers];
- d = &m->devinfo;
- memcpy(m, &this->mixers[mdac_index], sizeof(*m));
- d->mixer_class = AZ_CLASS_INPUT;
- snprintf(d->label.name, sizeof(d->label.name), AudioNdac);
- this->nmixers++;
- }
-
- /* Recreate mixer indexes and defaults after making a mess of things */
- generic_mixer_fix_indexes(this);
- generic_mixer_default(this);
-
- return 0;
-}
-
-/* ----------------------------------------------------------------
- * Analog Devices AD1981HD
- * ---------------------------------------------------------------- */
-
-#define AD1981HD_THINKPAD 0x201017aa
-
-static const mixer_item_t ad1981hd_mixer_items[] = {
- AZ_MIXER_CLASSES,
-
- {{0, {AzaliaNdigital "." AudioNsource, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
- 0, 0, .un.e={2, {{{"os", 0}, 0}, {{"adc", 0}, 1}}}}, 0x02, MI_TARGET_CONNLIST},
-
- {{0, {"lineout." AudioNsource, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
- 0, 0, .un.e={2, {{{AudioNdac, 0}, 0}, {{AudioNmixerout, 0}, 1}}}},
- 0x05, MI_TARGET_CONNLIST},
- {{0, {"lineout." AudioNmute, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
- 0, 0, ENUM_OFFON}, 0x05, MI_TARGET_OUTAMP},
- {{0, {"lineout", 0}, AUDIO_MIXER_VALUE, AZ_CLASS_OUTPUT,
- 0, 0, .un.v={{"", 0}, 2, MIXER_DELTA(63)}}, 0x05, MI_TARGET_OUTAMP},
- {{0, {"lineout", 0}, AUDIO_MIXER_VALUE, AZ_CLASS_RECORD,
- 0, 0, .un.v={{"", 0}, 2, MIXER_DELTA(3)}}, 0x05, MI_TARGET_INAMP(0)},
- {{0, {"lineout.dir", 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
- 0, 0, ENUM_IO}, 0x05, MI_TARGET_PINDIR},
- {{0, {"lineout.boost", 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
- 0, 0, ENUM_OFFON}, 0x05, MI_TARGET_PINBOOST},
- {{0, {"lineout.eapd", 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
- 0, 0, ENUM_OFFON}, 0x05, MI_TARGET_EAPD},
-
- {{0, {AudioNheadphone ".src", 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
- 0, 0, .un.e={2, {{{AudioNdac, 0}, 0}, {{AudioNmixerout, 0}, 1}}}},
- 0x06, MI_TARGET_CONNLIST},
- {{0, {AudioNheadphone "." AudioNmute, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
- 0, 0, ENUM_OFFON}, 0x06, MI_TARGET_OUTAMP},
- {{0, {AudioNheadphone, 0}, AUDIO_MIXER_VALUE, AZ_CLASS_OUTPUT,
- 0, 0, .un.v={{"", 0}, 2, MIXER_DELTA(63)}}, 0x06, MI_TARGET_OUTAMP},
- {{0, {AudioNheadphone ".boost", 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
- 0, 0, ENUM_OFFON}, 0x06, MI_TARGET_PINBOOST},
-
- {{0, {AudioNmono "." AudioNmute, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
- 0, 0, ENUM_OFFON}, 0x07, MI_TARGET_OUTAMP},
- {{0, {AudioNmono, 0}, AUDIO_MIXER_VALUE, AZ_CLASS_OUTPUT,
- 0, 0, .un.v={{"", 0}, 1, MIXER_DELTA(63)}}, 0x07, MI_TARGET_OUTAMP},
-
- {{0, {AudioNmicrophone, 0}, AUDIO_MIXER_VALUE, AZ_CLASS_RECORD,
- 0, 0, .un.v={{"", 0}, 2, MIXER_DELTA(3)}}, 0x08, MI_TARGET_INAMP(0)},
-
- {{0, {"linein." AudioNsource, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
- 0, 0, .un.e={2, {{{AudioNdac, 0}, 0}, {{AudioNmixerout, 0}, 1}}}},
- 0x09, MI_TARGET_CONNLIST},
- {{0, {"linein." AudioNmute, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
- 0, 0, ENUM_OFFON}, 0x09, MI_TARGET_OUTAMP},
- {{0, {"linein", 0}, AUDIO_MIXER_VALUE, AZ_CLASS_OUTPUT,
- 0, 0, .un.v={{"", 0}, 2, MIXER_DELTA(63)}}, 0x09, MI_TARGET_OUTAMP},
- {{0, {"linein", 0}, AUDIO_MIXER_VALUE, AZ_CLASS_RECORD,
- 0, 0, .un.v={{"", 0}, 2, MIXER_DELTA(3)}}, 0x09, MI_TARGET_INAMP(0)},
- {{0, {"linein.dir", 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
- 0, 0, ENUM_IO}, 0x09, MI_TARGET_PINDIR},
-
- {{0, {AudioNmono "." AudioNsource, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
- 0, 0, .un.e={6, {{{AudioNdac, 0}, 0}, {{"mixedmic", 0}, 1},
- {{"linein", 0}, 2}, {{AudioNmixerout, 0}, 3},
- {{"lineout", 0}, 4}, {{"mic2", 0}, 5}}}},
- 0x0b, MI_TARGET_CONNLIST},
-
- {{0, {"beep." AudioNsource, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_INPUT,
- 0, 0, .un.e={2, {{{"digitalbeep", 0}, 0}, {{"beep", 0}, 1}}}},
- 0x0d, MI_TARGET_CONNLIST},
- {{0, {"beep." AudioNmute, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_INPUT,
- 0, 0, ENUM_OFFON}, 0x0d, MI_TARGET_OUTAMP},
- {{0, {"beep", 0}, AUDIO_MIXER_VALUE, AZ_CLASS_INPUT,
- 0, 0, .un.v={{"", 0}, 1, MIXER_DELTA(15)}}, 0x0d, MI_TARGET_OUTAMP},
-
- {{0, {AudioNdac "." AudioNmute, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_INPUT,
- 0, 0, ENUM_OFFON}, 0x11, MI_TARGET_OUTAMP},
- {{0, {AudioNdac, 0}, AUDIO_MIXER_VALUE, AZ_CLASS_INPUT,
- 0, 0, .un.v={{"", 0}, 2, MIXER_DELTA(31)}}, 0x11, MI_TARGET_OUTAMP},
-
- {{0, {AudioNmicrophone "." AudioNmute, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_INPUT,
- 0, 0, ENUM_OFFON}, 0x12, MI_TARGET_OUTAMP},
- {{0, {AudioNmicrophone, 0}, AUDIO_MIXER_VALUE, AZ_CLASS_INPUT,
- 0, 0, .un.v={{"", 0}, 2, MIXER_DELTA(31)}}, 0x12, MI_TARGET_OUTAMP},
-
- {{0, {"linein." AudioNmute, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_INPUT,
- 0, 0, ENUM_OFFON}, 0x13, MI_TARGET_OUTAMP},
- {{0, {"linein", 0}, AUDIO_MIXER_VALUE, AZ_CLASS_INPUT,
- 0, 0, .un.v={{"", 0}, 2, MIXER_DELTA(31)}}, 0x13, MI_TARGET_OUTAMP},
-
- {{0, {AudioNsource, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_RECORD,
- 0, 0, .un.e={8, {{{"mixedmic", 0}, 0}, {{"linein", 0}, 1},
- {{AudioNmixerout, 0}, 2}, {{AudioNmono, 0}, 3},
- {{AudioNcd, 0}, 4}, {{"lineout", 0}, 5},
- {{"mic2", 0}, 6}, {{AudioNaux, 0}, 7}}}},
- 0x15, MI_TARGET_CONNLIST},
- {{0, {AudioNmute, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_RECORD,
- 0, 0, ENUM_OFFON}, 0x15, MI_TARGET_OUTAMP},
- {{0, {AudioNmaster, 0}, AUDIO_MIXER_VALUE, AZ_CLASS_RECORD,
- 0, 0, .un.v={{"", 0}, 2, MIXER_DELTA(15)}}, 0x15, MI_TARGET_OUTAMP},
-
- {{0, {"mic2." AudioNsource, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
- 0, 0, .un.e={2, {{{AudioNdac, 0}, 0}, {{AudioNmixerout, 0}, 1}}}},
- 0x18, MI_TARGET_CONNLIST},
- {{0, {"mic2." AudioNmute, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
- 0, 0, ENUM_OFFON}, 0x18, MI_TARGET_OUTAMP},
- {{0, {"mic2", 0}, AUDIO_MIXER_VALUE, AZ_CLASS_OUTPUT,
- 0, 0, .un.v={{"", 0}, 2, MIXER_DELTA(63)}}, 0x18, MI_TARGET_OUTAMP},
- {{0, {"mic2", 0}, AUDIO_MIXER_VALUE, AZ_CLASS_RECORD,
- 0, 0, .un.v={{"", 0}, 2, MIXER_DELTA(3)}}, 0x18, MI_TARGET_INAMP(0)},
- {{0, {"mic2.dir", 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
- 0, 0, ENUM_IO}, 0x18, MI_TARGET_PINDIR},
-
- {{0, {"lineout." AudioNmute, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_INPUT,
- 0, 0, ENUM_OFFON}, 0x1a, MI_TARGET_OUTAMP},
- {{0, {"lineout", 0}, AUDIO_MIXER_VALUE, AZ_CLASS_INPUT,
- 0, 0, .un.v={{"", 0}, 2, MIXER_DELTA(31)}}, 0x1a, MI_TARGET_OUTAMP},
-
- {{0, {AudioNaux "." AudioNmute, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_INPUT,
- 0, 0, ENUM_OFFON}, 0x1b, MI_TARGET_OUTAMP},
- {{0, {AudioNaux, 0}, AUDIO_MIXER_VALUE, AZ_CLASS_INPUT,
- 0, 0, .un.v={{"", 0}, 2, MIXER_DELTA(31)}}, 0x1b, MI_TARGET_OUTAMP},
-
- {{0, {"mic2." AudioNmute, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_INPUT,
- 0, 0, ENUM_OFFON}, 0x1c, MI_TARGET_OUTAMP},
- {{0, {"mic2", 0}, AUDIO_MIXER_VALUE, AZ_CLASS_INPUT,
- 0, 0, .un.v={{"", 0}, 2, MIXER_DELTA(31)}}, 0x1c, MI_TARGET_OUTAMP},
-
- {{0, {AudioNcd "." AudioNmute, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_INPUT,
- 0, 0, ENUM_OFFON}, 0x1d, MI_TARGET_OUTAMP},
- {{0, {AudioNcd, 0}, AUDIO_MIXER_VALUE, AZ_CLASS_INPUT,
- 0, 0, .un.v={{"", 0}, 2, MIXER_DELTA(31)}}, 0x1d, MI_TARGET_OUTAMP},
-
- {{0, {"mixedmic.mute1", 0}, AUDIO_MIXER_ENUM, AZ_CLASS_RECORD,
- 0, 0, ENUM_OFFON}, 0x1e, MI_TARGET_OUTAMP},
- {{0, {"mixedmic.mute2", 0}, AUDIO_MIXER_ENUM, AZ_CLASS_RECORD,
- 0, 0, ENUM_OFFON}, 0x1f, MI_TARGET_OUTAMP},
-
- {{0, {AudioNmode, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_PLAYBACK, 0, 0,
- .un.e={2, {{{"analog", 0}, 0}, {{AzaliaNdigital, 0}, 1}}}}, 0, MI_TARGET_DAC},
-};
-
-static int
-ad1981hd_init_widget(const codec_t *this, widget_t *w, nid_t nid)
-{
- switch (nid) {
- case 0x05:
- strlcpy(w->name, AudioNline "out", sizeof(w->name));
- break;
- case 0x06:
- strlcpy(w->name, "hp", sizeof(w->name));
- break;
- case 0x07:
- strlcpy(w->name, AudioNmono, sizeof(w->name));
- break;
- case 0x08:
- strlcpy(w->name, AudioNmicrophone, sizeof(w->name));
- break;
- case 0x09:
- strlcpy(w->name, AudioNline "in", sizeof(w->name));
- break;
- case 0x0d:
- strlcpy(w->name, "beep", sizeof(w->name));
- break;
- case 0x17:
- strlcpy(w->name, AudioNaux, sizeof(w->name));
- break;
- case 0x18:
- strlcpy(w->name, AudioNmicrophone "2", sizeof(w->name));
- break;
- case 0x19:
- strlcpy(w->name, AudioNcd, sizeof(w->name));
- break;
- case 0x1d:
- strlcpy(w->name, AudioNcd, sizeof(w->name));
- break;
- }
- return 0;
-}
-
-static int
-ad1981hd_mixer_init(codec_t *this)
-{
- mixer_ctrl_t mc;
-
- this->nmixers = __arraycount(ad1981hd_mixer_items);
- this->szmixers = sizeof(ad1981hd_mixer_items);
- this->mixers = kmem_alloc(this->szmixers, KM_SLEEP);
- memcpy(this->mixers, ad1981hd_mixer_items, sizeof(ad1981hd_mixer_items));
- generic_mixer_fix_indexes(this);
- generic_mixer_default(this);
-
- if (this->subid == AD1981HD_THINKPAD) {
- mc.dev = -1;
- mc.type = AUDIO_MIXER_ENUM;
- mc.un.ord = 1;
- generic_mixer_set(this, 0x09, MI_TARGET_PINDIR, &mc);
- generic_mixer_set(this, 0x05, MI_TARGET_EAPD, &mc);
- mc.type = AUDIO_MIXER_VALUE;
- mc.un.value.num_channels = 2;
- mc.un.value.level[0] = AUDIO_MAX_GAIN;
- mc.un.value.level[1] = AUDIO_MAX_GAIN;
- generic_mixer_set(this, 0x1a, MI_TARGET_VOLUME, &mc);
- }
- return 0;
-}
-
-/* ----------------------------------------------------------------
- * Analog Devices AD1983
- * ---------------------------------------------------------------- */
-
-static const mixer_item_t ad1983_mixer_items[] = {
- AZ_MIXER_CLASSES,
-
- {{0, {AzaliaNdigital "." AudioNsource, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
- 0, 0, .un.e={2, {{{"os", 0}, 0}, {{"adc", 0}, 1}}}}, 0x02, MI_TARGET_CONNLIST},
-
- {{0, {AudioNspeaker "." AudioNsource, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
- 0, 0, .un.e={2, {{{AudioNdac, 0}, 0}, {{AudioNmixerout, 0}, 1}}}},
- 0x05, MI_TARGET_CONNLIST},
- {{0, {AudioNspeaker "." AudioNmute, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
- 0, 0, ENUM_OFFON}, 0x05, MI_TARGET_OUTAMP},
- {{0, {AudioNspeaker, 0}, AUDIO_MIXER_VALUE, AZ_CLASS_OUTPUT,
- 0, 0, .un.v={{"", 0}, 2, MIXER_DELTA(64)}}, 0x05, MI_TARGET_OUTAMP},
-
- {{0, {AudioNheadphone ".src", 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
- 0, 0, .un.e={2, {{{AudioNdac, 0}, 0}, {{AudioNmixerout, 0}, 1}}}},
- 0x06, MI_TARGET_CONNLIST},
- {{0, {AudioNheadphone "." AudioNmute, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
- 0, 0, ENUM_OFFON}, 0x06, MI_TARGET_OUTAMP},
- {{0, {AudioNheadphone, 0}, AUDIO_MIXER_VALUE, AZ_CLASS_OUTPUT,
- 0, 0, .un.v={{"", 0}, 2, MIXER_DELTA(64)}}, 0x06, MI_TARGET_OUTAMP},
- {{0, {AudioNheadphone ".boost", 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
- 0, 0, ENUM_OFFON}, 0x06, MI_TARGET_PINBOOST},
-
- {{0, {AudioNmono "." AudioNmute, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
- 0, 0, ENUM_OFFON}, 0x07, MI_TARGET_OUTAMP},
- {{0, {AudioNmono, 0}, AUDIO_MIXER_VALUE, AZ_CLASS_OUTPUT,
- 0, 0, .un.v={{"", 0}, 1, MIXER_DELTA(64)}}, 0x07, MI_TARGET_OUTAMP},
-
- {{0, {AudioNmono "." AudioNsource, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
- 0, 0, .un.e={4, {{{AudioNdac, 0}, 0}, {{AudioNmicrophone, 0}, 1},
- {{AudioNline, 0}, 2}, {{AudioNmixerout, 0}, 3}}}},
- 0x0b, MI_TARGET_CONNLIST},
-
- {{0, {AudioNmicrophone "." AudioNpreamp "." AudioNmute, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_INPUT,
- 0, 0, ENUM_OFFON}, 0x0c, MI_TARGET_OUTAMP},
- {{0, {AudioNmicrophone "." AudioNpreamp, 0}, AUDIO_MIXER_VALUE, AZ_CLASS_INPUT,
- 0, 0, .un.v={{"", 0}, 2, MIXER_DELTA(4)}}, 0x0c, MI_TARGET_OUTAMP},
- {{0, {AudioNmicrophone "." AudioNsource, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_INPUT,
- 0, 0, .un.e={2, {{{AudioNmicrophone, 0}, 0}, {{AudioNline, 0}, 1}}}},
- 0x0c, MI_TARGET_CONNLIST},
-
- {{0, {AudioNline "." AudioNsource, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_INPUT,
- 0, 0, .un.e={2, {{{AudioNline, 0}, 0}, {{AudioNmicrophone, 0}, 1}}}},
- 0x0d, MI_TARGET_CONNLIST},
-
- {{0, {"beep." AudioNmute, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_INPUT,
- 0, 0, ENUM_OFFON}, 0x10, MI_TARGET_OUTAMP},
- {{0, {"beep", 0}, AUDIO_MIXER_VALUE, AZ_CLASS_INPUT,
- 0, 0, .un.v={{"", 0}, 1, MIXER_DELTA(16)}}, 0x10, MI_TARGET_OUTAMP},
-
- {{0, {AudioNdac "." AudioNmute, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_INPUT,
- 0, 0, ENUM_OFFON}, 0x11, MI_TARGET_OUTAMP},
- {{0, {AudioNdac, 0}, AUDIO_MIXER_VALUE, AZ_CLASS_INPUT,
- 0, 0, .un.v={{"", 0}, 2, MIXER_DELTA(32)}}, 0x11, MI_TARGET_OUTAMP},
-
- {{0, {AudioNmicrophone "." AudioNmute, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_INPUT,
- 0, 0, ENUM_OFFON}, 0x12, MI_TARGET_OUTAMP},
- {{0, {AudioNmicrophone, 0}, AUDIO_MIXER_VALUE, AZ_CLASS_INPUT,
- 0, 0, .un.v={{"", 0}, 2, MIXER_DELTA(32)}}, 0x12, MI_TARGET_OUTAMP},
-
- {{0, {AudioNline "." AudioNmute, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_INPUT,
- 0, 0, ENUM_OFFON}, 0x13, MI_TARGET_OUTAMP},
- {{0, {AudioNline, 0}, AUDIO_MIXER_VALUE, AZ_CLASS_INPUT,
- 0, 0, .un.v={{"", 0}, 2, MIXER_DELTA(32)}}, 0x13, MI_TARGET_OUTAMP},
-
- {{0, {AudioNsource, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_RECORD,
- 0, 0, .un.e={4, {{{AudioNmicrophone, 0}, 0}, {{AudioNline, 0}, 1},
- {{AudioNmixerout, 0}, 2}, {{AudioNmono, 0}, 3}}}},
- 0x14, MI_TARGET_CONNLIST},
- {{0, {AudioNmute, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_RECORD,
- 0, 0, ENUM_OFFON}, 0x14, MI_TARGET_OUTAMP},
- {{0, {AudioNvolume, 0}, AUDIO_MIXER_VALUE, AZ_CLASS_RECORD,
- 0, 0, .un.v={{"", 0}, 2, MIXER_DELTA(16)}}, 0x14, MI_TARGET_OUTAMP},
-
- {{0, {AudioNmode, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_PLAYBACK, 0, 0,
- .un.e={2, {{{"analog", 0}, 0}, {{AzaliaNdigital, 0}, 1}}}}, 0, MI_TARGET_DAC},
-};
-
-static int
-ad1983_mixer_init(codec_t *this)
-{
- mixer_ctrl_t mc;
-
- this->nmixers = __arraycount(ad1983_mixer_items);
- this->szmixers = sizeof(ad1983_mixer_items);
- this->mixers = kmem_alloc(this->szmixers, KM_SLEEP);
- memcpy(this->mixers, ad1983_mixer_items, sizeof(ad1983_mixer_items));
- generic_mixer_fix_indexes(this);
- generic_mixer_default(this);
-
-#define AD198X_EVENT_HP 1
-#define AD198X_EVENT_SPEAKER 2
-
- mc.dev = -1; /* no need for generic_mixer_set() */
- mc.type = AUDIO_MIXER_ENUM;
- mc.un.ord = 1; /* connlist: mixerout */
- generic_mixer_set(this, 0x05, MI_TARGET_CONNLIST, &mc);
- generic_mixer_set(this, 0x06, MI_TARGET_CONNLIST, &mc);
- mc.un.ord = 3; /* connlist: mixerout */
- generic_mixer_set(this, 0x0b, MI_TARGET_CONNLIST, &mc);
-
- /* setup a unsolicited event for the headphones and speaker */
- this->comresp(this, 0x05, CORB_SET_UNSOLICITED_RESPONSE,
- CORB_UNSOL_ENABLE | AD198X_EVENT_SPEAKER, NULL);
- this->comresp(this, 0x06, CORB_SET_UNSOLICITED_RESPONSE,
- CORB_UNSOL_ENABLE | AD198X_EVENT_HP, NULL);
- ad1983_unsol_event(this, AD198X_EVENT_SPEAKER);
- ad1983_unsol_event(this, AD198X_EVENT_HP);
- return 0;
-}
-
-static int
-ad1983_unsol_event(codec_t *this, int tag)
-{
- int err;
- uint32_t value;
- mixer_ctrl_t mc;
-
- mc.dev = -1;
- mc.type = AUDIO_MIXER_ENUM;
-
- switch (tag) {
- case AD198X_EVENT_HP:
- err = this->comresp(this, 0x06, CORB_GET_PIN_SENSE, 0, &value);
- if (err)
- break;
- if (value & CORB_PS_PRESENCE) {
- DPRINTF(("%s: headphone has been inserted.\n", __func__));
- mc.un.ord = 1; /* mute */
- generic_mixer_set(this, 0x05, MI_TARGET_OUTAMP, &mc);
- generic_mixer_set(this, 0x07, MI_TARGET_OUTAMP, &mc);
- } else {
- DPRINTF(("%s: headphone has been pulled out.\n", __func__));
- mc.un.ord = 0; /* unmute */
- generic_mixer_set(this, 0x05, MI_TARGET_OUTAMP, &mc);
- /* if no speaker unmute internal mono */
- err = this->comresp(this, 0x05, CORB_GET_PIN_SENSE, 0, &value);
- if (err)
- break;
- if (!(value & CORB_PS_PRESENCE))
- generic_mixer_set(this, 0x07, MI_TARGET_OUTAMP, &mc);
- }
- break;
- case AD198X_EVENT_SPEAKER:
- err = this->comresp(this, 0x05, CORB_GET_PIN_SENSE, 0, &value);
- if (err)
- break;
- if (value & CORB_PS_PRESENCE) {
- DPRINTF(("%s: speaker has been inserted.\n", __func__));
- mc.un.ord = 1; /* mute */
- generic_mixer_set(this, 0x07, MI_TARGET_OUTAMP, &mc);
- } else {
- DPRINTF(("%s: speaker has been pulled out.\n", __func__));
- /* if no headphones unmute internal mono */
- err = this->comresp(this, 0x06, CORB_GET_PIN_SENSE, 0, &value);
- if (err)
- break;
- if (!(value & CORB_PS_PRESENCE)) {
- mc.un.ord = 0; /* unmute */
- generic_mixer_set(this, 0x07, MI_TARGET_OUTAMP, &mc);
- }
- }
- break;
- default:
- printf("%s: unknown tag: %d\n", __func__, tag);
- }
- return 0;
-}
-
-/* ----------------------------------------------------------------
- * Analog Devices AD1984
- * ---------------------------------------------------------------- */
-
-#define AD1984_THINKPAD 0x20ac17aa
-#define AD1984_DELL_OPTIPLEX_755 0x02111028
-#define AD1984A_DELL_OPTIPLEX_760 0x027f1028
-
-static int
-ad1984_init_dacgroup(codec_t *this)
-{
- static const convgroupset_t dacs = {
- -1, 2,
- {{2, {0x04, 0x03}}, /* analog 4ch */
- {1, {0x02}}}}; /* digital */
- static const convgroupset_t adcs = {
- -1, 3,
- {{2, {0x08, 0x09}}, /* analog 4ch */
- {1, {0x06}}, /* digital */
- {1, {0x05}}}}; /* digital */
- this->dacs = dacs;
- this->adcs = adcs;
- return 0;
-}
-
-static int
-ad1984_mixer_init(codec_t *this)
-{
- int err;
-
- err = generic_mixer_autoinit(this);
- if (err)
- return err;
-
- if (this->subid == AD1984_DELL_OPTIPLEX_755 ||
- this->subid == AD1984A_DELL_OPTIPLEX_760) {
- /* setup a unsolicited event for the headphones and speaker */
- this->comresp(this, 0x12, CORB_SET_UNSOLICITED_RESPONSE,
- CORB_UNSOL_ENABLE | AD198X_EVENT_SPEAKER, NULL);
- this->comresp(this, 0x11, CORB_SET_UNSOLICITED_RESPONSE,
- CORB_UNSOL_ENABLE | AD198X_EVENT_HP, NULL);
- ad1984_unsol_event(this, AD198X_EVENT_SPEAKER);
- ad1984_unsol_event(this, AD198X_EVENT_HP);
- }
-
- return 0;
-}
-
-static int
-ad1984_init_widget(const codec_t *this, widget_t *w, nid_t nid)
-{
- switch (nid) {
- case 0x07:
- strlcpy(w->name, "hp", sizeof(w->name));
- break;
- case 0x0a:
- strlcpy(w->name, "spkr", sizeof(w->name));
- break;
- case 0x0b:
- strlcpy(w->name, AudioNaux, sizeof(w->name));
- break;
- case 0x0c:
- strlcpy(w->name, "adc08", sizeof(w->name));
- break;
- case 0x0d:
- strlcpy(w->name, "adc09", sizeof(w->name));
- break;
- case 0x0e:
- strlcpy(w->name, AudioNmono "sel", sizeof(w->name));
- break;
- case 0x0f:
- strlcpy(w->name, AudioNaux "sel", sizeof(w->name));
- break;
- case 0x10:
- strlcpy(w->name, "beep", sizeof(w->name));
- break;
- case 0x1e:
- strlcpy(w->name, AudioNmono, sizeof(w->name));
- break;
- case 0x22:
- strlcpy(w->name, "hp" "sel", sizeof(w->name));
- break;
- case 0x23:
- strlcpy(w->name, "dock" "sel", sizeof(w->name));
- break;
- case 0x24:
- strlcpy(w->name, "dock", sizeof(w->name));
- break;
- case 0x25:
- strlcpy(w->name, "dock.pre", sizeof(w->name));
- break;
- default:
- return generic_mixer_init_widget(this, w, nid);
- }
-
- return 0;
-}
-
-static int
-ad1984_unsol_event(codec_t *this, int tag)
-{
- int err;
- uint32_t value;
- mixer_ctrl_t mc;
-
- mc.dev = -1;
- mc.type = AUDIO_MIXER_ENUM;
-
- switch (tag) {
- case AD198X_EVENT_HP:
- err = this->comresp(this, 0x11, CORB_GET_PIN_SENSE, 0, &value);
- if (err)
- break;
- if (value & CORB_PS_PRESENCE) {
- DPRINTF(("%s: headphone has been inserted.\n", __func__));
- mc.un.ord = 1; /* mute */
- generic_mixer_set(this, 0x12, MI_TARGET_OUTAMP, &mc);
- generic_mixer_set(this, 0x13, MI_TARGET_OUTAMP, &mc);
- } else {
- DPRINTF(("%s: headphone has been pulled out.\n", __func__));
- mc.un.ord = 0; /* unmute */
- generic_mixer_set(this, 0x12, MI_TARGET_OUTAMP, &mc);
- /* if no speaker unmute internal mono */
- err = this->comresp(this, 0x12, CORB_GET_PIN_SENSE, 0, &value);
- if (err)
- break;
- if (!(value & CORB_PS_PRESENCE))
- generic_mixer_set(this, 0x13, MI_TARGET_OUTAMP, &mc);
- }
- break;
- case AD198X_EVENT_SPEAKER:
- err = this->comresp(this, 0x12, CORB_GET_PIN_SENSE, 0, &value);
- if (err)
- break;
- if (value & CORB_PS_PRESENCE) {
- DPRINTF(("%s: speaker has been inserted.\n", __func__));
- mc.un.ord = 1; /* mute */
- generic_mixer_set(this, 0x13, MI_TARGET_OUTAMP, &mc);
- } else {
- DPRINTF(("%s: speaker has been pulled out.\n", __func__));
- /* if no headphones unmute internal mono */
- err = this->comresp(this, 0x11, CORB_GET_PIN_SENSE, 0, &value);
- if (err)
- break;
- if (!(value & CORB_PS_PRESENCE)) {
- mc.un.ord = 0; /* unmute */
- generic_mixer_set(this, 0x13, MI_TARGET_OUTAMP, &mc);
- }
- }
- break;
- default:
- printf("%s: unknown tag: %d\n", __func__, tag);
- }
- return 0;
-}
-
-/* ----------------------------------------------------------------
- * Analog Devices AD1986A
- * ---------------------------------------------------------------- */
-
-static const mixer_item_t ad1986a_mixer_items[] = {
- AZ_MIXER_CLASSES,
-
- {{0, {AzaliaNdigital "." AudioNsource, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
- 0, 0, .un.e={2, {{{"hdaudio", 0}, 0}, {{"recordout", 0}, 1}}}}, 0x02, MI_TARGET_CONNLIST},
-
-#if 0
- /* fix to mixerout (default) */
- {{0, {AudioNheadphone ".src", 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
- 0, 0, .un.e={3, {{{AudioNmixerout, 0}, 0}, {{"surrounddac", 0}, 1},
- {{"clfedac", 0}, 2}}}}, 0x0a, MI_TARGET_CONNLIST},
-#endif
- {{0, {AudioNheadphone "." AudioNmute, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
- 0, 0, ENUM_OFFON}, 0x1a, MI_TARGET_OUTAMP},
- {{0, {AudioNheadphone "." "boost", 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
- 0, 0, ENUM_OFFON}, 0x1a, MI_TARGET_PINBOOST},
- {{0, {AudioNheadphone, 0}, AUDIO_MIXER_VALUE, AZ_CLASS_OUTPUT,
- 0, 0, .un.v={{"", 0}, 2, MIXER_DELTA(31)}}, 0x1a, MI_TARGET_OUTAMP},
-
-#if 0
- /* fix to mixerout (default) */
- {{0, {AudioNline "." AudioNsource, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
- 0, 0, .un.e={2, {{{AudioNmixerout, 0}, 0}, {{"surrounddac", 0}, 1}}}},
- 0x0b, MI_TARGET_CONNLIST},
-#endif
- {{0, {AudioNline "." AudioNmute, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
- 0, 0, ENUM_OFFON}, 0x1b, MI_TARGET_OUTAMP},
- {{0, {AudioNline "." "boost", 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
- 0, 0, ENUM_OFFON}, 0x1b, MI_TARGET_PINBOOST},
- {{0, {AudioNline "." "eapd", 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
- 0, 0, ENUM_OFFON}, 0x1b, MI_TARGET_EAPD},
- {{0, {AudioNline, 0}, AUDIO_MIXER_VALUE, AZ_CLASS_OUTPUT,
- 0, 0, .un.v={{"", 0}, 2, MIXER_DELTA(31)}}, 0x1b, MI_TARGET_OUTAMP},
-
-#if 0
- /* fix to the surround DAC (default) */
- {{0, {AudioNsurround "." AudioNsource, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
- 0, 0, .un.e={2, {{{"surrounddac", 0}, 0}, {{AudioNmixerout, 0}, 1}}}},
- 0x0c, MI_TARGET_CONNLIST},
- /* unmute */
- {{0, {AudioNsurround "." AudioNmute, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
- 0, 0, ENUM_OFFON}, 0x1c, MI_TARGET_OUTAMP},
- /* fix to output */
- {{0, {AudioNsurround "." "dir", 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
- 0, 0, ENUM_IO}, 0x1c, MI_TARGET_PINDIR},
- /* fix to maximum */
- {{0, {AudioNsurround, 0}, AUDIO_MIXER_VALUE, AZ_CLASS_OUTPUT,
- 0, 0, .un.v={{"", 0}, 2, MIXER_DELTA(31)}}, 0x1c, MI_TARGET_OUTAMP},
-#endif
- {{0, {AudioNsurround "." AudioNmute, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
- 0, 0, ENUM_OFFON}, 0x04, MI_TARGET_OUTAMP},
- {{0, {AudioNsurround, 0}, AUDIO_MIXER_VALUE, AZ_CLASS_OUTPUT,
- 0, 0, .un.v={{"", 0}, 2, MIXER_DELTA(31)}}, 0x04, MI_TARGET_OUTAMP},
-
-#if 0
- /* fix to the clfe DAC (default) */
- {{0, {AzaliaNclfe "." AudioNsource, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
- 0, 0, .un.e={2, {{{"clfedac", 0}, 0}, {{"mixeroutmono", 0}, 1}}}},
- 0x0d, MI_TARGET_CONNLIST},
- /* unmute */
- {{0, {AzaliaNclfe "." AudioNmute, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
- 0, 0, ENUM_OFFON}, 0x1d, MI_TARGET_OUTAMP},
- /* fix to output */
- {{0, {AzaliaNclfe "." "dir", 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
- 0, 0, ENUM_IO}, 0x1d, MI_TARGET_PINDIR},
- /* fix to maximum */
- {{0, {AzaliaNclfe, 0}, AUDIO_MIXER_VALUE, AZ_CLASS_OUTPUT,
- 0, 0, .un.v={{"", 0}, 2, MIXER_DELTA(31)}}, 0x1d, MI_TARGET_OUTAMP},
-#endif
- {{0, {AzaliaNclfe "." AudioNmute, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
- 0, 0, ENUM_OFFON}, 0x05, MI_TARGET_OUTAMP},
- {{0, {AzaliaNclfe, 0}, AUDIO_MIXER_VALUE, AZ_CLASS_OUTPUT,
- 0, 0, .un.v={{"", 0}, 2, MIXER_DELTA(31)}}, 0x05, MI_TARGET_OUTAMP},
- {{0, {AzaliaNclfe "." "lrswap", 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
- 0, 0, ENUM_OFFON}, 0x1d, MI_TARGET_LRSWAP},
-
- {{0, {AudioNmono "." AudioNsource, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
- 0, 0, .un.e={2, {{{AudioNmixerout, 0}, 0}, {{AudioNmicrophone, 0}, 1}}}},
- 0x0e, MI_TARGET_CONNLIST},
- {{0, {AudioNmono "." AudioNmute, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
- 0, 0, ENUM_OFFON}, 0x1e, MI_TARGET_OUTAMP},
- {{0, {AudioNmono, 0}, AUDIO_MIXER_VALUE, AZ_CLASS_OUTPUT,
- 0, 0, .un.v={{"", 0}, 2, MIXER_DELTA(31)}}, 0x1e, MI_TARGET_OUTAMP},
-
- /* Front DAC */
- {{0, {AudioNdac "." AudioNmute, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_INPUT,
- 0, 0, ENUM_OFFON}, 0x03, MI_TARGET_OUTAMP},
- {{0, {AudioNdac, 0}, AUDIO_MIXER_VALUE, AZ_CLASS_INPUT,
- 0, 0, .un.v={{"", 0}, 2, MIXER_DELTA(31)}}, 0x03, MI_TARGET_OUTAMP},
-
-#if 0
- /* 0x09: 5.1 -> Stereo Downmix */
- {{0, {"downmix" "." AudioNmute, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_INPUT,
- 0, 0, ENUM_OFFON}, 0x09, MI_TARGET_OUTAMP},
-#endif
-
-#if 0
- /* mic source is mic jack (default) */
- {{0, {AudioNmicrophone "." AudioNsource, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_INPUT,
- 0, 0, .un.e={8, {{{AudioNmicrophone, 0}, 0}, {{AudioNline, 0}, 1},
- {{AzaliaNclfe, 0}, 2}, {{AzaliaNclfe "2", 0}, 3},
- {{"micclfe", 0}, 4}, {{"micline", 0}, 5},
- {{"clfeline", 0}, 6}, {{"miclineclfe", 0}, 7}}}},
- 0x0f, MI_TARGET_CONNLIST},
-#endif
- {{0, {AudioNmicrophone "." "gain", 0}, AUDIO_MIXER_VALUE, AZ_CLASS_RECORD,
- 0, 0, .un.v={{"", 0}, 2, MIXER_DELTA(3)}}, 0x0f, MI_TARGET_OUTAMP},
- {{0, {AudioNmicrophone "." AudioNmute, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_RECORD,
- 0, 0, ENUM_OFFON}, 0x13, MI_TARGET_OUTAMP},
- {{0, {AudioNmicrophone, 0}, AUDIO_MIXER_VALUE, AZ_CLASS_RECORD,
- 0, 0, .un.v={{"", 0}, 2, MIXER_DELTA(31)}}, 0x13, MI_TARGET_OUTAMP},
-
-#if 0
- /* line source is line jack (default) */
- {{0, {AudioNline "." AudioNsource, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_INPUT,
- 0, 0, .un.e={3, {{{AudioNline, 0}, 0}, {{AudioNsurround, 0}, 1},
- {{AudioNmicrophone, 0}, 2}}}}, 0x10, MI_TARGET_CONNLIST},
-#endif
- {{0, {AudioNline "." AudioNmute, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_INPUT,
- 0, 0, ENUM_OFFON}, 0x17, MI_TARGET_OUTAMP},
- {{0, {AudioNline, 0}, AUDIO_MIXER_VALUE, AZ_CLASS_INPUT,
- 0, 0, .un.v={{"", 0}, 2, MIXER_DELTA(31)}}, 0x17, MI_TARGET_OUTAMP},
-
- {{0, {"phone" "." AudioNmute, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_INPUT,
- 0, 0, ENUM_OFFON}, 0x14, MI_TARGET_OUTAMP},
- {{0, {"phone", 0}, AUDIO_MIXER_VALUE, AZ_CLASS_INPUT,
- 0, 0, .un.v={{"", 0}, 2, MIXER_DELTA(31)}}, 0x14, MI_TARGET_OUTAMP},
-
- {{0, {AudioNcd "." AudioNmute, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_INPUT,
- 0, 0, ENUM_OFFON}, 0x15, MI_TARGET_OUTAMP},
- {{0, {AudioNcd, 0}, AUDIO_MIXER_VALUE, AZ_CLASS_INPUT,
- 0, 0, .un.v={{"", 0}, 2, MIXER_DELTA(31)}}, 0x15, MI_TARGET_OUTAMP},
-
- {{0, {AudioNaux "." AudioNmute, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_INPUT,
- 0, 0, ENUM_OFFON}, 0x16, MI_TARGET_OUTAMP},
- {{0, {AudioNaux, 0}, AUDIO_MIXER_VALUE, AZ_CLASS_INPUT,
- 0, 0, .un.v={{"", 0}, 2, MIXER_DELTA(31)}}, 0x16, MI_TARGET_OUTAMP},
-
- {{0, {AudioNspeaker "." AudioNmute, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_INPUT,
- 0, 0, ENUM_OFFON}, 0x18, MI_TARGET_OUTAMP},
- {{0, {AudioNspeaker, 0}, AUDIO_MIXER_VALUE, AZ_CLASS_INPUT,
- 0, 0, .un.v={{"", 0}, 2, MIXER_DELTA(15)}}, 0x18, MI_TARGET_OUTAMP},
-
-
- /* 0x11: inputs.sel11.source=sel0f [ sel0f mix2b ] XXXX
- inputs.sel11.lrswap=off [ off on ] XXXX */
-
- {{0, {AudioNsource, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_RECORD,
- 0, 0, .un.e={7, {{{AudioNmicrophone, 0}, 0}, {{AudioNcd, 0}, 1},
- {{AudioNaux, 0}, 2}, {{AudioNline, 0}, 3},
- {{AudioNmixerout, 0}, 4}, {{"mixeroutmono", 0}, 5},
- {{"phone", 0}, 6}}}},
- 0x12, MI_TARGET_CONNLIST},
- {{0, {AudioNvolume "." AudioNmute, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_RECORD,
- 0, 0, ENUM_OFFON}, 0x12, MI_TARGET_OUTAMP},
- {{0, {AudioNvolume, 0}, AUDIO_MIXER_VALUE, AZ_CLASS_RECORD,
- 0, 0, .un.v={{"", 0}, 2, MIXER_DELTA(15)}}, 0x12, MI_TARGET_OUTAMP},
-
- {{0, {AudioNmode, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_PLAYBACK, 0, 0,
- .un.e={2, {{{"analog", 0}, 0}, {{AzaliaNdigital, 0}, 1}}}}, 0, MI_TARGET_DAC},
-};
-
-static int
-ad1986a_mixer_init(codec_t *this)
-{
- mixer_ctrl_t mc;
-
- this->nmixers = __arraycount(ad1986a_mixer_items);
- this->szmixers = sizeof(ad1986a_mixer_items);
- this->mixers = kmem_alloc(this->szmixers, KM_SLEEP);
- memcpy(this->mixers, ad1986a_mixer_items, sizeof(ad1986a_mixer_items));
- generic_mixer_fix_indexes(this);
- generic_mixer_default(this);
-
- mc.dev = -1;
- mc.type = AUDIO_MIXER_ENUM;
- mc.un.ord = 0; /* unmute */
- generic_mixer_set(this, 0x1c, MI_TARGET_OUTAMP, &mc);
- mc.un.ord = 1; /* dir: output */
- generic_mixer_set(this, 0x1c, MI_TARGET_PINDIR, &mc);
- mc.type = AUDIO_MIXER_VALUE;
- mc.un.value.num_channels = 2;
- mc.un.value.level[0] = AUDIO_MAX_GAIN;
- mc.un.value.level[1] = AUDIO_MAX_GAIN;
- generic_mixer_set(this, 0x1c, MI_TARGET_VOLUME, &mc);
- mc.type = AUDIO_MIXER_ENUM;
- mc.un.ord = 0; /* unmute */
- generic_mixer_set(this, 0x1d, MI_TARGET_OUTAMP, &mc);
- mc.un.ord = 1; /* dir: output */
- generic_mixer_set(this, 0x1d, MI_TARGET_PINDIR, &mc);
- mc.type = AUDIO_MIXER_VALUE;
- mc.un.value.num_channels = 2;
- mc.un.value.level[0] = AUDIO_MAX_GAIN;
- mc.un.value.level[1] = AUDIO_MAX_GAIN;
- generic_mixer_set(this, 0x1d, MI_TARGET_VOLUME, &mc);
- return 0;
-}
-
-static int
-ad1986a_init_dacgroup(codec_t *this)
-{
- static const convgroupset_t dacs = {
- -1, 2,
- {{6, {0x03, 0x04, 0x05}}, /* analog 6ch */
- {1, {0x02}}}}; /* digital */
- static const convgroupset_t adcs = {
- -1, 1,
- {{1, {0x06}}}}; /* analog 2ch */
-
- this->dacs = dacs;
- this->adcs = adcs;
- return 0;
-}
-
-/* ----------------------------------------------------------------
- * Analog Devices AD1988A/AD1988B
- * ---------------------------------------------------------------- */
-
-static int
-ad1988_init_dacgroup(codec_t *this)
-{
- static const convgroupset_t dacs = {
- -1, 3,
- {{4, {0x04, 0x05, 0x06, 0x0a}}, /* analog 8ch */
- {1, {0x02}}, /* digital */
- {1, {0x03}}}}; /* another analog */
- static const convgroupset_t adcs = {
- -1, 2,
- {{2, {0x08, 0x09, 0x0f}}, /* analog 6ch */
- {1, {0x07}}}}; /* digital */
-
- this->dacs = dacs;
- this->adcs = adcs;
- return 0;
-}
-
-/* ----------------------------------------------------------------
- * CMedia CMI9880
- * ---------------------------------------------------------------- */
-
-static const mixer_item_t cmi9880_mixer_items[] = {
- AZ_MIXER_CLASSES,
-
- {{0, {AudioNmaster"."AudioNmute, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
- 0, 0, ENUM_OFFON}, 0x03, MI_TARGET_OUTAMP},
- {{0, {AudioNsurround"."AudioNmute, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
- 0, 0, ENUM_OFFON}, 0x04, MI_TARGET_OUTAMP},
- {{0, {AzaliaNclfe"."AudioNmute, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
- 0, 0, ENUM_OFFON}, 0x05, MI_TARGET_OUTAMP},
- {{0, {AzaliaNside"."AudioNmute, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
- 0, 0, ENUM_OFFON}, 0x06, MI_TARGET_OUTAMP},
- {{0, {AzaliaNdigital"."AudioNmute, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
- 0, 0, ENUM_OFFON}, 0x07, MI_TARGET_OUTAMP},
-
- {{0, {AzaliaNfront"."AudioNmute, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_RECORD,
- 0, 0, ENUM_OFFON}, 0x08, MI_TARGET_INAMP(0)},
- {{0, {AzaliaNfront, 0}, AUDIO_MIXER_VALUE, AZ_CLASS_RECORD,
- 0, 0, .un.v={{"", 0}, 2, MIXER_DELTA(30)}}, 0x08, MI_TARGET_INAMP(0)},
- {{0, {AzaliaNfront"."AudioNsource, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_RECORD,
- 0, 0, .un.e={4, {{{AudioNmicrophone, 0}, 5}, {{AudioNcd, 0}, 6},
- {{"line1", 0}, 7}, {{"line2", 0}, 8}}}},
- 0x08, MI_TARGET_CONNLIST},
- {{0, {AudioNsurround"."AudioNmute, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_RECORD,
- 0, 0, ENUM_OFFON}, 0x09, MI_TARGET_INAMP(0)},
- {{0, {AudioNsurround, 0}, AUDIO_MIXER_VALUE, AZ_CLASS_RECORD,
- 0, 0, .un.v={{"", 0}, 2, MIXER_DELTA(30)}}, 0x09, MI_TARGET_INAMP(0)},
- {{0, {AudioNsurround"."AudioNsource, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_RECORD,
- 0, 0, .un.e={4, {{{AudioNmicrophone, 0}, 5}, {{AudioNcd, 0}, 6},
- {{"line1", 0}, 7}, {{"line2", 0}, 8}}}},
- 0x09, MI_TARGET_CONNLIST},
-
- {{0, {AudioNspeaker"."AudioNmute, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_INPUT,
- 0, 0, ENUM_OFFON}, 0x23, MI_TARGET_OUTAMP},
- {{0, {AudioNspeaker, 0}, AUDIO_MIXER_VALUE, AZ_CLASS_INPUT,
- 0, 0, .un.v={{"", 0}, 1, MIXER_DELTA(15)}}, 0x23, MI_TARGET_OUTAMP}
-};
-
-static int
-cmi9880_mixer_init(codec_t *this)
-{
- mixer_ctrl_t mc;
-
- this->nmixers = __arraycount(cmi9880_mixer_items);
- this->szmixers = sizeof(cmi9880_mixer_items);
- this->mixers = kmem_alloc(this->szmixers, KM_SLEEP);
- memcpy(this->mixers, cmi9880_mixer_items, sizeof(cmi9880_mixer_items));
- generic_mixer_fix_indexes(this);
- generic_mixer_default(this);
-
- mc.dev = -1;
- mc.type = AUDIO_MIXER_ENUM;
- mc.un.ord = 5; /* record.front.source=mic */
- generic_mixer_set(this, 0x08, MI_TARGET_CONNLIST, &mc);
- mc.un.ord = 7; /* record.surround.source=line1 */
- generic_mixer_set(this, 0x09, MI_TARGET_CONNLIST, &mc);
- mc.un.ord = 1; /* pindir: output */
- generic_mixer_set(this, 0x0b, MI_TARGET_PINDIR, &mc);
- generic_mixer_set(this, 0x0c, MI_TARGET_PINDIR, &mc);
- generic_mixer_set(this, 0x0d, MI_TARGET_PINDIR, &mc);
- generic_mixer_set(this, 0x0e, MI_TARGET_PINDIR, &mc);
- generic_mixer_set(this, 0x0f, MI_TARGET_PINDIR, &mc);
- mc.un.ord = 0; /* front DAC -> headphones */
- generic_mixer_set(this, 0x0f, MI_TARGET_CONNLIST, &mc);
- mc.un.ord = 0; /* pindir: input */
- generic_mixer_set(this, 0x10, MI_TARGET_PINDIR, &mc); /* mic */
- generic_mixer_set(this, 0x13, MI_TARGET_PINDIR, &mc); /* SPDIF-in */
- generic_mixer_set(this, 0x1f, MI_TARGET_PINDIR, &mc); /* line1 */
- generic_mixer_set(this, 0x20, MI_TARGET_PINDIR, &mc); /* line2 */
- return 0;
-}
-
-static int
-cmi9880_init_dacgroup(codec_t *this)
-{
- static const convgroupset_t dacs = {
- -1, 2,
- {{4, {0x03, 0x04, 0x05, 0x06}}, /* analog 8ch */
- {1, {0x07}}}}; /* digital */
- static const convgroupset_t adcs = {
- -1, 2,
- {{2, {0x08, 0x09}}, /* analog 4ch */
- {1, {0x0a}}}}; /* digital */
-
- this->dacs = dacs;
- this->adcs = adcs;
- return 0;
-}
-
-/* ----------------------------------------------------------------
- * Sigmatel STAC9221 and STAC9221D
- * ---------------------------------------------------------------- */
-
-#define STAC9221_MAC 0x76808384
-
-static int
-stac9221_init_dacgroup(codec_t *this)
-{
- static const convgroupset_t dacs = {
- -1, 3,
- {{4, {0x02, 0x03, 0x04, 0x05}}, /* analog 8ch */
- {1, {0x08}}, /* digital */
- {1, {0x1a}}}}; /* another digital? */
- static const convgroupset_t adcs = {
- -1, 2,
- {{2, {0x06, 0x07}}, /* analog 4ch */
- {1, {0x09}}}}; /* digital */
-
- this->dacs = dacs;
- this->adcs = adcs;
- return 0;
-}
-
-static int
-stac9221_mixer_init(codec_t *this)
-{
- int err;
-
- err = generic_mixer_init(this);
- if (err)
- return err;
- if (this->subid == STAC9221_MAC) {
- stac9221_gpio_unmute(this, 0);
- stac9221_gpio_unmute(this, 1);
- }
- return 0;
-}
-
-static int
-stac9221_gpio_unmute(codec_t *this, int pin)
-{
- uint32_t data, mask, dir;
-
- this->comresp(this, this->audiofunc, CORB_GET_GPIO_DATA, 0, &data);
- this->comresp(this, this->audiofunc,
- CORB_GET_GPIO_ENABLE_MASK, 0, &mask);
- this->comresp(this, this->audiofunc, CORB_GET_GPIO_DIRECTION, 0, &dir);
- data &= ~(1 << pin);
- mask |= 1 << pin;
- dir |= 1 << pin;
- this->comresp(this, this->audiofunc, 0x7e7, 0, NULL);
- this->comresp(this, this->audiofunc,
- CORB_SET_GPIO_ENABLE_MASK, mask, NULL);
- this->comresp(this, this->audiofunc,
- CORB_SET_GPIO_DIRECTION, dir, NULL);
- DELAY(1000);
- this->comresp(this, this->audiofunc, CORB_SET_GPIO_DATA, data, NULL);
- return 0;
-}
-
-/* ----------------------------------------------------------------
- * Sigmatel STAC9200 and STAC9200D
- * ---------------------------------------------------------------- */
-
-static const mixer_item_t stac9200_mixer_items[] = {
- AZ_MIXER_CLASSES,
-
- {{0, {AudioNsource, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
- 0, 0, .un.e={3, {{{AudioNdac, 0}, 0}, {{AzaliaNdigital"-in", 0}, 1},
- {{"selector", 0}, 2}}}}, 0x07, MI_TARGET_CONNLIST},
- {{0, {AzaliaNdigital"."AudioNsource, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
- 0, 0, .un.e={2, {{{AudioNdac, 0}, 0}, {{"selector", 0}, 1}}}},
- 0x09, MI_TARGET_CONNLIST}, /* AudioNdac is not accurate name */
- {{0, {"selector."AudioNmute, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
- 0, 0, ENUM_OFFON}, 0x0a, MI_TARGET_OUTAMP},
- {{0, {"selector", 0}, AUDIO_MIXER_VALUE, AZ_CLASS_OUTPUT,
- 0, 0, .un.v={{"", 0}, 2, MIXER_DELTA(15)}}, 0x0a, MI_TARGET_OUTAMP},
- {{0, {AudioNmaster"."AudioNmute, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
- 0, 0, ENUM_OFFON}, 0x0b, MI_TARGET_OUTAMP},
- {{0, {AudioNmaster, 0}, AUDIO_MIXER_VALUE, AZ_CLASS_OUTPUT,
- 0, 0, .un.v={{"", 0}, 2, MIXER_DELTA(31)}}, 0x0b, MI_TARGET_OUTAMP},
- {{0, {"selector."AudioNsource, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_INPUT,
- 0, 0, .un.e={3, {{{"mic1", 0}, 0}, {{"mic2", 0}, 1}, {{AudioNcd, 0}, 4}}}},
- 0x0c, MI_TARGET_CONNLIST},
- {{0, {AudioNheadphone".boost", 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
- 0, 0, ENUM_OFFON}, 0x0d, MI_TARGET_PINBOOST},
- {{0, {AudioNspeaker".boost", 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
- 0, 0, ENUM_OFFON}, 0x0e, MI_TARGET_PINBOOST},
- {{0, {AudioNmono"."AudioNmute, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
- 0, 0, ENUM_OFFON}, 0x11, MI_TARGET_OUTAMP},
- {{0, {AudioNmono, 0}, AUDIO_MIXER_VALUE, AZ_CLASS_OUTPUT,
- 0, 0, .un.v={{"", 0}, 1, MIXER_DELTA(31)}}, 0x11, MI_TARGET_OUTAMP},
- {{0, {"beep."AudioNmute, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_OUTPUT,
- 0, 0, ENUM_OFFON}, 0x14, MI_TARGET_OUTAMP},
- {{0, {"beep", 0}, AUDIO_MIXER_VALUE, AZ_CLASS_OUTPUT,
- 0, 0, .un.v={{"", 0}, 1, MIXER_DELTA(3)}}, 0x14, MI_TARGET_OUTAMP},
- {{0, {AudioNmode, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_PLAYBACK,
- 0, 0, .un.e={2, {{{"analog", 0}, 0}, {{AzaliaNdigital, 0}, 1}}}},
- 0, MI_TARGET_DAC},
- {{0, {AudioNmode, 0}, AUDIO_MIXER_ENUM, AZ_CLASS_RECORD,
- 0, 0, .un.e={2, {{{"analog", 0}, 0}, {{AzaliaNdigital, 0}, 1}}}},
- 0, MI_TARGET_ADC},
-};
-
-static int
-stac9200_mixer_init(codec_t *this)
-{
- mixer_ctrl_t mc;
- uint32_t value;
-
- this->nmixers = __arraycount(stac9200_mixer_items);
- this->szmixers = sizeof(stac9200_mixer_items);
- this->mixers = kmem_alloc(this->szmixers, KM_SLEEP);
- memcpy(this->mixers, stac9200_mixer_items, sizeof(stac9200_mixer_items));
- generic_mixer_fix_indexes(this);
- generic_mixer_default(this);
-
- mc.dev = -1; /* no need for generic_mixer_set() */
- mc.type = AUDIO_MIXER_ENUM;
- mc.un.ord = 1; /* pindir: output */
- generic_mixer_set(this, 0x0d, MI_TARGET_PINDIR, &mc); /* headphones */
- generic_mixer_set(this, 0x0e, MI_TARGET_PINDIR, &mc); /* speaker */
- mc.un.ord = 0; /* pindir: input */
- generic_mixer_set(this, 0x0f, MI_TARGET_PINDIR, &mc); /* mic2 */
- generic_mixer_set(this, 0x10, MI_TARGET_PINDIR, &mc); /* mic1 */
- mc.type = AUDIO_MIXER_VALUE;
- mc.un.value.num_channels = 2;
- mc.un.value.level[0] = generic_mixer_max(this, 0x0c, MI_TARGET_OUTAMP);
- mc.un.value.level[1] = mc.un.value.level[0];
- generic_mixer_set(this, 0x0c, MI_TARGET_OUTAMP, &mc);
-
-#define STAC9200_DELL_INSPIRON6400_ID 0x01bd1028
-#define STAC9200_DELL_INSPIRON9400_ID 0x01cd1028
-#define STAC9200_DELL_640M_ID 0x01d81028
-#define STAC9200_DELL_LATITUDE_D420_ID 0x01d61028
-#define STAC9200_DELL_LATITUDE_D430_ID 0x02011028
-
-#define STAC9200_EVENT_HP 0
-#define STAC9200_NID_HP 0x0d
-#define STAC9200_NID_SPEAKER 0x0e
-
- switch (this->subid) {
- case STAC9200_DELL_INSPIRON6400_ID:
- case STAC9200_DELL_INSPIRON9400_ID:
- case STAC9200_DELL_640M_ID:
- case STAC9200_DELL_LATITUDE_D420_ID:
- case STAC9200_DELL_LATITUDE_D430_ID:
- /* Does every DELL model have the same pin configuration?
- * I'm not sure. */
-
- /* setup a unsolicited event for the headphones */
- this->comresp(this, STAC9200_NID_HP, CORB_SET_UNSOLICITED_RESPONSE,
- CORB_UNSOL_ENABLE | STAC9200_EVENT_HP, NULL);
- /* If the headphone presents, mute the internal speaker */
- this->comresp(this, STAC9200_NID_HP, CORB_GET_PIN_SENSE, 0, &value);
- if (value & CORB_PS_PRESENCE) {
- generic_mixer_pinctrl(this, STAC9200_NID_SPEAKER, 0);
- } else {
- generic_mixer_pinctrl(this,
- STAC9200_NID_SPEAKER, CORB_PWC_OUTPUT);
- }
- break;
- default:
- break;
- }
- return 0;
-}
-
-static int
-stac9200_unsol_event(codec_t *this, int tag)
-{
- int err;
- uint32_t value;
-
- switch (tag) {
- case STAC9200_EVENT_HP:
- err = this->comresp(this, STAC9200_NID_HP,
- CORB_GET_PIN_SENSE, 0, &value);
- if (err)
- break;
- if (value & CORB_PS_PRESENCE) {
- DPRINTF(("%s: headphone has been inserted.\n", __func__));
- generic_mixer_pinctrl(this, STAC9200_NID_SPEAKER, 0);
- } else {
- DPRINTF(("%s: headphone has been pulled out.\n", __func__));
- generic_mixer_pinctrl(this, STAC9200_NID_SPEAKER, CORB_PWC_OUTPUT);
- }
- break;
- default:
- printf("%s: unknown tag: %d\n", __func__, tag);
- }
- return 0;
-}
-
-/* ----------------------------------------------------------------
- * ATI HDMI
- * ---------------------------------------------------------------- */
-
-static int
-atihdmi_init_dacgroup(codec_t *this)
-{
- static const convgroupset_t dacs = {
- -1, 1,
- {{1, {0x02}}}}; /* digital */
- static const convgroupset_t adcs = {
- -1, 0,
- {{0, {0x00}}}}; /* no recording */
-
- this->dacs = dacs;
- this->adcs = adcs;
- return 0;
-}
diff --git a/sys/dev/pci/files.pci b/sys/dev/pci/files.pci
index b7c2ba4c7ca..63d088a5474 100644
--- a/sys/dev/pci/files.pci
+++ b/sys/dev/pci/files.pci
@@ -1,4 +1,4 @@
-# $NetBSD: files.pci,v 1.425 2020/01/25 18:59:43 thorpej Exp $
+# $NetBSD: files.pci,v 1.426 2020/02/09 16:06:18 jmcneill Exp $
#
# Config file and device description for machine-independent PCI code.
# Included by ports that need it. Requires that the SCSI files be
@@ -500,12 +500,6 @@ device auixp: audiobus, ac97, aurateconv
attach auixp at pci
file dev/pci/auixp.c auixp
-# High Definition Audio
-device azalia: audiobus, ac97, aurateconv
-attach azalia at pci
-file dev/pci/azalia.c azalia
-file dev/pci/azalia_codec.c azalia
-
# AMD Geode CS5536 Companion Audio
device gcscaudio: audiobus, ac97, aurateconv
attach gcscaudio at pci