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