[ALSA] Support all sample rate conversion capabilities of DXS channels

Documentation,VIA82xx driver
Add support for full sample rate conversion capabilities of DXS
channels present in VIA VT8233/5/7 controllers:

- any sample rate in the 8000 ... 48000 Hz range is supported even if
  the AC'97 codec supports only 48000 Hz output;

- different DXS channels can use different sample rates at the same
  time (the controller performs required sample rate conversion and
  mixing in hardware).

Signed-off-by: Sergey Vlasov <vsu@altlinux.ru>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
Sergey Vlasov 2005-04-11 15:04:33 +02:00 committed by Jaroslav Kysela
parent 26be865923
commit 2d7eb7cb2b
2 changed files with 30 additions and 11 deletions

View File

@ -1211,16 +1211,18 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
------------------ ------------------
Module for AC'97 motherboards based on VIA 82C686A/686B, 8233, Module for AC'97 motherboards based on VIA 82C686A/686B, 8233,
8233A, 8233C, 8235 (south) bridge. 8233A, 8233C, 8235, 8237 (south) bridge.
mpu_port - 0x300,0x310,0x320,0x330, otherwise obtain BIOS setup mpu_port - 0x300,0x310,0x320,0x330, otherwise obtain BIOS setup
[VIA686A/686B only] [VIA686A/686B only]
joystick - Enable joystick (default off) [VIA686A/686B only] joystick - Enable joystick (default off) [VIA686A/686B only]
ac97_clock - AC'97 codec clock base (default 48000Hz) ac97_clock - AC'97 codec clock base (default 48000Hz)
dxs_support - support DXS channels, dxs_support - support DXS channels,
0 = auto (defalut), 1 = enable, 2 = disable, 0 = auto (default), 1 = enable, 2 = disable,
3 = 48k only, 4 = no VRA 3 = 48k only, 4 = no VRA, 5 = enable any sample
[VIA8233/C,8235 only] rate and different sample rates on different
channels
[VIA8233/C, 8235, 8237 only]
ac97_quirk - AC'97 workaround for strange hardware ac97_quirk - AC'97 workaround for strange hardware
See the description of intel8x0 module for details. See the description of intel8x0 module for details.
@ -1232,18 +1234,21 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
default value 1.4. Then the interrupt number will be default value 1.4. Then the interrupt number will be
assigned under 15. You might also upgrade your BIOS. assigned under 15. You might also upgrade your BIOS.
Note: VIA8233/5 (not VIA8233A) can support DXS (direct sound) Note: VIA8233/5/7 (not VIA8233A) can support DXS (direct sound)
channels as the first PCM. On these channels, up to 4 channels as the first PCM. On these channels, up to 4
streams can be played at the same time. streams can be played at the same time, and the controller
can perform sample rate conversion with separate rates for
each channel.
As default (dxs_support = 0), 48k fixed rate is chosen As default (dxs_support = 0), 48k fixed rate is chosen
except for the known devices since the output is often except for the known devices since the output is often
noisy except for 48k on some mother boards due to the noisy except for 48k on some mother boards due to the
bug of BIOS. bug of BIOS.
Please try once dxs_support=1 and if it works on other Please try once dxs_support=5 and if it works on other
sample rates (e.g. 44.1kHz of mp3 playback), please let us sample rates (e.g. 44.1kHz of mp3 playback), please let us
know the PCI subsystem vendor/device id's (output of know the PCI subsystem vendor/device id's (output of
"lspci -nv"). "lspci -nv").
If it doesn't work, try dxs_support=4. If it still doesn't If dxs_support=5 does not work, try dxs_support=1; if it
doesn't work too, try dxs_support=4. If it still doesn't
work and the default setting is ok, dxs_support=3 is the work and the default setting is ok, dxs_support=3 is the
right choice. If the default setting doesn't work at all, right choice. If the default setting doesn't work at all,
try dxs_support=2 to disable the DXS channels. try dxs_support=2 to disable the DXS channels.

View File

@ -101,7 +101,7 @@ MODULE_PARM_DESC(ac97_clock, "AC'97 codec clock (default 48000Hz).");
module_param_array(ac97_quirk, charp, NULL, 0444); module_param_array(ac97_quirk, charp, NULL, 0444);
MODULE_PARM_DESC(ac97_quirk, "AC'97 workaround for strange hardware."); MODULE_PARM_DESC(ac97_quirk, "AC'97 workaround for strange hardware.");
module_param_array(dxs_support, int, NULL, 0444); module_param_array(dxs_support, int, NULL, 0444);
MODULE_PARM_DESC(dxs_support, "Support for DXS channels (0 = auto, 1 = enable, 2 = disable, 3 = 48k only, 4 = no VRA)"); MODULE_PARM_DESC(dxs_support, "Support for DXS channels (0 = auto, 1 = enable, 2 = disable, 3 = 48k only, 4 = no VRA, 5 = enable any sample rate)");
/* pci ids */ /* pci ids */
@ -302,6 +302,7 @@ DEFINE_VIA_REGSET(CAPTURE_8233, 0x60);
#define VIA_DXS_DISABLE 2 #define VIA_DXS_DISABLE 2
#define VIA_DXS_48K 3 #define VIA_DXS_48K 3
#define VIA_DXS_NO_VRA 4 #define VIA_DXS_NO_VRA 4
#define VIA_DXS_SRC 5
/* /*
@ -380,6 +381,7 @@ struct _snd_via82xx {
struct via_rate_lock rates[2]; /* playback and capture */ struct via_rate_lock rates[2]; /* playback and capture */
unsigned int dxs_fixed: 1; /* DXS channel accepts only 48kHz */ unsigned int dxs_fixed: 1; /* DXS channel accepts only 48kHz */
unsigned int no_vra: 1; /* no need to set VRA on DXS channels */ unsigned int no_vra: 1; /* no need to set VRA on DXS channels */
unsigned int dxs_src: 1; /* use full SRC capabilities of DXS */
unsigned int spdif_on: 1; /* only spdif rates work to external DACs */ unsigned int spdif_on: 1; /* only spdif rates work to external DACs */
snd_pcm_t *pcms[2]; snd_pcm_t *pcms[2];
@ -924,15 +926,16 @@ static int snd_via8233_playback_prepare(snd_pcm_substream_t *substream)
via82xx_t *chip = snd_pcm_substream_chip(substream); via82xx_t *chip = snd_pcm_substream_chip(substream);
viadev_t *viadev = (viadev_t *)substream->runtime->private_data; viadev_t *viadev = (viadev_t *)substream->runtime->private_data;
snd_pcm_runtime_t *runtime = substream->runtime; snd_pcm_runtime_t *runtime = substream->runtime;
int ac97_rate = chip->dxs_src ? 48000 : runtime->rate;
int rate_changed; int rate_changed;
u32 rbits; u32 rbits;
if ((rate_changed = via_lock_rate(&chip->rates[0], runtime->rate)) < 0) if ((rate_changed = via_lock_rate(&chip->rates[0], ac97_rate)) < 0)
return rate_changed; return rate_changed;
if (rate_changed) { if (rate_changed) {
snd_ac97_set_rate(chip->ac97, AC97_PCM_FRONT_DAC_RATE, snd_ac97_set_rate(chip->ac97, AC97_PCM_FRONT_DAC_RATE,
chip->no_vra ? 48000 : runtime->rate); chip->no_vra ? 48000 : runtime->rate);
snd_ac97_set_rate(chip->ac97, AC97_SPDIF, runtime->rate); snd_ac97_set_rate(chip->ac97, AC97_SPDIF, ac97_rate);
} }
if (runtime->rate == 48000) if (runtime->rate == 48000)
rbits = 0xfffff; rbits = 0xfffff;
@ -1074,6 +1077,12 @@ static int snd_via82xx_pcm_open(via82xx_t *chip, viadev_t *viadev, snd_pcm_subst
/* fixed DXS playback rate */ /* fixed DXS playback rate */
runtime->hw.rates = SNDRV_PCM_RATE_48000; runtime->hw.rates = SNDRV_PCM_RATE_48000;
runtime->hw.rate_min = runtime->hw.rate_max = 48000; runtime->hw.rate_min = runtime->hw.rate_max = 48000;
} else if (chip->dxs_src && viadev->reg_offset < 0x40) {
/* use full SRC capabilities of DXS */
runtime->hw.rates = (SNDRV_PCM_RATE_CONTINUOUS |
SNDRV_PCM_RATE_8000_48000);
runtime->hw.rate_min = 8000;
runtime->hw.rate_max = 48000;
} else if (! ratep->rate) { } else if (! ratep->rate) {
int idx = viadev->direction ? AC97_RATES_ADC : AC97_RATES_FRONT_DAC; int idx = viadev->direction ? AC97_RATES_ADC : AC97_RATES_FRONT_DAC;
runtime->hw.rates = chip->ac97->rates[idx]; runtime->hw.rates = chip->ac97->rates[idx];
@ -2149,6 +2158,7 @@ static int __devinit check_dxs_list(struct pci_dev *pci)
{ .vendor = 0x1043, .device = 0x8095, .action = VIA_DXS_NO_VRA }, /* ASUS A7V8X (FIXME: possibly VIA_DXS_ENABLE?)*/ { .vendor = 0x1043, .device = 0x8095, .action = VIA_DXS_NO_VRA }, /* ASUS A7V8X (FIXME: possibly VIA_DXS_ENABLE?)*/
{ .vendor = 0x1043, .device = 0x80a1, .action = VIA_DXS_NO_VRA }, /* ASUS A7V8-X */ { .vendor = 0x1043, .device = 0x80a1, .action = VIA_DXS_NO_VRA }, /* ASUS A7V8-X */
{ .vendor = 0x1043, .device = 0x80b0, .action = VIA_DXS_NO_VRA }, /* ASUS A7V600 & K8V*/ { .vendor = 0x1043, .device = 0x80b0, .action = VIA_DXS_NO_VRA }, /* ASUS A7V600 & K8V*/
{ .vendor = 0x1043, .device = 0x812a, .action = VIA_DXS_SRC }, /* ASUS A8V Deluxe */
{ .vendor = 0x1071, .device = 0x8375, .action = VIA_DXS_NO_VRA }, /* Vobis/Yakumo/Mitac notebook */ { .vendor = 0x1071, .device = 0x8375, .action = VIA_DXS_NO_VRA }, /* Vobis/Yakumo/Mitac notebook */
{ .vendor = 0x10cf, .device = 0x118e, .action = VIA_DXS_ENABLE }, /* FSC laptop */ { .vendor = 0x10cf, .device = 0x118e, .action = VIA_DXS_ENABLE }, /* FSC laptop */
{ .vendor = 0x1106, .device = 0x4161, .action = VIA_DXS_NO_VRA }, /* ASRock K7VT2 */ { .vendor = 0x1106, .device = 0x4161, .action = VIA_DXS_NO_VRA }, /* ASRock K7VT2 */
@ -2288,6 +2298,10 @@ static int __devinit snd_via82xx_probe(struct pci_dev *pci,
chip->dxs_fixed = 1; chip->dxs_fixed = 1;
else if (dxs_support[dev] == VIA_DXS_NO_VRA) else if (dxs_support[dev] == VIA_DXS_NO_VRA)
chip->no_vra = 1; chip->no_vra = 1;
else if (dxs_support[dev] == VIA_DXS_SRC) {
chip->no_vra = 1;
chip->dxs_src = 1;
}
} }
if ((err = snd_via8233_init_misc(chip, dev)) < 0) if ((err = snd_via8233_init_misc(chip, dev)) < 0)
goto __error; goto __error;