diff options
author | Zhao Edgar Liu - Sun Microsystems <Edgar.Liu@Sun.COM> | 2009-10-21 10:55:51 +0800 |
---|---|---|
committer | Zhao Edgar Liu - Sun Microsystems <Edgar.Liu@Sun.COM> | 2009-10-21 10:55:51 +0800 |
commit | 89e1f902f752842a275fadd3481dd907e0a1a82a (patch) | |
tree | a1e556775a2c2df4c7855bd0587ffb243d64d203 /usr/src | |
parent | 86e4912a3476b98b8ed9e884e1994b058aff908e (diff) | |
download | illumos-gate-89e1f902f752842a275fadd3481dd907e0a1a82a.tar.gz |
6884252 Reliable hang with MCP51 audio effective build 123
Diffstat (limited to 'usr/src')
-rw-r--r-- | usr/src/uts/common/io/audio/drv/audiohd/audiohd.c | 70 | ||||
-rw-r--r-- | usr/src/uts/common/io/audio/drv/audiohd/audiohd.h | 13 |
2 files changed, 69 insertions, 14 deletions
diff --git a/usr/src/uts/common/io/audio/drv/audiohd/audiohd.c b/usr/src/uts/common/io/audio/drv/audiohd/audiohd.c index ad73de7c24..708f5cfebb 100644 --- a/usr/src/uts/common/io/audio/drv/audiohd/audiohd.c +++ b/usr/src/uts/common/io/audio/drv/audiohd/audiohd.c @@ -149,6 +149,7 @@ audiohd_set_chipset_info(audiohd_state_t *statep) devid = pci_config_get16(statep->hda_pci_handle, PCI_CONF_VENID); devid <<= 16; devid |= pci_config_get16(statep->hda_pci_handle, PCI_CONF_DEVID); + statep->devid = devid; name = AUDIOHD_DEV_CONFIG; vers = AUDIOHD_DEV_VERSION; @@ -180,7 +181,7 @@ audiohd_set_chipset_info(audiohd_state_t *statep) break; case 0x10de026c: name = "NVIDIA HD Audio"; - vers = "6151"; + vers = "MCP51"; break; case 0x10de03e4: name = "NVIDIA HD Audio"; @@ -194,6 +195,10 @@ audiohd_set_chipset_info(audiohd_state_t *statep) name = "NVIDIA HD Audio"; vers = "MCP67"; break; + case 0x10de0ac0: + name = "NVIDIA HD Audio"; + vers = "MCP79"; + break; case 0x1002437b: name = "ATI HD Audio"; vers = "SB450"; @@ -228,13 +233,14 @@ audiohd_add_intrs(audiohd_state_t *statep, int intr_type) int intr_size; int count; int i, j; - int ret; + int ret, flag; /* Get number of interrupts */ ret = ddi_intr_get_nintrs(dip, intr_type, &count); if ((ret != DDI_SUCCESS) || (count == 0)) { - audio_dev_warn(statep->adev, "ddi_intr_get_nintrs() failure," - "ret: %d, count: %d", ret, count); + audio_dev_warn(statep->adev, + "ddi_intr_get_nintrs() failure, ret: %d, count: %d", + ret, count); return (DDI_FAILURE); } @@ -246,24 +252,35 @@ audiohd_add_intrs(audiohd_state_t *statep, int intr_type) return (DDI_FAILURE); } + if (avail < 1) { + audio_dev_warn(statep->adev, + "Interrupts count: %d, available: %d", + count, avail); + } + /* Allocate an array of interrupt handles */ intr_size = count * sizeof (ddi_intr_handle_t); statep->htable = kmem_alloc(intr_size, KM_SLEEP); statep->intr_rqst = count; + flag = (intr_type == DDI_INTR_TYPE_MSI) ? + DDI_INTR_ALLOC_STRICT:DDI_INTR_ALLOC_NORMAL; + /* Call ddi_intr_alloc() */ ret = ddi_intr_alloc(dip, statep->htable, intr_type, 0, - count, &actual, DDI_INTR_ALLOC_NORMAL); + count, &actual, flag); if (ret != DDI_SUCCESS || actual == 0) { /* ddi_intr_alloc() failed */ kmem_free(statep->htable, intr_size); return (DDI_FAILURE); } - if (actual < count) { - audio_dev_warn(statep->adev, "ddi_intr_alloc() Requested: %d," - "Received: %d", + + if (actual < 1) { + audio_dev_warn(statep->adev, + "Interrupts requested: %d, received: %d", count, actual); } + statep->intr_cnt = actual; /* @@ -323,6 +340,10 @@ audiohd_add_intrs(audiohd_state_t *statep, int intr_type) return (DDI_FAILURE); } + for (i = 0; i < actual; i++) { + (void) ddi_intr_clr_mask(statep->htable[i]); + } + return (DDI_SUCCESS); } @@ -363,7 +384,7 @@ audiohd_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) audiohd_state_t *statep; int instance; int intr_types; - int i; + int i, rc = 0; instance = ddi_get_instance(dip); switch (cmd) { @@ -481,11 +502,21 @@ audiohd_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) */ if (statep->intr_cap & DDI_INTR_FLAG_BLOCK) { /* Call ddi_intr_block_enable() for MSI interrupts */ - (void) ddi_intr_block_enable(statep->htable, statep->intr_cnt); + rc = ddi_intr_block_enable(statep->htable, statep->intr_cnt); + if (rc != DDI_SUCCESS) { + audio_dev_warn(statep->adev, + "Enable block intr failed: %d\n", rc); + return (DDI_FAILURE); + } } else { /* Call ddi_intr_enable for MSI or FIXED interrupts */ for (i = 0; i < statep->intr_cnt; i++) { - (void) ddi_intr_enable(statep->htable[i]); + rc = ddi_intr_enable(statep->htable[i]); + if (rc != DDI_SUCCESS) { + audio_dev_warn(statep->adev, + "Enable intr failed: %d\n", rc); + return (DDI_FAILURE); + } } } @@ -959,6 +990,7 @@ audiohd_reset_port(audiohd_port_t *port) return (DDI_SUCCESS); } + static int audiohd_engine_open(void *arg, int flag, unsigned *fragfrp, unsigned *nfragsp, caddr_t *bufp) @@ -2783,6 +2815,15 @@ audiohd_init_controller(audiohd_state_t *statep) AUDIOHD_REG_SET16(AUDIOHD_REG_CORBRP, 0); AUDIOHD_REG_SET8(AUDIOHD_REG_CORBCTL, AUDIOHDR_CORBCTL_DMARUN); + /* work around for some chipsets which could not enable MSI */ + switch (statep->devid) { + case AUDIOHD_CONTROLLER_MCP51: + statep->msi_enable = B_FALSE; + break; + default: + break; + } + return (DDI_SUCCESS); } /* audiohd_init_controller() */ @@ -3170,6 +3211,9 @@ audiohd_set_codec_info(hda_codec_t *codec) case 0x10ec0662: (void) snprintf(buf, sizeof (buf), "Realtek HD codec: ALC662"); break; + case 0x10ec0663: + (void) snprintf(buf, sizeof (buf), "Realtek HD codec: ALC663"); + break; case 0x10ec861: (void) snprintf(buf, sizeof (buf), "Realtek HD codec: ALC861"); break; @@ -3191,6 +3235,10 @@ audiohd_set_codec_info(hda_codec_t *codec) case 0x10ec0888: (void) snprintf(buf, sizeof (buf), "Realtek HD codec: ALC888"); break; + case 0x10de0007: + (void) snprintf(buf, sizeof (buf), + "nVidia HD codec: MCP7A HDMI"); + break; case 0x13f69880: (void) snprintf(buf, sizeof (buf), "CMedia HD codec: CMI19880"); break; diff --git a/usr/src/uts/common/io/audio/drv/audiohd/audiohd.h b/usr/src/uts/common/io/audio/drv/audiohd/audiohd.h index 47bc9d9752..4bfb3b8d53 100644 --- a/usr/src/uts/common/io/audio/drv/audiohd/audiohd.h +++ b/usr/src/uts/common/io/audio/drv/audiohd/audiohd.h @@ -35,9 +35,15 @@ extern "C" { #define AUDIOHD_VID_INTEL 0x8086 #define AUDIOHD_VID_ATI 0x1002 #define AUDIOHD_VID_NVIDIA 0x10de +#define AUDIOHD_VID_REALTEK 0x10ec #define AUDIOHD_VID_SIGMATEL 0x8384 /* + * specific audiohd controller device id + */ +#define AUDIOHD_CONTROLLER_MCP51 0x10de026c + +/* * specific codec id used by specific vendors */ #define AUDIOHD_CODEC_IDT7608 0x111d7608 @@ -95,7 +101,7 @@ extern "C" { #define AUDIOHD_SP_ON 1 #define AUDIOHD_SP_OFF 0 -#define AUDIOHD_PORT_MAX 15 +#define AUDIOHD_PORT_MAX 15 #define AUDIOHD_CODEC_MAX 16 #define AUDIOHD_MEMIO_LEN 0x4000 @@ -146,8 +152,8 @@ extern "C" { #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_PIN_CLR_MASK 0xf +#define AUDIOHD_PIN_CLR_OFF 12 #define AUDIOHD_VERB_ADDR_OFF 28 @@ -807,6 +813,7 @@ struct audiohd_state { audio_dev_t *adev; + uint32_t devid; int hda_pint_freq; /* play intr frequence */ |