diff options
author | Takashi Iwai <tiwai@suse.de> | 2006-11-24 09:42:07 -0500 |
---|---|---|
committer | Jaroslav Kysela <perex@suse.cz> | 2007-02-09 03:01:56 -0500 |
commit | a9e996604f77be6f1f4deb0eb1cc2652000054f1 (patch) | |
tree | 38d456ed63e961f0e228c894f84a411430286ebc /sound/pci | |
parent | 5da8fa2516388a20a43cd928fda19f6ac2521afc (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')
-rw-r--r-- | sound/pci/intel8x0.c | 86 |
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; | |||
71 | static int buggy_semaphore; | 71 | static int buggy_semaphore; |
72 | static int buggy_irq = -1; /* auto-check */ | 72 | static int buggy_irq = -1; /* auto-check */ |
73 | static int xbox; | 73 | static int xbox; |
74 | static int spdif_aclink = -1; | ||
74 | 75 | ||
75 | module_param(index, int, 0444); | 76 | module_param(index, int, 0444); |
76 | MODULE_PARM_DESC(index, "Index value for Intel i8x0 soundcard."); | 77 | MODULE_PARM_DESC(index, "Index value for Intel i8x0 soundcard."); |
@@ -86,6 +87,8 @@ module_param(buggy_irq, bool, 0444); | |||
86 | MODULE_PARM_DESC(buggy_irq, "Enable workaround for buggy interrupts on some motherboards."); | 87 | MODULE_PARM_DESC(buggy_irq, "Enable workaround for buggy interrupts on some motherboards."); |
87 | module_param(xbox, bool, 0444); | 88 | module_param(xbox, bool, 0444); |
88 | MODULE_PARM_DESC(xbox, "Set to 1 for Xbox, if you have problems with the AC'97 codec detection."); | 89 | MODULE_PARM_DESC(xbox, "Set to 1 for Xbox, if you have problems with the AC'97 codec detection."); |
90 | module_param(spdif_aclink, int, 0444); | ||
91 | MODULE_PARM_DESC(spdif_aclink, "S/PDIF over AC-link."); | ||
89 | 92 | ||
90 | /* just for backward compatibility */ | 93 | /* just for backward compatibility */ |
91 | static int enable; | 94 | static 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 | ||
2940 | static 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 */ | ||
2946 | static 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 | |||
2931 | static int __devinit snd_intel8x0_probe(struct pci_dev *pci, | 2963 | static 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"); |