OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [freertos-6.1.1/] [Demo/] [CORTEX_AT91SAM3U256_IAR/] [AT91Lib/] [peripherals/] [ac97c/] [ac97c.c] - Blame information for rev 580

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 580 jeremybenn
/* ----------------------------------------------------------------------------
2
 *         ATMEL Microcontroller Software Support
3
 * ----------------------------------------------------------------------------
4
 * Copyright (c) 2008, Atmel Corporation
5
 *
6
 * All rights reserved.
7
 *
8
 * Redistribution and use in source and binary forms, with or without
9
 * modification, are permitted provided that the following conditions are met:
10
 *
11
 * - Redistributions of source code must retain the above copyright notice,
12
 * this list of conditions and the disclaimer below.
13
 *
14
 * Atmel's name may not be used to endorse or promote products derived from
15
 * this software without specific prior written permission.
16
 *
17
 * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
18
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
20
 * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
21
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
23
 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
24
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
25
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
26
 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
 * ----------------------------------------------------------------------------
28
 */
29
 
30
//------------------------------------------------------------------------------
31
//         Headers
32
//------------------------------------------------------------------------------
33
 
34
#include "ac97c.h"
35
#include <board.h>
36
#include <aic/aic.h>
37
#include <utility/assert.h>
38
#include <utility/trace.h>
39
#include <utility/math.h>
40
 
41
//------------------------------------------------------------------------------
42
//         Local constants
43
//------------------------------------------------------------------------------
44
 
45
/// Maximum size of one PDC buffer (in bytes).
46
#define MAX_PDC_COUNTER 65535
47
 
48
//------------------------------------------------------------------------------
49
//         Local types
50
//------------------------------------------------------------------------------
51
 
52
//------------------------------------------------------------------------------
53
/// AC97 transfer descriptor. Tracks the status and parameters of a transfer
54
/// on the AC97 bus.
55
//------------------------------------------------------------------------------
56
typedef struct _Ac97Transfer {
57
 
58
    /// Buffer containing the slots to send.
59
    unsigned char *pBuffer;
60
    /// Total number of samples to send.
61
    volatile unsigned int numSamples;
62
    /// Optional callback function.
63
    Ac97Callback callback;
64
    /// Optional argument to the callback function.
65
    void *pArg;
66
 
67
} Ac97Transfer;
68
 
69
//------------------------------------------------------------------------------
70
/// AC97 controller driver structure. Monitors the status of transfers on all
71
/// AC97 channels.
72
//------------------------------------------------------------------------------
73
typedef struct _Ac97c {
74
 
75
    /// List of transfers occuring on each channel.
76
    Ac97Transfer transfers[5];
77
} Ac97c;
78
 
79
//------------------------------------------------------------------------------
80
//         Local variables
81
//------------------------------------------------------------------------------
82
 
83
/// Global AC97 controller instance.
84
static Ac97c ac97c;
85
 
86
//------------------------------------------------------------------------------
87
//         Local functions
88
//------------------------------------------------------------------------------
89
 
90
//------------------------------------------------------------------------------
91
/// Returns the size of one sample (in bytes) on the given channel.
92
/// \param channel  Channel number.
93
//------------------------------------------------------------------------------
94
static unsigned char GetSampleSize(unsigned char channel)
95
{
96
    unsigned int size = 0;
97
 
98
    SANITY_CHECK((channel == AC97C_CHANNEL_A)
99
                 || (channel == AC97C_CHANNEL_B)
100
                 || (channel == AC97C_CHANNEL_CODEC));
101
 
102
    // Check selected channel
103
    switch (channel) {
104
        case AC97C_CHANNEL_CODEC: return 2;
105
 
106
        case AC97C_CHANNEL_A:
107
            size = (AT91C_BASE_AC97C->AC97C_CAMR & AT91C_AC97C_SIZE) >> 16;
108
            break;
109
 
110
        case AC97C_CHANNEL_B:
111
            size = (AT91C_BASE_AC97C->AC97C_CBMR & AT91C_AC97C_SIZE) >> 16;
112
            break;
113
    }
114
 
115
    // Compute size in bytes given SIZE field
116
    if ((size & 2) != 0) {
117
 
118
        return 2;
119
    }
120
    else {
121
 
122
        return 4;
123
    }
124
}
125
 
126
//------------------------------------------------------------------------------
127
/// Interrupt service routine for Codec, is invoked by AC97C_Handler.
128
//------------------------------------------------------------------------------
129
static void CodecHandler(void)
130
{
131
    unsigned int status;
132
    unsigned int data;
133
    Ac97Transfer *pTransfer = &(ac97c.transfers[AC97C_CODEC_TRANSFER]);
134
 
135
    // Read CODEC status register
136
    status = AT91C_BASE_AC97C->AC97C_COSR;
137
    status &= AT91C_BASE_AC97C->AC97C_COMR;
138
 
139
    // A sample has been transmitted
140
    if (status & AT91C_AC97C_TXRDY) {
141
 
142
        pTransfer->numSamples--;
143
 
144
        // If there are remaining samples, transmit one
145
        if (pTransfer->numSamples > 0) {
146
 
147
            data = *((unsigned int *) pTransfer->pBuffer);
148
            AT91C_BASE_AC97C->AC97C_COMR &= ~(AT91C_AC97C_TXRDY);
149
            AT91C_BASE_AC97C->AC97C_COTHR = data;
150
 
151
            // Check if transfer is read or write
152
            if ((data & AT91C_AC97C_READ) != 0) {
153
 
154
                AT91C_BASE_AC97C->AC97C_COMR |= AT91C_AC97C_RXRDY;
155
            }
156
            else {
157
 
158
                pTransfer->pBuffer += sizeof(unsigned int);
159
                AT91C_BASE_AC97C->AC97C_COMR |= AT91C_AC97C_TXRDY;
160
            }
161
        }
162
        // Transfer finished
163
        else {
164
 
165
            AT91C_BASE_AC97C->AC97C_IDR = AT91C_AC97C_COEVT;
166
            AT91C_BASE_AC97C->AC97C_COMR &= ~(AT91C_AC97C_TXRDY);
167
            if (pTransfer->callback) {
168
 
169
                pTransfer->callback(pTransfer->pArg, 0, 0);
170
            }
171
        }
172
    }
173
 
174
    // A sample has been received
175
    if (status & AT91C_AC97C_RXRDY) {
176
 
177
        // Store sample
178
        data = AT91C_BASE_AC97C->AC97C_CORHR;
179
        *((unsigned int *) pTransfer->pBuffer) = data;
180
 
181
        pTransfer->pBuffer += sizeof(unsigned int);
182
        pTransfer->numSamples--;
183
 
184
        // Transfer finished
185
        if (pTransfer->numSamples > 0) {
186
 
187
            data = *((unsigned int *) pTransfer->pBuffer);
188
            AT91C_BASE_AC97C->AC97C_COMR &= ~(AT91C_AC97C_RXRDY);
189
            AT91C_BASE_AC97C->AC97C_COTHR = data;
190
 
191
            // Check if transfer is read or write
192
            if ((data & AT91C_AC97C_READ) != 0) {
193
 
194
                AT91C_BASE_AC97C->AC97C_COMR |= AT91C_AC97C_RXRDY;
195
            }
196
            else {
197
 
198
                pTransfer->pBuffer += sizeof(unsigned int);
199
                AT91C_BASE_AC97C->AC97C_COMR |= AT91C_AC97C_TXRDY;
200
            }
201
        }
202
        else {
203
 
204
            AT91C_BASE_AC97C->AC97C_IDR = AT91C_AC97C_COEVT;
205
            AT91C_BASE_AC97C->AC97C_COMR &= ~(AT91C_AC97C_RXRDY);
206
            if (pTransfer->callback) {
207
 
208
                pTransfer->callback(pTransfer->pArg, 0, 0);
209
            }
210
        }
211
    }
212
}
213
 
214
//------------------------------------------------------------------------------
215
/// Interrupt service routine for channel A, is invoked by AC97C_Handler.
216
//------------------------------------------------------------------------------
217
static void ChannelAHandler(void)
218
{
219
    unsigned int status;
220
    Ac97Transfer *pTransmit = &(ac97c.transfers[AC97C_CHANNEL_A_TRANSMIT]);
221
    Ac97Transfer *pReceive = &(ac97c.transfers[AC97C_CHANNEL_A_RECEIVE]);
222
 
223
    // Read channel A status register
224
    status = AT91C_BASE_AC97C->AC97C_CASR;
225
 
226
    // A buffer has been transmitted
227
    if ((status & AT91C_AC97C_ENDTX) != 0) {
228
 
229
        // Update transfer information
230
        if (pTransmit->numSamples > MAX_PDC_COUNTER) {
231
 
232
            pTransmit->numSamples -= MAX_PDC_COUNTER;
233
        }
234
        else {
235
 
236
            pTransmit->numSamples = 0;
237
        }
238
 
239
        // Transmit new buffers if necessary
240
        if (pTransmit->numSamples > MAX_PDC_COUNTER) {
241
 
242
            // Fill next PDC
243
            AT91C_BASE_AC97C->AC97C_TNPR = (unsigned int) pTransmit->pBuffer;
244
            if (pTransmit->numSamples > 2 * MAX_PDC_COUNTER) {
245
 
246
                AT91C_BASE_AC97C->AC97C_TNCR = MAX_PDC_COUNTER;
247
                pTransmit->pBuffer += MAX_PDC_COUNTER
248
                                            * GetSampleSize(AC97C_CHANNEL_A);
249
            }
250
            else {
251
 
252
                AT91C_BASE_AC97C->AC97C_TNCR = pTransmit->numSamples
253
                                                            - MAX_PDC_COUNTER;
254
            }
255
        }
256
        // Only one buffer remaining
257
        else {
258
 
259
            AT91C_BASE_AC97C->AC97C_CAMR &= ~AT91C_AC97C_ENDTX;
260
            AT91C_BASE_AC97C->AC97C_CAMR |= AT91C_AC97C_TXBUFE;
261
        }
262
    }
263
 
264
    // Transmit completed
265
    if ((status & AT91C_AC97C_TXBUFE) != 0) {
266
 
267
        pTransmit->numSamples = 0;
268
        AT91C_BASE_AC97C->AC97C_PTCR = AT91C_PDC_TXTDIS;
269
        AT91C_BASE_AC97C->AC97C_CAMR &= ~AT91C_AC97C_TXBUFE;
270
        if (pTransmit->callback) {
271
 
272
            pTransmit->callback(pTransmit->pArg, 0, 0);
273
        }
274
    }
275
 
276
    // A buffer has been received
277
    if (status & AT91C_AC97C_ENDRX) {
278
 
279
        if (pReceive->numSamples > MAX_PDC_COUNTER) {
280
 
281
            pReceive->numSamples -= MAX_PDC_COUNTER;
282
        }
283
        else {
284
 
285
            pReceive->numSamples = 0;
286
        }
287
 
288
        // Transfer remaining samples
289
        if (pReceive->numSamples > MAX_PDC_COUNTER) {
290
 
291
            AT91C_BASE_AC97C->AC97C_RNPR = (unsigned int) pReceive->pBuffer;
292
            if (pReceive->numSamples > 2 * MAX_PDC_COUNTER) {
293
 
294
                AT91C_BASE_AC97C->AC97C_RNCR = MAX_PDC_COUNTER;
295
                pReceive->pBuffer += MAX_PDC_COUNTER
296
                                            * GetSampleSize(AC97C_CHANNEL_A);
297
            }
298
            else {
299
 
300
                AT91C_BASE_AC97C->AC97C_RNCR = pReceive->numSamples
301
                                                            - MAX_PDC_COUNTER;
302
            }
303
        }
304
        // Only one buffer remaining
305
        else {
306
 
307
            AT91C_BASE_AC97C->AC97C_CAMR &= ~(AT91C_AC97C_ENDRX);
308
            AT91C_BASE_AC97C->AC97C_CAMR |= AT91C_AC97C_RXBUFF;
309
        }
310
    }
311
 
312
    // Receive complete
313
    if ((status & AT91C_AC97C_RXBUFF) != 0) {
314
 
315
        pReceive->numSamples = 0;
316
        AT91C_BASE_AC97C->AC97C_PTCR = AT91C_PDC_RXTDIS;
317
        AT91C_BASE_AC97C->AC97C_CAMR &= ~AT91C_AC97C_RXBUFF;
318
        if (pReceive->callback) {
319
 
320
            pReceive->callback(pReceive->pArg, 0, 0);
321
        }
322
    }
323
}
324
 
325
//------------------------------------------------------------------------------
326
//         Exported functions
327
//------------------------------------------------------------------------------
328
//------------------------------------------------------------------------------
329
/// This handler function must be called by the AC97C interrupt service routine.
330
/// Identifies which event was activated and calls the associated function.
331
//------------------------------------------------------------------------------ 
332
void AC97C_Handler(void)
333
{
334
    unsigned int status;
335
 
336
    // Get the real interrupt source
337
    status = AT91C_BASE_AC97C->AC97C_SR;
338
    status &= AT91C_BASE_AC97C->AC97C_IMR;
339
 
340
    // Check if an event on the codec channel is active
341
    if ((status & AT91C_AC97C_COEVT) != 0) {
342
 
343
        CodecHandler();
344
    }
345
    // Check if an event on channel A is active
346
    if ((status & AT91C_AC97C_CAEVT) != 0) {
347
 
348
        ChannelAHandler();
349
    }
350
}
351
 
352
//------------------------------------------------------------------------------
353
/// Starts a read or write transfer on the given channel
354
/// \param channel particular channel (AC97C_CODEC_TRANSFER, 
355
///                AC97C_CHANNEL_A_RECEIVE, AC97C_CHANNEL_A_TRANSMIT,
356
///                AC97C_CHANNEL_B_RECEIVE or AC97C_CHANNEL_B_TRANSMIT).
357
/// \param pBuffer buffer containing the slots to send.
358
/// \param numSamples total number of samples to send.  
359
/// \param callback optional callback function.
360
/// \param pArg optional argument to the callback function.
361
//------------------------------------------------------------------------------
362
unsigned char AC97C_Transfer(
363
    unsigned char channel,
364
    unsigned char *pBuffer,
365
    unsigned int numSamples,
366
    Ac97Callback callback,
367
    void *pArg)
368
{
369
    unsigned int size;
370
    unsigned int data;
371
    Ac97Transfer *pTransfer;
372
 
373
    SANITY_CHECK(channel <= 5);
374
    SANITY_CHECK(pBuffer);
375
    SANITY_CHECK(numSamples > 0);
376
 
377
    // Check that no transfer is pending on the channel
378
    pTransfer = &(ac97c.transfers[channel]);
379
    if (pTransfer->numSamples > 0) {
380
 
381
        TRACE_WARNING(
382
            "AC97C_Transfer: Channel %d is busy\n\r", channel);
383
        return AC97C_ERROR_BUSY;
384
    }
385
 
386
    // Fill transfer information
387
    pTransfer->pBuffer = pBuffer;
388
    pTransfer->numSamples = numSamples;
389
    pTransfer->callback = callback;
390
    pTransfer->pArg = pArg;
391
 
392
    // Transmit or receive over codec channel
393
    if (channel == AC97C_CODEC_TRANSFER) {
394
 
395
        // Send command
396
        data = *((unsigned int *) pTransfer->pBuffer);
397
        AT91C_BASE_AC97C->AC97C_COTHR = data;
398
 
399
        // Check if transfer is read or write
400
        if ((data & AT91C_AC97C_READ) != 0) {
401
 
402
            AT91C_BASE_AC97C->AC97C_COMR |= AT91C_AC97C_RXRDY;
403
        }
404
        else {
405
 
406
            pTransfer->pBuffer += sizeof(unsigned int);
407
            AT91C_BASE_AC97C->AC97C_COMR |= AT91C_AC97C_TXRDY;
408
        }
409
 
410
        // Enable interrupts
411
        AT91C_BASE_AC97C->AC97C_IER |= AT91C_AC97C_COEVT;
412
    }
413
    // Transmit over channel A
414
    else if (channel == AC97C_CHANNEL_A_TRANSMIT) {
415
 
416
        // Disable PDC
417
        AT91C_BASE_AC97C->AC97C_PTCR = AT91C_PDC_TXTDIS;
418
 
419
        // Fill PDC buffers
420
        size = min(pTransfer->numSamples, MAX_PDC_COUNTER);
421
        AT91C_BASE_AC97C->AC97C_TPR = (unsigned int) pTransfer->pBuffer;
422
        AT91C_BASE_AC97C->AC97C_TCR = size;
423
        pTransfer->pBuffer += size * GetSampleSize(AC97C_CHANNEL_A);
424
 
425
        size = min(pTransfer->numSamples - size, MAX_PDC_COUNTER);
426
        if (size > 0) {
427
 
428
            AT91C_BASE_AC97C->AC97C_TNPR = (unsigned int) pTransfer->pBuffer;
429
            AT91C_BASE_AC97C->AC97C_TNCR = size;
430
            pTransfer->pBuffer += size * GetSampleSize(AC97C_CHANNEL_A);
431
        }
432
 
433
        // Enable interrupts
434
        AT91C_BASE_AC97C->AC97C_CAMR |= AT91C_AC97C_PDCEN | AT91C_AC97C_ENDTX;
435
        AT91C_BASE_AC97C->AC97C_IER |= AT91C_AC97C_CAEVT;
436
 
437
        // Start transfer
438
        AT91C_BASE_AC97C->AC97C_PTCR = AT91C_PDC_TXTEN;
439
    }
440
    // Receive over channel A
441
    else if (channel == AC97C_CHANNEL_A_RECEIVE) {
442
 
443
        // Disable PDC
444
        AT91C_BASE_AC97C->AC97C_PTCR = AT91C_PDC_RXTDIS;
445
 
446
        // Fill PDC buffers
447
        size = min(pTransfer->numSamples, MAX_PDC_COUNTER);
448
        AT91C_BASE_AC97C->AC97C_RPR = (unsigned int) pTransfer->pBuffer;
449
        AT91C_BASE_AC97C->AC97C_RCR = size;
450
        pTransfer->pBuffer += size * GetSampleSize(AC97C_CHANNEL_A);
451
 
452
        size = min(pTransfer->numSamples - size, MAX_PDC_COUNTER);
453
        if (size > 0) {
454
 
455
            AT91C_BASE_AC97C->AC97C_RNPR = (unsigned int) pTransfer->pBuffer;
456
            AT91C_BASE_AC97C->AC97C_RNCR = size;
457
            pTransfer->pBuffer += size * GetSampleSize(AC97C_CHANNEL_A);
458
        }
459
 
460
        // Enable interrupts
461
        AT91C_BASE_AC97C->AC97C_CAMR |= AT91C_AC97C_PDCEN | AT91C_AC97C_ENDRX;
462
        AT91C_BASE_AC97C->AC97C_IER |= AT91C_AC97C_CAEVT;
463
 
464
        // Start transfer
465
        AT91C_BASE_AC97C->AC97C_PTCR = AT91C_PDC_RXTEN;
466
    }
467
 
468
    return 0;
469
}
470
 
471
//------------------------------------------------------------------------------
472
/// Stop read or write transfer on the given channel.
473
/// \param channel  Channel number.
474
//------------------------------------------------------------------------------
475
void AC97C_CancelTransfer(unsigned char channel)
476
{
477
    unsigned int size = 0;
478
    Ac97Transfer *pTransfer;
479
 
480
    SANITY_CHECK(channel <= AC97C_CHANNEL_B_TRANSMIT);
481
 
482
    // Save remaining size
483
    pTransfer = &(ac97c.transfers[channel]);
484
    size = pTransfer->numSamples;
485
    pTransfer->numSamples = 0;
486
 
487
    // Stop PDC
488
    if (channel == AC97C_CHANNEL_A_TRANSMIT) {
489
 
490
        AT91C_BASE_AC97C->AC97C_PTCR = AT91C_PDC_TXTDIS;
491
        size -= min(size, MAX_PDC_COUNTER) - AT91C_BASE_AC97C->AC97C_TCR;
492
    }
493
    if (channel == AC97C_CHANNEL_A_RECEIVE) {
494
 
495
        AT91C_BASE_AC97C->AC97C_PTCR = AT91C_PDC_RXTDIS;
496
        size -= min(size, MAX_PDC_COUNTER) - AT91C_BASE_AC97C->AC97C_RCR;
497
    }
498
 
499
    // Invoke callback if provided
500
    if (pTransfer->callback) {
501
 
502
        pTransfer->callback(pTransfer->pArg, AC97C_ERROR_STOPPED, size);
503
    }
504
}
505
 
506
//------------------------------------------------------------------------------
507
/// Initializes the AC97 controller.
508
//------------------------------------------------------------------------------
509
void AC97C_Configure(void)
510
{
511
    unsigned char channel;
512
 
513
    // Enable the AC97 controller peripheral clock
514
    AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_AC97C);
515
 
516
    // Enable the peripheral and variable rate adjustment
517
    AT91C_BASE_AC97C->AC97C_MR = AT91C_AC97C_ENA  | AT91C_AC97C_VRA;
518
 
519
    // Unassigns all input & output slots
520
    AC97C_AssignInputSlots(0, 0xFFFF);
521
    AC97C_AssignOutputSlots(0, 0xFFFF);
522
 
523
    // Install the AC97C interrupt handler
524
    AT91C_BASE_AC97C->AC97C_IDR = 0xFFFFFFFF;
525
    AIC_ConfigureIT(AT91C_ID_AC97C, 0, AC97C_Handler);
526
    AIC_EnableIT(AT91C_ID_AC97C);
527
 
528
    // Disable PDC transfers
529
    AT91C_BASE_AC97C->AC97C_PTCR = AT91C_PDC_TXTDIS | AT91C_PDC_RXTDIS;
530
 
531
    // Clear channel transfers
532
    for (channel = 0; channel < AC97C_CHANNEL_B_TRANSMIT; channel++) {
533
 
534
        ac97c.transfers[channel].numSamples = 0;
535
    }
536
}
537
 
538
//------------------------------------------------------------------------------
539
/// Configures the desired channel with the given value.
540
/// \param channel  Channel number.
541
/// \param cfg  Configuration value.
542
//------------------------------------------------------------------------------
543
void AC97C_ConfigureChannel(unsigned char channel, unsigned int cfg)
544
{
545
    SANITY_CHECK((channel == AC97C_CHANNEL_A) || (channel == AC97C_CHANNEL_B));
546
 
547
    if (channel == AC97C_CHANNEL_A) {
548
 
549
        AT91C_BASE_AC97C->AC97C_CAMR = cfg;
550
    }
551
    else {
552
 
553
        AT91C_BASE_AC97C->AC97C_CBMR = cfg;
554
    }
555
}
556
 
557
//------------------------------------------------------------------------------
558
/// Assigns the desired input slots to a particular channel.
559
/// \param channel  Channel number (or 0 to unassign slots).
560
/// \param slots  Bitfield value of slots to assign.
561
//------------------------------------------------------------------------------
562
void AC97C_AssignInputSlots(unsigned char channel, unsigned int slots)
563
{
564
    unsigned int value;
565
    unsigned int i;
566
 
567
    SANITY_CHECK(channel <= AC97C_CHANNEL_B);
568
 
569
    // Assign all slots
570
    slots >>= 3;
571
    for (i = 3; i < 15; i++) {
572
 
573
        // Check if slots is selected
574
        if (slots & 1) {
575
 
576
            value = AT91C_BASE_AC97C->AC97C_ICA;
577
            value &= ~(0x07 << ((i - 3) * 3));
578
            value |= channel << ((i - 3) * 3);
579
            AT91C_BASE_AC97C->AC97C_ICA = value;
580
        }
581
        slots >>= 1;
582
    }
583
}
584
 
585
//------------------------------------------------------------------------------
586
/// Assigns the desired output slots to a particular channel.
587
/// \param channel  Channel number (or 0 to unassign slots).
588
/// \param slots  Bitfield value of slots to assign.
589
//------------------------------------------------------------------------------
590
void AC97C_AssignOutputSlots(unsigned char channel, unsigned int slots)
591
{
592
    unsigned int value;
593
    unsigned int i;
594
 
595
    SANITY_CHECK(channel <= AC97C_CHANNEL_B);
596
 
597
    // Assign all slots
598
    slots >>= 3;
599
    for (i = 3; i < 15; i++) {
600
 
601
        // Check if slots is selected
602
        if (slots & 1) {
603
 
604
            value = AT91C_BASE_AC97C->AC97C_OCA;
605
            value &= ~(0x07 << ((i - 3) * 3));
606
            value |= channel << ((i - 3) * 3);
607
            AT91C_BASE_AC97C->AC97C_OCA = value;
608
        }
609
        slots >>= 1;
610
    }
611
}
612
 
613
//------------------------------------------------------------------------------
614
/// Returns 1 if no transfer is currently pending on the given channel;
615
/// otherwise, returns 0.
616
/// \param channel  Channel number.
617
//------------------------------------------------------------------------------
618
unsigned char AC97C_IsFinished(unsigned char channel)
619
{
620
    SANITY_CHECK(channel <= AC97C_CHANNEL_B_TRANSMIT);
621
 
622
    if (ac97c.transfers[channel].numSamples > 0) {
623
 
624
        return 0;
625
    }
626
    else {
627
 
628
        return 1;
629
    }
630
}
631
 
632
//------------------------------------------------------------------------------
633
/// Convenience function for synchronously sending commands to the codec.
634
/// \param address  Register address.
635
/// \param data  Command data.
636
//------------------------------------------------------------------------------
637
void AC97C_WriteCodec(unsigned char address, unsigned short data)
638
{
639
    unsigned int sample;
640
 
641
    sample = (address << 16) | data;
642
    AC97C_Transfer(AC97C_CODEC_TRANSFER, (unsigned char *) &sample, 1, 0, 0);
643
    while (!AC97C_IsFinished(AC97C_CODEC_TRANSFER));
644
}
645
 
646
//------------------------------------------------------------------------------
647
/// Convenience function for receiving data from the AC97 codec.
648
/// \param address  Register address.
649
//------------------------------------------------------------------------------
650
unsigned short AC97C_ReadCodec(unsigned char address)
651
{
652
    unsigned int sample;
653
 
654
    sample = AT91C_AC97C_READ | (address << 16);
655
    AC97C_Transfer(AC97C_CODEC_TRANSFER, (unsigned char *) &sample, 1, 0, 0);
656
    while (!AC97C_IsFinished(AC97C_CODEC_TRANSFER));
657
 
658
    return sample;
659
}
660
 
661
//------------------------------------------------------------------------------
662
/// Sets the size in bits of one sample on the given channel.
663
/// \param channel  Channel number.
664
/// \param size  Size of one sample in bits (10, 16, 18 or 24).
665
//------------------------------------------------------------------------------
666
void AC97C_SetChannelSize(unsigned char channel, unsigned char size)
667
{
668
    unsigned int bits = 0;
669
 
670
    SANITY_CHECK((size == 10) || (size == 16) || (size == 18) || (size == 24));
671
    SANITY_CHECK((channel == AC97C_CHANNEL_A) || (channel == AC97C_CHANNEL_B));
672
 
673
    switch (size) {
674
 
675
        case 10 : bits = AT91C_AC97C_SIZE_10_BITS; break;
676
        case 16 : bits = AT91C_AC97C_SIZE_16_BITS; break;
677
        case 18 : bits = AT91C_AC97C_SIZE_18_BITS; break;
678
        case 20 : bits = AT91C_AC97C_SIZE_20_BITS; break;
679
    }
680
 
681
    if (channel == AC97C_CHANNEL_A) {
682
 
683
        AT91C_BASE_AC97C->AC97C_CAMR &= ~(AT91C_AC97C_SIZE);
684
        AT91C_BASE_AC97C->AC97C_CAMR |= bits;
685
    }
686
    else {
687
 
688
        AT91C_BASE_AC97C->AC97C_CBMR &= ~(AT91C_AC97C_SIZE);
689
        AT91C_BASE_AC97C->AC97C_CBMR |= bits;
690
    }
691
}
692
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.