#include <Debug.h>
#include "Theater100.h"
#include "Theater.h"
#include "TheatreReg.h"
#include "lendian_bitfield.h"
CTheater100::CTheater100(CRadeon & radeon, int device)
:CTheater(radeon, device)
{
PRINT(("CTheater100::CTheater100()\n"));
if( fPort.InitCheck() == B_OK ) {
radeon_video_tuner tuner;
radeon_video_decoder video;
radeon.GetMMParameters(tuner, video, fClock,
fTunerPort, fCompositePort, fSVideoPort);
if (fClock != C_RADEON_VIDEO_CLOCK_29_49892_MHZ &&
fClock != C_RADEON_VIDEO_CLOCK_27_00000_MHZ)
PRINT(("CTheater100::CTheater100() - Unsupported crystal clock!\n"));
}
if( InitCheck() != B_OK )
PRINT(("CTheater100::CTheater100() - Rage Theater not found!\n"));
}
CTheater100::~CTheater100()
{
PRINT(("CTheater100::~CTheater100()\n"));
if( InitCheck() == B_OK )
SetEnable(false, false);
}
status_t CTheater100::InitCheck() const
{
status_t res;
res = fPort.InitCheck();
if( res != B_OK )
return res;
return (fDevice >= C_VIP_PORT_DEVICE_0 && fDevice <= C_VIP_PORT_DEVICE_3) ? B_OK : B_ERROR;
}
void CTheater100::Reset()
{
PRINT(("CTheater100::Reset()\n"));
SetHue(0);
SetBrightness(0);
SetSaturation(0);
SetContrast(0);
SetSharpness(false);
}
void CTheater100::SetEnable(bool enable, bool vbi)
{
PRINT(("CTheater100::SetEnable(%d, %d)\n", enable, vbi));
#if 0
SetRegister(VIP_ADC_CNTL, ADC_CPRESET, ADC_CPRESET);
snooze(1000);
SetRegister(VIP_ADC_CNTL, ADC_CPRESET, 0);
snooze(1000);
SetRegister(VIP_ADC_CNTL, ADC_PDWN, ADC_PDWN_DOWN);
#endif
WaitVSYNC();
SetRegister(VIP_MASTER_CNTL, VIN_ASYNC_RST, VIN_ASYNC_RST);
SetRegister(VIP_MASTER_CNTL, DVS_ASYNC_RST, DVS_ASYNC_RST);
SetRegister(VIP_CLOCK_SEL_CNTL, VIN_CLK_SEL, VIN_CLK_SEL_REF_CLK);
SetRegister(VIP_PLL_CNTL1, VINRST, VINRST);
SetRegister(VIP_PLL_CNTL1, L54RST, L54RST);
SetRegister(VIP_ADC_CNTL, ADC_PDWN, ADC_PDWN);
SetRegister(VIP_DVS_PORT_CTRL, DVS_DIRECTION, DVS_DIRECTION_INPUT);
SetRegister(VIP_DVS_PORT_CTRL, DVS_CLK_SELECT, DVS_CLK_SELECT_8X);
SetRegister(VIP_DVS_PORT_CTRL, CONTINUOUS_STREAM, 0);
if (enable) {
WaitVSYNC();
SetClock(fStandard, fClock);
SetADC(fStandard, fSource);
SetLuminanceProcessor(fStandard);
SetChromaProcessor(fStandard);
SetVSYNC(fStandard);
SetClipWindow(fStandard, vbi);
SetCombFilter(fStandard, fSource);
SetHSYNC(fStandard);
SetSyncGenerator(fStandard);
SetScaler(fStandard, fHActive, fVActive, fDeinterlace);
SetRegister(VIP_ADC_CNTL, ADC_PDWN, ADC_PDWN_UP);
WaitVSYNC();
SetRegister(VIP_MASTER_CNTL, VIN_ASYNC_RST, 0);
SetRegister(VIP_MASTER_CNTL, DVS_ASYNC_RST, 0);
SetRegister(VIP_DVS_PORT_CTRL, DVS_DIRECTION, DVS_DIRECTION_OUTPUT);
SetLuminanceLevels(fStandard, fBrightness, fContrast);
SetChromaLevels(fStandard, fSaturation, fHue);
}
}
void CTheater100::SetStandard(theater_standard standard, theater_source source)
{
PRINT(("CTheater100::SetStandard(%s, %s)\n",
"NTSC\0\0\0\0\0\0NTSC-J\0\0\0\0NTSC-443\0\0PAL-M\0\0\0\0\0"
"PAL-N\0\0\0\0\0PAL-NC\0\0\0\0PAL-BDGHI\0PAL-60\0\0\0\0"
"SECAM\0\0\0\0\0"+10*standard,
"TUNER\0COMP\0\0SVIDEO"+6*source));
fStandard = standard;
fSource = source;
}
void CTheater100::SetSize(int hactive, int vactive)
{
PRINT(("CTheater100::SetSize(%d, %d)\n", hactive, vactive));
fHActive = hactive;
fVActive = vactive;
}
void CTheater100::SetDeinterlace(bool deinterlace)
{
PRINT(("CTheater100::SetDeinterlace(%d)\n", deinterlace));
fDeinterlace = deinterlace;
}
void CTheater100::SetSharpness(int sharpness)
{
PRINT(("CTheater100::SetSharpness(%d)\n", sharpness));
SetRegister(VIP_H_SCALER_CONTROL, H_SHARPNESS, sharpness << 25);
}
void CTheater100::SetBrightness(int brightness)
{
PRINT(("CTheater100::SetBrightness(%d)\n", brightness));
fBrightness = brightness;
SetLuminanceLevels(fStandard, fBrightness, fContrast);
}
void CTheater100::SetContrast(int contrast)
{
PRINT(("CTheater100::SetContrast(%d)\n", contrast));
fContrast = contrast;
SetLuminanceLevels(fStandard, fBrightness, fContrast);
}
void CTheater100::SetSaturation(int saturation)
{
PRINT(("CTheater100::SetSaturation(%d)\n", saturation));
fSaturation = saturation;
SetChromaLevels(fStandard, fSaturation, fHue);
}
void CTheater100::SetHue(int hue)
{
PRINT(("CTheater100::SetHue(%d)\n", hue));
fHue = hue;
SetChromaLevels(fStandard, fSaturation, fHue);
}
void CTheater100::SetClock(theater_standard standard, radeon_video_clock clock)
{
int referenceDivider, feedbackDivider, postDivider;
switch (standard) {
case C_THEATER_NTSC:
case C_THEATER_NTSC_JAPAN:
if (clock == C_RADEON_VIDEO_CLOCK_29_49892_MHZ) {
referenceDivider = 0x39;
feedbackDivider = 0x14c;
postDivider = 0x6;
}
else {
referenceDivider = 0x0b;
feedbackDivider = 0x46;
postDivider = 0x6;
}
break;
case C_THEATER_NTSC_443:
if (clock == C_RADEON_VIDEO_CLOCK_29_49892_MHZ) {
referenceDivider = 0x23;
feedbackDivider = 0x88;
postDivider = 0x7;
}
else {
referenceDivider = 0x2c;
feedbackDivider = 0x121;
postDivider = 0x5;
}
break;
case C_THEATER_PAL_M:
if (clock == C_RADEON_VIDEO_CLOCK_29_49892_MHZ) {
referenceDivider = 0x2c;
feedbackDivider = 0x12b;
postDivider = 0x7;
}
else {
referenceDivider = 0x0b;
feedbackDivider = 0x46;
postDivider = 0x6;
}
break;
case C_THEATER_PAL_BDGHI:
case C_THEATER_PAL_N:
case C_THEATER_PAL_60:
case C_THEATER_SECAM:
if (clock == C_RADEON_VIDEO_CLOCK_29_49892_MHZ) {
referenceDivider = 0x0e;
feedbackDivider = 0x65;
postDivider = 0x6;
}
else {
referenceDivider = 0x2c;
feedbackDivider = 0x121;
postDivider = 0x5;
}
break;
case C_THEATER_PAL_NC:
if (clock == C_RADEON_VIDEO_CLOCK_29_49892_MHZ) {
referenceDivider = 0x23;
feedbackDivider = 0x88;
postDivider = 0x7;
}
else {
referenceDivider = 0x37;
feedbackDivider = 0x1d3;
postDivider = 0x8;
}
break;
default:
PRINT(("CTheater100::SetClock() - Bad standard\n"));
return;
}
SetRegister(VIP_CLOCK_SEL_CNTL, VIN_CLK_SEL, VIN_CLK_SEL_REF_CLK);
SetRegister(VIP_PLL_CNTL1, VINRST, VINRST);
SetRegister(VIP_PLL_CNTL1, L54RST, L54RST);
SetRegister(VIP_VIN_PLL_CNTL, VIN_M0, referenceDivider << 0);
SetRegister(VIP_VIN_PLL_CNTL, VIN_N0, feedbackDivider << 11);
SetRegister(VIP_VIN_PLL_CNTL, VIN_P, postDivider << 24);
SetRegister(VIP_PLL_CNTL1, VINRST, 0);
SetRegister(VIP_PLL_CNTL1, L54RST, 0);
SetRegister(VIP_CLOCK_SEL_CNTL, VIN_CLK_SEL, VIN_CLK_SEL_VIPLL_CLK);
PRINT(("CTheater100::SetClock(Fsamp=%g, Fref=%g)\n",
((fClock == C_RADEON_VIDEO_CLOCK_29_49892_MHZ ? 29.49892 : 27.0) * feedbackDivider) / (referenceDivider * postDivider),
(fClock == C_RADEON_VIDEO_CLOCK_29_49892_MHZ ? 29.49892 : 27.0)));
}
void CTheater100::SetADC(theater_standard standard, theater_source source)
{
PRINT(("CTheater100::SetADC(%c, %c)\n", "NJ4MNCB6S"[standard], "TCS"[source]));
SetRegister(VIP_HW_DEBUG, 0x0000f000);
switch (standard) {
case C_THEATER_NTSC:
case C_THEATER_NTSC_JAPAN:
case C_THEATER_NTSC_443:
case C_THEATER_PAL_M:
SetRegister(VIP_STANDARD_SELECT, STANDARD_SEL, STANDARD_NTSC);
break;
case C_THEATER_PAL_BDGHI:
case C_THEATER_PAL_N:
case C_THEATER_PAL_60:
case C_THEATER_PAL_NC:
SetRegister(VIP_STANDARD_SELECT, STANDARD_SEL, STANDARD_PAL);
break;
case C_THEATER_SECAM:
SetRegister(VIP_STANDARD_SELECT, STANDARD_SEL, STANDARD_SECAM);
break;
default:
PRINT(("CTheater100::SetADC() - Bad standard\n"));
return;
}
switch (source) {
case C_THEATER_TUNER:
SetRegister(VIP_ADC_CNTL, INPUT_SELECT, fTunerPort);
SetRegister(VIP_STANDARD_SELECT, YC_MODE, YC_MODE_COMPOSITE);
break;
case C_THEATER_COMPOSITE:
SetRegister(VIP_ADC_CNTL, INPUT_SELECT, fCompositePort);
SetRegister(VIP_STANDARD_SELECT, YC_MODE, YC_MODE_COMPOSITE);
break;
case C_THEATER_SVIDEO:
SetRegister(VIP_ADC_CNTL, INPUT_SELECT, fSVideoPort);
SetRegister(VIP_STANDARD_SELECT, YC_MODE, YC_MODE_SVIDEO);
break;
default:
PRINT(("CTheater100::SetADC() - Bad source\n"));
return;
}
SetRegister(VIP_ADC_CNTL, I_CLAMP_SEL, I_CLAMP_SEL_22);
SetRegister(VIP_ADC_CNTL, I_AGC_SEL, I_AGC_SEL_7);
SetRegister(VIP_ADC_CNTL, EXT_CLAMP_CAP, EXT_CLAMP_CAP_EXTERNAL);
SetRegister(VIP_ADC_CNTL, EXT_AGC_CAP, EXT_AGC_CAP_EXTERNAL);
SetRegister(VIP_ADC_CNTL, ADC_DECI_BYPASS, ADC_DECI_WITH_FILTER);
SetRegister(VIP_ADC_CNTL, VBI_DECI_BYPASS, VBI_DECI_WITH_FILTER);
SetRegister(VIP_ADC_CNTL, DECI_DITHER_EN, 0 << 12);
SetRegister(VIP_ADC_CNTL, ADC_CLK_SEL, ADC_CLK_SEL_8X);
SetRegister(VIP_ADC_CNTL, ADC_BYPASS, ADC_BYPASS_INTERNAL);
switch (standard) {
case C_THEATER_NTSC:
case C_THEATER_NTSC_JAPAN:
case C_THEATER_NTSC_443:
case C_THEATER_PAL_M:
SetRegister(VIP_ADC_CNTL, ADC_CH_GAIN_SEL, ADC_CH_GAIN_SEL_NTSC);
break;
case C_THEATER_PAL_BDGHI:
case C_THEATER_PAL_N:
case C_THEATER_PAL_60:
case C_THEATER_PAL_NC:
case C_THEATER_SECAM:
SetRegister(VIP_ADC_CNTL, ADC_CH_GAIN_SEL, ADC_CH_GAIN_SEL_PAL);
break;
}
SetRegister(VIP_ADC_CNTL, ADC_PAICM, 1 << 18);
SetRegister(VIP_ADC_CNTL, ADC_PDCBIAS, 2 << 20);
SetRegister(VIP_ADC_CNTL, ADC_PREFHI, ADC_PREFHI_2_7);
SetRegister(VIP_ADC_CNTL, ADC_PREFLO, ADC_PREFLO_1_5);
SetRegister(VIP_ADC_CNTL, ADC_IMUXOFF, 0 << 26);
SetRegister(VIP_ADC_CNTL, ADC_CPRESET, 0 << 27);
}
void CTheater100::SetHSYNC(theater_standard standard)
{
static const uint16 hs_line_total[] = {
0x38E, 0x38E, 0x46F, 0x38D, 0x46F, 0x395, 0x46F, 0x467, 0x46F };
static const uint32 hs_dto_inc[] = {
0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x3E7A2 };
static const uint8 hs_pll_sgain[] = {
2, 2, 2, 2, 2, 2, 2, 2, 2 };
static const uint8 hs_pll_fgain[] = {
8, 8, 8, 8, 8, 8, 8, 8, 8 };
static const uint8 gen_lock_delay[] = {
0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10 };
static const uint8 min_pulse_width[] = {
0x21, 0x21, 0x29, 0x21, 0x29, 0x21, 0x29, 0x29, 0x29 };
static const uint8 max_pulse_width[] = {
0x64, 0x64, 0x7D, 0x64, 0x7D, 0x65, 0x7D, 0x7D, 0x7D };
static const uint16 win_close_limit[] = {
0x0A0, 0x0A0, 0x0C7, 0x0A0, 0x0C7, 0x0A0, 0x0C7, 0x0C7, 0x0C7 };
static const uint16 win_open_limit[] = {
0x1B7, 0x1B7, 0x228, 0x1B7, 0x228, 0x1BB, 0x228, 0x224, 0x228 };
SetRegister(VIP_HS_PLINE, HS_LINE_TOTAL, hs_line_total[standard]);
SetRegister(VIP_HS_DTOINC, HS_DTO_INC, hs_dto_inc[standard]);
SetRegister(VIP_HS_PLLGAIN, HS_PLL_SGAIN, hs_pll_sgain[standard] << 0);
SetRegister(VIP_HS_PLLGAIN, HS_PLL_FGAIN, (uint32)hs_pll_fgain[standard] << 4);
SetRegister(VIP_HS_GENLOCKDELAY, GEN_LOCK_DELAY, gen_lock_delay[standard]);
SetRegister(VIP_HS_MINMAXWIDTH, MIN_PULSE_WIDTH, min_pulse_width[standard] << 0);
SetRegister(VIP_HS_MINMAXWIDTH, MAX_PULSE_WIDTH, (uint32)max_pulse_width[standard] << 8);
SetRegister(VIP_HS_WINDOW_LIMIT, WIN_CLOSE_LIMIT, win_close_limit[standard] << 0);
SetRegister(VIP_HS_WINDOW_LIMIT, WIN_OPEN_LIMIT, (uint32)win_open_limit[standard] << 16);
PRINT(("CTheater100::SetHSYNC(total=%d, pulse=%d/%d, window=%d/%d)\n",
Register(VIP_HS_PLINE, HS_LINE_TOTAL),
Register(VIP_HS_MINMAXWIDTH, MIN_PULSE_WIDTH) >> 0,
Register(VIP_HS_MINMAXWIDTH, MAX_PULSE_WIDTH) >> 8,
Register(VIP_HS_WINDOW_LIMIT, WIN_CLOSE_LIMIT) >> 0,
Register(VIP_HS_WINDOW_LIMIT, WIN_OPEN_LIMIT) >> 16));
}
void CTheater100::WaitHSYNC()
{
for (int timeout = 0; timeout < 1000; timeout++) {
if (Register(VIP_HS_PULSE_WIDTH, HS_GENLOCKED) != 0)
return;
snooze(20);
}
PRINT(("CTheater100::WaitHSYNC() - wait for HSync locking time out!\n"));
}
void CTheater100::SetVSYNC(theater_standard standard)
{
static const uint16 vsync_int_trigger[] = {
0x2AA, 0x2AA, 0x353, 0x2AA, 0x353, 0x2B0, 0x353, 0x34D, 0x353 };
static const uint16 vsync_int_hold[] = {
0x017, 0x017, 0x01C, 0x017, 0x01C, 0x017, 0x01C, 0x01C, 0x01C };
static const uint16 vs_field_blank_start[] = {
0x206, 0x206, 0x206, 0x206, 0x26d, 0x26d, 0x26d, 0x206, 0x26d };
static const uint8 vs_field_blank_end[] = {
0x00a, 0x00a, 0x00a, 0x00a, 0x02a, 0x02a, 0x02a, 0x00a, 0x02a };
static const uint16 vs_field_id_location[] = {
0x105, 0x105, 0x105, 0x105, 0x1, 0x1, 0x1, 0x105, 0x1 };
static const uint16 vs_frame_total[] = {
0x217, 0x217, 0x217, 0x217, 0x27B, 0x27B, 0x27B, 0x217, 0x27B };
SetRegister(VIP_VS_DETECTOR_CNTL, VSYNC_INT_TRIGGER, vsync_int_trigger[standard] << 0);
SetRegister(VIP_VS_DETECTOR_CNTL, VSYNC_INT_HOLD, (uint32)vsync_int_hold[standard] << 16);
SetRegister(VIP_VS_BLANKING_CNTL, VS_FIELD_BLANK_START, vs_field_blank_start[standard] << 0);
SetRegister(VIP_VS_BLANKING_CNTL, VS_FIELD_BLANK_END, (uint32)vs_field_blank_end[standard] << 16);
SetRegister(VIP_VS_FRAME_TOTAL, VS_FRAME_TOTAL, vs_frame_total[standard]);
SetRegister(VIP_VS_FIELD_ID_CNTL, VS_FIELD_ID_LOCATION, vs_field_id_location[standard] << 0);
SetRegister(VIP_VS_COUNTER_CNTL, FIELD_DETECT_MODE, FIELD_DETECT_DETECTED);
SetRegister(VIP_VS_COUNTER_CNTL, FIELD_FLIP_EN, 0 );
PRINT(("CTheater100::SetVSYNC(total=%d)\n",
Register(VIP_VS_FRAME_TOTAL, VS_FRAME_TOTAL)));
}
void CTheater100::WaitVSYNC()
{
for (int timeout = 0; timeout < 1000; timeout++) {
int lineCount = Register(VIP_VS_LINE_COUNT, VS_LINE_COUNT);
if (lineCount > 1 && lineCount < 20)
return;
snooze(20);
}
PRINT(("CTheater100::WaitVSYNC() - wait for VBI timed out!\n"));
}
void CTheater100::SetSyncGenerator(theater_standard standard)
{
static const uint16 blank_int_start[] = {
0x031, 0x031, 0x046, 0x031, 0x046, 0x046, 0x046, 0x031, 0x046 };
static const uint8 blank_int_length[] = {
0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F };
static const uint16 sync_tip_start[] = {
0x0372, 0x0372, 0x0453, 0x0371, 0x0453, 0x0379, 0x0453, 0x044B, 0x0453 };
static const uint8 sync_tip_length[] = {
0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F };
static const uint8 uv_int_start[] = {
0x03B, 0x03B, 0x052, 0x03B, 0x052, 0x03B, 0x052, 0x03C, 0x068 };
static const uint8 u_int_length[] = {
0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F };
static const uint8 v_int_length[] = {
0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F };
SetRegister(VIP_SG_BLACK_GATE, BLANK_INT_START, blank_int_start[standard] );
SetRegister(VIP_SG_BLACK_GATE, BLANK_INT_LENGTH, (uint32)blank_int_length[standard] << 8);
SetRegister(VIP_SG_SYNCTIP_GATE, SYNC_TIP_START, sync_tip_start[standard]);
SetRegister(VIP_SG_SYNCTIP_GATE, SYNC_TIP_LENGTH, (uint32)sync_tip_length[standard] << 12);
SetRegister(VIP_SG_UVGATE_GATE, UV_INT_START, uv_int_start[standard] << 0);
SetRegister(VIP_SG_UVGATE_GATE, U_INT_LENGTH, (uint32)u_int_length[standard] << 8);
SetRegister(VIP_SG_UVGATE_GATE, V_INT_LENGTH, (uint32)v_int_length[standard] << 12);
PRINT(("CTheater100::SetSyncGenerator(black=%d/%d, synctip=%d/%d, uvgate=%d/%d-%d)\n",
Register(VIP_SG_BLACK_GATE, BLANK_INT_START) >> 0,
Register(VIP_SG_BLACK_GATE, BLANK_INT_LENGTH) >> 8,
Register(VIP_SG_SYNCTIP_GATE, SYNC_TIP_START),
Register(VIP_SG_SYNCTIP_GATE, SYNC_TIP_LENGTH) >> 12,
Register(VIP_SG_UVGATE_GATE, UV_INT_START),
Register(VIP_SG_UVGATE_GATE, U_INT_LENGTH) >> 8,
Register(VIP_SG_UVGATE_GATE, V_INT_LENGTH) >> 12));
}
void CTheater100::SetCombFilter(theater_standard standard, theater_source source)
{
enum {
_3Tap_2D_adaptive_Comb = 1,
_2Tap_C_combed_Y_Sub = 2,
_2Tap_C_combed_Y_combed = 3,
_3Tap_C_combed_Y_Sub = 4,
_3Tap_C_combed_Y_combed = 5,
YC_mode_Comb_filter_off = 6,
YC_mode_2Tap_YV_filter = 7,
YC_mode_3Tap_YV_filter = 8
};
typedef struct {
LBITFIELD32_12 (
comb_hck : 8,
comb_vck : 8,
comb_filter_en : 1,
comb_adaptiv_en : 1,
comb_bpfmuxsel : 3,
comb_coutsel : 2,
comb_sumdiff0sel : 1,
comb_sumdiff1sel : 2,
comb_yvlpfsel : 1,
comb_dlylinesel : 2,
comb_ydlyinsel : 2,
comb_ysubbw : 1
);
} comb_cntl0;
typedef struct {
LBITFIELD32_7 (
comb_ydlyoutsel : 2,
comb_coresize : 2,
comb_ysuben : 1,
comb_youtsel : 1,
comb_syncpfsel : 2,
comb_synclpfrst : 1,
comb_debug : 1
);
} comb_cntl1;
typedef struct {
LBITFIELD32_4 (
comb_hyk0 : 8,
comb_vyk0 : 8,
comb_hyk1 : 8,
comb_vyk1 : 8
);
} comb_cntl2;
typedef struct {
LBITFIELD32_2 (
comb_tap0length : 16,
comb_tap1length : 12
);
} comb_line_length;
typedef struct {
const uint8 *types;
const comb_cntl0 *cntl0;
const comb_cntl1 *cntl1;
const comb_cntl2 *cntl2;
const comb_line_length *line_length;
} comb_settings;
static const uint8 comb_types_ntsc_m[] = {
_3Tap_2D_adaptive_Comb,
_2Tap_C_combed_Y_Sub,
_2Tap_C_combed_Y_combed,
_3Tap_C_combed_Y_Sub,
_3Tap_C_combed_Y_combed,
YC_mode_Comb_filter_off,
YC_mode_2Tap_YV_filter,
YC_mode_3Tap_YV_filter,
0
};
static const comb_cntl0 comb_cntl0_ntsc_m[] = {
{ 0x90, 0x80, 1, 1, 0, 2, 0, 1, 0, 1, 0, 0 },
{ 0, 0, 1, 0, 3, 2, 0, 0, 0, 1, 0, 0 },
{ 0, 0, 1, 0, 3, 2, 0, 0, 0, 1, 1, 0 },
{ 0, 0, 1, 0, 1, 2, 0, 1, 0, 1, 0, 0 },
{ 0, 0, 1, 0, 1, 2, 0, 1, 1, 1, 0, 0 },
{ 0, 0, 0, 0, 5, 2, 0, 0, 0, 1, 2, 0 },
{ 0, 0, 0, 0, 5, 2, 0, 0, 0, 1, 1, 0 },
{ 0, 0, 0, 0, 5, 2, 0, 0, 1, 1, 0, 0 }
};
static const comb_cntl1 comb_cntl1_ntsc_m[] = {
{ 0, 0, 1, 0, 0, 0, 0 },
{ 2, 0, 1, 0, 0, 0, 0 },
{ 3, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 1, 0, 1, 0, 0 },
{ 3, 0, 0, 0, 1, 0, 0 },
{ 1, 0, 0, 0, 2, 0, 0 },
{ 3, 0, 0, 0, 0, 0, 0 },
{ 3, 0, 0, 0, 1, 0, 0 }
};
static const comb_cntl2 comb_cntl2_ntsc_m[] = {
{ 0x10, 0x10, 0x16, 0x16 },
{ 0xFF, 0xFF, 0xFF, 0xFF },
{ 0xFF, 0xFF, 0xFF, 0xFF },
{ 0xFF, 0xFF, 0xFF, 0xFF },
{ 0xFF, 0xFF, 0xFF, 0xFF },
{ 0xFF, 0xFF, 0xFF, 0xFF },
{ 0xFF, 0xFF, 0xFF, 0xFF },
{ 0xFF, 0xFF, 0xFF, 0xFF }
};
static const comb_line_length comb_line_length_ntsc_m[] = {
{ 0x38A, 0x718 },
{ 0x38A, 0x718 },
{ 0x38A, 0x718 },
{ 0x38A, 0x718 },
{ 0x38A, 0x718 },
{ 0, 0 },
{ 0x38A, 0 },
{ 0x38A, 0x718 }
};
static const uint8 comb_types_ntsc_433[] = {
_2Tap_C_combed_Y_Sub,
_2Tap_C_combed_Y_combed,
_3Tap_C_combed_Y_Sub,
_3Tap_C_combed_Y_combed,
YC_mode_Comb_filter_off,
YC_mode_2Tap_YV_filter,
YC_mode_3Tap_YV_filter,
0
};
static const comb_cntl0 comb_cntl0_ntsc_433[] = {
{ 0, 0, 1, 0, 3, 2, 0, 0, 0, 1, 0, 0 },
{ 0, 0, 1, 0, 3, 2, 0, 0, 0, 1, 1, 0 },
{ 0, 0, 1, 0, 1, 2, 0, 1, 0, 1, 0, 0 },
{ 0, 0, 1, 0, 1, 2, 0, 1, 1, 1, 0, 0 },
{ 0, 0, 0, 0, 5, 2, 0, 0, 0, 1, 2, 0 },
{ 0, 0, 0, 0, 5, 2, 0, 0, 0, 1, 1, 0 },
{ 0, 0, 0, 0, 5, 2, 0, 0, 1, 1, 0, 0 }
};
static const comb_cntl1 comb_cntl1_ntsc_433[] = {
{ 2, 0, 1, 0, 0, 0, 0 },
{ 3, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 1, 0, 1, 0, 0 },
{ 3, 0, 0, 0, 1, 0, 0 },
{ 1, 0, 0, 0, 2, 0, 0 },
{ 3, 0, 0, 0, 0, 0, 0 },
{ 3, 0, 0, 0, 1, 0, 0 }
};
static const comb_cntl2 comb_cntl2_ntsc_433[] = {
{ 0xFF, 0xFF, 0xFF, 0xFF },
{ 0xFF, 0xFF, 0xFF, 0xFF },
{ 0xFF, 0xFF, 0xFF, 0xFF },
{ 0xFF, 0xFF, 0xFF, 0xFF },
{ 0xFF, 0xFF, 0xFF, 0xFF },
{ 0xFF, 0xFF, 0xFF, 0xFF },
{ 0xFF, 0xFF, 0xFF, 0xFF }
};
static const comb_line_length comb_line_length_ntsc_433[] = {
{ 0x462, 0x8C9 },
{ 0x462, 0x8C9 },
{ 0x462, 0x8C9 },
{ 0x462, 0x8C9 },
{ 0, 0 },
{ 0x462, 0x8C9 },
{ 0x462, 0x8C9 }
};
static const uint8 comb_types_pal_m[] = {
_2Tap_C_combed_Y_Sub,
YC_mode_2Tap_YV_filter,
0
};
static const comb_cntl0 comb_cntl0_pal_m[] = {
{ 0, 0, 1, 0, 4, 0, 1, 2, 0, 0, 2, 0 },
{ 0, 0, 1, 0, 5, 0, 1, 2, 0, 0, 2, 0 }
};
static const comb_cntl1 comb_cntl1_pal_m[] = {
{ 1, 0, 1, 1, 2, 0, 0 },
{ 1, 0, 0, 1, 2, 0, 0 }
};
static const comb_cntl2 comb_cntl2_pal_m[] = {
{ 0xFF, 0xFF, 0xFF, 0xFF },
{ 0xFF, 0xFF, 0xFF, 0xFF }
};
static const comb_line_length comb_line_length_pal_m[] = {
{ 0x389, 0 },
{ 0x389, 0 }
};
static const uint8 comb_types_pal_n[] = {
_3Tap_2D_adaptive_Comb,
_2Tap_C_combed_Y_Sub,
YC_mode_2Tap_YV_filter,
0
};
static const comb_cntl0 comb_cntl0_pal_n[] = {
{ 0x90, 0x80, 1, 1, 0, 2, 0, 1, 0, 1, 0, 0 },
{ 0, 0, 1, 0, 4, 0, 1, 2, 0, 0, 2, 0 },
{ 0, 0, 1, 0, 5, 0, 1, 2, 0, 0, 2, 0 }
};
static const comb_cntl1 comb_cntl1_pal_n[] = {
{ 0, 0, 1, 0, 0, 0, 0 },
{ 1, 0, 1, 1, 2, 0, 0 },
{ 1, 0, 0, 1, 2, 0, 0 }
};
static const comb_cntl2 comb_cntl2_pal_n[] = {
{ 0x10, 0x10, 0x16, 0x16 },
{ 0xFF, 0xFF, 0xFF, 0xFF },
{ 0xFF, 0xFF, 0xFF, 0xFF }
};
static const comb_line_length comb_line_length_pal_n[] = {
{ 0x46B, 0x8DA },
{ 0x46C, 0 },
{ 0x46C, 0 }
};
static const uint8 comb_types_pal_nc[] = {
_3Tap_2D_adaptive_Comb,
_2Tap_C_combed_Y_Sub,
YC_mode_2Tap_YV_filter,
0
};
#define X 0
static const comb_cntl0 comb_cntl0_pal_nc[] = {
{ 0x90, 0x80, 1, 1, 0, 2, 0, 1, 0, 1, 0, 0 },
{ X, X, 1, 0, 4, 0, 1, 2, 0, 0, 2, 0 },
{ X, X, 1, 0, 5, 0, 1, 2, X, 0, 2, 0 }
};
static const comb_cntl1 comb_cntl1_pal_nc[] = {
{ 0, 0, 1, 0, 0, 0, 0 },
{ 1, 0, 1, 1, 2, 0, 0 },
{ 1, 0, 0, 1, 2, 0, 0 }
};
static const comb_cntl2 comb_cntl2_pal_nc[] = {
{ 0x10, 0x10, 0x16, 0x16 },
{ 0xFF, 0xFF, 0xFF, 0xFF },
{ 0xFF, 0xFF, 0xFF, 0xFF }
};
static const comb_line_length comb_line_length_pal_nc[] = {
{ 0x391, 0x726 },
{ 0x394, X },
{ 0x394, X }
};
static const uint8 comb_types_pal[] = {
_3Tap_2D_adaptive_Comb,
_2Tap_C_combed_Y_Sub,
YC_mode_2Tap_YV_filter,
0
};
static const comb_cntl0 comb_cntl0_pal[] = {
{ 0x90, 0x80, 1, 1, 0, 2, 0, 1, 0, 1, 0, 0 },
{ 0, 0, 1, 0, 4, 0, 1, 2, 0, 0, 2, 0 },
{ 0, 0, 1, 0, 5, 0, 1, 2, X, 0, 2, 0 }
};
static const comb_cntl1 comb_cntl1_pal[] = {
{ 0, 0, 1, 0, 0, 0, 0 },
{ 1, 0, 1, 1, 2, 0, 0 },
{ 1, 0, 0, 1, 2, 0, 0 }
};
static const comb_cntl2 comb_cntl2_pal[] = {
{ 2, 1, 8, 6 },
{ 0xFF, 0xFF, 0xFF, 0xFF },
{ 0xFF, 0xFF, 0xFF, 0xFF }
};
static const comb_line_length comb_line_length_pal[] = {
{ 0x46B, 0x8DA },
{ 0x46C, X },
{ 0x46C, X }
};
static const uint8 comb_types_pal_60[] = {
_2Tap_C_combed_Y_Sub,
YC_mode_2Tap_YV_filter,
0
};
static const comb_cntl0 comb_cntl0_pal_60[] = {
{ 0, 0, 1, 0, 4, 0, 1, 2, 0, 0, 2, 0 },
{ 0, 0, 1, 0, 5, 0, 1, 2, 0, 0, 2, 0 }
};
static const comb_cntl1 comb_cntl1_pal_60[] = {
{ 1, 0, 1, 1, 2, 0, 0 },
{ 1, 0, 0, 1, 2, 0, 0 }
};
static const comb_cntl2 comb_cntl2_pal_60[] = {
{ 0xFF, 0xFF, 0xFF, 0xFF },
{ 0xFF, 0xFF, 0xFF, 0xFF }
};
static const comb_line_length comb_line_length_pal_60[] = {
{ 0x463, 0 },
{ 0x463, 0 }
};
static const uint8 comb_types_secam[] = {
_2Tap_C_combed_Y_Sub,
YC_mode_2Tap_YV_filter,
0,
};
static const comb_cntl0 comb_cntl0_secam[] = {
{ X, X, 0, 0, 4, X, X, X, X, 2, 2, 1 },
{ X, X, 0, 0, 5, X, X, X, X, 2, 2, X }
};
static const comb_cntl1 comb_cntl1_secam[] = {
{ 1, 0, 1, 0, 2, 0, 0 },
{ 1, X, 0, 0, 2, 0, 0 }
};
static const comb_cntl2 comb_cntl2_secam[] = {
{ 0xFF, 0xFF, 0xFF, 0xFF },
{ 0xFF, 0xFF, 0xFF, 0xFF }
};
static const comb_line_length comb_line_length_secam[] = {
{ 0x46A, 0 },
{ 0x46A, 0 }
};
#undef X
static const comb_settings comb_settings_list[] = {
{ comb_types_ntsc_m, comb_cntl0_ntsc_m, comb_cntl1_ntsc_m, comb_cntl2_ntsc_m, comb_line_length_ntsc_m },
{ comb_types_ntsc_m, comb_cntl0_ntsc_m, comb_cntl1_ntsc_m, comb_cntl2_ntsc_m, comb_line_length_ntsc_m },
{ comb_types_ntsc_433, comb_cntl0_ntsc_433, comb_cntl1_ntsc_433, comb_cntl2_ntsc_433, comb_line_length_ntsc_433 },
{ comb_types_pal_m, comb_cntl0_pal_m, comb_cntl1_pal_m, comb_cntl2_pal_m, comb_line_length_pal_m },
{ comb_types_pal_n, comb_cntl0_pal_n, comb_cntl1_pal_n, comb_cntl2_pal_n, comb_line_length_pal_n },
{ comb_types_pal_nc, comb_cntl0_pal_nc, comb_cntl1_pal_nc, comb_cntl2_pal_nc, comb_line_length_pal_nc },
{ comb_types_pal, comb_cntl0_pal, comb_cntl1_pal, comb_cntl2_pal, comb_line_length_pal },
{ comb_types_pal_60, comb_cntl0_pal_60, comb_cntl1_pal_60, comb_cntl2_pal_60, comb_line_length_pal_60 },
{ comb_types_secam, comb_cntl0_secam, comb_cntl1_secam, comb_cntl2_secam, comb_line_length_secam }
};
int min_type, max_type, type;
const comb_settings *settings;
int i = 0;
PRINT(("CTheater100::SetCombFilter(%c, %c)\n", "NJ4MNCB6S"[standard], "TCS"[source]));
if( source == C_THEATER_TUNER || source == C_THEATER_COMPOSITE ) {
min_type = _3Tap_2D_adaptive_Comb;
max_type = _3Tap_C_combed_Y_combed;
} else {
min_type = YC_mode_Comb_filter_off;
max_type = YC_mode_3Tap_YV_filter;
}
settings = &comb_settings_list[standard];
for( type = min_type; type <= max_type; ++type ) {
for( i = 0; settings->types[i]; ++i ) {
if( settings->types[i] == type )
break;
}
if( settings->types[i] != 0 )
break;
}
if( type > max_type ) {
PRINT(("CTheater100::SetCombFilter() - No settings for this standard and input type combination!!!\n"));
return;
}
SetRegister(VIP_COMB_CNTL0, *(const int32 *)(settings->cntl0 + i));
SetRegister(VIP_COMB_CNTL1, *(const int32 *)(settings->cntl1 + i));
SetRegister(VIP_COMB_CNTL2, *(const int32 *)(settings->cntl2 + i));
SetRegister(VIP_COMB_LINE_LENGTH, *(const int32 *)(settings->line_length + i));
SetRegister(VIP_COMB_CNTL1, Register(VIP_COMB_CNTL1) ^ COMB_SYNCLPFRST);
SetRegister(VIP_COMB_CNTL1, Register(VIP_COMB_CNTL1) ^ COMB_SYNCLPFRST);
}
void CTheater100::SetLuminanceProcessor(theater_standard standard)
{
static const uint16 synctip_ref0[] = {
0x037, 0x037, 0x037, 0x037, 0x037, 0x037, 0x037, 0x037, 0x037 };
static const uint16 synctip_ref1[] = {
0x029, 0x029, 0x029, 0x029, 0x029, 0x026, 0x026, 0x026, 0x026 };
static const uint16 clamp_ref[] = {
0x03B, 0x03B, 0x03B, 0x03B, 0x03B, 0x03B, 0x03B, 0x03B, 0x03B };
static const uint16 agc_peakwhite[] = {
0x0FF, 0x0FF, 0x0FF, 0x0FF, 0x0FF, 0x0FF, 0x0FF, 0x0FF, 0x0FF };
static const uint16 vbi_peakwhite[] = {
0x0D2, 0x0D2, 0xD2, 0x0D2, 0x0D2, 0x0C6, 0x0C6, 0x0C6, 0x0C6 };
static const uint16 wpa_threshold[] = {
0x406, 0x406, 0x4FC, 0x406, 0x59C, 0x488, 0x59C, 0x59C, 0x57A };
static const uint16 wpa_trigger_lo[] = {
0x0B3, 0x0B3, 0x0B3, 0x0B3, 0x096, 0x096, 0x096, 0x0B3, 0x096 };
static const uint16 wpa_trigger_hi[] = {
0x21B, 0x21B, 0x21B, 0x21B, 0x1C2, 0x1C2, 0x1C2, 0x21B, 0x1C2 };
static const uint16 lp_lockout_start[] = {
0x206, 0x206, 0x206, 0x206, 0x263, 0x263, 0x263, 0x206, 0x263 };
static const uint16 lp_lockout_end[] = {
0x00B, 0x00B, 0x00B, 0x00B, 0x00C, 0x00C, 0x00C, 0x00B, 0x00C };
PRINT(("CTheater100::SetLuminanceProcessor(%c)\n", "NJ4MNCB6S"[standard]));
SetRegister(VIP_LP_AGC_CLAMP_CNTL0, SYNCTIP_REF0, synctip_ref0[standard] << 0);
SetRegister(VIP_LP_AGC_CLAMP_CNTL0, SYNCTIP_REF1, (uint32)synctip_ref1[standard] << 8);
SetRegister(VIP_LP_AGC_CLAMP_CNTL0, CLAMP_REF, (uint32)clamp_ref[standard] << 16);
SetRegister(VIP_LP_AGC_CLAMP_CNTL0, AGC_PEAKWHITE, (uint32)agc_peakwhite[standard] << 24);
SetRegister(VIP_LP_AGC_CLAMP_CNTL1, VBI_PEAKWHITE, (uint32)vbi_peakwhite[standard] << 0);
SetRegister(VIP_LP_WPA_CNTL0, WPA_THRESHOLD, wpa_threshold[standard] << 0);
SetRegister(VIP_LP_WPA_CNTL1, WPA_TRIGGER_LO, wpa_trigger_lo[standard] << 0);
SetRegister(VIP_LP_WPA_CNTL1, WPA_TRIGGER_HI, (uint32)wpa_trigger_hi[standard] << 16);
SetRegister(VIP_LP_VERT_LOCKOUT, LP_LOCKOUT_START, lp_lockout_start[standard] << 0);
SetRegister(VIP_LP_VERT_LOCKOUT, LP_LOCKOUT_END, (uint32)lp_lockout_end[standard] << 16);
}
void CTheater100::SetLuminanceLevels(theater_standard standard, int brightness, int contrast)
{
double ref0, setup, gain;
ref0 = Register(VIP_LP_AGC_CLAMP_CNTL0, SYNCTIP_REF0);
switch (standard) {
case C_THEATER_NTSC:
case C_THEATER_PAL_M:
case C_THEATER_NTSC_443:
setup = 7.5 * ref0 / 40.0;
gain = 219.0 / (92.5 * ref0 / 40.0);
break;
case C_THEATER_NTSC_JAPAN:
setup = 0.0;
gain = 219.0 / (100.0 * ref0 / 40.0);
break;
case C_THEATER_PAL_BDGHI:
case C_THEATER_PAL_N:
case C_THEATER_SECAM:
case C_THEATER_PAL_60:
case C_THEATER_PAL_NC:
setup = 0.0;
gain = 219.0 / (100.0 * ref0 / 43.0);
break;
default:
setup = 0.0;
gain = 0.0;
break;
}
if (contrast <= -100)
contrast = -99;
SetRegister(VIP_LP_CONTRAST, CONTRAST,
int(64.0 * ((contrast + 100) / 100.0) * gain) << 0);
SetRegister(VIP_LP_BRIGHTNESS, BRIGHTNESS,
int(16.0 * ((brightness - setup) + 16.0 / ((contrast + 100) * gain / 100.0))) & BRIGHTNESS);
}
void CTheater100::SetChromaProcessor(theater_standard standard)
{
PRINT(("CTheater100::SetChromaProcessor(%c)\n", "NJ4MNCB6S"[standard]));
static const uint32 ch_dto_inc[] = {
0x400000, 0x400000, 0x400000, 0x400000, 0x400000, 0x400000, 0x400000, 0x400000, 0x3E7A28 };
static const uint8 ch_pll_sgain[] = {
1, 1, 1, 1, 1, 1, 1, 1, 5 };
static const uint8 ch_pll_fgain[] = {
2, 2, 2, 2, 2, 2, 2, 2, 6 };
static const uint8 ch_height[] = {
0xCD, 0xCD, 0xCD, 0x91, 0x91, 0x9C, 0x9C, 0x9C, 0x66 };
static const uint8 ch_kill_level[] = {
0x0C0, 0xC0, 0xC0, 0x8C, 0x8C, 0x90, 0x90, 0x90, 0x60 };
static const uint8 ch_agc_error_lim[] = {
2, 2, 2, 2, 2, 2, 2, 2, 3 };
static const uint8 ch_agc_filter_en[] = {
0, 0, 0, 0, 0, 0, 1, 0, 0 };
static const uint8 ch_agc_loop_speed[] = {
0, 0, 0, 0, 0, 0, 0, 0, 0 };
static const uint16 cr_burst_gain[] = {
0x7A, 0x71, 0x7A, 0x7A, 0x7A, 0x7A, 0x7A, 0x7A, 0x1FF };
static const uint16 cb_burst_gain[] = {
0xAC, 0x9F, 0xAC, 0xAC, 0xAC, 0xAB, 0xAB, 0xAB, 0x1FF };
static const uint16 crdr_active_gain[] = {
0x7A, 0x71, 0x7A, 0x7A, 0x7A, 0x7A, 0x7A, 0x7A, 0x11C };
static const uint16 cbdb_active_gain[] = {
0xAC, 0x9F, 0xAC, 0xAC, 0xAC, 0xAB, 0xAB, 0xAB, 0x15A };
static const uint16 cp_vert_lockout_start[] = {
0x207, 0x207, 0x207, 0x207, 0x269, 0x269, 0x269, 0x207, 0x269 };
static const uint8 cp_vert_lockout_end[] = {
0x00E, 0x00E, 0x00E, 0x00E, 0x00E, 0x012, 0x012, 0x00E, 0x012 };
SetRegister(VIP_CP_PLL_CNTL0, CH_DTO_INC, ch_dto_inc[standard] << 0);
SetRegister(VIP_CP_PLL_CNTL0, CH_PLL_SGAIN, (uint32)ch_pll_sgain[standard] << 24);
SetRegister(VIP_CP_PLL_CNTL0, CH_PLL_FGAIN, (uint32)ch_pll_fgain[standard] << 28);
SetRegister(VIP_CP_AGC_CNTL, CH_HEIGHT, ch_height[standard] << 0);
SetRegister(VIP_CP_AGC_CNTL, CH_KILL_LEVEL, (uint32)ch_kill_level[standard] << 8);
SetRegister(VIP_CP_AGC_CNTL, CH_AGC_ERROR_LIM, (uint32)ch_agc_error_lim[standard] << 16);
SetRegister(VIP_CP_AGC_CNTL, CH_AGC_FILTER_EN, (uint32)ch_agc_filter_en[standard] << 18);
SetRegister(VIP_CP_AGC_CNTL, CH_AGC_LOOP_SPEED, (uint32)ch_agc_loop_speed[standard] << 19);
SetRegister(VIP_CP_BURST_GAIN, CR_BURST_GAIN, cr_burst_gain[standard] << 0);
SetRegister(VIP_CP_BURST_GAIN, CB_BURST_GAIN, (uint32)cb_burst_gain[standard] << 16);
SetRegister(VIP_CP_ACTIVE_GAIN, CRDR_ACTIVE_GAIN, crdr_active_gain[standard] << 0);
SetRegister(VIP_CP_ACTIVE_GAIN, CBDB_ACTIVE_GAIN, (uint32)cbdb_active_gain[standard] << 16);
SetRegister(VIP_CP_VERT_LOCKOUT, CP_LOCKOUT_START, cp_vert_lockout_start[standard] << 0);
SetRegister(VIP_CP_VERT_LOCKOUT, CP_LOCKOUT_END, (uint32)cp_vert_lockout_end[standard] << 16);
}
void CTheater100::SetChromaLevels(theater_standard standard, int saturation, int hue)
{
int ref0;
double gain, CRgain, CBgain;
ref0 = Register(VIP_LP_AGC_CLAMP_CNTL0, SYNCTIP_REF0);
switch (standard) {
case C_THEATER_NTSC:
case C_THEATER_NTSC_443:
case C_THEATER_PAL_M:
CRgain = (40.0 / ref0) * (100.0 / 92.5) * (1.0 / 0.877) * (112.0 / 70.1) / 1.5;
CBgain = (40.0 / ref0) * (100.0 / 92.5) * (1.0 / 0.492) * (112.0 / 88.6) / 1.5;
break;
case C_THEATER_NTSC_JAPAN:
CRgain = (40.0 / ref0) * (100.0 / 100.0) * (1.0 / 0.877) * (112.0 / 70.1) / 1.5;
CBgain = (40.0 / ref0) * (100.0 / 100.0) * (1.0 / 0.492) * (112.0 / 88.6) / 1.5;
break;
case C_THEATER_PAL_BDGHI:
case C_THEATER_PAL_60:
case C_THEATER_PAL_NC:
case C_THEATER_PAL_N:
CRgain = (43.0 / ref0) * (100.0 / 92.5) * (1.0 / 0.877) * (112.0 / 70.1) / 1.5;
CBgain = (43.0 / ref0) * (100.0 / 92.5) * (1.0 / 0.492) * (112.0 / 88.6) / 1.5;
break;
case C_THEATER_SECAM:
CRgain = 32.0 * 32768.0 / 280000.0 / (33554432.0 / 35.46985) * (1.597 / 1.902) / 1.5;
CBgain = 32.0 * 32768.0 / 230000.0 / (33554432.0 / 35.46985) * (1.267 / 1.505) / 1.5;
break;
default:
PRINT(("CTheater100::SetChromaLevels() - Bad standard\n"));
CRgain = 0.0;
CBgain = 0.0;
break;
}
if (saturation >= 0)
gain = 1.0 + 4.9 * saturation / 100.0;
else
gain = 1.0 + saturation / 100.0;
SetRegister(VIP_CP_ACTIVE_GAIN, CRDR_ACTIVE_GAIN, int(128 * CRgain * gain) << 0);
SetRegister(VIP_CP_ACTIVE_GAIN, CBDB_ACTIVE_GAIN, int(128 * CBgain * gain) << 16);
if (hue >= 0)
hue = (256 * hue) / 360;
else
hue = (256 * (hue + 360)) / 360;
SetRegister(VIP_CP_HUE_CNTL, HUE_ADJ, hue << 0);
}
static const uint16 h_active_start[] = {
0x06b, 0x06B, 0x07E, 0x067, 0x09A, 0x07D, 0x09A, 0x084, 0x095 };
static const uint16 h_active_end[] = {
0x363, 0x363, 0x42A, 0x363, 0x439, 0x439, 0x439, 0x363, 0x439 };
static const uint16 v_active_start[] = {
0x025, 0x025, 0x025, 0x025, 0x02E, 0x02E, 0x02E, 0x025, 0x02E };
static const uint16 v_active_end[] = {
0x204, 0x204, 0x204, 0x204, 0x269, 0x269, 0x269, 0x204, 0x269 };
static const uint16 h_vbi_wind_start[] = {
0x064, 0x064, 0x064, 0x064, 0x084, 0x084, 0x084, 0x064, 0x084 };
static const uint16 h_vbi_wind_end[] = {
0x366, 0x366, 0x366, 0x366, 0x41F, 0x41F, 0x41F, 0x366, 0x41F };
static const uint16 v_vbi_wind_start[] = {
0x00b, 0x00b, 0x00b, 0x00b, 0x008, 0x008, 0x008, 0x00b, 0x008 };
static const uint16 v_vbi_wind_end[] = {
0x024, 0x024, 0x024, 0x024, 0x02d, 0x02d, 0x02d, 0x024, 0x02d };
void CTheater100::getActiveRange( theater_standard standard, CRadeonRect &rect )
{
rect.SetTo(
h_active_start[standard], v_active_start[standard],
h_active_end[standard], v_active_end[standard] );
}
void CTheater100::getVBIRange( theater_standard standard, CRadeonRect &rect )
{
rect.SetTo(
h_vbi_wind_start[standard], v_vbi_wind_start[standard],
h_vbi_wind_end[standard], v_vbi_wind_end[standard] );
}
void CTheater100::SetClipWindow(theater_standard standard, bool vbi)
{
SetRegister(VIP_H_ACTIVE_WINDOW, H_ACTIVE_START, h_active_start[standard] << 0);
SetRegister(VIP_H_ACTIVE_WINDOW, H_ACTIVE_END, (uint32)h_active_end[standard] << 16);
SetRegister(VIP_V_ACTIVE_WINDOW, V_ACTIVE_START, v_active_start[standard] << 0);
SetRegister(VIP_V_ACTIVE_WINDOW, V_ACTIVE_END, (uint32)v_active_end[standard] << 16);
SetRegister(VIP_H_VBI_WINDOW, H_VBI_WIND_START, h_vbi_wind_start[standard] << 0);
SetRegister(VIP_H_VBI_WINDOW, H_VBI_WIND_END, (uint32)h_vbi_wind_end[standard] << 16);
SetRegister(VIP_V_VBI_WINDOW, V_VBI_WIND_START, v_vbi_wind_start[standard] << 0);
SetRegister(VIP_V_VBI_WINDOW, V_VBI_WIND_END, (uint32)v_vbi_wind_end[standard] << 16);
SetRegister(VIP_VBI_SCALER_CONTROL, (1 << 16) & VBI_SCALING_RATIO);
SetRegister(VIP_VBI_CONTROL, VBI_CAPTURE_ENABLE,
vbi ? VBI_CAPTURE_EN : VBI_CAPTURE_DIS);
PRINT(("CTheater100::SetClipWindow(active=%d/%d/%d/%d, vbi=%d/%d/%d/%d)\n",
Register(VIP_H_ACTIVE_WINDOW, H_ACTIVE_START) >> 0,
Register(VIP_H_ACTIVE_WINDOW, H_ACTIVE_END) >> 16,
Register(VIP_V_ACTIVE_WINDOW, V_ACTIVE_START) >> 0,
Register(VIP_V_ACTIVE_WINDOW, V_ACTIVE_END) >> 16,
Register(VIP_H_VBI_WINDOW, H_VBI_WIND_START) >> 0,
Register(VIP_H_VBI_WINDOW, H_VBI_WIND_END) >> 16,
Register(VIP_V_VBI_WINDOW, V_VBI_WIND_START) >> 0,
Register(VIP_V_VBI_WINDOW, V_VBI_WIND_END) >> 16));
}
void CTheater100::SetScaler(theater_standard standard, int hactive, int vactive, bool deinterlace)
{
int oddOffset, evenOffset;
uint16 h_active_width, v_active_height;
h_active_width = h_active_end[standard] - h_active_start[standard] + 1;
v_active_height = v_active_end[standard] - v_active_start[standard] + 1;
if( vactive > v_active_height )
vactive = v_active_height;
if (deinterlace) {
evenOffset = oddOffset = 512 - (int) ((512 * vactive) / v_active_height);
}
else {
evenOffset = (int) ((512 * vactive) / v_active_height);
oddOffset = 2048 - evenOffset;
}
SetRegister(VIP_SCALER_IN_WINDOW, H_IN_WIND_START, h_active_start[standard] << 0);
SetRegister(VIP_SCALER_IN_WINDOW, V_IN_WIND_START, (uint32)v_active_start[standard] << 16);
SetRegister(VIP_SCALER_OUT_WINDOW, H_OUT_WIND_WIDTH, hactive << 0);
SetRegister(VIP_SCALER_OUT_WINDOW, V_OUT_WIND_HEIGHT, (vactive / 2) << 16);
SetRegister(VIP_H_SCALER_CONTROL, H_SCALE_RATIO, (((uint32)h_active_width << 16) / hactive) << 0);
SetRegister(VIP_V_SCALER_CONTROL, V_SCALE_RATIO, ((vactive << 11) / v_active_height) << 0);
SetRegister(VIP_H_SCALER_CONTROL, H_BYPASS,
h_active_width == hactive ? H_BYPASS : 0);
SetRegister(VIP_V_SCALER_CONTROL, V_BYPASS,
v_active_height == vactive ? V_BYPASS : 0);
SetRegister(VIP_V_SCALER_CONTROL, V_DEINTERLACE_ON, deinterlace ? V_DEINTERLACE_ON : 0);
SetRegister(VIP_V_DEINTERLACE_CONTROL, EVENF_OFFSET, evenOffset << 0);
SetRegister(VIP_V_DEINTERLACE_CONTROL, ODDF_OFFSET, oddOffset << 11);
SetRegister(VIP_V_SCALER_CONTROL, V_DEINTERLACE_ON, deinterlace ? V_DEINTERLACE_ON : 0);
PRINT(("CTheater100::SetScaler(active=%d/%d/%d/%d, scale=%d/%d)\n",
Register(VIP_SCALER_IN_WINDOW, H_IN_WIND_START) >> 0,
Register(VIP_SCALER_IN_WINDOW, V_IN_WIND_START) >> 16,
hactive, vactive,
Register(VIP_H_SCALER_CONTROL, H_SCALE_RATIO),
Register(VIP_V_SCALER_CONTROL, V_SCALE_RATIO)));
}
int CTheater100::CurrentLine()
{
return Register(VIP_VS_LINE_COUNT) & VS_LINE_COUNT;
}
void CTheater100::PrintToStream()
{
PRINT(("<<< Rage Theater Registers >>>\n"));
for (int index = 0x0400; index <= 0x06ff; index += 4) {
int value = Register(index);
value = value;
PRINT(("REG_0x%04x = 0x%08x\n", index, value));
}
}