Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c74db86b authored by Takashi Iwai's avatar Takashi Iwai Committed by Jaroslav Kysela
Browse files

[ALSA] Add position_fix module option



Documentation,HDA Intel driver
Added position_fix module option to HDA-intel driver for fixing up
the DMA position (possibly hardware-) bugs.

Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent 091bf4dc
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -618,6 +618,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
    Module for Intel HD Audio (ICH6, ICH6M, ICH7)

    model	- force the model name
    position_fix - Fix DMA pointer (0 = FIFO size, 1 = none, 2 = POSBUF)

    Module supports up to 8 cards.

@@ -643,6 +644,14 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
	  full_dig	6-jack in back, 2-jack in front, SPDIF I/O
	  allout	5-jack in back, 2-jack in front, SPDIF out

    Note 2: If you get click noises on output, try the module option
	    position_fix=1 or 2.  position_fix=1 will use the SD_LPIB
	    register value without FIFO size correction as the current
	    DMA pointer.  position_fix=2 will make the driver to use
	    the position buffer instead of reading SD_LPIB register.
	    (Usually SD_LPLIB register is more accurate than the
	    position buffer.)

  Module snd-hdsp
  ---------------

+48 −37
Original line number Diff line number Diff line
@@ -51,6 +51,7 @@ static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
static char *model[SNDRV_CARDS];
static int position_fix[SNDRV_CARDS];

module_param_array(index, int, NULL, 0444);
MODULE_PARM_DESC(index, "Index value for Intel HD audio interface.");
@@ -60,6 +61,8 @@ module_param_array(enable, bool, NULL, 0444);
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, bool, NULL, 0444);
MODULE_PARM_DESC(position_fix, "Fix DMA pointer (0 = FIFO size, 1 = none, 2 = POSBUF).");

MODULE_LICENSE("GPL");
MODULE_SUPPORTED_DEVICE("{{Intel, ICH6},"
@@ -183,6 +186,12 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 };
#define ICH6_MAX_CORB_ENTRIES	256
#define ICH6_MAX_RIRB_ENTRIES	256

/* position fix mode */
enum {
	POS_FIX_FIFO,
	POS_FIX_NONE,
	POS_FIX_POSBUF
};

/*
 * Use CORB/RIRB for communication from/to codecs.
@@ -190,12 +199,6 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 };
 */
#define USE_CORB_RIRB

/*
 * Define this if use the position buffer instead of reading SD_LPIB
 * It's not used as default since SD_LPIB seems to give more accurate position
 */
/* #define USE_POSBUF */

/*
 */

@@ -271,6 +274,9 @@ struct snd_azx {
	struct snd_dma_buffer bdl;
	struct snd_dma_buffer rb;
	struct snd_dma_buffer posbuf;

	/* flags */
	int position_fix;
};

/*
@@ -657,11 +663,11 @@ static void azx_init_chip(azx_t *chip)
	/* initialize the codec command I/O */
	azx_init_cmd_io(chip);

#ifdef USE_POSBUF
	if (chip->position_fix == POS_FIX_POSBUF) {
		/* program the position buffer */
		azx_writel(chip, DPLBASE, (u32)chip->posbuf.addr);
		azx_writel(chip, DPUBASE, upper_32bit(chip->posbuf.addr));
#endif
	}
}


@@ -791,11 +797,12 @@ static int azx_setup_controller(azx_t *chip, azx_dev_t *azx_dev)
	/* upper BDL address */
	azx_sd_writel(azx_dev, SD_BDLPU, upper_32bit(azx_dev->bdl_addr));

#ifdef USE_POSBUF
	if (chip->position_fix == POS_FIX_POSBUF) {
		/* enable the position buffer */
		if (! (azx_readl(chip, DPLBASE) & ICH6_DPLBASE_ENABLE))
			azx_writel(chip, DPLBASE, (u32)chip->posbuf.addr | ICH6_DPLBASE_ENABLE);
#endif
	}

	/* set the interrupt enable bits in the descriptor control register */
	azx_sd_writel(azx_dev, SD_CTL, azx_sd_readl(azx_dev, SD_CTL) | SD_INT_MASK);

@@ -1036,16 +1043,20 @@ static int azx_pcm_trigger(snd_pcm_substream_t *substream, int cmd)

static snd_pcm_uframes_t azx_pcm_pointer(snd_pcm_substream_t *substream)
{
	struct azx_pcm *apcm = snd_pcm_substream_chip(substream);
	azx_t *chip = apcm->chip;
	azx_dev_t *azx_dev = get_azx_dev(substream);
	unsigned int pos;

#ifdef USE_POSBUF
	if (chip->position_fix == POS_FIX_POSBUF) {
		/* use the position buffer */
		pos = *azx_dev->posbuf;
#else
	} else {
		/* read LPIB */
	pos = azx_sd_readl(azx_dev, SD_LPIB) + azx_dev->fifo_size;
#endif
		pos = azx_sd_readl(azx_dev, SD_LPIB);
		if (chip->position_fix == POS_FIX_FIFO)
			pos += azx_dev->fifo_size;
	}
	if (pos >= azx_dev->bufsize)
		pos = 0;
	return bytes_to_frames(substream->runtime, pos);
@@ -1155,9 +1166,8 @@ static int __devinit azx_init_stream(azx_t *chip)
		azx_dev_t *azx_dev = &chip->azx_dev[i];
		azx_dev->bdl = (u32 *)(chip->bdl.area + off);
		azx_dev->bdl_addr = chip->bdl.addr + off;
#ifdef USE_POSBUF
		if (chip->position_fix == POS_FIX_POSBUF)
			azx_dev->posbuf = (volatile u32 *)(chip->posbuf.area + i * 8);
#endif
		/* offset: SDI0=0x80, SDI1=0xa0, ... SDO3=0x160 */
		azx_dev->sd_addr = chip->remap_addr + (0x20 * i + 0x80);
		/* int mask: SDI0=0x01, SDI1=0x02, ... SDO3=0x80 */
@@ -1237,10 +1247,8 @@ static int azx_free(azx_t *chip)
		snd_dma_free_pages(&chip->bdl);
	if (chip->rb.area)
		snd_dma_free_pages(&chip->rb);
#ifdef USE_POSBUF
	if (chip->posbuf.area)
		snd_dma_free_pages(&chip->posbuf);
#endif
	pci_release_regions(chip->pci);
	pci_disable_device(chip->pci);
	kfree(chip);
@@ -1256,7 +1264,8 @@ static int azx_dev_free(snd_device_t *device)
/*
 * constructor
 */
static int __devinit azx_create(snd_card_t *card, struct pci_dev *pci, azx_t **rchip)
static int __devinit azx_create(snd_card_t *card, struct pci_dev *pci,
				int posfix, azx_t **rchip)
{
	azx_t *chip;
	int err = 0;
@@ -1283,6 +1292,8 @@ static int __devinit azx_create(snd_card_t *card, struct pci_dev *pci, azx_t **r
	chip->pci = pci;
	chip->irq = -1;

	chip->position_fix = posfix;

	if ((err = pci_request_regions(pci, "ICH HD audio")) < 0) {
		kfree(chip);
		pci_disable_device(pci);
@@ -1314,14 +1325,14 @@ static int __devinit azx_create(snd_card_t *card, struct pci_dev *pci, azx_t **r
		snd_printk(KERN_ERR SFX "cannot allocate BDL\n");
		goto errout;
	}
#ifdef USE_POSBUF
	if (chip->position_fix == POS_FIX_POSBUF) {
		/* allocate memory for the position buffer */
		if ((err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(chip->pci),
					       MAX_ICH6_DEV * 8, &chip->posbuf)) < 0) {
			snd_printk(KERN_ERR SFX "cannot allocate posbuf\n");
			goto errout;
		}
#endif
	}
	/* allocate CORB/RIRB */
	if ((err = azx_alloc_cmd_io(chip)) < 0)
		goto errout;
@@ -1372,7 +1383,7 @@ static int __devinit azx_probe(struct pci_dev *pci, const struct pci_device_id *
		return -ENOMEM;
	}

	if ((err = azx_create(card, pci, &chip)) < 0) {
	if ((err = azx_create(card, pci, position_fix[dev], &chip)) < 0) {
		snd_card_free(card);
		return err;
	}