[PATCH 11/25] added drx_driver for pctv80e support

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



---
 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


[Index of Archives]     [Linux Input]     [Video for Linux]     [Gstreamer Embedded]     [Mplayer Users]     [Linux USB Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]
  Powered by Linux