Explorar o código

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>
David Henningsson %!s(int64=14) %!d(string=hai) anos
pai
achega
4cb3631084
Modificáronse 2 ficheiros con 24 adicións e 25 borrados
  1. 5 3
      Documentation/sound/alsa/HD-Audio.txt
  2. 19 22
      sound/pci/hda/hda_intel.c

+ 5 - 3
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.
 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
-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.
 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

+ 19 - 22
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_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 "
-		 "(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_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 ||
-	    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))
 		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 {
-		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)
 	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) {