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