add op_lidstate
[pandora-misc.git] / tests / llautest.c
1 #include <stdio.h>
2 #include <sys/types.h>
3 #include <sys/stat.h>
4 #include <fcntl.h>
5 #include <sys/mman.h>
6 #include <unistd.h>
7
8 #define DO_SYNTH
9
10 /* McBSP Register Offsets. */
11 #define MCBSP_DRR_OFFSET            0x00
12 #define MCBSP_DXR_OFFSET            0x08
13 #define MCBSP_SPCR2_OFFSET          0x10
14 #define MCBSP_SPCR1_OFFSET          0x14
15 #define MCBSP_RCR2_OFFSET           0x18
16 #define MCBSP_RCR1_OFFSET           0x1C
17 #define MCBSP_XCR2_OFFSET           0x20
18 #define MCBSP_XCR1_OFFSET           0x24
19 #define MCBSP_SRGR2_OFFSET          0x28
20 #define MCBSP_SRGR1_OFFSET          0x2C
21 #define MCBSP_MCR2_OFFSET           0x30
22 #define MCBSP_MCR1_OFFSET           0x34
23 #define MCBSP_RCERA_OFFSET          0x38
24 #define MCBSP_RCERB_OFFSET          0x3C
25 #define MCBSP_XCERA_OFFSET          0x40
26 #define MCBSP_XCERB_OFFSET          0x44
27 #define MCBSP_PCR0_OFFSET           0x48
28
29 #define MCBSP_REV_OFFSET            0x7C
30 #define MCBSP_RINTCLR_OFFSET        0x80
31 #define MCBSP_XINTCLR_OFFSET        0x84
32 #define MCBSP_ROVFLCLR_OFFSET       0x88
33 #define MCBSP_SYSCONFIG_OFFSET      0x8C
34 #define MCBSP_THRSH2_OFFSET         0x90
35 #define MCBSP_THRSH1_OFFSET         0x94
36 #define MCBSP_IRQSTATUS_OFFSET      0xA0
37
38 #define MCBSP_IRQSTATUS_OFFSET      0xA0
39 #define MCBSP_IRQENABLE_OFFSET      0xA4
40 #define MCBSP_WAKEUPEN_OFFSET       0xA8
41 #define MCBSP_XCCR_OFFSET           0xAC
42 #define MCBSP_RCCR_OFFSET           0xB0
43 #define MCBSP_XBUFFSTAT_OFFSET      0xB4
44 #define MCBSP_RBUFFSTAT_OFFSET      0xB8
45
46 #define BITSPERSAMPLE   16
47
48 typedef unsigned int U32;
49 #define out_regl(a,d) *((volatile unsigned int *)(a)) = d
50
51
52 /* Reset the McBSP. */
53 static void reset_mcbsp (U32 mcbsp_base_addr, U32 enable)
54 {
55     /*
56     ** Checking whether McBSP is providing the clock (Word and bit CLK)
57     ** or McBSP is master.
58     */
59     if (((*(volatile U32 *)(mcbsp_base_addr + MCBSP_PCR0_OFFSET)) & 0x0F00)
60         != 0x0F00)
61     {
62         /*
63         ** If McBSP is not master, then TX/RX/SCG are not enabled
64         ** and disabled between each call to the macbsp_write/read functions.
65         */
66         return;
67     }
68     else
69     {
70         *((volatile U32 *)(mcbsp_base_addr + MCBSP_DXR_OFFSET))= 0x0;
71         if (enable)
72         {
73             /* The serial port transmitter is enabled. */
74             *((volatile U32 *)(mcbsp_base_addr + MCBSP_SPCR2_OFFSET)) |= 0x0001;
75
76             /* The serial port receiver is enabled. */
77             *((volatile U32 *)(mcbsp_base_addr + MCBSP_SPCR1_OFFSET)) |= 0x0001;
78
79             /*
80             ** Sample rate generator is pulled out of reset.
81             ** Frame counters are loaded with their programmed values.
82             */
83             *((volatile U32 *)(mcbsp_base_addr + MCBSP_SPCR2_OFFSET)) |= 0x00C0;
84         }
85         else
86         {
87             /*
88             ** The serial port transmitter is disabled and in reset state.
89             ** Frame-synchronization logic is reset.
90             */
91             *((volatile U32 *)(mcbsp_base_addr + MCBSP_SPCR2_OFFSET))
92                 &= ~(0x00C1);
93
94             /* The serial port receiver is disabled and in reset state. */
95             *((volatile U32 *)(mcbsp_base_addr + MCBSP_SPCR1_OFFSET))
96                 &= ~(0x0001);
97         }
98     }
99 }
100
101
102 /* Writes TX data register by polling method. */
103 static int write_data_mcbsp(U32 mcbsp_base_addr, U32 data)
104 {
105     U32 ret_status = 0;
106     U32 attempts;
107
108     *((volatile U32 *)(mcbsp_base_addr + MCBSP_DXR_OFFSET)) = data;
109
110     /* If frame sync error - clear the error. */
111     if (*((volatile U32 *)(mcbsp_base_addr + MCBSP_SPCR2_OFFSET)) & 0x08)
112     {
113         printf("Frame sync error.\n");
114         /* Clear error. */
115         *((volatile U32 *)(mcbsp_base_addr + MCBSP_SPCR2_OFFSET)) &= ~(0x08);
116     }
117
118     /* Wait for transmit confirmation. */
119     attempts = 0;
120     while  ((*((volatile U32 *)(mcbsp_base_addr + MCBSP_SPCR2_OFFSET)) & 0x2)
121             != 0x2)
122     {
123         if (attempts++ > 1000)
124         {
125             /* The attempt failed, so reset the Tx. */
126             *((volatile U32 *)(mcbsp_base_addr + MCBSP_SPCR2_OFFSET)) &= ~(0x1);
127
128             /* Enable Tx. */
129             *((volatile U32 *)(mcbsp_base_addr + MCBSP_SPCR2_OFFSET)) |= 0x1;
130
131             printf("McBSP write failed.\n");
132             return -1;
133         }
134     }
135
136     return ret_status;
137 }
138
139 int main(int argc, char *argv[])
140 {
141         volatile unsigned int *regs;
142         unsigned int mcbsp_base_addr, sample;
143         int ret, memdev;
144 #ifdef DO_SYNTH
145         int count = 0;
146 #else
147         FILE *f;
148
149         f = fopen(argv[1], "rb");
150         if (f == NULL)
151         {
152                 printf("no file.\n");
153                 return 0;
154         }
155 #endif
156
157         memdev = open("/dev/mem", O_RDWR|O_SYNC);
158         if (memdev == -1)
159         {
160                 printf("no memdev\n");
161                 return 1;
162         }
163
164         // 0x480022D8 ~ CONTROL_DEVCONF1
165         // 0x49024000 ~ McBSP3
166         regs = mmap(0, 0x10000, PROT_WRITE|PROT_READ, MAP_SHARED, memdev, 0x48000000);
167         if (regs == MAP_FAILED)
168         {
169                 printf("mmap failed\n");
170                 return 1;
171         }
172
173         mcbsp_base_addr = (unsigned int)mmap(0, 0x2000, PROT_WRITE|PROT_READ, MAP_SHARED, memdev, 0x49024000);
174         if ((int)mcbsp_base_addr == (int)MAP_FAILED)
175         {
176                 printf("mmap failed\n");
177                 return 1;
178         }
179
180         /* ----- clocks ----- */
181
182         /*
183          ** Configure the CLKS input to 96M functional clk from PRCM
184          ** and not MCBSP.CLKS pin.(this is for McBSP2)
185          ** CONTROL_DEVCONF0 ,set bit 6 to zero.
186          */
187         regs[0x2274>>2] &= 0xFFFFFFBF;
188
189         // CONTROL_DEVCONF1 For McBSP3 we want to use the MCBSP.CLKS pin
190         regs[0x22D8>>2] |= 1;
191
192         /* CM_CLKSEL1_PLL 96 Mhz selected. */
193         regs[0x4d40>>2] &= 0xFFFFFFF7;
194
195         /* CM_FCLKEN_PER Enable the functional clock of McBSP3. */
196         regs[0x5000>>2] |= 0x00000002;
197
198         /* CM_ICLKEN_PER Enable the Interface clock of McBSP3 */
199         regs[0x5010>>2] |= 0x00000002;
200
201         /* McBSP3 selected. */
202         regs[0x5030>>2] |= 0x00000002;
203
204         /* ----- McBSP ----- */
205
206         /* Make all registers to zero to start with. */
207         out_regl((mcbsp_base_addr + MCBSP_SPCR2_OFFSET), 0);
208         out_regl((mcbsp_base_addr + MCBSP_SPCR1_OFFSET), 0);
209 //      out_regl((mcbsp_base_addr + MCBSP_PCR0_OFFSET), 0);
210         out_regl((mcbsp_base_addr + MCBSP_XCR1_OFFSET), 0);
211         out_regl((mcbsp_base_addr + MCBSP_RCR1_OFFSET), 0);
212         out_regl((mcbsp_base_addr + MCBSP_XCR2_OFFSET), 0);
213         out_regl((mcbsp_base_addr + MCBSP_RCR2_OFFSET), 0);
214         out_regl((mcbsp_base_addr + MCBSP_SRGR1_OFFSET), 0);
215         out_regl((mcbsp_base_addr + MCBSP_SRGR2_OFFSET), 0);
216
217         /* Disable TX and RX DMA. */
218         out_regl((mcbsp_base_addr + MCBSP_XCCR_OFFSET), 0);
219         out_regl((mcbsp_base_addr + MCBSP_RCCR_OFFSET), 0);
220         out_regl((mcbsp_base_addr + MCBSP_THRSH2_OFFSET), 0);
221         out_regl((mcbsp_base_addr + MCBSP_THRSH1_OFFSET), 0);
222         out_regl((mcbsp_base_addr + MCBSP_IRQENABLE_OFFSET), 0);
223         out_regl((mcbsp_base_addr + MCBSP_IRQSTATUS_OFFSET), 0x7fbf); // clear IRQs
224
225         /* Set the audio configuration. */
226
227         /*
228         ** Codec is slave McBSP is master
229         ** Enable the following bits FSXM, FSRM, CLKXM, CLKRM, CLKXP, CLKRP.
230         */
231         *((volatile U32 *)(mcbsp_base_addr + MCBSP_PCR0_OFFSET)) = 0x0f0C;//0x0f00; //0x0f03;
232         *((volatile U32 *)(mcbsp_base_addr + MCBSP_SPCR1_OFFSET)) |=  0x0008;
233         *((volatile U32 *)(mcbsp_base_addr + MCBSP_SPCR2_OFFSET)) |=  0x0008;
234
235         /* Tx word len1= 16bits, 1 word per frame. */
236         *((volatile U32 *)(mcbsp_base_addr + MCBSP_XCR1_OFFSET))  |=  0x40;
237
238         /*
239         ** Dual phase frame
240         ** Tx word len2 = 16 bits, 1 word per frame.
241         ** No companding data starts with MSB first
242         ** Transmit frame-synchronization pulses after the first are ignored.
243         ** Tx Data delay - 1bit.
244         */
245         *((volatile U32 *)(mcbsp_base_addr + MCBSP_XCR2_OFFSET))  |=  0x8041;
246
247         /* Rx word len1 = 16bits, 1 word per frame. */
248         *((volatile U32 *)(mcbsp_base_addr + MCBSP_RCR1_OFFSET))  |=  0x40;
249
250         /*
251         ** Dual phase frame
252         ** Rx word len2=16 bits ,1 word per frame.
253         ** No companding data starts with MSB first
254         ** Rx Data delay- 1bit.
255         */
256         *((volatile U32 *)(mcbsp_base_addr + MCBSP_RCR2_OFFSET))  |=  0x8041;
257
258         /* Configure the sample generator. */
259
260         /*
261         ** McBSP sample rate generator register 1
262         ** Frame pulse width is 16 clk periods
263         ** Sample rate generator clock divider - 70
264         ** 44.1Khz
265         */
266         *((volatile U32 *)(mcbsp_base_addr + MCBSP_SRGR1_OFFSET))
267             = ((BITSPERSAMPLE - 1) << 8) | (8 - 1); // BCLK = 32fs
268
269         /* Next frame-sync signal becomes active after 32 clock periods. */
270         *((volatile U32 *)(mcbsp_base_addr + MCBSP_SRGR2_OFFSET)) =
271 //              0x2000 |
272                 0x1000 | ((BITSPERSAMPLE * 2) - 1);
273
274         /* Enable the sample rate generator. */
275         *((volatile U32 *)(mcbsp_base_addr + MCBSP_SPCR2_OFFSET)) |= 0x00C0;
276
277         /* Enable the Tx, Rx. */
278         *((volatile U32 *)(mcbsp_base_addr + MCBSP_SPCR1_OFFSET)) |= 1;
279         *((volatile U32 *)(mcbsp_base_addr + MCBSP_SPCR2_OFFSET)) |= 1;
280
281         usleep(1000);
282
283         /* Reset the device. */
284         reset_mcbsp(mcbsp_base_addr, 1);
285
286         /* must restore ?DMAEN bits to defaults */
287         out_regl((mcbsp_base_addr + MCBSP_XCCR_OFFSET), 8);
288         out_regl((mcbsp_base_addr + MCBSP_RCCR_OFFSET), 8);
289
290         usleep(1000);
291
292         /* write */
293         sample = 0;
294         while (1)
295         {
296 #ifndef DO_SYNTH
297                 ret = fread(&sample, 1, 2, f);
298                 if (ret != 2) break;
299 #else
300                 sample = (count & 0x80) ? 65536-10000 : 10000;
301                 count++;
302                 if (count > 200*1024) break;
303 #endif
304
305                 ret = write_data_mcbsp(mcbsp_base_addr, sample);
306                 if (ret != 0) break;
307         }
308
309         /* Reset the device. */
310         reset_mcbsp(mcbsp_base_addr, 0);
311
312         munmap((void *)regs, 0x10000);
313         munmap((void *)mcbsp_base_addr, 0x2000);
314         close(memdev);
315 #ifndef DO_SYNTH
316         fclose(f);
317 #endif
318
319         return 0;
320 }
321