📄 xp_osi_clk.c
字号:
/*----------------------------------------------------------------------------+| This source code has been made available to you by IBM on an AS-IS| basis. Anyone receiving this source is licensed under IBM| copyrights to use it in any way he or she deems fit, including| copying it, modifying it, compiling it, and redistributing it either| with or without modifications. No license under IBM patents or| patent applications is to be implied by the copyright license.|| Any user of this software should understand that IBM cannot provide| technical support for this software and will not be responsible for| any consequences resulting from the use of this software.|| Any person who transfers this source code or any derivative work| must include the IBM copyright notice, this paragraph, and the| preceding two paragraphs in the transferred software.|| COPYRIGHT I B M CORPORATION 1999| LICENSED MATERIAL - PROGRAM PROPERTY OF I B M+----------------------------------------------------------------------------*//*----------------------------------------------------------------------------+|| DESCRIPTION : The set of functions allow the application to process| the clock recovery interrupts.|+----------------------------------------------------------------------------*//*----------------------------------------------------------------------------+| Author : Andy Anderson, Ian Govett| Component : xp| File : xp_clk.c| Purpose : Clock Recovery.| Changes :|| Date: By Comment:| --------- --- --------| 15-Jan-98 IG Created| 30-Sep-01 LGH Ported to Linux| 01-aug-02 LGH FIx the bug in PCR interrupt+----------------------------------------------------------------------------*//*----------------------------------------------------------------------------+| Clock Recovery+-----------------------------------------------------------------------------+|| The clock recovery is implemented by making use of both the hardware| (auto-PWM), and software. The software algorithm provides fast and| accurate control necessary to quickly match the clock rates. The| hardware algorithm (auto-PWM) makes much smaller adjustments to| "maintain" the proper clock rate. The software algorithm is activated| when the PCR PID is updated or when the STC & PCR differ by a| programmable value.| Once this difference is below a pre-determined threshold, the software| algorithm shuts off. At this time, the hardware algorithm (auto-PWM)| continues to adjust the clock rate based on the current STC and| arriving PCRs. When the threshold is exceeded, the software algorithm| is activated via a PCR type interrupt. Using this technique, the| number of clock recovery interrupts is greatly reduced.|| The clock recovery algorithm make use of two types of hardware| interrupts: STC_LOAD, and PCR. An interrupt handler is registered| when the clock recovery algorithm is started. The hardware makes use| of the PWM register to control the clock rate, and a threshold register| to control when interrupts should be generated for the software| algorithm.|| The following functions provide access to clock recovery algorithms| available for the transport demux driver. The clock recovery| algorithms are enabled and disabled using the xp0_clk_start() and| xp0_clk_stop() functions. The xp0_clk_set_pid() function designates the| PID value of the transport packets containing the PCR's. The| xp0_clk_get_stc_high() function provides the caller with the current| value of the STC register which may be used by the decoder device| driver for the decoders.|+----------------------------------------------------------------------------*//* The necessary header files */#include <linux/config.h>#include <linux/version.h>#ifdef MODVERSIONS#include <linux/modversions.h>#endif#define __NO_VERSION__#include <linux/module.h>#include <linux/kernel.h>#include <linux/types.h>#include "xp_osi_global.h"#include "xp_atom_reg.h"XP_STC_NOTIFY_FN stc_notify_fn = NULL;/*----------------------------------------------------------------------------+| Local Defines+----------------------------------------------------------------------------*/#define PWM_CLAMP 50 /* Sets the maximum rate of change */ /* of the PWM value */#define STC_LOAD_PWM_CLAMP 100 /* Sets the maximum rate of change */ /* just after the PWM value is read */#define PCRS_HIGH_GAIN 10 /* Number of PCRs after the STC is */ /* loaded which will use */ /* STC_LOAD_PWM_CLAMP */#define RATE_GAIN 4 /* The calculated rate difference */ /* is divided by RATE_GAIN ^ 2 */#define DELTA_GAIN 4 /* The calculated delta */ /* is divided by DELTA_GAIN ^ 2 */#define LOW_THRESHOLD 32 /* Lower Delta Threshold for the */ /* s/w clock recovery algorithm */#define HIGH_THRESHOLD 256 /* Upper Delta Threshold for the */ /* s/w clock recovery algorithm */#define DECODE_DELAY ((unsigned long) 10)/* decode delay *///Internalstatic void pcr_interrupt(GLOBAL_RESOURCES *pGlobal,ULONG ulInterrupt);/*----------------------------------------------------------------------------+| XXXX XX XX XXXXXX XXXXXXX XXXXXX XX XX XX XXXX| XX XXX XX X XX X XX X XX XX XXX XX XXXX XX| XX XXXX XX XX XX X XX XX XXXX XX XX XX XX| XX XX XXXX XX XXXX XXXXX XX XXXX XX XX XX| XX XX XXX XX XX X XX XX XX XXX XXXXXX XX| XX XX XX XX XX X XX XX XX XX XX XX XX XX| XXXX XX XX XXXX XXXXXXX XXX XX XX XX XX XX XXXXXXX+----------------------------------------------------------------------------*//*----------------------------------------------------------------------------+| pcr_interrupt+-----------------------------------------------------------------------------+|| FUNCTION : pcr_interrupt|| DESCRIPTION : This function is called by an interrupt service| routine whenever an PCR or STC is processed by hardware|| COMMENTS : This function is processed in the interrupt context| and must be careful to only use functions which are| safe within the context of an interrupt. Do NOT use| any I/O instructions such as printf() or gets(), etc.|| Portions of this function could be shared with the| other interrupt routine. The question is how to best| optimize the interrupt routines and the overhead| of function calls.|| The other option which is better is to integrate both| functions and setup so that the single function is| called in either case|+----------------------------------------------------------------------------*/static void pcr_interrupt(GLOBAL_RESOURCES *pGlobal,ULONG ulInterrupt){ unsigned overflow; /* Delta Overflow bit */ unsigned long delta; /* Delta or Delta Magnitude */ unsigned long tdelta; short rate_adjust; /* Adjustment to PWM based on frequency*/ short pwm_adjust; /* The amount to adjust the pwm */ unsigned long pwm; /* Current PWM value */ unsigned long new_pwm; /* Updated PWM value */ short soft_overflow; /* software algorithm overflow */ long delta_pcr; /* Difference between the current */ long delta_stc; /* and previous values */ long temp1; long temp2; long value_adjust; /* Adjustment to PWM based on delta */ unsigned long stc_high; unsigned long stc_low; unsigned long pcr_high; unsigned long pcr_low; unsigned long stc; unsigned long pcr; XP_PCRSTCD_REGP p_delta; UINT32 flag; /*------------------------------------------------------------------------+ | Read the STC, PCR, and delta values +------------------------------------------------------------------------*/ flag = os_enter_critical_section(); pcr_high = xp_atom_dcr_read(pGlobal->uDeviceIndex,XP_DCR_ADDR_PCRHI); pcr_low = xp_atom_dcr_read(pGlobal->uDeviceIndex,XP_DCR_ADDR_PCRLOW); stc_high = xp_atom_dcr_read(pGlobal->uDeviceIndex,XP_DCR_ADDR_LSTCHI); stc_low = xp_atom_dcr_read(pGlobal->uDeviceIndex,XP_DCR_ADDR_LSTCLOW); tdelta = xp_atom_dcr_read(pGlobal->uDeviceIndex,XP_DCR_ADDR_PCRSTCD); os_leave_critical_section(flag); p_delta = (XP_PCRSTCD_REGP)(void *) &tdelta; delta = p_delta->delta; overflow = p_delta->ovfl; if(overflow) { delta = ~0; } /*------------------------------------------------------------------------+ | Make sure the clock recovery registers are consistent | Later the value of Incons_data can be returned as | part of the status of the driver. | This is a candidate to be removed later. +------------------------------------------------------------------------*/ flag = os_enter_critical_section(); if(pcr_low != xp_atom_dcr_read(pGlobal->uDeviceIndex,XP_DCR_ADDR_PCRLOW)) { pGlobal->ClkInfo.XpClkInconsData++; return; } os_leave_critical_section(flag); /*------------------------------------------------------------------------+ | Track number of PCRS Since STC loaded +------------------------------------------------------------------------*/ if(ulInterrupt & XP_INTERRUPT_IR_STCL) { pGlobal->ClkInfo.XpClkNpcrs = 0; /* Initialize to 0 */ if(stc_notify_fn != NULL) (*stc_notify_fn)(pGlobal,STC_DISCONTINUITY);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -