--- drivers/media/dvb/frontends/drx_driver.c | 1504 ++++++++++++++++++++++++++++++ 1 files changed, 1504 insertions(+), 0 deletions(-) create mode 100644 drivers/media/dvb/frontends/drx_driver.c diff --git a/drivers/media/dvb/frontends/drx_driver.c b/drivers/media/dvb/frontends/drx_driver.c new file mode 100644 index 0000000..1f58de7 --- /dev/null +++ b/drivers/media/dvb/frontends/drx_driver.c @@ -0,0 +1,1504 @@ +/* + Copyright (c), 2004-2005,2007-2010 Trident Microsystems, Inc. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name of Trident Microsystems nor Hauppauge Computer Works + nor the names of its contributors may be used to endorse or promote + products derived from this software without specific prior written + permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +/** +* \file $Id: drx_driver.c,v 1.40 2010/01/12 01:24:56 lfeng Exp $ +* +* \brief Generic DRX functionality, DRX driver core. +* +*/ + +/*------------------------------------------------------------------------------ +INCLUDE FILES +------------------------------------------------------------------------------*/ +#include "drx_driver.h" +#include "bsp_host.h" + +#define VERSION_FIXED 0 +#if VERSION_FIXED +#define VERSION_MAJOR 0 +#define VERSION_MINOR 0 +#define VERSION_PATCH 0 +#else +#include "drx_driver_version.h" +#endif + +/*------------------------------------------------------------------------------ +DEFINES +------------------------------------------------------------------------------*/ + +/*============================================================================*/ +/*=== MICROCODE RELATED DEFINES ==============================================*/ +/*============================================================================*/ + +/** \brief Magic word for checking correct Endianess of microcode data. */ +#ifndef DRX_UCODE_MAGIC_WORD +#define DRX_UCODE_MAGIC_WORD ((((u16_t)'H')<<8)+((u16_t)'L')) +#endif + +/** \brief CRC flag in ucode header, flags field. */ +#ifndef DRX_UCODE_CRC_FLAG +#define DRX_UCODE_CRC_FLAG (0x0001) +#endif + +/** \brief Compression flag in ucode header, flags field. */ +#ifndef DRX_UCODE_COMPRESSION_FLAG +#define DRX_UCODE_COMPRESSION_FLAG (0x0002) +#endif + +/** \brief Maximum size of buffer used to verify the microcode. + Must be an even number. */ +#ifndef DRX_UCODE_MAX_BUF_SIZE +#define DRX_UCODE_MAX_BUF_SIZE (DRXDAP_MAX_RCHUNKSIZE) +#endif +#if DRX_UCODE_MAX_BUF_SIZE & 1 +#error DRX_UCODE_MAX_BUF_SIZE must be an even number +#endif + +/*============================================================================*/ +/*=== CHANNEL SCAN RELATED DEFINES ===========================================*/ +/*============================================================================*/ + +/** +* \brief Maximum progress indication. +* +* Progress indication will run from 0 upto DRX_SCAN_MAX_PROGRESS during scan. +* +*/ +#ifndef DRX_SCAN_MAX_PROGRESS +#define DRX_SCAN_MAX_PROGRESS 1000 +#endif + +/*============================================================================*/ +/*=== MACROS =================================================================*/ +/*============================================================================*/ + +#define DRX_ISPOWERDOWNMODE(mode) ((mode == DRX_POWER_MODE_9) || \ + (mode == DRX_POWER_MODE_10) || \ + (mode == DRX_POWER_MODE_11) || \ + (mode == DRX_POWER_MODE_12) || \ + (mode == DRX_POWER_MODE_13) || \ + (mode == DRX_POWER_MODE_14) || \ + (mode == DRX_POWER_MODE_15) || \ + (mode == DRX_POWER_MODE_16) || \ + (mode == DRX_POWER_DOWN)) + +/*------------------------------------------------------------------------------ +GLOBAL VARIABLES +------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------ +STRUCTURES +------------------------------------------------------------------------------*/ +/** \brief Structure of the microcode block headers */ +typedef struct { + u32_t addr; /**< Destination address of the data in this block */ + u16_t size; /**< Size of the block data following this header counted in + 16 bits words */ + u16_t flags; /**< Flags for this data block: + - bit[0]= CRC on/off + - bit[1]= compression on/off + - bit[15..2]=reserved */ + u16_t CRC; /**< CRC value of the data block, only valid if CRC flag is + set. */ +} DRXUCodeBlockHdr_t, *pDRXUCodeBlockHdr_t; + +/*------------------------------------------------------------------------------ +FUNCTIONS +------------------------------------------------------------------------------*/ + +/*============================================================================*/ +/*============================================================================*/ +/*== Channel Scan Functions ==================================================*/ +/*============================================================================*/ +/*============================================================================*/ + +#ifndef DRX_EXCLUDE_SCAN + +/* Prototype of default scanning function */ +static DRXStatus_t +ScanFunctionDefault(void *scanContext, + DRXScanCommand_t scanCommand, + pDRXChannel_t scanChannel, + pBool_t getNextChannel); + +/** +* \brief Get pointer to scanning function. +* \param demod: Pointer to demodulator instance. +* \return DRXScanFunc_t. +*/ +static DRXScanFunc_t +GetScanFunction(pDRXDemodInstance_t demod) +{ + pDRXCommonAttr_t commonAttr = (pDRXCommonAttr_t)(NULL); + DRXScanFunc_t scanFunc = (DRXScanFunc_t)(NULL); + + /* get scan function from common attributes */ + commonAttr = (pDRXCommonAttr_t)demod->myCommonAttr; + scanFunc = commonAttr->scanFunction; + + if (scanFunc != NULL) { + /* return device-specific scan function if it's not NULL */ + return scanFunc; + } + /* otherwise return default scan function in core driver */ + return &ScanFunctionDefault; +} + +/** +* \brief Get Context pointer. +* \param demod: Pointer to demodulator instance. +* \param scanContext: Context Pointer. +* \return DRXScanFunc_t. +*/ +void *GetScanContext(pDRXDemodInstance_t demod, + void *scanContext) +{ + pDRXCommonAttr_t commonAttr = (pDRXCommonAttr_t)(NULL); + + /* get scan function from common attributes */ + commonAttr = (pDRXCommonAttr_t) demod->myCommonAttr; + scanContext = commonAttr->scanContext; + + if (scanContext == NULL) { + scanContext = (void *) demod; + } + + return scanContext; +} + +/** +* \brief Wait for lock while scanning. +* \param demod: Pointer to demodulator instance. +* \param lockStat: Pointer to bool indicating if end result is lock or not. +* \return DRXStatus_t. +* \retval DRX_STS_OK: Success +* \retval DRX_STS_ERROR: I2C failure or bsp function failure. +* +* Wait until timeout, desired lock or NEVER_LOCK. +* Assume: +* - lock function returns : at least DRX_NOT_LOCKED and a lock state +* higher than DRX_NOT_LOCKED. +* - BSP has a clock function to retrieve a millisecond ticker value. +* - BSP has a sleep function to enable sleep of n millisecond. +* +* In case DRX_NEVER_LOCK is returned the poll-wait will be aborted. +* +*/ +static DRXStatus_t +ScanWaitForLock(pDRXDemodInstance_t demod, + pBool_t isLocked) +{ + Bool_t doneWaiting = FALSE; + DRXLockStatus_t lockState = DRX_NOT_LOCKED; + DRXLockStatus_t desiredLockState = DRX_NOT_LOCKED; + u32_t timeoutValue = 0; + u32_t startTimeLockStage = 0; + u32_t currentTime = 0; + u32_t timerValue = 0; + + *isLocked = FALSE; + timeoutValue = (u32_t) demod->myCommonAttr->scanDemodLockTimeout; + desiredLockState = demod->myCommonAttr->scanDesiredLock; + startTimeLockStage = DRXBSP_HST_Clock(); + + /* Start polling loop, checking for lock & timeout */ + while (doneWaiting == FALSE) + { + + if (DRX_Ctrl(demod, DRX_CTRL_LOCK_STATUS, &lockState) != + DRX_STS_OK) { + return DRX_STS_ERROR; + } + currentTime = DRXBSP_HST_Clock(); + + timerValue = currentTime - startTimeLockStage; + if (lockState >= desiredLockState) { + *isLocked = TRUE; + doneWaiting = TRUE; + } /* if (lockState >= desiredLockState) .. */ + else if (lockState == DRX_NEVER_LOCK) { + doneWaiting = TRUE; + } /* if (lockState == DRX_NEVER_LOCK) .. */ + else if (timerValue > timeoutValue) { + /* lockState == DRX_NOT_LOCKED and timeout */ + doneWaiting = TRUE; + } + else { + if (DRXBSP_HST_Sleep(10) != DRX_STS_OK) { + return DRX_STS_ERROR; + } + } /* if (timerValue > timeoutValue) .. */ + + } /* while */ + + return DRX_STS_OK; +} + +/*============================================================================*/ + +/** +* \brief Determine next frequency to scan. +* \param demod: Pointer to demodulator instance. +* \param skip : Minimum frequency step to take. +* \return DRXStatus_t. +* \retval DRX_STS_OK: Succes. +* \retval DRX_STS_INVALID_ARG: Invalid frequency plan. +* +* Helper function for CtrlScanNext() function. +* Compute next frequency & index in frequency plan. +* Check if scan is ready. +* +*/ +static DRXStatus_t +ScanPrepareNextScan (pDRXDemodInstance_t demod, + DRXFrequency_t skip) +{ + pDRXCommonAttr_t commonAttr = (pDRXCommonAttr_t)(NULL); + u16_t tableIndex = 0; + u16_t frequencyPlanSize = 0; + pDRXFrequencyPlan_t frequencyPlan = (pDRXFrequencyPlan_t)(NULL); + DRXFrequency_t nextFrequency = 0; + DRXFrequency_t tunerMinFrequency = 0; + DRXFrequency_t tunerMaxFrequency = 0; + + commonAttr = (pDRXCommonAttr_t)demod->myCommonAttr; + tableIndex = commonAttr->scanFreqPlanIndex; + frequencyPlan = commonAttr->scanParam->frequencyPlan; + nextFrequency = commonAttr->scanNextFrequency; + tunerMinFrequency = commonAttr->tunerMinFreqRF; + tunerMaxFrequency = commonAttr->tunerMaxFreqRF; + + do + { + /* Search next frequency to scan */ + + /* always take at least one step */ + (commonAttr->scanChannelsScanned) ++; + nextFrequency += frequencyPlan[tableIndex].step; + skip -= frequencyPlan[tableIndex].step; + + /* and then as many steps necessary to exceed 'skip' + without exceeding end of the band */ + while ((skip > 0) && + (nextFrequency <= frequencyPlan[tableIndex].last)) + { + (commonAttr->scanChannelsScanned) ++; + nextFrequency += frequencyPlan[tableIndex].step; + skip -= frequencyPlan[tableIndex].step; + } + /* reset skip, in case we move to the next band later */ + skip = 0; + + if (nextFrequency > frequencyPlan[tableIndex].last) { + /* reached end of this band */ + tableIndex++; + frequencyPlanSize = commonAttr->scanParam->frequencyPlanSize; + if (tableIndex >= frequencyPlanSize) { + /* reached end of frequency plan */ + commonAttr->scanReady = TRUE; + } + else { + nextFrequency = frequencyPlan[tableIndex].first; + } + } + if (nextFrequency > (tunerMaxFrequency)) { + /* reached end of tuner range */ + commonAttr->scanReady = TRUE; + } + } while((nextFrequency < tunerMinFrequency) && + (commonAttr->scanReady == FALSE)); + + /* Store new values */ + commonAttr->scanFreqPlanIndex = tableIndex; + commonAttr->scanNextFrequency = nextFrequency; + + return DRX_STS_OK; +} + +/*============================================================================*/ + +/** +* \brief Default DTV scanning function. +* +* \param demod: Pointer to demodulator instance. +* \param scanCommand: Scanning command: INIT, NEXT or STOP. +* \param scanChannel: Channel to check: frequency and bandwidth, others AUTO +* \param getNextChannel: Return TRUE if next frequency is desired at next call +* +* \return DRXStatus_t. +* \retval DRX_STS_OK: Channel found, DRX_CTRL_GET_CHANNEL can be used +* to retrieve channel parameters. +* \retval DRX_STS_BUSY: Channel not found (yet). +* \retval DRX_STS_ERROR: Something went wrong. +* +* scanChannel and getNextChannel will be NULL for INIT and STOP. +*/ +static DRXStatus_t +ScanFunctionDefault (void *scanContext, + DRXScanCommand_t scanCommand, + pDRXChannel_t scanChannel, + pBool_t getNextChannel) +{ + pDRXDemodInstance_t demod = NULL; + DRXStatus_t status = DRX_STS_ERROR; + Bool_t isLocked = FALSE; + + demod = (pDRXDemodInstance_t) scanContext; + + if (scanCommand != DRX_SCAN_COMMAND_NEXT) { + /* just return OK if not doing "scan next" */ + return DRX_STS_OK; + } + + *getNextChannel = FALSE; + + status = DRX_Ctrl (demod, DRX_CTRL_SET_CHANNEL, scanChannel); + if (status != DRX_STS_OK) { + return (status); + } + + status = ScanWaitForLock (demod, &isLocked); + if (status != DRX_STS_OK) { + return status; + } + + /* done with this channel, move to next one */ + *getNextChannel = TRUE; + + if (isLocked == FALSE) { + /* no channel found */ + return DRX_STS_BUSY; + } + /* channel found */ + return DRX_STS_OK; +} + +/*============================================================================*/ + +/** +* \brief Initialize for channel scan. +* \param demod: Pointer to demodulator instance. +* \param scanParam: Pointer to scan parameters. +* \return DRXStatus_t. +* \retval DRX_STS_OK: Initialized for scan. +* \retval DRX_STS_ERROR: No overlap between frequency plan and tuner +* range. +* \retval DRX_STS_INVALID_ARG: Wrong parameters. +* +* This function should be called before starting a complete channel scan. +* It will prepare everything for a complete channel scan. +* After calling this function the DRX_CTRL_SCAN_NEXT control function can be +* used to perform the actual scanning. Scanning will start at the first +* center frequency of the frequency plan that is within the tuner range. +* +*/ +static DRXStatus_t +CtrlScanInit(pDRXDemodInstance_t demod, + pDRXScanParam_t scanParam) +{ + DRXStatus_t status = DRX_STS_ERROR; + pDRXCommonAttr_t commonAttr =(pDRXCommonAttr_t)(NULL); + DRXFrequency_t maxTunerFreq = 0; + DRXFrequency_t minTunerFreq = 0; + u16_t nrChannelsInPlan = 0; + u16_t i = 0; + void *scanContext = NULL; + + commonAttr = (pDRXCommonAttr_t)demod->myCommonAttr; + commonAttr->scanActive = TRUE; + + /* invalidate a previous SCAN_INIT */ + commonAttr->scanParam = (pDRXScanParam_t)(NULL); + commonAttr->scanNextFrequency = 0; + + /* Check parameters */ + if (((demod->myTuner == NULL) && + (scanParam->numTries !=1)) || + + (scanParam == NULL) || + (scanParam->numTries == 0) || + (scanParam->frequencyPlan == NULL) || + (scanParam->frequencyPlanSize == 0) + ) { + commonAttr->scanActive = FALSE; + return DRX_STS_INVALID_ARG; + } + + /* Check frequency plan contents */ + maxTunerFreq = commonAttr->tunerMaxFreqRF; + minTunerFreq = commonAttr->tunerMinFreqRF; + for(i = 0; i < (scanParam->frequencyPlanSize); i++) { + DRXFrequency_t width = 0; + DRXFrequency_t step = scanParam->frequencyPlan[i].step; + DRXFrequency_t firstFreq = scanParam->frequencyPlan[i].first; + DRXFrequency_t lastFreq = scanParam->frequencyPlan[i].last; + DRXFrequency_t minFreq = 0; + DRXFrequency_t maxFreq = 0; + + if (step <= 0) { + /* Step must be positive and non-zero */ + commonAttr->scanActive = FALSE; + return DRX_STS_INVALID_ARG; + } + + if (firstFreq > lastFreq) { + /* First center frequency is higher than last center frequency */ + commonAttr->scanActive = FALSE; + return DRX_STS_INVALID_ARG; + } + + width = lastFreq - firstFreq; + + if ((width % step) != 0) { + /* Difference between last and first center frequency is not + an integer number of steps */ + commonAttr->scanActive = FALSE; + return DRX_STS_INVALID_ARG; + } + + /* Check if frequency plan entry intersects with tuner range */ + if (lastFreq >= minTunerFreq) { + if (firstFreq <= maxTunerFreq) { + if (firstFreq >= minTunerFreq) { + minFreq = firstFreq; + } + else { + DRXFrequency_t n = 0; + + n = (minTunerFreq - firstFreq) / step; + if (((minTunerFreq - firstFreq) % step) != 0) { + n++; + } + minFreq = firstFreq + n*step; + } + + if (lastFreq <= maxTunerFreq) { + maxFreq = lastFreq; + } + else { + DRXFrequency_t n=0; + + n=(lastFreq - maxTunerFreq)/step; + if (((lastFreq - maxTunerFreq)%step) !=0) { + n++; + } + maxFreq = lastFreq - n*step; + } + } + } + + /* Keep track of total number of channels within tuner range + in this frequency plan. */ + if ((minFreq !=0) && (maxFreq != 0)) { + nrChannelsInPlan += (u16_t)(((maxFreq-minFreq) / step) +1); + + /* Determine first frequency (within tuner range) to scan */ + if (commonAttr->scanNextFrequency == 0) { + commonAttr->scanNextFrequency = minFreq; + commonAttr->scanFreqPlanIndex = i; + } + } + + }/* for (...) */ + + if (nrChannelsInPlan == 0) { + /* Tuner range and frequency plan ranges do not overlap */ + commonAttr->scanActive = FALSE; + return DRX_STS_ERROR; + } + + /* Store parameters */ + commonAttr->scanReady = FALSE; + commonAttr->scanMaxChannels = nrChannelsInPlan; + commonAttr->scanChannelsScanned = 0; + commonAttr->scanParam = scanParam; /* SCAN_NEXT is now allowed */ + + scanContext = GetScanContext(demod, scanContext); + + status = (*(GetScanFunction(demod))) + (scanContext, DRX_SCAN_COMMAND_INIT, NULL, NULL); + + commonAttr->scanActive = FALSE; + + return DRX_STS_OK; +} + +/*============================================================================*/ + +/** +* \brief Stop scanning. +* \param demod: Pointer to demodulator instance. +* \return DRXStatus_t. +* \retval DRX_STS_OK: Scan stopped. +* \retval DRX_STS_ERROR: Something went wrong. +* \retval DRX_STS_INVALID_ARG: Wrong parameters. +*/ +static DRXStatus_t +CtrlScanStop(pDRXDemodInstance_t demod) +{ + DRXStatus_t status = DRX_STS_ERROR; + pDRXCommonAttr_t commonAttr = (pDRXCommonAttr_t) (NULL); + void *scanContext = NULL; + + commonAttr = (pDRXCommonAttr_t)demod->myCommonAttr; + commonAttr->scanActive = TRUE; + + if ((commonAttr->scanParam == NULL) || + (commonAttr->scanMaxChannels == 0)) { + /* Scan was not running, just return OK */ + commonAttr->scanActive = FALSE; + return DRX_STS_OK; + } + + /* Call default or device-specific scanning stop function */ + scanContext = GetScanContext(demod, scanContext); + + status = (*(GetScanFunction(demod))) + (scanContext, DRX_SCAN_COMMAND_STOP, NULL, NULL); + + /* All done, invalidate scan-init */ + commonAttr->scanParam = NULL; + commonAttr->scanMaxChannels = 0; + commonAttr->scanActive = FALSE; + + return status; +} + +/*============================================================================*/ + +/** +* \brief Scan for next channel. +* \param demod: Pointer to demodulator instance. +* \param scanProgress: Pointer to scan progress. +* \return DRXStatus_t. +* \retval DRX_STS_OK: Channel found, DRX_CTRL_GET_CHANNEL can be used +* to retrieve channel parameters. +* \retval DRX_STS_BUSY: Tried part of the channels, as specified in +* numTries field of scan parameters. At least one +* more call to DRX_CTRL_SCAN_NEXT is needed to +* complete scanning. +* \retval DRX_STS_READY: Reached end of scan range. +* \retval DRX_STS_ERROR: Something went wrong. +* \retval DRX_STS_INVALID_ARG: Wrong parameters. The scanProgress may be NULL. +* +* Progress indication will run from 0 upto DRX_SCAN_MAX_PROGRESS during scan. +* +*/ +static DRXStatus_t +CtrlScanNext (pDRXDemodInstance_t demod, + pu16_t scanProgress) +{ + pDRXCommonAttr_t commonAttr = (pDRXCommonAttr_t)(NULL); + pBool_t scanReady = (pBool_t)(NULL); + u16_t maxProgress = DRX_SCAN_MAX_PROGRESS; + u32_t numTries = 0; + u32_t i = 0; + + commonAttr = (pDRXCommonAttr_t)demod->myCommonAttr; + + /* Check scan parameters */ + if (scanProgress == NULL) { + commonAttr->scanActive = FALSE; + return DRX_STS_INVALID_ARG; + } + + *scanProgress = 0; + commonAttr->scanActive = TRUE; + if ((commonAttr->scanParam == NULL) || + (commonAttr->scanMaxChannels == 0)) { + /* CtrlScanInit() was not called succesfully before CtrlScanNext() */ + commonAttr->scanActive = FALSE; + return DRX_STS_ERROR; + } + + *scanProgress = (u16_t)(((commonAttr->scanChannelsScanned)* + ((u32_t)(maxProgress))) / + (commonAttr->scanMaxChannels)); + + /* Scan */ + numTries = commonAttr->scanParam->numTries; + scanReady = &(commonAttr->scanReady); + + for (i = 0; ((i < numTries) && ((*scanReady) == FALSE)); i++) { + DRXChannel_t scanChannel = { 0 }; + DRXStatus_t status = DRX_STS_ERROR; + pDRXFrequencyPlan_t freqPlan = (pDRXFrequencyPlan_t) (NULL); + Bool_t nextChannel = FALSE; + void *scanContext = NULL; + + /* Next channel to scan */ + freqPlan = + &(commonAttr->scanParam->frequencyPlan[commonAttr->scanFreqPlanIndex]); + scanChannel.frequency = commonAttr->scanNextFrequency; + scanChannel.bandwidth = freqPlan->bandwidth; + scanChannel.mirror = DRX_MIRROR_AUTO; + scanChannel.constellation = DRX_CONSTELLATION_AUTO; + scanChannel.hierarchy = DRX_HIERARCHY_AUTO; + scanChannel.priority = DRX_PRIORITY_HIGH; + scanChannel.coderate = DRX_CODERATE_AUTO; + scanChannel.guard = DRX_GUARD_AUTO; + scanChannel.fftmode = DRX_FFTMODE_AUTO; + scanChannel.classification = DRX_CLASSIFICATION_AUTO; + scanChannel.symbolrate = 0; + scanChannel.interleavemode = DRX_INTERLEAVEMODE_AUTO; + scanChannel.ldpc = DRX_LDPC_AUTO; + scanChannel.carrier = DRX_CARRIER_AUTO; + scanChannel.framemode = DRX_FRAMEMODE_AUTO; + scanChannel.pilot = DRX_PILOT_AUTO; + + /* Call default or device-specific scanning function */ + scanContext = GetScanContext(demod, scanContext); + + status = (*(GetScanFunction(demod))) + (scanContext,DRX_SCAN_COMMAND_NEXT,&scanChannel,&nextChannel); + + /* Proceed to next channel if requested */ + if (nextChannel == TRUE) { + DRXStatus_t nextStatus = DRX_STS_ERROR; + DRXFrequency_t skip = 0; + + if (status == DRX_STS_OK) { + /* a channel was found, so skip some frequency steps */ + skip = commonAttr->scanParam->skip; + } + nextStatus = ScanPrepareNextScan(demod, skip); + + /* keep track of progress */ + *scanProgress = (u16_t)(((commonAttr->scanChannelsScanned)* + ((u32_t)(maxProgress)))/ + (commonAttr->scanMaxChannels)); + + if (nextStatus != DRX_STS_OK) { + commonAttr->scanActive = FALSE; + return (nextStatus); + } + } + if (status != DRX_STS_BUSY) { + /* channel found or error */ + commonAttr->scanActive = FALSE; + return status; + } + } /* for (i = 0; i < (... numTries); i++) */ + + if ((*scanReady) == TRUE) { + /* End of scan reached: call stop-scan, ignore any error */ + CtrlScanStop(demod); + commonAttr->scanActive = FALSE; + return (DRX_STS_READY); + } + + commonAttr->scanActive = FALSE; + + return DRX_STS_BUSY; +} + +#endif /* #ifndef DRX_EXCLUDE_SCAN */ + +/*============================================================================*/ + +/** +* \brief Program tuner. +* \param demod: Pointer to demodulator instance. +* \param tunerChannel: Pointer to tuning parameters. +* \return DRXStatus_t. +* \retval DRX_STS_OK: Tuner programmed successfully. +* \retval DRX_STS_ERROR: Something went wrong. +* \retval DRX_STS_INVALID_ARG: Wrong parameters. +* +* tunerChannel passes parameters to program the tuner, +* but also returns the actual RF and IF frequency from the tuner. +* +*/ +static DRXStatus_t +CtrlProgramTuner(pDRXDemodInstance_t demod, + pDRXChannel_t channel) +{ + pDRXCommonAttr_t commonAttr = (pDRXCommonAttr_t)(NULL); + DRXStandard_t standard = DRX_STANDARD_UNKNOWN; + TUNERMode_t tunerMode = 0; + DRXStatus_t status = DRX_STS_ERROR; + DRXFrequency_t ifFrequency = 0; + Bool_t tunerSlowMode = FALSE; + + /* can't tune without a tuner */ + if (demod->myTuner == NULL) { + return DRX_STS_INVALID_ARG; + } + + commonAttr = (pDRXCommonAttr_t) demod->myCommonAttr; + + /* select analog or digital tuner mode based on current standard */ + if (DRX_Ctrl(demod, DRX_CTRL_GET_STANDARD, &standard) != DRX_STS_OK) { + return DRX_STS_ERROR; + } + + if (DRX_ISATVSTD(standard)) { + tunerMode |= TUNER_MODE_ANALOG; + } + else /* note: also for unknown standard */ { + tunerMode |= TUNER_MODE_DIGITAL; + } + + /* select tuner bandwidth */ + switch (channel->bandwidth) { + case DRX_BANDWIDTH_6MHZ: + tunerMode |= TUNER_MODE_6MHZ; + break; + case DRX_BANDWIDTH_7MHZ: + tunerMode |= TUNER_MODE_7MHZ; + break; + case DRX_BANDWIDTH_8MHZ: + tunerMode |= TUNER_MODE_8MHZ; + break; + default: /* note: also for unknown bandwidth */ + return DRX_STS_INVALID_ARG; + } + + DRX_GET_TUNERSLOWMODE (demod, tunerSlowMode); + + /* select fast (switch) or slow (lock) tuner mode */ + if (tunerSlowMode) { + tunerMode |= TUNER_MODE_LOCK; + } + else { + tunerMode |= TUNER_MODE_SWITCH; + } + + if (commonAttr->tunerPortNr == 1) { + Bool_t bridgeClosed = TRUE; + DRXStatus_t statusBridge = DRX_STS_ERROR; + + statusBridge = DRX_Ctrl(demod, DRX_CTRL_I2C_BRIDGE, &bridgeClosed); + if (statusBridge != DRX_STS_OK) { + return statusBridge; + } + } + + status = DRXBSP_TUNER_SetFrequency(demod->myTuner, + tunerMode, + channel->frequency); + + /* attempt restoring bridge before checking status of SetFrequency */ + if (commonAttr->tunerPortNr == 1) { + Bool_t bridgeClosed = FALSE; + DRXStatus_t statusBridge = DRX_STS_ERROR; + + statusBridge = DRX_Ctrl(demod, DRX_CTRL_I2C_BRIDGE, &bridgeClosed); + if (statusBridge != DRX_STS_OK) { + return statusBridge; + } + } + + /* now check status of DRXBSP_TUNER_SetFrequency */ + if (status != DRX_STS_OK) { + return status; + } + + /* get actual RF and IF frequencies from tuner */ + status = DRXBSP_TUNER_GetFrequency(demod->myTuner, + tunerMode, + &(channel->frequency), + &(ifFrequency)); + if (status != DRX_STS_OK) { + return status; + } + + /* update common attributes with information available from this function; + TODO: check if this is required and safe */ + DRX_SET_INTERMEDIATEFREQ(demod, ifFrequency); + + return DRX_STS_OK; +} + +/*============================================================================*/ + +/** +* \brief function to do a register dump. +* \param demod: Pointer to demodulator instance. +* \param registers: Registers to dump. +* \return DRXStatus_t. +* \retval DRX_STS_OK: Dump executed successfully. +* \retval DRX_STS_ERROR: Something went wrong. +* \retval DRX_STS_INVALID_ARG: Wrong parameters. +* +*/ +DRXStatus_t CtrlDumpRegisters(pDRXDemodInstance_t demod, + pDRXRegDump_t registers) +{ + u16_t i = 0; + + if (registers == NULL) { + /* registers not supplied */ + return DRX_STS_INVALID_ARG; + } + + /* start dumping registers */ + while (registers[i].address != 0) { + DRXStatus_t status = DRX_STS_ERROR; + u16_t value = 0; + u32_t data = 0; + + status = demod->myAccessFunct->readReg16Func( + demod->myI2CDevAddr, registers[i].address, &value, 0); + + data = (u32_t)value; + + if (status != DRX_STS_OK) { + /* no breakouts; + depending on device ID, some HW blocks might not be available */ + data |= ((u32_t)status) << 16; + } + registers[i].data = data; + i++; + } + + /* all done, all OK (any errors are saved inside data) */ + return DRX_STS_OK; +} + +/*============================================================================*/ +/*============================================================================*/ +/*===Microcode related functions==============================================*/ +/*============================================================================*/ +/*============================================================================*/ + +/** +* \brief Read a 16 bits word, expects big endian data. +* \param addr: Pointer to memory from which to read the 16 bits word. +* \return u16_t The data read. +* +* This function takes care of the possible difference in endianness between the +* host and the data contained in the microcode image file. +* +*/ +static u16_t +UCodeRead16(pu8_t addr) +{ + /* Works fo any host processor */ + + u16_t word=0; + + word = ((u16_t)addr[0]); + word <<= 8; + word |=((u16_t)addr[1]); + + return word; +} + +/*============================================================================*/ + +/** +* \brief Read a 32 bits word, expects big endian data. +* \param addr: Pointer to memory from which to read the 32 bits word. +* \return u32_t The data read. +* +* This function takes care of the possible difference in endianness between the +* host and the data contained in the microcode image file. +* +*/ +static u32_t +UCodeRead32(pu8_t addr) +{ + /* Works fo any host processor */ + + u32_t word=0; + + word = ((u16_t)addr[0]); + word <<= 8; + word |= ((u16_t)addr[1]); + word <<= 8; + word |= ((u16_t)addr[2]); + word <<= 8; + word |= ((u16_t)addr[3]); + + return word ; +} + +/*============================================================================*/ + +/** +* \brief Compute CRC of block of microcode data. +* \param blockData: Pointer to microcode data. +* \param nrWords: Size of microcode block (number of 16 bits words). +* \return u16_t The computed CRC residu. +*/ +static u16_t +UCodeComputeCRC (pu8_t blockData, u16_t nrWords) +{ + u16_t i = 0; + u16_t j = 0; + u32_t CRCWord = 0; + u32_t carry = 0; + + while (i < nrWords) { + CRCWord |= (u32_t) UCodeRead16(blockData); + for (j = 0; j < 16; j++) { + CRCWord <<= 1; + if (carry != 0) { + CRCWord ^= 0x80050000UL; + } + carry = CRCWord & 0x80000000UL; + } + i++; + blockData+=(sizeof(u16_t)); + } + return ((u16_t) (CRCWord >> 16)); +} + +/*============================================================================*/ + +/** +* \brief Handle microcode upload or verify. +* \param devAddr: Address of device. +* \param mcInfo: Pointer to information about microcode data. +* \param action: Either UCODE_UPLOAD or UCODE_VERIFY +* \return DRXStatus_t. +* \retval DRX_STS_OK: +* - In case of UCODE_UPLOAD: code is successfully uploaded. +* - In case of UCODE_VERIFY: image on device is equal to +* image provided to this control function. +* \retval DRX_STS_ERROR: +* - In case of UCODE_UPLOAD: I2C error. +* - In case of UCODE_VERIFY: I2C error or image on device +* is not equal to image provided to this control function. +* \retval DRX_STS_INVALID_ARG: +* - Invalid arguments. +* - Provided image is corrupt +*/ +static DRXStatus_t +CtrlUCode(pDRXDemodInstance_t demod, + pDRXUCodeInfo_t mcInfo, + DRXUCodeAction_t action) +{ + DRXStatus_t rc; + u16_t i = 0; + u16_t mcNrOfBlks = 0; + u16_t mcMagicWord = 0; + pu8_t mcData = (pu8_t)(NULL); + pI2CDeviceAddr_t devAddr = (pI2CDeviceAddr_t)(NULL); + + devAddr = demod -> myI2CDevAddr; + + /* Check arguments */ + if ((mcInfo == NULL) || + (mcInfo->mcData == NULL)) { + return DRX_STS_INVALID_ARG; + } + + mcData = mcInfo->mcData; + + /* Check data */ + mcMagicWord = UCodeRead16(mcData); + mcData += sizeof(u16_t); + mcNrOfBlks = UCodeRead16(mcData); + mcData += sizeof(u16_t); + + if ((mcMagicWord != DRX_UCODE_MAGIC_WORD) || + (mcNrOfBlks == 0)) { + /* wrong endianess or wrong data ? */ + return DRX_STS_INVALID_ARG; + } + + /* Scan microcode blocks first for version info if uploading */ + if (action == UCODE_UPLOAD) { + /* Clear version block */ + DRX_SET_MCVERTYPE (demod, 0); + DRX_SET_MCDEV (demod, 0); + DRX_SET_MCVERSION (demod, 0); + DRX_SET_MCPATCH (demod, 0); + for (i = 0; i < mcNrOfBlks; i++) { + DRXUCodeBlockHdr_t blockHdr; + + /* Process block header */ + blockHdr.addr = UCodeRead32(mcData); + mcData += sizeof(u32_t); + blockHdr.size = UCodeRead16(mcData); + mcData += sizeof(u16_t); + blockHdr.flags = UCodeRead16(mcData); + mcData += sizeof(u16_t); + blockHdr.CRC = UCodeRead16(mcData); + mcData += sizeof(u16_t); + + if (blockHdr.flags & 0x8) { + /* Aux block. Check type */ + pu8_t auxblk = mcInfo->mcData + blockHdr.addr; + u16_t auxtype = UCodeRead16 (auxblk); + if (DRX_ISMCVERTYPE (auxtype)) { + DRX_SET_MCVERTYPE (demod, UCodeRead16 (auxblk)); + auxblk += sizeof (u16_t); + DRX_SET_MCDEV (demod, UCodeRead32 (auxblk)); + auxblk += sizeof (u32_t); + DRX_SET_MCVERSION (demod, UCodeRead32 (auxblk)); + auxblk += sizeof (u32_t); + DRX_SET_MCPATCH (demod, UCodeRead32 (auxblk)); + } + } + + /* Next block */ + mcData += blockHdr.size * sizeof (u16_t); + } + /* After scanning, validate the microcode. + It is also valid if no validation control exists. + */ + rc = DRX_Ctrl (demod, DRX_CTRL_VALIDATE_UCODE, NULL); + if (rc != DRX_STS_OK && rc != DRX_STS_FUNC_NOT_AVAILABLE) { + return rc; + } + + /* Restore data pointer */ + mcData = mcInfo->mcData + 2 * sizeof(u16_t); + } + + /* Process microcode blocks */ + for(i = 0 ; i<mcNrOfBlks ; i++) { + DRXUCodeBlockHdr_t blockHdr; + u16_t mcBlockNrBytes = 0; + + /* Process block header */ + blockHdr.addr = UCodeRead32(mcData); + mcData += sizeof(u32_t); + blockHdr.size = UCodeRead16(mcData); + mcData += sizeof(u16_t); + blockHdr.flags = UCodeRead16(mcData); + mcData += sizeof(u16_t); + blockHdr.CRC = UCodeRead16(mcData); + mcData += sizeof(u16_t); + + /* Check block header on: + - data larger than 64Kb + - if CRC enabled check CRC + */ + if ((blockHdr.size > 0x7FFF) || + (((blockHdr.flags & DRX_UCODE_CRC_FLAG) != 0) && + (blockHdr.CRC != UCodeComputeCRC (mcData, blockHdr.size))) + ) { + /* Wrong data ! */ + return DRX_STS_INVALID_ARG; + } + + mcBlockNrBytes = blockHdr.size * ((u16_t)sizeof(u16_t)); + + if (blockHdr.size != 0) { + /* Perform the desired action */ + switch (action) { + /*================================================================*/ + case UCODE_UPLOAD : { + /* Upload microcode */ + if (demod->myAccessFunct->writeBlockFunc( + devAddr, + (DRXaddr_t) blockHdr.addr, + mcBlockNrBytes, + mcData, + 0x0000) != DRX_STS_OK) { + return (DRX_STS_ERROR); + } /* if */ + }; + break; + + /*================================================================*/ + case UCODE_VERIFY : { + int result = 0; + u8_t mcDataBuffer[DRX_UCODE_MAX_BUF_SIZE]; + u32_t bytesToCompare=0; + u32_t bytesLeftToCompare=0; + DRXaddr_t currAddr = (DRXaddr_t)0; + pu8_t currPtr =NULL; + + bytesLeftToCompare = mcBlockNrBytes; + currAddr = blockHdr.addr; + currPtr = mcData; + + while(bytesLeftToCompare != 0) { + if (bytesLeftToCompare > ((u32_t)DRX_UCODE_MAX_BUF_SIZE)) { + bytesToCompare = ((u32_t)DRX_UCODE_MAX_BUF_SIZE); + } + else { + bytesToCompare = bytesLeftToCompare; + } + + if (demod->myAccessFunct->readBlockFunc( + devAddr, + currAddr, + (u16_t)bytesToCompare, + (pu8_t)mcDataBuffer, + 0x0000) != DRX_STS_OK) { + return (DRX_STS_ERROR); + } + + result = DRXBSP_HST_Memcmp(currPtr, + mcDataBuffer, + bytesToCompare); + + if (result != 0) { + return DRX_STS_ERROR; + } + + currAddr += ((DRXaddr_t)(bytesToCompare/2)); + currPtr = &(currPtr[bytesToCompare]); + bytesLeftToCompare -= ((u32_t)bytesToCompare); + } /* while(bytesToCompare > DRX_UCODE_MAX_BUF_SIZE) */ + }; + break; + + /*================================================================*/ + default: + return DRX_STS_INVALID_ARG; + break; + + } /* switch (action) */ + } /* if (blockHdr.size != 0) */ + + /* Next block */ + mcData += mcBlockNrBytes; + + } /* for(i = 0 ; i<mcNrOfBlks ; i++) */ + + return DRX_STS_OK; +} + +/*============================================================================*/ + +/** +* \brief Build list of version information. +* \param demod: A pointer to a demodulator instance. +* \param versionList: Pointer to linked list of versions. +* \return DRXStatus_t. +* \retval DRX_STS_OK: Version information stored in versionList +* \retval DRX_STS_INVALID_ARG: Invalid arguments. +*/ +static DRXStatus_t +CtrlVersion(pDRXDemodInstance_t demod, + pDRXVersionList_t *versionList) +{ + static char drxDriverCoreModuleName[] = "Core driver"; + static char drxDriverCoreVersionText[] = + DRX_VERSIONSTRING(VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH); + + static DRXVersion_t drxDriverCoreVersion; + static DRXVersionList_t drxDriverCoreVersionList; + + pDRXVersionList_t demodVersionList = (pDRXVersionList_t)(NULL); + DRXStatus_t returnStatus = DRX_STS_ERROR; + + /* Check arguments */ + if (versionList == NULL) { + return DRX_STS_INVALID_ARG; + } + + /* Get version info list from demod */ + returnStatus = (*(demod->myDemodFunct->ctrlFunc))( + demod, + DRX_CTRL_VERSION, + (void *) &demodVersionList); + + /* Always fill in the information of the driver SW . */ + drxDriverCoreVersion.moduleType = DRX_MODULE_DRIVERCORE; + drxDriverCoreVersion.moduleName = drxDriverCoreModuleName; + drxDriverCoreVersion.vMajor = VERSION_MAJOR; + drxDriverCoreVersion.vMinor = VERSION_MINOR; + drxDriverCoreVersion.vPatch = VERSION_PATCH; + drxDriverCoreVersion.vString = drxDriverCoreVersionText; + + drxDriverCoreVersionList.version = &drxDriverCoreVersion; + drxDriverCoreVersionList.next = (pDRXVersionList_t)(NULL); + + if ((returnStatus == DRX_STS_OK) && (demodVersionList != NULL)) { + /* Append versioninfo from driver to versioninfo from demod */ + /* Return version info in "bottom-up" order. This way, multiple + devices can be handled without using malloc. */ + pDRXVersionList_t currentListElement = demodVersionList; + while (currentListElement->next != NULL) { + currentListElement = currentListElement->next; + } + currentListElement->next = &drxDriverCoreVersionList; + + *versionList = demodVersionList; + } + else { + /* Just return versioninfo from driver */ + *versionList = &drxDriverCoreVersionList; + } + + return DRX_STS_OK; +} + +/*============================================================================*/ +/*============================================================================*/ +/*== Exported functions ======================================================*/ +/*============================================================================*/ +/*============================================================================*/ + + + +/** +* \brief This function is obsolete. +* \param demods: Don't care, parameter is ignored. +* \return DRXStatus_t Return status. +* \retval DRX_STS_OK: Initialization completed. +* +* This function is obsolete, prototype available for backward compatability. +* +*/ + +DRXStatus_t +DRX_Init(pDRXDemodInstance_t demods[]) +{ + return DRX_STS_OK; +} + +/*============================================================================*/ + +/** +* \brief This function is obsolete. +* \return DRXStatus_t Return status. +* \retval DRX_STS_OK: Terminated driver successful. +* +* This function is obsolete, prototype available for backward compatability. +* +*/ + +DRXStatus_t +DRX_Term(void) +{ + return DRX_STS_OK; +} + +/*============================================================================*/ + +/** +* \brief Open a demodulator instance. +* \param demod: A pointer to a demodulator instance. +* \return DRXStatus_t Return status. +* \retval DRX_STS_OK: Opened demod instance with succes. +* \retval DRX_STS_ERROR: Driver not initialized or unable to initialize +* demod. +* \retval DRX_STS_INVALID_ARG: Demod instance has invalid content. +* +*/ + +DRXStatus_t +DRX_Open(pDRXDemodInstance_t demod) +{ + DRXStatus_t status = DRX_STS_OK; + + if ((demod == NULL) || + (demod->myDemodFunct == NULL) || + (demod->myCommonAttr == NULL) || + (demod->myExtAttr == NULL) || + (demod->myI2CDevAddr == NULL) || + (demod->myCommonAttr->isOpened == TRUE)) { + return (DRX_STS_INVALID_ARG); + } + + status = (*(demod->myDemodFunct->openFunc))(demod); + + if (status == DRX_STS_OK) { + demod->myCommonAttr->isOpened = TRUE; + } + + return status; +} + +/*============================================================================*/ + +/** +* \brief Close device. +* \param demod: A pointer to a demodulator instance. +* \return DRXStatus_t Return status. +* \retval DRX_STS_OK: Closed demod instance with succes. +* \retval DRX_STS_ERROR: Driver not initialized or error during close +* demod. +* \retval DRX_STS_INVALID_ARG: Demod instance has invalid content. +* +* Free resources occupied by device instance. +* Put device into sleep mode. +*/ + +DRXStatus_t +DRX_Close(pDRXDemodInstance_t demod) +{ + DRXStatus_t status = DRX_STS_OK; + + if ((demod == NULL) || + (demod->myDemodFunct == NULL) || + (demod->myCommonAttr == NULL) || + (demod->myExtAttr == NULL) || + (demod->myI2CDevAddr == NULL) || + (demod->myCommonAttr->isOpened == FALSE)) { + return DRX_STS_INVALID_ARG; + } + + status = (*(demod->myDemodFunct->closeFunc))(demod); + + DRX_SET_ISOPENED (demod, FALSE); + + return status; +} + +/*============================================================================*/ + +/** +* \brief Control the device. +* \param demod: A pointer to a demodulator instance. +* \param ctrl: Reference to desired control function. +* \param ctrlData: Pointer to data structure for control function. +* \return DRXStatus_t Return status. +* \retval DRX_STS_OK: Control function completed successfully. +* \retval DRX_STS_ERROR: Driver not initialized or error during +* control demod. +* \retval DRX_STS_INVALID_ARG: Demod instance or ctrlData has invalid +* content. +* \retval DRX_STS_FUNC_NOT_AVAILABLE: Specified control function is not +* available. +* +* Data needed or returned by the control function is stored in ctrlData. +* +*/ + +DRXStatus_t +DRX_Ctrl(pDRXDemodInstance_t demod, DRXCtrlIndex_t ctrl, void *ctrlData) +{ + DRXStatus_t status = DRX_STS_ERROR; + + if ((demod == NULL) || + (demod->myDemodFunct == NULL) || + (demod->myCommonAttr == NULL) || + (demod->myExtAttr == NULL) || + (demod->myI2CDevAddr == NULL) + ) { + return (DRX_STS_INVALID_ARG); + } + + if (((demod->myCommonAttr->isOpened == FALSE) && + (ctrl != DRX_CTRL_PROBE_DEVICE) && + (ctrl != DRX_CTRL_VERSION)) + ) { + return (DRX_STS_INVALID_ARG); + } + + if ((DRX_ISPOWERDOWNMODE(demod->myCommonAttr->currentPowerMode) && + (ctrl != DRX_CTRL_POWER_MODE) && + (ctrl != DRX_CTRL_PROBE_DEVICE) && + (ctrl != DRX_CTRL_NOP) && + (ctrl != DRX_CTRL_VERSION) + ) + ) { + return DRX_STS_FUNC_NOT_AVAILABLE; + } + + /* Fixed control functions */ + switch (ctrl) { + /*======================================================================*/ + case DRX_CTRL_NOP: + /* No operation */ + return DRX_STS_OK; + break; + + /*======================================================================*/ + case DRX_CTRL_VERSION: + return CtrlVersion(demod, (pDRXVersionList_t *) ctrlData); + break; + + /*======================================================================*/ + default : + /* Do nothing */ + break; + } + + /* Virtual functions */ + /* First try calling function from derived class */ + status = (*(demod->myDemodFunct->ctrlFunc))(demod, ctrl, ctrlData); + if (status == DRX_STS_FUNC_NOT_AVAILABLE) { + /* Now try calling a the base class function */ + switch (ctrl) { + /*===================================================================*/ + case DRX_CTRL_LOAD_UCODE: + return CtrlUCode (demod, + (pDRXUCodeInfo_t) ctrlData, + UCODE_UPLOAD); + break; + + /*===================================================================*/ + case DRX_CTRL_VERIFY_UCODE: { + return CtrlUCode (demod, + (pDRXUCodeInfo_t) ctrlData, + UCODE_VERIFY); + } + break; + +#ifndef DRX_EXCLUDE_SCAN + /*===================================================================*/ + case DRX_CTRL_SCAN_INIT: { + return CtrlScanInit(demod, (pDRXScanParam_t) ctrlData); + } + break; + + /*===================================================================*/ + case DRX_CTRL_SCAN_NEXT: { + return CtrlScanNext(demod, (pu16_t) ctrlData); + } + break; + + /*===================================================================*/ + case DRX_CTRL_SCAN_STOP: { + return CtrlScanStop(demod); + } + break; +#endif /* #ifndef DRX_EXCLUDE_SCAN */ + + /*===================================================================*/ + case DRX_CTRL_PROGRAM_TUNER: { + return CtrlProgramTuner(demod, (pDRXChannel_t) ctrlData); + } + break; + + /*===================================================================*/ + case DRX_CTRL_DUMP_REGISTERS: { + return CtrlDumpRegisters(demod, (pDRXRegDump_t) ctrlData); + } + break; + + /*===================================================================*/ + default : + return DRX_STS_FUNC_NOT_AVAILABLE; + } + } + else { + return (status); + } + + return DRX_STS_OK; +} + + +/*============================================================================*/ + +/* END OF FILE */ -- 1.7.5.4 -- To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html