patch-2.3.13 linux/drivers/sbus/audio/cs4231.c

Next file: linux/drivers/sbus/char/bpp.c
Previous file: linux/drivers/sbus/audio/audio.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.3.12/linux/drivers/sbus/audio/cs4231.c linux/drivers/sbus/audio/cs4231.c
@@ -1421,7 +1421,7 @@
     status += 2;
   }
 
-  sparcaudio_input_done(drv, 1);
+  sparcaudio_input_done(drv, status);
 
   return 1;
 }
@@ -1484,26 +1484,23 @@
   cs4231_chip->perchip_info.play.active = 1;
   cs4231_chip->playing_count = 0;
 
+  cs4231_playintr(drv);
   if ((cs4231_chip->regs->dmacsr & APC_PPAUSE) || 
       !(cs4231_chip->regs->dmacsr & APC_PDMA_READY)) {
-    cs4231_chip->regs->dmacsr &= ~APC_XINT_PLAY;
-    cs4231_chip->regs->dmacsr &= ~APC_PPAUSE;
-    
-    cs4231_playintr(drv);
-
-    cs4231_chip->regs->dmacsr |= APC_PLAY_SETUP;
+    cs4231_chip->regs->dmacsr &= ~(APC_XINT_PLAY | APC_PPAUSE);
+    cs4231_chip->regs->dmacsr |= APC_GENL_INT | APC_XINT_ENA | APC_XINT_PLAY
+      | APC_XINT_GENL | APC_XINT_PENA | APC_PDMA_READY;
     cs4231_enable_play(drv);
-
+  
     cs4231_ready(drv);
-  } else 
-    cs4231_playintr(drv);
+  }
 }
 
 #ifdef EB4231_SUPPORT
 static void eb4231_stop_output(struct sparcaudio_driver *drv)
 {
   struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
-  int dcsr;
+  unsigned int dcsr;
 
   dprintk(("eb4231_stop_output: dcsr 0x%x dacr 0x%x dbcr %d\n",
            readl(&cs4231_chip->eb2p->dcsr),
@@ -1525,6 +1522,7 @@
 
   /* Else subsequent speed setting changes are ignored by the chip. */
   cs4231_disable_play(drv);
+  cs4231_chip->perchip_info.play.active = 0;
 }
 #endif
 
@@ -1547,9 +1545,14 @@
     cs4231_chip->output_next_dma_handle = 0;
     cs4231_chip->output_next_dma_size = 0;
   }
-#if 0 /* Not safe without shutting off the DMA controller as well. -DaveM */
+#if 1 /* Not safe without shutting off the DMA controller as well. -DaveM */
   /* Else subsequent speed setting changes are ignored by the chip. */
+  cs4231_chip->regs->dmacsr &= ~(APC_GENL_INT | APC_XINT_ENA | APC_XINT_PLAY 
+                                 | APC_XINT_GENL | APC_PDMA_READY 
+                                 | APC_XINT_PENA | APC_PPAUSE );
+  printk("in cs4231_stop_output: 0x%x\n", cs4231_chip->regs->dmacsr);
   cs4231_disable_play(drv);
+  cs4231_chip->perchip_info.play.active = 0;
 #endif
 }
 
@@ -1635,6 +1638,68 @@
   cs4231_pollinput(drv);
 }
 
+#ifdef EB4231_SUPPORT
+static void eb4231_start_input(struct sparcaudio_driver *drv, __u8 * buffer, 
+                               unsigned long count)
+{
+  struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
+  unsigned int dcsr;
+
+  cs4231_chip->input_ptr = buffer;
+  cs4231_chip->input_size = count;
+
+  if (cs4231_chip->perchip_info.record.active || 
+      (cs4231_chip->perchip_info.record.pause))
+    return;
+
+  cs4231_ready(drv);
+
+  cs4231_chip->perchip_info.record.active = 1;
+  cs4231_chip->recording_count = 0;
+
+  dcsr = readl(&cs4231_chip->eb2c->dcsr);
+  if (!(dcsr & EBUS_DCSR_EN_DMA)) {
+    writel(EBUS_DCSR_RESET, &(cs4231_chip->eb2c->dcsr));
+    writel(EBUS_DCSR_BURST_SZ_16, &(cs4231_chip->eb2c->dcsr));
+
+    eb4231_recintr(drv);
+
+    writel(EBUS_DCSR_BURST_SZ_16 |
+           (EBUS_DCSR_EN_DMA | EBUS_DCSR_INT_EN | EBUS_DCSR_EN_CNT | EBUS_DCSR_EN_NEXT),
+           &(cs4231_chip->eb2c->dcsr));
+
+    cs4231_enable_rec(drv);
+    cs4231_ready(drv);
+  } else
+    eb4231_recintr(drv);
+}
+
+static void eb4231_stop_input(struct sparcaudio_driver *drv)
+{
+  struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
+  unsigned int dcsr;
+
+  cs4231_chip->perchip_info.record.active = 0;
+
+  cs4231_chip->input_ptr = NULL;
+  cs4231_chip->input_size = 0;
+  if (cs4231_chip->input_dma_handle) {
+    cs4231_chip->input_dma_handle = 0;
+    cs4231_chip->input_dma_size = 0;
+  }
+  if (cs4231_chip->input_next_dma_handle) {
+    cs4231_chip->input_next_dma_handle = 0;
+    cs4231_chip->input_next_dma_size = 0;
+  }
+
+  dcsr = readl(&(cs4231_chip->eb2c->dcsr));
+  if (dcsr & EBUS_DCSR_EN_DMA)
+    writel(dcsr & ~EBUS_DCSR_EN_DMA, &(cs4231_chip->eb2c->dcsr));
+
+  cs4231_disable_rec(drv);
+}
+#endif
+
 static int cs4231_set_output_pause(struct sparcaudio_driver *drv, int value)
 {
         struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
@@ -1763,13 +1828,25 @@
   struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
   int dummy;
   
-  /* Read status. */
-  dummy = readl(&cs4231_chip->eb2c->dcsr);
+  /* Clear the interrupt. */
+  dummy = readl(&(cs4231_chip->eb2c->dcsr));
+  writel(dummy, &(cs4231_chip->eb2c->dcsr));
 
-  cs4231_chip->perchip_info.record.samples += 
-          cs4231_length_to_samplecount(&(cs4231_chip->perchip_info.record), 
-                                       cs4231_chip->reclen);
-  eb4231_recintr(drv);
+  if ((dummy & EBUS_DCSR_TC) != 0
+      /*&& (dummy & EBUS_DCSR_A_LOADED) != 0*/) {
+    cs4231_chip->perchip_info.record.samples += 
+      cs4231_length_to_samplecount(&(cs4231_chip->perchip_info.record), 
+                                   cs4231_chip->reclen);
+    eb4231_recintr(drv);
+  }
+
+  if ((dummy & EBUS_DCSR_A_LOADED) == 0) {
+    cs4231_chip->perchip_info.record.active = 0;
+    eb4231_recintr(drv);
+#if 1
+    eb4231_getsamplecount(drv, cs4231_chip->reclen, 1);
+#endif
+  }
 }
 
 /* ebus audio play interrupt handler. */
@@ -1797,7 +1874,6 @@
   }
 
   if((dummy & EBUS_DCSR_A_LOADED) == 0) {
-    cs4231_chip->perchip_info.play.active = 0;
     eb4231_playintr(drv);
 
     eb4231_getsamplecount(drv, cs4231_chip->playlen, 0);
@@ -1822,13 +1898,11 @@
    * if anything since we may be doing shared interrupts 
    */
 
-  if (dummy & APC_PLAY_INT) {
-    if (dummy & APC_XINT_PNVA) {
+  if (dummy & (APC_PLAY_INT|APC_XINT_PNVA|APC_XINT_PLAY|APC_XINT_EMPT|APC_XINT_PEMP)) {
       cs4231_chip->perchip_info.play.samples += 
 	cs4231_length_to_samplecount(&(cs4231_chip->perchip_info.play), 
 				     cs4231_chip->playlen); 
       cs4231_playintr(drv);
-    } 
     /* Any other conditions we need worry about? */
   }
 
@@ -1853,6 +1927,7 @@
   }
 
   if (dummy & APC_XINT_EMPT) {
+#if 0 /* Call to stop_output from midlevel will get this */
     if (!cs4231_chip->output_next_dma_handle) {
       cs4231_chip->regs->dmacsr |= (APC_PPAUSE);
       cs4231_disable_play(drv);
@@ -1860,6 +1935,7 @@
     }
     cs4231_chip->perchip_info.play.active = 0;
     cs4231_playintr(drv);
+#endif
 
     cs4231_getsamplecount(drv, cs4231_chip->playlen, 0);
   }
@@ -1937,8 +2013,8 @@
 	cs4231_ioctl,
 	eb4231_start_output,
 	eb4231_stop_output,
-	cs4231_start_input,
-        cs4231_stop_input,
+	eb4231_start_input,
+        eb4231_stop_input,
 	cs4231_audio_getdev,
         cs4231_set_output_volume,
         cs4231_get_output_volume,

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)