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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [freertos-6.1.1/] [Demo/] [Common/] [drivers/] [Atmel/] [at91lib/] [peripherals/] [ac97c/] [ac97c.c] - Blame information for rev 608

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 608 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
        case AC97C_CHANNEL_A: size = (AT91C_BASE_AC97C->AC97C_CAMR & AT91C_AC97C_SIZE) >> 16; break;
106
        case AC97C_CHANNEL_B: size = (AT91C_BASE_AC97C->AC97C_CBMR & AT91C_AC97C_SIZE) >> 16; break;
107
    }
108
 
109
    // Compute size in bytes given SIZE field
110
    if ((size & 2) != 0) {
111
 
112
        return 2;
113
    }
114
    else {
115
 
116
        return 4;
117
    }
118
}
119
 
120
//------------------------------------------------------------------------------
121
/// Interrupt service routine for Codec, is invoked by AC97C_Handler.
122
//------------------------------------------------------------------------------
123
static void CodecHandler(void)
124
{
125
    unsigned int status;
126
    unsigned int data;
127
    Ac97Transfer *pTransfer = &(ac97c.transfers[AC97C_CODEC_TRANSFER]);
128
 
129
    // Read CODEC status register
130
    status = AT91C_BASE_AC97C->AC97C_COSR;
131
    status &= AT91C_BASE_AC97C->AC97C_COMR;
132
 
133
    // A sample has been transmitted
134
    if (status & AT91C_AC97C_TXRDY) {
135
 
136
        pTransfer->numSamples--;
137
 
138
        // If there are remaining samples, transmit one
139
        if (pTransfer->numSamples > 0) {
140
 
141
            data = *((unsigned int *) pTransfer->pBuffer);
142
            AT91C_BASE_AC97C->AC97C_COMR &= ~(AT91C_AC97C_TXRDY);
143
            AT91C_BASE_AC97C->AC97C_COTHR = data;
144
 
145
            // Check if transfer is read or write
146
            if ((data & AT91C_AC97C_READ) != 0) {
147
 
148
                AT91C_BASE_AC97C->AC97C_COMR |= AT91C_AC97C_RXRDY;
149
            }
150
            else {
151
 
152
                pTransfer->pBuffer += sizeof(unsigned int);
153
                AT91C_BASE_AC97C->AC97C_COMR |= AT91C_AC97C_TXRDY;
154
            }
155
        }
156
        // Transfer finished
157
        else {
158
 
159
            AT91C_BASE_AC97C->AC97C_IDR = AT91C_AC97C_COEVT;
160
            AT91C_BASE_AC97C->AC97C_COMR &= ~(AT91C_AC97C_TXRDY);
161
            if (pTransfer->callback) {
162
 
163
                pTransfer->callback(pTransfer->pArg, 0, 0);
164
            }
165
        }
166
    }
167
 
168
    // A sample has been received
169
    if (status & AT91C_AC97C_RXRDY) {
170
 
171
        // Store sample
172
        data = AT91C_BASE_AC97C->AC97C_CORHR;
173
        *((unsigned int *) pTransfer->pBuffer) = data;
174
 
175
        pTransfer->pBuffer += sizeof(unsigned int);
176
        pTransfer->numSamples--;
177
 
178
        // Transfer finished
179
        if (pTransfer->numSamples > 0) {
180
 
181
            data = *((unsigned int *) pTransfer->pBuffer);
182
            AT91C_BASE_AC97C->AC97C_COMR &= ~(AT91C_AC97C_RXRDY);
183
            AT91C_BASE_AC97C->AC97C_COTHR = data;
184
 
185
            // Check if transfer is read or write
186
            if ((data & AT91C_AC97C_READ) != 0) {
187
 
188
                AT91C_BASE_AC97C->AC97C_COMR |= AT91C_AC97C_RXRDY;
189
            }
190
            else {
191
 
192
                pTransfer->pBuffer += sizeof(unsigned int);
193
                AT91C_BASE_AC97C->AC97C_COMR |= AT91C_AC97C_TXRDY;
194
            }
195
        }
196
        else {
197
 
198
            AT91C_BASE_AC97C->AC97C_IDR = AT91C_AC97C_COEVT;
199
            AT91C_BASE_AC97C->AC97C_COMR &= ~(AT91C_AC97C_RXRDY);
200
            if (pTransfer->callback) {
201
 
202
                pTransfer->callback(pTransfer->pArg, 0, 0);
203
            }
204
        }
205
    }
206
}
207
 
208
//------------------------------------------------------------------------------
209
/// Interrupt service routine for channel A, is invoked by AC97C_Handler.
210
//------------------------------------------------------------------------------
211
static void ChannelAHandler(void)
212
{
213
    unsigned int status;
214
    Ac97Transfer *pTransmit = &(ac97c.transfers[AC97C_CHANNEL_A_TRANSMIT]);
215
    Ac97Transfer *pReceive = &(ac97c.transfers[AC97C_CHANNEL_A_RECEIVE]);
216
 
217
    // Read channel A status register
218
    status = AT91C_BASE_AC97C->AC97C_CASR;
219
 
220
    // A buffer has been transmitted
221
    if ((status & AT91C_AC97C_ENDTX) != 0) {
222
 
223
        // Update transfer information
224
        if (pTransmit->numSamples > MAX_PDC_COUNTER) {
225
 
226
            pTransmit->numSamples -= MAX_PDC_COUNTER;
227
        }
228
        else {
229
 
230
            pTransmit->numSamples = 0;
231
        }
232
 
233
        // Transmit new buffers if necessary
234
        if (pTransmit->numSamples > MAX_PDC_COUNTER) {
235
 
236
            // Fill next PDC
237
            AT91C_BASE_AC97C->AC97C_TNPR = (unsigned int) pTransmit->pBuffer;
238
            if (pTransmit->numSamples > 2 * MAX_PDC_COUNTER) {
239
 
240
                AT91C_BASE_AC97C->AC97C_TNCR = MAX_PDC_COUNTER;
241
                pTransmit->pBuffer += MAX_PDC_COUNTER * GetSampleSize(AC97C_CHANNEL_A);
242
            }
243
            else {
244
 
245
                AT91C_BASE_AC97C->AC97C_TNCR = pTransmit->numSamples - MAX_PDC_COUNTER;
246
            }
247
        }
248
        // Only one buffer remaining
249
        else {
250
 
251
            AT91C_BASE_AC97C->AC97C_CAMR &= ~AT91C_AC97C_ENDTX;
252
            AT91C_BASE_AC97C->AC97C_CAMR |= AT91C_AC97C_TXBUFE;
253
        }
254
    }
255
 
256
    // Transmit completed
257
    if ((status & AT91C_AC97C_TXBUFE) != 0) {
258
 
259
        pTransmit->numSamples = 0;
260
        AT91C_BASE_AC97C->AC97C_PTCR = AT91C_PDC_TXTDIS;
261
        AT91C_BASE_AC97C->AC97C_CAMR &= ~AT91C_AC97C_TXBUFE;
262
        if (pTransmit->callback) {
263
 
264
            pTransmit->callback(pTransmit->pArg, 0, 0);
265
        }
266
    }
267
 
268
    // A buffer has been received
269
    if (status & AT91C_AC97C_ENDRX) {
270
 
271
        if (pReceive->numSamples > MAX_PDC_COUNTER) {
272
 
273
            pReceive->numSamples -= MAX_PDC_COUNTER;
274
        }
275
        else {
276
 
277
            pReceive->numSamples = 0;
278
        }
279
 
280
        // Transfer remaining samples
281
        if (pReceive->numSamples > MAX_PDC_COUNTER) {
282
 
283
            AT91C_BASE_AC97C->AC97C_RNPR = (unsigned int) pReceive->pBuffer;
284
            if (pReceive->numSamples > 2 * MAX_PDC_COUNTER) {
285
 
286
                AT91C_BASE_AC97C->AC97C_RNCR = MAX_PDC_COUNTER;
287
                pReceive->pBuffer += MAX_PDC_COUNTER * GetSampleSize(AC97C_CHANNEL_A);
288
            }
289
            else {
290
 
291
                AT91C_BASE_AC97C->AC97C_RNCR = pReceive->numSamples - MAX_PDC_COUNTER;
292
            }
293
        }
294
        // Only one buffer remaining
295
        else {
296
 
297
            AT91C_BASE_AC97C->AC97C_CAMR &= ~(AT91C_AC97C_ENDRX);
298
            AT91C_BASE_AC97C->AC97C_CAMR |= AT91C_AC97C_RXBUFF;
299
        }
300
    }
301
 
302
    // Receive complete
303
    if ((status & AT91C_AC97C_RXBUFF) != 0) {
304
 
305
        pReceive->numSamples = 0;
306
        AT91C_BASE_AC97C->AC97C_PTCR = AT91C_PDC_RXTDIS;
307
        AT91C_BASE_AC97C->AC97C_CAMR &= ~AT91C_AC97C_RXBUFF;
308
        if (pReceive->callback) {
309
 
310
            pReceive->callback(pReceive->pArg, 0, 0);
311
        }
312
    }
313
}
314
 
315
//------------------------------------------------------------------------------
316
//         Exported functions
317
//------------------------------------------------------------------------------
318
//------------------------------------------------------------------------------
319
/// This handler function must be called by the AC97C interrupt service routine.
320
/// Identifies which event was activated and calls the associated function.
321
//------------------------------------------------------------------------------ 
322
void AC97C_Handler(void)
323
{
324
    unsigned int status;
325
 
326
    // Get the real interrupt source
327
    status = AT91C_BASE_AC97C->AC97C_SR;
328
    status &= AT91C_BASE_AC97C->AC97C_IMR;
329
 
330
    // Check if an event on the codec channel is active
331
    if ((status & AT91C_AC97C_COEVT) != 0) {
332
 
333
        CodecHandler();
334
    }
335
    // Check if an event on channel A is active
336
    if ((status & AT91C_AC97C_CAEVT) != 0) {
337
 
338
        ChannelAHandler();
339
    }
340
}
341
 
342
//------------------------------------------------------------------------------
343
/// Starts a read or write transfer on the given channel
344
/// \param channel particular channel (AC97C_CHANNEL_A or AC97C_CHANNEL_B).
345
/// \param pBuffer buffer containing the slots to send.
346
/// \param numSamples total number of samples to send.  
347
/// \param callback optional callback function.
348
/// \param pArg optional argument to the callback function.
349
//------------------------------------------------------------------------------
350
unsigned char AC97C_Transfer(
351
    unsigned char channel,
352
    unsigned char *pBuffer,
353
    unsigned int numSamples,
354
    Ac97Callback callback,
355
    void *pArg)
356
{
357
    unsigned int size;
358
    unsigned int data;
359
    Ac97Transfer *pTransfer;
360
 
361
    SANITY_CHECK(channel <= 5);
362
    SANITY_CHECK(pBuffer);
363
    SANITY_CHECK(numSamples > 0);
364
 
365
    // Check that no transfer is pending on the channel
366
    pTransfer = &(ac97c.transfers[channel]);
367
    if (pTransfer->numSamples > 0) {
368
 
369
        trace_LOG(trace_WARNING, "-W- AC97C_Transfer: Channel %d is busy\n\r", channel);
370
        return AC97C_ERROR_BUSY;
371
    }
372
 
373
    // Fill transfer information
374
    pTransfer->pBuffer = pBuffer;
375
    pTransfer->numSamples = numSamples;
376
    pTransfer->callback = callback;
377
    pTransfer->pArg = pArg;
378
 
379
    // Transmit or receive over codec channel
380
    if (channel == AC97C_CODEC_TRANSFER) {
381
 
382
        // Send command
383
        data = *((unsigned int *) pTransfer->pBuffer);
384
        AT91C_BASE_AC97C->AC97C_COTHR = data;
385
 
386
        // Check if transfer is read or write
387
        if ((data & AT91C_AC97C_READ) != 0) {
388
 
389
            AT91C_BASE_AC97C->AC97C_COMR |= AT91C_AC97C_RXRDY;
390
        }
391
        else {
392
 
393
            pTransfer->pBuffer += sizeof(unsigned int);
394
            AT91C_BASE_AC97C->AC97C_COMR |= AT91C_AC97C_TXRDY;
395
        }
396
 
397
        // Enable interrupts
398
        AT91C_BASE_AC97C->AC97C_IER |= AT91C_AC97C_COEVT;
399
    }
400
    // Transmit over channel A
401
    else if (channel == AC97C_CHANNEL_A_TRANSMIT) {
402
 
403
        // Disable PDC
404
        AT91C_BASE_AC97C->AC97C_PTCR = AT91C_PDC_TXTDIS;
405
 
406
        // Fill PDC buffers
407
        size = min(pTransfer->numSamples, MAX_PDC_COUNTER);
408
        AT91C_BASE_AC97C->AC97C_TPR = (unsigned int) pTransfer->pBuffer;
409
        AT91C_BASE_AC97C->AC97C_TCR = size;
410
        pTransfer->pBuffer += size * GetSampleSize(AC97C_CHANNEL_A);
411
 
412
        size = min(pTransfer->numSamples - size, MAX_PDC_COUNTER);
413
        if (size > 0) {
414
 
415
            AT91C_BASE_AC97C->AC97C_TNPR = (unsigned int) pTransfer->pBuffer;
416
            AT91C_BASE_AC97C->AC97C_TNCR = size;
417
            pTransfer->pBuffer += size * GetSampleSize(AC97C_CHANNEL_A);
418
        }
419
 
420
        // Enable interrupts
421
        AT91C_BASE_AC97C->AC97C_CAMR |= AT91C_AC97C_PDCEN | AT91C_AC97C_ENDTX;
422
        AT91C_BASE_AC97C->AC97C_IER |= AT91C_AC97C_CAEVT;
423
 
424
        // Start transfer
425
        AT91C_BASE_AC97C->AC97C_PTCR = AT91C_PDC_TXTEN;
426
    }
427
    // Receive over channel A
428
    else if (channel == AC97C_CHANNEL_A_RECEIVE) {
429
 
430
        // Disable PDC
431
        AT91C_BASE_AC97C->AC97C_PTCR = AT91C_PDC_RXTDIS;
432
 
433
        // Fill PDC buffers
434
        size = min(pTransfer->numSamples, MAX_PDC_COUNTER);
435
        AT91C_BASE_AC97C->AC97C_RPR = (unsigned int) pTransfer->pBuffer;
436
        AT91C_BASE_AC97C->AC97C_RCR = size;
437
        pTransfer->pBuffer += size * GetSampleSize(AC97C_CHANNEL_A);
438
 
439
        size = min(pTransfer->numSamples - size, MAX_PDC_COUNTER);
440
        if (size > 0) {
441
 
442
            AT91C_BASE_AC97C->AC97C_RNPR = (unsigned int) pTransfer->pBuffer;
443
            AT91C_BASE_AC97C->AC97C_RNCR = size;
444
            pTransfer->pBuffer += size * GetSampleSize(AC97C_CHANNEL_A);
445
        }
446
 
447
        // Enable interrupts
448
        AT91C_BASE_AC97C->AC97C_CAMR |= AT91C_AC97C_PDCEN | AT91C_AC97C_ENDRX;
449
        AT91C_BASE_AC97C->AC97C_IER |= AT91C_AC97C_CAEVT;
450
 
451
        // Start transfer
452
        AT91C_BASE_AC97C->AC97C_PTCR = AT91C_PDC_RXTEN;
453
    }
454
 
455
    return 0;
456
}
457
 
458
//------------------------------------------------------------------------------
459
/// Stop read or write transfer on the given channel.
460
/// \param channel  Channel number.
461
//------------------------------------------------------------------------------
462
void AC97C_CancelTransfer(unsigned char channel)
463
{
464
    unsigned int size = 0;
465
    Ac97Transfer *pTransfer;
466
 
467
    SANITY_CHECK(channel <= AC97C_CHANNEL_B_TRANSMIT);
468
 
469
    // Save remaining size
470
    pTransfer = &(ac97c.transfers[channel]);
471
    size = pTransfer->numSamples;
472
    pTransfer->numSamples = 0;
473
 
474
    // Stop PDC
475
    if (channel == AC97C_CHANNEL_A_TRANSMIT) {
476
 
477
        AT91C_BASE_AC97C->AC97C_PTCR = AT91C_PDC_TXTDIS;
478
        size -= min(size, MAX_PDC_COUNTER) - AT91C_BASE_AC97C->AC97C_TCR;
479
    }
480
    if (channel == AC97C_CHANNEL_A_RECEIVE) {
481
 
482
        AT91C_BASE_AC97C->AC97C_PTCR = AT91C_PDC_RXTDIS;
483
        size -= min(size, MAX_PDC_COUNTER) - AT91C_BASE_AC97C->AC97C_RCR;
484
    }
485
 
486
    // Invoke callback if provided
487
    if (pTransfer->callback) {
488
 
489
        pTransfer->callback(pTransfer->pArg, AC97C_ERROR_STOPPED, size);
490
    }
491
}
492
 
493
//------------------------------------------------------------------------------
494
/// Initializes the AC97 controller.
495
//------------------------------------------------------------------------------
496
void AC97C_Configure(void)
497
{
498
    unsigned char channel;
499
 
500
    // Enable the AC97 controller peripheral clock
501
    AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_AC97C);
502
 
503
    // Enable the peripheral and variable rate adjustment
504
    AT91C_BASE_AC97C->AC97C_MR = AT91C_AC97C_ENA  | AT91C_AC97C_VRA;
505
 
506
    // Unassigns all input & output slots
507
    AC97C_AssignInputSlots(0, 0xFFFF);
508
    AC97C_AssignOutputSlots(0, 0xFFFF);
509
 
510
    // Install the AC97C interrupt handler
511
    AT91C_BASE_AC97C->AC97C_IDR = 0xFFFFFFFF;
512
    AIC_ConfigureIT(AT91C_ID_AC97C, 0, AC97C_Handler);
513
    AIC_EnableIT(AT91C_ID_AC97C);
514
 
515
    // Disable PDC transfers
516
    AT91C_BASE_AC97C->AC97C_PTCR = AT91C_PDC_TXTDIS | AT91C_PDC_RXTDIS;
517
 
518
    // Clear channel transfers
519
    for (channel = 0; channel < AC97C_CHANNEL_B_TRANSMIT; channel++) {
520
 
521
        ac97c.transfers[channel].numSamples = 0;
522
    }
523
}
524
 
525
//------------------------------------------------------------------------------
526
/// Configures the desired channel with the given value.
527
/// \param channel  Channel number.
528
/// \param cfg  Configuration value.
529
//------------------------------------------------------------------------------
530
void AC97C_ConfigureChannel(unsigned char channel, unsigned int cfg)
531
{
532
    SANITY_CHECK((channel == AC97C_CHANNEL_A) || (channel == AC97C_CHANNEL_B));
533
 
534
    if (channel == AC97C_CHANNEL_A) {
535
 
536
        AT91C_BASE_AC97C->AC97C_CAMR = cfg;
537
    }
538
    else {
539
 
540
        AT91C_BASE_AC97C->AC97C_CBMR = cfg;
541
    }
542
}
543
 
544
//------------------------------------------------------------------------------
545
/// Assigns the desired input slots to a particular channel.
546
/// \param channel  Channel number (or 0 to unassign slots).
547
/// \param slots  Bitfield value of slots to assign.
548
//------------------------------------------------------------------------------
549
void AC97C_AssignInputSlots(unsigned char channel, unsigned int slots)
550
{
551
    unsigned int value;
552
    unsigned int i;
553
 
554
    SANITY_CHECK(channel <= AC97C_CHANNEL_B);
555
 
556
    // Assign all slots
557
    slots >>= 3;
558
    for (i = 3; i < 15; i++) {
559
 
560
        // Check if slots is selected
561
        if (slots & 1) {
562
 
563
            value = AT91C_BASE_AC97C->AC97C_ICA;
564
            value &= ~(0x07 << ((i - 3) * 3));
565
            value |= channel << ((i - 3) * 3);
566
            AT91C_BASE_AC97C->AC97C_ICA = value;
567
        }
568
        slots >>= 1;
569
    }
570
}
571
 
572
//------------------------------------------------------------------------------
573
/// Assigns the desired output slots to a particular channel.
574
/// \param channel  Channel number (or 0 to unassign slots).
575
/// \param slots  Bitfield value of slots to assign.
576
//------------------------------------------------------------------------------
577
void AC97C_AssignOutputSlots(unsigned char channel, unsigned int slots)
578
{
579
    unsigned int value;
580
    unsigned int i;
581
 
582
    SANITY_CHECK(channel <= AC97C_CHANNEL_B);
583
 
584
    // Assign all slots
585
    slots >>= 3;
586
    for (i = 3; i < 15; i++) {
587
 
588
        // Check if slots is selected
589
        if (slots & 1) {
590
 
591
            value = AT91C_BASE_AC97C->AC97C_OCA;
592
            value &= ~(0x07 << ((i - 3) * 3));
593
            value |= channel << ((i - 3) * 3);
594
            AT91C_BASE_AC97C->AC97C_OCA = value;
595
        }
596
        slots >>= 1;
597
    }
598
}
599
 
600
//------------------------------------------------------------------------------
601
/// Returns 1 if no transfer is currently pending on the given channel;
602
/// otherwise, returns 0.
603
/// \param channel  Channel number.
604
//------------------------------------------------------------------------------
605
unsigned char AC97C_IsFinished(unsigned char channel)
606
{
607
    SANITY_CHECK(channel <= AC97C_CHANNEL_B_TRANSMIT);
608
 
609
        if (ac97c.transfers[channel].numSamples > 0) {
610
 
611
                return 0;
612
        }
613
        else {
614
 
615
                return 1;
616
        }
617
}
618
 
619
//------------------------------------------------------------------------------
620
/// Convenience function for synchronously sending commands to the codec.
621
/// \param address  Register address.
622
/// \param data  Command data.
623
//------------------------------------------------------------------------------
624
void AC97C_WriteCodec(unsigned char address, unsigned short data)
625
{
626
    unsigned int sample;
627
 
628
    sample = (address << 16) | data;
629
    AC97C_Transfer(AC97C_CODEC_TRANSFER, (unsigned char *) &sample, 1, 0, 0);
630
    while (!AC97C_IsFinished(AC97C_CODEC_TRANSFER));
631
}
632
 
633
//------------------------------------------------------------------------------
634
/// Convenience function for receiving data from the AC97 codec.
635
/// \param address  Register address.
636
//------------------------------------------------------------------------------
637
unsigned short AC97C_ReadCodec(unsigned char address)
638
{
639
    unsigned int sample;
640
 
641
    sample = AT91C_AC97C_READ | (address << 16);
642
    AC97C_Transfer(AC97C_CODEC_TRANSFER, (unsigned char *) &sample, 1, 0, 0);
643
        while (!AC97C_IsFinished(AC97C_CODEC_TRANSFER));
644
 
645
    return sample;
646
}
647
 
648
//------------------------------------------------------------------------------
649
/// Sets the size in bits of one sample on the given channel.
650
/// \param channel  Channel number.
651
/// \param size  Size of one sample in bits (10, 16, 18 or 24).
652
//------------------------------------------------------------------------------        
653
void AC97C_SetChannelSize(unsigned char channel, unsigned char size)
654
{
655
    unsigned int bits = 0;
656
 
657
    SANITY_CHECK((size == 10) || (size == 16) || (size == 18) || (size == 24));
658
    SANITY_CHECK((channel == AC97C_CHANNEL_A) || (channel == AC97C_CHANNEL_B));
659
 
660
    switch (size) {
661
 
662
        case 10 : bits = AT91C_AC97C_SIZE_10_BITS; break;
663
        case 16 : bits = AT91C_AC97C_SIZE_16_BITS; break;
664
        case 18 : bits = AT91C_AC97C_SIZE_18_BITS; break;
665
        case 20 : bits = AT91C_AC97C_SIZE_20_BITS; break;
666
    }
667
 
668
    if (channel == AC97C_CHANNEL_A) {
669
 
670
        AT91C_BASE_AC97C->AC97C_CAMR &= ~(AT91C_AC97C_SIZE);
671
        AT91C_BASE_AC97C->AC97C_CAMR |= bits;
672
    }
673
    else {
674
 
675
        AT91C_BASE_AC97C->AC97C_CBMR &= ~(AT91C_AC97C_SIZE);
676
        AT91C_BASE_AC97C->AC97C_CBMR |= bits;
677
    }
678
}
679
 

powered by: WebSVN 2.1.0

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