diff --git a/sys/dev/pci/azalia.c b/sys/dev/pci/azalia.c index e02e51c6272b..73a740396a83 100644 --- a/sys/dev/pci/azalia.c +++ b/sys/dev/pci/azalia.c @@ -1,4 +1,4 @@ -/* $NetBSD: azalia.c,v 1.12 2005/09/26 17:30:04 kent Exp $ */ +/* $NetBSD: azalia.c,v 1.13 2005/09/28 13:06:49 kent Exp $ */ /*- * Copyright (c) 2005 The NetBSD Foundation, Inc. @@ -49,428 +49,18 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: azalia.c,v 1.12 2005/09/26 17:30:04 kent Exp $"); +__KERNEL_RCSID(0, "$NetBSD: azalia.c,v 1.13 2005/09/28 13:06:49 kent Exp $"); #include #include #include #include -#include #include #include #include #include -/* ---------------------------------------------------------------- - * 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 0x00000080 -#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_CONVERTER_CONTROL 0xf0d -#define CORB_SET_DIGITAL_CONVERTER_CONTROL_L 0x70d -#define CORB_SET_DIGITAL_CONVERTER_CONTROL_H 0x70e -#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_GET_PIN_SENSE 0xf09 -#define CORB_EXECUTE_PIN_SENSE 0x709 -#define CORB_GET_EAPD_BTL_ENABLE 0xf0c -#define CORB_SET_EAPD_BTL_ENABLE 0x70c -#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 - - -#define PCI_SUBCLASS_HDAUDIO 0x03 - -/* 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_UNSOLICITED_RESPONSE (1 << 4) -} __packed rirb_entry_t; - +#include /* ---------------------------------------------------------------- * ICH6/ICH7 constant values @@ -485,17 +75,6 @@ typedef struct { #define ICH_PCI_HDCTL_CLKDETINV 0x02 #define ICH_PCI_HDCTL_SIGNALMODE 0x01 -/* #define AZALIA_DEBUG */ -#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 - - /* internal types */ typedef struct { @@ -531,84 +110,6 @@ typedef struct { #define STR_WRITE_4(s, r, v) \ bus_space_write_4((s)->az->iot, (s)->az->ioh, (s)->regbase + HDA_SD_##r, v) -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; - -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 -} mixer_item_t; - -typedef struct { - int nconv; - nid_t conv[HDA_MAX_CHANNELS]; -} convgroup_t; - -typedef struct codec_t { - int (*comresp)(const struct codec_t *, nid_t, uint32_t, uint32_t, uint32_t *); - struct azalia_t *az; - 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++) - - int ndacgroups; - convgroup_t dacgroups[32]; - int cur_dac; /* currently selected DAC group index */ - int nadcs; - nid_t adcs[32]; - int cur_adc; /* currently selected ADC index */ - - int nmixers, maxmixers; - mixer_item_t *mixers; - - struct audio_format* formats; - int nformats; - struct audio_encoding_set *encodings; -} codec_t; - typedef struct azalia_t { struct device dev; struct device *audiodev; @@ -666,14 +167,10 @@ static int azalia_free_dmamem(const azalia_t *, azalia_dma_t*); static int azalia_codec_init(codec_t *); static int azalia_codec_delete(codec_t *); -static int azalia_codec_init_dacgroup(codec_t *); -static int azalia_codec_add_dacgroup(codec_t *, int, uint32_t); static int azalia_codec_construct_format(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_find_pin(const codec_t *, int, int, uint32_t); -static int azalia_codec_find_dac(const codec_t *, int, int); 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); @@ -931,7 +428,7 @@ azalia_intr(void *v) rirbsts | HDA_RIRBSTS_RIRBOIS | HDA_RIRBSTS_RINTFL); ret++; } - return 0; + return ret; } /* ================================================================ @@ -1527,118 +1024,6 @@ azalia_codec_delete(codec_t *this) return 0; } -static int -azalia_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->ndacgroups = 0; - for (assoc = 0; assoc < CORB_CD_ASSOCIATION_MAX; assoc++) { - azalia_codec_add_dacgroup(this, assoc, 0); - azalia_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) { - boolean_t found; - - if (this->w[i].type != COP_AWTYPE_AUDIO_OUTPUT) - continue; - found = FALSE; - for (group = 0; group < this->ndacgroups; group++) { - for (j = 0; j < this->dacgroups[group].nconv; j++) { - if (i == this->dacgroups[group].conv[j]) { - found = TRUE; - group = this->ndacgroups; - break; - } - } - } - if (found) - continue; - if (this->ndacgroups >= 32) - break; - this->dacgroups[this->ndacgroups].nconv = 1; - this->dacgroups[this->ndacgroups].conv[0] = i; - this->ndacgroups++; - } -#ifdef AZALIA_DEBUG - for (group = 0; group < this->ndacgroups; group++) { - DPRINTF(("%s: dacgroup[%d]:", __func__, group)); - for (j = 0; j < this->dacgroups[group].nconv; j++) { - DPRINTF((" %2.2x", this->dacgroups[group].conv[j])); - } - DPRINTF(("\n")); - } -#endif - this->cur_dac = 0; - - /* enumerate ADCs */ - this->nadcs = 0; - FOR_EACH_WIDGET(this, i) { - if (this->w[i].type != COP_AWTYPE_AUDIO_INPUT) - continue; - this->adcs[this->nadcs++] = i; - if (this->nadcs >= 32) - break; - } - this->cur_adc = 0; - return 0; -} - -static int -azalia_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 = azalia_codec_find_pin(this, assoc, seq, digital); - if (i < 0) - continue; - dac = azalia_codec_find_dac(this, i, 0); - if (dac < 0) - continue; - /* duplication check */ - for (j = 0; j < n; j++) { - if (this->dacgroups[this->ndacgroups].conv[j] == dac) - break; - } - if (j < n) /* this group already has */ - continue; - this->dacgroups[this->ndacgroups].conv[n++] = dac; - DPRINTF(("%s: assoc=%d seq=%d ==> g=%d n=%d\n", - __func__, assoc, seq, this->ndacgroups, n-1)); - } - if (n <= 0) /* no such DACs */ - return 0; - this->dacgroups[this->ndacgroups].nconv = n; - - /* check if the same combination is already registered */ - for (i = 0; i < this->ndacgroups; i++) { - if (n != this->dacgroups[i].nconv) - continue; - for (j = 0; j < n; j++) { - if (this->dacgroups[this->ndacgroups].conv[j] != - this->dacgroups[i].conv[j]) - break; - } - if (j >= n) /* matched */ - return 0; - } - /* found no equivalent group */ - this->ndacgroups++; - return 0; -} - static int azalia_codec_construct_format(codec_t *this) { @@ -1818,63 +1203,6 @@ azalia_codec_add_format(codec_t *this, int chan, int valid, int prec, f->frequency[f->frequency_type++] = 384000; } -static int -azalia_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 -azalia_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]; - ret = azalia_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]; - ret = azalia_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; -} - static int azalia_codec_comresp(const codec_t *codec, nid_t nid, uint32_t control, uint32_t param, uint32_t* result) diff --git a/sys/dev/pci/azalia.h b/sys/dev/pci/azalia.h new file mode 100644 index 000000000000..b56bbf5c27ce --- /dev/null +++ b/sys/dev/pci/azalia.h @@ -0,0 +1,542 @@ +/* $NetBSD: azalia.h,v 1.1 2005/09/28 13:06:49 kent Exp $ */ + +/*- + * Copyright (c) 2005 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. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 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 +#include + +/* ---------------------------------------------------------------- + * 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 0x00000080 +#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_CONVERTER_CONTROL 0xf0d +#define CORB_SET_DIGITAL_CONVERTER_CONTROL_L 0x70d +#define CORB_SET_DIGITAL_CONVERTER_CONTROL_H 0x70e +#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_GET_PIN_SENSE 0xf09 +#define CORB_EXECUTE_PIN_SENSE 0x709 +#define CORB_GET_EAPD_BTL_ENABLE 0xf0c +#define CORB_SET_EAPD_BTL_ENABLE 0x70c +#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 + + +#define PCI_SUBCLASS_HDAUDIO 0x03 + +/* 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_UNSOLICITED_RESPONSE (1 << 4) +} __packed rirb_entry_t; + + +/* #define AZALIA_DEBUG */ +#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; + +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 +} mixer_item_t; + +typedef struct { + int nconv; + nid_t conv[HDA_MAX_CHANNELS]; +} convgroup_t; + +typedef struct codec_t { + int (*comresp)(const struct codec_t *, nid_t, uint32_t, uint32_t, uint32_t *); + struct azalia_t *az; + 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++) + + int ndacgroups; + convgroup_t dacgroups[32]; + int cur_dac; /* currently selected DAC group index */ + int nadcs; + nid_t adcs[32]; + int cur_adc; /* currently selected ADC index */ + + int nmixers, maxmixers; + mixer_item_t *mixers; + + struct audio_format* formats; + int nformats; + struct audio_encoding_set *encodings; +} codec_t; + + +int azalia_codec_init_dacgroup(codec_t *); diff --git a/sys/dev/pci/azalia_codec.c b/sys/dev/pci/azalia_codec.c new file mode 100644 index 000000000000..c59e7444f2c5 --- /dev/null +++ b/sys/dev/pci/azalia_codec.c @@ -0,0 +1,216 @@ +/* $NetBSD: azalia_codec.c,v 1.1 2005/09/28 13:06:49 kent Exp $ */ + +/*- + * Copyright (c) 2005 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. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 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 +__KERNEL_RCSID(0, "$NetBSD: azalia_codec.c,v 1.1 2005/09/28 13:06:49 kent Exp $"); + +#include + +static int azalia_codec_add_dacgroup(codec_t *, int, uint32_t); +static int azalia_codec_find_pin(const codec_t *, int, int, uint32_t); +static int azalia_codec_find_dac(const codec_t *, int, int); + +int +azalia_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->ndacgroups = 0; + for (assoc = 0; assoc < CORB_CD_ASSOCIATION_MAX; assoc++) { + azalia_codec_add_dacgroup(this, assoc, 0); + azalia_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) { + boolean_t found; + + if (this->w[i].type != COP_AWTYPE_AUDIO_OUTPUT) + continue; + found = FALSE; + for (group = 0; group < this->ndacgroups; group++) { + for (j = 0; j < this->dacgroups[group].nconv; j++) { + if (i == this->dacgroups[group].conv[j]) { + found = TRUE; + group = this->ndacgroups; + break; + } + } + } + if (found) + continue; + if (this->ndacgroups >= 32) + break; + this->dacgroups[this->ndacgroups].nconv = 1; + this->dacgroups[this->ndacgroups].conv[0] = i; + this->ndacgroups++; + } +#ifdef AZALIA_DEBUG + for (group = 0; group < this->ndacgroups; group++) { + DPRINTF(("%s: dacgroup[%d]:", __func__, group)); + for (j = 0; j < this->dacgroups[group].nconv; j++) { + DPRINTF((" %2.2x", this->dacgroups[group].conv[j])); + } + DPRINTF(("\n")); + } +#endif + this->cur_dac = 0; + + /* enumerate ADCs */ + this->nadcs = 0; + FOR_EACH_WIDGET(this, i) { + if (this->w[i].type != COP_AWTYPE_AUDIO_INPUT) + continue; + this->adcs[this->nadcs++] = i; + if (this->nadcs >= 32) + break; + } + this->cur_adc = 0; + return 0; +} + +static int +azalia_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 = azalia_codec_find_pin(this, assoc, seq, digital); + if (i < 0) + continue; + dac = azalia_codec_find_dac(this, i, 0); + if (dac < 0) + continue; + /* duplication check */ + for (j = 0; j < n; j++) { + if (this->dacgroups[this->ndacgroups].conv[j] == dac) + break; + } + if (j < n) /* this group already has */ + continue; + this->dacgroups[this->ndacgroups].conv[n++] = dac; + DPRINTF(("%s: assoc=%d seq=%d ==> g=%d n=%d\n", + __func__, assoc, seq, this->ndacgroups, n-1)); + } + if (n <= 0) /* no such DACs */ + return 0; + this->dacgroups[this->ndacgroups].nconv = n; + + /* check if the same combination is already registered */ + for (i = 0; i < this->ndacgroups; i++) { + if (n != this->dacgroups[i].nconv) + continue; + for (j = 0; j < n; j++) { + if (this->dacgroups[this->ndacgroups].conv[j] != + this->dacgroups[i].conv[j]) + break; + } + if (j >= n) /* matched */ + return 0; + } + /* found no equivalent group */ + this->ndacgroups++; + return 0; +} + +static int +azalia_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 +azalia_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]; + ret = azalia_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]; + ret = azalia_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; +} + diff --git a/sys/dev/pci/files.pci b/sys/dev/pci/files.pci index 64029c1f4e7a..9ac8f4c31130 100644 --- a/sys/dev/pci/files.pci +++ b/sys/dev/pci/files.pci @@ -1,4 +1,4 @@ -# $NetBSD: files.pci,v 1.238 2005/09/09 10:30:27 ragge Exp $ +# $NetBSD: files.pci,v 1.239 2005/09/28 13:06:49 kent Exp $ # # Config file and device description for machine-independent PCI code. # Included by ports that need it. Requires that the SCSI files be @@ -441,6 +441,7 @@ file dev/pci/auixp.c auixp device azalia: audiobus, auconv, mulaw, ac97, aurateconv attach azalia at pci file dev/pci/azalia.c azalia +file dev/pci/azalia_codec.c azalia # NeoMagic 256 AC'97 Audio device neo: audiobus, auconv, mulaw, ac97