[media] drx-j: get rid of the integer typedefs
[deliverable/linux.git] / drivers / media / dvb-frontends / drx39xyj / drx_driver.c
CommitLineData
ca3355a9
DH
1/*
2 Copyright (c), 2004-2005,2007-2010 Trident Microsystems, Inc.
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are met:
7
8 * Redistributions of source code must retain the above copyright notice,
9 this list of conditions and the following disclaimer.
10 * Redistributions in binary form must reproduce the above copyright notice,
11 this list of conditions and the following disclaimer in the documentation
12 and/or other materials provided with the distribution.
13 * Neither the name of Trident Microsystems nor Hauppauge Computer Works
14 nor the names of its contributors may be used to endorse or promote
15 products derived from this software without specific prior written
16 permission.
17
18 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
22 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 POSSIBILITY OF SUCH DAMAGE.
29*/
30
38b2df95
DH
31/**
32* \file $Id: drx_driver.c,v 1.40 2010/01/12 01:24:56 lfeng Exp $
33*
34* \brief Generic DRX functionality, DRX driver core.
35*
38b2df95
DH
36*/
37
38/*------------------------------------------------------------------------------
39INCLUDE FILES
40------------------------------------------------------------------------------*/
41#include "drx_driver.h"
42#include "bsp_host.h"
43
44#define VERSION_FIXED 0
45#if VERSION_FIXED
46#define VERSION_MAJOR 0
47#define VERSION_MINOR 0
48#define VERSION_PATCH 0
49#else
50#include "drx_driver_version.h"
51#endif
52
53/*------------------------------------------------------------------------------
54DEFINES
55------------------------------------------------------------------------------*/
56
57/*============================================================================*/
58/*=== MICROCODE RELATED DEFINES ==============================================*/
59/*============================================================================*/
60
61/** \brief Magic word for checking correct Endianess of microcode data. */
62#ifndef DRX_UCODE_MAGIC_WORD
43a431e4 63#define DRX_UCODE_MAGIC_WORD ((((u16)'H')<<8)+((u16)'L'))
38b2df95
DH
64#endif
65
66/** \brief CRC flag in ucode header, flags field. */
67#ifndef DRX_UCODE_CRC_FLAG
68#define DRX_UCODE_CRC_FLAG (0x0001)
69#endif
70
71/** \brief Compression flag in ucode header, flags field. */
72#ifndef DRX_UCODE_COMPRESSION_FLAG
73#define DRX_UCODE_COMPRESSION_FLAG (0x0002)
74#endif
75
76/** \brief Maximum size of buffer used to verify the microcode.
77 Must be an even number. */
78#ifndef DRX_UCODE_MAX_BUF_SIZE
79#define DRX_UCODE_MAX_BUF_SIZE (DRXDAP_MAX_RCHUNKSIZE)
80#endif
81#if DRX_UCODE_MAX_BUF_SIZE & 1
82#error DRX_UCODE_MAX_BUF_SIZE must be an even number
83#endif
84
85/*============================================================================*/
86/*=== CHANNEL SCAN RELATED DEFINES ===========================================*/
87/*============================================================================*/
88
89/**
90* \brief Maximum progress indication.
91*
92* Progress indication will run from 0 upto DRX_SCAN_MAX_PROGRESS during scan.
93*
94*/
95#ifndef DRX_SCAN_MAX_PROGRESS
96#define DRX_SCAN_MAX_PROGRESS 1000
97#endif
98
99/*============================================================================*/
100/*=== MACROS =================================================================*/
101/*============================================================================*/
102
103#define DRX_ISPOWERDOWNMODE( mode ) ( ( mode == DRX_POWER_MODE_9 ) || \
104 ( mode == DRX_POWER_MODE_10 ) || \
105 ( mode == DRX_POWER_MODE_11 ) || \
106 ( mode == DRX_POWER_MODE_12 ) || \
107 ( mode == DRX_POWER_MODE_13 ) || \
108 ( mode == DRX_POWER_MODE_14 ) || \
109 ( mode == DRX_POWER_MODE_15 ) || \
110 ( mode == DRX_POWER_MODE_16 ) || \
111 ( mode == DRX_POWER_DOWN ) )
112
113/*------------------------------------------------------------------------------
114GLOBAL VARIABLES
115------------------------------------------------------------------------------*/
116
117/*------------------------------------------------------------------------------
118STRUCTURES
119------------------------------------------------------------------------------*/
120/** \brief Structure of the microcode block headers */
121typedef struct {
43a431e4 122 u32 addr;
443f18d0 123 /**< Destination address of the data in this block */
43a431e4 124 u16 size;
443f18d0 125 /**< Size of the block data following this header counted in
38b2df95 126 16 bits words */
43a431e4 127 u16 flags;
443f18d0 128 /**< Flags for this data block:
38b2df95
DH
129 - bit[0]= CRC on/off
130 - bit[1]= compression on/off
131 - bit[15..2]=reserved */
43a431e4 132 u16 CRC;/**< CRC value of the data block, only valid if CRC flag is
38b2df95
DH
133 set. */
134} DRXUCodeBlockHdr_t, *pDRXUCodeBlockHdr_t;
135
136/*------------------------------------------------------------------------------
137FUNCTIONS
138------------------------------------------------------------------------------*/
139
140/*============================================================================*/
141/*============================================================================*/
142/*== Channel Scan Functions ==================================================*/
143/*============================================================================*/
144/*============================================================================*/
145
146#ifndef DRX_EXCLUDE_SCAN
147
148/* Prototype of default scanning function */
149static DRXStatus_t
443f18d0
MCC
150ScanFunctionDefault(void *scanContext,
151 DRXScanCommand_t scanCommand,
152 pDRXChannel_t scanChannel, pBool_t getNextChannel);
38b2df95
DH
153
154/**
155* \brief Get pointer to scanning function.
156* \param demod: Pointer to demodulator instance.
157* \return DRXScanFunc_t.
158*/
443f18d0 159static DRXScanFunc_t GetScanFunction(pDRXDemodInstance_t demod)
38b2df95 160{
443f18d0
MCC
161 pDRXCommonAttr_t commonAttr = (pDRXCommonAttr_t) (NULL);
162 DRXScanFunc_t scanFunc = (DRXScanFunc_t) (NULL);
163
164 /* get scan function from common attributes */
165 commonAttr = (pDRXCommonAttr_t) demod->myCommonAttr;
166 scanFunc = commonAttr->scanFunction;
167
168 if (scanFunc != NULL) {
169 /* return device-specific scan function if it's not NULL */
170 return scanFunc;
171 }
172 /* otherwise return default scan function in core driver */
173 return &ScanFunctionDefault;
38b2df95
DH
174}
175
176/**
177* \brief Get Context pointer.
178* \param demod: Pointer to demodulator instance.
179* \param scanContext: Context Pointer.
180* \return DRXScanFunc_t.
181*/
443f18d0 182void *GetScanContext(pDRXDemodInstance_t demod, void *scanContext)
38b2df95 183{
443f18d0 184 pDRXCommonAttr_t commonAttr = (pDRXCommonAttr_t) (NULL);
38b2df95 185
443f18d0
MCC
186 /* get scan function from common attributes */
187 commonAttr = (pDRXCommonAttr_t) demod->myCommonAttr;
188 scanContext = commonAttr->scanContext;
38b2df95 189
443f18d0
MCC
190 if (scanContext == NULL) {
191 scanContext = (void *)demod;
192 }
38b2df95 193
443f18d0 194 return scanContext;
38b2df95
DH
195}
196
197/**
198* \brief Wait for lock while scanning.
199* \param demod: Pointer to demodulator instance.
200* \param lockStat: Pointer to bool indicating if end result is lock or not.
201* \return DRXStatus_t.
202* \retval DRX_STS_OK: Success
203* \retval DRX_STS_ERROR: I2C failure or bsp function failure.
204*
205* Wait until timeout, desired lock or NEVER_LOCK.
206* Assume:
207* - lock function returns : at least DRX_NOT_LOCKED and a lock state
208* higher than DRX_NOT_LOCKED.
209* - BSP has a clock function to retrieve a millisecond ticker value.
210* - BSP has a sleep function to enable sleep of n millisecond.
211*
212* In case DRX_NEVER_LOCK is returned the poll-wait will be aborted.
213*
214*/
443f18d0 215static DRXStatus_t ScanWaitForLock(pDRXDemodInstance_t demod, pBool_t isLocked)
38b2df95 216{
443f18d0
MCC
217 Bool_t doneWaiting = FALSE;
218 DRXLockStatus_t lockState = DRX_NOT_LOCKED;
219 DRXLockStatus_t desiredLockState = DRX_NOT_LOCKED;
43a431e4
MCC
220 u32 timeoutValue = 0;
221 u32 startTimeLockStage = 0;
222 u32 currentTime = 0;
223 u32 timerValue = 0;
443f18d0
MCC
224
225 *isLocked = FALSE;
43a431e4 226 timeoutValue = (u32) demod->myCommonAttr->scanDemodLockTimeout;
443f18d0
MCC
227 desiredLockState = demod->myCommonAttr->scanDesiredLock;
228 startTimeLockStage = DRXBSP_HST_Clock();
229
230 /* Start polling loop, checking for lock & timeout */
231 while (doneWaiting == FALSE) {
232
233 if (DRX_Ctrl(demod, DRX_CTRL_LOCK_STATUS, &lockState) !=
234 DRX_STS_OK) {
235 return DRX_STS_ERROR;
236 }
237 currentTime = DRXBSP_HST_Clock();
238
239 timerValue = currentTime - startTimeLockStage;
240 if (lockState >= desiredLockState) {
241 *isLocked = TRUE;
242 doneWaiting = TRUE;
243 } /* if ( lockState >= desiredLockState ) .. */
244 else if (lockState == DRX_NEVER_LOCK) {
245 doneWaiting = TRUE;
246 } /* if ( lockState == DRX_NEVER_LOCK ) .. */
247 else if (timerValue > timeoutValue) {
248 /* lockState == DRX_NOT_LOCKED and timeout */
249 doneWaiting = TRUE;
250 } else {
251 if (DRXBSP_HST_Sleep(10) != DRX_STS_OK) {
252 return DRX_STS_ERROR;
253 }
254 } /* if ( timerValue > timeoutValue ) .. */
255
256 } /* while */
257
258 return DRX_STS_OK;
38b2df95
DH
259}
260
261/*============================================================================*/
262
263/**
264* \brief Determine next frequency to scan.
265* \param demod: Pointer to demodulator instance.
266* \param skip : Minimum frequency step to take.
267* \return DRXStatus_t.
268* \retval DRX_STS_OK: Succes.
269* \retval DRX_STS_INVALID_ARG: Invalid frequency plan.
270*
271* Helper function for CtrlScanNext() function.
272* Compute next frequency & index in frequency plan.
273* Check if scan is ready.
274*
275*/
276static DRXStatus_t
443f18d0 277ScanPrepareNextScan(pDRXDemodInstance_t demod, DRXFrequency_t skip)
38b2df95 278{
443f18d0 279 pDRXCommonAttr_t commonAttr = (pDRXCommonAttr_t) (NULL);
43a431e4
MCC
280 u16 tableIndex = 0;
281 u16 frequencyPlanSize = 0;
443f18d0
MCC
282 pDRXFrequencyPlan_t frequencyPlan = (pDRXFrequencyPlan_t) (NULL);
283 DRXFrequency_t nextFrequency = 0;
284 DRXFrequency_t tunerMinFrequency = 0;
285 DRXFrequency_t tunerMaxFrequency = 0;
286
287 commonAttr = (pDRXCommonAttr_t) demod->myCommonAttr;
288 tableIndex = commonAttr->scanFreqPlanIndex;
289 frequencyPlan = commonAttr->scanParam->frequencyPlan;
290 nextFrequency = commonAttr->scanNextFrequency;
291 tunerMinFrequency = commonAttr->tunerMinFreqRF;
292 tunerMaxFrequency = commonAttr->tunerMaxFreqRF;
293
294 do {
295 /* Search next frequency to scan */
296
297 /* always take at least one step */
298 (commonAttr->scanChannelsScanned)++;
299 nextFrequency += frequencyPlan[tableIndex].step;
300 skip -= frequencyPlan[tableIndex].step;
301
302 /* and then as many steps necessary to exceed 'skip'
303 without exceeding end of the band */
304 while ((skip > 0) &&
305 (nextFrequency <= frequencyPlan[tableIndex].last)) {
306 (commonAttr->scanChannelsScanned)++;
307 nextFrequency += frequencyPlan[tableIndex].step;
308 skip -= frequencyPlan[tableIndex].step;
309 }
310 /* reset skip, in case we move to the next band later */
311 skip = 0;
312
313 if (nextFrequency > frequencyPlan[tableIndex].last) {
314 /* reached end of this band */
315 tableIndex++;
316 frequencyPlanSize =
317 commonAttr->scanParam->frequencyPlanSize;
318 if (tableIndex >= frequencyPlanSize) {
319 /* reached end of frequency plan */
320 commonAttr->scanReady = TRUE;
321 } else {
322 nextFrequency = frequencyPlan[tableIndex].first;
323 }
324 }
325 if (nextFrequency > (tunerMaxFrequency)) {
326 /* reached end of tuner range */
327 commonAttr->scanReady = TRUE;
328 }
329 } while ((nextFrequency < tunerMinFrequency) &&
330 (commonAttr->scanReady == FALSE));
331
332 /* Store new values */
333 commonAttr->scanFreqPlanIndex = tableIndex;
334 commonAttr->scanNextFrequency = nextFrequency;
335
336 return DRX_STS_OK;
38b2df95
DH
337}
338
339/*============================================================================*/
340
341/**
342* \brief Default DTV scanning function.
343*
344* \param demod: Pointer to demodulator instance.
345* \param scanCommand: Scanning command: INIT, NEXT or STOP.
346* \param scanChannel: Channel to check: frequency and bandwidth, others AUTO
347* \param getNextChannel: Return TRUE if next frequency is desired at next call
348*
349* \return DRXStatus_t.
350* \retval DRX_STS_OK: Channel found, DRX_CTRL_GET_CHANNEL can be used
351* to retrieve channel parameters.
352* \retval DRX_STS_BUSY: Channel not found (yet).
353* \retval DRX_STS_ERROR: Something went wrong.
354*
355* scanChannel and getNextChannel will be NULL for INIT and STOP.
356*/
357static DRXStatus_t
443f18d0
MCC
358ScanFunctionDefault(void *scanContext,
359 DRXScanCommand_t scanCommand,
360 pDRXChannel_t scanChannel, pBool_t getNextChannel)
38b2df95 361{
443f18d0
MCC
362 pDRXDemodInstance_t demod = NULL;
363 DRXStatus_t status = DRX_STS_ERROR;
364 Bool_t isLocked = FALSE;
365
366 demod = (pDRXDemodInstance_t) scanContext;
367
368 if (scanCommand != DRX_SCAN_COMMAND_NEXT) {
369 /* just return OK if not doing "scan next" */
370 return DRX_STS_OK;
371 }
372
373 *getNextChannel = FALSE;
374
375 status = DRX_Ctrl(demod, DRX_CTRL_SET_CHANNEL, scanChannel);
376 if (status != DRX_STS_OK) {
377 return (status);
378 }
379
380 status = ScanWaitForLock(demod, &isLocked);
381 if (status != DRX_STS_OK) {
382 return status;
383 }
384
385 /* done with this channel, move to next one */
386 *getNextChannel = TRUE;
387
388 if (isLocked == FALSE) {
389 /* no channel found */
390 return DRX_STS_BUSY;
391 }
392 /* channel found */
393 return DRX_STS_OK;
38b2df95
DH
394}
395
396/*============================================================================*/
397
398/**
399* \brief Initialize for channel scan.
400* \param demod: Pointer to demodulator instance.
401* \param scanParam: Pointer to scan parameters.
402* \return DRXStatus_t.
403* \retval DRX_STS_OK: Initialized for scan.
404* \retval DRX_STS_ERROR: No overlap between frequency plan and tuner
405* range.
406* \retval DRX_STS_INVALID_ARG: Wrong parameters.
407*
408* This function should be called before starting a complete channel scan.
409* It will prepare everything for a complete channel scan.
410* After calling this function the DRX_CTRL_SCAN_NEXT control function can be
411* used to perform the actual scanning. Scanning will start at the first
412* center frequency of the frequency plan that is within the tuner range.
413*
414*/
415static DRXStatus_t
443f18d0 416CtrlScanInit(pDRXDemodInstance_t demod, pDRXScanParam_t scanParam)
38b2df95 417{
443f18d0
MCC
418 DRXStatus_t status = DRX_STS_ERROR;
419 pDRXCommonAttr_t commonAttr = (pDRXCommonAttr_t) (NULL);
420 DRXFrequency_t maxTunerFreq = 0;
421 DRXFrequency_t minTunerFreq = 0;
43a431e4
MCC
422 u16 nrChannelsInPlan = 0;
423 u16 i = 0;
443f18d0
MCC
424 void *scanContext = NULL;
425
426 commonAttr = (pDRXCommonAttr_t) demod->myCommonAttr;
427 commonAttr->scanActive = TRUE;
428
429 /* invalidate a previous SCAN_INIT */
430 commonAttr->scanParam = (pDRXScanParam_t) (NULL);
431 commonAttr->scanNextFrequency = 0;
432
433 /* Check parameters */
434 if (((demod->myTuner == NULL) &&
435 (scanParam->numTries != 1)) ||
436 (scanParam == NULL) ||
437 (scanParam->numTries == 0) ||
438 (scanParam->frequencyPlan == NULL) ||
439 (scanParam->frequencyPlanSize == 0)
440 ) {
441 commonAttr->scanActive = FALSE;
442 return DRX_STS_INVALID_ARG;
443 }
444
445 /* Check frequency plan contents */
446 maxTunerFreq = commonAttr->tunerMaxFreqRF;
447 minTunerFreq = commonAttr->tunerMinFreqRF;
448 for (i = 0; i < (scanParam->frequencyPlanSize); i++) {
449 DRXFrequency_t width = 0;
450 DRXFrequency_t step = scanParam->frequencyPlan[i].step;
451 DRXFrequency_t firstFreq = scanParam->frequencyPlan[i].first;
452 DRXFrequency_t lastFreq = scanParam->frequencyPlan[i].last;
453 DRXFrequency_t minFreq = 0;
454 DRXFrequency_t maxFreq = 0;
455
456 if (step <= 0) {
457 /* Step must be positive and non-zero */
458 commonAttr->scanActive = FALSE;
459 return DRX_STS_INVALID_ARG;
460 }
461
462 if (firstFreq > lastFreq) {
463 /* First center frequency is higher than last center frequency */
464 commonAttr->scanActive = FALSE;
465 return DRX_STS_INVALID_ARG;
466 }
467
468 width = lastFreq - firstFreq;
469
470 if ((width % step) != 0) {
471 /* Difference between last and first center frequency is not
472 an integer number of steps */
473 commonAttr->scanActive = FALSE;
474 return DRX_STS_INVALID_ARG;
475 }
476
477 /* Check if frequency plan entry intersects with tuner range */
478 if (lastFreq >= minTunerFreq) {
479 if (firstFreq <= maxTunerFreq) {
480 if (firstFreq >= minTunerFreq) {
481 minFreq = firstFreq;
482 } else {
483 DRXFrequency_t n = 0;
484
485 n = (minTunerFreq - firstFreq) / step;
486 if (((minTunerFreq -
487 firstFreq) % step) != 0) {
488 n++;
489 }
490 minFreq = firstFreq + n * step;
491 }
492
493 if (lastFreq <= maxTunerFreq) {
494 maxFreq = lastFreq;
495 } else {
496 DRXFrequency_t n = 0;
497
498 n = (lastFreq - maxTunerFreq) / step;
499 if (((lastFreq -
500 maxTunerFreq) % step) != 0) {
501 n++;
502 }
503 maxFreq = lastFreq - n * step;
504 }
505 }
506 }
507
508 /* Keep track of total number of channels within tuner range
509 in this frequency plan. */
510 if ((minFreq != 0) && (maxFreq != 0)) {
511 nrChannelsInPlan +=
43a431e4 512 (u16) (((maxFreq - minFreq) / step) + 1);
443f18d0
MCC
513
514 /* Determine first frequency (within tuner range) to scan */
515 if (commonAttr->scanNextFrequency == 0) {
516 commonAttr->scanNextFrequency = minFreq;
517 commonAttr->scanFreqPlanIndex = i;
518 }
519 }
520
521 } /* for ( ... ) */
522
523 if (nrChannelsInPlan == 0) {
524 /* Tuner range and frequency plan ranges do not overlap */
525 commonAttr->scanActive = FALSE;
526 return DRX_STS_ERROR;
527 }
528
529 /* Store parameters */
530 commonAttr->scanReady = FALSE;
531 commonAttr->scanMaxChannels = nrChannelsInPlan;
532 commonAttr->scanChannelsScanned = 0;
533 commonAttr->scanParam = scanParam; /* SCAN_NEXT is now allowed */
534
535 scanContext = GetScanContext(demod, scanContext);
536
537 status = (*(GetScanFunction(demod)))
538 (scanContext, DRX_SCAN_COMMAND_INIT, NULL, NULL);
539
540 commonAttr->scanActive = FALSE;
541
542 return DRX_STS_OK;
38b2df95
DH
543}
544
545/*============================================================================*/
546
547/**
548* \brief Stop scanning.
549* \param demod: Pointer to demodulator instance.
550* \return DRXStatus_t.
551* \retval DRX_STS_OK: Scan stopped.
552* \retval DRX_STS_ERROR: Something went wrong.
553* \retval DRX_STS_INVALID_ARG: Wrong parameters.
554*/
443f18d0 555static DRXStatus_t CtrlScanStop(pDRXDemodInstance_t demod)
38b2df95 556{
443f18d0
MCC
557 DRXStatus_t status = DRX_STS_ERROR;
558 pDRXCommonAttr_t commonAttr = (pDRXCommonAttr_t) (NULL);
559 void *scanContext = NULL;
38b2df95 560
443f18d0
MCC
561 commonAttr = (pDRXCommonAttr_t) demod->myCommonAttr;
562 commonAttr->scanActive = TRUE;
38b2df95 563
443f18d0
MCC
564 if ((commonAttr->scanParam == NULL) ||
565 (commonAttr->scanMaxChannels == 0)) {
566 /* Scan was not running, just return OK */
567 commonAttr->scanActive = FALSE;
568 return DRX_STS_OK;
569 }
38b2df95 570
443f18d0
MCC
571 /* Call default or device-specific scanning stop function */
572 scanContext = GetScanContext(demod, scanContext);
38b2df95 573
443f18d0
MCC
574 status = (*(GetScanFunction(demod)))
575 (scanContext, DRX_SCAN_COMMAND_STOP, NULL, NULL);
38b2df95 576
443f18d0
MCC
577 /* All done, invalidate scan-init */
578 commonAttr->scanParam = NULL;
579 commonAttr->scanMaxChannels = 0;
580 commonAttr->scanActive = FALSE;
38b2df95 581
443f18d0 582 return status;
38b2df95
DH
583}
584
585/*============================================================================*/
586
587/**
588* \brief Scan for next channel.
589* \param demod: Pointer to demodulator instance.
590* \param scanProgress: Pointer to scan progress.
591* \return DRXStatus_t.
592* \retval DRX_STS_OK: Channel found, DRX_CTRL_GET_CHANNEL can be used
593* to retrieve channel parameters.
594* \retval DRX_STS_BUSY: Tried part of the channels, as specified in
595* numTries field of scan parameters. At least one
596* more call to DRX_CTRL_SCAN_NEXT is needed to
597* complete scanning.
598* \retval DRX_STS_READY: Reached end of scan range.
599* \retval DRX_STS_ERROR: Something went wrong.
600* \retval DRX_STS_INVALID_ARG: Wrong parameters. The scanProgress may be NULL.
601*
602* Progress indication will run from 0 upto DRX_SCAN_MAX_PROGRESS during scan.
603*
604*/
43a431e4 605static DRXStatus_t CtrlScanNext(pDRXDemodInstance_t demod, u16 *scanProgress)
38b2df95 606{
443f18d0
MCC
607 pDRXCommonAttr_t commonAttr = (pDRXCommonAttr_t) (NULL);
608 pBool_t scanReady = (pBool_t) (NULL);
43a431e4
MCC
609 u16 maxProgress = DRX_SCAN_MAX_PROGRESS;
610 u32 numTries = 0;
611 u32 i = 0;
443f18d0
MCC
612
613 commonAttr = (pDRXCommonAttr_t) demod->myCommonAttr;
614
615 /* Check scan parameters */
616 if (scanProgress == NULL) {
617 commonAttr->scanActive = FALSE;
618 return DRX_STS_INVALID_ARG;
619 }
620
621 *scanProgress = 0;
622 commonAttr->scanActive = TRUE;
623 if ((commonAttr->scanParam == NULL) ||
624 (commonAttr->scanMaxChannels == 0)) {
625 /* CtrlScanInit() was not called succesfully before CtrlScanNext() */
626 commonAttr->scanActive = FALSE;
627 return DRX_STS_ERROR;
628 }
629
43a431e4
MCC
630 *scanProgress = (u16) (((commonAttr->scanChannelsScanned) *
631 ((u32) (maxProgress))) /
443f18d0
MCC
632 (commonAttr->scanMaxChannels));
633
634 /* Scan */
635 numTries = commonAttr->scanParam->numTries;
636 scanReady = &(commonAttr->scanReady);
637
638 for (i = 0; ((i < numTries) && ((*scanReady) == FALSE)); i++) {
639 DRXChannel_t scanChannel = { 0 };
640 DRXStatus_t status = DRX_STS_ERROR;
641 pDRXFrequencyPlan_t freqPlan = (pDRXFrequencyPlan_t) (NULL);
642 Bool_t nextChannel = FALSE;
643 void *scanContext = NULL;
644
645 /* Next channel to scan */
646 freqPlan =
647 &(commonAttr->scanParam->
648 frequencyPlan[commonAttr->scanFreqPlanIndex]);
649 scanChannel.frequency = commonAttr->scanNextFrequency;
650 scanChannel.bandwidth = freqPlan->bandwidth;
651 scanChannel.mirror = DRX_MIRROR_AUTO;
652 scanChannel.constellation = DRX_CONSTELLATION_AUTO;
653 scanChannel.hierarchy = DRX_HIERARCHY_AUTO;
654 scanChannel.priority = DRX_PRIORITY_HIGH;
655 scanChannel.coderate = DRX_CODERATE_AUTO;
656 scanChannel.guard = DRX_GUARD_AUTO;
657 scanChannel.fftmode = DRX_FFTMODE_AUTO;
658 scanChannel.classification = DRX_CLASSIFICATION_AUTO;
659 scanChannel.symbolrate = 0;
660 scanChannel.interleavemode = DRX_INTERLEAVEMODE_AUTO;
661 scanChannel.ldpc = DRX_LDPC_AUTO;
662 scanChannel.carrier = DRX_CARRIER_AUTO;
663 scanChannel.framemode = DRX_FRAMEMODE_AUTO;
664 scanChannel.pilot = DRX_PILOT_AUTO;
665
666 /* Call default or device-specific scanning function */
667 scanContext = GetScanContext(demod, scanContext);
668
669 status = (*(GetScanFunction(demod)))
670 (scanContext, DRX_SCAN_COMMAND_NEXT, &scanChannel,
671 &nextChannel);
672
673 /* Proceed to next channel if requested */
674 if (nextChannel == TRUE) {
675 DRXStatus_t nextStatus = DRX_STS_ERROR;
676 DRXFrequency_t skip = 0;
677
678 if (status == DRX_STS_OK) {
679 /* a channel was found, so skip some frequency steps */
680 skip = commonAttr->scanParam->skip;
681 }
682 nextStatus = ScanPrepareNextScan(demod, skip);
683
684 /* keep track of progress */
685 *scanProgress =
43a431e4
MCC
686 (u16) (((commonAttr->scanChannelsScanned) *
687 ((u32) (maxProgress))) /
443f18d0
MCC
688 (commonAttr->scanMaxChannels));
689
690 if (nextStatus != DRX_STS_OK) {
691 commonAttr->scanActive = FALSE;
692 return (nextStatus);
693 }
694 }
695 if (status != DRX_STS_BUSY) {
696 /* channel found or error */
697 commonAttr->scanActive = FALSE;
698 return status;
699 }
700 } /* for ( i = 0; i < ( ... numTries); i++) */
701
702 if ((*scanReady) == TRUE) {
703 /* End of scan reached: call stop-scan, ignore any error */
704 CtrlScanStop(demod);
705 commonAttr->scanActive = FALSE;
706 return (DRX_STS_READY);
707 }
708
709 commonAttr->scanActive = FALSE;
710
711 return DRX_STS_BUSY;
38b2df95
DH
712}
713
714#endif /* #ifndef DRX_EXCLUDE_SCAN */
715
716/*============================================================================*/
717
718/**
719* \brief Program tuner.
720* \param demod: Pointer to demodulator instance.
721* \param tunerChannel: Pointer to tuning parameters.
722* \return DRXStatus_t.
723* \retval DRX_STS_OK: Tuner programmed successfully.
724* \retval DRX_STS_ERROR: Something went wrong.
725* \retval DRX_STS_INVALID_ARG: Wrong parameters.
726*
727* tunerChannel passes parameters to program the tuner,
728* but also returns the actual RF and IF frequency from the tuner.
729*
730*/
731static DRXStatus_t
443f18d0 732CtrlProgramTuner(pDRXDemodInstance_t demod, pDRXChannel_t channel)
38b2df95 733{
443f18d0
MCC
734 pDRXCommonAttr_t commonAttr = (pDRXCommonAttr_t) (NULL);
735 DRXStandard_t standard = DRX_STANDARD_UNKNOWN;
736 TUNERMode_t tunerMode = 0;
737 DRXStatus_t status = DRX_STS_ERROR;
738 DRXFrequency_t ifFrequency = 0;
739 Bool_t tunerSlowMode = FALSE;
740
741 /* can't tune without a tuner */
742 if (demod->myTuner == NULL) {
743 return DRX_STS_INVALID_ARG;
744 }
745
746 commonAttr = (pDRXCommonAttr_t) demod->myCommonAttr;
747
748 /* select analog or digital tuner mode based on current standard */
749 if (DRX_Ctrl(demod, DRX_CTRL_GET_STANDARD, &standard) != DRX_STS_OK) {
750 return DRX_STS_ERROR;
751 }
752
753 if (DRX_ISATVSTD(standard)) {
754 tunerMode |= TUNER_MODE_ANALOG;
755 } else { /* note: also for unknown standard */
756
757 tunerMode |= TUNER_MODE_DIGITAL;
758 }
759
760 /* select tuner bandwidth */
761 switch (channel->bandwidth) {
762 case DRX_BANDWIDTH_6MHZ:
763 tunerMode |= TUNER_MODE_6MHZ;
764 break;
765 case DRX_BANDWIDTH_7MHZ:
766 tunerMode |= TUNER_MODE_7MHZ;
767 break;
768 case DRX_BANDWIDTH_8MHZ:
769 tunerMode |= TUNER_MODE_8MHZ;
770 break;
771 default: /* note: also for unknown bandwidth */
772 return DRX_STS_INVALID_ARG;
773 }
774
775 DRX_GET_TUNERSLOWMODE(demod, tunerSlowMode);
776
777 /* select fast (switch) or slow (lock) tuner mode */
778 if (tunerSlowMode) {
779 tunerMode |= TUNER_MODE_LOCK;
780 } else {
781 tunerMode |= TUNER_MODE_SWITCH;
782 }
783
784 if (commonAttr->tunerPortNr == 1) {
785 Bool_t bridgeClosed = TRUE;
786 DRXStatus_t statusBridge = DRX_STS_ERROR;
787
788 statusBridge =
789 DRX_Ctrl(demod, DRX_CTRL_I2C_BRIDGE, &bridgeClosed);
790 if (statusBridge != DRX_STS_OK) {
791 return statusBridge;
792 }
793 }
794
795 status = DRXBSP_TUNER_SetFrequency(demod->myTuner,
796 tunerMode, channel->frequency);
797
798 /* attempt restoring bridge before checking status of SetFrequency */
799 if (commonAttr->tunerPortNr == 1) {
800 Bool_t bridgeClosed = FALSE;
801 DRXStatus_t statusBridge = DRX_STS_ERROR;
802
803 statusBridge =
804 DRX_Ctrl(demod, DRX_CTRL_I2C_BRIDGE, &bridgeClosed);
805 if (statusBridge != DRX_STS_OK) {
806 return statusBridge;
807 }
808 }
809
810 /* now check status of DRXBSP_TUNER_SetFrequency */
811 if (status != DRX_STS_OK) {
812 return status;
813 }
814
815 /* get actual RF and IF frequencies from tuner */
816 status = DRXBSP_TUNER_GetFrequency(demod->myTuner,
817 tunerMode,
818 &(channel->frequency),
819 &(ifFrequency));
820 if (status != DRX_STS_OK) {
821 return status;
822 }
823
824 /* update common attributes with information available from this function;
825 TODO: check if this is required and safe */
826 DRX_SET_INTERMEDIATEFREQ(demod, ifFrequency);
827
828 return DRX_STS_OK;
38b2df95
DH
829}
830
831/*============================================================================*/
832
833/**
834* \brief function to do a register dump.
835* \param demod: Pointer to demodulator instance.
836* \param registers: Registers to dump.
837* \return DRXStatus_t.
838* \retval DRX_STS_OK: Dump executed successfully.
839* \retval DRX_STS_ERROR: Something went wrong.
840* \retval DRX_STS_INVALID_ARG: Wrong parameters.
841*
842*/
443f18d0
MCC
843DRXStatus_t CtrlDumpRegisters(pDRXDemodInstance_t demod,
844 pDRXRegDump_t registers)
38b2df95 845{
43a431e4 846 u16 i = 0;
443f18d0
MCC
847
848 if (registers == NULL) {
849 /* registers not supplied */
850 return DRX_STS_INVALID_ARG;
851 }
852
853 /* start dumping registers */
854 while (registers[i].address != 0) {
855 DRXStatus_t status = DRX_STS_ERROR;
43a431e4
MCC
856 u16 value = 0;
857 u32 data = 0;
443f18d0
MCC
858
859 status =
860 demod->myAccessFunct->readReg16Func(demod->myI2CDevAddr,
861 registers[i].address,
862 &value, 0);
863
43a431e4 864 data = (u32) value;
443f18d0
MCC
865
866 if (status != DRX_STS_OK) {
867 /* no breakouts;
868 depending on device ID, some HW blocks might not be available */
43a431e4 869 data |= ((u32) status) << 16;
443f18d0
MCC
870 }
871 registers[i].data = data;
872 i++;
873 }
874
875 /* all done, all OK (any errors are saved inside data) */
876 return DRX_STS_OK;
38b2df95
DH
877}
878
879/*============================================================================*/
880/*============================================================================*/
881/*===Microcode related functions==============================================*/
882/*============================================================================*/
883/*============================================================================*/
884
885/**
886* \brief Read a 16 bits word, expects big endian data.
887* \param addr: Pointer to memory from which to read the 16 bits word.
43a431e4 888* \return u16 The data read.
38b2df95
DH
889*
890* This function takes care of the possible difference in endianness between the
891* host and the data contained in the microcode image file.
892*
893*/
43a431e4 894static u16 UCodeRead16(u8 *addr)
38b2df95 895{
443f18d0 896 /* Works fo any host processor */
38b2df95 897
43a431e4 898 u16 word = 0;
38b2df95 899
43a431e4 900 word = ((u16) addr[0]);
443f18d0 901 word <<= 8;
43a431e4 902 word |= ((u16) addr[1]);
38b2df95 903
443f18d0 904 return word;
38b2df95
DH
905}
906
907/*============================================================================*/
908
909/**
910* \brief Read a 32 bits word, expects big endian data.
911* \param addr: Pointer to memory from which to read the 32 bits word.
43a431e4 912* \return u32 The data read.
38b2df95
DH
913*
914* This function takes care of the possible difference in endianness between the
915* host and the data contained in the microcode image file.
916*
917*/
43a431e4 918static u32 UCodeRead32(u8 *addr)
38b2df95 919{
443f18d0 920 /* Works fo any host processor */
38b2df95 921
43a431e4 922 u32 word = 0;
38b2df95 923
43a431e4 924 word = ((u16) addr[0]);
443f18d0 925 word <<= 8;
43a431e4 926 word |= ((u16) addr[1]);
443f18d0 927 word <<= 8;
43a431e4 928 word |= ((u16) addr[2]);
443f18d0 929 word <<= 8;
43a431e4 930 word |= ((u16) addr[3]);
38b2df95 931
443f18d0 932 return word;
38b2df95
DH
933}
934
935/*============================================================================*/
936
937/**
938* \brief Compute CRC of block of microcode data.
939* \param blockData: Pointer to microcode data.
940* \param nrWords: Size of microcode block (number of 16 bits words).
43a431e4 941* \return u16 The computed CRC residu.
38b2df95 942*/
43a431e4 943static u16 UCodeComputeCRC(u8 *blockData, u16 nrWords)
38b2df95 944{
43a431e4
MCC
945 u16 i = 0;
946 u16 j = 0;
947 u32 CRCWord = 0;
948 u32 carry = 0;
443f18d0
MCC
949
950 while (i < nrWords) {
43a431e4 951 CRCWord |= (u32) UCodeRead16(blockData);
443f18d0
MCC
952 for (j = 0; j < 16; j++) {
953 CRCWord <<= 1;
954 if (carry != 0) {
955 CRCWord ^= 0x80050000UL;
956 }
957 carry = CRCWord & 0x80000000UL;
958 }
959 i++;
43a431e4 960 blockData += (sizeof(u16));
443f18d0 961 }
43a431e4 962 return ((u16) (CRCWord >> 16));
38b2df95
DH
963}
964
965/*============================================================================*/
966
967/**
968* \brief Handle microcode upload or verify.
969* \param devAddr: Address of device.
970* \param mcInfo: Pointer to information about microcode data.
971* \param action: Either UCODE_UPLOAD or UCODE_VERIFY
972* \return DRXStatus_t.
973* \retval DRX_STS_OK:
974* - In case of UCODE_UPLOAD: code is successfully uploaded.
975* - In case of UCODE_VERIFY: image on device is equal to
976* image provided to this control function.
977* \retval DRX_STS_ERROR:
978* - In case of UCODE_UPLOAD: I2C error.
979* - In case of UCODE_VERIFY: I2C error or image on device
980* is not equal to image provided to this control function.
981* \retval DRX_STS_INVALID_ARG:
982* - Invalid arguments.
983* - Provided image is corrupt
984*/
985static DRXStatus_t
443f18d0
MCC
986CtrlUCode(pDRXDemodInstance_t demod,
987 pDRXUCodeInfo_t mcInfo, DRXUCodeAction_t action)
38b2df95 988{
443f18d0 989 DRXStatus_t rc;
43a431e4
MCC
990 u16 i = 0;
991 u16 mcNrOfBlks = 0;
992 u16 mcMagicWord = 0;
993 u8 *mcData = (u8 *) (NULL);
5b223b39 994 struct i2c_device_addr *devAddr = (struct i2c_device_addr *) (NULL);
443f18d0
MCC
995
996 devAddr = demod->myI2CDevAddr;
997
998 /* Check arguments */
999 if ((mcInfo == NULL) || (mcInfo->mcData == NULL)) {
1000 return DRX_STS_INVALID_ARG;
1001 }
1002
1003 mcData = mcInfo->mcData;
1004
1005 /* Check data */
1006 mcMagicWord = UCodeRead16(mcData);
43a431e4 1007 mcData += sizeof(u16);
443f18d0 1008 mcNrOfBlks = UCodeRead16(mcData);
43a431e4 1009 mcData += sizeof(u16);
443f18d0
MCC
1010
1011 if ((mcMagicWord != DRX_UCODE_MAGIC_WORD) || (mcNrOfBlks == 0)) {
1012 /* wrong endianess or wrong data ? */
1013 return DRX_STS_INVALID_ARG;
1014 }
1015
1016 /* Scan microcode blocks first for version info if uploading */
1017 if (action == UCODE_UPLOAD) {
1018 /* Clear version block */
1019 DRX_SET_MCVERTYPE(demod, 0);
1020 DRX_SET_MCDEV(demod, 0);
1021 DRX_SET_MCVERSION(demod, 0);
1022 DRX_SET_MCPATCH(demod, 0);
1023 for (i = 0; i < mcNrOfBlks; i++) {
1024 DRXUCodeBlockHdr_t blockHdr;
1025
1026 /* Process block header */
1027 blockHdr.addr = UCodeRead32(mcData);
43a431e4 1028 mcData += sizeof(u32);
443f18d0 1029 blockHdr.size = UCodeRead16(mcData);
43a431e4 1030 mcData += sizeof(u16);
443f18d0 1031 blockHdr.flags = UCodeRead16(mcData);
43a431e4 1032 mcData += sizeof(u16);
443f18d0 1033 blockHdr.CRC = UCodeRead16(mcData);
43a431e4 1034 mcData += sizeof(u16);
443f18d0
MCC
1035
1036 if (blockHdr.flags & 0x8) {
1037 /* Aux block. Check type */
43a431e4
MCC
1038 u8 *auxblk = mcInfo->mcData + blockHdr.addr;
1039 u16 auxtype = UCodeRead16(auxblk);
443f18d0
MCC
1040 if (DRX_ISMCVERTYPE(auxtype)) {
1041 DRX_SET_MCVERTYPE(demod,
1042 UCodeRead16(auxblk));
43a431e4 1043 auxblk += sizeof(u16);
443f18d0
MCC
1044 DRX_SET_MCDEV(demod,
1045 UCodeRead32(auxblk));
43a431e4 1046 auxblk += sizeof(u32);
443f18d0
MCC
1047 DRX_SET_MCVERSION(demod,
1048 UCodeRead32(auxblk));
43a431e4 1049 auxblk += sizeof(u32);
443f18d0
MCC
1050 DRX_SET_MCPATCH(demod,
1051 UCodeRead32(auxblk));
1052 }
1053 }
1054
1055 /* Next block */
43a431e4 1056 mcData += blockHdr.size * sizeof(u16);
443f18d0
MCC
1057 }
1058
1059 /* After scanning, validate the microcode.
1060 It is also valid if no validation control exists.
1061 */
1062 rc = DRX_Ctrl(demod, DRX_CTRL_VALIDATE_UCODE, NULL);
1063 if (rc != DRX_STS_OK && rc != DRX_STS_FUNC_NOT_AVAILABLE) {
1064 return rc;
1065 }
1066
1067 /* Restore data pointer */
43a431e4 1068 mcData = mcInfo->mcData + 2 * sizeof(u16);
443f18d0
MCC
1069 }
1070
1071 /* Process microcode blocks */
1072 for (i = 0; i < mcNrOfBlks; i++) {
1073 DRXUCodeBlockHdr_t blockHdr;
43a431e4 1074 u16 mcBlockNrBytes = 0;
443f18d0
MCC
1075
1076 /* Process block header */
1077 blockHdr.addr = UCodeRead32(mcData);
43a431e4 1078 mcData += sizeof(u32);
443f18d0 1079 blockHdr.size = UCodeRead16(mcData);
43a431e4 1080 mcData += sizeof(u16);
443f18d0 1081 blockHdr.flags = UCodeRead16(mcData);
43a431e4 1082 mcData += sizeof(u16);
443f18d0 1083 blockHdr.CRC = UCodeRead16(mcData);
43a431e4 1084 mcData += sizeof(u16);
443f18d0
MCC
1085
1086 /* Check block header on:
1087 - data larger than 64Kb
1088 - if CRC enabled check CRC
1089 */
1090 if ((blockHdr.size > 0x7FFF) ||
1091 (((blockHdr.flags & DRX_UCODE_CRC_FLAG) != 0) &&
1092 (blockHdr.CRC != UCodeComputeCRC(mcData, blockHdr.size)))
1093 ) {
1094 /* Wrong data ! */
1095 return DRX_STS_INVALID_ARG;
1096 }
1097
43a431e4 1098 mcBlockNrBytes = blockHdr.size * ((u16) sizeof(u16));
443f18d0
MCC
1099
1100 if (blockHdr.size != 0) {
1101 /* Perform the desired action */
1102 switch (action) {
38b2df95 1103 /*================================================================*/
443f18d0
MCC
1104 case UCODE_UPLOAD:
1105 {
1106 /* Upload microcode */
1107 if (demod->myAccessFunct->
1108 writeBlockFunc(devAddr,
1109 (DRXaddr_t) blockHdr.
1110 addr, mcBlockNrBytes,
1111 mcData,
1112 0x0000) !=
1113 DRX_STS_OK) {
1114 return (DRX_STS_ERROR);
1115 } /* if */
1116 };
1117 break;
38b2df95
DH
1118
1119 /*================================================================*/
443f18d0
MCC
1120 case UCODE_VERIFY:
1121 {
1122 int result = 0;
43a431e4 1123 u8 mcDataBuffer
443f18d0 1124 [DRX_UCODE_MAX_BUF_SIZE];
43a431e4
MCC
1125 u32 bytesToCompare = 0;
1126 u32 bytesLeftToCompare = 0;
443f18d0 1127 DRXaddr_t currAddr = (DRXaddr_t) 0;
43a431e4 1128 u8 *currPtr = NULL;
443f18d0
MCC
1129
1130 bytesLeftToCompare = mcBlockNrBytes;
1131 currAddr = blockHdr.addr;
1132 currPtr = mcData;
1133
1134 while (bytesLeftToCompare != 0) {
1135 if (bytesLeftToCompare >
43a431e4 1136 ((u32)
443f18d0
MCC
1137 DRX_UCODE_MAX_BUF_SIZE)) {
1138 bytesToCompare =
43a431e4 1139 ((u32)
443f18d0
MCC
1140 DRX_UCODE_MAX_BUF_SIZE);
1141 } else {
1142 bytesToCompare =
1143 bytesLeftToCompare;
1144 }
1145
1146 if (demod->myAccessFunct->
1147 readBlockFunc(devAddr,
1148 currAddr,
43a431e4 1149 (u16)
443f18d0 1150 bytesToCompare,
43a431e4 1151 (u8 *)
443f18d0
MCC
1152 mcDataBuffer,
1153 0x0000) !=
1154 DRX_STS_OK) {
1155 return (DRX_STS_ERROR);
1156 }
1157
1158 result =
1159 DRXBSP_HST_Memcmp(currPtr,
1160 mcDataBuffer,
1161 bytesToCompare);
1162
1163 if (result != 0) {
1164 return DRX_STS_ERROR;
1165 }
1166
1167 currAddr +=
1168 ((DRXaddr_t)
1169 (bytesToCompare / 2));
1170 currPtr =
1171 &(currPtr[bytesToCompare]);
1172 bytesLeftToCompare -=
43a431e4 1173 ((u32) bytesToCompare);
443f18d0
MCC
1174 } /* while( bytesToCompare > DRX_UCODE_MAX_BUF_SIZE ) */
1175 };
1176 break;
38b2df95
DH
1177
1178 /*================================================================*/
443f18d0
MCC
1179 default:
1180 return DRX_STS_INVALID_ARG;
1181 break;
38b2df95 1182
443f18d0
MCC
1183 } /* switch ( action ) */
1184 }
38b2df95 1185
443f18d0
MCC
1186 /* if (blockHdr.size != 0 ) */
1187 /* Next block */
1188 mcData += mcBlockNrBytes;
38b2df95 1189
443f18d0 1190 } /* for( i = 0 ; i<mcNrOfBlks ; i++ ) */
38b2df95 1191
443f18d0 1192 return DRX_STS_OK;
38b2df95
DH
1193}
1194
1195/*============================================================================*/
1196
1197/**
1198* \brief Build list of version information.
1199* \param demod: A pointer to a demodulator instance.
1200* \param versionList: Pointer to linked list of versions.
1201* \return DRXStatus_t.
1202* \retval DRX_STS_OK: Version information stored in versionList
1203* \retval DRX_STS_INVALID_ARG: Invalid arguments.
1204*/
1205static DRXStatus_t
443f18d0 1206CtrlVersion(pDRXDemodInstance_t demod, pDRXVersionList_t * versionList)
38b2df95 1207{
443f18d0
MCC
1208 static char drxDriverCoreModuleName[] = "Core driver";
1209 static char drxDriverCoreVersionText[] =
1210 DRX_VERSIONSTRING(VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH);
1211
1212 static DRXVersion_t drxDriverCoreVersion;
1213 static DRXVersionList_t drxDriverCoreVersionList;
1214
1215 pDRXVersionList_t demodVersionList = (pDRXVersionList_t) (NULL);
1216 DRXStatus_t returnStatus = DRX_STS_ERROR;
1217
1218 /* Check arguments */
1219 if (versionList == NULL) {
1220 return DRX_STS_INVALID_ARG;
1221 }
1222
1223 /* Get version info list from demod */
1224 returnStatus = (*(demod->myDemodFunct->ctrlFunc)) (demod,
1225 DRX_CTRL_VERSION,
1226 (void *)
1227 &demodVersionList);
1228
1229 /* Always fill in the information of the driver SW . */
1230 drxDriverCoreVersion.moduleType = DRX_MODULE_DRIVERCORE;
1231 drxDriverCoreVersion.moduleName = drxDriverCoreModuleName;
1232 drxDriverCoreVersion.vMajor = VERSION_MAJOR;
1233 drxDriverCoreVersion.vMinor = VERSION_MINOR;
1234 drxDriverCoreVersion.vPatch = VERSION_PATCH;
1235 drxDriverCoreVersion.vString = drxDriverCoreVersionText;
1236
1237 drxDriverCoreVersionList.version = &drxDriverCoreVersion;
1238 drxDriverCoreVersionList.next = (pDRXVersionList_t) (NULL);
1239
1240 if ((returnStatus == DRX_STS_OK) && (demodVersionList != NULL)) {
1241 /* Append versioninfo from driver to versioninfo from demod */
1242 /* Return version info in "bottom-up" order. This way, multiple
1243 devices can be handled without using malloc. */
1244 pDRXVersionList_t currentListElement = demodVersionList;
1245 while (currentListElement->next != NULL) {
1246 currentListElement = currentListElement->next;
1247 }
1248 currentListElement->next = &drxDriverCoreVersionList;
1249
1250 *versionList = demodVersionList;
1251 } else {
1252 /* Just return versioninfo from driver */
1253 *versionList = &drxDriverCoreVersionList;
1254 }
1255
1256 return DRX_STS_OK;
38b2df95
DH
1257}
1258
1259/*============================================================================*/
1260/*============================================================================*/
1261/*== Exported functions ======================================================*/
1262/*============================================================================*/
1263/*============================================================================*/
1264
38b2df95
DH
1265/**
1266* \brief This function is obsolete.
1267* \param demods: Don't care, parameter is ignored.
1268* \return DRXStatus_t Return status.
1269* \retval DRX_STS_OK: Initialization completed.
1270*
1271* This function is obsolete, prototype available for backward compatability.
1272*
1273*/
1274
443f18d0 1275DRXStatus_t DRX_Init(pDRXDemodInstance_t demods[])
38b2df95 1276{
443f18d0 1277 return DRX_STS_OK;
38b2df95
DH
1278}
1279
1280/*============================================================================*/
1281
1282/**
1283* \brief This function is obsolete.
1284* \return DRXStatus_t Return status.
1285* \retval DRX_STS_OK: Terminated driver successful.
1286*
1287* This function is obsolete, prototype available for backward compatability.
1288*
1289*/
1290
443f18d0 1291DRXStatus_t DRX_Term(void)
38b2df95 1292{
443f18d0 1293 return DRX_STS_OK;
38b2df95
DH
1294}
1295
1296/*============================================================================*/
1297
1298/**
1299* \brief Open a demodulator instance.
1300* \param demod: A pointer to a demodulator instance.
1301* \return DRXStatus_t Return status.
1302* \retval DRX_STS_OK: Opened demod instance with succes.
1303* \retval DRX_STS_ERROR: Driver not initialized or unable to initialize
1304* demod.
1305* \retval DRX_STS_INVALID_ARG: Demod instance has invalid content.
1306*
1307*/
1308
443f18d0 1309DRXStatus_t DRX_Open(pDRXDemodInstance_t demod)
38b2df95 1310{
443f18d0
MCC
1311 DRXStatus_t status = DRX_STS_OK;
1312
1313 if ((demod == NULL) ||
1314 (demod->myDemodFunct == NULL) ||
1315 (demod->myCommonAttr == NULL) ||
1316 (demod->myExtAttr == NULL) ||
1317 (demod->myI2CDevAddr == NULL) ||
1318 (demod->myCommonAttr->isOpened == TRUE)) {
1319 return (DRX_STS_INVALID_ARG);
1320 }
1321
1322 status = (*(demod->myDemodFunct->openFunc)) (demod);
1323
1324 if (status == DRX_STS_OK) {
1325 demod->myCommonAttr->isOpened = TRUE;
1326 }
1327
1328 return status;
38b2df95
DH
1329}
1330
1331/*============================================================================*/
1332
1333/**
1334* \brief Close device.
1335* \param demod: A pointer to a demodulator instance.
1336* \return DRXStatus_t Return status.
1337* \retval DRX_STS_OK: Closed demod instance with succes.
1338* \retval DRX_STS_ERROR: Driver not initialized or error during close
1339* demod.
1340* \retval DRX_STS_INVALID_ARG: Demod instance has invalid content.
1341*
1342* Free resources occupied by device instance.
1343* Put device into sleep mode.
1344*/
1345
443f18d0 1346DRXStatus_t DRX_Close(pDRXDemodInstance_t demod)
38b2df95 1347{
443f18d0 1348 DRXStatus_t status = DRX_STS_OK;
38b2df95 1349
443f18d0
MCC
1350 if ((demod == NULL) ||
1351 (demod->myDemodFunct == NULL) ||
1352 (demod->myCommonAttr == NULL) ||
1353 (demod->myExtAttr == NULL) ||
1354 (demod->myI2CDevAddr == NULL) ||
1355 (demod->myCommonAttr->isOpened == FALSE)) {
1356 return DRX_STS_INVALID_ARG;
1357 }
38b2df95 1358
443f18d0 1359 status = (*(demod->myDemodFunct->closeFunc)) (demod);
38b2df95 1360
443f18d0 1361 DRX_SET_ISOPENED(demod, FALSE);
38b2df95 1362
443f18d0 1363 return status;
38b2df95
DH
1364}
1365
1366/*============================================================================*/
1367
1368/**
1369* \brief Control the device.
1370* \param demod: A pointer to a demodulator instance.
1371* \param ctrl: Reference to desired control function.
1372* \param ctrlData: Pointer to data structure for control function.
1373* \return DRXStatus_t Return status.
1374* \retval DRX_STS_OK: Control function completed successfully.
1375* \retval DRX_STS_ERROR: Driver not initialized or error during
1376* control demod.
1377* \retval DRX_STS_INVALID_ARG: Demod instance or ctrlData has invalid
1378* content.
1379* \retval DRX_STS_FUNC_NOT_AVAILABLE: Specified control function is not
1380* available.
1381*
1382* Data needed or returned by the control function is stored in ctrlData.
1383*
1384*/
1385
1386DRXStatus_t
1387DRX_Ctrl(pDRXDemodInstance_t demod, DRXCtrlIndex_t ctrl, void *ctrlData)
1388{
443f18d0
MCC
1389 DRXStatus_t status = DRX_STS_ERROR;
1390
1391 if ((demod == NULL) ||
1392 (demod->myDemodFunct == NULL) ||
1393 (demod->myCommonAttr == NULL) ||
1394 (demod->myExtAttr == NULL) || (demod->myI2CDevAddr == NULL)
1395 ) {
1396 return (DRX_STS_INVALID_ARG);
1397 }
1398
1399 if (((demod->myCommonAttr->isOpened == FALSE) &&
1400 (ctrl != DRX_CTRL_PROBE_DEVICE) && (ctrl != DRX_CTRL_VERSION))
1401 ) {
1402 return (DRX_STS_INVALID_ARG);
1403 }
1404
1405 if ((DRX_ISPOWERDOWNMODE(demod->myCommonAttr->currentPowerMode) &&
1406 (ctrl != DRX_CTRL_POWER_MODE) &&
1407 (ctrl != DRX_CTRL_PROBE_DEVICE) &&
1408 (ctrl != DRX_CTRL_NOP) && (ctrl != DRX_CTRL_VERSION)
1409 )
1410 ) {
1411 return DRX_STS_FUNC_NOT_AVAILABLE;
1412 }
1413
1414 /* Fixed control functions */
1415 switch (ctrl) {
38b2df95 1416 /*======================================================================*/
443f18d0
MCC
1417 case DRX_CTRL_NOP:
1418 /* No operation */
1419 return DRX_STS_OK;
1420 break;
38b2df95
DH
1421
1422 /*======================================================================*/
443f18d0
MCC
1423 case DRX_CTRL_VERSION:
1424 return CtrlVersion(demod, (pDRXVersionList_t *) ctrlData);
1425 break;
38b2df95
DH
1426
1427 /*======================================================================*/
443f18d0
MCC
1428 default:
1429 /* Do nothing */
1430 break;
1431 }
1432
1433 /* Virtual functions */
1434 /* First try calling function from derived class */
1435 status = (*(demod->myDemodFunct->ctrlFunc)) (demod, ctrl, ctrlData);
1436 if (status == DRX_STS_FUNC_NOT_AVAILABLE) {
1437 /* Now try calling a the base class function */
1438 switch (ctrl) {
38b2df95 1439 /*===================================================================*/
443f18d0
MCC
1440 case DRX_CTRL_LOAD_UCODE:
1441 return CtrlUCode(demod,
1442 (pDRXUCodeInfo_t) ctrlData,
1443 UCODE_UPLOAD);
1444 break;
38b2df95
DH
1445
1446 /*===================================================================*/
443f18d0
MCC
1447 case DRX_CTRL_VERIFY_UCODE:
1448 {
1449 return CtrlUCode(demod,
1450 (pDRXUCodeInfo_t) ctrlData,
1451 UCODE_VERIFY);
1452 }
1453 break;
38b2df95
DH
1454
1455#ifndef DRX_EXCLUDE_SCAN
1456 /*===================================================================*/
443f18d0
MCC
1457 case DRX_CTRL_SCAN_INIT:
1458 {
1459 return CtrlScanInit(demod,
1460 (pDRXScanParam_t) ctrlData);
1461 }
1462 break;
38b2df95
DH
1463
1464 /*===================================================================*/
443f18d0
MCC
1465 case DRX_CTRL_SCAN_NEXT:
1466 {
43a431e4 1467 return CtrlScanNext(demod, (u16 *) ctrlData);
443f18d0
MCC
1468 }
1469 break;
38b2df95
DH
1470
1471 /*===================================================================*/
443f18d0
MCC
1472 case DRX_CTRL_SCAN_STOP:
1473 {
1474 return CtrlScanStop(demod);
1475 }
1476 break;
38b2df95
DH
1477#endif /* #ifndef DRX_EXCLUDE_SCAN */
1478
1479 /*===================================================================*/
443f18d0
MCC
1480 case DRX_CTRL_PROGRAM_TUNER:
1481 {
1482 return CtrlProgramTuner(demod,
1483 (pDRXChannel_t)
1484 ctrlData);
1485 }
1486 break;
38b2df95
DH
1487
1488 /*===================================================================*/
443f18d0
MCC
1489 case DRX_CTRL_DUMP_REGISTERS:
1490 {
1491 return CtrlDumpRegisters(demod,
1492 (pDRXRegDump_t)
1493 ctrlData);
1494 }
1495 break;
38b2df95
DH
1496
1497 /*===================================================================*/
443f18d0
MCC
1498 default:
1499 return DRX_STS_FUNC_NOT_AVAILABLE;
1500 }
1501 } else {
1502 return (status);
1503 }
1504
1505 return DRX_STS_OK;
38b2df95
DH
1506}
1507
38b2df95
DH
1508/*============================================================================*/
1509
1510/* END OF FILE */
This page took 0.089491 seconds and 5 git commands to generate.