|
Lines 37-42
Link Here
|
| 37 |
#define CANCHANGE(c) (!(c)->buffer.dl) |
37 |
#define CANCHANGE(c) (!(c)->buffer.dl) |
| 38 |
|
38 |
|
| 39 |
static void chn_stintr(pcm_channel *c); |
39 |
static void chn_stintr(pcm_channel *c); |
|
|
40 |
static void chn_clearbuf(pcm_channel *c, int length); |
| 40 |
/* |
41 |
/* |
| 41 |
* SOUND OUTPUT |
42 |
* SOUND OUTPUT |
| 42 |
|
43 |
|
|
Lines 103-109
Link Here
|
| 103 |
{ |
104 |
{ |
| 104 |
if (ISA_DMA(&c->buffer)) { |
105 |
if (ISA_DMA(&c->buffer)) { |
| 105 |
/* tell isa_dma to bounce data in/out */ |
106 |
/* tell isa_dma to bounce data in/out */ |
| 106 |
} else panic("chn_isadmabounce called on invalid channel"); |
107 |
} else KASSERT(1, ("chn_isadmabounce called on invalid channel")); |
| 107 |
} |
108 |
} |
| 108 |
|
109 |
|
| 109 |
static int |
110 |
static int |
|
Lines 153-179
Link Here
|
| 153 |
* NOTE: when we are using auto dma in the device, rl might become |
154 |
* NOTE: when we are using auto dma in the device, rl might become |
| 154 |
* negative. |
155 |
* negative. |
| 155 |
*/ |
156 |
*/ |
|
|
157 |
DEB (static int chn_updatecount=0); |
| 158 |
|
| 156 |
void |
159 |
void |
| 157 |
chn_dmaupdate(pcm_channel *c) |
160 |
chn_dmaupdate(pcm_channel *c) |
| 158 |
{ |
161 |
{ |
| 159 |
snd_dbuf *b = &c->buffer; |
162 |
snd_dbuf *b = &c->buffer; |
| 160 |
int delta, hwptr = chn_getptr(c); |
163 |
int delta, hwptr; |
|
|
164 |
DEB (int b_rl=b->rl; int b_fl=b->fl; int b_rp=b->rp; int b_fp=b->fp); |
| 161 |
|
165 |
|
|
|
166 |
hwptr = chn_getptr(c); |
| 162 |
if (c->direction == PCMDIR_PLAY) { |
167 |
if (c->direction == PCMDIR_PLAY) { |
| 163 |
delta = (b->bufsize + hwptr - b->rp) % b->bufsize; |
168 |
delta = (b->bufsize + hwptr - b->rp) % b->bufsize; |
| 164 |
b->rp = hwptr; |
169 |
b->rp = hwptr; |
| 165 |
b->rl -= delta; |
170 |
b->rl -= delta; |
| 166 |
b->fl += delta; |
171 |
b->fl += delta; |
|
|
172 |
DEB(if (b->rl<0) printf("OUCH!(%d) rl %d(%d) delta %d bufsize %d hwptr %d rp %d(%d)\n", chn_updatecount++, b->rl, b_rl, delta, b->bufsize, hwptr, b->rp, b_rp)); |
| 167 |
} else { |
173 |
} else { |
| 168 |
delta = (b->bufsize + hwptr - b->fp) % b->bufsize; |
174 |
delta = (b->bufsize + hwptr - b->fp) % b->bufsize; |
| 169 |
b->fp = hwptr; |
175 |
b->fp = hwptr; |
| 170 |
b->rl += delta; |
176 |
b->rl += delta; |
| 171 |
b->fl -= delta; |
177 |
b->fl -= delta; |
|
|
178 |
DEB(if (b->fl<0) printf("OUCH!(%d) fl %d(%d) delta %d bufsize %d hwptr %d fp %d(%d)\n", chn_updatecount++, b->fl, b_fl, delta, b->bufsize, hwptr, b->fp, b_fp)); |
| 172 |
} |
179 |
} |
| 173 |
b->total += delta; |
180 |
b->total += delta; |
| 174 |
} |
181 |
} |
| 175 |
|
182 |
|
| 176 |
/* |
183 |
/* |
|
|
184 |
* Check channel for underflow occured, reset DMA buffer in case of |
| 185 |
* underflow. It must be called at spltty(). |
| 186 |
*/ |
| 187 |
static void |
| 188 |
chn_checkunderflow(pcm_channel *c) |
| 189 |
{ |
| 190 |
snd_dbuf *b = &c->buffer; |
| 191 |
|
| 192 |
if (b->underflow) { |
| 193 |
DEB(printf("Clear underflow condition\n")); |
| 194 |
b->rp = b->fp = chn_getptr(c); |
| 195 |
b->rl = 0; |
| 196 |
b->fl = b->bufsize; |
| 197 |
b->underflow=0; |
| 198 |
} else { |
| 199 |
chn_dmaupdate(c); |
| 200 |
} |
| 201 |
} |
| 202 |
|
| 203 |
/* |
| 177 |
* Write interrupt routine. Can be called from other places (e.g. |
204 |
* Write interrupt routine. Can be called from other places (e.g. |
| 178 |
* to start a paused transfer), but with interrupts disabled. |
205 |
* to start a paused transfer), but with interrupts disabled. |
| 179 |
*/ |
206 |
*/ |
|
Lines 183-189
Link Here
|
| 183 |
snd_dbuf *b = &c->buffer; |
210 |
snd_dbuf *b = &c->buffer; |
| 184 |
int start; |
211 |
int start; |
| 185 |
|
212 |
|
| 186 |
if (b->dl) chn_dmadone(c); |
213 |
if (b->underflow) return; /* nothing new happened */ |
|
|
214 |
if (b->dl) chn_dmadone(c); |
| 187 |
|
215 |
|
| 188 |
/* |
216 |
/* |
| 189 |
* start another dma operation only if have ready data in the buffer, |
217 |
* start another dma operation only if have ready data in the buffer, |
|
Lines 198-237
Link Here
|
| 198 |
if (start) { |
226 |
if (start) { |
| 199 |
int l; |
227 |
int l; |
| 200 |
chn_dmaupdate(c); |
228 |
chn_dmaupdate(c); |
| 201 |
l = min(b->rl, c->blocksize) & DMA_ALIGN_MASK; |
|
|
| 202 |
if (c->flags & CHN_F_MAPPED) l = c->blocksize; |
229 |
if (c->flags & CHN_F_MAPPED) l = c->blocksize; |
|
|
230 |
else l = min(b->rl, c->blocksize) & DMA_ALIGN_MASK; |
| 203 |
/* |
231 |
/* |
| 204 |
* check if we need to reprogram the DMA on the sound card. |
232 |
* check if we need to reprogram the DMA on the sound card. |
| 205 |
* This happens if the size has changed _and_ the new size |
233 |
* This happens if the size has changed from zero |
| 206 |
* is smaller, or it matches the blocksize. |
|
|
| 207 |
* |
234 |
* |
| 208 |
* 0 <= l <= blocksize |
|
|
| 209 |
* 0 <= dl <= blocksize |
| 210 |
* reprog if (dl == 0 || l != dl) |
| 211 |
* was: |
| 212 |
* l != b->dl && (b->dl == 0 || l < b->dl || l == c->blocksize) |
| 213 |
*/ |
235 |
*/ |
| 214 |
if (b->dl == 0 || l != b->dl) { |
236 |
if (b->dl == 0) { |
| 215 |
/* size has changed. Stop and restart */ |
237 |
/* Start DMA operation */ |
| 216 |
DEB(printf("wrintr: bsz %d -> %d, rp %d rl %d\n", |
238 |
b->dl = c->blocksize ; /* record new transfer size */ |
| 217 |
b->dl, l, b->rp, b->rl)); |
|
|
| 218 |
if (b->dl) chn_trigger(c, PCMTRIG_STOP); |
| 219 |
b->dl = l; /* record new transfer size */ |
| 220 |
chn_trigger(c, PCMTRIG_START); |
239 |
chn_trigger(c, PCMTRIG_START); |
|
|
240 |
} else if (b->dl != l) { |
| 241 |
/* |
| 242 |
* we are near to underflow condition, so to prevent |
| 243 |
* audio 'clicks' clear next 1.5*dl bytes |
| 244 |
*/ |
| 245 |
chn_clearbuf(c, (b->dl*3)/2); |
| 221 |
} |
246 |
} |
| 222 |
} else { |
247 |
} else { |
| 223 |
/* cannot start a new dma transfer */ |
248 |
/* cannot start a new dma transfer */ |
| 224 |
DEB(printf("cannot start wr-dma flags 0x%08x rp %d rl %d\n", |
249 |
DEB(printf("cannot start wr-dma flags 0x%08x rp %d rl %d\n", |
| 225 |
c->flags, b->rp, b->rl)); |
250 |
c->flags, b->rp, b->rl)); |
| 226 |
if (b->dl) { /* was active */ |
251 |
if (b->dl) { /* DMA was active */ |
| 227 |
b->dl = 0; |
252 |
b->underflow = 1; /* set underflow flag */ |
| 228 |
chn_trigger(c, PCMTRIG_STOP); |
253 |
chn_clearbuf(c, b->bufsize); /* and clear all DMA buffer */ |
| 229 |
#if 0 |
|
|
| 230 |
if (c->flags & CHN_F_WRITING) |
| 231 |
DEB(printf("got wrint while reloading\n")); |
| 232 |
else if (b->rl <= 0) /* XXX added 980110 lr */ |
| 233 |
chn_resetbuf(c); |
| 234 |
#endif |
| 235 |
} |
254 |
} |
| 236 |
} |
255 |
} |
| 237 |
} |
256 |
} |
|
Lines 255-263
Link Here
|
| 255 |
int |
274 |
int |
| 256 |
chn_write(pcm_channel *c, struct uio *buf) |
275 |
chn_write(pcm_channel *c, struct uio *buf) |
| 257 |
{ |
276 |
{ |
| 258 |
int a, l, w, timeout, ret = 0; |
277 |
int a, l, w, timeout, ret = 0, rc; |
| 259 |
long s; |
278 |
long s; |
| 260 |
snd_dbuf *b = &c->buffer; |
279 |
snd_dbuf *b = &c->buffer; |
|
|
280 |
int threshold, maxthreshold, minthreshold; |
| 261 |
|
281 |
|
| 262 |
if (c->flags & CHN_F_WRITING) { |
282 |
if (c->flags & CHN_F_WRITING) { |
| 263 |
/* This shouldn't happen and is actually silly |
283 |
/* This shouldn't happen and is actually silly |
|
Lines 267-301
Link Here
|
| 267 |
return EBUSY; |
287 |
return EBUSY; |
| 268 |
} |
288 |
} |
| 269 |
a = (1 << c->align) - 1; |
289 |
a = (1 << c->align) - 1; |
|
|
290 |
maxthreshold=(b->dl/4+a)&(~a); |
| 291 |
minthreshold=a; |
| 270 |
c->flags |= CHN_F_WRITING; |
292 |
c->flags |= CHN_F_WRITING; |
| 271 |
while ((c->smegcnt + buf->uio_resid) > a) { |
293 |
s = spltty(); |
| 272 |
s = spltty(); |
294 |
chn_checkunderflow(c); |
| 273 |
chn_dmaupdate(c); |
295 |
splx(s); |
| 274 |
splx(s); |
296 |
while ((buf->uio_resid+c->smegcnt) > minthreshold ) { /* Don't allow write unaligned data */ |
| 275 |
if (b->fl < DMA_ALIGN_THRESHOLD) { |
297 |
threshold = min ((buf->uio_resid+c->smegcnt), maxthreshold); |
|
|
298 |
if (b->fl < threshold) { |
| 276 |
if (c->flags & CHN_F_NBIO) break; |
299 |
if (c->flags & CHN_F_NBIO) break; |
| 277 |
timeout = (buf->uio_resid >= b->dl)? hz : 1; |
300 |
timeout = (buf->uio_resid >= b->dl)? hz : 1; |
| 278 |
ret = tsleep(b, PRIBIO | PCATCH, "pcmwr", timeout); |
301 |
rc = tsleep(b, PRIBIO | PCATCH, "pcmwr", timeout); |
| 279 |
if (ret == EINTR) chn_abort(c); |
302 |
if (rc == 0 || rc == EWOULDBLOCK) { |
| 280 |
if (ret == EINTR || ret == ERESTART) break; |
303 |
s = spltty(); |
| 281 |
ret = 0; |
304 |
chn_checkunderflow(c); |
| 282 |
continue; |
305 |
splx(s); |
| 283 |
} |
306 |
if (b->fl < minthreshold) continue; /* write only alligned chunk of data */ |
|
|
307 |
} else { |
| 308 |
#if 0 |
| 309 |
if (ret == EINTR) chn_abort(c); |
| 310 |
#endif |
| 311 |
ret=rc; |
| 312 |
break; |
| 313 |
} |
| 314 |
} |
| 284 |
/* ensure we always have a whole number of samples */ |
315 |
/* ensure we always have a whole number of samples */ |
| 285 |
l = min(b->fl, b->bufsize - b->fp) & ~a; |
316 |
l = min(b->fl, b->bufsize - b->fp); |
| 286 |
if (l == 0) break; |
317 |
KASSERT(!(l & a),("unaligned write %d, %d fl %d fp %d bufsize %d", l, a + 1, b->fl, b->fp, b->bufsize)); |
| 287 |
w = c->feeder->feed(c->feeder, c, b->buf + b->fp, l, buf); |
318 |
w = c->feeder->feed(c->feeder, c, b->buf + b->fp, l, buf); |
| 288 |
if (w == 0) panic("no feed"); |
319 |
KASSERT(w, ("chn_write: no feed")); |
| 289 |
s = spltty(); |
320 |
s = spltty(); |
| 290 |
b->rl += w; |
321 |
b->rl += w; |
| 291 |
b->fl -= w; |
322 |
b->fl -= w; |
| 292 |
b->fp = (b->fp + w) % b->bufsize; |
323 |
b->fp = (b->fp + w) % b->bufsize; |
| 293 |
splx(s); |
324 |
splx(s); |
| 294 |
if (b->rl && !b->dl) chn_stintr(c); |
325 |
DEB(if(1) printf("write %d bytes fp %d rl %d\n",w ,b->fp, b->rl)); |
|
|
326 |
if (!b->dl) chn_stintr(c); |
| 295 |
} |
327 |
} |
| 296 |
if ((ret == 0) && (buf->uio_resid > 0)) { |
328 |
if ((ret == 0) && (buf->uio_resid > 0)) { |
| 297 |
l = buf->uio_resid; |
329 |
l = buf->uio_resid; |
| 298 |
if ((c->smegcnt + l) >= SMEGBUFSZ) panic("resid overflow %d", l); |
330 |
KASSERT( (c->smegcnt + l) < SMEGBUFSZ, ("resid overflow %d", l)); |
| 299 |
uiomove(c->smegbuf + c->smegcnt, l, buf); |
331 |
uiomove(c->smegbuf + c->smegcnt, l, buf); |
| 300 |
c->smegcnt += l; |
332 |
c->smegcnt += l; |
| 301 |
} |
333 |
} |
|
Lines 472-515
Link Here
|
| 472 |
return 0; |
504 |
return 0; |
| 473 |
} |
505 |
} |
| 474 |
|
506 |
|
|
|
507 |
static void |
| 508 |
chn_clearbuf(pcm_channel *c, int length) |
| 509 |
{ |
| 510 |
int i; |
| 511 |
u_int16_t data, *p; |
| 512 |
|
| 513 |
snd_dbuf *b = &c->buffer; |
| 514 |
/* rely on length & DMA_ALIGN_MASK == 0 */ |
| 515 |
length&=DMA_ALIGN_MASK; |
| 516 |
if (c->hwfmt & AFMT_SIGNED) data = 0x00; else data = 0x80; |
| 517 |
if (c->hwfmt & AFMT_16BIT) data <<= 8; else data |= data << 8; |
| 518 |
if (c->hwfmt & AFMT_BIGENDIAN) |
| 519 |
data = ((data >> 8) & 0x00ff) | ((data << 8) & 0xff00); |
| 520 |
for (i = b->fp, p=(u_int16_t*)(b->buf+b->fp) ; i < b->bufsize && length; i += 2, length-=2) |
| 521 |
*p++ = data; |
| 522 |
for (i = 0, p=(u_int16_t*)b->buf; i < b->bufsize && length; i += 2, length-=2) |
| 523 |
*p++ = data; |
| 524 |
|
| 525 |
return; |
| 526 |
} |
| 527 |
|
| 475 |
void |
528 |
void |
| 476 |
chn_resetbuf(pcm_channel *c) |
529 |
chn_resetbuf(pcm_channel *c) |
| 477 |
{ |
530 |
{ |
| 478 |
snd_dbuf *b = &c->buffer; |
531 |
snd_dbuf *b = &c->buffer; |
| 479 |
u_int16_t data, *p; |
|
|
| 480 |
u_int32_t i; |
| 481 |
|
532 |
|
| 482 |
c->smegcnt = 0; |
533 |
c->smegcnt = 0; |
| 483 |
c->buffer.sample_size = 1; |
534 |
c->buffer.sample_size = 1; |
| 484 |
c->buffer.sample_size <<= (c->hwfmt & AFMT_STEREO)? 1 : 0; |
535 |
c->buffer.sample_size <<= (c->hwfmt & AFMT_STEREO)? 1 : 0; |
| 485 |
c->buffer.sample_size <<= (c->hwfmt & AFMT_16BIT)? 1 : 0; |
536 |
c->buffer.sample_size <<= (c->hwfmt & AFMT_16BIT)? 1 : 0; |
| 486 |
/* rely on bufsize & 3 == 0 */ |
|
|
| 487 |
if (c->hwfmt & AFMT_SIGNED) data = 0x00; else data = 0x80; |
| 488 |
if (c->hwfmt & AFMT_16BIT) data <<= 8; else data |= data << 8; |
| 489 |
if (c->hwfmt & AFMT_BIGENDIAN) |
| 490 |
data = ((data >> 8) & 0x00ff) | ((data << 8) & 0xff00); |
| 491 |
for (i = 0, p = (u_int16_t *)b->buf; i < b->bufsize; i += 2) |
| 492 |
*p++ = data; |
| 493 |
b->rp = b->fp = 0; |
537 |
b->rp = b->fp = 0; |
| 494 |
b->dl = b->rl = 0; |
538 |
b->dl = b->rl = 0; |
|
|
539 |
b->fl = b->bufsize; |
| 540 |
chn_clearbuf(c, b->bufsize); |
| 495 |
b->prev_total = b->total = 0; |
541 |
b->prev_total = b->total = 0; |
| 496 |
b->prev_int_count = b->int_count = 0; |
542 |
b->prev_int_count = b->int_count = 0; |
| 497 |
b->first_poll = 1; |
543 |
b->first_poll = 1; |
| 498 |
b->fl = b->bufsize; |
544 |
b->underflow=0; |
| 499 |
} |
545 |
} |
| 500 |
|
546 |
|
| 501 |
void |
547 |
void |
| 502 |
buf_isadma(snd_dbuf *b, int go) |
548 |
buf_isadma(snd_dbuf *b, int go) |
| 503 |
{ |
549 |
{ |
| 504 |
if (ISA_DMA(b)) { |
550 |
if (ISA_DMA(b)) { |
| 505 |
if (go == PCMTRIG_START) isa_dmastart(b->dir | B_RAW, b->buf, |
551 |
if (go == PCMTRIG_START) { |
| 506 |
b->bufsize, b->chan); |
552 |
DEB(printf("buf 0x%p ISA DMA started\n", b)); |
| 507 |
else { |
553 |
isa_dmastart(b->dir | B_RAW, b->buf, |
|
|
554 |
b->bufsize, b->chan); |
| 555 |
} else { |
| 556 |
DEB(printf("buf 0x%p ISA DMA stopped\n", b)); |
| 508 |
isa_dmastop(b->chan); |
557 |
isa_dmastop(b->chan); |
| 509 |
isa_dmadone(b->dir | B_RAW, b->buf, b->bufsize, |
558 |
isa_dmadone(b->dir | B_RAW, b->buf, b->bufsize, |
| 510 |
b->chan); |
559 |
b->chan); |
| 511 |
} |
560 |
} |
| 512 |
} else panic("buf_isadma called on invalid channel"); |
561 |
} else KASSERT(1, ("buf_isadma called on invalid channel")); |
| 513 |
} |
562 |
} |
| 514 |
|
563 |
|
| 515 |
int |
564 |
int |
|
Lines 519-525
Link Here
|
| 519 |
int i = b->dl? isa_dmastatus(b->chan) : b->bufsize; |
568 |
int i = b->dl? isa_dmastatus(b->chan) : b->bufsize; |
| 520 |
if (i < 0) i = 0; |
569 |
if (i < 0) i = 0; |
| 521 |
return b->bufsize - i; |
570 |
return b->bufsize - i; |
| 522 |
} else panic("buf_isadmaptr called on invalid channel"); |
571 |
} else KASSERT(1, ("buf_isadmaptr called on invalid channel")); |
| 523 |
return -1; |
572 |
return -1; |
| 524 |
} |
573 |
} |
| 525 |
|
574 |
|
|
Lines 543-549
Link Here
|
| 543 |
ret = tsleep((caddr_t)b, PRIBIO | PCATCH, "pcmsyn", 1); |
592 |
ret = tsleep((caddr_t)b, PRIBIO | PCATCH, "pcmsyn", 1); |
| 544 |
splx(s); |
593 |
splx(s); |
| 545 |
if (ret == ERESTART || ret == EINTR) { |
594 |
if (ret == ERESTART || ret == EINTR) { |
| 546 |
printf("tsleep returns %d\n", ret); |
595 |
DEB(printf("chn_sync: tsleep returns %d\n", ret)); |
| 547 |
return -1; |
596 |
return -1; |
| 548 |
} |
597 |
} |
| 549 |
} else break; |
598 |
} else break; |
|
Lines 605-622
Link Here
|
| 605 |
DEB(printf("snd_flush c->flags 0x%08x\n", c->flags)); |
654 |
DEB(printf("snd_flush c->flags 0x%08x\n", c->flags)); |
| 606 |
c->flags |= CHN_F_CLOSING; |
655 |
c->flags |= CHN_F_CLOSING; |
| 607 |
if (c->direction != PCMDIR_PLAY) chn_abort(c); |
656 |
if (c->direction != PCMDIR_PLAY) chn_abort(c); |
| 608 |
else while (b->dl) { |
657 |
else if (b->dl) while (!b->underflow) { |
| 609 |
/* still pending output data. */ |
658 |
/* still pending output data. */ |
| 610 |
ret = tsleep((caddr_t)b, PRIBIO | PCATCH, "pcmflu", hz); |
659 |
ret = tsleep((caddr_t)b, PRIBIO | PCATCH, "pcmflu", hz); |
| 611 |
chn_dmaupdate(c); |
660 |
DEB(chn_dmaupdate(c)); |
| 612 |
DEB(printf("snd_sync: now rl : fl %d : %d\n", b->rl, b->fl)); |
661 |
DEB(printf("snd_sync: now rl : fl %d : %d\n", b->rl, b->fl)); |
| 613 |
if (ret == EINTR) { |
662 |
if (ret == EINTR || ret == ERESTART) { |
| 614 |
printf("tsleep returns %d\n", ret); |
663 |
DEB(printf("chn_flush: tsleep returns %d\n", ret)); |
| 615 |
return -1; |
664 |
return -1; |
| 616 |
} |
665 |
} |
| 617 |
if (ret && --count == 0) { |
666 |
if (ret && --count == 0) { |
| 618 |
printf("timeout flushing dbuf_out, cnt 0x%x flags 0x%x\n", |
667 |
DEB(printf("chn_flush: timeout flushing dbuf_out, cnt 0x%x flags 0x%x\n",\ |
| 619 |
b->rl, c->flags); |
668 |
b->rl, c->flags)); |
| 620 |
break; |
669 |
break; |
| 621 |
} |
670 |
} |
| 622 |
} |
671 |
} |
|
Lines 641-651
Link Here
|
| 641 |
if ((c->flags & CHN_F_INIT) && CANCHANGE(c)) { |
690 |
if ((c->flags & CHN_F_INIT) && CANCHANGE(c)) { |
| 642 |
chn_setformat(c, c->format); |
691 |
chn_setformat(c, c->format); |
| 643 |
chn_setspeed(c, c->speed); |
692 |
chn_setspeed(c, c->speed); |
| 644 |
chn_setblocksize(c, c->blocksize); |
693 |
chn_setblocksize(c, (c->flags & CHN_F_HAS_SIZE) ? c->blocksize : 0); |
| 645 |
chn_setvolume(c, (c->volume >> 8) & 0xff, c->volume & 0xff); |
694 |
chn_setvolume(c, (c->volume >> 8) & 0xff, c->volume & 0xff); |
| 646 |
c->flags &= ~CHN_F_INIT; |
695 |
c->flags &= ~CHN_F_INIT; |
| 647 |
return 1; |
696 |
return 1; |
| 648 |
} |
697 |
} |
|
|
698 |
if (CANCHANGE(c) && !(c->flags & CHN_F_HAS_SIZE) ) |
| 699 |
chn_setblocksize(c, 0); /* Apply new block size */ |
| 649 |
return 0; |
700 |
return 0; |
| 650 |
} |
701 |
} |
| 651 |
|
702 |
|
|
Lines 716-725
Link Here
|
| 716 |
c->flags &= ~CHN_F_HAS_SIZE; |
767 |
c->flags &= ~CHN_F_HAS_SIZE; |
| 717 |
if (blksz >= 2) c->flags |= CHN_F_HAS_SIZE; |
768 |
if (blksz >= 2) c->flags |= CHN_F_HAS_SIZE; |
| 718 |
blksz = abs(blksz); |
769 |
blksz = abs(blksz); |
| 719 |
if (blksz < 2) blksz = (c->buffer.sample_size * c->speed) >> 2; |
770 |
if (blksz < 2) blksz = c->buffer.sample_size * (c->speed / 4); /* 1/4 sec */ |
| 720 |
RANGE(blksz, 1024, c->buffer.bufsize / 4); |
771 |
RANGE(blksz, 1024, c->buffer.bufsize / 4); |
| 721 |
blksz &= ~3; |
772 |
blksz &= DMA_ALIGN_MASK; |
| 722 |
c->blocksize = c->setblocksize(c->devinfo, blksz); |
773 |
c->blocksize = c->setblocksize(c->devinfo, blksz)&DMA_ALIGN_MASK; |
| 723 |
return c->blocksize; |
774 |
return c->blocksize; |
| 724 |
} |
775 |
} |
| 725 |
c->blocksize = blksz; |
776 |
c->blocksize = blksz; |
|
Lines 736-742
Link Here
|
| 736 |
int |
787 |
int |
| 737 |
chn_getptr(pcm_channel *c) |
788 |
chn_getptr(pcm_channel *c) |
| 738 |
{ |
789 |
{ |
| 739 |
return c->getptr(c->devinfo); |
790 |
int hwptr; |
|
|
791 |
int a = (1 << c->align) - 1; |
| 792 |
|
| 793 |
hwptr=c->getptr(c->devinfo); |
| 794 |
/* don't allow unaligned values in the hwa ptr */ |
| 795 |
hwptr &= ~a ; /* Apply channel align mask */ |
| 796 |
hwptr &= DMA_ALIGN_MASK; /* Apply DMA align mask */ |
| 797 |
return hwptr; |
| 740 |
} |
798 |
} |
| 741 |
|
799 |
|
| 742 |
pcmchan_caps * |
800 |
pcmchan_caps * |