r2283 - trunk/src/host/qemu-neo1973/hw

andrew at sita.openmoko.org andrew at sita.openmoko.org
Sun Jun 17 03:19:49 CEST 2007


Author: andrew
Date: 2007-06-17 03:19:47 +0200 (Sun, 17 Jun 2007)
New Revision: 2283

Modified:
   trunk/src/host/qemu-neo1973/hw/s3c2410.c
   trunk/src/host/qemu-neo1973/hw/wm8753.c
Log:
Rewrite DMA queuing.  Enhance buffering of audio data in WM8753.


Modified: trunk/src/host/qemu-neo1973/hw/s3c2410.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/s3c2410.c	2007-06-16 15:23:39 UTC (rev 2282)
+++ trunk/src/host/qemu-neo1973/hw/s3c2410.c	2007-06-17 01:19:47 UTC (rev 2283)
@@ -696,7 +696,7 @@
     } ch[S3C_DMA_CH_N];
 };
 
-static void s3c_dma_ch_run(struct s3c_dma_state_s *s,
+static inline void s3c_dma_ch_run(struct s3c_dma_state_s *s,
                 struct s3c_dma_ch_state_s *ch)
 {
     int width, burst, t;
@@ -704,12 +704,12 @@
     width = 1 << ((ch->con >> 20) & 3);				/* DSZ */
     burst = (ch->con & (1 << 28)) ? 4 : 1;			/* TSZ */
 
-    while (!ch->running && ch->req && (ch->mask & (1 << 1))) {	/* ON_OFF */
+    while (!ch->running && ch->curr_tc > 0 && ch->req &&
+                    (ch->mask & (1 << 1))) {		/* ON_OFF */
         if (width > sizeof(buffer)) {
             printf("%s: wrong access width\n", __FUNCTION__);
             return;
         }
-        ch->curr_tc = ch->con & 0xfffff;			/* TC */
         ch->running = 1;
         while (ch->curr_tc --) {
             for (t = 0; t < burst; t ++) {
@@ -726,24 +726,35 @@
                 break;
         }
         ch->running = 0;
-        if (!ch->curr_tc && (ch->con & (1 << 29)))		/* INT */
-            qemu_irq_raise(ch->intr);
 
-        if (ch->con & (1 << 22)) {				/* RELOAD */
-            if (!(ch->con & (1 << 23))) {			/* SWHW_SEL */
-                printf("%s: auto-reload software controlled transfer\n",
-                                __FUNCTION__);
+        if (!(ch->con & (1 << 23))) {				/* SWHW_SEL */
+            ch->req = 0;
+        }
+
+        if (ch->curr_tc <= 0) {
+            if (ch->con & (1 << 22))				/* RELOAD */
+                ch->mask &= ~(1 << 1);				/* ON_OFF */
+            else {
+                if (!(ch->con & (1 << 23))) {			/* SWHW_SEL */
+                    printf("%s: auto-reload software controlled transfer\n",
+                                    __FUNCTION__);
+                    break;
+                }
+                ch->csrc = ch->isrc;				/* S_ADDR */
+                ch->cdst = ch->idst;				/* D_ADDR */
+                ch->curr_tc = ch->con & 0xfffff;		/* TC */
+                ch->con |= 1 << 22;				/* ON_OFF */
+            }
+
+            if (ch->con & (1 << 31))				/* DMD_HS */
+                ch->req = 0;
+
+            if (ch->con & (1 << 29)) {				/* INT */
+                qemu_irq_raise(ch->intr);
+                /* Give the system a chance to respond.  */
                 break;
             }
-            ch->csrc = ch->isrc;				/* S_ADDR */
-            ch->cdst = ch->idst;				/* D_ADDR */
-            ch->curr_tc = ch->con & 0xfffff;			/* TC */
         }
-        if (!(ch->con & (1 << 23))) {				/* SWHW_SEL */
-            ch->req = 0;
-        }
-        if (!ch->curr_tc && !(ch->con & (1 << 22)))		/* RELOAD */
-            ch->mask &= ~(1 << 1);				/* ON_OFF */
     }
 }
 
@@ -839,22 +850,27 @@
         ch->con = value;
         break;
     case S3C_DISRC:
-        ch->csrc = ch->isrc = value;
+        ch->isrc = value;
         break;
     case S3C_DISRCC:
         ch->isrcc = value;
         break;
     case S3C_DIDST:
-        ch->cdst = ch->idst = value;
+        ch->idst = value;
         break;
     case S3C_DIDSTC:
         ch->idstc = value;
         break;
     case S3C_DMASKTRIG:
+        if (~ch->mask & value & (1 << 1)) {			/* ON_OFF */
+            ch->curr_tc = ch->con & 0xfffff;			/* TC */
+            ch->csrc = ch->isrc;				/* S_ADDR */
+            ch->cdst = ch->idst;				/* D_ADDR */
+        }
+
         ch->mask = value;
         if (value & (1 << 2)) {					/* STOP */
-            ch->curr_tc = 0;
-            ch->mask &= ~(1 << 1);				/* ON_OFF */
+            ch->mask &= ~(3 << 1);				/* ON_OFF */
         } else if (!(ch->con & (1 << 23))) {			/* SWHW_SEL */
             ch->req = value & 1;				/* SW_TRIG */
             s3c_dma_ch_run(s, ch);

Modified: trunk/src/host/qemu-neo1973/hw/wm8753.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/wm8753.c	2007-06-16 15:23:39 UTC (rev 2282)
+++ trunk/src/host/qemu-neo1973/hw/wm8753.c	2007-06-17 01:19:47 UTC (rev 2283)
@@ -74,10 +74,10 @@
 
 static inline void wm8753_out_flush(struct wm8753_s *s)
 {
-    int sent;
-    if (!s->idx_out)
-        return;
-    sent = AUD_write(*s->out[0], s->data_out, s->idx_out);
+    int sent = 0;
+    while (sent < s->idx_out)
+        sent += AUD_write(*s->out[0], s->data_out + sent, s->idx_out - sent)
+                ?: s->idx_out;
     s->idx_out = 0;
 }
 
@@ -91,10 +91,14 @@
 static void wm8753_audio_out_cb(void *opaque, int free_b)
 {
     struct wm8753_s *s = (struct wm8753_s *) opaque;
-    wm8753_out_flush(s);
+    if (s->idx_out >= free_b) {
+        s->idx_out = free_b;
+        s->req_out = 0;
+        wm8753_out_flush(s);
+    } else
+        s->req_out = free_b - s->idx_out;
 
-    s->req_out = free_b;
-    s->data_req(s->opaque, free_b >> 2, s->req_in >> 2);
+    s->data_req(s->opaque, s->req_out >> 2, s->req_in >> 2);
 }
 
 struct wm_rate_s {





More information about the commitlog mailing list