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;
 
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to