aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/intel8x0.c
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2006-11-24 09:42:07 -0500
committerJaroslav Kysela <perex@suse.cz>2007-02-09 03:01:56 -0500
commita9e996604f77be6f1f4deb0eb1cc2652000054f1 (patch)
tree38d456ed63e961f0e228c894f84a411430286ebc /sound/pci/intel8x0.c
parent5da8fa2516388a20a43cd928fda19f6ac2521afc (diff)
[ALSA] intel8x0 - Add spdif_aclink option
Added spdif_aclink module option to specify whether the board has SPDIF over AC-link or a direct connection from the controller chip. NForce and ICH4 (or newer) boards may be equipped with SPDIF through AC97 codec. In such a case, SPDIF should be handled as if the old ICH style (the same slot for analog and digital). A quirk list is added to detect this automatically for known hardwares. Corresponds to ALSA bug#2637. Signed-off-by: Takashi Iwai <tiwai@suse.de> Signed-off-by: Jaroslav Kysela <perex@suse.cz>
Diffstat (limited to 'sound/pci/intel8x0.c')
-rw-r--r--sound/pci/intel8x0.c86
1 files changed, 60 insertions, 26 deletions
diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c
index f8aef131be7a..a289abfc7172 100644
--- a/sound/pci/intel8x0.c
+++ b/sound/pci/intel8x0.c
@@ -71,6 +71,7 @@ static char *ac97_quirk;
71static int buggy_semaphore; 71static int buggy_semaphore;
72static int buggy_irq = -1; /* auto-check */ 72static int buggy_irq = -1; /* auto-check */
73static int xbox; 73static int xbox;
74static int spdif_aclink = -1;
74 75
75module_param(index, int, 0444); 76module_param(index, int, 0444);
76MODULE_PARM_DESC(index, "Index value for Intel i8x0 soundcard."); 77MODULE_PARM_DESC(index, "Index value for Intel i8x0 soundcard.");
@@ -86,6 +87,8 @@ module_param(buggy_irq, bool, 0444);
86MODULE_PARM_DESC(buggy_irq, "Enable workaround for buggy interrupts on some motherboards."); 87MODULE_PARM_DESC(buggy_irq, "Enable workaround for buggy interrupts on some motherboards.");
87module_param(xbox, bool, 0444); 88module_param(xbox, bool, 0444);
88MODULE_PARM_DESC(xbox, "Set to 1 for Xbox, if you have problems with the AC'97 codec detection."); 89MODULE_PARM_DESC(xbox, "Set to 1 for Xbox, if you have problems with the AC'97 codec detection.");
90module_param(spdif_aclink, int, 0444);
91MODULE_PARM_DESC(spdif_aclink, "S/PDIF over AC-link.");
89 92
90/* just for backward compatibility */ 93/* just for backward compatibility */
91static int enable; 94static int enable;
@@ -1578,10 +1581,14 @@ static int __devinit snd_intel8x0_pcm(struct intel8x0 *chip)
1578 case DEVICE_INTEL_ICH4: 1581 case DEVICE_INTEL_ICH4:
1579 tbl = intel_pcms; 1582 tbl = intel_pcms;
1580 tblsize = ARRAY_SIZE(intel_pcms); 1583 tblsize = ARRAY_SIZE(intel_pcms);
1584 if (spdif_aclink)
1585 tblsize--;
1581 break; 1586 break;
1582 case DEVICE_NFORCE: 1587 case DEVICE_NFORCE:
1583 tbl = nforce_pcms; 1588 tbl = nforce_pcms;
1584 tblsize = ARRAY_SIZE(nforce_pcms); 1589 tblsize = ARRAY_SIZE(nforce_pcms);
1590 if (spdif_aclink)
1591 tblsize--;
1585 break; 1592 break;
1586 case DEVICE_ALI: 1593 case DEVICE_ALI:
1587 tbl = ali_pcms; 1594 tbl = ali_pcms;
@@ -2040,17 +2047,19 @@ static int __devinit snd_intel8x0_mixer(struct intel8x0 *chip, int ac97_clock,
2040 }; 2047 };
2041 2048
2042 chip->spdif_idx = -1; /* use PCMOUT (or disabled) */ 2049 chip->spdif_idx = -1; /* use PCMOUT (or disabled) */
2043 switch (chip->device_type) { 2050 if (!spdif_aclink) {
2044 case DEVICE_NFORCE: 2051 switch (chip->device_type) {
2045 chip->spdif_idx = NVD_SPBAR; 2052 case DEVICE_NFORCE:
2046 break; 2053 chip->spdif_idx = NVD_SPBAR;
2047 case DEVICE_ALI: 2054 break;
2048 chip->spdif_idx = ALID_AC97SPDIFOUT; 2055 case DEVICE_ALI:
2049 break; 2056 chip->spdif_idx = ALID_AC97SPDIFOUT;
2050 case DEVICE_INTEL_ICH4: 2057 break;
2051 chip->spdif_idx = ICHD_SPBAR; 2058 case DEVICE_INTEL_ICH4:
2052 break; 2059 chip->spdif_idx = ICHD_SPBAR;
2053 }; 2060 break;
2061 };
2062 }
2054 2063
2055 chip->in_ac97_init = 1; 2064 chip->in_ac97_init = 1;
2056 2065
@@ -2173,11 +2182,11 @@ static int __devinit snd_intel8x0_mixer(struct intel8x0 *chip, int ac97_clock,
2173 if ((igetdword(chip, ICHREG(GLOB_STA)) & ICH_SAMPLE_CAP) == ICH_SAMPLE_16_20) 2182 if ((igetdword(chip, ICHREG(GLOB_STA)) & ICH_SAMPLE_CAP) == ICH_SAMPLE_16_20)
2174 chip->smp20bit = 1; 2183 chip->smp20bit = 1;
2175 } 2184 }
2176 if (chip->device_type == DEVICE_NFORCE) { 2185 if (chip->device_type == DEVICE_NFORCE && !spdif_aclink) {
2177 /* 48kHz only */ 2186 /* 48kHz only */
2178 chip->ichd[chip->spdif_idx].pcm->rates = SNDRV_PCM_RATE_48000; 2187 chip->ichd[chip->spdif_idx].pcm->rates = SNDRV_PCM_RATE_48000;
2179 } 2188 }
2180 if (chip->device_type == DEVICE_INTEL_ICH4) { 2189 if (chip->device_type == DEVICE_INTEL_ICH4 && !spdif_aclink) {
2181 /* use slot 10/11 for SPDIF */ 2190 /* use slot 10/11 for SPDIF */
2182 u32 val; 2191 u32 val;
2183 val = igetdword(chip, ICHREG(GLOB_CNT)) & ~ICH_PCM_SPDIF_MASK; 2192 val = igetdword(chip, ICHREG(GLOB_CNT)) & ~ICH_PCM_SPDIF_MASK;
@@ -2305,7 +2314,7 @@ static int snd_intel8x0_ich_chip_init(struct intel8x0 *chip, int probing)
2305 /* unmute the output on SIS7012 */ 2314 /* unmute the output on SIS7012 */
2306 iputword(chip, 0x4c, igetword(chip, 0x4c) | 1); 2315 iputword(chip, 0x4c, igetword(chip, 0x4c) | 1);
2307 } 2316 }
2308 if (chip->device_type == DEVICE_NFORCE) { 2317 if (chip->device_type == DEVICE_NFORCE && !spdif_aclink) {
2309 /* enable SPDIF interrupt */ 2318 /* enable SPDIF interrupt */
2310 unsigned int val; 2319 unsigned int val;
2311 pci_read_config_dword(chip->pci, 0x4c, &val); 2320 pci_read_config_dword(chip->pci, 0x4c, &val);
@@ -2398,7 +2407,7 @@ static int snd_intel8x0_free(struct intel8x0 *chip)
2398 /* reset channels */ 2407 /* reset channels */
2399 for (i = 0; i < chip->bdbars_count; i++) 2408 for (i = 0; i < chip->bdbars_count; i++)
2400 iputbyte(chip, ICH_REG_OFF_CR + chip->ichd[i].reg_offset, ICH_RESETREGS); 2409 iputbyte(chip, ICH_REG_OFF_CR + chip->ichd[i].reg_offset, ICH_RESETREGS);
2401 if (chip->device_type == DEVICE_NFORCE) { 2410 if (chip->device_type == DEVICE_NFORCE && !spdif_aclink) {
2402 /* stop the spdif interrupt */ 2411 /* stop the spdif interrupt */
2403 unsigned int val; 2412 unsigned int val;
2404 pci_read_config_dword(chip->pci, 0x4c, &val); 2413 pci_read_config_dword(chip->pci, 0x4c, &val);
@@ -2492,7 +2501,7 @@ static int intel8x0_resume(struct pci_dev *pci)
2492 snd_intel8x0_chip_init(chip, 0); 2501 snd_intel8x0_chip_init(chip, 0);
2493 2502
2494 /* re-initialize mixer stuff */ 2503 /* re-initialize mixer stuff */
2495 if (chip->device_type == DEVICE_INTEL_ICH4) { 2504 if (chip->device_type == DEVICE_INTEL_ICH4 && !spdif_aclink) {
2496 /* enable separate SDINs for ICH4 */ 2505 /* enable separate SDINs for ICH4 */
2497 iputbyte(chip, ICHREG(SDM), chip->sdm_saved); 2506 iputbyte(chip, ICHREG(SDM), chip->sdm_saved);
2498 /* use slot 10/11 for SPDIF */ 2507 /* use slot 10/11 for SPDIF */
@@ -2928,6 +2937,29 @@ static struct shortname_table {
2928 { 0, NULL }, 2937 { 0, NULL },
2929}; 2938};
2930 2939
2940static struct snd_pci_quirk spdif_aclink_defaults[] __devinitdata = {
2941 SND_PCI_QUIRK(0x147b, 0x1c1a, "ASUS KN8", 1),
2942 { } /* end */
2943};
2944
2945/* look up white/black list for SPDIF over ac-link */
2946static int __devinit check_default_spdif_aclink(struct pci_dev *pci)
2947{
2948 const struct snd_pci_quirk *w;
2949
2950 w = snd_pci_quirk_lookup(pci, spdif_aclink_defaults);
2951 if (w) {
2952 if (w->value)
2953 snd_printdd(KERN_INFO "intel8x0: Using SPDIF over "
2954 "AC-Link for %s\n", w->name);
2955 else
2956 snd_printdd(KERN_INFO "intel8x0: Using integrated "
2957 "SPDIF DMA for %s\n", w->name);
2958 return w->value;
2959 }
2960 return 0;
2961}
2962
2931static int __devinit snd_intel8x0_probe(struct pci_dev *pci, 2963static int __devinit snd_intel8x0_probe(struct pci_dev *pci,
2932 const struct pci_device_id *pci_id) 2964 const struct pci_device_id *pci_id)
2933{ 2965{
@@ -2940,16 +2972,18 @@ static int __devinit snd_intel8x0_probe(struct pci_dev *pci,
2940 if (card == NULL) 2972 if (card == NULL)
2941 return -ENOMEM; 2973 return -ENOMEM;
2942 2974
2943 switch (pci_id->driver_data) { 2975 if (spdif_aclink < 0)
2944 case DEVICE_NFORCE: 2976 spdif_aclink = check_default_spdif_aclink(pci);
2945 strcpy(card->driver, "NFORCE"); 2977
2946 break; 2978 strcpy(card->driver, "ICH");
2947 case DEVICE_INTEL_ICH4: 2979 if (!spdif_aclink) {
2948 strcpy(card->driver, "ICH4"); 2980 switch (pci_id->driver_data) {
2949 break; 2981 case DEVICE_NFORCE:
2950 default: 2982 strcpy(card->driver, "NFORCE");
2951 strcpy(card->driver, "ICH"); 2983 break;
2952 break; 2984 case DEVICE_INTEL_ICH4:
2985 strcpy(card->driver, "ICH4");
2986 }
2953 } 2987 }
2954 2988
2955 strcpy(card->shortname, "Intel ICH"); 2989 strcpy(card->shortname, "Intel ICH");