00001
00057 #include <cfg/os.h>
00058 #include <cfg/clock.h>
00059 #include <dev/board.h>
00060 #include <dev/irqreg.h>
00061 #include <dev/twif.h>
00062
00063 #include <stdlib.h>
00064 #include <string.h>
00065 #include <memdebug.h>
00066
00067 #include <sys/event.h>
00068 #include <sys/timer.h>
00069
00070 #include <dev/tlv320dac.h>
00071
00072 #ifndef TWI_SLA_DAC
00073 #define TWI_SLA_DAC 0x1A
00074 #endif
00075
00076
00077
00078
00079 #ifndef TLV320DAC_VOL
00080 #define TLV320DAC_VOL 0x18
00081 #endif
00082
00083
00084
00085
00086 #ifndef SAMPLE_BUFFERS
00087 #if defined (AT91SAM9260_EK)
00088 #define SAMPLE_BUFFERS 32
00089 #else
00090 #define SAMPLE_BUFFERS 3
00091 #endif
00092 #endif
00093
00094
00095
00096
00097 #if defined (MCU_AT91SAM9260)
00098
00099 #define DACI2S_PIO_ID PIOB_ID
00100 #define DACI2S_PINS_A _BV(PB18_TD0_A) | _BV(PB17_TF0_A) | _BV(PB16_TK0_A)
00101 #define DACI2S_PINS_B 0
00102
00103 #else
00104 #define DACI2S_PIO_ID PIOA_ID
00105 #define DACI2S_PINS_A _BV(PA23_TD_A) | _BV(PA21_TF_A) | _BV(PA22_TK_A)
00106 #define DACI2S_PINS_B 0
00107 #endif
00108
00109
00110
00111
00112 #if DACI2S_PIO_ID == PIOA_ID
00113 #define DACI2S_PDR PIOA_PDR
00114 #define DACI2S_ASR PIOA_ASR
00115 #define DACI2S_BSR PIOA_BSR
00116 #elif DACI2S_PIO_ID == PIOB_ID
00117 #define DACI2S_PDR PIOB_PDR
00118 #define DACI2S_ASR PIOB_ASR
00119 #define DACI2S_BSR PIOB_BSR
00120 #endif
00121
00122 volatile uint32_t irq_counter;
00123
00127 static HANDLE i2s_que;
00128
00132 #define PCM_CHANS 2
00133
00137 #define PCM_BITS 16
00138
00142 typedef struct _PCM_BUFFER {
00143 u_short *wbf_dat;
00144 int wbf_siz;
00145 int wbf_len;
00146 } PCM_BUFFER;
00147
00148
00149 unsigned int use_pdc = 1;
00150
00151 static PCM_BUFFER pcm_bufq[SAMPLE_BUFFERS];
00152
00153 static volatile unsigned int brd_idx;
00154
00155 static volatile int brd_pos;
00156
00157 static unsigned int bwr_idx;
00158
00164 static void I2sPdcFill(void)
00165 {
00166 if (brd_idx != bwr_idx) {
00167 if (inr(SSC_TNCR) == 0) {
00168 if (++brd_idx >= SAMPLE_BUFFERS) {
00169 brd_idx = 0;
00170 }
00171 outr(SSC_TNPR, (unsigned int) pcm_bufq[brd_idx].wbf_dat);
00172 outr(SSC_TNCR, pcm_bufq[brd_idx].wbf_len);
00173 }
00174 }
00175 }
00176
00182 static void I2sInterrupt(void *arg)
00183 {
00184 irq_counter++;
00185 if (use_pdc) {
00186 I2sPdcFill();
00187 NutEventPostFromIrq(&i2s_que);
00188 } else {
00189 if (brd_pos >= pcm_bufq[brd_idx].wbf_len) {
00190 brd_pos = 0;
00191 NutEventPostFromIrq(&i2s_que);
00192 if (brd_idx == bwr_idx) {
00193 outr(SSC_THR, 0);
00194 return;
00195 }
00196 if (++brd_idx >= SAMPLE_BUFFERS) {
00197 brd_idx = 0;
00198 }
00199 }
00200 outr(SSC_THR, pcm_bufq[brd_idx].wbf_dat[brd_pos]);
00201 brd_pos++;
00202 }
00203 }
00204
00214 u_char Tlv320DacReadReg(unsigned int reg)
00215 {
00216 return 0xFF;
00217 }
00218
00227 void Tlv320DacWriteReg(unsigned int reg, unsigned int val)
00228 {
00229 u_char txdata[2];
00230
00231 txdata[0] = (u_char)(reg << 1) | (u_char)(val >> 8);
00232 txdata[1] = (u_char)val;
00233 TwMasterTransact(TWI_SLA_DAC, txdata, 2, NULL, 0, 0);
00234 }
00235
00243 static int Tlv320I2sEnable(unsigned int rate)
00244 {
00245
00246 outr(PMC_PCER, _BV(SSC_ID));
00247
00248
00249 outr(DACI2S_ASR, DACI2S_PINS_A);
00250 outr(DACI2S_BSR, DACI2S_PINS_B);
00251
00252
00253 outr(DACI2S_PDR, DACI2S_PINS_A | DACI2S_PINS_B);
00254
00255
00256 outr(SSC_CMR, 0);
00257 outr(SSC_TCMR,
00258 SSC_CKS_PIN |
00259 SSC_START_EDGE_RF |
00260 (1 << SSC_STTDLY_LSB));
00261 outr(SSC_TFMR,
00262 ((PCM_BITS - 1) << SSC_DATLEN_LSB) |
00263 SSC_MSBF);
00264
00265 if (use_pdc) {
00266
00267 outr(SSC_PTCR, PDC_TXTEN);
00268 }
00269 outr(SSC_CR, SSC_TXEN);
00270
00271 return 0;
00272 }
00273
00279 static int Tlv320I2sDisable(void)
00280 {
00281
00282 outr(SSC_IDR, 0xFFFFFFFF);
00283
00284
00285 NutIrqDisable(&sig_SSC);
00286
00287
00288 outr(PMC_PCDR, _BV(SSC_ID));
00289
00290
00291 outr(SSC_CR, SSC_SWRST | SSC_RXDIS | SSC_TXDIS);
00292 outr(SSC_RCMR, 0);
00293 outr(SSC_RFMR, 0);
00294 outr(SSC_PTCR, PDC_RXTDIS);
00295 outr(SSC_PTCR, PDC_TXTDIS);
00296 outr(SSC_TNCR, 0);
00297 outr(SSC_TCR, 0);
00298
00299 return 0;
00300 }
00301
00309 static int Tlv320I2sInit(unsigned int rate)
00310 {
00311
00312 NutRegisterIrqHandler(&sig_SSC, I2sInterrupt, 0);
00313
00314 Tlv320I2sDisable();
00315 Tlv320I2sEnable(rate);
00316
00317
00318 NutIrqEnable(&sig_SSC);
00319
00320 return 0;
00321 }
00322
00323 int Tlv320DacSetRate(unsigned int rate)
00324 {
00325 switch(rate) {
00326 case 8000:
00327 #ifdef AT91SAM7X_EK
00328 Tlv320DacWriteReg(DAC_SRATE, (3 << DAC_SRATE_SR_LSB));
00329 #else
00330 Tlv320DacWriteReg(DAC_SRATE, (3 << DAC_SRATE_SR_LSB) | DAC_SRATE_USB);
00331 #endif
00332 break;
00333 case 8021:
00334 Tlv320DacWriteReg(DAC_SRATE, (11 << DAC_SRATE_SR_LSB) | DAC_SRATE_BOSR | DAC_SRATE_USB);
00335 break;
00336 case 44100:
00337 Tlv320DacWriteReg(DAC_SRATE, (8 << DAC_SRATE_SR_LSB) | DAC_SRATE_BOSR | DAC_SRATE_USB);
00338 break;
00339 case 48000:
00340 Tlv320DacWriteReg(DAC_SRATE, (0 << DAC_SRATE_SR_LSB) | DAC_SRATE_USB);
00341 break;
00342 case 88200:
00343 Tlv320DacWriteReg(DAC_SRATE, (15 << DAC_SRATE_SR_LSB) | DAC_SRATE_BOSR | DAC_SRATE_USB);
00344 break;
00345 case 96000:
00346 Tlv320DacWriteReg(DAC_SRATE, (7 << DAC_SRATE_SR_LSB) | DAC_SRATE_USB);
00347 break;
00348 default:
00349 return -1;
00350 }
00351 return 0;
00352 }
00353
00361 int Tlv320DacInit(unsigned int rate)
00362 {
00363
00364 TwInit(0);
00365
00366 Tlv320DacWriteReg(DAC_RESET, 0);
00367
00368 Tlv320DacWriteReg(DAC_PWRDN, DAC_PWRDN_LINE);
00369 Tlv320DacWriteReg(DAC_PWRDN, 0);
00370
00371 if (Tlv320DacSetRate(rate)) {
00372 Tlv320DacWriteReg(DAC_RESET, 0);
00373 return -1;
00374 }
00375 Tlv320DacWriteReg(DAC_ANA_PATH, DAC_ANA_PATH_DAC | DAC_ANA_PATH_INSEL | DAC_ANA_PATH_MICB);
00376 Tlv320DacWriteReg(DAC_DIG_PATH, 0);
00377
00378 Tlv320DacWriteReg(DAC_DAI_FMT, DAC_DAI_FMT_MS | DAC_DAI_FMT_FOR_I2S);
00379 Tlv320DacWriteReg(DAC_DI_ACT, DAC_DI_ACT_ACT);
00380
00381 Tlv320DacWriteReg(DAC_LHP_VOL, DAC_LHP_VOL_LRS | (0x60 << DAC_LHP_VOL_LHV_LSB));
00382
00383
00384 return Tlv320I2sInit(rate);
00385 }
00386
00392 static int Tlv320DacStart(void)
00393 {
00394 NutIrqDisable(&sig_SSC);
00395 if (use_pdc) {
00396 outr(SSC_IDR, SSC_TXEMPTY);
00397
00398 outr(SSC_PTCR, PDC_TXTEN);
00399 I2sPdcFill();
00400 outr(SSC_IER, SSC_ENDTX);
00401 } else {
00402 outr(SSC_IDR, SSC_ENDTX);
00403
00404 outr(SSC_PTCR, PDC_TXTDIS);
00405 outr(SSC_IER, SSC_TXEMPTY);
00406 }
00407
00408 outr(SSC_CR, SSC_TXEN);
00409 NutIrqEnable(&sig_SSC);
00410
00411 return 0;
00412 }
00413
00419 int Tlv320DacFlush(void)
00420 {
00421 int rc = 0;
00422
00423 while (bwr_idx != brd_idx) {
00424 Tlv320DacStart();
00425 if ((rc = NutEventWait(&i2s_que, 500)) != 0) {
00426 break;
00427 }
00428 }
00429 return rc;
00430 }
00431
00440 int Tlv320DacWrite(void *buf, int len)
00441 {
00442 unsigned int idx;
00443
00444
00445 idx = bwr_idx + 1;
00446 if (idx >= SAMPLE_BUFFERS) {
00447 idx = 0;
00448 }
00449
00450
00451
00452 while (idx == brd_idx) {
00453 if (NutEventWait(&i2s_que, 100)) {
00454 Tlv320DacStart();
00455 }
00456 }
00457
00458
00459
00460
00461 if (pcm_bufq[idx].wbf_siz < len) {
00462 if (pcm_bufq[idx].wbf_siz) {
00463 free(pcm_bufq[idx].wbf_dat);
00464 pcm_bufq[idx].wbf_siz = 0;
00465 }
00466 pcm_bufq[idx].wbf_dat = malloc(len * 2);
00467 if (pcm_bufq[idx].wbf_dat == NULL) {
00468
00469 return -1;
00470 }
00471 pcm_bufq[idx].wbf_siz = len;
00472 }
00473
00474
00475
00476
00477
00478
00479 memcpy(pcm_bufq[idx].wbf_dat, buf, len * 2);
00480 pcm_bufq[idx].wbf_len = len;
00481 bwr_idx = idx;
00482
00483 return 0;
00484 }
00485
00496 int Tlv320DacSetVolume(int left, int right)
00497 {
00498
00499 if (left > DAC_MAX_VOLUME) {
00500 left = DAC_MAX_VOLUME;
00501 }
00502 else if (left < DAC_MIN_VOLUME) {
00503 left = DAC_MIN_VOLUME;
00504 }
00505 if (right > DAC_MAX_VOLUME) {
00506 right = DAC_MAX_VOLUME;
00507 }
00508 else if (right < DAC_MIN_VOLUME) {
00509 right = DAC_MIN_VOLUME;
00510 }
00511 Tlv320DacWriteReg(DAC_LHP_VOL, (unsigned int)(left + 121));
00512 Tlv320DacWriteReg(DAC_RHP_VOL, (unsigned int)(right + 121));
00513
00514 return 0;
00515 }
00516
00517 int Tlv320SwitchMode(void)
00518 {
00519 NutIrqDisable(&sig_SSC);
00520 use_pdc = !use_pdc;
00521 Tlv320DacStart();
00522 return 0;
00523 }