[stage: 8/9]
Implement CHANNEL_SETFRAGMENTS() for snd_atiixp, snd_es137x, snd_hda and snd_via8233. CHANNEL_SETBLOCKSIZE() will basically call CHANNEL_SETFRAGMENTS() internally using conservative blocksize / blockcount hints. Other drivers will be converted later.
This commit is contained in:
parent
7d9022b422
commit
1042342ad8
@ -65,11 +65,14 @@
|
||||
|
||||
SND_DECLARE_FILE("$FreeBSD$");
|
||||
|
||||
#define ATI_IXP_DMA_RETRY_MAX 100
|
||||
#define ATI_IXP_DMA_RETRY_MAX 100
|
||||
|
||||
#define ATI_IXP_BUFSZ_MIN 4096
|
||||
#define ATI_IXP_BUFSZ_MAX 65536
|
||||
#define ATI_IXP_BUFSZ_DEFAULT 16384
|
||||
#define ATI_IXP_BUFSZ_MIN 4096
|
||||
#define ATI_IXP_BUFSZ_MAX 65536
|
||||
#define ATI_IXP_BUFSZ_DEFAULT 16384
|
||||
|
||||
#define ATI_IXP_BLK_MIN 32
|
||||
#define ATI_IXP_BLK_ALIGN (~(ATI_IXP_BLK_MIN - 1))
|
||||
|
||||
struct atiixp_dma_op {
|
||||
volatile uint32_t addr;
|
||||
@ -180,6 +183,7 @@ static void *atiixp_chan_init(kobj_t, void *, struct snd_dbuf *,
|
||||
struct pcm_channel *, int);
|
||||
static int atiixp_chan_setformat(kobj_t, void *, uint32_t);
|
||||
static int atiixp_chan_setspeed(kobj_t, void *, uint32_t);
|
||||
static int atiixp_chan_setfragments(kobj_t, void *, uint32_t, uint32_t);
|
||||
static int atiixp_chan_setblocksize(kobj_t, void *, uint32_t);
|
||||
static void atiixp_buildsgdt(struct atiixp_chinfo *);
|
||||
static int atiixp_chan_trigger(kobj_t, void *, int);
|
||||
@ -460,8 +464,8 @@ atiixp_chan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b,
|
||||
|
||||
atiixp_lock(sc);
|
||||
num = sc->registered_channels++;
|
||||
ch->sgd_table = &sc->sgd_table[num * ch->blkcnt];
|
||||
ch->sgd_addr = sc->sgd_addr + (num * ch->blkcnt *
|
||||
ch->sgd_table = &sc->sgd_table[num * ATI_IXP_DMA_CHSEGS_MAX];
|
||||
ch->sgd_addr = sc->sgd_addr + (num * ATI_IXP_DMA_CHSEGS_MAX *
|
||||
sizeof(struct atiixp_dma_op));
|
||||
atiixp_disable_dma(ch);
|
||||
atiixp_unlock(sc);
|
||||
@ -513,22 +517,52 @@ atiixp_chan_setspeed(kobj_t obj, void *data, uint32_t spd)
|
||||
return (ATI_IXP_BASE_RATE);
|
||||
}
|
||||
|
||||
static int
|
||||
atiixp_chan_setfragments(kobj_t obj, void *data,
|
||||
uint32_t blksz, uint32_t blkcnt)
|
||||
{
|
||||
struct atiixp_chinfo *ch = data;
|
||||
struct atiixp_info *sc = ch->parent;
|
||||
|
||||
blksz &= ATI_IXP_BLK_ALIGN;
|
||||
|
||||
if (blksz > (sndbuf_getmaxsize(ch->buffer) / ATI_IXP_DMA_CHSEGS_MIN))
|
||||
blksz = sndbuf_getmaxsize(ch->buffer) / ATI_IXP_DMA_CHSEGS_MIN;
|
||||
if (blksz < ATI_IXP_BLK_MIN)
|
||||
blksz = ATI_IXP_BLK_MIN;
|
||||
if (blkcnt > ATI_IXP_DMA_CHSEGS_MAX)
|
||||
blkcnt = ATI_IXP_DMA_CHSEGS_MAX;
|
||||
if (blkcnt < ATI_IXP_DMA_CHSEGS_MIN)
|
||||
blkcnt = ATI_IXP_DMA_CHSEGS_MIN;
|
||||
|
||||
while ((blksz * blkcnt) > sndbuf_getmaxsize(ch->buffer)) {
|
||||
if ((blkcnt >> 1) >= ATI_IXP_DMA_CHSEGS_MIN)
|
||||
blkcnt >>= 1;
|
||||
else if ((blksz >> 1) >= ATI_IXP_BLK_MIN)
|
||||
blksz >>= 1;
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
if ((sndbuf_getblksz(ch->buffer) != blksz ||
|
||||
sndbuf_getblkcnt(ch->buffer) != blkcnt) &&
|
||||
sndbuf_resize(ch->buffer, blkcnt, blksz) != 0)
|
||||
device_printf(sc->dev, "%s: failed blksz=%u blkcnt=%u\n",
|
||||
__func__, blksz, blkcnt);
|
||||
|
||||
ch->blksz = sndbuf_getblksz(ch->buffer);
|
||||
ch->blkcnt = sndbuf_getblkcnt(ch->buffer);
|
||||
|
||||
return (1);
|
||||
}
|
||||
|
||||
static int
|
||||
atiixp_chan_setblocksize(kobj_t obj, void *data, uint32_t blksz)
|
||||
{
|
||||
struct atiixp_chinfo *ch = data;
|
||||
struct atiixp_info *sc = ch->parent;
|
||||
|
||||
if ((blksz * ch->blkcnt) > sndbuf_getmaxsize(ch->buffer))
|
||||
blksz = sndbuf_getmaxsize(ch->buffer) / ch->blkcnt;
|
||||
|
||||
if ((sndbuf_getblksz(ch->buffer) != blksz ||
|
||||
sndbuf_getblkcnt(ch->buffer) != ch->blkcnt) &&
|
||||
sndbuf_resize(ch->buffer, ch->blkcnt, blksz) != 0)
|
||||
device_printf(sc->dev, "%s: failed blksz=%u blkcnt=%u\n",
|
||||
__func__, blksz, ch->blkcnt);
|
||||
|
||||
ch->blksz = sndbuf_getblksz(ch->buffer);
|
||||
atiixp_chan_setfragments(obj, data, blksz, sc->blkcnt);
|
||||
|
||||
return (ch->blksz);
|
||||
}
|
||||
@ -807,6 +841,7 @@ static kobj_method_t atiixp_chan_methods[] = {
|
||||
KOBJMETHOD(channel_setformat, atiixp_chan_setformat),
|
||||
KOBJMETHOD(channel_setspeed, atiixp_chan_setspeed),
|
||||
KOBJMETHOD(channel_setblocksize, atiixp_chan_setblocksize),
|
||||
KOBJMETHOD(channel_setfragments, atiixp_chan_setfragments),
|
||||
KOBJMETHOD(channel_trigger, atiixp_chan_trigger),
|
||||
KOBJMETHOD(channel_getptr, atiixp_chan_getptr),
|
||||
KOBJMETHOD(channel_getcaps, atiixp_chan_getcaps),
|
||||
@ -1179,6 +1214,9 @@ atiixp_pci_attach(device_t dev)
|
||||
*/
|
||||
if (resource_int_value(device_get_name(dev),
|
||||
device_get_unit(dev), "blocksize", &i) == 0 && i > 0) {
|
||||
i &= ATI_IXP_BLK_ALIGN;
|
||||
if (i < ATI_IXP_BLK_MIN)
|
||||
i = ATI_IXP_BLK_MIN;
|
||||
sc->blkcnt = sc->bufsz / i;
|
||||
i = 0;
|
||||
while (sc->blkcnt >> i)
|
||||
@ -1212,7 +1250,7 @@ atiixp_pci_attach(device_t dev)
|
||||
/*lowaddr*/BUS_SPACE_MAXADDR_32BIT,
|
||||
/*highaddr*/BUS_SPACE_MAXADDR,
|
||||
/*filter*/NULL, /*filterarg*/NULL,
|
||||
/*maxsize*/sc->blkcnt * ATI_IXP_NCHANS *
|
||||
/*maxsize*/ATI_IXP_DMA_CHSEGS_MAX * ATI_IXP_NCHANS *
|
||||
sizeof(struct atiixp_dma_op),
|
||||
/*nsegments*/1, /*maxsegz*/0x3ffff,
|
||||
/*flags*/0, /*lockfunc*/NULL,
|
||||
@ -1226,8 +1264,8 @@ atiixp_pci_attach(device_t dev)
|
||||
goto bad;
|
||||
|
||||
if (bus_dmamap_load(sc->sgd_dmat, sc->sgd_dmamap, sc->sgd_table,
|
||||
sc->blkcnt * ATI_IXP_NCHANS * sizeof(struct atiixp_dma_op),
|
||||
atiixp_dma_cb, sc, 0))
|
||||
ATI_IXP_DMA_CHSEGS_MAX * ATI_IXP_NCHANS *
|
||||
sizeof(struct atiixp_dma_op), atiixp_dma_cb, sc, 0))
|
||||
goto bad;
|
||||
|
||||
|
||||
|
@ -93,6 +93,11 @@ SND_DECLARE_FILE("$FreeBSD$");
|
||||
#define ES_ADC 2
|
||||
#define ES_NCHANS 3
|
||||
|
||||
#define ES_DMA_SEGS_MIN 2
|
||||
#define ES_DMA_SEGS_MAX 256
|
||||
#define ES_BLK_MIN 64
|
||||
#define ES_BLK_ALIGN (~(ES_BLK_MIN - 1))
|
||||
|
||||
#define ES1370_DAC1_MINSPEED 5512
|
||||
#define ES1370_DAC1_MAXSPEED 44100
|
||||
|
||||
@ -593,27 +598,52 @@ eschan1371_setspeed(kobj_t obj, void *data, uint32_t speed)
|
||||
return (i);
|
||||
}
|
||||
|
||||
static int
|
||||
eschan_setfragments(kobj_t obj, void *data, uint32_t blksz, uint32_t blkcnt)
|
||||
{
|
||||
struct es_chinfo *ch = data;
|
||||
struct es_info *es = ch->parent;
|
||||
|
||||
blksz &= ES_BLK_ALIGN;
|
||||
|
||||
if (blksz > (sndbuf_getmaxsize(ch->buffer) / ES_DMA_SEGS_MIN))
|
||||
blksz = sndbuf_getmaxsize(ch->buffer) / ES_DMA_SEGS_MIN;
|
||||
if (blksz < ES_BLK_MIN)
|
||||
blksz = ES_BLK_MIN;
|
||||
if (blkcnt > ES_DMA_SEGS_MAX)
|
||||
blkcnt = ES_DMA_SEGS_MAX;
|
||||
if (blkcnt < ES_DMA_SEGS_MIN)
|
||||
blkcnt = ES_DMA_SEGS_MIN;
|
||||
|
||||
while ((blksz * blkcnt) > sndbuf_getmaxsize(ch->buffer)) {
|
||||
if ((blkcnt >> 1) >= ES_DMA_SEGS_MIN)
|
||||
blkcnt >>= 1;
|
||||
else if ((blksz >> 1) >= ES_BLK_MIN)
|
||||
blksz >>= 1;
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
if ((sndbuf_getblksz(ch->buffer) != blksz ||
|
||||
sndbuf_getblkcnt(ch->buffer) != blkcnt) &&
|
||||
sndbuf_resize(ch->buffer, blkcnt, blksz) != 0)
|
||||
device_printf(es->dev, "%s: failed blksz=%u blkcnt=%u\n",
|
||||
__func__, blksz, blkcnt);
|
||||
|
||||
ch->bufsz = sndbuf_getsize(ch->buffer);
|
||||
ch->blksz = sndbuf_getblksz(ch->buffer);
|
||||
ch->blkcnt = sndbuf_getblkcnt(ch->buffer);
|
||||
|
||||
return (1);
|
||||
}
|
||||
|
||||
static int
|
||||
eschan_setblocksize(kobj_t obj, void *data, uint32_t blksz)
|
||||
{
|
||||
struct es_chinfo *ch = data;
|
||||
struct es_info *es = ch->parent;
|
||||
|
||||
blksz &= ~0x3f;
|
||||
if (blksz < 0x40)
|
||||
blksz = 0x40;
|
||||
|
||||
if ((blksz * ch->blkcnt) > sndbuf_getmaxsize(ch->buffer))
|
||||
blksz = sndbuf_getmaxsize(ch->buffer) / ch->blkcnt;
|
||||
|
||||
if ((sndbuf_getblksz(ch->buffer) != blksz ||
|
||||
sndbuf_getblkcnt(ch->buffer) != ch->blkcnt) &&
|
||||
sndbuf_resize(ch->buffer, ch->blkcnt, blksz) != 0)
|
||||
device_printf(es->dev, "%s: failed blksz=%u blkcnt=%u\n",
|
||||
__func__, blksz, ch->blkcnt);
|
||||
|
||||
ch->bufsz = sndbuf_getsize(ch->buffer);
|
||||
ch->blksz = sndbuf_getblksz(ch->buffer);
|
||||
eschan_setfragments(obj, data, blksz, es->blkcnt);
|
||||
|
||||
return (ch->blksz);
|
||||
}
|
||||
@ -813,7 +843,7 @@ eschan_getptr(kobj_t obj, void *data)
|
||||
}
|
||||
ES_UNLOCK(es);
|
||||
|
||||
cnt &= ~0x3f;
|
||||
cnt &= ES_BLK_ALIGN;
|
||||
|
||||
return (cnt);
|
||||
}
|
||||
@ -831,6 +861,7 @@ static kobj_method_t eschan1370_methods[] = {
|
||||
KOBJMETHOD(channel_setformat, eschan_setformat),
|
||||
KOBJMETHOD(channel_setspeed, eschan1370_setspeed),
|
||||
KOBJMETHOD(channel_setblocksize, eschan_setblocksize),
|
||||
KOBJMETHOD(channel_setfragments, eschan_setfragments),
|
||||
KOBJMETHOD(channel_trigger, eschan_trigger),
|
||||
KOBJMETHOD(channel_getptr, eschan_getptr),
|
||||
KOBJMETHOD(channel_getcaps, eschan_getcaps),
|
||||
@ -843,6 +874,7 @@ static kobj_method_t eschan1371_methods[] = {
|
||||
KOBJMETHOD(channel_setformat, eschan_setformat),
|
||||
KOBJMETHOD(channel_setspeed, eschan1371_setspeed),
|
||||
KOBJMETHOD(channel_setblocksize, eschan_setblocksize),
|
||||
KOBJMETHOD(channel_setfragments, eschan_setfragments),
|
||||
KOBJMETHOD(channel_trigger, eschan_trigger),
|
||||
KOBJMETHOD(channel_getptr, eschan_getptr),
|
||||
KOBJMETHOD(channel_getcaps, eschan_getcaps),
|
||||
@ -1049,9 +1081,10 @@ es1371_wrcd(kobj_t obj, void *s, int addr, uint32_t data)
|
||||
uint32_t t, x, orig;
|
||||
struct es_info *es = (struct es_info*)s;
|
||||
|
||||
for (t = 0; t < 0x1000; t++)
|
||||
for (t = 0; t < 0x1000; t++) {
|
||||
if (!es_rd(es, ES1371_REG_CODEC & CODEC_WIP, 4))
|
||||
break;
|
||||
}
|
||||
/* save the current state for later */
|
||||
x = orig = es_rd(es, ES1371_REG_SMPRATE, 4);
|
||||
/* enable SRC state data in SRC mux */
|
||||
@ -1571,10 +1604,10 @@ es_init_sysctls(device_t dev)
|
||||
revid = pci_get_revid(dev);
|
||||
es = pcm_getdevinfo(dev);
|
||||
if ((devid == ES1371_PCI_ID && revid == ES1371REV_ES1373_8) ||
|
||||
(devid == ES1371_PCI_ID && revid == ES1371REV_CT5880_A) ||
|
||||
(devid == CT5880_PCI_ID && revid == CT5880REV_CT5880_C) ||
|
||||
(devid == CT5880_PCI_ID && revid == CT5880REV_CT5880_D) ||
|
||||
(devid == CT5880_PCI_ID && revid == CT5880REV_CT5880_E)) {
|
||||
(devid == ES1371_PCI_ID && revid == ES1371REV_CT5880_A) ||
|
||||
(devid == CT5880_PCI_ID && revid == CT5880REV_CT5880_C) ||
|
||||
(devid == CT5880_PCI_ID && revid == CT5880REV_CT5880_D) ||
|
||||
(devid == CT5880_PCI_ID && revid == CT5880REV_CT5880_E)) {
|
||||
/* XXX: an user should be able to set this with a control tool,
|
||||
if not done before 7.0-RELEASE, this needs to be converted
|
||||
to a device specific sysctl "dev.pcm.X.yyy" via
|
||||
@ -1699,18 +1732,18 @@ es_pci_attach(device_t dev)
|
||||
es->bufsz = pcm_getbuffersize(dev, 4096, ES_DEFAULT_BUFSZ, 65536);
|
||||
if (resource_int_value(device_get_name(dev),
|
||||
device_get_unit(dev), "blocksize", &i) == 0 && i > 0) {
|
||||
i &= ~0x3f;
|
||||
if (i < 0x40)
|
||||
i = 0x40;
|
||||
i &= ES_BLK_ALIGN;
|
||||
if (i < ES_BLK_MIN)
|
||||
i = ES_BLK_MIN;
|
||||
es->blkcnt = es->bufsz / i;
|
||||
i = 0;
|
||||
while (es->blkcnt >> i)
|
||||
i++;
|
||||
es->blkcnt = 1 << (i - 1);
|
||||
if (es->blkcnt < 2)
|
||||
es->blkcnt = 2;
|
||||
else if (es->blkcnt > 256)
|
||||
es->blkcnt = 256;
|
||||
if (es->blkcnt < ES_DMA_SEGS_MIN)
|
||||
es->blkcnt = ES_DMA_SEGS_MIN;
|
||||
else if (es->blkcnt > ES_DMA_SEGS_MAX)
|
||||
es->blkcnt = ES_DMA_SEGS_MAX;
|
||||
|
||||
} else
|
||||
es->blkcnt = 2;
|
||||
|
@ -80,7 +80,7 @@
|
||||
|
||||
#include "mixer_if.h"
|
||||
|
||||
#define HDA_DRV_TEST_REV "20070316_0041"
|
||||
#define HDA_DRV_TEST_REV "20070317_0042"
|
||||
#define HDA_WIDGET_PARSER_REV 1
|
||||
|
||||
SND_DECLARE_FILE("$FreeBSD$");
|
||||
@ -201,6 +201,7 @@ SND_DECLARE_FILE("$FreeBSD$");
|
||||
#define ASUS_P1AH2_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x81cb)
|
||||
#define ASUS_A7M_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x1323)
|
||||
#define ASUS_A7T_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x13c2)
|
||||
#define ASUS_W6F_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x1263)
|
||||
#define ASUS_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0xffff)
|
||||
|
||||
/* IBM / Lenovo */
|
||||
@ -301,6 +302,9 @@ static const struct {
|
||||
#define HDA_BDL_MAX 256
|
||||
#define HDA_BDL_DEFAULT HDA_BDL_MIN
|
||||
|
||||
#define HDA_BLK_MIN 128
|
||||
#define HDA_BLK_ALIGN (~(HDA_BLK_MIN - 1))
|
||||
|
||||
#define HDA_BUFSZ_MIN 4096
|
||||
#define HDA_BUFSZ_MAX 65536
|
||||
#define HDA_BUFSZ_DEFAULT 16384
|
||||
@ -2763,26 +2767,52 @@ hdac_stream_setup(struct hdac_chan *ch)
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
hdac_channel_setfragments(kobj_t obj, void *data,
|
||||
uint32_t blksz, uint32_t blkcnt)
|
||||
{
|
||||
struct hdac_chan *ch = data;
|
||||
struct hdac_softc *sc = ch->devinfo->codec->sc;
|
||||
|
||||
blksz &= HDA_BLK_ALIGN;
|
||||
|
||||
if (blksz > (sndbuf_getmaxsize(ch->b) / HDA_BDL_MIN))
|
||||
blksz = sndbuf_getmaxsize(ch->b) / HDA_BDL_MIN;
|
||||
if (blksz < HDA_BLK_MIN)
|
||||
blksz = HDA_BLK_MIN;
|
||||
if (blkcnt > HDA_BDL_MAX)
|
||||
blkcnt = HDA_BDL_MAX;
|
||||
if (blkcnt < HDA_BDL_MIN)
|
||||
blkcnt = HDA_BDL_MIN;
|
||||
|
||||
while ((blksz * blkcnt) > sndbuf_getmaxsize(ch->b)) {
|
||||
if ((blkcnt >> 1) >= HDA_BDL_MIN)
|
||||
blkcnt >>= 1;
|
||||
else if ((blksz >> 1) >= HDA_BLK_MIN)
|
||||
blksz >>= 1;
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
if ((sndbuf_getblksz(ch->b) != blksz ||
|
||||
sndbuf_getblkcnt(ch->b) != blkcnt) &&
|
||||
sndbuf_resize(ch->b, blkcnt, blksz) != 0)
|
||||
device_printf(sc->dev, "%s: failed blksz=%u blkcnt=%u\n",
|
||||
__func__, blksz, blkcnt);
|
||||
|
||||
ch->blksz = sndbuf_getblksz(ch->b);
|
||||
ch->blkcnt = sndbuf_getblkcnt(ch->b);
|
||||
|
||||
return (1);
|
||||
}
|
||||
|
||||
static int
|
||||
hdac_channel_setblocksize(kobj_t obj, void *data, uint32_t blksz)
|
||||
{
|
||||
struct hdac_chan *ch = data;
|
||||
struct hdac_softc *sc = ch->devinfo->codec->sc;
|
||||
|
||||
blksz &= ~0x7f;
|
||||
if (blksz < 0x80)
|
||||
blksz = 0x80;
|
||||
|
||||
if ((blksz * ch->blkcnt) > sndbuf_getmaxsize(ch->b))
|
||||
blksz = sndbuf_getmaxsize(ch->b) / ch->blkcnt;
|
||||
|
||||
if ((sndbuf_getblksz(ch->b) != blksz ||
|
||||
sndbuf_getblkcnt(ch->b) != ch->blkcnt) &&
|
||||
sndbuf_resize(ch->b, ch->blkcnt, blksz) != 0)
|
||||
device_printf(sc->dev, "%s: failed blksz=%u blkcnt=%u\n",
|
||||
__func__, blksz, ch->blkcnt);
|
||||
|
||||
ch->blksz = sndbuf_getblksz(ch->b);
|
||||
hdac_channel_setfragments(obj, data, blksz, sc->chan_blkcnt);
|
||||
|
||||
return (ch->blksz);
|
||||
}
|
||||
@ -2857,7 +2887,7 @@ hdac_channel_getptr(kobj_t obj, void *data)
|
||||
* Round to available space and force 128 bytes aligment.
|
||||
*/
|
||||
ptr %= ch->blksz * ch->blkcnt;
|
||||
ptr &= ~0x7f;
|
||||
ptr &= HDA_BLK_ALIGN;
|
||||
|
||||
return (ptr);
|
||||
}
|
||||
@ -2873,6 +2903,7 @@ static kobj_method_t hdac_channel_methods[] = {
|
||||
KOBJMETHOD(channel_setformat, hdac_channel_setformat),
|
||||
KOBJMETHOD(channel_setspeed, hdac_channel_setspeed),
|
||||
KOBJMETHOD(channel_setblocksize, hdac_channel_setblocksize),
|
||||
KOBJMETHOD(channel_setfragments, hdac_channel_setfragments),
|
||||
KOBJMETHOD(channel_trigger, hdac_channel_trigger),
|
||||
KOBJMETHOD(channel_getptr, hdac_channel_getptr),
|
||||
KOBJMETHOD(channel_getcaps, hdac_channel_getcaps),
|
||||
@ -3259,9 +3290,9 @@ hdac_attach(device_t dev)
|
||||
|
||||
if (resource_int_value(device_get_name(sc->dev),
|
||||
device_get_unit(sc->dev), "blocksize", &i) == 0 && i > 0) {
|
||||
i &= ~0x7f;
|
||||
if (i < 0x80)
|
||||
i = 0x80;
|
||||
i &= HDA_BLK_ALIGN;
|
||||
if (i < HDA_BLK_MIN)
|
||||
i = HDA_BLK_MIN;
|
||||
sc->chan_blkcnt = sc->chan_size / i;
|
||||
i = 0;
|
||||
while (sc->chan_blkcnt >> i)
|
||||
|
@ -65,6 +65,8 @@ SND_DECLARE_FILE("$FreeBSD$");
|
||||
#define VIA_SEGS_MIN 2
|
||||
#define VIA_SEGS_MAX 64
|
||||
#define VIA_SEGS_DEFAULT 2
|
||||
#define VIA_BLK_MIN 32
|
||||
#define VIA_BLK_ALIGN (~(VIA_BLK_MIN - 1))
|
||||
|
||||
#define VIA_DEFAULT_BUFSZ 0x1000
|
||||
|
||||
@ -92,6 +94,8 @@ struct via_chinfo {
|
||||
};
|
||||
|
||||
struct via_info {
|
||||
device_t dev;
|
||||
|
||||
bus_space_tag_t st;
|
||||
bus_space_handle_t sh;
|
||||
bus_dma_tag_t parent_dmat;
|
||||
@ -312,7 +316,7 @@ via_waitready_codec(struct via_info *via)
|
||||
return (0);
|
||||
DELAY(1);
|
||||
}
|
||||
printf("via: codec busy\n");
|
||||
device_printf(via->dev, "%s: codec busy\n", __func__);
|
||||
return (1);
|
||||
}
|
||||
|
||||
@ -327,7 +331,7 @@ via_waitvalid_codec(struct via_info *via)
|
||||
return (0);
|
||||
DELAY(1);
|
||||
}
|
||||
printf("via: codec invalid\n");
|
||||
device_printf(via->dev, "%s: codec invalid\n", __func__);
|
||||
return (1);
|
||||
}
|
||||
|
||||
@ -555,21 +559,52 @@ via8233msgd_getcaps(kobj_t obj, void *data)
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Common functions */
|
||||
|
||||
static int
|
||||
via8233chan_setfragments(kobj_t obj, void *data,
|
||||
uint32_t blksz, uint32_t blkcnt)
|
||||
{
|
||||
struct via_chinfo *ch = data;
|
||||
struct via_info *via = ch->parent;
|
||||
|
||||
blksz &= VIA_BLK_ALIGN;
|
||||
|
||||
if (blksz > (sndbuf_getmaxsize(ch->buffer) / VIA_SEGS_MIN))
|
||||
blksz = sndbuf_getmaxsize(ch->buffer) / VIA_SEGS_MIN;
|
||||
if (blksz < VIA_BLK_MIN)
|
||||
blksz = VIA_BLK_MIN;
|
||||
if (blkcnt > VIA_SEGS_MAX)
|
||||
blkcnt = VIA_SEGS_MAX;
|
||||
if (blkcnt < VIA_SEGS_MIN)
|
||||
blkcnt = VIA_SEGS_MIN;
|
||||
|
||||
while ((blksz * blkcnt) > sndbuf_getmaxsize(ch->buffer)) {
|
||||
if ((blkcnt >> 1) >= VIA_SEGS_MIN)
|
||||
blkcnt >>= 1;
|
||||
else if ((blksz >> 1) >= VIA_BLK_MIN)
|
||||
blksz >>= 1;
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
if ((sndbuf_getblksz(ch->buffer) != blksz ||
|
||||
sndbuf_getblkcnt(ch->buffer) != blkcnt) &&
|
||||
sndbuf_resize(ch->buffer, blkcnt, blksz) != 0)
|
||||
device_printf(via->dev, "%s: failed blksz=%u blkcnt=%u\n",
|
||||
__func__, blksz, blkcnt);
|
||||
|
||||
ch->blksz = sndbuf_getblksz(ch->buffer);
|
||||
ch->blkcnt = sndbuf_getblkcnt(ch->buffer);
|
||||
|
||||
return (1);
|
||||
}
|
||||
|
||||
static int
|
||||
via8233chan_setblocksize(kobj_t obj, void *data, uint32_t blksz)
|
||||
{
|
||||
struct via_chinfo *ch = data;
|
||||
struct via_info *via = ch->parent;
|
||||
|
||||
if ((blksz * ch->blkcnt) > sndbuf_getmaxsize(ch->buffer))
|
||||
blksz = sndbuf_getmaxsize(ch->buffer) / ch->blkcnt;
|
||||
|
||||
if ((sndbuf_getblksz(ch->buffer) != blksz ||
|
||||
sndbuf_getblkcnt(ch->buffer) != ch->blkcnt) &&
|
||||
sndbuf_resize(ch->buffer, ch->blkcnt, blksz) != 0)
|
||||
printf("via: %s: failed blksz=%u blkcnt=%u\n",
|
||||
__func__, blksz, ch->blkcnt);
|
||||
|
||||
ch->blksz = sndbuf_getblksz(ch->buffer);
|
||||
via8233chan_setfragments(obj, data, blksz, via->blkcnt);
|
||||
|
||||
return (ch->blksz);
|
||||
}
|
||||
@ -613,8 +648,8 @@ via8233chan_reset(struct via_info *via, struct via_chinfo *ch)
|
||||
static void
|
||||
via8233chan_sgdinit(struct via_info *via, struct via_chinfo *ch, int chnum)
|
||||
{
|
||||
ch->sgd_table = &via->sgd_table[chnum * via->blkcnt];
|
||||
ch->sgd_addr = via->sgd_addr + chnum * via->blkcnt *
|
||||
ch->sgd_table = &via->sgd_table[chnum * VIA_SEGS_MAX];
|
||||
ch->sgd_addr = via->sgd_addr + chnum * VIA_SEGS_MAX *
|
||||
sizeof(struct via_dma_op);
|
||||
}
|
||||
|
||||
@ -716,10 +751,10 @@ via8233chan_mute(struct via_info *via, struct via_chinfo *ch, int muted)
|
||||
via_wr(via, ch->rbase + VIA8233_RP_DXS_RVOL, muted, 1);
|
||||
r = via_rd(via, ch->rbase + VIA8233_RP_DXS_LVOL, 1) &
|
||||
VIA8233_DXS_MUTE;
|
||||
if (r != muted) {
|
||||
printf("via: failed to set dxs volume "
|
||||
"(dxs base 0x%02x).\n", ch->rbase);
|
||||
}
|
||||
if (r != muted)
|
||||
device_printf(via->dev,
|
||||
"%s: failed to set dxs volume "
|
||||
"(dxs base 0x%02x).\n", __func__, ch->rbase);
|
||||
}
|
||||
}
|
||||
|
||||
@ -922,6 +957,7 @@ static kobj_method_t via8233wr_methods[] = {
|
||||
KOBJMETHOD(channel_setspeed, via8233wr_setspeed),
|
||||
KOBJMETHOD(channel_getcaps, via8233wr_getcaps),
|
||||
KOBJMETHOD(channel_setblocksize, via8233chan_setblocksize),
|
||||
KOBJMETHOD(channel_setfragments, via8233chan_setfragments),
|
||||
KOBJMETHOD(channel_trigger, via8233chan_trigger),
|
||||
KOBJMETHOD(channel_getptr, via8233chan_getptr),
|
||||
{ 0, 0 }
|
||||
@ -934,6 +970,7 @@ static kobj_method_t via8233dxs_methods[] = {
|
||||
KOBJMETHOD(channel_setspeed, via8233dxs_setspeed),
|
||||
KOBJMETHOD(channel_getcaps, via8233dxs_getcaps),
|
||||
KOBJMETHOD(channel_setblocksize, via8233chan_setblocksize),
|
||||
KOBJMETHOD(channel_setfragments, via8233chan_setfragments),
|
||||
KOBJMETHOD(channel_trigger, via8233chan_trigger),
|
||||
KOBJMETHOD(channel_getptr, via8233chan_getptr),
|
||||
{ 0, 0 }
|
||||
@ -946,6 +983,7 @@ static kobj_method_t via8233msgd_methods[] = {
|
||||
KOBJMETHOD(channel_setspeed, via8233msgd_setspeed),
|
||||
KOBJMETHOD(channel_getcaps, via8233msgd_getcaps),
|
||||
KOBJMETHOD(channel_setblocksize, via8233chan_setblocksize),
|
||||
KOBJMETHOD(channel_setfragments, via8233chan_setfragments),
|
||||
KOBJMETHOD(channel_trigger, via8233chan_trigger),
|
||||
KOBJMETHOD(channel_getptr, via8233chan_getptr),
|
||||
{ 0, 0 }
|
||||
@ -1125,6 +1163,7 @@ via_attach(device_t dev)
|
||||
}
|
||||
via->lock = snd_mtxcreate(device_get_nameunit(dev),
|
||||
"snd_via8233 softc");
|
||||
via->dev = dev;
|
||||
|
||||
callout_init(&via->poll_timer, CALLOUT_MPSAFE);
|
||||
via->poll_ticks = 1;
|
||||
@ -1161,6 +1200,9 @@ via_attach(device_t dev)
|
||||
via->bufsz = pcm_getbuffersize(dev, 4096, VIA_DEFAULT_BUFSZ, 65536);
|
||||
if (resource_int_value(device_get_name(dev),
|
||||
device_get_unit(dev), "blocksize", &i) == 0 && i > 0) {
|
||||
i &= VIA_BLK_ALIGN;
|
||||
if (i < VIA_BLK_MIN)
|
||||
i = VIA_BLK_MIN;
|
||||
via->blkcnt = via->bufsz / i;
|
||||
i = 0;
|
||||
while (via->blkcnt >> i)
|
||||
@ -1235,7 +1277,7 @@ via_attach(device_t dev)
|
||||
else
|
||||
via->dxs_src = 0;
|
||||
|
||||
nsegs = (via_dxs_chnum + via_sgd_chnum + NWRCHANS) * via->blkcnt;
|
||||
nsegs = (via_dxs_chnum + via_sgd_chnum + NWRCHANS) * VIA_SEGS_MAX;
|
||||
|
||||
/* DMA tag for buffers */
|
||||
if (bus_dma_tag_create(/*parent*/bus_get_dma_tag(dev), /*alignment*/2,
|
||||
|
Loading…
Reference in New Issue
Block a user