tlv320dac.c

Go to the documentation of this file.
00001 
00050 #include <cfg/os.h>
00051 #include <cfg/clock.h>
00052 #include <dev/board.h>
00053 #include <dev/irqreg.h>
00054 #include <dev/twif.h>
00055 
00056 #include <stdlib.h>
00057 #include <string.h>
00058 
00059 #include <sys/event.h>
00060 #include <sys/timer.h>
00061 
00062 #include <dev/tlv320dac.h>
00063 
00064 #ifndef TWI_SLA_DAC
00065 #define TWI_SLA_DAC     0x1A
00066 #endif
00067 
00068 /*
00069  * Initial volume.
00070  */
00071 #ifndef TLV320DAC_VOL
00072 #define TLV320DAC_VOL   0x18
00073 #endif
00074 
00075 /*
00076  * Number of PCM buffers.
00077  */
00078 #ifndef SAMPLE_BUFFERS
00079 #if defined (AT91SAM9260_EK)
00080 #define SAMPLE_BUFFERS  32
00081 #else
00082 #define SAMPLE_BUFFERS  3
00083 #endif
00084 #endif
00085 
00086 /*
00087  * Select I2S pins.
00088  */
00089 #if defined (MCU_AT91SAM9260) /* _EK */
00090 
00091 #define DACI2S_PIO_ID   PIOB_ID
00092 #define DACI2S_PINS_A   _BV(PB18_TD0_A) | _BV(PB17_TF0_A) | _BV(PB16_TK0_A)
00093 #define DACI2S_PINS_B   0
00094 
00095 #else                           /* _EK */
00096 #define DACI2S_PIO_ID   PIOA_ID
00097 #define DACI2S_PINS_A   _BV(PA23_TD_A) | _BV(PA21_TF_A) | _BV(PA22_TK_A)
00098 #define DACI2S_PINS_B   0
00099 #endif                          /* _EK */
00100 
00101 /*
00102  * Determine PIO used by I2S.
00103  */
00104 #if DACI2S_PIO_ID == PIOA_ID    /* DACI2S_PIO_ID */
00105 #define DACI2S_PDR  PIOA_PDR
00106 #define DACI2S_ASR  PIOA_ASR
00107 #define DACI2S_BSR  PIOA_BSR
00108 #elif DACI2S_PIO_ID == PIOB_ID  /* DACI2S_PIO_ID */
00109 #define DACI2S_PDR  PIOB_PDR
00110 #define DACI2S_ASR  PIOB_ASR
00111 #define DACI2S_BSR  PIOB_BSR
00112 #endif                          /* DACI2S_PIO_ID */
00113 
00114 volatile uint32_t irq_counter;
00115 
00119 static HANDLE i2s_que;
00120 
00124 #define PCM_CHANS   2
00125 
00129 #define PCM_BITS    16
00130 
00134 typedef struct _PCM_BUFFER {
00135     u_short *wbf_dat;           
00136     int wbf_siz;                
00137     int wbf_len;                
00138 } PCM_BUFFER;
00139 
00140 /* Enable PDC hardware. */
00141 u_int use_pdc = 1;
00142 /* PCM buffer queue. */
00143 static PCM_BUFFER pcm_bufq[SAMPLE_BUFFERS];
00144 /* PCM buffer read index. */
00145 static volatile u_int brd_idx;
00146 /* PCM buffer read position. */
00147 static volatile int brd_pos;
00148 /* PCM buffer write index. */
00149 static u_int bwr_idx;
00150 
00156 static void I2sPdcFill(void)
00157 {
00158     if (brd_idx != bwr_idx) {
00159         if (inr(SSC_TNCR) == 0) {
00160             if (++brd_idx >= SAMPLE_BUFFERS) {
00161                 brd_idx = 0;
00162             }
00163             outr(SSC_TNPR, (u_int) pcm_bufq[brd_idx].wbf_dat);
00164             outr(SSC_TNCR, pcm_bufq[brd_idx].wbf_len);
00165         }
00166     }
00167 }
00168 
00174 static void I2sInterrupt(void *arg)
00175 {
00176     irq_counter++;
00177     if (use_pdc) {
00178         I2sPdcFill();
00179         NutEventPostFromIrq(&i2s_que);
00180     } else {
00181         if (brd_pos >= pcm_bufq[brd_idx].wbf_len) {
00182             brd_pos = 0;
00183             NutEventPostFromIrq(&i2s_que);
00184             if (brd_idx == bwr_idx) {
00185                 outr(SSC_THR, 0);
00186                 return;
00187             }
00188             if (++brd_idx >= SAMPLE_BUFFERS) {
00189                 brd_idx = 0;
00190             }
00191         }
00192         outr(SSC_THR, pcm_bufq[brd_idx].wbf_dat[brd_pos]);
00193         brd_pos++;
00194     }
00195 }
00196 
00206 u_char Tlv320DacReadReg(u_int reg)
00207 {
00208     return 0xFF;
00209 }
00210 
00219 void Tlv320DacWriteReg(u_int reg, u_int val)
00220 {
00221     u_char txdata[2];
00222 
00223     txdata[0] = (u_char)(reg << 1) | (u_char)(val >> 8);
00224     txdata[1] = (u_char)val;
00225     TwMasterTransact(TWI_SLA_DAC, txdata, 2, NULL, 0, 0);
00226 }
00227 
00235 static int Tlv320I2sEnable(u_int rate)
00236 {
00237     /* Enable SSC clock. */
00238     outr(PMC_PCER, _BV(SSC_ID));
00239 
00240     /* Select SSC peripheral functions. */
00241     outr(DACI2S_ASR, DACI2S_PINS_A);
00242     outr(DACI2S_BSR, DACI2S_PINS_B);
00243 
00244     /* Enable SSC peripheral pins. */
00245     outr(DACI2S_PDR, DACI2S_PINS_A | DACI2S_PINS_B);
00246 
00247     /* Configure 16-bit stereo I2S transmit format. */
00248     outr(SSC_CMR, 0);
00249     outr(SSC_TCMR,              /* Set transmit clock mode. */
00250         SSC_CKS_PIN |            /* Use external clock at TK. */
00251         SSC_START_EDGE_RF |     /* Start transmission on any edge. */
00252         (1 << SSC_STTDLY_LSB)); /* Delay start by 1 cycle. */
00253     outr(SSC_TFMR,              /* Set transmit frame mode. */
00254         ((PCM_BITS - 1) << SSC_DATLEN_LSB) |   /* Transmit 16 bits. */
00255         SSC_MSBF);              /* Most significant bit first. */
00256 
00257     if (use_pdc) {
00258         /* Enable transmitter in PDC mode. */
00259         outr(SSC_PTCR, PDC_TXTEN);
00260     }
00261     outr(SSC_CR, SSC_TXEN);
00262 
00263     return 0;
00264 }
00265 
00271 static int Tlv320I2sDisable(void)
00272 {
00273     /* Disable all interrupts. */
00274     outr(SSC_IDR, 0xFFFFFFFF);
00275 
00276     /* Disable SSC interrupt. */
00277     NutIrqDisable(&sig_SSC);
00278 
00279     /* Disable SSC clock. */
00280     outr(PMC_PCDR, _BV(SSC_ID));
00281 
00282     /* Reset receiver and transmitter. */
00283     outr(SSC_CR, SSC_SWRST | SSC_RXDIS | SSC_TXDIS);
00284     outr(SSC_RCMR, 0);
00285     outr(SSC_RFMR, 0);
00286     outr(SSC_PTCR, PDC_RXTDIS);
00287     outr(SSC_PTCR, PDC_TXTDIS);
00288     outr(SSC_TNCR, 0);
00289     outr(SSC_TCR, 0);
00290 
00291     return 0;
00292 }
00293 
00301 static int Tlv320I2sInit(u_int rate)
00302 {
00303     /* Register SSC interrupt handler. */
00304     NutRegisterIrqHandler(&sig_SSC, I2sInterrupt, 0);
00305 
00306     Tlv320I2sDisable();
00307     Tlv320I2sEnable(rate);
00308 
00309     /* Enable SSC interrupt. */
00310     NutIrqEnable(&sig_SSC);
00311 
00312     return 0;
00313 }
00314 
00315 int Tlv320DacSetRate(u_int rate)
00316 {
00317     switch(rate) {
00318     case 8000:
00319 #ifdef AT91SAM7X_EK
00320         Tlv320DacWriteReg(DAC_SRATE, (3 << DAC_SRATE_SR_LSB));
00321 #else
00322         Tlv320DacWriteReg(DAC_SRATE, (3 << DAC_SRATE_SR_LSB) | DAC_SRATE_USB);
00323 #endif
00324         break;
00325     case 8021:      
00326         Tlv320DacWriteReg(DAC_SRATE, (11 << DAC_SRATE_SR_LSB) | DAC_SRATE_BOSR | DAC_SRATE_USB);
00327         break;
00328     case 44100:     
00329         Tlv320DacWriteReg(DAC_SRATE, (8 << DAC_SRATE_SR_LSB) | DAC_SRATE_BOSR | DAC_SRATE_USB);
00330         break;
00331     case 48000:     
00332         Tlv320DacWriteReg(DAC_SRATE, (0 << DAC_SRATE_SR_LSB) | DAC_SRATE_USB);
00333         break;
00334     case 88200:     
00335         Tlv320DacWriteReg(DAC_SRATE, (15 << DAC_SRATE_SR_LSB) | DAC_SRATE_BOSR | DAC_SRATE_USB);
00336         break;
00337     case 96000:     
00338         Tlv320DacWriteReg(DAC_SRATE, (7 << DAC_SRATE_SR_LSB) | DAC_SRATE_USB);
00339         break;
00340     default:        
00341         return -1;
00342     }
00343     return 0;
00344 }
00345 
00353 int Tlv320DacInit(u_int rate)
00354 {
00355     /* Initialize TWI. */
00356     TwInit(0);
00357 
00358     Tlv320DacWriteReg(DAC_RESET, 0);
00359     /* Power down line in. */
00360     Tlv320DacWriteReg(DAC_PWRDN, DAC_PWRDN_LINE);
00361     Tlv320DacWriteReg(DAC_PWRDN, 0);
00362     /* Set sampling rate. */
00363     if (Tlv320DacSetRate(rate)) {
00364         Tlv320DacWriteReg(DAC_RESET, 0);
00365         return -1;
00366     }
00367     Tlv320DacWriteReg(DAC_ANA_PATH, DAC_ANA_PATH_DAC | DAC_ANA_PATH_INSEL | DAC_ANA_PATH_MICB);
00368     Tlv320DacWriteReg(DAC_DIG_PATH, 0);
00369     /* I2S master. */
00370     Tlv320DacWriteReg(DAC_DAI_FMT, DAC_DAI_FMT_MS | DAC_DAI_FMT_FOR_I2S);
00371     Tlv320DacWriteReg(DAC_DI_ACT, DAC_DI_ACT_ACT);
00372 
00373     Tlv320DacWriteReg(DAC_LHP_VOL, DAC_LHP_VOL_LRS | (0x60 << DAC_LHP_VOL_LHV_LSB));
00374 
00375     /* Initialize I2S. */
00376     return Tlv320I2sInit(rate);
00377 }
00378 
00384 static int Tlv320DacStart(void)
00385 {
00386     NutIrqDisable(&sig_SSC);
00387     if (use_pdc) {
00388         outr(SSC_IDR, SSC_TXEMPTY);
00389         /* Enable transmitter in PDC mode. */
00390         outr(SSC_PTCR, PDC_TXTEN);
00391         I2sPdcFill();
00392         outr(SSC_IER, SSC_ENDTX);
00393     } else {
00394         outr(SSC_IDR, SSC_ENDTX);
00395         /* Disable transmitter in PDC mode. */
00396         outr(SSC_PTCR, PDC_TXTDIS);
00397         outr(SSC_IER, SSC_TXEMPTY);
00398     }
00399     /* Enable transmitter. */
00400     outr(SSC_CR, SSC_TXEN);
00401     NutIrqEnable(&sig_SSC);
00402 
00403     return 0;
00404 }
00405 
00411 int Tlv320DacFlush(void)
00412 {
00413     int rc = 0;
00414 
00415     while (bwr_idx != brd_idx) {
00416         Tlv320DacStart();
00417         if ((rc = NutEventWait(&i2s_que, 500)) != 0) {
00418             break;
00419         }
00420     }
00421     return rc;
00422 }
00423 
00432 int Tlv320DacWrite(void *buf, int len)
00433 {
00434     u_int idx;
00435 
00436     /* Move to the next buffer to write to. */
00437     idx = bwr_idx + 1;
00438     if (idx >= SAMPLE_BUFFERS) {
00439         idx = 0;
00440     }
00441 
00442     /* If all buffers are filled, wait for an event posted by the
00443        interrupt routine. */
00444     while (idx == brd_idx) {
00445         if (NutEventWait(&i2s_que, 100)) {
00446             Tlv320DacStart();
00447         }
00448     }
00449 
00450     /*
00451      * Check, if the current buffer size is too small or not allocated.
00452      */
00453     if (pcm_bufq[idx].wbf_siz < len) {
00454         if (pcm_bufq[idx].wbf_siz) {
00455             free(pcm_bufq[idx].wbf_dat);
00456             pcm_bufq[idx].wbf_siz = 0;
00457         }
00458         pcm_bufq[idx].wbf_dat = malloc(len * 2);
00459         if (pcm_bufq[idx].wbf_dat == NULL) {
00460             /* Out of memory. */
00461             return -1;
00462         }
00463         pcm_bufq[idx].wbf_siz = len;
00464     }
00465 
00466     /*
00467      * At this point we got an available buffer with sufficient size.
00468      * Move the data to it, set the number of valid bytes and update
00469      * the write (producer) index.
00470      */
00471     memcpy(pcm_bufq[idx].wbf_dat, buf, len * 2);
00472     pcm_bufq[idx].wbf_len = len;
00473     bwr_idx = idx;
00474 
00475     return 0;
00476 }
00477 
00488 int Tlv320DacSetVolume(int left, int right)
00489 {
00490     /* Cut to limits. */
00491     if (left > DAC_MAX_VOLUME) {
00492         left = DAC_MAX_VOLUME;
00493     }
00494     else if (left < DAC_MIN_VOLUME) {
00495         left = DAC_MIN_VOLUME;
00496     }
00497     if (right > DAC_MAX_VOLUME) {
00498         right = DAC_MAX_VOLUME;
00499     }
00500     else if (right < DAC_MIN_VOLUME) {
00501         right = DAC_MIN_VOLUME;
00502     }
00503     Tlv320DacWriteReg(DAC_LHP_VOL, (u_int)(left + 121));
00504     Tlv320DacWriteReg(DAC_RHP_VOL, (u_int)(right + 121));
00505 
00506     return 0;
00507 }
00508 
00509 int Tlv320SwitchMode(void)
00510 {
00511     NutIrqDisable(&sig_SSC);
00512     use_pdc = !use_pdc;
00513     Tlv320DacStart();
00514     return 0;
00515 }

© 2000-2007 by egnite Software GmbH - visit http://www.ethernut.de/