svn commit: r297911 - head/sys/arm/broadcom/bcm2835
Oleksandr Tymoshenko
gonzo at FreeBSD.org
Wed Apr 13 05:28:28 UTC 2016
Author: gonzo
Date: Wed Apr 13 05:28:27 2016
New Revision: 297911
URL: https://svnweb.freebsd.org/changeset/base/297911
Log:
Multiple fixes in VCHI audio driver:
- Pre-buffer audio data to VideoCore so there are no audible glitches when
driver is too late to provide samples
- Start actual playback when there is some prebuffered audio,
it fixes audible noisy click in the beginning of playback
- Use #defines instead of hardcoded values where appropriate
- Fix copy-pasted comment
PR: 208678
Modified:
head/sys/arm/broadcom/bcm2835/bcm2835_audio.c
Modified: head/sys/arm/broadcom/bcm2835/bcm2835_audio.c
==============================================================================
--- head/sys/arm/broadcom/bcm2835/bcm2835_audio.c Wed Apr 13 05:19:16 2016 (r297910)
+++ head/sys/arm/broadcom/bcm2835/bcm2835_audio.c Wed Apr 13 05:28:27 2016 (r297911)
@@ -46,6 +46,7 @@ SND_DECLARE_FILE("$FreeBSD$");
#define VCHIQ_AUDIO_PACKET_SIZE 4000
#define VCHIQ_AUDIO_BUFFER_SIZE 128000
+#define VCHIQ_AUDIO_PREBUFFER 10 /* Number of pre-buffered audio messages */
#define VCHIQ_AUDIO_MAX_VOLUME
/* volume in terms of 0.01dB */
@@ -91,6 +92,7 @@ struct bcm2835_audio_chinfo {
uint32_t free_buffer;
uint32_t buffered_ptr;
int playback_state;
+ int prebuffered;
};
struct bcm2835_audio_info {
@@ -170,11 +172,10 @@ bcm2835_audio_callback(void *param, cons
ch->complete_pos = (ch->complete_pos + count) % sndbuf_getsize(ch->buffer);
ch->free_buffer += count;
+ chn_intr(sc->pch.channel);
- if (perr || ch->free_buffer >= VCHIQ_AUDIO_PACKET_SIZE) {
- chn_intr(ch->channel);
+ if (perr || ch->free_buffer >= VCHIQ_AUDIO_PACKET_SIZE)
cv_signal(&sc->data_cv);
- }
} else
printf("%s: unknown m.type: %d\n", __func__, m.type);
}
@@ -244,6 +245,7 @@ bcm2835_audio_reset_channel(struct bcm28
ch->playback_state = 0;
ch->buffered_ptr = 0;
ch->complete_pos = 0;
+ ch->prebuffered = 0;
sndbuf_reset(ch->buffer);
}
@@ -478,21 +480,29 @@ bcm2835_audio_worker(void *data)
if (sc->unloading)
break;
- if ((ch->playback_state == PLAYBACK_PLAYING) &&
- (vchiq_unbuffered_bytes(ch) >= VCHIQ_AUDIO_PACKET_SIZE)
- && (ch->free_buffer >= VCHIQ_AUDIO_PACKET_SIZE)) {
- bcm2835_audio_write_samples(ch);
- } else {
- if (ch->playback_state == PLAYBACK_STOPPING) {
- bcm2835_audio_reset_channel(&sc->pch);
- ch->playback_state = PLAYBACK_IDLE;
- }
-
+ if (ch->playback_state == PLAYBACK_IDLE) {
cv_wait_sig(&sc->data_cv, &sc->data_lock);
+ continue;
+ }
+
+ if (ch->playback_state == PLAYBACK_STOPPING) {
+ bcm2835_audio_reset_channel(&sc->pch);
+ ch->playback_state = PLAYBACK_IDLE;
+ continue;
+ }
+
+ if (ch->free_buffer < vchiq_unbuffered_bytes(ch)) {
+ cv_timedwait_sig(&sc->data_cv, &sc->data_lock, 10);
+ continue;
+ }
+
+
+ bcm2835_audio_write_samples(ch);
- if (ch->playback_state == PLAYBACK_STARTING) {
- /* Give it initial kick */
- chn_intr(sc->pch.channel);
+ if (ch->playback_state == PLAYBACK_STARTING) {
+ ch->prebuffered++;
+ if (ch->prebuffered == VCHIQ_AUDIO_PREBUFFER) {
+ bcm2835_audio_start(ch);
ch->playback_state = PLAYBACK_PLAYING;
}
}
@@ -514,7 +524,7 @@ bcm2835_audio_create_worker(struct bcm28
}
/* -------------------------------------------------------------------- */
-/* channel interface for ESS18xx */
+/* channel interface for VCHI audio */
static void *
bcmchan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, struct pcm_channel *c, int dir)
{
@@ -612,7 +622,6 @@ bcmchan_trigger(kobj_t obj, void *data,
switch (go) {
case PCMTRIG_START:
- bcm2835_audio_start(ch);
ch->playback_state = PLAYBACK_STARTING;
/* wakeup worker thread */
cv_signal(&sc->data_cv);
@@ -620,7 +629,7 @@ bcmchan_trigger(kobj_t obj, void *data,
case PCMTRIG_STOP:
case PCMTRIG_ABORT:
- ch->playback_state = 1;
+ ch->playback_state = PLAYBACK_STOPPING;
bcm2835_audio_stop(ch);
break;
More information about the svn-src-all
mailing list