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