Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 24 Aug 2001 02:43:18 +0900
From:      Katsurajima Naoto <raven@katsurajima.seya.yokohama.jp>
To:        FreeBSD-multimedia@FreeBSD.ORG
Cc:        freebsd-users-jp@jp.FreeBSD.ORG
Subject:   4.4-RC ich sound driver bug fix
Message-ID:  <20010824024318.13add558.raven@katsurajima.seya.yokohama.jp>

next in thread | raw e-mail | index | archive | help
Hellow.

I fixed sound driver for Intel ICH AC'97. Changed points are

- FIFO buffer control method is now been strict. By this change, CPU
  and DMA are never conflict on same buffer block. Many troubles
  are occured by this conflict.

- Not use ICH's PICB(Position In Current Buffer) function for getting
  hardware pointer. This function seems to be buggy, and not only
  untrused on the value, but also getting trouble. On the other hand,
  this driver cannot check playing position under block size. But many
  case, this is not so big problem.

- and few little fixes

I checked this driver with xmms, xine, rollemup and timidity++. Under
first 3 programs, there is no problem and very stable on my notebook
PC(Toshiba DynaBookSS3440). But timidity++ plays with crick noise.(I
have not checked yet why)

It may be better to reboot by power off/on than by reboot command, after
attemp patch and rebuild kernel. It is because of clearing illeagal
condition caused by old driver.

This patch is tested only on 4.4-RC. But may work on -CURRENT.

Please check it.
-- 
Katsurajima "Raven" Naoto($B7KEg(B $BD>?M(B)
Family Emblem: Circle and Left 3 Clove-TOMOE($B4]$K:8;0$DCz;RGC(B)
e-mail: raven@katsurajima.seya.yokohama.jp

--- cut here
*** sys/dev/sound/pci/ich.c.orig	Wed Aug  1 14:37:30 2001
--- sys/dev/sound/pci/ich.c	Thu Aug 23 10:32:55 2001
***************
*** 53,58 ****
--- 53,59 ----
  	u_int32_t num, run;
  	u_int32_t blksz, blkcnt;
  	u_int32_t regbase, spdreg;
+ 	u_int32_t civ;
  
  	struct snd_dbuf *buffer;
  	struct pcm_channel *channel;
***************
*** 296,302 ****
  
  	ch->blksz = blocksize;
  	ich_filldtbl(ch);
! 	ich_wr(sc, ch->regbase + ICH_REG_X_LVI, ICH_DTBL_LENGTH - 1, 1);
  
  	return ch->blksz;
  }
--- 297,303 ----
  
  	ch->blksz = blocksize;
  	ich_filldtbl(ch);
! 	ich_wr(sc, ch->regbase + ICH_REG_X_LVI, ch->blkcnt - 1, 1);
  
  	return ch->blksz;
  }
***************
*** 306,311 ****
--- 307,313 ----
  {
  	struct sc_chinfo *ch = data;
  	struct sc_info *sc = ch->parent;
+ 	u_int32_t st;
  
  	switch (go) {
  	case PCMTRIG_START:
***************
*** 314,319 ****
--- 316,327 ----
  		ich_wr(sc, ch->regbase + ICH_REG_X_CR, ICH_X_CR_RPBM | ICH_X_CR_LVBIE | ICH_X_CR_IOCE | ICH_X_CR_FEIE, 1);
  		break;
  
+ 	case PCMTRIG_STOP:
+ 		ch->run = 0;
+ 		st = ich_rd(sc, ch->regbase + ICH_REG_X_CR, 1);
+ 		ich_wr(sc, ch->regbase + ICH_REG_X_CR, st & ~ICH_X_CR_RPBM, 1);
+ 		break;
+ 
  	case PCMTRIG_ABORT:
  		ich_resetchan(sc, ch->num);
  		ch->run = 0;
***************
*** 327,344 ****
  {
  	struct sc_chinfo *ch = data;
  	struct sc_info *sc = ch->parent;
! 	u_int32_t ci, ofs, pos;
  
- 	ofs = 0;
  	ci = 1234;
! 	while (ci != ich_rd(sc, ch->regbase + ICH_REG_X_CIV, 1)) {
  		ci = ich_rd(sc, ch->regbase + ICH_REG_X_CIV, 1);
- 		ofs = ich_rd(sc, ch->regbase + ICH_REG_X_PICB, 2) * 2;
- 	}
  
! 	ofs = ch->blksz - ofs;
  	ci %= ch->blkcnt;
! 	pos = (ch->blksz * ci) + ofs;
  
  	return pos;
  }
--- 335,349 ----
  {
  	struct sc_chinfo *ch = data;
  	struct sc_info *sc = ch->parent;
! 	u_int32_t ci, pos;
  
  	ci = 1234;
! 	while (ci != ich_rd(sc, ch->regbase + ICH_REG_X_CIV, 1))
  		ci = ich_rd(sc, ch->regbase + ICH_REG_X_CIV, 1);
  
! 	ch->civ = ci;
  	ci %= ch->blkcnt;
! 	pos = ch->blksz * ci;
  
  	return pos;
  }
***************
*** 371,377 ****
  {
  	struct sc_info *sc = (struct sc_info *)p;
  	struct sc_chinfo *ch;
! 	u_int32_t st, lvi;
  	int i;
  
  	for (i = 0; i < 3; i++) {
--- 376,382 ----
  {
  	struct sc_info *sc = (struct sc_info *)p;
  	struct sc_chinfo *ch;
! 	u_int32_t st, lvi, cbi, lbi;
  	int i;
  
  	for (i = 0; i < 3; i++) {
***************
*** 385,391 ****
  				if (ch->run)
  					chn_intr(ch->channel);
  				lvi = ich_rd(sc, ch->regbase + ICH_REG_X_LVI, 1);
! 				lvi++;
  				lvi %= ICH_DTBL_LENGTH;
  				ich_wr(sc, ch->regbase + ICH_REG_X_LVI, lvi, 1);
  			}
--- 390,405 ----
  				if (ch->run)
  					chn_intr(ch->channel);
  				lvi = ich_rd(sc, ch->regbase + ICH_REG_X_LVI, 1);
! 				cbi = ch->civ % ch->blkcnt;
! 				if (cbi == 0)
! 					cbi = ch->blkcnt - 1;
! 				else
! 					cbi--;
! 				lbi = lvi % ch->blkcnt;
! 				if (cbi >= lbi)
! 					lvi += cbi - lbi;
! 				else
! 					lvi += cbi + ch->blkcnt - lbi;
  				lvi %= ICH_DTBL_LENGTH;
  				ich_wr(sc, ch->regbase + ICH_REG_X_LVI, lvi, 1);
  			}
***************
*** 419,425 ****
  
  	ich_wr(sc, ICH_REG_GLOB_CNT, ICH_GLOB_CTL_COLD | ICH_GLOB_CTL_PRES, 4);
  
! 	if (ich_resetchan(sc, 0) || ich_resetchan(sc, 0))
  		return ENXIO;
  
  	if (bus_dmamem_alloc(sc->dmat, (void **)&sc->dtbl, BUS_DMA_NOWAIT, &sc->dtmap))
--- 433,439 ----
  
  	ich_wr(sc, ICH_REG_GLOB_CNT, ICH_GLOB_CTL_COLD | ICH_GLOB_CTL_PRES, 4);
  
! 	if (ich_resetchan(sc, 0) || ich_resetchan(sc, 1))
  		return ENXIO;
  
  	if (bus_dmamem_alloc(sc->dmat, (void **)&sc->dtbl, BUS_DMA_NOWAIT, &sc->dtmap))
***************
*** 475,481 ****
  	sc->dev = dev;
  
  	data = pci_read_config(dev, PCIR_COMMAND, 2);
! 	data |= (PCIM_CMD_PORTEN | PCIM_CMD_MEMEN | PCIM_CMD_BUSMASTEREN);
  	pci_write_config(dev, PCIR_COMMAND, data, 2);
  	data = pci_read_config(dev, PCIR_COMMAND, 2);
  
--- 489,495 ----
  	sc->dev = dev;
  
  	data = pci_read_config(dev, PCIR_COMMAND, 2);
! 	data |= (PCIM_CMD_PORTEN | PCIM_CMD_BUSMASTEREN);
  	pci_write_config(dev, PCIR_COMMAND, data, 2);
  	data = pci_read_config(dev, PCIR_COMMAND, 2);
  
***************
*** 494,500 ****
  	sc->nabmbart = rman_get_bustag(sc->nabmbar);
  	sc->nabmbarh = rman_get_bushandle(sc->nabmbar);
  
! 	if (bus_dma_tag_create(NULL, 4, 0, BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR,
  			       NULL, NULL, ICH_DEFAULT_BUFSZ, 1, 0x3ffff, 0, &sc->dmat) != 0) {
  		device_printf(dev, "unable to create dma tag\n");
  		goto bad;
--- 508,514 ----
  	sc->nabmbart = rman_get_bustag(sc->nabmbar);
  	sc->nabmbarh = rman_get_bushandle(sc->nabmbar);
  
! 	if (bus_dma_tag_create(NULL, 8, 0, BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR,
  			       NULL, NULL, ICH_DEFAULT_BUFSZ, 1, 0x3ffff, 0, &sc->dmat) != 0) {
  		device_printf(dev, "unable to create dma tag\n");
  		goto bad;

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-multimedia" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20010824024318.13add558.raven>