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