diff options
author | mav <mav@FreeBSD.org> | 2010-01-12 16:40:13 +0000 |
---|---|---|
committer | mav <mav@FreeBSD.org> | 2010-01-12 16:40:13 +0000 |
commit | bb7fdc82c19ada0c2f269fd2dbdd79c692a814c0 (patch) | |
tree | f4243e95db157c074710a44027ed8a169ef1a5a5 /sys/dev/sound | |
parent | 04bf24b5af9dd51bdf900c3dfaaf031e28ff6ef7 (diff) | |
download | FreeBSD-src-bb7fdc82c19ada0c2f269fd2dbdd79c692a814c0.zip FreeBSD-src-bb7fdc82c19ada0c2f269fd2dbdd79c692a814c0.tar.gz |
Align buffer size to LCM of 128bytes, required by hardware, and alignment of
current format. This fixes problems with non-power-of-2 number of channels.
Enable 5.1 formats support, as they are working fine now.
Diffstat (limited to 'sys/dev/sound')
-rw-r--r-- | sys/dev/sound/pci/hda/hdac.c | 32 |
1 files changed, 28 insertions, 4 deletions
diff --git a/sys/dev/sound/pci/hda/hdac.c b/sys/dev/sound/pci/hda/hdac.c index fa978d8..ce33728 100644 --- a/sys/dev/sound/pci/hda/hdac.c +++ b/sys/dev/sound/pci/hda/hdac.c @@ -86,7 +86,7 @@ #include "mixer_if.h" -#define HDA_DRV_TEST_REV "20100111_0139" +#define HDA_DRV_TEST_REV "20100112_0140" SND_DECLARE_FILE("$FreeBSD$"); @@ -3543,6 +3543,32 @@ hdac_stream_setup(struct hdac_chan *ch) } } +/* + * Greatest Common Divisor. + */ +static unsigned +gcd(unsigned a, unsigned b) +{ + u_int c; + + while (b != 0) { + c = a; + a = b; + b = (c % b); + } + return (a); +} + +/* + * Least Common Multiple. + */ +static unsigned +lcm(unsigned a, unsigned b) +{ + + return ((a * b) / gcd(a, b)); +} + static int hdac_channel_setfragments(kobj_t obj, void *data, uint32_t blksz, uint32_t blkcnt) @@ -3550,7 +3576,7 @@ hdac_channel_setfragments(kobj_t obj, void *data, struct hdac_chan *ch = data; struct hdac_softc *sc = ch->devinfo->codec->sc; - blksz &= HDA_BLK_ALIGN; + blksz -= blksz % lcm(HDAC_DMA_ALIGNMENT, sndbuf_getalign(ch->b)); if (blksz > (sndbuf_getmaxsize(ch->b) / HDA_BDL_MIN)) blksz = sndbuf_getmaxsize(ch->b) / HDA_BDL_MIN; @@ -6551,14 +6577,12 @@ hdac_pcmchannel_setup(struct hdac_chan *ch) if (ch->bit32) ch->fmtlist[i++] = SND_FORMAT(AFMT_S32_LE, 4, 0); } -#ifdef notyet if (channels == 6 || /* Any 6-channel */ pinset == 0x0017) { /* 7.1 */ ch->fmtlist[i++] = SND_FORMAT(AFMT_S16_LE, 6, 1); if (ch->bit32) ch->fmtlist[i++] = SND_FORMAT(AFMT_S32_LE, 6, 1); } -#endif if (channels == 8) { /* Any 8-channel */ ch->fmtlist[i++] = SND_FORMAT(AFMT_S16_LE, 8, 1); if (ch->bit32) |