summaryrefslogtreecommitdiff
path: root/sound/pci/cs46xx/imgs/cwcdma.asp
diff options
context:
space:
mode:
Diffstat (limited to 'sound/pci/cs46xx/imgs/cwcdma.asp')
-rw-r--r--sound/pci/cs46xx/imgs/cwcdma.asp170
1 files changed, 170 insertions, 0 deletions
diff --git a/sound/pci/cs46xx/imgs/cwcdma.asp b/sound/pci/cs46xx/imgs/cwcdma.asp
new file mode 100644
index 00000000..a65e1193
--- /dev/null
+++ b/sound/pci/cs46xx/imgs/cwcdma.asp
@@ -0,0 +1,170 @@
+//
+// Copyright(c) by Benny Sjostrand (benny@hostmobility.com)
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+
+
+//
+// This code runs inside the DSP (cs4610, cs4612, cs4624, or cs4630),
+// to compile it you need a tool named SPASM 3.0 and DSP code owned by
+// Cirrus Logic(R). The SPASM program will generate a object file (cwcdma.osp),
+// the "ospparser" tool will genereate the cwcdma.h file it's included from
+// the cs46xx_lib.c file.
+//
+//
+// The purpose of this code is very simple: make it possible to tranfser
+// the samples 'as they are' with no alteration from a PCMreader
+// SCB (DMA from host) to any other SCB. This is useful for AC3 through SPDIF.
+// SRC (source rate converters) task always alters the samples in somehow,
+// however it's from 48khz -> 48khz.
+// The alterations are not audible, but AC3 wont work.
+//
+// ...
+// |
+// +---------------+
+// | AsynchFGTxSCB |
+// +---------------+
+// |
+// subListPtr
+// |
+// +--------------+
+// | DMAReader |
+// +--------------+
+// |
+// subListPtr
+// |
+// +-------------+
+// | PCMReader |
+// +-------------+
+// (DMA from host)
+//
+
+struct dmaSCB
+ {
+ long dma_reserved1[3];
+
+ short dma_reserved2:dma_outBufPtr;
+
+ short dma_unused1:dma_unused2;
+
+ long dma_reserved3[4];
+
+ short dma_subListPtr:dma_nextSCB;
+ short dma_SPBptr:dma_entryPoint;
+
+ long dma_strmRsConfig;
+ long dma_strmBufPtr;
+
+ long dma_reserved4;
+
+ VolumeControl s2m_volume;
+ };
+
+#export DMAReader
+void DMAReader()
+{
+ execChild();
+ r2 = r0->dma_subListPtr;
+ r1 = r0->nextSCB;
+
+ rsConfig01 = r2->strmRsConfig;
+ // Load rsConfig for input buffer
+
+ rsDMA01 = r2->basicReq.daw, , tb = Z(0 - rf);
+ // Load rsDMA in case input buffer is a DMA buffer Test to see if there is any data to transfer
+
+ if (tb) goto execSibling_2ind1 after {
+ r5 = rf + (-1);
+ r6 = r1->dma_entryPoint; // r6 = entry point of sibling task
+ r1 = r1->dma_SPBptr, // r1 = pointer to sibling task's SPB
+ , ind = r6; // Load entry point of sibling task
+ }
+
+ rsConfig23 = r0->dma_strmRsConfig;
+ // Load rsConfig for output buffer (never a DMA buffer)
+
+ r4 = r0->dma_outBufPtr;
+
+ rsa0 = r2->strmBufPtr;
+ // rsa0 = input buffer pointer
+
+ for (i = r5; i >= 0; --i)
+ after {
+ rsa2 = r4;
+ // rsa2 = output buffer pointer
+
+ nop;
+ nop;
+ }
+ //*****************************
+ // TODO: cycles to this point *
+ //*****************************
+ {
+ acc0 = (rsd0 = *rsa0++1);
+ // get sample
+
+ nop; // Those "nop"'s are really uggly, but there's
+ nop; // something with DSP's pipelines which I don't
+ nop; // understand, resulting this code to fail without
+ // having those "nop"'s (Benny)
+
+ rsa0?reqDMA = r2;
+ // Trigger DMA transfer on input stream,
+ // if needed to replenish input buffer
+
+ nop;
+ // Yet another magic "nop" to make stuff work
+
+ ,,r98 = acc0 $+>> 0;
+ // store sample in ALU
+
+ nop;
+ // latency on load register.
+ // (this one is understandable)
+
+ *rsa2++1 = r98;
+ // store sample in output buffer
+
+ nop; // The same story
+ nop; // as above again ...
+ nop;
+ }
+ // TODO: cycles per loop iteration
+
+ r2->strmBufPtr = rsa0,, ;
+ // Update the modified buffer pointers
+
+ r4 = rsa2;
+ // Load output pointer position into r4
+
+ r2 = r0->nextSCB;
+ // Sibling task
+
+ goto execSibling_2ind1 // takes 6 cycles
+ after {
+ r98 = r2->thisSPB:entryPoint;
+ // Load child routine entry and data address
+
+ r1 = r9;
+ // r9 is r2->thisSPB
+
+ r0->dma_outBufPtr = r4,,
+ // Store updated output buffer pointer
+
+ ind = r8;
+ // r8 is r2->entryPoint
+ }
+}