ALSA: HDA: Add position_fix=3 module option, and refactor related code

What was previously known as via_dmapos_patch, and hard-coded to be
used for VIA and ATI controllers, is now configurable through a module
option. The background is that some VIA controllers seem to prefer
via_dmapos_patch to be turned off.

Signed-off-by: David Henningsson <david.henningsson@canonical.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
David Henningsson
2010-09-30 10:12:50 +02:00
committed by Takashi Iwai
parent c123e5e437
commit 4cb3631084
2 changed files with 24 additions and 25 deletions

View File

@@ -57,9 +57,11 @@ dead. However, this detection isn't perfect on some devices. In such
a case, you can change the default method via `position_fix` option. a case, you can change the default method via `position_fix` option.
`position_fix=1` means to use LPIB method explicitly. `position_fix=1` means to use LPIB method explicitly.
`position_fix=2` means to use the position-buffer. 0 is the default `position_fix=2` means to use the position-buffer.
value, the automatic check and fallback to LPIB as described in the `position_fix=3` means to use a combination of both methods, needed
above. If you get a problem of repeated sounds, this option might for some VIA and ATI controllers. 0 is the default value for all other
controllers, the automatic check and fallback to LPIB as described in
the above. If you get a problem of repeated sounds, this option might
help. help.
In addition to that, every controller is known to be broken regarding In addition to that, every controller is known to be broken regarding

View File

@@ -78,8 +78,8 @@ MODULE_PARM_DESC(enable, "Enable Intel HD audio interface.");
module_param_array(model, charp, NULL, 0444); module_param_array(model, charp, NULL, 0444);
MODULE_PARM_DESC(model, "Use the given board model."); MODULE_PARM_DESC(model, "Use the given board model.");
module_param_array(position_fix, int, NULL, 0444); module_param_array(position_fix, int, NULL, 0444);
MODULE_PARM_DESC(position_fix, "Fix DMA pointer " MODULE_PARM_DESC(position_fix, "DMA pointer read method."
"(0 = auto, 1 = none, 2 = POSBUF)."); "(0 = auto, 1 = LPIB, 2 = POSBUF, 3 = VIACOMBO).");
module_param_array(bdl_pos_adj, int, NULL, 0644); module_param_array(bdl_pos_adj, int, NULL, 0644);
MODULE_PARM_DESC(bdl_pos_adj, "BDL position adjustment offset."); MODULE_PARM_DESC(bdl_pos_adj, "BDL position adjustment offset.");
module_param_array(probe_mask, int, NULL, 0444); module_param_array(probe_mask, int, NULL, 0444);
@@ -305,6 +305,7 @@ enum {
POS_FIX_AUTO, POS_FIX_AUTO,
POS_FIX_LPIB, POS_FIX_LPIB,
POS_FIX_POSBUF, POS_FIX_POSBUF,
POS_FIX_VIACOMBO,
}; };
/* Defines for ATI HD Audio support in SB450 south bridge */ /* Defines for ATI HD Audio support in SB450 south bridge */
@@ -433,7 +434,6 @@ struct azx {
unsigned int polling_mode :1; unsigned int polling_mode :1;
unsigned int msi :1; unsigned int msi :1;
unsigned int irq_pending_warned :1; unsigned int irq_pending_warned :1;
unsigned int via_dmapos_patch :1; /* enable DMA-position fix for VIA */
unsigned int probing :1; /* codec probing phase */ unsigned int probing :1; /* codec probing phase */
/* for debugging */ /* for debugging */
@@ -1309,11 +1309,8 @@ static int azx_setup_controller(struct azx *chip, struct azx_dev *azx_dev)
azx_sd_writel(azx_dev, SD_BDLPU, upper_32_bits(azx_dev->bdl.addr)); azx_sd_writel(azx_dev, SD_BDLPU, upper_32_bits(azx_dev->bdl.addr));
/* enable the position buffer */ /* enable the position buffer */
if (chip->position_fix[0] == POS_FIX_POSBUF || if (chip->position_fix[0] != POS_FIX_LPIB ||
chip->position_fix[0] == POS_FIX_AUTO || chip->position_fix[1] != POS_FIX_LPIB) {
chip->position_fix[1] == POS_FIX_POSBUF ||
chip->position_fix[1] == POS_FIX_AUTO ||
chip->via_dmapos_patch) {
if (!(azx_readl(chip, DPLBASE) & ICH6_DPLBASE_ENABLE)) if (!(azx_readl(chip, DPLBASE) & ICH6_DPLBASE_ENABLE))
azx_writel(chip, DPLBASE, azx_writel(chip, DPLBASE,
(u32)chip->posbuf.addr | ICH6_DPLBASE_ENABLE); (u32)chip->posbuf.addr | ICH6_DPLBASE_ENABLE);
@@ -1852,20 +1849,21 @@ static unsigned int azx_get_position(struct azx *chip,
struct azx_dev *azx_dev) struct azx_dev *azx_dev)
{ {
unsigned int pos; unsigned int pos;
int stream = azx_dev->substream->stream;
if (chip->via_dmapos_patch) switch (chip->position_fix[stream]) {
case POS_FIX_LPIB:
/* read LPIB */
pos = azx_sd_readl(azx_dev, SD_LPIB);
break;
case POS_FIX_VIACOMBO:
pos = azx_via_get_position(chip, azx_dev); pos = azx_via_get_position(chip, azx_dev);
else { break;
int stream = azx_dev->substream->stream; default:
if (chip->position_fix[stream] == POS_FIX_POSBUF || /* use the position buffer */
chip->position_fix[stream] == POS_FIX_AUTO) { pos = le32_to_cpu(*azx_dev->posbuf);
/* use the position buffer */
pos = le32_to_cpu(*azx_dev->posbuf);
} else {
/* read LPIB */
pos = azx_sd_readl(azx_dev, SD_LPIB);
}
} }
if (pos >= azx_dev->bufsize) if (pos >= azx_dev->bufsize)
pos = 0; pos = 0;
return pos; return pos;
@@ -2313,6 +2311,7 @@ static int __devinit check_position_fix(struct azx *chip, int fix)
switch (fix) { switch (fix) {
case POS_FIX_LPIB: case POS_FIX_LPIB:
case POS_FIX_POSBUF: case POS_FIX_POSBUF:
case POS_FIX_VIACOMBO:
return fix; return fix;
} }
@@ -2320,11 +2319,9 @@ static int __devinit check_position_fix(struct azx *chip, int fix)
switch (chip->driver_type) { switch (chip->driver_type) {
case AZX_DRIVER_VIA: case AZX_DRIVER_VIA:
case AZX_DRIVER_ATI: case AZX_DRIVER_ATI:
chip->via_dmapos_patch = 1;
/* Use link position directly, avoid any transfer problem. */ /* Use link position directly, avoid any transfer problem. */
return POS_FIX_LPIB; return POS_FIX_VIACOMBO;
} }
chip->via_dmapos_patch = 0;
q = snd_pci_quirk_lookup(chip->pci, position_fix_list); q = snd_pci_quirk_lookup(chip->pci, position_fix_list);
if (q) { if (q) {