tree-wide: fix assorted typos all over the place
[linux-2.6.git] / sound / pci / cs46xx / imgs / cwcdma.asp
1 // 
2 //  Copyright(c) by Benny Sjostrand (benny@hostmobility.com)
3 //
4 //  This program is free software; you can redistribute it and/or modify
5 //  it under the terms of the GNU General Public License as published by
6 //  the Free Software Foundation; either version 2 of the License, or
7 //  (at your option) any later version.
8 //
9 //  This program is distributed in the hope that it will be useful,
10 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
11 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 //  GNU General Public License for more details.
13 //
14 //  You should have received a copy of the GNU General Public License
15 //  along with this program; if not, write to the Free Software
16 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
17 //
18
19
20 //
21 // This code runs inside the DSP (cs4610, cs4612, cs4624, or cs4630),
22 // to compile it you need a tool named SPASM 3.0 and DSP code owned by 
23 // Cirrus Logic(R). The SPASM program will generate a object file (cwcdma.osp),
24 // the "ospparser"  tool will genereate the cwcdma.h file it's included from
25 // the cs46xx_lib.c file.
26 //
27 //
28 // The purpose of this code is very simple: make it possible to tranfser
29 // the samples 'as they are' with no alteration from a PCMreader
30 // SCB (DMA from host) to any other SCB. This is useful for AC3 through SPDIF.
31 // SRC (source rate converters) task always alters the samples in somehow,
32 // however it's from 48khz -> 48khz.
33 // The alterations are not audible, but AC3 wont work. 
34 //
35 //        ...
36 //         |
37 // +---------------+
38 // | AsynchFGTxSCB |
39 // +---------------+
40 //        |
41 //    subListPtr
42 //        |
43 // +--------------+
44 // |   DMAReader  |
45 // +--------------+
46 //        |
47 //    subListPtr
48 //        |
49 // +-------------+
50 // | PCMReader   |
51 // +-------------+
52 // (DMA from host)
53 //
54
55 struct dmaSCB
56   {
57     long  dma_reserved1[3];
58
59     short dma_reserved2:dma_outBufPtr;
60
61     short dma_unused1:dma_unused2;
62
63     long  dma_reserved3[4];
64
65     short dma_subListPtr:dma_nextSCB;
66     short dma_SPBptr:dma_entryPoint;
67
68     long  dma_strmRsConfig;
69     long  dma_strmBufPtr;
70
71     long  dma_reserved4;
72
73     VolumeControl s2m_volume;
74   };
75
76 #export DMAReader
77 void DMAReader()
78 {
79   execChild();
80   r2 = r0->dma_subListPtr;
81   r1 = r0->nextSCB;
82         
83   rsConfig01 = r2->strmRsConfig;
84   // Load rsConfig for input buffer
85
86   rsDMA01 = r2->basicReq.daw,       ,                   tb = Z(0 - rf);
87   // Load rsDMA in case input buffer is a DMA buffer    Test to see if there is any data to transfer
88
89   if (tb) goto execSibling_2ind1 after {
90       r5 = rf + (-1);
91       r6 = r1->dma_entryPoint;           // r6 = entry point of sibling task
92       r1 = r1->dma_SPBptr,               // r1 = pointer to sibling task's SPB
93           ,   ind = r6;                  // Load entry point of sibling task
94   }
95
96   rsConfig23 = r0->dma_strmRsConfig;
97   // Load rsConfig for output buffer (never a DMA buffer)
98
99   r4 = r0->dma_outBufPtr;
100
101   rsa0 = r2->strmBufPtr;
102   // rsa0 = input buffer pointer                        
103
104   for (i = r5; i >= 0; --i)
105     after {
106       rsa2 = r4;
107       // rsa2 = output buffer pointer
108
109       nop;
110       nop;
111     }
112   //*****************************
113   // TODO: cycles to this point *
114   //*****************************
115     {
116       acc0 =  (rsd0 = *rsa0++1);
117       // get sample
118
119       nop;  // Those "nop"'s are really uggly, but there's
120       nop;  // something with DSP's pipelines which I don't
121       nop;  // understand, resulting this code to fail without
122             // having those "nop"'s (Benny)
123
124       rsa0?reqDMA = r2;
125       // Trigger DMA transfer on input stream, 
126       // if needed to replenish input buffer
127
128       nop;
129       // Yet another magic "nop" to make stuff work
130
131       ,,r98 = acc0 $+>> 0;
132       // store sample in ALU
133
134       nop;
135       // latency on load register.
136       // (this one is understandable)
137
138       *rsa2++1 = r98;
139       // store sample in output buffer
140
141       nop; // The same story
142       nop; // as above again ...
143       nop;
144     }
145   // TODO: cycles per loop iteration
146
147   r2->strmBufPtr = rsa0,,   ;
148   // Update the modified buffer pointers
149
150   r4 = rsa2;
151   // Load output pointer position into r4
152
153   r2 = r0->nextSCB;
154   // Sibling task
155
156   goto execSibling_2ind1 // takes 6 cycles
157     after {
158       r98 = r2->thisSPB:entryPoint;
159       // Load child routine entry and data address 
160
161       r1 = r9;
162       // r9 is r2->thisSPB
163
164       r0->dma_outBufPtr = r4,,
165       // Store updated output buffer pointer
166
167       ind = r8;
168       // r8 is r2->entryPoint
169     }
170 }