00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057 #include <cfg/arch/avr.h>
00058 #include <cfg/audio.h>
00059
00060 #include <sys/atom.h>
00061 #include <sys/event.h>
00062 #include <sys/timer.h>
00063 #include <sys/heap.h>
00064
00065 #include <dev/irqreg.h>
00066 #include <dev/vscodec.h>
00067
00068 #include <sys/bankmem.h>
00069
00070 #include <stdlib.h>
00071 #include <stddef.h>
00072 #include <string.h>
00073
00078
00079 #if !defined(AUDIO_VS1001K) && !defined(AUDIO_VS1011E) && !defined(AUDIO_VS1002D) && !defined(AUDIO_VS1003B) && !defined(AUDIO_VS1033C) && !defined(AUDIO_VS1053C)
00080 #define AUDIO_VS1001K
00081 #endif
00082
00083 #ifndef VS10XX_FREQ
00084
00085 #define VS10XX_FREQ 12288000UL
00086 #endif
00087
00088 #ifndef VS10XX_HWRST_DURATION
00089
00090 #define VS10XX_HWRST_DURATION 1
00091 #endif
00092
00093 #ifndef VS10XX_HWRST_RECOVER
00094
00095 #define VS10XX_HWRST_RECOVER 4
00096 #endif
00097
00098 #ifndef VS10XX_SWRST_RECOVER
00099
00100 #define VS10XX_SWRST_RECOVER 2
00101 #endif
00102
00103 #ifndef VS10XX_SCI_MODE
00104 #define VS10XX_SCI_MODE 0
00105 #endif
00106
00107 #ifndef VS10XX_SCI_RATE
00108 #define VS10XX_SCI_RATE (VS10XX_FREQ / 6)
00109 #endif
00110
00111 #ifndef VS10XX_SDI_MODE
00112 #define VS10XX_SDI_MODE 0
00113 #endif
00114
00115 #ifndef VS10XX_SDI_RATE
00116 #define VS10XX_SDI_RATE (VS10XX_FREQ / 6)
00117 #endif
00118
00119
00120
00121
00122
00123 #if defined (MCU_AT91R40008) || defined (MCU_AT91SAM7X256) || defined (MCU_AT91SAM7SE512) || defined (MCU_AT91SAM9260)
00124
00125 #if defined(ELEKTOR_IR1)
00126
00127 #define VS_XRESET_BIT 31
00128 #define VS10XX_XCS_BIT PA31_SPI0_NPCS1_A
00129 #define VS10XX_XCS_PORT PIOA_ID
00130 #define VS10XX_XDCS_BIT PB30_SPI0_NPCS2_A
00131 #define VS10XX_XDCS_PORT PIOB_ID
00132 #define VS10XX_DREQ_BIT PA30_IRQ1_A
00133 #define VS10XX_DREQ_PIO_ID PIOA_ID
00134 #define VS10XX_SIGNAL sig_INTERRUPT1
00135
00136 #endif
00137
00138 #if defined(VS10XX_XCS_BIT)
00139
00140 #if !defined(VS10XX_XCS_PORT)
00141 #define VS10XX_XCS_PE_REG PIO_PER
00142 #define VS10XX_XCS_OE_REG PIO_OER
00143 #define VS10XX_XCS_COD_REG PIO_CODR
00144 #define VS10XX_XCS_SOD_REG PIO_SODR
00145 #elif VS10XX_XCS_PORT == PIOA_ID
00146 #define VS10XX_XCS_PE_REG PIOA_PER
00147 #define VS10XX_XCS_OE_REG PIOA_OER
00148 #define VS10XX_XCS_COD_REG PIOA_CODR
00149 #define VS10XX_XCS_SOD_REG PIOA_SODR
00150 #elif VS10XX_XCS_PORT == PIOB_ID
00151 #define VS10XX_XCS_PE_REG PIOB_PER
00152 #define VS10XX_XCS_OE_REG PIOB_OER
00153 #define VS10XX_XCS_COD_REG PIOB_CODR
00154 #define VS10XX_XCS_SOD_REG PIOB_SODR
00155 #elif VS10XX_XCS_PORT == PIOC_ID
00156 #define VS10XX_XCS_PE_REG PIOC_PER
00157 #define VS10XX_XCS_OE_REG PIOC_OER
00158 #define VS10XX_XCS_COD_REG PIOC_CODR
00159 #define VS10XX_XCS_SOD_REG PIOC_SODR
00160 #endif
00161 #define VS10XX_XCS_ENA() \
00162 outr(VS10XX_XCS_PE_REG, _BV(VS10XX_XCS_BIT)); \
00163 outr(VS10XX_XCS_OE_REG, _BV(VS10XX_XCS_BIT))
00164 #define VS10XX_XCS_CLR() outr(VS10XX_XCS_COD_REG, _BV(VS10XX_XCS_BIT))
00165 #define VS10XX_XCS_SET() outr(VS10XX_XCS_SOD_REG, _BV(VS10XX_XCS_BIT))
00166
00167 #else
00168
00169 #define VS10XX_XCS_ENA()
00170 #define VS10XX_XCS_CLR()
00171 #define VS10XX_XCS_SET()
00172
00173 #endif
00174
00175 #if defined(VS10XX_XDCS_BIT)
00176
00177 #if !defined(VS10XX_XDCS_PORT)
00178 #define VS10XX_XDCS_PE_REG PIO_PER
00179 #define VS10XX_XDCS_OE_REG PIO_OER
00180 #define VS10XX_XDCS_COD_REG PIO_CODR
00181 #define VS10XX_XDCS_SOD_REG PIO_SODR
00182 #elif VS10XX_XDCS_PORT == PIOA_ID
00183 #define VS10XX_XDCS_PE_REG PIOA_PER
00184 #define VS10XX_XDCS_OE_REG PIOA_OER
00185 #define VS10XX_XDCS_COD_REG PIOA_CODR
00186 #define VS10XX_XDCS_SOD_REG PIOA_SODR
00187 #elif VS10XX_XDCS_PORT == PIOB_ID
00188 #define VS10XX_XDCS_PE_REG PIOB_PER
00189 #define VS10XX_XDCS_OE_REG PIOB_OER
00190 #define VS10XX_XDCS_COD_REG PIOB_CODR
00191 #define VS10XX_XDCS_SOD_REG PIOB_SODR
00192 #elif VS10XX_XDCS_PORT == PIOC_ID
00193 #define VS10XX_XDCS_PE_REG PIOC_PER
00194 #define VS10XX_XDCS_OE_REG PIOC_OER
00195 #define VS10XX_XDCS_COD_REG PIOC_CODR
00196 #define VS10XX_XDCS_SOD_REG PIOC_SODR
00197 #endif
00198 #define VS10XX_XDCS_ENA() \
00199 outr(VS10XX_XDCS_PE_REG, _BV(VS10XX_XDCS_BIT)); \
00200 outr(VS10XX_XDCS_OE_REG, _BV(VS10XX_XDCS_BIT))
00201 #define VS10XX_XDCS_CLR() outr(VS10XX_XDCS_COD_REG, _BV(VS10XX_XDCS_BIT))
00202 #define VS10XX_XDCS_SET() outr(VS10XX_XDCS_SOD_REG, _BV(VS10XX_XDCS_BIT))
00203
00204 #else
00205
00206 #define VS10XX_XDCS_ENA()
00207 #define VS10XX_XDCS_CLR()
00208 #define VS10XX_XDCS_SET()
00209
00210 #endif
00211
00212 #if defined(VS10XX_DREQ_BIT)
00213
00214 #if !defined(VS10XX_DREQ_PIO_ID)
00215 #define VS10XX_DREQ_PD_REG PIO_PDR
00216 #define VS10XX_DREQ_OD_REG PIO_ODR
00217 #define VS10XX_DREQ_PDS_REG PIO_PDSR
00218 #elif VS10XX_DREQ_PIO_ID == PIOA_ID
00219 #define VS10XX_DREQ_PD_REG PIOA_PDR
00220 #define VS10XX_DREQ_OD_REG PIOA_ODR
00221 #define VS10XX_DREQ_PDS_REG PIOA_PDSR
00222 #elif VS10XX_DREQ_PIO_ID == PIOB_ID
00223 #define VS10XX_DREQ_PD_REG PIOB_PDR
00224 #define VS10XX_DREQ_OD_REG PIOB_ODR
00225 #define VS10XX_DREQ_PDS_REG PIOB_PDSR
00226 #elif VS10XX_DREQ_PIO_ID == PIOC_ID
00227 #define VS10XX_DREQ_PD_REG PIOC_PDR
00228 #define VS10XX_DREQ_OD_REG PIOC_ODR
00229 #define VS10XX_DREQ_PDS_REG PIOC_PDSR
00230 #endif
00231
00232 #define VS10XX_DREQ_ENA() \
00233 outr(VS10XX_DREQ_PD_REG, _BV(VS10XX_DREQ_BIT)); \
00234 outr(VS10XX_DREQ_OD_REG, _BV(VS10XX_DREQ_BIT))
00235 #define VS10XX_DREQ_TST() ((inr(VS10XX_DREQ_PDS_REG) & _BV(VS10XX_DREQ_BIT)) == _BV(VS10XX_DREQ_BIT))
00236
00237 #else
00238
00239 #define VS10XX_DREQ_ENA()
00240 #define VS10XX_DREQ_TST() 0
00241
00242 #endif
00243
00244
00245
00246
00247 #endif
00248
00249
00250 #define VSREQ_PLAY 0x00000001
00251 #define VSREQ_CANCEL 0x00000002
00252 #define VSREQ_BEEP 0x00000004
00253
00254 typedef struct _VSDCB {
00255 int dcb_pbstat;
00256 uint32_t dcb_scmd;
00257 int dcb_crvol;
00258 int dcb_srvol;
00259 int dcb_clvol;
00260 int dcb_slvol;
00261 uint32_t dcb_pbwlo;
00262 uint32_t dcb_pbwhi;
00263 } VSDCB;
00264
00265 static VSDCB dcb;
00266 static u_int vs_chip;
00267
00268
00269
00270
00271
00272 static uint8_t SpiByte(uint8_t val)
00273 {
00274
00275 outr(SPI0_TDR, val);
00276
00277 while((inr(SPI0_SR) & SPI_RDRF) == 0);
00278
00279 val = (uint8_t)inr(SPI0_RDR);
00280
00281 return val;
00282 }
00283
00284 static void SciSelect(void)
00285 {
00286 outr(SPI0_CSR0, (24 << SPI_SCBR_LSB) | SPI_NCPHA);
00287 outr(SPI0_MR, SPI_MODFDIS | SPI_MSTR);
00288 outr(PIOA_CODR, _BV(VS10XX_XCS_BIT));
00289 }
00290
00291 static void SciDeselect(void)
00292 {
00293 outr(PIOA_SODR, _BV(VS10XX_XCS_BIT));
00294 }
00295
00302 static int VsWaitReady(void)
00303 {
00304 int tmo = 16384;
00305
00306 do {
00307 if (VS10XX_DREQ_TST()) {
00308 return 0;
00309 }
00310 } while (tmo--);
00311
00312 return -1;
00313 }
00314
00315
00316
00317
00318
00319
00320
00321 static int VsSdiWrite(CONST uint8_t * data, size_t len)
00322 {
00323 while (len--) {
00324 if (!VS10XX_DREQ_TST() && VsWaitReady()) {
00325 return -1;
00326 }
00327 SpiByte(*data);
00328 data++;
00329 }
00330 return 0;
00331 }
00332
00333
00334
00335
00336
00337
00338
00339
00340 static int VsSdiWrite_P(PGM_P data, size_t len)
00341 {
00342 while (len--) {
00343 if (!VS10XX_DREQ_TST() && VsWaitReady()) {
00344 return -1;
00345 }
00346 SpiByte(PRG_RDB(data));
00347 data++;
00348 }
00349 return 0;
00350 }
00351
00352
00353
00354
00355
00356
00357 static void VsRegWrite(ureg_t reg, uint16_t data)
00358 {
00359 VsWaitReady();
00360 SciSelect();
00361 SpiByte(VS_OPCODE_WRITE);
00362 SpiByte((uint8_t) reg);
00363 SpiByte((uint8_t) (data >> 8));
00364 SpiByte((uint8_t) data);
00365 SciDeselect();
00366 }
00367
00368
00369
00370
00371
00372
00373
00374
00375 static uint16_t VsRegRead(ureg_t reg)
00376 {
00377 uint16_t data;
00378
00379 VsWaitReady();
00380 SciSelect();
00381 SpiByte(VS_OPCODE_READ);
00382 SpiByte((uint8_t) reg);
00383 data = (uint16_t)SpiByte(0) << 8;
00384 data |= SpiByte(0);
00385 SciDeselect();
00386
00387 return data;
00388 }
00389
00400 static int VsBeep(uint8_t fsin, uint8_t ms)
00401 {
00402 static prog_char on[] = { 0x53, 0xEF, 0x6E };
00403 static prog_char off[] = { 0x45, 0x78, 0x69, 0x74 };
00404 static prog_char end[] = { 0x00, 0x00, 0x00, 0x00 };
00405
00406 VsRegWrite(VS_MODE_REG, VS_SM_TESTS | VS_SM_SDINEW);
00407
00408 fsin = 56 + (fsin & 7) * 9;
00409 VsSdiWrite_P(on, sizeof(on));
00410 VsSdiWrite(&fsin, 1);
00411 VsSdiWrite_P(end, sizeof(end));
00412 NutDelay(ms);
00413 VsSdiWrite_P(off, sizeof(off));
00414 VsSdiWrite_P(end, sizeof(end));
00415
00416 VsRegWrite(VS_MODE_REG, VS_SM_SDINEW);
00417
00418 return 0;
00419 }
00420
00421 static HANDLE vs_ready;
00422
00423 static void VsInterrupt(void *arg)
00424 {
00425 NutEventPostFromIrq(&vs_ready);
00426 }
00427
00428 THREAD(FeederThread, arg)
00429 {
00430 char *bp;
00431 size_t avail;
00432 int filled;
00433 uint8_t crgain;
00434 uint8_t srgain;
00435 uint8_t clgain;
00436 uint8_t slgain;
00437
00438 NutSleep(500);
00439
00440 dcb.dcb_slvol = dcb.dcb_clvol = -12;
00441 dcb.dcb_srvol = dcb.dcb_crvol = -12;
00442 srgain = (uint8_t)(-2 * dcb.dcb_srvol);
00443 crgain = 254;
00444 slgain = (uint8_t)(-2 * dcb.dcb_slvol);
00445 clgain = 254;
00446 VsRegWrite(VS_VOL_REG, ((uint16_t)clgain << VS_VOL_LEFT_LSB) | ((uint16_t)crgain << VS_VOL_RIGHT_LSB));
00447
00448
00449 while (NutRegisterIrqHandler(&VS10XX_SIGNAL, VsInterrupt, NULL)) {
00450 NutSleep(1000);
00451 }
00452
00453
00454 NutIrqSetMode(&VS10XX_SIGNAL, NUT_IRQMODE_RISINGEDGE);
00455
00456 VS10XX_DREQ_ENA();
00457 NutIrqEnable(&VS10XX_SIGNAL);
00458
00459 for (;;) {
00460 NutEventWait(&vs_ready, 100);
00461 if (!VS10XX_DREQ_TST()) {
00462 continue;
00463 }
00464 if (dcb.dcb_scmd) {
00465 if (dcb.dcb_scmd & VSREQ_CANCEL) {
00466 NutSegBufReset();
00467 }
00468 if (dcb.dcb_scmd & VSREQ_BEEP) {
00469 VsBeep(2, 100);
00470 }
00471 dcb.dcb_scmd &= VSREQ_PLAY;
00472 }
00473 if (NutSegBufUsed() < dcb.dcb_pbwlo) {
00474 dcb.dcb_pbstat = CODEC_STATUS_IDLE;
00475 if (crgain != 254) {
00476 clgain = crgain = 254;
00477 VsRegWrite(VS_VOL_REG, ((uint16_t)clgain << VS_VOL_LEFT_LSB) | ((uint16_t)crgain << VS_VOL_RIGHT_LSB));
00478 }
00479 while (NutSegBufUsed() < dcb.dcb_pbwhi) {
00480 if (dcb.dcb_scmd) {
00481 if (dcb.dcb_scmd & VSREQ_PLAY) {
00482 dcb.dcb_pbwhi = dcb.dcb_pbwlo = NutSegBufUsed() / 2;
00483 }
00484 break;
00485 }
00486 NutSleep(100);
00487 }
00488 }
00489 dcb.dcb_scmd &= ~VSREQ_PLAY;
00490 if (dcb.dcb_scmd) {
00491 continue;
00492 }
00493
00494 outr(SPI0_CSR0, (12 << SPI_SCBR_LSB) | SPI_NCPHA);
00495 outr(SPI0_MR, SPI_MODFDIS | SPI_MSTR);
00496 if (dcb.dcb_pbstat != CODEC_STATUS_PLAYING) {
00497 outr(PIOB_CODR, _BV(30));
00498 while (!VS10XX_DREQ_TST()) {
00499 SpiByte(0);
00500 }
00501 outr(PIOB_SODR, _BV(30));
00502 }
00503
00504 for (;;) {
00505 if (!VS10XX_DREQ_TST()) {
00506 break;
00507 }
00508 bp = NutSegBufReadRequest(&avail);
00509 if (avail == 0) {
00510 dcb.dcb_pbstat = CODEC_STATUS_IDLE;
00511 if (crgain != 254) {
00512 clgain = crgain = 254;
00513 VsRegWrite(VS_VOL_REG, ((uint16_t)clgain << VS_VOL_LEFT_LSB) | ((uint16_t)crgain << VS_VOL_RIGHT_LSB));
00514 }
00515 break;
00516 }
00517 outr(PIOB_CODR, _BV(30));
00518 for (filled = 0; avail--; filled++, bp++) {
00519 if (!VS10XX_DREQ_TST()) {
00520 dcb.dcb_pbstat = CODEC_STATUS_PLAYING;
00521 break;
00522 }
00523 SpiByte(*bp);
00524 }
00525 outr(PIOB_SODR, _BV(30));
00526 NutSegBufReadLast(filled);
00527 }
00528 if (dcb.dcb_clvol != dcb.dcb_slvol || dcb.dcb_crvol != dcb.dcb_srvol) {
00529 srgain = (uint8_t)(-2 * dcb.dcb_srvol);
00530 slgain = (uint8_t)(-2 * dcb.dcb_slvol);
00531
00532 dcb.dcb_clvol = dcb.dcb_slvol;
00533 dcb.dcb_crvol = dcb.dcb_srvol;
00534 }
00535 else if (srgain != crgain || slgain != clgain) {
00536 int diff = (int)srgain - (int)crgain;
00537
00538 if (diff > 4) {
00539 diff = 4;
00540 }
00541 else if (diff < -4) {
00542 diff = -4;
00543 }
00544 crgain = (uint8_t)((int)crgain + diff);
00545
00546 diff = (int)slgain - (int)clgain;
00547 if (diff > 4) {
00548 diff = 4;
00549 }
00550 else if (diff < -4) {
00551 diff = -4;
00552 }
00553 clgain = (uint8_t)((int)clgain + diff);
00554 VsRegWrite(VS_VOL_REG, ((uint16_t)clgain << VS_VOL_LEFT_LSB) | ((uint16_t)crgain << VS_VOL_RIGHT_LSB));
00555 }
00556 }
00557 }
00558
00559 static int VsPlayerFlush(void)
00560 {
00561 int tmo = 1000;
00562
00563
00564 while(dcb.dcb_pbstat == CODEC_STATUS_PLAYING) {
00565 NutSleep(1);
00566 if (tmo-- <= 0) {
00567 return -1;
00568 }
00569 }
00570 return 0;
00571 }
00572
00581 static int VsWrite(NUTFILE * fp, CONST void *data, int len)
00582 {
00583 char *buf;
00584 size_t rbytes;
00585
00586
00587 if (data == NULL || len == 0) {
00588 return VsPlayerFlush();
00589 }
00590 if (len) {
00591 buf = NutSegBufWriteRequest(&rbytes);
00592 if (len > rbytes) {
00593 len = rbytes;
00594 }
00595 if (len) {
00596 memcpy(buf, data, len);
00597 }
00598 NutSegBufWriteLast(len);
00599 }
00600 return len;
00601 }
00602
00603 #ifdef __HARVARD_ARCH__
00604
00626 static int VsWrite_P(NUTFILE * nfp, PGM_P buffer, int len)
00627 {
00628 return -1;
00629 }
00630 #endif
00631
00637 static NUTFILE *VsOpen(NUTDEVICE * dev, CONST char *name, int mode, int acc)
00638 {
00639 NUTFILE *nfp;
00640
00641 VsRegWrite(VS_MODE_REG, VS_SM_RESET | VS_SM_SDINEW);
00642 NutSleep(2);
00643
00644 nfp = malloc(sizeof(NUTFILE));
00645 nfp->nf_next = NULL;
00646 nfp->nf_dev = dev;
00647 nfp->nf_fcb = NULL;
00648
00649 NutSegBufReset();
00650
00651 return nfp;
00652 }
00653
00657 static int VsClose(NUTFILE * nfp)
00658 {
00659 int rc = VsPlayerFlush();
00660
00661 if (nfp) {
00662 free(nfp);
00663 }
00664 return rc;
00665 }
00666
00667 static int VsPlayBufferInit(uint32_t size)
00668 {
00669 if (dcb.dcb_pbstat != CODEC_STATUS_IDLE) {
00670 return -1;
00671 }
00672 if (NutSegBufInit((size_t)size) == NULL) {
00673 return -1;
00674 }
00675 dcb.dcb_pbwlo = NutSegBufAvailable() / 3;
00676 dcb.dcb_pbwhi = dcb.dcb_pbwlo * 2;
00677
00678 return 0;
00679 }
00680
00700 static int VsIOCtl(NUTDEVICE * dev, int req, void *conf)
00701 {
00702 int rc = 0;
00703 uint32_t *lvp = (uint32_t *) conf;
00704 int *ivp = (int *) conf;
00705 int iv = *ivp;
00706
00707 switch (req) {
00708 case AUDIO_PLAY:
00709
00710 if (dcb.dcb_pbstat != CODEC_STATUS_PLAYING) {
00711 dcb.dcb_scmd |= VSREQ_PLAY;
00712 }
00713 break;
00714 case AUDIO_CANCEL:
00715
00716 if (dcb.dcb_pbstat == CODEC_STATUS_PLAYING) {
00717 dcb.dcb_scmd |= VSREQ_CANCEL;
00718 }
00719 break;
00720 case AUDIO_GET_STATUS:
00721 *ivp = dcb.dcb_pbstat;
00722 break;
00723 case AUDIO_GET_PLAYGAIN:
00724 if (dcb.dcb_crvol >= dcb.dcb_clvol) {
00725 *ivp = dcb.dcb_crvol;
00726 }
00727 else {
00728 *ivp = dcb.dcb_clvol;
00729 }
00730 break;
00731 case AUDIO_SET_PLAYGAIN:
00732 if (iv > AUDIO_DAC_MAX_GAIN) {
00733 iv = AUDIO_DAC_MAX_GAIN;
00734 }
00735 if (iv < AUDIO_DAC_MIN_GAIN) {
00736 iv = AUDIO_DAC_MIN_GAIN;
00737 }
00738 dcb.dcb_slvol = dcb.dcb_srvol = iv;
00739 break;
00740 case AUDIO_GET_PBSIZE:
00741 *lvp = NutSegBufAvailable() + NutSegBufUsed();
00742 break;
00743 case AUDIO_SET_PBSIZE:
00744 rc = VsPlayBufferInit(*lvp);
00745 break;
00746 case AUDIO_GET_PBLEVEL:
00747 *lvp = NutSegBufUsed();
00748 break;
00749 case AUDIO_GET_PBWLOW:
00750 *lvp = dcb.dcb_pbwlo;
00751 break;
00752 case AUDIO_SET_PBWLOW:
00753 dcb.dcb_pbwlo = *lvp;
00754 break;
00755 case AUDIO_GET_PBWHIGH:
00756 *lvp = dcb.dcb_pbwhi;
00757 break;
00758 case AUDIO_SET_PBWHIGH:
00759 dcb.dcb_pbwhi = *lvp;
00760 break;
00761 case AUDIO_BEEP:
00762 dcb.dcb_scmd |= VSREQ_BEEP;
00763 break;
00764 #if 0
00765 case AUDIO_GET_DECINFO:
00766
00767 break;
00768 case AUDIO_GET_DECCAPS:
00769
00770 break;
00771 case AUDIO_GET_DECFMTS:
00772
00773 break;
00774 case AUDIO_SET_DECFMTS:
00775
00776 break;
00777 case AUDIO_GET_CODINFO:
00778
00779 break;
00780 case AUDIO_GET_CODCAPS:
00781
00782 break;
00783 case AUDIO_GET_CODFMTS:
00784
00785 break;
00786 case AUDIO_SET_CODFMTS:
00787
00788 break;
00789 case AUDIO_GET_MIDINFO:
00790
00791 break;
00792 case AUDIO_GET_MIDCAPS:
00793
00794 break;
00795 #endif
00796 default:
00797 rc = -1;
00798 break;
00799 }
00800 return rc;
00801 }
00802
00803
00804
00805
00806 static int VsInit(NUTDEVICE * dev)
00807 {
00808 uint16_t mode;
00809
00810
00811 outr(PIOB_PER, _BV(VS_XRESET_BIT));
00812 outr(PIOB_SODR, _BV(VS_XRESET_BIT));
00813 outr(PIOB_OER, _BV(VS_XRESET_BIT));
00814 NutSleep(3);
00815
00816 VsRegRead(VS_MODE_REG);
00817 mode = VsRegRead(VS_MODE_REG);
00818 if ((mode & VS_SM_SDINEW) == 0) {
00819 VsRegWrite(VS_MODE_REG, VS_SM_RESET | VS_SM_SDINEW);
00820 NutSleep(2);
00821 }
00822 vs_chip = (VsRegRead(VS_STATUS_REG) & VS_SS_VER) >> VS_SS_VER_LSB;
00823 #if VS10XX_FREQ < 20000000UL
00824 VsRegWrite(VS_CLOCKF_REG, (uint16_t)(VS_CF_DOUBLER | (VS10XX_FREQ / 2000UL)));
00825 #else
00826 VsRegWrite(VS_CLOCKF_REG, (uint16_t)(VS10XX_FREQ / 2000UL));
00827 #endif
00828 if (vs_chip == 0) {
00829
00830 VsRegWrite(VS_INT_FCTLH_REG, 0x8008);
00831 }
00832
00833 if (VsPlayBufferInit(0)) {
00834 return -1;
00835 }
00836 if (NutThreadCreate("vsdeco", FeederThread, NULL, 1024) == 0) {
00837 return -1;
00838 }
00839 return 0;
00840 }
00841
00852 NUTDEVICE devVsCodec = {
00853 0,
00854 {'a', 'u', 'd', 'i', 'o', '0', 0, 0, 0},
00855 IFTYP_CHAR,
00856 0,
00857 0,
00858 0,
00859 &dcb,
00860 VsInit,
00861 VsIOCtl,
00862 NULL,
00863 VsWrite,
00864 #ifdef __HARVARD_ARCH__
00865 VsWrite_P,
00866 #endif
00867 VsOpen,
00868 VsClose,
00869 NULL
00870 };
00871