From 4cb36310848fd17766aa72afd1f2873f54b4e055 Mon Sep 17 00:00:00 2001 From: David Henningsson Date: Thu, 30 Sep 2010 10:12:50 +0200 Subject: 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 Signed-off-by: Takashi Iwai --- Documentation/sound/alsa/HD-Audio.txt | 8 ++++--- sound/pci/hda/hda_intel.c | 41 ++++++++++++++++------------------- 2 files changed, 24 insertions(+), 25 deletions(-) diff --git a/Documentation/sound/alsa/HD-Audio.txt b/Documentation/sound/alsa/HD-Audio.txt index 278cc21..c82beb0 100644 --- a/Documentation/sound/alsa/HD-Audio.txt +++ b/Documentation/sound/alsa/HD-Audio.txt @@ -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. `position_fix=1` means to use LPIB method explicitly. -`position_fix=2` means to use the position-buffer. 0 is the default -value, the automatic check and fallback to LPIB as described in the -above. If you get a problem of repeated sounds, this option might +`position_fix=2` means to use the position-buffer. +`position_fix=3` means to use a combination of both methods, needed +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. In addition to that, every controller is known to be broken regarding diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index ec07e47..38b063e 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -78,8 +78,8 @@ MODULE_PARM_DESC(enable, "Enable Intel HD audio interface."); module_param_array(model, charp, NULL, 0444); MODULE_PARM_DESC(model, "Use the given board model."); module_param_array(position_fix, int, NULL, 0444); -MODULE_PARM_DESC(position_fix, "Fix DMA pointer " - "(0 = auto, 1 = none, 2 = POSBUF)."); +MODULE_PARM_DESC(position_fix, "DMA pointer read method." + "(0 = auto, 1 = LPIB, 2 = POSBUF, 3 = VIACOMBO)."); module_param_array(bdl_pos_adj, int, NULL, 0644); MODULE_PARM_DESC(bdl_pos_adj, "BDL position adjustment offset."); module_param_array(probe_mask, int, NULL, 0444); @@ -305,6 +305,7 @@ enum { POS_FIX_AUTO, POS_FIX_LPIB, POS_FIX_POSBUF, + POS_FIX_VIACOMBO, }; /* Defines for ATI HD Audio support in SB450 south bridge */ @@ -433,7 +434,6 @@ struct azx { unsigned int polling_mode :1; unsigned int msi :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 */ /* 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)); /* enable the position buffer */ - if (chip->position_fix[0] == POS_FIX_POSBUF || - chip->position_fix[0] == POS_FIX_AUTO || - chip->position_fix[1] == POS_FIX_POSBUF || - chip->position_fix[1] == POS_FIX_AUTO || - chip->via_dmapos_patch) { + if (chip->position_fix[0] != POS_FIX_LPIB || + chip->position_fix[1] != POS_FIX_LPIB) { if (!(azx_readl(chip, DPLBASE) & ICH6_DPLBASE_ENABLE)) azx_writel(chip, DPLBASE, (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) { 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); - else { - int stream = azx_dev->substream->stream; - if (chip->position_fix[stream] == POS_FIX_POSBUF || - chip->position_fix[stream] == POS_FIX_AUTO) { - /* use the position buffer */ - pos = le32_to_cpu(*azx_dev->posbuf); - } else { - /* read LPIB */ - pos = azx_sd_readl(azx_dev, SD_LPIB); - } + break; + default: + /* use the position buffer */ + pos = le32_to_cpu(*azx_dev->posbuf); } + if (pos >= azx_dev->bufsize) pos = 0; return pos; @@ -2313,6 +2311,7 @@ static int __devinit check_position_fix(struct azx *chip, int fix) switch (fix) { case POS_FIX_LPIB: case POS_FIX_POSBUF: + case POS_FIX_VIACOMBO: return fix; } @@ -2320,11 +2319,9 @@ static int __devinit check_position_fix(struct azx *chip, int fix) switch (chip->driver_type) { case AZX_DRIVER_VIA: case AZX_DRIVER_ATI: - chip->via_dmapos_patch = 1; /* 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); if (q) { -- cgit v1.1