1 /* ----------------------------------------------------------------------------
\r
2 * ATMEL Microcontroller Software Support
\r
3 * ----------------------------------------------------------------------------
\r
4 * Copyright (c) 2008, Atmel Corporation
\r
6 * All rights reserved.
\r
8 * Redistribution and use in source and binary forms, with or without
\r
9 * modification, are permitted provided that the following conditions are met:
\r
11 * - Redistributions of source code must retain the above copyright notice,
\r
12 * this list of conditions and the disclaimer below.
\r
14 * Atmel's name may not be used to endorse or promote products derived from
\r
15 * this software without specific prior written permission.
\r
17 * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
\r
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
\r
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
\r
20 * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
\r
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
\r
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
\r
23 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
\r
24 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
\r
25 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
\r
26 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\r
27 * ----------------------------------------------------------------------------
\r
30 //------------------------------------------------------------------------------
\r
32 //------------------------------------------------------------------------------
\r
36 #include <aic/aic.h>
\r
37 #include <utility/assert.h>
\r
38 #include <utility/trace.h>
\r
39 #include <utility/math.h>
\r
41 //------------------------------------------------------------------------------
\r
43 //------------------------------------------------------------------------------
\r
45 /// Maximum size of one PDC buffer (in bytes).
\r
46 #define MAX_PDC_COUNTER 65535
\r
48 //------------------------------------------------------------------------------
\r
50 //------------------------------------------------------------------------------
\r
52 //------------------------------------------------------------------------------
\r
53 /// AC97 transfer descriptor. Tracks the status and parameters of a transfer
\r
54 /// on the AC97 bus.
\r
55 //------------------------------------------------------------------------------
\r
56 typedef struct _Ac97Transfer {
\r
58 /// Buffer containing the slots to send.
\r
59 unsigned char *pBuffer;
\r
60 /// Total number of samples to send.
\r
61 volatile unsigned int numSamples;
\r
62 /// Optional callback function.
\r
63 Ac97Callback callback;
\r
64 /// Optional argument to the callback function.
\r
69 //------------------------------------------------------------------------------
\r
70 /// AC97 controller driver structure. Monitors the status of transfers on all
\r
72 //------------------------------------------------------------------------------
\r
73 typedef struct _Ac97c {
\r
75 /// List of transfers occuring on each channel.
\r
76 Ac97Transfer transfers[5];
\r
79 //------------------------------------------------------------------------------
\r
81 //------------------------------------------------------------------------------
\r
83 /// Global AC97 controller instance.
\r
86 //------------------------------------------------------------------------------
\r
88 //------------------------------------------------------------------------------
\r
90 //------------------------------------------------------------------------------
\r
91 /// Returns the size of one sample (in bytes) on the given channel.
\r
92 /// \param channel Channel number.
\r
93 //------------------------------------------------------------------------------
\r
94 static unsigned char GetSampleSize(unsigned char channel)
\r
96 unsigned int size = 0;
\r
98 SANITY_CHECK((channel == AC97C_CHANNEL_A)
\r
99 || (channel == AC97C_CHANNEL_B)
\r
100 || (channel == AC97C_CHANNEL_CODEC));
\r
102 // Check selected channel
\r
104 case AC97C_CHANNEL_CODEC: return 2;
\r
105 case AC97C_CHANNEL_A: size = (AT91C_BASE_AC97C->AC97C_CAMR & AT91C_AC97C_SIZE) >> 16; break;
\r
106 case AC97C_CHANNEL_B: size = (AT91C_BASE_AC97C->AC97C_CBMR & AT91C_AC97C_SIZE) >> 16; break;
\r
109 // Compute size in bytes given SIZE field
\r
110 if ((size & 2) != 0) {
\r
120 //------------------------------------------------------------------------------
\r
121 /// Interrupt service routine for Codec, is invoked by AC97C_Handler.
\r
122 //------------------------------------------------------------------------------
\r
123 static void CodecHandler(void)
\r
125 unsigned int status;
\r
127 Ac97Transfer *pTransfer = &(ac97c.transfers[AC97C_CODEC_TRANSFER]);
\r
129 // Read CODEC status register
\r
130 status = AT91C_BASE_AC97C->AC97C_COSR;
\r
131 status &= AT91C_BASE_AC97C->AC97C_COMR;
\r
133 // A sample has been transmitted
\r
134 if (status & AT91C_AC97C_TXRDY) {
\r
136 pTransfer->numSamples--;
\r
138 // If there are remaining samples, transmit one
\r
139 if (pTransfer->numSamples > 0) {
\r
141 data = *((unsigned int *) pTransfer->pBuffer);
\r
142 AT91C_BASE_AC97C->AC97C_COMR &= ~(AT91C_AC97C_TXRDY);
\r
143 AT91C_BASE_AC97C->AC97C_COTHR = data;
\r
145 // Check if transfer is read or write
\r
146 if ((data & AT91C_AC97C_READ) != 0) {
\r
148 AT91C_BASE_AC97C->AC97C_COMR |= AT91C_AC97C_RXRDY;
\r
152 pTransfer->pBuffer += sizeof(unsigned int);
\r
153 AT91C_BASE_AC97C->AC97C_COMR |= AT91C_AC97C_TXRDY;
\r
156 // Transfer finished
\r
159 AT91C_BASE_AC97C->AC97C_IDR = AT91C_AC97C_COEVT;
\r
160 AT91C_BASE_AC97C->AC97C_COMR &= ~(AT91C_AC97C_TXRDY);
\r
161 if (pTransfer->callback) {
\r
163 pTransfer->callback(pTransfer->pArg, 0, 0);
\r
168 // A sample has been received
\r
169 if (status & AT91C_AC97C_RXRDY) {
\r
172 data = AT91C_BASE_AC97C->AC97C_CORHR;
\r
173 *((unsigned int *) pTransfer->pBuffer) = data;
\r
175 pTransfer->pBuffer += sizeof(unsigned int);
\r
176 pTransfer->numSamples--;
\r
178 // Transfer finished
\r
179 if (pTransfer->numSamples > 0) {
\r
181 data = *((unsigned int *) pTransfer->pBuffer);
\r
182 AT91C_BASE_AC97C->AC97C_COMR &= ~(AT91C_AC97C_RXRDY);
\r
183 AT91C_BASE_AC97C->AC97C_COTHR = data;
\r
185 // Check if transfer is read or write
\r
186 if ((data & AT91C_AC97C_READ) != 0) {
\r
188 AT91C_BASE_AC97C->AC97C_COMR |= AT91C_AC97C_RXRDY;
\r
192 pTransfer->pBuffer += sizeof(unsigned int);
\r
193 AT91C_BASE_AC97C->AC97C_COMR |= AT91C_AC97C_TXRDY;
\r
198 AT91C_BASE_AC97C->AC97C_IDR = AT91C_AC97C_COEVT;
\r
199 AT91C_BASE_AC97C->AC97C_COMR &= ~(AT91C_AC97C_RXRDY);
\r
200 if (pTransfer->callback) {
\r
202 pTransfer->callback(pTransfer->pArg, 0, 0);
\r
208 //------------------------------------------------------------------------------
\r
209 /// Interrupt service routine for channel A, is invoked by AC97C_Handler.
\r
210 //------------------------------------------------------------------------------
\r
211 static void ChannelAHandler(void)
\r
213 unsigned int status;
\r
214 Ac97Transfer *pTransmit = &(ac97c.transfers[AC97C_CHANNEL_A_TRANSMIT]);
\r
215 Ac97Transfer *pReceive = &(ac97c.transfers[AC97C_CHANNEL_A_RECEIVE]);
\r
217 // Read channel A status register
\r
218 status = AT91C_BASE_AC97C->AC97C_CASR;
\r
220 // A buffer has been transmitted
\r
221 if ((status & AT91C_AC97C_ENDTX) != 0) {
\r
223 // Update transfer information
\r
224 if (pTransmit->numSamples > MAX_PDC_COUNTER) {
\r
226 pTransmit->numSamples -= MAX_PDC_COUNTER;
\r
230 pTransmit->numSamples = 0;
\r
233 // Transmit new buffers if necessary
\r
234 if (pTransmit->numSamples > MAX_PDC_COUNTER) {
\r
237 AT91C_BASE_AC97C->AC97C_TNPR = (unsigned int) pTransmit->pBuffer;
\r
238 if (pTransmit->numSamples > 2 * MAX_PDC_COUNTER) {
\r
240 AT91C_BASE_AC97C->AC97C_TNCR = MAX_PDC_COUNTER;
\r
241 pTransmit->pBuffer += MAX_PDC_COUNTER * GetSampleSize(AC97C_CHANNEL_A);
\r
245 AT91C_BASE_AC97C->AC97C_TNCR = pTransmit->numSamples - MAX_PDC_COUNTER;
\r
248 // Only one buffer remaining
\r
251 AT91C_BASE_AC97C->AC97C_CAMR &= ~AT91C_AC97C_ENDTX;
\r
252 AT91C_BASE_AC97C->AC97C_CAMR |= AT91C_AC97C_TXBUFE;
\r
256 // Transmit completed
\r
257 if ((status & AT91C_AC97C_TXBUFE) != 0) {
\r
259 pTransmit->numSamples = 0;
\r
260 AT91C_BASE_AC97C->AC97C_PTCR = AT91C_PDC_TXTDIS;
\r
261 AT91C_BASE_AC97C->AC97C_CAMR &= ~AT91C_AC97C_TXBUFE;
\r
262 if (pTransmit->callback) {
\r
264 pTransmit->callback(pTransmit->pArg, 0, 0);
\r
268 // A buffer has been received
\r
269 if (status & AT91C_AC97C_ENDRX) {
\r
271 if (pReceive->numSamples > MAX_PDC_COUNTER) {
\r
273 pReceive->numSamples -= MAX_PDC_COUNTER;
\r
277 pReceive->numSamples = 0;
\r
280 // Transfer remaining samples
\r
281 if (pReceive->numSamples > MAX_PDC_COUNTER) {
\r
283 AT91C_BASE_AC97C->AC97C_RNPR = (unsigned int) pReceive->pBuffer;
\r
284 if (pReceive->numSamples > 2 * MAX_PDC_COUNTER) {
\r
286 AT91C_BASE_AC97C->AC97C_RNCR = MAX_PDC_COUNTER;
\r
287 pReceive->pBuffer += MAX_PDC_COUNTER * GetSampleSize(AC97C_CHANNEL_A);
\r
291 AT91C_BASE_AC97C->AC97C_RNCR = pReceive->numSamples - MAX_PDC_COUNTER;
\r
294 // Only one buffer remaining
\r
297 AT91C_BASE_AC97C->AC97C_CAMR &= ~(AT91C_AC97C_ENDRX);
\r
298 AT91C_BASE_AC97C->AC97C_CAMR |= AT91C_AC97C_RXBUFF;
\r
302 // Receive complete
\r
303 if ((status & AT91C_AC97C_RXBUFF) != 0) {
\r
305 pReceive->numSamples = 0;
\r
306 AT91C_BASE_AC97C->AC97C_PTCR = AT91C_PDC_RXTDIS;
\r
307 AT91C_BASE_AC97C->AC97C_CAMR &= ~AT91C_AC97C_RXBUFF;
\r
308 if (pReceive->callback) {
\r
310 pReceive->callback(pReceive->pArg, 0, 0);
\r
315 //------------------------------------------------------------------------------
\r
316 // Exported functions
\r
317 //------------------------------------------------------------------------------
\r
318 //------------------------------------------------------------------------------
\r
319 /// This handler function must be called by the AC97C interrupt service routine.
\r
320 /// Identifies which event was activated and calls the associated function.
\r
321 //------------------------------------------------------------------------------
\r
322 void AC97C_Handler(void)
\r
324 unsigned int status;
\r
326 // Get the real interrupt source
\r
327 status = AT91C_BASE_AC97C->AC97C_SR;
\r
328 status &= AT91C_BASE_AC97C->AC97C_IMR;
\r
330 // Check if an event on the codec channel is active
\r
331 if ((status & AT91C_AC97C_COEVT) != 0) {
\r
335 // Check if an event on channel A is active
\r
336 if ((status & AT91C_AC97C_CAEVT) != 0) {
\r
338 ChannelAHandler();
\r
342 //------------------------------------------------------------------------------
\r
343 /// Starts a read or write transfer on the given channel
\r
344 /// \param channel particular channel (AC97C_CHANNEL_A or AC97C_CHANNEL_B).
\r
345 /// \param pBuffer buffer containing the slots to send.
\r
346 /// \param numSamples total number of samples to send.
\r
347 /// \param callback optional callback function.
\r
348 /// \param pArg optional argument to the callback function.
\r
349 //------------------------------------------------------------------------------
\r
350 unsigned char AC97C_Transfer(
\r
351 unsigned char channel,
\r
352 unsigned char *pBuffer,
\r
353 unsigned int numSamples,
\r
354 Ac97Callback callback,
\r
359 Ac97Transfer *pTransfer;
\r
361 SANITY_CHECK(channel <= 5);
\r
362 SANITY_CHECK(pBuffer);
\r
363 SANITY_CHECK(numSamples > 0);
\r
365 // Check that no transfer is pending on the channel
\r
366 pTransfer = &(ac97c.transfers[channel]);
\r
367 if (pTransfer->numSamples > 0) {
\r
369 trace_LOG(trace_WARNING, "-W- AC97C_Transfer: Channel %d is busy\n\r", channel);
\r
370 return AC97C_ERROR_BUSY;
\r
373 // Fill transfer information
\r
374 pTransfer->pBuffer = pBuffer;
\r
375 pTransfer->numSamples = numSamples;
\r
376 pTransfer->callback = callback;
\r
377 pTransfer->pArg = pArg;
\r
379 // Transmit or receive over codec channel
\r
380 if (channel == AC97C_CODEC_TRANSFER) {
\r
383 data = *((unsigned int *) pTransfer->pBuffer);
\r
384 AT91C_BASE_AC97C->AC97C_COTHR = data;
\r
386 // Check if transfer is read or write
\r
387 if ((data & AT91C_AC97C_READ) != 0) {
\r
389 AT91C_BASE_AC97C->AC97C_COMR |= AT91C_AC97C_RXRDY;
\r
393 pTransfer->pBuffer += sizeof(unsigned int);
\r
394 AT91C_BASE_AC97C->AC97C_COMR |= AT91C_AC97C_TXRDY;
\r
397 // Enable interrupts
\r
398 AT91C_BASE_AC97C->AC97C_IER |= AT91C_AC97C_COEVT;
\r
400 // Transmit over channel A
\r
401 else if (channel == AC97C_CHANNEL_A_TRANSMIT) {
\r
404 AT91C_BASE_AC97C->AC97C_PTCR = AT91C_PDC_TXTDIS;
\r
406 // Fill PDC buffers
\r
407 size = min(pTransfer->numSamples, MAX_PDC_COUNTER);
\r
408 AT91C_BASE_AC97C->AC97C_TPR = (unsigned int) pTransfer->pBuffer;
\r
409 AT91C_BASE_AC97C->AC97C_TCR = size;
\r
410 pTransfer->pBuffer += size * GetSampleSize(AC97C_CHANNEL_A);
\r
412 size = min(pTransfer->numSamples - size, MAX_PDC_COUNTER);
\r
415 AT91C_BASE_AC97C->AC97C_TNPR = (unsigned int) pTransfer->pBuffer;
\r
416 AT91C_BASE_AC97C->AC97C_TNCR = size;
\r
417 pTransfer->pBuffer += size * GetSampleSize(AC97C_CHANNEL_A);
\r
420 // Enable interrupts
\r
421 AT91C_BASE_AC97C->AC97C_CAMR |= AT91C_AC97C_PDCEN | AT91C_AC97C_ENDTX;
\r
422 AT91C_BASE_AC97C->AC97C_IER |= AT91C_AC97C_CAEVT;
\r
425 AT91C_BASE_AC97C->AC97C_PTCR = AT91C_PDC_TXTEN;
\r
427 // Receive over channel A
\r
428 else if (channel == AC97C_CHANNEL_A_RECEIVE) {
\r
431 AT91C_BASE_AC97C->AC97C_PTCR = AT91C_PDC_RXTDIS;
\r
433 // Fill PDC buffers
\r
434 size = min(pTransfer->numSamples, MAX_PDC_COUNTER);
\r
435 AT91C_BASE_AC97C->AC97C_RPR = (unsigned int) pTransfer->pBuffer;
\r
436 AT91C_BASE_AC97C->AC97C_RCR = size;
\r
437 pTransfer->pBuffer += size * GetSampleSize(AC97C_CHANNEL_A);
\r
439 size = min(pTransfer->numSamples - size, MAX_PDC_COUNTER);
\r
442 AT91C_BASE_AC97C->AC97C_RNPR = (unsigned int) pTransfer->pBuffer;
\r
443 AT91C_BASE_AC97C->AC97C_RNCR = size;
\r
444 pTransfer->pBuffer += size * GetSampleSize(AC97C_CHANNEL_A);
\r
447 // Enable interrupts
\r
448 AT91C_BASE_AC97C->AC97C_CAMR |= AT91C_AC97C_PDCEN | AT91C_AC97C_ENDRX;
\r
449 AT91C_BASE_AC97C->AC97C_IER |= AT91C_AC97C_CAEVT;
\r
452 AT91C_BASE_AC97C->AC97C_PTCR = AT91C_PDC_RXTEN;
\r
458 //------------------------------------------------------------------------------
\r
459 /// Stop read or write transfer on the given channel.
\r
460 /// \param channel Channel number.
\r
461 //------------------------------------------------------------------------------
\r
462 void AC97C_CancelTransfer(unsigned char channel)
\r
464 unsigned int size = 0;
\r
465 Ac97Transfer *pTransfer;
\r
467 SANITY_CHECK(channel <= AC97C_CHANNEL_B_TRANSMIT);
\r
469 // Save remaining size
\r
470 pTransfer = &(ac97c.transfers[channel]);
\r
471 size = pTransfer->numSamples;
\r
472 pTransfer->numSamples = 0;
\r
475 if (channel == AC97C_CHANNEL_A_TRANSMIT) {
\r
477 AT91C_BASE_AC97C->AC97C_PTCR = AT91C_PDC_TXTDIS;
\r
478 size -= min(size, MAX_PDC_COUNTER) - AT91C_BASE_AC97C->AC97C_TCR;
\r
480 if (channel == AC97C_CHANNEL_A_RECEIVE) {
\r
482 AT91C_BASE_AC97C->AC97C_PTCR = AT91C_PDC_RXTDIS;
\r
483 size -= min(size, MAX_PDC_COUNTER) - AT91C_BASE_AC97C->AC97C_RCR;
\r
486 // Invoke callback if provided
\r
487 if (pTransfer->callback) {
\r
489 pTransfer->callback(pTransfer->pArg, AC97C_ERROR_STOPPED, size);
\r
493 //------------------------------------------------------------------------------
\r
494 /// Initializes the AC97 controller.
\r
495 //------------------------------------------------------------------------------
\r
496 void AC97C_Configure(void)
\r
498 unsigned char channel;
\r
500 // Enable the AC97 controller peripheral clock
\r
501 AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_AC97C);
\r
503 // Enable the peripheral and variable rate adjustment
\r
504 AT91C_BASE_AC97C->AC97C_MR = AT91C_AC97C_ENA | AT91C_AC97C_VRA;
\r
506 // Unassigns all input & output slots
\r
507 AC97C_AssignInputSlots(0, 0xFFFF);
\r
508 AC97C_AssignOutputSlots(0, 0xFFFF);
\r
510 // Install the AC97C interrupt handler
\r
511 AT91C_BASE_AC97C->AC97C_IDR = 0xFFFFFFFF;
\r
512 AIC_ConfigureIT(AT91C_ID_AC97C, 0, AC97C_Handler);
\r
513 AIC_EnableIT(AT91C_ID_AC97C);
\r
515 // Disable PDC transfers
\r
516 AT91C_BASE_AC97C->AC97C_PTCR = AT91C_PDC_TXTDIS | AT91C_PDC_RXTDIS;
\r
518 // Clear channel transfers
\r
519 for (channel = 0; channel < AC97C_CHANNEL_B_TRANSMIT; channel++) {
\r
521 ac97c.transfers[channel].numSamples = 0;
\r
525 //------------------------------------------------------------------------------
\r
526 /// Configures the desired channel with the given value.
\r
527 /// \param channel Channel number.
\r
528 /// \param cfg Configuration value.
\r
529 //------------------------------------------------------------------------------
\r
530 void AC97C_ConfigureChannel(unsigned char channel, unsigned int cfg)
\r
532 SANITY_CHECK((channel == AC97C_CHANNEL_A) || (channel == AC97C_CHANNEL_B));
\r
534 if (channel == AC97C_CHANNEL_A) {
\r
536 AT91C_BASE_AC97C->AC97C_CAMR = cfg;
\r
540 AT91C_BASE_AC97C->AC97C_CBMR = cfg;
\r
544 //------------------------------------------------------------------------------
\r
545 /// Assigns the desired input slots to a particular channel.
\r
546 /// \param channel Channel number (or 0 to unassign slots).
\r
547 /// \param slots Bitfield value of slots to assign.
\r
548 //------------------------------------------------------------------------------
\r
549 void AC97C_AssignInputSlots(unsigned char channel, unsigned int slots)
\r
551 unsigned int value;
\r
554 SANITY_CHECK(channel <= AC97C_CHANNEL_B);
\r
556 // Assign all slots
\r
558 for (i = 3; i < 15; i++) {
\r
560 // Check if slots is selected
\r
563 value = AT91C_BASE_AC97C->AC97C_ICA;
\r
564 value &= ~(0x07 << ((i - 3) * 3));
\r
565 value |= channel << ((i - 3) * 3);
\r
566 AT91C_BASE_AC97C->AC97C_ICA = value;
\r
572 //------------------------------------------------------------------------------
\r
573 /// Assigns the desired output slots to a particular channel.
\r
574 /// \param channel Channel number (or 0 to unassign slots).
\r
575 /// \param slots Bitfield value of slots to assign.
\r
576 //------------------------------------------------------------------------------
\r
577 void AC97C_AssignOutputSlots(unsigned char channel, unsigned int slots)
\r
579 unsigned int value;
\r
582 SANITY_CHECK(channel <= AC97C_CHANNEL_B);
\r
584 // Assign all slots
\r
586 for (i = 3; i < 15; i++) {
\r
588 // Check if slots is selected
\r
591 value = AT91C_BASE_AC97C->AC97C_OCA;
\r
592 value &= ~(0x07 << ((i - 3) * 3));
\r
593 value |= channel << ((i - 3) * 3);
\r
594 AT91C_BASE_AC97C->AC97C_OCA = value;
\r
600 //------------------------------------------------------------------------------
\r
601 /// Returns 1 if no transfer is currently pending on the given channel;
\r
602 /// otherwise, returns 0.
\r
603 /// \param channel Channel number.
\r
604 //------------------------------------------------------------------------------
\r
605 unsigned char AC97C_IsFinished(unsigned char channel)
\r
607 SANITY_CHECK(channel <= AC97C_CHANNEL_B_TRANSMIT);
\r
609 if (ac97c.transfers[channel].numSamples > 0) {
\r
619 //------------------------------------------------------------------------------
\r
620 /// Convenience function for synchronously sending commands to the codec.
\r
621 /// \param address Register address.
\r
622 /// \param data Command data.
\r
623 //------------------------------------------------------------------------------
\r
624 void AC97C_WriteCodec(unsigned char address, unsigned short data)
\r
626 unsigned int sample;
\r
628 sample = (address << 16) | data;
\r
629 AC97C_Transfer(AC97C_CODEC_TRANSFER, (unsigned char *) &sample, 1, 0, 0);
\r
630 while (!AC97C_IsFinished(AC97C_CODEC_TRANSFER));
\r
633 //------------------------------------------------------------------------------
\r
634 /// Convenience function for receiving data from the AC97 codec.
\r
635 /// \param address Register address.
\r
636 //------------------------------------------------------------------------------
\r
637 unsigned short AC97C_ReadCodec(unsigned char address)
\r
639 unsigned int sample;
\r
641 sample = AT91C_AC97C_READ | (address << 16);
\r
642 AC97C_Transfer(AC97C_CODEC_TRANSFER, (unsigned char *) &sample, 1, 0, 0);
\r
643 while (!AC97C_IsFinished(AC97C_CODEC_TRANSFER));
\r
648 //------------------------------------------------------------------------------
\r
649 /// Sets the size in bits of one sample on the given channel.
\r
650 /// \param channel Channel number.
\r
651 /// \param size Size of one sample in bits (10, 16, 18 or 24).
\r
652 //------------------------------------------------------------------------------
\r
653 void AC97C_SetChannelSize(unsigned char channel, unsigned char size)
\r
655 unsigned int bits = 0;
\r
657 SANITY_CHECK((size == 10) || (size == 16) || (size == 18) || (size == 24));
\r
658 SANITY_CHECK((channel == AC97C_CHANNEL_A) || (channel == AC97C_CHANNEL_B));
\r
662 case 10 : bits = AT91C_AC97C_SIZE_10_BITS; break;
\r
663 case 16 : bits = AT91C_AC97C_SIZE_16_BITS; break;
\r
664 case 18 : bits = AT91C_AC97C_SIZE_18_BITS; break;
\r
665 case 20 : bits = AT91C_AC97C_SIZE_20_BITS; break;
\r
668 if (channel == AC97C_CHANNEL_A) {
\r
670 AT91C_BASE_AC97C->AC97C_CAMR &= ~(AT91C_AC97C_SIZE);
\r
671 AT91C_BASE_AC97C->AC97C_CAMR |= bits;
\r
675 AT91C_BASE_AC97C->AC97C_CBMR &= ~(AT91C_AC97C_SIZE);
\r
676 AT91C_BASE_AC97C->AC97C_CBMR |= bits;
\r