Problem with snd_ich.ko
Don Lewis
truckman at FreeBSD.org
Sun Sep 12 18:30:28 PDT 2004
On 12 Sep, Derrick Edwards wrote:
> On Friday 10 September 2004 10:24 am, Lutz Bichler wrote:
>
> Did you ever get an answer to yoru problem? I kinda was having the same
> problem. When booting up, I would be able to get sound wihen I play songs
> from the console. When I booted into kde 3.3 during the splash sreen I would
> lose the sound. If I want to have sound during the kde session I have to wait
> until kde is up and running then load snd_ich. If I log out of that current
> session I have to reboot and start the process all over..
> Derrick
>
>> Hi,
>>
>> i have a "funny" problem with snd_ich on 5.3 Beta3. Whenever i boot my
>> machine, sound.ko and snd_ich.ko are loaded, but i do not get any sound
>> working. After unloading and reloading snd_ich.ko things work fine. Any
>> idea abou what going wrong at boot-time loading of the modules?
You might want to try this patch:
Index: sys/dev/sound/pcm/channel.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/sound/pcm/channel.c,v
retrieving revision 1.97
diff -u -r1.97 channel.c
--- sys/dev/sound/pcm/channel.c 28 Feb 2004 19:47:02 -0000 1.97
+++ sys/dev/sound/pcm/channel.c 9 Sep 2004 20:41:18 -0000
@@ -405,9 +405,9 @@
if ((c->flags & CHN_F_MAPPED) || !(c->flags & CHN_F_TRIGGERED))
return;
- chn_trigger(c, PCMTRIG_EMLDMARD);
chn_dmaupdate(c);
ret = chn_rdfeed(c);
+ chn_trigger(c, PCMTRIG_EMLDMARD);
if (ret)
printf("chn_rdfeed: %d\n", ret);
@@ -417,15 +417,21 @@
static void
chn_rdintr(struct pcm_channel *c)
{
- int ret;
CHN_LOCKASSERT(c);
/* tell the driver to update the primary buffer if non-dma */
- chn_trigger(c, PCMTRIG_EMLDMARD);
/* update pointers in primary buffer */
chn_dmaupdate(c);
/* ...and feed from primary to secondary */
- ret = chn_rdfeed(c);
+ chn_rdfeed(c);
+ chn_trigger(c, PCMTRIG_EMLDMARD);
+}
+
+int
+chn_hwunownedbufoffset(struct pcm_channel *c)
+{
+ return ((c->direction == PCMDIR_PLAY) ? sndbuf_getfreeptr(c->bufhard) :
+ sndbuf_getreadyptr(c->bufhard));
}
/*
Index: sys/dev/sound/pcm/channel.h
===================================================================
RCS file: /home/ncvs/src/sys/dev/sound/pcm/channel.h,v
retrieving revision 1.30
diff -u -r1.30 channel.h
--- sys/dev/sound/pcm/channel.h 28 Feb 2004 19:47:02 -0000 1.30
+++ sys/dev/sound/pcm/channel.h 9 Sep 2004 20:36:34 -0000
@@ -93,6 +93,7 @@
void chn_intr(struct pcm_channel *c);
int chn_wrfeed(struct pcm_channel *c);
int chn_rdfeed(struct pcm_channel *c);
+int chn_hwunownedbufoffset(struct pcm_channel *c);
int chn_abort(struct pcm_channel *c);
void chn_wrupdate(struct pcm_channel *c);
Index: sys/dev/sound/pci/ich.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/sound/pci/ich.c,v
retrieving revision 1.42
diff -u -r1.42 ich.c
--- sys/dev/sound/pci/ich.c 16 Jul 2004 03:59:27 -0000 1.42
+++ sys/dev/sound/pci/ich.c 9 Sep 2004 20:36:10 -0000
@@ -336,11 +336,33 @@
{
struct sc_chinfo *ch = data;
struct sc_info *sc = ch->parent;
+ u_int32_t lbb, lbi, lvi, nlbi;
switch (go) {
case PCMTRIG_START:
ch->run = 1;
ich_wr(sc, ch->regbase + ICH_REG_X_BDBAR, (u_int32_t)(ch->desc_addr), 4);
+ lvi = ((chn_hwunownedbufoffset(ch->channel) +
+ ch->blkcnt * ch->blksz - 1) / ch->blksz) % ch->blkcnt;
+ ich_wr(sc, ch->regbase + ICH_REG_X_LVI, lvi, 1);
+ ich_wr(sc, ch->regbase + ICH_REG_X_CR, ICH_X_CR_RPBM | ICH_X_CR_LVBIE | ICH_X_CR_IOCE, 1);
+ break;
+
+ case PCMTRIG_EMLDMAWR:
+ case PCMTRIG_EMLDMARD:
+ lvi = ich_rd(sc, ch->regbase + ICH_REG_X_LVI, 1);
+ lbi = lvi % ch->blkcnt;
+ lbb = lvi / ch->blkcnt;
+ nlbi = ((chn_hwunownedbufoffset(ch->channel) +
+ ch->blkcnt * ch->blksz - 1) / ch->blksz) % ch->blkcnt;
+ nlbi = (chn_hwunownedbufoffset(ch->channel) / ch->blksz +
+ ch->blkcnt - 1) % ch->blkcnt;
+ if (nlbi < lbi)
+ lbb = (lbb + 1) % (ICH_DTBL_LENGTH / ch->blkcnt);
+ lvi = lbb * ch->blkcnt + nlbi;
+ ich_wr(sc, ch->regbase + ICH_REG_X_LVI, lvi, 1);
+ /* restart channel in case DMA underflowed and shut down */
+ /* XXX - track restarts? */
ich_wr(sc, ch->regbase + ICH_REG_X_CR, ICH_X_CR_RPBM | ICH_X_CR_LVBIE | ICH_X_CR_IOCE, 1);
break;
@@ -394,7 +416,7 @@
{
struct sc_info *sc = (struct sc_info *)p;
struct sc_chinfo *ch;
- u_int32_t cbi, lbi, lvi, st, gs;
+ u_int32_t st, gs;
int i;
gs = ich_rd(sc, ICH_REG_GLOB_STA, 4) & ICH_GLOB_STA_IMASK;
@@ -417,20 +439,6 @@
/* block complete - update buffer */
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);
-
}
/* clear status bit */
ich_wr(sc, ch->regbase +
More information about the freebsd-current
mailing list