spi_vscodec0.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2008-2009 by egnite GmbH
00003  * Copyright (C) 2001-2007 by egnite Software GmbH
00004  *
00005  * All rights reserved.
00006  *
00007  * Redistribution and use in source and binary forms, with or without
00008  * modification, are permitted provided that the following conditions
00009  * are met:
00010  *
00011  * 1. Redistributions of source code must retain the above copyright
00012  *    notice, this list of conditions and the following disclaimer.
00013  * 2. Redistributions in binary form must reproduce the above copyright
00014  *    notice, this list of conditions and the following disclaimer in the
00015  *    documentation and/or other materials provided with the distribution.
00016  * 3. Neither the name of the copyright holders nor the names of
00017  *    contributors may be used to endorse or promote products derived
00018  *    from this software without specific prior written permission.
00019  *
00020  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00021  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00022  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00023  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00024  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00025  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00026  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
00027  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
00028  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00029  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
00030  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00031  * SUCH DAMAGE.
00032  *
00033  * For additional information see http://www.ethernut.de/
00034  */
00035 
00036 /*
00037  * $Id: spi_vscodec0.c,v 1.1 2009/02/06 15:48:08 haraldkipp Exp $
00038  */
00039 
00040 #include <dev/gpio.h>
00041 #include <dev/irqreg.h>
00042 #include <dev/vscodec.h>
00043 #include <dev/spibus.h>
00044 
00045 #include <sys/event.h>
00046 #include <sys/timer.h>
00047 #include <sys/heap.h>
00048 #include <sys/nutdebug.h>
00049 #include <sys/bankmem.h>
00050 
00051 #include <stdlib.h>
00052 #include <string.h>
00053 
00054 #if defined(VSCODEC0_SIGNAL_IRQ) && defined(VSCODEC0_DREQ_PORT) && defined(VSCODEC0_DREQ_BIT)
00055 #if defined(VSCODEC0_XCS_PORT) && defined(VSCODEC0_XCS_BIT)
00056 #define VSCODEC0_CONFIGURED 1
00057 #endif
00058 #endif
00059 
00060 #if VSCODEC0_CONFIGURED
00061 
00066 
00067 #ifndef NUT_THREAD_VSCODEC0STACK
00068 #if defined(__AVR__)
00069 /* avr-gcc optimized code used 88 bytes. */
00070 #define NUT_THREAD_VSCODEC0STACK    128
00071 #else
00072 /* arm-elf-gcc optimized code used 112 bytes. */
00073 #define NUT_THREAD_VSCODEC0STACK    192
00074 #endif
00075 #endif
00076 
00077 #ifndef VSCODEC0_HWRST_DURATION
00078 
00079 #define VSCODEC0_HWRST_DURATION     1
00080 #endif
00081 
00082 #ifndef VSCODEC0_FREQ
00083 
00084 #define VSCODEC0_FREQ               12288000UL
00085 #endif
00086 
00087 #ifndef VSCODEC0_SPI_RATE
00088 
00089 #define VSCODEC0_SPI_RATE           (VSCODEC0_FREQ / 8)
00090 #endif
00091 
00092 #ifndef VSCODEC0_SPI_MODE
00093 
00094 #define VSCODEC0_SPI_MODE           SPI_MODE_0
00095 #endif
00096 
00097 #ifndef VSCODEC0_SPIBUS_WAIT
00098 
00099 #define VSCODEC0_SPIBUS_WAIT        NUT_WAIT_INFINITE
00100 #endif
00101 
00102 #ifndef VSCODEC0_MAX_OUTPUT_BUFSIZ
00103 
00104 #define VSCODEC0_MAX_OUTPUT_BUFSIZ  16384
00105 #endif
00106 
00107 /*
00108  * Determine interrupt settings.
00109  */
00110 #if (VSCODEC0_SIGNAL_IRQ == NUTGPIO_EXTINT0)
00111 #define VSCODEC0_DREQ_SIGNAL  sig_INTERRUPT0
00112 #elif (VSCODEC0_SIGNAL_IRQ == NUTGPIO_EXTINT1)
00113 #define VSCODEC0_DREQ_SIGNAL  sig_INTERRUPT1
00114 #elif (VSCODEC0_SIGNAL_IRQ == NUTGPIO_EXTINT2)
00115 #define VSCODEC0_DREQ_SIGNAL  sig_INTERRUPT2
00116 #elif (VSCODEC0_SIGNAL_IRQ == NUTGPIO_EXTINT3)
00117 #define VSCODEC0_DREQ_SIGNAL  sig_INTERRUPT3
00118 #elif (VSCODEC0_SIGNAL_IRQ == NUTGPIO_EXTINT4)
00119 #define VSCODEC0_DREQ_SIGNAL  sig_INTERRUPT4
00120 #elif (VSCODEC0_SIGNAL_IRQ == NUTGPIO_EXTINT5)
00121 #define VSCODEC0_DREQ_SIGNAL  sig_INTERRUPT5
00122 #elif (VSCODEC0_SIGNAL_IRQ == NUTGPIO_EXTINT6)
00123 #define VSCODEC0_DREQ_SIGNAL  sig_INTERRUPT6
00124 #elif (VSCODEC0_SIGNAL_IRQ == NUTGPIO_EXTINT7)
00125 #define VSCODEC0_DREQ_SIGNAL  sig_INTERRUPT7
00126 #endif
00127 
00131 static NUTSPINODE nodeSpiVsCodec0 = {
00132     NULL,               
00133     NULL,               
00134     VSCODEC0_SPI_RATE,  
00135     VSCODEC0_SPI_MODE,  
00136     8,                  
00137     0                   
00138 };
00139 
00140 static VSDCB dcbVsCodec0;
00141 
00142 /*
00143  * VLSI codec 0 interrupt handler.
00144  *
00145  * \param arg Pointer to an event queue.
00146  */
00147 static void VsCodec0Interrupt(void *arg)
00148 {
00149     NutEventPostFromIrq((void **)arg);
00150 }
00151 
00157 static int VsCodec0IsReady(void)
00158 {
00159     return GpioPinGet(VSCODEC0_DREQ_PORT, VSCODEC0_DREQ_BIT) != 0;
00160 }
00161 
00162 /*
00163  * \brief Write to command channel of codec 0.
00164  *
00165  * This routine will not check the DREQ line.
00166  *
00167  * \param cmd  Points to the buffer. On entry it contains the data to 
00168  *             send. On exit it will contain the data received from
00169  *             the chip.
00170  * \param len  Number of bytes to send and receive.
00171  */
00172 static int VsCodec0SendCmd(void *cmd, size_t len)
00173 {
00174     int rc;
00175 
00176     /* Allocate the SPI bus. */
00177     rc = (*nodeSpiVsCodec0.node_bus->bus_alloc) (&nodeSpiVsCodec0, VSCODEC0_SPIBUS_WAIT);
00178     if (rc == 0) {
00179         /* Activate chip selects. */
00180 #if defined(VSCODEC0_VSCS_PORT) && defined(VSCODEC0_VSCS_BIT)
00181         GpioPinSetLow(VSCODEC0_VSCS_PORT, VSCODEC0_VSCS_BIT);
00182 #endif
00183         GpioPinSetLow(VSCODEC0_XCS_PORT, VSCODEC0_XCS_BIT);
00184         /* Send command bytes and receive response. */
00185         rc = (*nodeSpiVsCodec0.node_bus->bus_transfer) (&nodeSpiVsCodec0, cmd, cmd, len);
00186         /* Dectivate chip selects. */
00187         GpioPinSetHigh(VSCODEC0_XCS_PORT, VSCODEC0_XCS_BIT);
00188 #if defined(VSCODEC0_VSCS_PORT) && defined(VSCODEC0_VSCS_BIT)
00189         GpioPinSetHigh(VSCODEC0_VSCS_PORT, VSCODEC0_VSCS_BIT);
00190 #endif
00191         /* Release the SPI bus. */
00192         (*nodeSpiVsCodec0.node_bus->bus_release) (&nodeSpiVsCodec0);
00193     }
00194     return rc;
00195 }
00196 
00197 /*
00198  * \brief Write data to the decoder.
00199  *
00200  * Data is sent in fixed chunks. The first one is sent without
00201  * checking the DREQ line. Any subsequent chunk is sent only if
00202  * the DREQ line is still high.
00203  *
00204  * \param node Specifies the SPI node.
00205  * \param buf  Points to the data. May be NULL, in which case the routine
00206  *             will send the specified number of zeros.
00207  * \param len  Number of bytes to send.
00208  *
00209  * \return The number of bytes actually sent. This may be less than the
00210  *         specified data length. Zero is returned in case of an error.
00211  */
00212 static int VsCodec0SendData(CONST uint8_t *buf, size_t len)
00213 {
00214     int rc = 0;
00215     CONST uint8_t *bp;
00216     size_t chunk;
00217 
00218     /* Allocate the SPI bus. */
00219     if ((*nodeSpiVsCodec0.node_bus->bus_alloc) (&nodeSpiVsCodec0, VSCODEC0_SPIBUS_WAIT) == 0) {
00220 #if defined(VSCODEC0_VSCS_PORT) && defined(VSCODEC0_VSCS_BIT)
00221         /* Activate optional VSCS line. */
00222         GpioPinSetLow(VSCODEC0_VSCS_PORT, VSCODEC0_VSCS_BIT);
00223 #endif
00224 #if defined(VSCODEC0_XDCS_PORT) && defined(VSCODEC0_XDCS_BIT)
00225         /* Activate optional XDCS line. */
00226         GpioPinSetLow(VSCODEC0_XDCS_PORT, VSCODEC0_XDCS_BIT);
00227 #endif
00228         /* Set our internal buffer pointer, either to the start of the 
00229         ** encoded data or to a chunk of zeros. */
00230         bp = buf ? buf : zero_chunk;
00231         /* Loop until all data had been sent or DREQ goes low. */
00232         while (len) {
00233             /* Determine chunk size. */
00234             chunk = len > VSCODEC_DATA_CHUNK_SIZE ? VSCODEC_DATA_CHUNK_SIZE : len;
00235             /* Send the chunk, exit on errors. */
00236             if ((*nodeSpiVsCodec0.node_bus->bus_transfer) (&nodeSpiVsCodec0, bp, NULL, chunk)) {
00237                 break;
00238             }
00239             /* Update function result. */
00240             rc += chunk;
00241             /* Check if decoder is ready for more. Exit, if not. */
00242             if (!VsCodec0IsReady()) {
00243                 break;
00244             }
00245             /* Update remaining number of bytes and buffer pointer. */
00246             len -= chunk;
00247             if (buf) {
00248                 bp += chunk;
00249             }
00250         }
00251 #if defined(VSCODEC0_XDCS_PORT) && defined(VSCODEC0_XDCS_BIT)
00252         /* Deactivate optional XDCS line. */
00253         GpioPinSetHigh(VSCODEC0_XDCS_PORT, VSCODEC0_XDCS_BIT);
00254 #endif
00255 #if defined(VSCODEC0_VSCS_PORT) && defined(VSCODEC0_VSCS_BIT)
00256         /* Deactivate optional VSCS line. */
00257         GpioPinSetHigh(VSCODEC0_VSCS_PORT, VSCODEC0_VSCS_BIT);
00258 #endif
00259         /* Release the SPI bus. */
00260         (*nodeSpiVsCodec0.node_bus->bus_release) (&nodeSpiVsCodec0);
00261     }
00262     return rc;
00263 }
00264 
00277 static int VsCodec0SetClock(uint32_t xtal, uint_fast8_t dreq)
00278 {
00279     int rc = 0;
00280 
00281 #if VS_HAS_SC_X3FREQ
00282     /* This hardware got the new CLOCKF register layout. */
00283     if (dreq) {
00284         /* Honor the DREQ line, if requested. */
00285         VsCodecWaitReady(&devSpiVsCodec0, VSCODEC_CMD_TIMEOUT);
00286     }
00287     {
00288         uint8_t cmd[4] = { VS_OPCODE_WRITE, VS_CLOCKF_REG, 0, 0 };
00289         uint16_t freq = (uint16_t)((xtal - 8000000UL) / 4000UL);
00290 
00291         freq |= (VS_SC_MULT_3_5 | VS_SC_ADD_1_0);
00292         cmd[2] = (uint8_t) (freq >> 8);
00293         cmd[3] = (uint8_t) freq;
00294         rc = VsCodec0SendCmd(cmd, 4);
00295     }
00296 #else
00297     /* Old hardware, requires clock doubler with lower frequence crystal. */
00298     if (xtal < 20000000UL) {
00299         VsCodecReg(&devSpiVsCodec0, VS_OPCODE_WRITE, VS_CLOCKF_REG, (uint16_t)(VS_CF_DOUBLER | (xtal / 2000UL)));
00300     } else {
00301         VsCodecReg(&devSpiVsCodec0, VS_OPCODE_WRITE, VS_CLOCKF_REG, (uint16_t)(xtal / 2000UL));
00302     }
00303 #endif
00304 
00305     /* Force frequency change (see VS1001 datasheet). */
00306 #if defined(AUDIO0_VS1001K)
00307     VsCodecReg(&devSpiVsCodec0, VS_OPCODE_WRITE, VS_INT_FCTLH_REG, 0x8008);
00308 #elif defined(AUDIO0_VSAUTO) && defined(VS_INT_FCTLH_REG)
00309     if (dcbVsCodec0.dcb_codec_ver == 1001) {
00310         VsCodecReg(&devSpiVsCodec0, VS_OPCODE_WRITE, VS_INT_FCTLH_REG, 0x8008);
00311     }
00312 #endif
00313 
00314     /* With higher clock we can increase the SPI rate. */
00315     if (rc == 0) {
00316 #if VS_HAS_SC_X3FREQ
00317         (*nodeSpiVsCodec0.node_bus->bus_set_rate) (&nodeSpiVsCodec0, xtal / 2);
00318 #else
00319         (*nodeSpiVsCodec0.node_bus->bus_set_rate) (&nodeSpiVsCodec0, xtal / 3);
00320 #endif
00321     }
00322     return rc;
00323 }
00324 
00336 static int VsCodec0Detect(void)
00337 {
00338     int rc = -1;
00339     uint_fast16_t status;
00340 
00341     /* While the VS1053B works fine on the EIR board, we still need
00342     ** a dummy read on the Ethernut 2.1B with Medianut 2. TODO: Why? */
00343     status = VsCodecReg(&devSpiVsCodec0, VS_OPCODE_READ, VS_STATUS_REG, 0);
00344     status = VsCodecReg(&devSpiVsCodec0, VS_OPCODE_READ, VS_STATUS_REG, 0);
00345 
00346     /*
00347     ** Verify the hardware if chip is pre-configured.
00348     */
00349 #if defined(AUDIO0_VS1001K)
00350     if ((status & VS_SS_VER) == (VS1001_SS_VER << VS_SS_VER_LSB)) {
00351         dcbVsCodec0.dcb_codec_ver = 1001;
00352         dcbVsCodec0.dcb_codec_rev = 'K';
00353         rc = 0;
00354     }
00355 #elif defined(AUDIO0_VS1011E)
00356     if ((status & VS_SS_VER) == (VS1011E_SS_VER << VS_SS_VER_LSB)) {
00357         dcbVsCodec0.dcb_codec_ver = 1011;
00358         dcbVsCodec0.dcb_codec_rev = 'E';
00359         rc = 0;
00360     }
00361 #elif defined(AUDIO0_VS1002D)
00362     if ((status & VS_SS_VER) == (VS1002_SS_VER << VS_SS_VER_LSB)) {
00363         dcbVsCodec0.dcb_codec_ver = 1002;
00364         dcbVsCodec0.dcb_codec_rev = 'D';
00365         rc = 0;
00366     }
00367 #elif defined(AUDIO0_VS1003B)
00368     if ((status & VS_SS_VER) == (VS1003_SS_VER << VS_SS_VER_LSB)) {
00369         dcbVsCodec0.dcb_codec_ver = 1003;
00370         dcbVsCodec0.dcb_codec_rev = 'B';
00371         rc = 0;
00372     }
00373 #elif defined(AUDIO0_VS1033C)
00374     if ((status & VS_SS_VER) == (VS1033_SS_VER << VS_SS_VER_LSB)) {
00375         dcbVsCodec0.dcb_codec_ver = 1033;
00376         dcbVsCodec0.dcb_codec_rev = 'C';
00377         rc = 0;
00378     }
00379 #elif defined(AUDIO0_VS1053B)
00380     if ((status & VS_SS_VER) == (VS1053_SS_VER << VS_SS_VER_LSB)) {
00381         dcbVsCodec0.dcb_codec_ver = 1053;
00382         dcbVsCodec0.dcb_codec_rev = 'B';
00383         rc = 0;
00384     }
00385 #else
00386     /*
00387     ** If not configured, try to figure it out.
00388     */
00389     rc = 0;
00390     switch ((status & VS_SS_VER) >> VS_SS_VER_LSB) {
00391     case VS1001_SS_VER:
00392         dcbVsCodec0.dcb_codec_ver = 1001;
00393         break;
00394     case VS1011_SS_VER:
00395         dcbVsCodec0.dcb_codec_ver = 1011;
00396         break;
00397     case VS1002_SS_VER:
00398         if (VsCodecReg(&devSpiVsCodec0, VS_OPCODE_READ, VS_MODE_REG, 0) & VS_SM_SDINEW) {
00399             dcbVsCodec0.dcb_codec_ver = 1002;
00400         } else {
00401             dcbVsCodec0.dcb_codec_ver = 1011;
00402             dcbVsCodec0.dcb_codec_rev = 'E';
00403         }
00404         break;
00405     case VS1003_SS_VER:
00406         dcbVsCodec0.dcb_codec_ver = 1003;
00407         break;
00408     case VS1053_SS_VER:
00409         dcbVsCodec0.dcb_codec_ver = 1053;
00410         break;
00411     case VS1033_SS_VER:
00412         dcbVsCodec0.dcb_codec_ver = 1033;
00413         break;
00414     case VS1103_SS_VER:
00415         dcbVsCodec0.dcb_codec_ver = 1103;
00416         break;
00417     default:
00418         rc = -1;
00419         break;
00420     }
00421 #endif
00422     return rc;
00423 }
00424 
00436 static int VsCodec0ResetHardware(int on)
00437 {
00438     if (on) {
00439         /*
00440         ** Activate reset.
00441         */
00442 #if defined(VSCODEC0_XRESET_PORT) && defined(VSCODEC0_XRESET_BIT)
00443         /* Activate the reset line. */
00444         GpioPinSetLow(VSCODEC0_XRESET_PORT, VSCODEC0_XRESET_BIT);
00445         GpioPinConfigSet(VSCODEC0_XRESET_PORT, VSCODEC0_XRESET_BIT, GPIO_CFG_OUTPUT);
00446         NutSleep(VSCODEC0_HWRST_DURATION);
00447 #else
00448         return -1;
00449 #endif
00450     } else {
00451         /*
00452         ** Deactivate reset.
00453         */
00454         uint_fast8_t clkset = 0;
00455 
00456 #if defined(VSCODEC0_XRESET_PORT) && defined(VSCODEC0_XRESET_BIT)
00457         /* Release the reset line. */
00458         GpioPinSetHigh(VSCODEC0_XRESET_PORT, VSCODEC0_XRESET_BIT);
00459 #if VSCODEC0_FREQ >= 24000000UL
00460         /* With input clocks equal or above 24MHz we must set CLOCKF early 
00461         ** and must not wait for rising DREQ. */
00462         csrc = VsCodec0SetClock(VSCODEC0_FREQ, 0) == 0;
00463 #endif /* VSCODEC0_FREQ */
00464 #endif /* VSCODEC0_XRESET_PORT */
00465 
00466 #if VSCODEC0_HWRST_RECOVER
00467         /* Optional delay after hardware reset. */
00468         NutSleep(VSCODEC0_HWRST_RECOVER);
00469 #endif
00470         /* Chip hardware detection. */
00471         if (VsCodec0Detect()) {
00472             return -1;
00473         }
00474 #if !defined(AUDIO0_VS1001K)
00475         if (dcbVsCodec0.dcb_codec_ver != 1001) {
00476 #if VS_HAS_SM_SDINEW
00477 #if defined(VSCODEC0_XDCS_PORT) && defined(VSCODEC0_XDCS_BIT)
00478             VsCodecMode(&devSpiVsCodec0, VS_SM_SDINEW, VS_SM_SDINEW);
00479 #else
00480             VsCodecMode(&devSpiVsCodec0, VS_SM_SDINEW | VS_SM_SDISHARE, VS_SM_SDINEW | VS_SM_SDISHARE);
00481 #endif
00482 #endif /* VS_HAS_SM_SDINEW */
00483         }
00484 #endif /* AUDIO0_VS1001K */
00485 
00486         /* Set clock now, if not done successfully before. */
00487         if (!clkset) {
00488             VsCodec0SetClock(VSCODEC0_FREQ, 1);
00489         }
00490     }
00491     return 0;
00492 }
00493 
00494 
00495 /*
00496  * Called via dev_init pointer when the device is registered.
00497  *
00498  * \param dev Specifies the audio codec device.
00499  *
00500  * \return 0 on success, -1 otherwise.
00501  */
00502 static int VsCodec0Init(NUTDEVICE * dev)
00503 {
00504     size_t avail;
00505 
00506     /* Set function pointers. */
00507     dcbVsCodec0.dcb_isready = VsCodec0IsReady;
00508     dcbVsCodec0.dcb_sendcmd = VsCodec0SendCmd;
00509     dcbVsCodec0.dcb_senddata = VsCodec0SendData;
00510 
00511     /* Activate hardware reset. */
00512     VsCodec0ResetHardware(1);
00513 
00514     /* Initialize DREQ input. Will be later used as an external interupt. */
00515     GpioPinConfigSet(VSCODEC0_DREQ_PORT, VSCODEC0_DREQ_BIT, 0);
00516     /* Initialize chip selects, XCS and optional XDCS. */
00517     GpioPinSetHigh(VSCODEC0_XCS_PORT, VSCODEC0_XCS_BIT);
00518     GpioPinConfigSet(VSCODEC0_XCS_PORT, VSCODEC0_XCS_BIT, GPIO_CFG_OUTPUT);
00519 #if defined(VSCODEC0_XDCS_PORT) && defined(VSCODEC0_XDCS_BIT)
00520     GpioPinSetHigh(VSCODEC0_XDCS_PORT, VSCODEC0_XDCS_BIT);
00521     GpioPinConfigSet(VSCODEC0_XDCS_PORT, VSCODEC0_XDCS_BIT, GPIO_CFG_OUTPUT);
00522 #endif
00523 #if defined(VSCODEC0_VSCS_PORT) && defined(VSCODEC0_VSCS_BIT)
00524     GpioPinSetHigh(VSCODEC0_VSCS_PORT, VSCODEC0_VSCS_BIT);
00525     GpioPinConfigSet(VSCODEC0_VSCS_PORT, VSCODEC0_VSCS_BIT, GPIO_CFG_OUTPUT);
00526 #endif
00527 
00528     /* Register the DREQ interrupt routine. */
00529     NutRegisterIrqHandler(&VSCODEC0_DREQ_SIGNAL, VsCodec0Interrupt, &dcbVsCodec0.dcb_feedme);
00530 
00531     /* Rising edge will generate an interrupt. */
00532     GpioPinConfigSet(VSCODEC0_DREQ_PORT, VSCODEC0_DREQ_BIT, GPIO_CFG_DISABLED);
00533     NutIrqSetMode(&VSCODEC0_DREQ_SIGNAL, NUT_IRQMODE_RISINGEDGE);
00534     NutIrqEnable(&VSCODEC0_DREQ_SIGNAL);
00535 
00536     /* Deactivate hardware reset. */
00537     if (VsCodec0ResetHardware(0)) {
00538         /* Probably failed to detect the hardware. */
00539         return -1;
00540     }
00541 
00542     /*
00543     ** Initialize the decoder stream buffer.
00544     */
00545 #ifdef VSCODEC0_OUTPUT_BUFSIZ
00546     avail = VSCODEC0_OUTPUT_BUFSIZ;
00547 #else
00548     avail = NutHeapAvailable() / 2;
00549     if (avail > VSCODEC0_MAX_OUTPUT_BUFSIZ) {
00550         avail = VSCODEC0_MAX_OUTPUT_BUFSIZ;
00551     }
00552 #endif
00553     if (VsDecoderBufferInit(dev, avail)) {
00554         return -1;
00555     }
00556 
00557     /* Start the feeder thread. */
00558     if (NutThreadCreate(dev->dev_name, FeederThread, dev, 
00559         (NUT_THREAD_VSCODEC0STACK * NUT_THREAD_STACK_MULT) + NUT_THREAD_STACK_ADD) == 0) {
00560         return -1;
00561     }
00562     return 0;
00563 }
00564 
00575 NUTDEVICE devSpiVsCodec0 = {
00576     0,                  /* Pointer to next device, dev_next. */
00577     {'a', 'u', 'd', 'i', 'o', '0', 0, 0, 0},    /* Unique device name, dev_name. */
00578     IFTYP_CHAR,         /* Type of device, dev_type. */
00579     0,                  /* Codec number, dev_base. */
00580     0,                  /* First interrupt number, dev_irq (not used). */
00581     &nodeSpiVsCodec0,   /* Interface control block, dev_icb (not used). */
00582     &dcbVsCodec0,       /* Driver control block, dev_dcb. */
00583     VsCodec0Init,       /* Driver initialization routine, dev_init. */
00584     VsCodecIOCtl,       /* Driver specific control function, dev_ioctl. */
00585     NULL,               /* Read from device, dev_read. */
00586     VsCodecWrite,       /* Write to device, dev_write. */
00587 #ifdef __HARVARD_ARCH__
00588     VsCodecWrite_P,     /* Write data from program space to device, dev_write_P. */
00589 #endif
00590     VsCodecOpen,        /* Open a device or file, dev_open. */
00591     VsCodecClose,       /* Close a device or file, dev_close. */
00592     NULL                /* Request file size, dev_size. */
00593 };
00594 
00597 #endif

© 2000-2007 by egnite Software GmbH - visit http://www.ethernut.de/