📄 theater.cpp
字号:
/******************************************************************************// File: Theater.cpp// Description: ATI Rage Theater Video Decoder interface.// Copyright 2001, Carlos Hasan/*******************************************************************************/#include <Debug.h>#include "Theater.h"#include "TheatreReg.h"#include "lendian_bitfield.h"CTheater::CTheater(CRadeon & radeon) : fPort(radeon), fDevice(0), fClock(C_RADEON_NO_VIDEO_CLOCK), fTunerPort(0), fCompositePort(0), fSVideoPort(0), fStandard(C_THEATER_NTSC), fSource(C_THEATER_TUNER), fBrightness(0), fContrast(0), fSaturation(0), fHue(0), fDeinterlace(true){ PRINT(("CTheater::CTheater()\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(("CTheater::CTheater() - Unsupported crystal clock!\n")); fDevice = fPort.FindVIPDevice( (C_THEATER_VIP_VENDOR_ID << 0) | (C_THEATER_VIP_DEVICE_ID << 16)); } if( InitCheck() != B_OK ) PRINT(("CTheater::CTheater() - Rage Theater not found!\n"));}CTheater::~CTheater(){ PRINT(("CTheater::~CTheater()\n")); if( InitCheck() == B_OK ) SetEnable(false, false);}status_t CTheater::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 CTheater::Reset(){ PRINT(("CTheater::Reset()\n")); SetHue(0); SetBrightness(0); SetSaturation(0); SetContrast(0); SetSharpness(false);}// disable/enable capturingvoid CTheater::SetEnable(bool enable, bool vbi){ PRINT(("CTheater::SetEnable(%d, %d)\n", enable, vbi));#if 0 //@ reset ADC? 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(); /* Disable the Video In, Scaler and DVS port */ SetRegister(VIP_MASTER_CNTL, VIN_ASYNC_RST, VIN_ASYNC_RST); SetRegister(VIP_MASTER_CNTL, DVS_ASYNC_RST, DVS_ASYNC_RST); /* select the reference clock for the Video In */ SetRegister(VIP_CLOCK_SEL_CNTL, VIN_CLK_SEL, VIN_CLK_SEL_REF_CLK); /* reset the VIN/L54 PLL clocks */ SetRegister(VIP_PLL_CNTL1, VINRST, VINRST); SetRegister(VIP_PLL_CNTL1, L54RST, L54RST); /* power down the ADC block */ SetRegister(VIP_ADC_CNTL, ADC_PDWN, ADC_PDWN); /* set DVS port to input mode */ SetRegister(VIP_DVS_PORT_CTRL, DVS_DIRECTION, DVS_DIRECTION_INPUT); /* select DVS clock to 8xFsc and disable continuous mode */ 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); /* Enable ADC block */ SetRegister(VIP_ADC_CNTL, ADC_PDWN, ADC_PDWN_UP); WaitVSYNC(); /* Enable the Video In, Scaler and DVS port */ SetRegister(VIP_MASTER_CNTL, VIN_ASYNC_RST, 0); SetRegister(VIP_MASTER_CNTL, DVS_ASYNC_RST, 0); /* set DVS port to output mode */ SetRegister(VIP_DVS_PORT_CTRL, DVS_DIRECTION, DVS_DIRECTION_OUTPUT); //WaitHSYNC(); /* restore luminance and chroma settings */ SetLuminanceLevels(fStandard, fBrightness, fContrast); SetChromaLevels(fStandard, fSaturation, fHue); }}void CTheater::SetStandard(theater_standard standard, theater_source source){ PRINT(("CTheater::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 CTheater::SetSize(int hactive, int vactive){ PRINT(("CTheater::SetSize(%d, %d)\n", hactive, vactive)); fHActive = hactive; fVActive = vactive;}void CTheater::SetDeinterlace(bool deinterlace){ PRINT(("CTheater::SetDeinterlace(%d)\n", deinterlace)); fDeinterlace = deinterlace;}void CTheater::SetSharpness(int sharpness){ PRINT(("CTheater::SetSharpness(%d)\n", sharpness)); SetRegister(VIP_H_SCALER_CONTROL, H_SHARPNESS, sharpness << 25);}void CTheater::SetBrightness(int brightness){ PRINT(("CTheater::SetBrightness(%d)\n", brightness)); fBrightness = brightness; SetLuminanceLevels(fStandard, fBrightness, fContrast);}void CTheater::SetContrast(int contrast){ PRINT(("CTheater::SetContrast(%d)\n", contrast)); fContrast = contrast; SetLuminanceLevels(fStandard, fBrightness, fContrast);}void CTheater::SetSaturation(int saturation){ PRINT(("CTheater::SetSaturation(%d)\n", saturation)); fSaturation = saturation; SetChromaLevels(fStandard, fSaturation, fHue);}void CTheater::SetHue(int hue){ PRINT(("CTheater::SetHue(%d)\n", hue)); fHue = hue; SetChromaLevels(fStandard, fSaturation, fHue);}// set pixel clockvoid CTheater::SetClock(theater_standard standard, radeon_video_clock clock){ // set VIN PLL clock dividers 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(("CTheater::SetClock() - Bad standard\n")); return; } // reset VIN PLL and select the reference clock 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); // set up the VIN PLL clock control 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); // active the VIN/L54 PLL and attach the VIN PLL to the VIN clock 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(("CTheater::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)));}// setup analog-digital convertervoid CTheater::SetADC(theater_standard standard, theater_source source){ PRINT(("CTheater::SetADC(%c, %c)\n", "NJ4MNCB6S"[standard], "TCS"[source])); // set HW_DEBUG before setting the standard SetRegister(VIP_HW_DEBUG, 0x0000f000); // select the video standard 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(("CTheater::SetADC() - Bad standard\n")); return; } // select input connector and Y/C mode 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(("CTheater::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);}// setup horizontal sync PLLvoid CTheater::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 }; // TK: completely different in gatos 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 }; // set number of samples per line 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]); // set min/max pulse width in samples 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(("CTheater::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,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -