summaryrefslogtreecommitdiff
path: root/firmware/target/arm/tms320dm320/dsp/dma.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target/arm/tms320dm320/dsp/dma.c')
-rw-r--r--firmware/target/arm/tms320dm320/dsp/dma.c267
1 files changed, 145 insertions, 122 deletions
diff --git a/firmware/target/arm/tms320dm320/dsp/dma.c b/firmware/target/arm/tms320dm320/dsp/dma.c
index 430cc909f7..590b35de80 100644
--- a/firmware/target/arm/tms320dm320/dsp/dma.c
+++ b/firmware/target/arm/tms320dm320/dsp/dma.c
@@ -23,185 +23,208 @@
23 23
24#include "registers.h" 24#include "registers.h"
25#include "arm.h" 25#include "arm.h"
26#include "dma.h" 26#include "ipc.h"
27
28/* Size of data buffer in words (16 bit) */
29#define DSP_BUFFER_SIZE (0x1000)
27 30
28/* This is placed at the right (aligned) address using linker.cmd. */ 31/* Put the "data" buffer in it's own .dma section so that it can
32 * be handled in the linker.cmd. */
29#pragma DATA_SECTION (data, ".dma") 33#pragma DATA_SECTION (data, ".dma")
30 34
31#define DSP_BUFFER_SIZE PCM_SIZE/2 35/* This is the "data" buffer on the DSP side used for SARAM to McBSP (IIS) */
32 36static signed short data[DSP_BUFFER_SIZE];
33/* This is the buffer on the DSP side used for SARAM to McBSP (IIS) */
34signed short data[DSP_BUFFER_SIZE];
35 37
36/* These two describe the location of the buffer on the ARM (set in DSPHINT 38/* These two describe the location of the buffer on the ARM (set in DSPHINT) */
37 * and dspinit)
38 */
39volatile unsigned short sdem_addrh; 39volatile unsigned short sdem_addrh;
40volatile unsigned short sdem_addrl; 40volatile unsigned short sdem_addrl;
41 41
42/* This is the size of the ARM buffer (set in DSPHINT and dspinit) */ 42/* This is the size of the ARM buffer (set in DSPHINT) */
43volatile unsigned short sdem_dsp_size; 43volatile unsigned short sdem_dsp_size;
44 44
45/* These two variables keep track of the buffer level in the DSP, dsp_level, 45/* These two variables keep track of the buffer level in the DSP, dsp_level,
46 * (SARAM to McBSP) and the level on the ARM buffer (sdem_level). 46 * (SARAM to McBSP) and the level on the ARM buffer (sdem_level).
47 */ 47 * sdem_level is used in the main firmware to keep track of the current
48unsigned short dsp_level=0; 48 * playback status. dsp_level is only used in this function. */
49unsigned short sdem_level=0; 49static unsigned short dsp_level;
50volatile unsigned short sdem_level;
50 51
51/* This is used to keep track of the last SDRAM to SARAM transfer */ 52/* This is used to keep track of the last SDRAM to SARAM transfer */
52unsigned short last_size; 53static unsigned short last_size;
53 54
54/* This tells us which half of the DSP buffer (data) is free */ 55/* This tells us which half of the DSP buffer (data) is free */
55unsigned short dma0_unlocked; 56static unsigned short dma0_unlocked;
56 57
57volatile unsigned short dma0_stopped=1; 58/* This is used by the ARM to flag playback status and start/stop the DMA
59 * transfers. */
60volatile unsigned short dma0_stopped;
58 61
59short waiting=0; 62/* This is used to effectively flag whether the ARM has new data ready or not */
60/* rebuffer sets up the next SDRAM to SARAM transfer and tells the ARM when it 63short waiting;
61 * is done with a buffer. 64
62 */ 65
63 66/* rebuffer sets up the next SDRAM to SARAM transfer and tells the ARM when DMA
64/* Notes: The upper limit on larger buffers is the size of a short. If larger 67 * needs a new buffer.
68 *
69 * Note: The upper limit on larger buffers is the size of a short. If larger
65 * buffer sizes are needed the code on the ARM side needs to be changed to 70 * buffer sizes are needed the code on the ARM side needs to be changed to
66 * update a full long. 71 * update a full long.
67 */ 72 */
68void rebuffer(void) 73void rebuffer(void)
69{ 74{
70 unsigned long sdem_addr; 75 unsigned long sdem_addr;
71 76
72 if(dma0_stopped==1) /* Stop */ 77 if(dma0_stopped==1 || dma0_stopped==2) /* Stop / Pause */
73 { 78 {
74 DMPREC&=0xFFFE; /* Stop MCBSP DMA0 */ 79 /* Stop MCBSP DMA0 */
75 audiohw_stop(); 80 DMPREC &= 0xFFFE;
76 DMSFC0 = 2 << 12 | 1 << 11; 81 /* Shut the transmitter down */
77 sdem_level=0; 82 audiohw_stop();
78 return; 83
79 } 84 /* Stop the HPIB transfer if it is running */
80 85 DMA_TRG = 0;
81 if(dsp_level==DSP_BUFFER_SIZE || sdem_level==sdem_dsp_size) 86
82 { 87 /* Reset the following variables for DMA restart */
83 if(dma0_stopped==2) /* Pause */ 88 sdem_level = 0;
84 { 89 dsp_level = 0;
85 DMPREC&=0xFFFE; /* Stop MCBSP DMA0 */ 90 last_size = 0;
86 audiohw_stop(); 91
87 return; 92 return;
88 } 93 }
89 }
90
91 /* If the sdem_level is equal to the buffer size the ARM code gave
92 * (sdem_dsp_size) then reset the size and ask the arm for another buffer
93 */
94 if(sdem_level==sdem_dsp_size)
95 {
96 sdem_level=0;
97
98 /* Get a new buffer (location and size) from ARM */
99 status.msg = MSG_REFILL;
100 waiting=1;
101
102 startack();
103 }
104
105 if(!waiting)
106 {
107 /* Size is in bytes (but forced 32 bit transfers */
108 if( (dsp_level + (sdem_dsp_size - sdem_level) ) > DSP_BUFFER_SIZE)
109 {
110 last_size = DSP_BUFFER_SIZE-dsp_level;
111 }
112 else
113 {
114 last_size = sdem_dsp_size-sdem_level;
115 }
116
117 /* DSP addresses are 16 bit (word) */
118 DSP_ADDRL = (unsigned short)data + (dma0_unlocked >> 1) + (dsp_level>>1);
119 DSP_ADDRH = 0;
120
121 /* SDRAM addresses are 8 bit (byte)
122 * Warning: These addresses are forced to 32 bit alignment!
123 */
124 sdem_addr = ((unsigned long)sdem_addrh << 16 | sdem_addrl) + sdem_level;
125 SDEM_ADDRL = sdem_addr & 0xffff;
126 SDEM_ADDRH = sdem_addr >> 16;
127 94
128 /* Set the size of the SDRAM to SARAM transfer (demac transfer) */ 95 /* If the sdem_level is equal to the buffer size the ARM code gave
129 DMA_SIZE = last_size; 96 * (sdem_dsp_size) then reset the size and ask the arm for another buffer
97 */
98 if(sdem_level == sdem_dsp_size)
99 {
100 sdem_level=0;
101
102 /* Get a new buffer (location and size) from ARM */
103 status.msg = MSG_REFILL;
104 waiting=1;
105
106 /* trigger DSPHINT on the ARM */
107 int_arm();
108 }
109
110 if(!waiting)
111 {
112 /* Size is in bytes (but forced 32 bit transfers). Comparison is
113 * against DSP_BUFFER_SIZE because it is in words and this needs to
114 * compare against half the total size in bytes. */
115 if( dsp_level + sdem_dsp_size - sdem_level > DSP_BUFFER_SIZE)
116 {
117 last_size = DSP_BUFFER_SIZE - dsp_level;
118 }
119 else
120 {
121 last_size = sdem_dsp_size - sdem_level;
122 }
123
124 /* DSP addresses are 16 bit (word). dsp_level is in bytes so it needs to
125 * be converted to words. */
126 DSP_ADDRL = (unsigned short)data + dma0_unlocked + (dsp_level >> 1);
127 DSP_ADDRH = 0;
128
129 /* SDRAM addresses are 8 bit (byte)
130 * Warning: These addresses are forced to 32 bit alignment!
131 */
132 sdem_addr = ((unsigned long)sdem_addrh << 16 | sdem_addrl) + sdem_level;
133 SDEM_ADDRL = sdem_addr & 0xffff;
134 SDEM_ADDRH = sdem_addr >> 16;
135
136 /* Set the size of the SDRAM to SARAM transfer (demac transfer) */
137 DMA_SIZE = last_size;
130 138
131 DMA_CTRL = 0; 139 DMA_CTRL = 0;
132 140
133 /* These are just debug signals that are not used/needed right now */ 141 /* These are just debug signals that are not used/needed right now */
134 status.payload.refill._DMA_TRG = DMA_TRG; 142 status.payload.refill._DMA_TRG = DMA_TRG;
135 status.payload.refill._SDEM_ADDRH = SDEM_ADDRH; 143 status.payload.refill._SDEM_ADDRH = SDEM_ADDRH;
136 status.payload.refill._SDEM_ADDRL = SDEM_ADDRL; 144 status.payload.refill._SDEM_ADDRL = SDEM_ADDRL;
137 status.payload.refill._DSP_ADDRH = DSP_ADDRH; 145 status.payload.refill._DSP_ADDRH = DSP_ADDRH;
138 status.payload.refill._DSP_ADDRL = DSP_ADDRL; 146 status.payload.refill._DSP_ADDRL = DSP_ADDRL;
139 147
140 /* Start the demac transfer */ 148 /* Start the demac transfer */
141 DMA_TRG = 1; 149 DMA_TRG = 1;
142 } 150 }
143} 151}
144 152
145/* This interupt handler is for the SARAM (on DSP) to McBSP IIS DMA transfer. 153/* This interupt handler is for the SARAM (on DSP) to McBSP IIS DMA transfer.
146 * It interupts at 1/2 empty and empty so that we can start filling a new buffer 154 * It interupts at 1/2 empty and empty so that we can start filling a new buffer
147 * from SDRAM when a half is free. dsp_level should always be full when this 155 * from SDRAM when a half is free. dsp_level should always be full when this
148 * interupt occurs except for the initial start. 156 * interupt occurs except for the initial start. */
149 */
150interrupt void handle_dma0(void) 157interrupt void handle_dma0(void)
151{ 158{
152 /* Byte offset to half-buffer locked by DMA0. 159 /* Byte offset to half-buffer locked by DMA0.
153 0 for top, PCM_SIZE/2 for bottom */ 160 0 for top, DSP_BUFFER_SIZE/2 for bottom */
154 unsigned short dma0_locked; 161 unsigned short dma0_locked;
155 162
156 IFR = 1 << 6; 163 IFR = 1 << 6;
157 164
158 /* DMSRC0 is the beginning of the DMA0-locked SARAM half-buffer. */ 165 /* DMSRC0 is the beginning of the DMA0-locked SARAM half-buffer. */
159 DMSA = 0x00 /* DMSRC0 */; 166 DMSA = 0x00 /* DMSRC0 (banked register, see page 133 of SPRU302B */;
160 dma0_locked = (DMSDN << 1) & (DSP_BUFFER_SIZE);
161 dma0_unlocked = dma0_locked ^ (DSP_BUFFER_SIZE);
162 167
163 dsp_level = 0; 168 /* Note that these address offsets (dma0_locked and dma0_unlocked are in
169 * words. */
170 dma0_locked = DMSDN & (DSP_BUFFER_SIZE>>1);
171 dma0_unlocked = dma0_locked ^ (DSP_BUFFER_SIZE>>1);
172
173 dsp_level = 0;
164 174
165 /* Start the SDRAM to SARAM copy */ 175 /* Start the SDRAM to SARAM copy */
166 rebuffer(); 176 rebuffer();
167} 177}
168 178
169/* This interupt handler runs every time a DMA transfer is complete from SDRAM 179/* This interupt handler runs every time a DMA transfer is complete from SDRAM
170 * to the SARAM buffer. It is used to update the SARAM buffer level 180 * to the SARAM buffer. It is used to update the SARAM buffer level
171 * (dsp_level), the SDRAM buffer level (sdem_level) and to rebuffer if the dsp 181 * (dsp_level), the SDRAM buffer level (sdem_level) and to rebuffer if the dsp
172 * buffer is not full. 182 * buffer is not full. */
173 */
174interrupt void handle_dmac(void) { 183interrupt void handle_dmac(void) {
175 IFR = 1 << 11; 184 IFR = 1 << 11; /* Clear interrupt */
176 185
177 dsp_level+=last_size; 186 /* dsp_level and sdem_level are in bytes */
178 sdem_level+=last_size; 187 dsp_level += last_size;
179 188 sdem_level += last_size;
180 if(dsp_level<DSP_BUFFER_SIZE) 189
190 /* compare to DSP_BUFFER_SIZE without a divide because it is in words and
191 * we want half the total size in bytes. */
192 if(dsp_level < DSP_BUFFER_SIZE)
181 { 193 {
182 rebuffer(); 194 rebuffer();
183 } 195 }
184} 196}
185 197
186void dma_init(void) { 198void dma_init(void) {
187 /* Configure SARAM to McBSP DMA */ 199 /* Initialize some of the global variables to known values avoiding the
200 * .cinit section. */
201 dsp_level = 0;
202 sdem_level = 0;
203
204 last_size = 0;
205 dma0_unlocked = 0;
206 dma0_stopped = 1;
188 207
208 waiting = 0;
209
210 /* Configure SARAM to McBSP DMA */
211
189 /* Event XEVT0, 32-bit transfers, 0 frame count */ 212 /* Event XEVT0, 32-bit transfers, 0 frame count */
190 DMSFC0 = 2 << 12 | 1 << 11; 213 DMSFC0 = 2 << 12 | 1 << 11;
191 214
192 /* Interrupts generated, Half and full buffer. 215 /* Interrupts generated, Half and full buffer.
193 * ABU mode, From data space with postincrement, to data space with no 216 * ABU mode, From data space with postincrement, to data space with no
194 * change 217 * change
195 */ 218 */
196 DMMCR0 = 1 << 14 | 1 << 13 | 219 DMMCR0 = 1 << 14 | 1 << 13 |
197 1 << 12 | 1 << 8 | 1 << 6 | 1; 220 1 << 12 | 1 << 8 | 1 << 6 | 1;
198 221
199 /* Set the source (incrementing) location */ 222 /* Set the source (incrementing) location */
200 DMSRC0 = (unsigned short)&data; 223 DMSRC0 = (unsigned short)&data;
201 224
202 /* Set the destination (static) location to the McBSP IIS interface */ 225 /* Set the destination (static) location to the McBSP IIS interface */
203 DMDST0 = (unsigned short)&DXR20; 226 DMDST0 = (unsigned short)&DXR20;
204 227
205 /* Set the size of the buffer */ 228 /* Set the size of the buffer */
206 DMCTR0 = sizeof(data); 229 DMCTR0 = sizeof(data);
207 230