aboutsummaryrefslogtreecommitdiff
path: root/sound/pci/cs46xx/imgs/cwcdma.asp
blob: a65e1193c89ad646d8a042ea606ff933e703bf3a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
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
    }
}