root/usr/src/uts/common/io/audio/drv/audiohd/audiohd.h
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */
/*
 * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
 */
#ifndef _SYS_AUDIOHD_IMPL_H_
#define _SYS_AUDIOHD_IMPL_H_

#ifdef __cplusplus
extern "C" {
#endif

/*
 * vendor IDs of PCI audio controllers
 */
#define AUDIOHD_VID_ATI         0x1002
#define AUDIOHD_VID_CIRRUS      0x1013
#define AUDIOHD_VID_NVIDIA      0x10de
#define AUDIOHD_VID_REALTEK     0x10ec
#define AUDIOHD_VID_CREATIVE    0x1102
#define AUDIOHD_VID_IDT         0x111d
#define AUDIOHD_VID_ANALOG      0x11d4
#define AUDIOHD_VID_CONEXANT    0x14f1
#define AUDIOHD_VID_SIGMATEL    0x8384
#define AUDIOHD_VID_INTEL       0x8086

/*
 * specific audiohd controller device id
 */
#define AUDIOHD_CONTROLLER_MCP51        0x10de026c

/*
 * codec special initial flags
 */
#define NO_GPIO         0x00000001
#define NO_MIXER        0x00000002
#define NO_SPDIF        0x00000004
#define EN_PIN_BEEP     0x00000008

#define AUDIOHD_DEV_CONFIG      "onboard1"
#define AUDIOHD_DEV_VERSION     "a"

/*
 * Only for Intel hardware:
 * PCI Express traffic class select register in PCI configure space
 */
#define AUDIOHD_INTEL_PCI_TCSEL 0x44
#define AUDIOHD_INTEL_TCS_MASK  0xf8

/*
 * Only for ATI SB450:
 * MISC control register 2
 */
#define AUDIOHD_ATI_PCI_MISC2   0x42
#define AUDIOHD_ATI_MISC2_MASK  0xf8
#define AUDIOHD_ATI_MISC2_SNOOP 0x02

/* NVIDIA snoop */
#define AUDIOHD_NVIDIA_SNOOP    0x0f

#define AUDIOHDC_NID(x)         x
#define AUDIOHDC_NULL_NODE      -1
#define AUDIOHD_NULL_CONN       ((uint_t)(-1))

#define AUDIOHD_EXT_AMP_MASK    0x00010000
#define AUDIOHD_EXT_AMP_ENABLE  0x02

/* Power On/Off */
#define AUDIOHD_PW_D0           0
#define AUDIOHD_PW_D2           2

/* Pin speaker On/Off */
#define AUDIOHD_SP_ON           1
#define AUDIOHD_SP_OFF          0

#define AUDIOHD_PORT_MAX        15
#define AUDIOHD_CODEC_MAX       16
#define AUDIOHD_MEMIO_LEN       0x4000

#define AUDIOHD_RETRY_TIMES     60
#define AUDIOHD_TEST_TIMES      500
#define AUDIOHD_OUTSTR_NUM_OFF  12
#define AUDIOHD_INSTR_NUM_OFF   8

#define AUDIOHD_CORB_SIZE_OFF   0x4e

#define AUDIOHD_URCAP_MASK      0x80
#define AUDIOHD_DTCCAP_MASK     0x4
#define AUDIOHD_UR_ENABLE_OFF   8
#define AUDIOHD_UR_TAG_MASK     0x3f

#define AUDIOHD_CIS_MASK        0x40000000

#define AUDIOHD_RIRB_UR_MASK    0x10
#define AUDIOHD_RIRB_CODEC_MASK 0xf
#define AUDIOHD_RIRB_WID_OFF    27
#define AUDIOHD_RIRB_INTRCNT    0x0
#define AUDIOHD_RIRB_WPMASK     0xff

#define AUDIOHD_FORM_MASK       0x0080
#define AUDIOHD_LEN_MASK        0x007f
#define AUDIOHD_PIN_CAP_MASK    0x00000010
#define AUDIOHD_PIN_CONF_MASK   0xc0000000
#define AUDIOHD_PIN_CON_MASK    3
#define AUDIOHD_PIN_CON_STEP    30
#define AUDIOHD_PIN_IO_MASK     0X0018
#define AUDIOHD_PIN_SEQ_MASK    0x0000000f
#define AUDIOHD_PIN_ASO_MASK    0x000000f0
#define AUDIOHD_PIN_ASO_OFF     0x4
#define AUDIOHD_PIN_DEV_MASK    0x00f00000
#define AUDIOHD_PIN_DEV_OFF     20
#define AUDIOHD_PIN_NUMS        6
#define AUDIOHD_PIN_NO_CONN     0x40000000
#define AUDIOHD_PIN_IN_ENABLE   0x20
#define AUDIOHD_PIN_OUT_ENABLE  0x40
#define AUDIOHD_PIN_PRES_MASK   0x80000000
#define AUDIOHD_PIN_CONTP_OFF   0x1e
#define AUDIOHD_PIN_CON_JACK    0
#define AUDIOHD_PIN_CON_FIXED   0x2
#define AUDIOHD_PIN_CONTP_MASK  0x3
#define AUDIOHD_PIN_VREF_L1     0x20
#define AUDIOHD_PIN_VREF_L2     0x10
#define AUDIOHD_PIN_VREF_L3     0x04
#define AUDIOHD_PIN_VREF_L4     0x02
#define AUDIOHD_PIN_VREF_OFF    8
#define AUDIOHD_PIN_VREF_MASK   0xff
#define AUDIOHD_PIN_CLR_MASK    0xf
#define AUDIOHD_PIN_CLR_OFF     12

#define AUDIOHD_VERB_ADDR_OFF   28
#define AUDIOHD_VERB_NID_OFF    20
#define AUDIOHD_VERB_CMD_OFF    8
#define AUDIOHD_VERB_CMD16_OFF  16

#define AUDIOHD_RING_MAX_SIZE   0x00ff
#define AUDIOHD_REC_TAG_OFF     4
#define AUDIOHD_PLAY_TAG_OFF    4
#define AUDIOHD_PLAY_CTL_OFF    2
#define AUDIOHD_REC_CTL_OFF     2

#define AUDIOHD_SPDIF_ON        1
#define AUDIOHD_SPDIF_MASK      0x00ff

#define AUDIOHD_GAIN_OFF        8

#define AUDIOHD_CODEC_STR_OFF   16
#define AUDIOHD_CODEC_STR_MASK  0x000000ff
#define AUDIOHD_CODEC_NUM_MASK  0x000000ff
#define AUDIOHD_CODEC_TYPE_MASK 0x000000ff

#define AUDIOHD_ROUNDUP(x, algn)        (((x) + ((algn) - 1)) & ~((algn) - 1))
#define AUDIOHD_BDLE_BUF_ALIGN  128
#define AUDIOHD_CMDIO_ENT_MASK  0x00ff  /* 256 entries for CORB/RIRB */
#define AUDIOHD_CDBIO_CORB_LEN  1024    /* 256 entries for CORB, 1024B */
#define AUDIOHD_CDBIO_RIRB_LEN  2048    /* 256 entries for RIRB, 2048B */
#define AUDIOHD_BDLE_NUMS       4       /* 4 entires for record/play BD list */

#define AUDIOHD_PORT_UNMUTE     (0xffffffff)

/*
 * Audio registers of high definition
 */
#define AUDIOHD_REG_GCAP                0x00
#define AUDIOHDR_GCAP_OUTSTREAMS        0xf000
#define AUDIOHDR_GCAP_INSTREAMS         0x0f00
#define AUDIOHDR_GCAP_BSTREAMS          0x00f8
#define AUDIOHDR_GCAP_NSDO              0x0006
#define AUDIOHDR_GCAP_64OK              0x0001

#define AUDIOHD_REG_VMIN                0x02
#define AUDIOHD_REG_VMAJ                0x03
#define AUDIOHD_REG_OUTPAY              0x04
#define AUDIOHD_REG_INPAY               0x06
#define AUDIOHD_REG_GCTL                0x08
#define AUDIOHD_REG_WAKEEN              0x0C
#define AUDIOHD_REG_STATESTS            0x0E
#define AUDIOHD_STATESTS_BIT_SDINS      0x7F

#define AUDIOHD_REG_GSTS                0x10
#define AUDIOHD_REG_INTCTL              0x20
#define AUDIOHD_INTCTL_BIT_GIE          0x80000000
#define AUDIOHD_INTCTL_BIT_CIE          0x40000000
#define AUDIOHD_INTCTL_BIT_SIE          0x3FFFFFFF


#define AUDIOHD_REG_INTSTS              0x24
#define AUDIOHD_INTSTS_BIT_GIS          0x80000000
#define AUDIOHD_INTSTS_BIT_CIS          0x40000000
#define AUDIOHD_INTSTS_BIT_SINTS        (0x3fffffff)

#define AUDIOHD_REG_WALCLK              0x30
#define AUDIOHD_REG_SYNC                0x38

#define AUDIOHD_REG_CORBLBASE           0x40
#define AUDIOHD_REG_CORBUBASE           0x44
#define AUDIOHD_REG_CORBWP              0x48
#define AUDIOHD_REG_CORBRP              0x4A
#define AUDIOHD_REG_CORBCTL             0x4C
#define AUDIOHD_REG_CORBST              0x4D
#define AUDIOHD_REG_CORBSIZE            0x4E

#define AUDIOHD_REG_RIRBLBASE           0x50
#define AUDIOHD_REG_RIRBUBASE           0x54
#define AUDIOHD_REG_RIRBWP              0x58
#define AUDIOHD_REG_RINTCNT             0x5A
#define AUDIOHD_REG_RIRBCTL             0x5C
#define AUDIOHD_REG_RIRBSTS             0x5D
#define AUDIOHD_REG_RIRBSIZE            0x5E

#define AUDIOHD_REG_IC                  0x60
#define AUDIOHD_REG_IR                  0x64
#define AUDIOHD_REG_IRS                 0x68
#define AUDIOHD_REG_DPLBASE             0x70
#define AUDIOHD_REG_DPUBASE             0x74

#define AUDIOHD_REG_SD_BASE             0x80
#define AUDIOHD_REG_SD_LEN              0x20

/*
 * Offset of Stream Descriptor Registers
 */
#define AUDIOHD_SDREG_OFFSET_CTL                0x00
#define AUDIOHD_SDREG_OFFSET_STS                0x03
#define AUDIOHD_SDREG_OFFSET_LPIB               0x04
#define AUDIOHD_SDREG_OFFSET_CBL                0x08
#define AUDIOHD_SDREG_OFFSET_LVI                0x0c
#define AUDIOHD_SDREG_OFFSET_FIFOW              0x0e
#define AUDIOHD_SDREG_OFFSET_FIFOSIZE           0x10
#define AUDIOHD_SDREG_OFFSET_FORMAT             0x12
#define AUDIOHD_SDREG_OFFSET_BDLPL              0x18
#define AUDIOHD_SDREG_OFFSET_BDLPU              0x1c

/* bits for stream descriptor control reg */
#define AUDIOHDR_SD_CTL_DEIE            0x000010
#define AUDIOHDR_SD_CTL_FEIE            0x000008
#define AUDIOHDR_SD_CTL_IOCE            0x000004
#define AUDIOHDR_SD_CTL_SRUN            0x000002
#define AUDIOHDR_SD_CTL_SRST            0x000001

/* bits for stream descriptor status register */
#define AUDIOHDR_SD_STS_BCIS            0x0004
#define AUDIOHDR_SD_STS_FIFOE           0x0008
#define AUDIOHDR_SD_STS_DESE            0x0010
#define AUDIOHDR_SD_STS_FIFORY          0x0020
#define AUDIOHDR_SD_STS_INTRS   \
        (AUDIOHDR_SD_STS_BCIS | \
        AUDIOHDR_SD_STS_FIFOE | \
        AUDIOHDR_SD_STS_DESE)

/* bits for GCTL register */
#define AUDIOHDR_GCTL_CRST              0x00000001
#define AUDIOHDR_GCTL_URESPE            0x00000100

/* bits for CORBRP register */
#define AUDIOHDR_CORBRP_RESET           0x8000
#define AUDIOHDR_CORBRP_WPTR            0x00ff

/* bits for CORBCTL register */
#define AUDIOHDR_CORBCTL_CMEIE          0x01
#define AUDIOHDR_CORBCTL_DMARUN         0x02

/* bits for CORB SIZE register */
#define AUDIOHDR_CORBSZ_8               0
#define AUDIOHDR_CORBSZ_16              1
#define AUDIOHDR_CORBSZ_256             2

/* bits for RIRBCTL register */
#define AUDIOHDR_RIRBCTL_RINTCTL        0x01
#define AUDIOHDR_RIRBCTL_DMARUN         0x02
#define AUDIOHDR_RIRBCTL_RIRBOIC        0x04
#define AUDIOHDR_RIRBCTL_RSTINT         0xfe

/* bits for RIRBWP register */
#define AUDIOHDR_RIRBWP_RESET           0x8000
#define AUDIOHDR_RIRBWP_WPTR            0x00ff

/* bits for RIRB SIZE register */
#define AUDIOHDR_RIRBSZ_8               0
#define AUDIOHDR_RIRBSZ_16              1
#define AUDIOHDR_RIRBSZ_256             2

#define AUDIOHD_BDLE_RIRB_SDI           0x0000000f
#define AUDIOHD_BDLE_RIRB_UNSOLICIT     0x00000010

/* HD spec: ID of Root node is 0 */
#define AUDIOHDC_NODE_ROOT              0x00

/* HD spec: ID of audio function group is "1" */
#define AUDIOHDC_AUDIO_FUNC_GROUP       1

/*
 * HD audio verbs can be either 12-bit or 4-bit in length.
 */
#define AUDIOHDC_12BIT_VERB_MASK        0xfffff000
#define AUDIOHDC_4BIT_VERB_MASK         0xfffffff0

#define AUDIOHDC_SAMPR48000             48000
#define AUDIOHDC_MAX_BEEP_GEN           12000
#define AUDIOHDC_MIX_BEEP_GEN           47
#define AUDIOHDC_MUTE_BEEP_GEN          0x0

/*
 * 12-bit verbs
 */
#define AUDIOHDC_VERB_GET_PARAM                 0xf00

#define AUDIOHDC_VERB_GET_CONN_SEL              0xf01
#define AUDIOHDC_VERB_SET_CONN_SEL              0x701

#define AUDIOHDC_VERB_GET_CONN_LIST_ENT         0xf02
#define AUDIOHDC_VERB_GET_PROCESS_STATE         0xf03
#define AUDIOHDC_VERB_GET_SDI_SEL               0xf04

#define AUDIOHDC_VERB_GET_POWER_STATE           0xf05
#define AUDIOHDC_VERB_SET_POWER_STATE           0x705

#define AUDIOHDC_VERB_GET_STREAM_CHANN          0xf06
#define AUDIOHDC_VERB_SET_STREAM_CHANN          0x706

#define AUDIOHDC_VERB_GET_PIN_CTRL              0xf07
#define AUDIOHDC_VERB_SET_PIN_CTRL              0x707

#define AUDIOHDC_VERB_GET_UNS_ENABLE            0xf08
#define AUDIOHDC_VERB_SET_UNS_ENABLE            0x708

#define AUDIOHDC_VERB_GET_PIN_SENSE             0xf09
#define AUDIOHDC_VERB_GET_PIN_SENSE             0xf09
#define AUDIOHDC_VERB_EXEC_PIN_SENSE            0x709

#define AUDIOHDC_VERB_GET_BEEP_GEN              0xf0a
#define AUDIOHDC_VERB_SET_BEEP_GEN              0x70a

#define AUDIOHDC_VERB_GET_EAPD                  0xf0c
#define AUDIOHDC_VERB_SET_EAPD                  0x70c

#define AUDIOHDC_VERB_GET_DEFAULT_CONF          0xf1c
#define AUDIOHDC_VERB_GET_SPDIF_CTL             0xf0d
#define AUDIOHDC_VERB_SET_SPDIF_LCL             0x70d

#define AUDIOHDC_VERB_GET_GPIO_MASK             0xf16
#define AUDIOHDC_VERB_SET_GPIO_MASK             0x716

#define AUDIOHDC_VERB_GET_UNSOL_ENABLE_MASK     0xf19
#define AUDIOHDC_VERB_SET_UNSOL_ENABLE_MASK     0x719

#define AUDIOHDC_VERB_GET_GPIO_DIREC            0xf17
#define AUDIOHDC_VERB_SET_GPIO_DIREC            0x717

#define AUDIOHDC_VERB_GET_GPIO_DATA             0xf15
#define AUDIOHDC_VERB_SET_GPIO_DATA             0x715

#define AUDIOHDC_VERB_GET_GPIO_STCK             0xf1a
#define AUDIOHDC_VERB_SET_GPIO_STCK             0x71a

#define AUDIOHDC_GPIO_ENABLE                    0xff
#define AUDIOHDC_GPIO_DIRECT                    0xf1

#define AUDIOHDC_GPIO_DATA_CTRL                 0xff
#define AUDIOHDC_GPIO_STCK_CTRL                 0xff
/*
 * 4-bit verbs
 */
#define AUDIOHDC_VERB_GET_CONV_FMT              0xa
#define AUDIOHDC_VERB_SET_CONV_FMT              0x2

#define AUDIOHDC_VERB_GET_AMP_MUTE              0xb
#define AUDIOHDC_VERB_SET_AMP_MUTE              0x3
#define AUDIOHDC_VERB_SET_BEEP_VOL              0x3A0

/*
 * parameters of nodes
 */
#define AUDIOHDC_PAR_VENDOR_ID                  0x00
#define AUDIOHDC_PAR_SUBSYS_ID                  0x01
#define AUDIOHDC_PAR_REV_ID                     0x02
#define AUDIOHDC_PAR_NODE_COUNT                 0x04
#define AUDIOHDC_PAR_FUNCTION_TYPE              0x05
#define AUDIOHDC_PAR_AUDIO_FG_CAP               0x08
#define AUDIOHDC_PAR_AUDIO_WID_CAP              0x09
#define AUDIOHDC_PAR_PCM                        0x0a
#define AUDIOHDC_PAR_STREAM                     0x0b
#define AUDIOHDC_PAR_PIN_CAP                    0x0c
#define AUDIOHDC_PAR_INAMP_CAP                  0x0d
#define AUDIOHDC_PAR_CONNLIST_LEN               0x0e
#define AUDIOHDC_PAR_POWER_STATE                0x0f
#define AUDIOHDC_PAR_PROC_CAP                   0x10
#define AUDIOHDC_PAR_GPIO_CAP                   0x11
#define AUDIOHDC_PAR_OUTAMP_CAP                 0x12

/*
 * bits for get/set amplifier gain/mute
 */
#define AUDIOHDC_AMP_SET_OUTPUT                 0x8000
#define AUDIOHDC_AMP_SET_INPUT                  0x4000
#define AUDIOHDC_AMP_SET_LEFT                   0x2000
#define AUDIOHDC_AMP_SET_RIGHT                  0x1000
#define AUDIOHDC_AMP_SET_MUTE                   0x0080
#define AUDIOHDC_AMP_SET_LNR                    0x3000
#define AUDIOHDC_AMP_SET_LR_INPUT               0x7000
#define AUDIOHDC_AMP_SET_LR_OUTPUT              0xb000
#define AUDIOHDC_AMP_SET_INDEX_OFFSET           8
#define AUDIOHDC_AMP_SET_GAIN_MASK              0x007f
#define AUDIOHDC_GAIN_MAX                       0x7f
#define AUDIOHDC_GAIN_BITS                      7
#define AUDIOHDC_GAIN_DEFAULT                   0x0f

#define AUDIOHDC_AMP_GET_OUTPUT                 0x8000
#define AUDIOHDC_AMP_GET_INPUT                  0x0000

/* value used to set max volume for left output */
#define AUDIOHDC_AMP_LOUT_MAX   \
        (AUDIOHDC_AMP_SET_OUTPUT | \
        AUDIOHDC_AMP_SET_LEFT | \
        AUDIOHDC_GAIN_MAX)

/* value used to set max volume for right output */
#define AUDIOHDC_AMP_ROUT_MAX   \
        (AUDIOHDC_AMP_SET_OUTPUT | \
        AUDIOHDC_AMP_SET_RIGHT | \
        AUDIOHDC_GAIN_MAX)


/*
 * Bits for pin widget control verb
 */
#define AUDIOHDC_PIN_CONTROL_HP_ENABLE          0x80
#define AUDIOHDC_PIN_CONTROL_OUT_ENABLE         0x40
#define AUDIOHDC_PIN_CONTROL_IN_ENABLE          0x20

/*
 * Bits for Amplifier capabilities
 */
#define AUDIOHDC_AMP_CAP_MUTE_CAP               0x80000000
#define AUDIOHDC_AMP_CAP_STEP_SIZE              0x007f0000
#define AUDIOHDC_AMP_CAP_STEP_NUMS              0x00007f00
#define AUDIOHDC_AMP_CAP_0DB_OFFSET             0x0000007f


/*
 * Bits for Audio Widget Capabilities
 */
#define AUDIOHD_WIDCAP_STEREO           0x00000001
#define AUDIOHD_WIDCAP_INAMP            0x00000002
#define AUDIOHD_WIDCAP_OUTAMP           0x00000004
#define AUDIOHD_WIDCAP_AMP_OVRIDE       0x00000008
#define AUDIOHD_WIDCAP_FMT_OVRIDE       0x00000010
#define AUDIOHD_WIDCAP_STRIP            0x00000020
#define AUDIOHD_WIDCAP_PROC_WID         0x00000040
#define AUDIOHD_WIDCAP_UNSOL            0x00000080
#define AUDIOHD_WIDCAP_CONNLIST         0x00000100
#define AUDIOHD_WIDCAP_DIGIT            0x00000200
#define AUDIOHD_WIDCAP_PWRCTRL          0x00000400
#define AUDIOHD_WIDCAP_LRSWAP           0x00000800
#define AUDIOHD_WIDCAP_TYPE             0x00f00000
#define AUDIOHD_WIDCAP_TO_WIDTYPE(wcap)         \
        ((wcap & AUDIOHD_WIDCAP_TYPE) >> 20)

#define AUDIOHD_CODEC_FAILURE   (uint32_t)(-1)

/* Higher sample/bits support */
#define AUDIOHD_BIT_DEPTH16     0x00020000
#define AUDIOHD_BIT_DEPTH24     0x00080000
#define AUDIOHD_SAMP_RATE48     0x00000040
#define AUDIOHD_SAMP_RATE96     0x00000100
#define AUDIOHD_SAMP_RATE192    0x00000400

/*
 * buffer descriptor list entry of stream descriptor
 */
typedef struct {
        uint64_t        sbde_addr;
        uint32_t        sbde_len;
        uint32_t
                sbde_ioc: 1,
                reserved: 31;
}sd_bdle_t;


#define AUDIOHD_PLAY_STARTED            0x00000001
#define AUDIOHD_PLAY_EMPTY              0x00000002
#define AUDIOHD_PLAY_PAUSED             0x00000004
#define AUDIOHD_RECORD_STARTED          0x00000008

enum audiohda_widget_type {
        WTYPE_AUDIO_OUT = 0,
        WTYPE_AUDIO_IN,
        WTYPE_AUDIO_MIX,
        WTYPE_AUDIO_SEL,
        WTYPE_PIN,
        WTYPE_POWER,
        WTYPE_VOL_KNOB,
        WTYPE_BEEP,
        WTYPE_VENDOR = 0xf
};

enum audiohda_device_type {
        DTYPE_LINEOUT = 0,
        DTYPE_SPEAKER,
        DTYPE_HP_OUT,
        DTYPE_CD,
        DTYPE_SPDIF_OUT,
        DTYPE_DIGIT_OUT,
        DTYPE_MODEM_SIDE,
        DTYPE_MODEM_HNAD_SIDE,
        DTYPE_LINE_IN,
        DTYPE_AUX,
        DTYPE_MIC_IN,
        DTYPE_TEL,
        DTYPE_SPDIF_IN,
        DTYPE_DIGIT_IN,
        DTYPE_OTHER = 0x0f,
};

enum audiohd_pin_color {
        AUDIOHD_PIN_UNKNOWN = 0,
        AUDIOHD_PIN_BLACK,
        AUDIOHD_PIN_GREY,
        AUDIOHD_PIN_BLUE,
        AUDIOHD_PIN_GREEN,
        AUDIOHD_PIN_RED,
        AUDIOHD_PIN_ORANGE,
        AUDIOHD_PIN_YELLOW,
        AUDIOHD_PIN_PURPLE,
        AUDIOHD_PIN_PINK,
        AUDIOHD_PIN_WHITE = 0xe,
        AUDIOHD_PIN_OTHER = 0xf,
};

/* values for audiohd_widget.path_flags */
#define AUDIOHD_PATH_DAC        (1 << 0)
#define AUDIOHD_PATH_ADC        (1 << 1)
#define AUDIOHD_PATH_MON        (1 << 2)
#define AUDIOHD_PATH_NOMON      (1 << 3)
#define AUDIOHD_PATH_BEEP       (1 << 4)
#define AUDIOHD_PATH_LOOPBACK   (1 << 5)

typedef struct audiohd_path     audiohd_path_t;
typedef struct audiohd_widget   audiohd_widget_t;
typedef struct audiohd_state    audiohd_state_t;
typedef struct audiohd_codec_info       audiohd_codec_info_t;
typedef struct audiohd_pin      audiohd_pin_t;
typedef struct hda_codec        hda_codec_t;
typedef uint32_t        wid_t;          /* id of widget */
typedef struct audiohd_entry_prop       audiohd_entry_prop_t;
typedef enum audiohda_device_type       audiohda_device_type_t;
typedef enum audiohd_pin_color          audiohd_pin_color_t;

#define AUDIOHD_MAX_WIDGET              128
#define AUDIOHD_MAX_CONN                16
#define AUDIOHD_MAX_PINS                16
#define AUDIOHD_MAX_DEPTH               8

struct audiohd_entry_prop {
        uint32_t        conn_len;
        uint32_t        mask_range;
        uint32_t        mask_wid;
        wid_t           input_wid;
        int             conns_per_entry;
        int             bits_per_conn;
};
struct audiohd_widget {
        wid_t           wid_wid;
        hda_codec_t     *codec;
        enum audiohda_widget_type type;

        uint32_t        widget_cap;
        uint32_t        pcm_format;
        uint32_t        inamp_cap;
        uint32_t        outamp_cap;

        uint32_t        path_flags;

        int             out_weight;
        int             in_weight;
        int             finish;

        /*
         * available (input) connections. 0 means this widget
         * has fixed connection
         */
        int             nconns;

        /*
         * wid of possible & selected input & output connections
         */
        wid_t           avail_conn[AUDIOHD_MAX_CONN];
        wid_t           output_path_next;       /* output pin -> DAC */
        wid_t           input_path_next;        /* ADC -> input pin */
        wid_t           monitor_path_next[AUDIOHD_MAX_CONN];
                                                /* output pin -> input pin */
        wid_t           beep_path_next;         /* output pin -> beep widget */
        wid_t           loopback_path_next;     /* ADC -> output pin */

        uint16_t        used;

        /*
         * pointer to struct depending on widget type:
         *      1. DAC  audiohd_path_t
         *      2. ADC  audiohd_path_t
         *      3. PIN  audiohd_pin_t
         */
        void    *priv;
};

#define AUDIOHD_FLAG_LINEOUT            (1 << 0)
#define AUDIOHD_FLAG_SPEAKER            (1 << 1)
#define AUDIOHD_FLAG_HP                 (1 << 2)
#define AUDIOHD_FLAG_MONO               (1 << 3)

#define AUDIOHD_MAX_MIXER               5
#define AUDIOHD_MAX_PIN                 4

#define PORT_DAC                0
#define PORT_ADC                1
#define PORT_MAX                2
typedef enum {
        PLAY = 0,
        RECORD = 1,
        BEEP = 2,
        LOOPBACK = 3,
} path_type_t;

struct audiohd_path {
        wid_t                   adda_wid;
        wid_t                   beep_wid;

        wid_t                   pin_wid[AUDIOHD_MAX_PINS];
        int                     sum_selconn[AUDIOHD_MAX_PINS];
        int                     mon_wid[AUDIOHD_MAX_PIN][AUDIOHD_MAX_MIXER];
        int                     pin_nums;
        int                     maxmixer[AUDIOHD_MAX_PINS];

        path_type_t             path_type;

        wid_t                   mute_wid;
        int                     mute_dir;
        wid_t                   gain_wid;
        int                     gain_dir;
        uint32_t                gain_bits;

        uint32_t                pin_outputs;
        uint8_t                 tag;

        hda_codec_t             *codec;

        wid_t                   sum_wid;

        audiohd_state_t         *statep;
};

typedef struct audiohd_port
{
        uint8_t                 nchan;
        int                     index;
        uint16_t                regoff;

        unsigned                nframes;
        size_t                  bufsize;
        size_t                  fragsize;
        uint64_t                count;
        int                     curpos;

        uint_t                  format;
        unsigned                sync_dir;

        ddi_dma_handle_t        samp_dmah;
        ddi_acc_handle_t        samp_acch;
        caddr_t                 samp_kaddr;
        uint64_t                samp_paddr;

        ddi_dma_handle_t        bdl_dmah;
        ddi_acc_handle_t        bdl_acch;
        size_t                  bdl_size;
        caddr_t                 bdl_kaddr;
        uint64_t                bdl_paddr;

        audio_engine_t          *engine;
        audiohd_state_t         *statep;
}audiohd_port_t;

enum {
        CTL_VOLUME = 0,
        CTL_FRONT,
        CTL_SPEAKER,
        CTL_HEADPHONE,
        CTL_REAR,
        CTL_CENTER,
        CTL_SURROUND,
        CTL_LFE,
        CTL_IGAIN,
        CTL_LINEIN,
        CTL_MIC,
        CTL_CD,
        CTL_MONGAIN,
        CTL_MONSRC,
        CTL_RECSRC,
        CTL_BEEP,
        CTL_LOOP,

        /* this one must be last */
        CTL_MAX
};

typedef struct audiohd_ctrl
{
        audiohd_state_t         *statep;
        audio_ctrl_t            *ctrl;
        int                     num;
        uint64_t                val;
} audiohd_ctrl_t;

struct audiohd_pin {
        audiohd_pin_t   *next;
        wid_t           wid;
        wid_t           mute_wid;       /* node used to mute this pin */
        int             mute_dir;       /* 1: input, 2: output */
        wid_t           gain_wid;       /* node for gain control */
        int             gain_dir;       /* _OUTPUT/_INPUT */
        uint32_t        gain_bits;

        uint8_t         vrefvalue;      /* value of VRef */

        uint32_t        cap;
        uint32_t        config;
        uint32_t        ctrl;
        uint32_t        assoc;
        uint32_t        seq;
        wid_t           adc_wid;
        wid_t           dac_wid;
        wid_t           beep_wid;
        int             no_phys_conn;
        enum audiohda_device_type       device;

        /*
         * mg_dir, mg_gain, mg_wid are used to store the monitor gain control
         * widget wid.
         */
        int             mg_dir[AUDIOHD_MAX_CONN];
        int             mg_gain[AUDIOHD_MAX_CONN];
        int             mg_wid[AUDIOHD_MAX_CONN];
        int             num;
        int             finish;

};

typedef struct {
        ddi_dma_handle_t        ad_dmahdl;
        ddi_acc_handle_t        ad_acchdl;
        caddr_t                 ad_vaddr;       /* virtual addr */
        uint64_t                ad_paddr;       /* physical addr */
        size_t                  ad_req_sz;      /* required size of memory */
        size_t                  ad_real_sz;     /* real size of memory */
} audiohd_dma_t;

struct hda_codec {
        uint8_t         index;          /* codec address */
        uint32_t        vid;            /* vendor id and device id */
        uint32_t        revid;          /* revision id */
        wid_t           wid_afg;        /* id of AFG */
        wid_t           first_wid;      /* wid of 1st subnode of AFG */
        wid_t           last_wid;       /* wid of the last subnode of AFG */
        int             nnodes;         /* # of subnodes of AFG */
        uint8_t         nistream;

        uint32_t        outamp_cap;
        uint32_t        inamp_cap;
        uint32_t        stream_format;
        uint32_t        pcm_format;

        audiohd_state_t         *statep;
        audiohd_codec_info_t    *codec_info;

        /* use wid as index to the array of widget pointers */
        audiohd_widget_t        *widget[AUDIOHD_MAX_WIDGET];

        audiohd_port_t          *port[AUDIOHD_PORT_MAX];
        uint8_t                 portnum;
        audiohd_pin_t           *first_pin;
};

#define AUDIOHD_MAX_ASSOC       15
struct audiohd_state {
        dev_info_t      *hda_dip;
        kstat_t         *hda_ksp;
        kmutex_t        hda_mutex;
        uint32_t        hda_flags;

        caddr_t                 hda_reg_base;
        ddi_acc_handle_t        hda_pci_handle;
        ddi_acc_handle_t        hda_reg_handle;

        audiohd_dma_t   hda_dma_corb;
        audiohd_dma_t   hda_dma_rirb;

        uint8_t         hda_rirb_rp;            /* read pointer for rirb */
        uint16_t        hda_codec_mask;

        audio_dev_t     *adev;
        uint32_t        devid;

        int             hda_input_streams;      /* # of input stream */
        int             hda_output_streams;     /* # of output stream */
        int             hda_streams_nums;       /* # of stream */

        uint_t          hda_play_regbase;
        uint_t          hda_record_regbase;

        uint_t          hda_play_stag;          /* tag of playback stream */
        uint_t          hda_record_stag;        /* tag of record stream */
        uint_t          hda_play_lgain;         /* left gain for playback */
        uint_t          hda_play_rgain;         /* right gain for playback */

        /*
         * Now, for the time being, we add some fields
         * for parsing codec topology
         */
        hda_codec_t     *codec[AUDIOHD_CODEC_MAX];

        /*
         * Suspend/Resume used fields
         */
        boolean_t       suspended;

        audiohd_path_t  *path[AUDIOHD_PORT_MAX];
        uint8_t         pathnum;
        audiohd_port_t  *port[PORT_MAX];
        uint8_t         pchan;
        uint8_t         rchan;

        uint64_t        inmask;

        uint_t          hda_out_ports;
        uint_t          in_port;

        /* Higher sample/rate */
        uint32_t        sample_rate;
        uint32_t        sample_bit_depth;
        uint8_t         sample_packed_bytes;

        /*
         * Controls
         */
        audiohd_ctrl_t  ctrls[CTL_MAX];
        boolean_t       monitor_supported;
        boolean_t       loopback_supported;

        /* for multichannel */
        uint8_t                 chann[AUDIOHD_MAX_ASSOC];
        uint8_t                 assoc;

};

struct audiohd_codec_info {
        uint32_t        devid;
        const char      *buf;
        uint32_t        flags;
};

/*
 * Operation for high definition audio control system bus
 * interface registers
 */
#define AUDIOHD_REG_GET8(reg)   \
        ddi_get8(statep->hda_reg_handle, \
        (void *)((char *)statep->hda_reg_base + (reg)))

#define AUDIOHD_REG_GET16(reg)  \
        ddi_get16(statep->hda_reg_handle, \
        (void *)((char *)statep->hda_reg_base + (reg)))

#define AUDIOHD_REG_GET32(reg)  \
        ddi_get32(statep->hda_reg_handle, \
        (void *)((char *)statep->hda_reg_base + (reg)))

#define AUDIOHD_REG_GET64(reg)  \
        ddi_get64(statep->hda_reg_handle, \
        (void *)((char *)statep->hda_reg_base + (reg)))

#define AUDIOHD_REG_SET8(reg, val)      \
        ddi_put8(statep->hda_reg_handle, \
        (void *)((char *)statep->hda_reg_base + (reg)), (val))

#define AUDIOHD_REG_SET16(reg, val)     \
        ddi_put16(statep->hda_reg_handle, \
        (void *)((char *)statep->hda_reg_base + (reg)), (val))

#define AUDIOHD_REG_SET32(reg, val)     \
        ddi_put32(statep->hda_reg_handle, \
        (void *)((char *)statep->hda_reg_base + (reg)), (val))

#define AUDIOHD_REG_SET64(reg, val)     \
        ddi_put64(statep->hda_reg_handle, \
        (void *)((char *)statep->hda_reg_base + (reg)), (val))


/*
 * enable a pin widget to input
 */
#define AUDIOHD_ENABLE_PIN_IN(statep, caddr, wid) \
{ \
        (void) audioha_codec_verb_get(statep, caddr, wid, \
            AUDIOHDC_VERB_SET_PIN_CTRL, AUDIOHDC_PIN_CONTROL_IN_ENABLE | 4); \
}

/*
 * disable input pin
 */
#define AUDIOHD_DISABLE_PIN_IN(statep, caddr, wid) \
{ \
        uint32_t        lTmp; \
\
        lTmp = audioha_codec_verb_get(statep, caddr, wid, \
            AUDIOHDC_VERB_GET_PIN_CTRL, 0); \
        if (lTmp == AUDIOHD_CODEC_FAILURE) \
                return (DDI_FAILURE); \
        lTmp = audioha_codec_verb_get(statep, caddr, wid, \
            AUDIOHDC_VERB_SET_PIN_CTRL, \
            (lTmp & ~AUDIOHDC_PIN_CONTROL_IN_ENABLE)); \
        if (lTmp == AUDIOHD_CODEC_FAILURE) \
                return (DDI_FAILURE); \
}

/*
 * unmute an output pin
 */
#define AUDIOHD_NODE_UNMUTE_OUT(statep, caddr, wid) \
{ \
        if (audioha_codec_4bit_verb_get(statep, \
            caddr, wid, AUDIOHDC_VERB_SET_AMP_MUTE, \
            AUDIOHDC_AMP_SET_LR_OUTPUT | AUDIOHDC_GAIN_MAX) == \
            AUDIOHD_CODEC_FAILURE) \
                return (DDI_FAILURE); \
}

/*
 * check volume adjust value of 2 channels control
 */
#define AUDIOHD_CHECK_2CHANNELS_VOLUME(value) \
{ \
        if ((value) & ~0xffff) \
                return (EINVAL); \
        if ((((value) & 0xff00) >> 8) > 100 || \
            ((value) & 0xff) > 100) \
                return (EINVAL); \
}

/*
 * check volume adjust value of mono channel control
 */
#define AUDIOHD_CHECK_CHANNEL_VOLUME(value) \
{ \
        if ((value) & ~0xff) \
                return (EINVAL); \
        if (((value) & 0xff) > 100) \
                return (EINVAL); \
}

#ifdef __cplusplus
}
#endif

/* Warlock annotation */
_NOTE(DATA_READABLE_WITHOUT_LOCK(audiohd_ctrl::statep))
_NOTE(DATA_READABLE_WITHOUT_LOCK(audiohd_state::inmask))
_NOTE(DATA_READABLE_WITHOUT_LOCK(audiohd_state::adev))
_NOTE(DATA_READABLE_WITHOUT_LOCK(audiohd_state::sample_bit_depth))
_NOTE(DATA_READABLE_WITHOUT_LOCK(audiohd_state::sample_rate))
_NOTE(READ_ONLY_DATA(audiohd_state::hda_reg_handle))
_NOTE(DATA_READABLE_WITHOUT_LOCK(audiohd_widget::codec))
_NOTE(DATA_READABLE_WITHOUT_LOCK(audiohd_widget::wid_wid))
_NOTE(DATA_READABLE_WITHOUT_LOCK(hda_codec::index))
_NOTE(DATA_READABLE_WITHOUT_LOCK(hda_codec::statep))
_NOTE(DATA_READABLE_WITHOUT_LOCK(hda_codec::vid))
_NOTE(DATA_READABLE_WITHOUT_LOCK(audiohd_port::nchan))
_NOTE(DATA_READABLE_WITHOUT_LOCK(audiohd_port::statep))
_NOTE(DATA_READABLE_WITHOUT_LOCK(audiohd_port::sync_dir))

#endif  /* _SYS_AUDIOHD_IMPL_H_ */