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