qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Andrzej Zaborowski <balrogg@gmail.com>
To: qemu-devel@nongnu.org
Subject: [Qemu-devel] [4969] Correct audio api usage in OMAP EAC (spotted by malc).
Date: Tue, 29 Jul 2008 17:29:42 +0000	[thread overview]
Message-ID: <E1KNt14-0000Vr-Ad@cvs.savannah.gnu.org> (raw)

Revision: 4969
          http://svn.sv.gnu.org/viewvc/?view=rev&root=qemu&revision=4969
Author:   balrog
Date:     2008-07-29 17:29:41 +0000 (Tue, 29 Jul 2008)

Log Message:
-----------
Correct audio api usage in OMAP EAC (spotted by malc).

This is to improve the usage of audio API thanks to explanation from malc.
Functionally may not be better.

Modified Paths:
--------------
    trunk/hw/omap2.c

Modified: trunk/hw/omap2.c
===================================================================
--- trunk/hw/omap2.c	2008-07-29 14:19:16 UTC (rev 4968)
+++ trunk/hw/omap2.c	2008-07-29 17:29:41 UTC (rev 4969)
@@ -1447,6 +1447,7 @@
 
 #define EAC_BUF_LEN 1024
         uint32_t rxbuf[EAC_BUF_LEN];
+        int rxoff;
         int rxlen;
         int rxavail;
         uint32_t txbuf[EAC_BUF_LEN];
@@ -1478,7 +1479,7 @@
 
 static inline void omap_eac_in_dmarequest_update(struct omap_eac_s *s)
 {
-    qemu_set_irq(s->codec.rxdrq, s->codec.rxavail + s->codec.rxlen &&
+    qemu_set_irq(s->codec.rxdrq, (s->codec.rxavail || s->codec.rxlen) &&
                     ((s->codec.config[1] >> 12) & 1));		/* DMAREN */
 }
 
@@ -1490,26 +1491,61 @@
 
 static inline void omap_eac_in_refill(struct omap_eac_s *s)
 {
-    int left, start = 0;
+    int left = MIN(EAC_BUF_LEN - s->codec.rxlen, s->codec.rxavail) << 2;
+    int start = ((s->codec.rxoff + s->codec.rxlen) & (EAC_BUF_LEN - 1)) << 2;
+    int leftwrap = MIN(left, (EAC_BUF_LEN << 2) - start);
+    int recv = 1;
+    uint8_t *buf = (uint8_t *) s->codec.rxbuf + start;
 
-    s->codec.rxlen = MIN(s->codec.rxavail, EAC_BUF_LEN);
-    s->codec.rxavail -= s->codec.rxlen;
+    left -= leftwrap;
+    start = 0;
+    while (leftwrap && (recv = AUD_read(s->codec.in_voice, buf + start,
+                                    leftwrap)) > 0) {	/* Be defensive */
+        start += recv;
+        leftwrap -= recv;
+    }
+    if (recv <= 0)
+        s->codec.rxavail = 0;
+    else
+        s->codec.rxavail -= start >> 2;
+    s->codec.rxlen += start >> 2;
 
-    for (left = s->codec.rxlen << 2; left; start = (EAC_BUF_LEN << 2) - left)
-        left -= AUD_read(s->codec.in_voice,
-                        (uint8_t *) s->codec.rxbuf + start, left);
+    if (recv > 0 && left > 0) {
+        start = 0;
+        while (left && (recv = AUD_read(s->codec.in_voice,
+                                        (uint8_t *) s->codec.rxbuf + start,
+                                        left)) > 0) {	/* Be defensive */
+            start += recv;
+            left -= recv;
+        }
+        if (recv <= 0)
+            s->codec.rxavail = 0;
+        else
+            s->codec.rxavail -= start >> 2;
+        s->codec.rxlen += start >> 2;
+    }
 }
 
 static inline void omap_eac_out_empty(struct omap_eac_s *s)
 {
-    int left, start = 0;
+    int left = s->codec.txlen << 2;
+    int start = 0;
+    int sent = 1;
 
-    for (left = s->codec.txlen << 2; left; start = (s->codec.txlen << 2) - left)
-        left -= AUD_write(s->codec.out_voice,
-                        (uint8_t *) s->codec.txbuf + start, left);
+    while (left && (sent = AUD_write(s->codec.out_voice,
+                                    (uint8_t *) s->codec.txbuf + start,
+                                    left)) > 0) {	/* Be defensive */
+        start += sent;
+        left -= sent;
+    }
 
-    s->codec.txavail -= s->codec.txlen;
-    s->codec.txlen = 0;
+    if (!sent) {
+        s->codec.txavail = 0;
+        omap_eac_out_dmarequest_update(s);
+    }
+
+    if (start)
+        s->codec.txlen = 0;
 }
 
 static void omap_eac_in_cb(void *opaque, int avail_b)
@@ -1517,8 +1553,9 @@
     struct omap_eac_s *s = (struct omap_eac_s *) opaque;
 
     s->codec.rxavail = avail_b >> 2;
+    omap_eac_in_refill(s);
+    /* TODO: possibly discard current buffer if overrun */
     omap_eac_in_dmarequest_update(s);
-    /* TODO: possibly discard current buffer if overrun */
 }
 
 static void omap_eac_out_cb(void *opaque, int free_b)
@@ -1526,10 +1563,10 @@
     struct omap_eac_s *s = (struct omap_eac_s *) opaque;
 
     s->codec.txavail = free_b >> 2;
-    if (s->codec.txlen > s->codec.txavail)
-        s->codec.txlen = s->codec.txavail;
-    omap_eac_out_empty(s);
-    omap_eac_out_dmarequest_update(s);
+    if (s->codec.txlen)
+        omap_eac_out_empty(s);
+    else
+        omap_eac_out_dmarequest_update(s);
 }
 
 static void omap_eac_enable_update(struct omap_eac_s *s)
@@ -1591,7 +1628,9 @@
 {
     audsettings_t fmt;
 
-    omap_eac_out_empty(s);
+    /* The hardware buffers at most one sample */
+    if (s->codec.rxlen)
+        s->codec.rxlen = 1;
 
     if (s->codec.in_voice) {
         AUD_set_active_in(s->codec.in_voice, 0);
@@ -1599,10 +1638,14 @@
         s->codec.in_voice = 0;
     }
     if (s->codec.out_voice) {
+        omap_eac_out_empty(s);
         AUD_set_active_out(s->codec.out_voice, 0);
         AUD_close_out(&s->codec.card, s->codec.out_voice);
         s->codec.out_voice = 0;
+        s->codec.txavail = 0;
     }
+    /* Discard what couldn't be written */
+    s->codec.txlen = 0;
 
     omap_eac_enable_update(s);
     if (!s->codec.enable)
@@ -1663,6 +1706,7 @@
     s->codec.config[1] = 0x0000;
     s->codec.config[2] = 0x0007;
     s->codec.config[3] = 0x1ffc;
+    s->codec.rxoff = 0;
     s->codec.rxlen = 0;
     s->codec.txlen = 0;
     s->codec.rxavail = 0;
@@ -1676,6 +1720,7 @@
 {
     struct omap_eac_s *s = (struct omap_eac_s *) opaque;
     int offset = addr - s->base;
+    uint32_t ret;
 
     switch (offset) {
     case 0x000:	/* CPCFR1 */
@@ -1739,16 +1784,19 @@
         /* This should be write-only?  Docs list it as read-only.  */
         return 0x0000;
     case 0x0b8:	/* ADRDR */
-        if (likely(s->codec.rxlen > 1))
-            return s->codec.rxbuf[EAC_BUF_LEN - s->codec.rxlen --];
-        else if (s->codec.rxlen) {
+        if (likely(s->codec.rxlen > 1)) {
+            ret = s->codec.rxbuf[s->codec.rxoff ++];
+            s->codec.rxlen --;
+            s->codec.rxoff &= EAC_BUF_LEN - 1;
+            return ret;
+        } else if (s->codec.rxlen) {
+            ret = s->codec.rxbuf[s->codec.rxoff ++];
+            s->codec.rxlen --;
+            s->codec.rxoff &= EAC_BUF_LEN - 1;
             if (s->codec.rxavail)
                 omap_eac_in_refill(s);
-            else {
-                s->codec.rxlen = 0;
-                omap_eac_in_dmarequest_update(s);
-            }
-            return s->codec.rxbuf[EAC_BUF_LEN - 1];
+            omap_eac_in_dmarequest_update(s);
+            return ret;
         }
         return 0x0000;
     case 0x0bc:	/* AGCFR */
@@ -1881,8 +1929,8 @@
                                 s->codec.txlen == s->codec.txavail)) {
             if (s->codec.txavail)
                 omap_eac_out_empty(s);
-            else
-                s->codec.txlen = 0;
+            /* Discard what couldn't be written */
+            s->codec.txlen = 0;
         }
         break;
 

                 reply	other threads:[~2008-07-29 17:29 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=E1KNt14-0000Vr-Ad@cvs.savannah.gnu.org \
    --to=balrogg@gmail.com \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).