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