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