1 /******************************************************************************
5 / Description: ATI Rage Theater Video Decoder interface.
7 / Copyright 2001, Carlos Hasan
9 *******************************************************************************/
12 #include "Theater100.h"
14 #include "TheatreReg.h"
15 #include "lendian_bitfield.h"
17 CTheater100::CTheater100(CRadeon
& radeon
, int device
)
18 :CTheater(radeon
, device
)
20 PRINT(("CTheater100::CTheater100()\n"));
22 if( fPort
.InitCheck() == B_OK
) {
23 radeon_video_tuner tuner
;
24 radeon_video_decoder video
;
26 radeon
.GetMMParameters(tuner
, video
, fClock
,
27 fTunerPort
, fCompositePort
, fSVideoPort
);
29 if (fClock
!= C_RADEON_VIDEO_CLOCK_29_49892_MHZ
&&
30 fClock
!= C_RADEON_VIDEO_CLOCK_27_00000_MHZ
)
31 PRINT(("CTheater100::CTheater100() - Unsupported crystal clock!\n"));
33 //fDevice = fPort.FindVIPDevice( C_THEATER100_VIP_DEVICE_ID );
37 if( InitCheck() != B_OK
)
38 PRINT(("CTheater100::CTheater100() - Rage Theater not found!\n"));
41 CTheater100::~CTheater100()
43 PRINT(("CTheater100::~CTheater100()\n"));
45 if( InitCheck() == B_OK
)
46 SetEnable(false, false);
49 status_t
CTheater100::InitCheck() const
53 res
= fPort
.InitCheck();
57 return (fDevice
>= C_VIP_PORT_DEVICE_0
&& fDevice
<= C_VIP_PORT_DEVICE_3
) ? B_OK
: B_ERROR
;
60 void CTheater100::Reset()
62 PRINT(("CTheater100::Reset()\n"));
71 // disable/enable capturing
72 void CTheater100::SetEnable(bool enable
, bool vbi
)
74 PRINT(("CTheater100::SetEnable(%d, %d)\n", enable
, vbi
));
78 SetRegister(VIP_ADC_CNTL
, ADC_CPRESET
, ADC_CPRESET
);
80 SetRegister(VIP_ADC_CNTL
, ADC_CPRESET
, 0);
82 SetRegister(VIP_ADC_CNTL
, ADC_PDWN
, ADC_PDWN_DOWN
);
88 /* Disable the Video In, Scaler and DVS port */
89 SetRegister(VIP_MASTER_CNTL
, VIN_ASYNC_RST
, VIN_ASYNC_RST
);
90 SetRegister(VIP_MASTER_CNTL
, DVS_ASYNC_RST
, DVS_ASYNC_RST
);
92 /* select the reference clock for the Video In */
93 SetRegister(VIP_CLOCK_SEL_CNTL
, VIN_CLK_SEL
, VIN_CLK_SEL_REF_CLK
);
95 /* reset the VIN/L54 PLL clocks */
96 SetRegister(VIP_PLL_CNTL1
, VINRST
, VINRST
);
97 SetRegister(VIP_PLL_CNTL1
, L54RST
, L54RST
);
99 /* power down the ADC block */
100 SetRegister(VIP_ADC_CNTL
, ADC_PDWN
, ADC_PDWN
);
102 /* set DVS port to input mode */
103 SetRegister(VIP_DVS_PORT_CTRL
, DVS_DIRECTION
, DVS_DIRECTION_INPUT
);
105 /* select DVS clock to 8xFsc and disable continuous mode */
106 SetRegister(VIP_DVS_PORT_CTRL
, DVS_CLK_SELECT
, DVS_CLK_SELECT_8X
);
107 SetRegister(VIP_DVS_PORT_CTRL
, CONTINUOUS_STREAM
, 0);
112 SetClock(fStandard
, fClock
);
113 SetADC(fStandard
, fSource
);
114 SetLuminanceProcessor(fStandard
);
115 SetChromaProcessor(fStandard
);
117 SetClipWindow(fStandard
, vbi
);
118 SetCombFilter(fStandard
, fSource
);
120 SetSyncGenerator(fStandard
);
121 SetScaler(fStandard
, fHActive
, fVActive
, fDeinterlace
);
123 /* Enable ADC block */
124 SetRegister(VIP_ADC_CNTL
, ADC_PDWN
, ADC_PDWN_UP
);
128 /* Enable the Video In, Scaler and DVS port */
129 SetRegister(VIP_MASTER_CNTL
, VIN_ASYNC_RST
, 0);
130 SetRegister(VIP_MASTER_CNTL
, DVS_ASYNC_RST
, 0);
132 /* set DVS port to output mode */
133 SetRegister(VIP_DVS_PORT_CTRL
, DVS_DIRECTION
, DVS_DIRECTION_OUTPUT
);
137 /* restore luminance and chroma settings */
138 SetLuminanceLevels(fStandard
, fBrightness
, fContrast
);
139 SetChromaLevels(fStandard
, fSaturation
, fHue
);
143 void CTheater100::SetStandard(theater_standard standard
, theater_source source
)
145 PRINT(("CTheater100::SetStandard(%s, %s)\n",
146 "NTSC\0\0\0\0\0\0NTSC-J\0\0\0\0NTSC-443\0\0PAL-M\0\0\0\0\0"
147 "PAL-N\0\0\0\0\0PAL-NC\0\0\0\0PAL-BDGHI\0PAL-60\0\0\0\0"
148 "SECAM\0\0\0\0\0"+10*standard
,
149 "TUNER\0COMP\0\0SVIDEO"+6*source
));
151 fStandard
= standard
;
155 void CTheater100::SetSize(int hactive
, int vactive
)
157 PRINT(("CTheater100::SetSize(%d, %d)\n", hactive
, vactive
));
163 void CTheater100::SetDeinterlace(bool deinterlace
)
165 PRINT(("CTheater100::SetDeinterlace(%d)\n", deinterlace
));
167 fDeinterlace
= deinterlace
;
170 void CTheater100::SetSharpness(int sharpness
)
172 PRINT(("CTheater100::SetSharpness(%d)\n", sharpness
));
174 SetRegister(VIP_H_SCALER_CONTROL
, H_SHARPNESS
, sharpness
<< 25);
177 void CTheater100::SetBrightness(int brightness
)
179 PRINT(("CTheater100::SetBrightness(%d)\n", brightness
));
181 fBrightness
= brightness
;
182 SetLuminanceLevels(fStandard
, fBrightness
, fContrast
);
185 void CTheater100::SetContrast(int contrast
)
187 PRINT(("CTheater100::SetContrast(%d)\n", contrast
));
189 fContrast
= contrast
;
190 SetLuminanceLevels(fStandard
, fBrightness
, fContrast
);
193 void CTheater100::SetSaturation(int saturation
)
195 PRINT(("CTheater100::SetSaturation(%d)\n", saturation
));
197 fSaturation
= saturation
;
198 SetChromaLevels(fStandard
, fSaturation
, fHue
);
201 void CTheater100::SetHue(int hue
)
203 PRINT(("CTheater100::SetHue(%d)\n", hue
));
206 SetChromaLevels(fStandard
, fSaturation
, fHue
);
211 void CTheater100::SetClock(theater_standard standard
, radeon_video_clock clock
)
213 // set VIN PLL clock dividers
214 int referenceDivider
, feedbackDivider
, postDivider
;
218 case C_THEATER_NTSC_JAPAN
:
219 if (clock
== C_RADEON_VIDEO_CLOCK_29_49892_MHZ
) {
220 referenceDivider
= 0x39;
221 feedbackDivider
= 0x14c;
225 referenceDivider
= 0x0b;
226 feedbackDivider
= 0x46;
230 case C_THEATER_NTSC_443
:
231 if (clock
== C_RADEON_VIDEO_CLOCK_29_49892_MHZ
) {
232 referenceDivider
= 0x23;
233 feedbackDivider
= 0x88;
237 referenceDivider
= 0x2c;
238 feedbackDivider
= 0x121;
242 case C_THEATER_PAL_M
:
243 if (clock
== C_RADEON_VIDEO_CLOCK_29_49892_MHZ
) {
244 referenceDivider
= 0x2c;
245 feedbackDivider
= 0x12b;
249 referenceDivider
= 0x0b;
250 feedbackDivider
= 0x46;
254 case C_THEATER_PAL_BDGHI
:
255 case C_THEATER_PAL_N
:
256 case C_THEATER_PAL_60
:
257 case C_THEATER_SECAM
:
258 if (clock
== C_RADEON_VIDEO_CLOCK_29_49892_MHZ
) {
259 referenceDivider
= 0x0e;
260 feedbackDivider
= 0x65;
264 referenceDivider
= 0x2c;
265 feedbackDivider
= 0x121;
269 case C_THEATER_PAL_NC
:
270 if (clock
== C_RADEON_VIDEO_CLOCK_29_49892_MHZ
) {
271 referenceDivider
= 0x23;
272 feedbackDivider
= 0x88;
276 referenceDivider
= 0x37;
277 feedbackDivider
= 0x1d3;
282 PRINT(("CTheater100::SetClock() - Bad standard\n"));
286 // reset VIN PLL and select the reference clock
287 SetRegister(VIP_CLOCK_SEL_CNTL
, VIN_CLK_SEL
, VIN_CLK_SEL_REF_CLK
);
288 SetRegister(VIP_PLL_CNTL1
, VINRST
, VINRST
);
289 SetRegister(VIP_PLL_CNTL1
, L54RST
, L54RST
);
291 // set up the VIN PLL clock control
292 SetRegister(VIP_VIN_PLL_CNTL
, VIN_M0
, referenceDivider
<< 0);
293 SetRegister(VIP_VIN_PLL_CNTL
, VIN_N0
, feedbackDivider
<< 11);
294 SetRegister(VIP_VIN_PLL_CNTL
, VIN_P
, postDivider
<< 24);
296 // active the VIN/L54 PLL and attach the VIN PLL to the VIN clock
297 SetRegister(VIP_PLL_CNTL1
, VINRST
, 0);
298 SetRegister(VIP_PLL_CNTL1
, L54RST
, 0);
299 SetRegister(VIP_CLOCK_SEL_CNTL
, VIN_CLK_SEL
, VIN_CLK_SEL_VIPLL_CLK
);
301 PRINT(("CTheater100::SetClock(Fsamp=%g, Fref=%g)\n",
302 ((fClock
== C_RADEON_VIDEO_CLOCK_29_49892_MHZ
? 29.49892 : 27.0) * feedbackDivider
) / (referenceDivider
* postDivider
),
303 (fClock
== C_RADEON_VIDEO_CLOCK_29_49892_MHZ
? 29.49892 : 27.0)));
307 // setup analog-digital converter
308 void CTheater100::SetADC(theater_standard standard
, theater_source source
)
310 PRINT(("CTheater100::SetADC(%c, %c)\n", "NJ4MNCB6S"[standard
], "TCS"[source
]));
312 // set HW_DEBUG before setting the standard
313 SetRegister(VIP_HW_DEBUG
, 0x0000f000);
315 // select the video standard
318 case C_THEATER_NTSC_JAPAN
:
319 case C_THEATER_NTSC_443
:
320 case C_THEATER_PAL_M
:
321 SetRegister(VIP_STANDARD_SELECT
, STANDARD_SEL
, STANDARD_NTSC
);
323 case C_THEATER_PAL_BDGHI
:
324 case C_THEATER_PAL_N
:
325 case C_THEATER_PAL_60
:
326 case C_THEATER_PAL_NC
:
327 SetRegister(VIP_STANDARD_SELECT
, STANDARD_SEL
, STANDARD_PAL
);
329 case C_THEATER_SECAM
:
330 SetRegister(VIP_STANDARD_SELECT
, STANDARD_SEL
, STANDARD_SECAM
);
333 PRINT(("CTheater100::SetADC() - Bad standard\n"));
337 // select input connector and Y/C mode
339 case C_THEATER_TUNER
:
340 SetRegister(VIP_ADC_CNTL
, INPUT_SELECT
, fTunerPort
);
341 SetRegister(VIP_STANDARD_SELECT
, YC_MODE
, YC_MODE_COMPOSITE
);
343 case C_THEATER_COMPOSITE
:
344 SetRegister(VIP_ADC_CNTL
, INPUT_SELECT
, fCompositePort
);
345 SetRegister(VIP_STANDARD_SELECT
, YC_MODE
, YC_MODE_COMPOSITE
);
347 case C_THEATER_SVIDEO
:
348 SetRegister(VIP_ADC_CNTL
, INPUT_SELECT
, fSVideoPort
);
349 SetRegister(VIP_STANDARD_SELECT
, YC_MODE
, YC_MODE_SVIDEO
);
352 PRINT(("CTheater100::SetADC() - Bad source\n"));
356 SetRegister(VIP_ADC_CNTL
, I_CLAMP_SEL
, I_CLAMP_SEL_22
);
357 SetRegister(VIP_ADC_CNTL
, I_AGC_SEL
, I_AGC_SEL_7
);
359 SetRegister(VIP_ADC_CNTL
, EXT_CLAMP_CAP
, EXT_CLAMP_CAP_EXTERNAL
);
360 SetRegister(VIP_ADC_CNTL
, EXT_AGC_CAP
, EXT_AGC_CAP_EXTERNAL
);
361 SetRegister(VIP_ADC_CNTL
, ADC_DECI_BYPASS
, ADC_DECI_WITH_FILTER
);
362 SetRegister(VIP_ADC_CNTL
, VBI_DECI_BYPASS
, VBI_DECI_WITH_FILTER
);
363 SetRegister(VIP_ADC_CNTL
, DECI_DITHER_EN
, 0 << 12);
364 SetRegister(VIP_ADC_CNTL
, ADC_CLK_SEL
, ADC_CLK_SEL_8X
);
365 SetRegister(VIP_ADC_CNTL
, ADC_BYPASS
, ADC_BYPASS_INTERNAL
);
368 case C_THEATER_NTSC_JAPAN
:
369 case C_THEATER_NTSC_443
:
370 case C_THEATER_PAL_M
:
371 SetRegister(VIP_ADC_CNTL
, ADC_CH_GAIN_SEL
, ADC_CH_GAIN_SEL_NTSC
);
373 case C_THEATER_PAL_BDGHI
:
374 case C_THEATER_PAL_N
:
375 case C_THEATER_PAL_60
:
376 case C_THEATER_PAL_NC
:
377 case C_THEATER_SECAM
:
378 SetRegister(VIP_ADC_CNTL
, ADC_CH_GAIN_SEL
, ADC_CH_GAIN_SEL_PAL
);
381 SetRegister(VIP_ADC_CNTL
, ADC_PAICM
, 1 << 18);
383 SetRegister(VIP_ADC_CNTL
, ADC_PDCBIAS
, 2 << 20);
384 SetRegister(VIP_ADC_CNTL
, ADC_PREFHI
, ADC_PREFHI_2_7
);
385 SetRegister(VIP_ADC_CNTL
, ADC_PREFLO
, ADC_PREFLO_1_5
);
387 SetRegister(VIP_ADC_CNTL
, ADC_IMUXOFF
, 0 << 26);
388 SetRegister(VIP_ADC_CNTL
, ADC_CPRESET
, 0 << 27);
392 // setup horizontal sync PLL
393 void CTheater100::SetHSYNC(theater_standard standard
)
395 static const uint16 hs_line_total
[] = {
396 0x38E, 0x38E, 0x46F, 0x38D, 0x46F, 0x395, 0x46F, 0x467, 0x46F };
398 static const uint32 hs_dto_inc
[] = {
399 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x3E7A2 };
401 // TK: completely different in gatos
402 static const uint8 hs_pll_sgain
[] = {
403 2, 2, 2, 2, 2, 2, 2, 2, 2 };
404 static const uint8 hs_pll_fgain
[] = {
405 8, 8, 8, 8, 8, 8, 8, 8, 8 };
407 static const uint8 gen_lock_delay
[] = {
408 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10 };
410 static const uint8 min_pulse_width
[] = {
411 0x21, 0x21, 0x29, 0x21, 0x29, 0x21, 0x29, 0x29, 0x29 };
412 static const uint8 max_pulse_width
[] = {
413 0x64, 0x64, 0x7D, 0x64, 0x7D, 0x65, 0x7D, 0x7D, 0x7D };
415 static const uint16 win_close_limit
[] = {
416 0x0A0, 0x0A0, 0x0C7, 0x0A0, 0x0C7, 0x0A0, 0x0C7, 0x0C7, 0x0C7 };
417 static const uint16 win_open_limit
[] = {
418 0x1B7, 0x1B7, 0x228, 0x1B7, 0x228, 0x1BB, 0x228, 0x224, 0x228 };
421 // set number of samples per line
422 SetRegister(VIP_HS_PLINE
, HS_LINE_TOTAL
, hs_line_total
[standard
]);
424 SetRegister(VIP_HS_DTOINC
, HS_DTO_INC
, hs_dto_inc
[standard
]);
426 SetRegister(VIP_HS_PLLGAIN
, HS_PLL_SGAIN
, hs_pll_sgain
[standard
] << 0);
427 SetRegister(VIP_HS_PLLGAIN
, HS_PLL_FGAIN
, (uint32
)hs_pll_fgain
[standard
] << 4);
429 SetRegister(VIP_HS_GENLOCKDELAY
, GEN_LOCK_DELAY
, gen_lock_delay
[standard
]);
431 // set min/max pulse width in samples
432 SetRegister(VIP_HS_MINMAXWIDTH
, MIN_PULSE_WIDTH
, min_pulse_width
[standard
] << 0);
433 SetRegister(VIP_HS_MINMAXWIDTH
, MAX_PULSE_WIDTH
, (uint32
)max_pulse_width
[standard
] << 8);
435 SetRegister(VIP_HS_WINDOW_LIMIT
, WIN_CLOSE_LIMIT
, win_close_limit
[standard
] << 0);
436 SetRegister(VIP_HS_WINDOW_LIMIT
, WIN_OPEN_LIMIT
, (uint32
)win_open_limit
[standard
] << 16);
439 PRINT(("CTheater100::SetHSYNC(total=%d, pulse=%d/%d, window=%d/%d)\n",
440 Register(VIP_HS_PLINE
, HS_LINE_TOTAL
),
441 Register(VIP_HS_MINMAXWIDTH
, MIN_PULSE_WIDTH
) >> 0,
442 Register(VIP_HS_MINMAXWIDTH
, MAX_PULSE_WIDTH
) >> 8,
443 Register(VIP_HS_WINDOW_LIMIT
, WIN_CLOSE_LIMIT
) >> 0,
444 Register(VIP_HS_WINDOW_LIMIT
, WIN_OPEN_LIMIT
) >> 16));
448 // wait until horizontal scaler is locked
449 void CTheater100::WaitHSYNC()
451 for (int timeout
= 0; timeout
< 1000; timeout
++) {
452 if (Register(VIP_HS_PULSE_WIDTH
, HS_GENLOCKED
) != 0)
456 PRINT(("CTheater100::WaitHSYNC() - wait for HSync locking time out!\n"));
460 // setup vertical sync and field detector
461 void CTheater100::SetVSYNC(theater_standard standard
)
463 static const uint16 vsync_int_trigger
[] = {
464 0x2AA, 0x2AA, 0x353, 0x2AA, 0x353, 0x2B0, 0x353, 0x34D, 0x353 };
465 static const uint16 vsync_int_hold
[] = {
466 0x017, 0x017, 0x01C, 0x017, 0x01C, 0x017, 0x01C, 0x01C, 0x01C };
467 // PAL value changed from 26b to 26d - else, odd/even field detection fails sometimes;
468 // did the same for PAL N, PAL NC and SECAM
469 static const uint16 vs_field_blank_start
[] = {
470 0x206, 0x206, 0x206, 0x206, 0x26d, 0x26d, 0x26d, 0x206, 0x26d };
471 static const uint8 vs_field_blank_end
[] = {
472 0x00a, 0x00a, 0x00a, 0x00a, 0x02a, 0x02a, 0x02a, 0x00a, 0x02a };
473 // NTSC value changed from 1 to 105 - else, odd/even fields were always swapped;
474 // did the same for NTSC Japan, NTSC 443, PAL M and PAL 60
475 static const uint16 vs_field_id_location
[] = {
476 0x105, 0x105, 0x105, 0x105, 0x1, 0x1, 0x1, 0x105, 0x1 };
477 static const uint16 vs_frame_total
[] = {
478 0x217, 0x217, 0x217, 0x217, 0x27B, 0x27B, 0x27B, 0x217, 0x27B };
480 SetRegister(VIP_VS_DETECTOR_CNTL
, VSYNC_INT_TRIGGER
, vsync_int_trigger
[standard
] << 0);
481 SetRegister(VIP_VS_DETECTOR_CNTL
, VSYNC_INT_HOLD
, (uint32
)vsync_int_hold
[standard
] << 16);
483 SetRegister(VIP_VS_BLANKING_CNTL
, VS_FIELD_BLANK_START
, vs_field_blank_start
[standard
] << 0);
484 SetRegister(VIP_VS_BLANKING_CNTL
, VS_FIELD_BLANK_END
, (uint32
)vs_field_blank_end
[standard
] << 16);
485 SetRegister(VIP_VS_FRAME_TOTAL
, VS_FRAME_TOTAL
, vs_frame_total
[standard
]);
487 SetRegister(VIP_VS_FIELD_ID_CNTL
, VS_FIELD_ID_LOCATION
, vs_field_id_location
[standard
] << 0);
489 // auto-detect fields
490 SetRegister(VIP_VS_COUNTER_CNTL
, FIELD_DETECT_MODE
, FIELD_DETECT_DETECTED
);
493 SetRegister(VIP_VS_COUNTER_CNTL
, FIELD_FLIP_EN
, 0 );
495 PRINT(("CTheater100::SetVSYNC(total=%d)\n",
496 Register(VIP_VS_FRAME_TOTAL
, VS_FRAME_TOTAL
)));
499 // wait until a visible line is viewed
500 void CTheater100::WaitVSYNC()
502 for (int timeout
= 0; timeout
< 1000; timeout
++) {
503 int lineCount
= Register(VIP_VS_LINE_COUNT
, VS_LINE_COUNT
);
504 if (lineCount
> 1 && lineCount
< 20)
508 PRINT(("CTheater100::WaitVSYNC() - wait for VBI timed out!\n"));
512 // setup timing generator
513 void CTheater100::SetSyncGenerator(theater_standard standard
)
515 static const uint16 blank_int_start
[] = {
516 0x031, 0x031, 0x046, 0x031, 0x046, 0x046, 0x046, 0x031, 0x046 };
517 static const uint8 blank_int_length
[] = {
518 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F };
520 static const uint16 sync_tip_start
[] = {
521 0x0372, 0x0372, 0x0453, 0x0371, 0x0453, 0x0379, 0x0453, 0x044B, 0x0453 };
522 static const uint8 sync_tip_length
[] = {
523 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F };
525 static const uint8 uv_int_start
[] = {
526 0x03B, 0x03B, 0x052, 0x03B, 0x052, 0x03B, 0x052, 0x03C, 0x068 };
527 static const uint8 u_int_length
[] = {
528 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F };
529 static const uint8 v_int_length
[] = {
530 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F };
532 // set blank interrupt position
533 SetRegister(VIP_SG_BLACK_GATE
, BLANK_INT_START
, blank_int_start
[standard
] );
534 SetRegister(VIP_SG_BLACK_GATE
, BLANK_INT_LENGTH
, (uint32
)blank_int_length
[standard
] << 8);
536 SetRegister(VIP_SG_SYNCTIP_GATE
, SYNC_TIP_START
, sync_tip_start
[standard
]);
537 SetRegister(VIP_SG_SYNCTIP_GATE
, SYNC_TIP_LENGTH
, (uint32
)sync_tip_length
[standard
] << 12);
539 SetRegister(VIP_SG_UVGATE_GATE
, UV_INT_START
, uv_int_start
[standard
] << 0);
541 SetRegister(VIP_SG_UVGATE_GATE
, U_INT_LENGTH
, (uint32
)u_int_length
[standard
] << 8);
542 SetRegister(VIP_SG_UVGATE_GATE
, V_INT_LENGTH
, (uint32
)v_int_length
[standard
] << 12);
544 PRINT(("CTheater100::SetSyncGenerator(black=%d/%d, synctip=%d/%d, uvgate=%d/%d-%d)\n",
545 Register(VIP_SG_BLACK_GATE
, BLANK_INT_START
) >> 0,
546 Register(VIP_SG_BLACK_GATE
, BLANK_INT_LENGTH
) >> 8,
547 Register(VIP_SG_SYNCTIP_GATE
, SYNC_TIP_START
),
548 Register(VIP_SG_SYNCTIP_GATE
, SYNC_TIP_LENGTH
) >> 12,
549 Register(VIP_SG_UVGATE_GATE
, UV_INT_START
),
550 Register(VIP_SG_UVGATE_GATE
, U_INT_LENGTH
) >> 8,
551 Register(VIP_SG_UVGATE_GATE
, V_INT_LENGTH
) >> 12));
555 // setup input comb filter.
556 // this is really ugly but I cannot find a scheme
557 void CTheater100::SetCombFilter(theater_standard standard
, theater_source source
)
560 _3Tap_2D_adaptive_Comb
= 1, // composite
561 _2Tap_C_combed_Y_Sub
= 2,
562 _2Tap_C_combed_Y_combed
= 3,
563 _3Tap_C_combed_Y_Sub
= 4,
564 _3Tap_C_combed_Y_combed
= 5,
565 YC_mode_Comb_filter_off
= 6, // S-Video
566 YC_mode_2Tap_YV_filter
= 7,
567 YC_mode_3Tap_YV_filter
= 8
570 // make sure to keep bitfield in sync with register definition!
571 // we could define each component as an uint8, but this would waste space
572 // and would require an extra register-composition
581 comb_sumdiff0sel
: 1,
582 comb_sumdiff1sel
: 2,
613 comb_tap0length
: 16,
620 const comb_cntl0
*cntl0
;
621 const comb_cntl1
*cntl1
;
622 const comb_cntl2
*cntl2
;
623 const comb_line_length
*line_length
;
626 static const uint8 comb_types_ntsc_m
[] = {
627 _3Tap_2D_adaptive_Comb
,
628 _2Tap_C_combed_Y_Sub
,
629 _2Tap_C_combed_Y_combed
,
630 _3Tap_C_combed_Y_Sub
,
631 _3Tap_C_combed_Y_combed
,
632 YC_mode_Comb_filter_off
,
633 YC_mode_2Tap_YV_filter
,
634 YC_mode_3Tap_YV_filter
,
638 static const comb_cntl0 comb_cntl0_ntsc_m
[] = {
639 { 0x90, 0x80, 1, 1, 0, 2, 0, 1, 0, 1, 0, 0 },
640 { 0, 0, 1, 0, 3, 2, 0, 0, 0, 1, 0, 0 },
641 { 0, 0, 1, 0, 3, 2, 0, 0, 0, 1, 1, 0 },
642 { 0, 0, 1, 0, 1, 2, 0, 1, 0, 1, 0, 0 },
643 { 0, 0, 1, 0, 1, 2, 0, 1, 1, 1, 0, 0 },
644 { 0, 0, 0, 0, 5, 2, 0, 0, 0, 1, 2, 0 },
645 { 0, 0, 0, 0, 5, 2, 0, 0, 0, 1, 1, 0 },
646 { 0, 0, 0, 0, 5, 2, 0, 0, 1, 1, 0, 0 }
649 static const comb_cntl1 comb_cntl1_ntsc_m
[] = {
650 { 0, 0, 1, 0, 0, 0, 0 },
651 { 2, 0, 1, 0, 0, 0, 0 },
652 { 3, 0, 0, 0, 0, 0, 0 },
653 { 0, 0, 1, 0, 1, 0, 0 },
654 { 3, 0, 0, 0, 1, 0, 0 },
655 { 1, 0, 0, 0, 2, 0, 0 },
656 { 3, 0, 0, 0, 0, 0, 0 },
657 { 3, 0, 0, 0, 1, 0, 0 }
660 static const comb_cntl2 comb_cntl2_ntsc_m
[] = {
661 { 0x10, 0x10, 0x16, 0x16 },
662 { 0xFF, 0xFF, 0xFF, 0xFF },
663 { 0xFF, 0xFF, 0xFF, 0xFF },
664 { 0xFF, 0xFF, 0xFF, 0xFF },
665 { 0xFF, 0xFF, 0xFF, 0xFF },
666 { 0xFF, 0xFF, 0xFF, 0xFF },
667 { 0xFF, 0xFF, 0xFF, 0xFF },
668 { 0xFF, 0xFF, 0xFF, 0xFF }
671 static const comb_line_length comb_line_length_ntsc_m
[] = {
683 static const uint8 comb_types_ntsc_433
[] = {
684 _2Tap_C_combed_Y_Sub
,
685 _2Tap_C_combed_Y_combed
,
686 _3Tap_C_combed_Y_Sub
,
687 _3Tap_C_combed_Y_combed
,
688 YC_mode_Comb_filter_off
,
689 YC_mode_2Tap_YV_filter
,
690 YC_mode_3Tap_YV_filter
,
694 static const comb_cntl0 comb_cntl0_ntsc_433
[] = {
695 { 0, 0, 1, 0, 3, 2, 0, 0, 0, 1, 0, 0 },
696 { 0, 0, 1, 0, 3, 2, 0, 0, 0, 1, 1, 0 },
697 { 0, 0, 1, 0, 1, 2, 0, 1, 0, 1, 0, 0 },
698 { 0, 0, 1, 0, 1, 2, 0, 1, 1, 1, 0, 0 },
699 { 0, 0, 0, 0, 5, 2, 0, 0, 0, 1, 2, 0 },
700 { 0, 0, 0, 0, 5, 2, 0, 0, 0, 1, 1, 0 },
701 { 0, 0, 0, 0, 5, 2, 0, 0, 1, 1, 0, 0 }
704 static const comb_cntl1 comb_cntl1_ntsc_433
[] = {
705 { 2, 0, 1, 0, 0, 0, 0 },
706 { 3, 0, 0, 0, 0, 0, 0 },
707 { 0, 0, 1, 0, 1, 0, 0 },
708 { 3, 0, 0, 0, 1, 0, 0 },
709 { 1, 0, 0, 0, 2, 0, 0 },
710 { 3, 0, 0, 0, 0, 0, 0 },
711 { 3, 0, 0, 0, 1, 0, 0 }
714 static const comb_cntl2 comb_cntl2_ntsc_433
[] = {
715 { 0xFF, 0xFF, 0xFF, 0xFF },
716 { 0xFF, 0xFF, 0xFF, 0xFF },
717 { 0xFF, 0xFF, 0xFF, 0xFF },
718 { 0xFF, 0xFF, 0xFF, 0xFF },
719 { 0xFF, 0xFF, 0xFF, 0xFF },
720 { 0xFF, 0xFF, 0xFF, 0xFF },
721 { 0xFF, 0xFF, 0xFF, 0xFF }
724 static const comb_line_length comb_line_length_ntsc_433
[] = {
735 static const uint8 comb_types_pal_m
[] = {
736 _2Tap_C_combed_Y_Sub
,
737 YC_mode_2Tap_YV_filter
,
741 static const comb_cntl0 comb_cntl0_pal_m
[] = {
742 { 0, 0, 1, 0, 4, 0, 1, 2, 0, 0, 2, 0 },
743 { 0, 0, 1, 0, 5, 0, 1, 2, 0, 0, 2, 0 }
746 static const comb_cntl1 comb_cntl1_pal_m
[] = {
747 { 1, 0, 1, 1, 2, 0, 0 },
748 { 1, 0, 0, 1, 2, 0, 0 }
751 static const comb_cntl2 comb_cntl2_pal_m
[] = {
752 { 0xFF, 0xFF, 0xFF, 0xFF },
753 { 0xFF, 0xFF, 0xFF, 0xFF }
756 static const comb_line_length comb_line_length_pal_m
[] = {
762 static const uint8 comb_types_pal_n
[] = {
763 _3Tap_2D_adaptive_Comb
,
764 _2Tap_C_combed_Y_Sub
,
765 YC_mode_2Tap_YV_filter
,
769 static const comb_cntl0 comb_cntl0_pal_n
[] = {
770 { 0x90, 0x80, 1, 1, 0, 2, 0, 1, 0, 1, 0, 0 },
771 { 0, 0, 1, 0, 4, 0, 1, 2, 0, 0, 2, 0 },
772 { 0, 0, 1, 0, 5, 0, 1, 2, 0, 0, 2, 0 }
775 static const comb_cntl1 comb_cntl1_pal_n
[] = {
776 { 0, 0, 1, 0, 0, 0, 0 },
777 { 1, 0, 1, 1, 2, 0, 0 },
778 { 1, 0, 0, 1, 2, 0, 0 }
781 static const comb_cntl2 comb_cntl2_pal_n
[] = {
782 { 0x10, 0x10, 0x16, 0x16 },
783 { 0xFF, 0xFF, 0xFF, 0xFF },
784 { 0xFF, 0xFF, 0xFF, 0xFF }
787 static const comb_line_length comb_line_length_pal_n
[] = {
794 static const uint8 comb_types_pal_nc
[] = {
795 _3Tap_2D_adaptive_Comb
,
796 _2Tap_C_combed_Y_Sub
,
797 YC_mode_2Tap_YV_filter
,
801 // used to represent an N/A for easier copy'n'paste
804 static const comb_cntl0 comb_cntl0_pal_nc
[] = {
805 { 0x90, 0x80, 1, 1, 0, 2, 0, 1, 0, 1, 0, 0 },
806 { X
, X
, 1, 0, 4, 0, 1, 2, 0, 0, 2, 0 },
807 { X
, X
, 1, 0, 5, 0, 1, 2, X
, 0, 2, 0 }
810 static const comb_cntl1 comb_cntl1_pal_nc
[] = {
811 { 0, 0, 1, 0, 0, 0, 0 },
812 { 1, 0, 1, 1, 2, 0, 0 },
813 { 1, 0, 0, 1, 2, 0, 0 }
816 static const comb_cntl2 comb_cntl2_pal_nc
[] = {
817 { 0x10, 0x10, 0x16, 0x16 },
818 { 0xFF, 0xFF, 0xFF, 0xFF },
819 { 0xFF, 0xFF, 0xFF, 0xFF }
822 static const comb_line_length comb_line_length_pal_nc
[] = {
829 static const uint8 comb_types_pal
[] = {
830 _3Tap_2D_adaptive_Comb
,
831 _2Tap_C_combed_Y_Sub
,
832 YC_mode_2Tap_YV_filter
,
836 static const comb_cntl0 comb_cntl0_pal
[] = {
837 { 0x90, 0x80, 1, 1, 0, 2, 0, 1, 0, 1, 0, 0 },
838 { 0, 0, 1, 0, 4, 0, 1, 2, 0, 0, 2, 0 },
839 { 0, 0, 1, 0, 5, 0, 1, 2, X
, 0, 2, 0 }
842 static const comb_cntl1 comb_cntl1_pal
[] = {
843 { 0, 0, 1, 0, 0, 0, 0 },
844 { 1, 0, 1, 1, 2, 0, 0 },
845 { 1, 0, 0, 1, 2, 0, 0 }
848 static const comb_cntl2 comb_cntl2_pal
[] = {
850 { 0xFF, 0xFF, 0xFF, 0xFF },
851 { 0xFF, 0xFF, 0xFF, 0xFF }
854 static const comb_line_length comb_line_length_pal
[] = {
861 static const uint8 comb_types_pal_60
[] = {
862 _2Tap_C_combed_Y_Sub
,
863 YC_mode_2Tap_YV_filter
,
867 static const comb_cntl0 comb_cntl0_pal_60
[] = {
868 { 0, 0, 1, 0, 4, 0, 1, 2, 0, 0, 2, 0 },
869 { 0, 0, 1, 0, 5, 0, 1, 2, 0, 0, 2, 0 }
872 static const comb_cntl1 comb_cntl1_pal_60
[] = {
873 { 1, 0, 1, 1, 2, 0, 0 },
874 { 1, 0, 0, 1, 2, 0, 0 }
877 static const comb_cntl2 comb_cntl2_pal_60
[] = {
878 { 0xFF, 0xFF, 0xFF, 0xFF },
879 { 0xFF, 0xFF, 0xFF, 0xFF }
882 static const comb_line_length comb_line_length_pal_60
[] = {
888 static const uint8 comb_types_secam
[] = {
889 _2Tap_C_combed_Y_Sub
, // could be another type, spec is unclear here
890 YC_mode_2Tap_YV_filter
,
894 static const comb_cntl0 comb_cntl0_secam
[] = {
895 { X
, X
, 0, 0, 4, X
, X
, X
, X
, 2, 2, 1 },
896 { X
, X
, 0, 0, 5, X
, X
, X
, X
, 2, 2, X
}
899 static const comb_cntl1 comb_cntl1_secam
[] = {
900 { 1, 0, 1, 0, 2, 0, 0 },
901 { 1, X
, 0, 0, 2, 0, 0 }
904 static const comb_cntl2 comb_cntl2_secam
[] = {
905 { 0xFF, 0xFF, 0xFF, 0xFF },
906 { 0xFF, 0xFF, 0xFF, 0xFF }
909 static const comb_line_length comb_line_length_secam
[] = {
916 static const comb_settings comb_settings_list
[] = {
917 { comb_types_ntsc_m
, comb_cntl0_ntsc_m
, comb_cntl1_ntsc_m
, comb_cntl2_ntsc_m
, comb_line_length_ntsc_m
},
918 { comb_types_ntsc_m
, comb_cntl0_ntsc_m
, comb_cntl1_ntsc_m
, comb_cntl2_ntsc_m
, comb_line_length_ntsc_m
},
919 { comb_types_ntsc_433
, comb_cntl0_ntsc_433
, comb_cntl1_ntsc_433
, comb_cntl2_ntsc_433
, comb_line_length_ntsc_433
},
920 { comb_types_pal_m
, comb_cntl0_pal_m
, comb_cntl1_pal_m
, comb_cntl2_pal_m
, comb_line_length_pal_m
},
921 { comb_types_pal_n
, comb_cntl0_pal_n
, comb_cntl1_pal_n
, comb_cntl2_pal_n
, comb_line_length_pal_n
},
922 { comb_types_pal_nc
, comb_cntl0_pal_nc
, comb_cntl1_pal_nc
, comb_cntl2_pal_nc
, comb_line_length_pal_nc
},
923 { comb_types_pal
, comb_cntl0_pal
, comb_cntl1_pal
, comb_cntl2_pal
, comb_line_length_pal
},
924 { comb_types_pal_60
, comb_cntl0_pal_60
, comb_cntl1_pal_60
, comb_cntl2_pal_60
, comb_line_length_pal_60
},
925 { comb_types_secam
, comb_cntl0_secam
, comb_cntl1_secam
, comb_cntl2_secam
, comb_line_length_secam
}
928 int min_type
, max_type
, type
;
929 const comb_settings
*settings
;
932 PRINT(("CTheater100::SetCombFilter(%c, %c)\n", "NJ4MNCB6S"[standard
], "TCS"[source
]));
934 // I don't really understand what the different types mean;
935 // what is particularly strange is that many types are defined for few standards only
936 if( source
== C_THEATER_TUNER
|| source
== C_THEATER_COMPOSITE
) {
937 min_type
= _3Tap_2D_adaptive_Comb
;
938 max_type
= _3Tap_C_combed_Y_combed
;
940 min_type
= YC_mode_Comb_filter_off
;
941 max_type
= YC_mode_3Tap_YV_filter
;
944 settings
= &comb_settings_list
[standard
];
946 for( type
= min_type
; type
<= max_type
; ++type
) {
947 for( i
= 0; settings
->types
[i
]; ++i
) {
948 if( settings
->types
[i
] == type
)
952 if( settings
->types
[i
] != 0 )
956 if( type
> max_type
) {
957 PRINT(("CTheater100::SetCombFilter() - No settings for this standard and input type combination!!!\n"));
961 SetRegister(VIP_COMB_CNTL0
, *(const int32
*)(settings
->cntl0
+ i
));
962 SetRegister(VIP_COMB_CNTL1
, *(const int32
*)(settings
->cntl1
+ i
));
963 SetRegister(VIP_COMB_CNTL2
, *(const int32
*)(settings
->cntl2
+ i
));
964 SetRegister(VIP_COMB_LINE_LENGTH
, *(const int32
*)(settings
->line_length
+ i
));
967 // reset the comb filter
968 SetRegister(VIP_COMB_CNTL1
, Register(VIP_COMB_CNTL1
) ^ COMB_SYNCLPFRST
);
969 SetRegister(VIP_COMB_CNTL1
, Register(VIP_COMB_CNTL1
) ^ COMB_SYNCLPFRST
);
973 // setup luma processor
974 void CTheater100::SetLuminanceProcessor(theater_standard standard
)
976 static const uint16 synctip_ref0
[] = {
977 0x037, 0x037, 0x037, 0x037, 0x037, 0x037, 0x037, 0x037, 0x037 };
978 static const uint16 synctip_ref1
[] = {
979 0x029, 0x029, 0x029, 0x029, 0x029, 0x026, 0x026, 0x026, 0x026 };
980 static const uint16 clamp_ref
[] = {
981 0x03B, 0x03B, 0x03B, 0x03B, 0x03B, 0x03B, 0x03B, 0x03B, 0x03B };
982 static const uint16 agc_peakwhite
[] = {
983 0x0FF, 0x0FF, 0x0FF, 0x0FF, 0x0FF, 0x0FF, 0x0FF, 0x0FF, 0x0FF };
984 static const uint16 vbi_peakwhite
[] = {
985 0x0D2, 0x0D2, 0xD2, 0x0D2, 0x0D2, 0x0C6, 0x0C6, 0x0C6, 0x0C6 };
987 static const uint16 wpa_threshold
[] = {
988 0x406, 0x406, 0x4FC, 0x406, 0x59C, 0x488, 0x59C, 0x59C, 0x57A };
989 static const uint16 wpa_trigger_lo
[] = {
990 0x0B3, 0x0B3, 0x0B3, 0x0B3, 0x096, 0x096, 0x096, 0x0B3, 0x096 };
991 static const uint16 wpa_trigger_hi
[] = {
992 0x21B, 0x21B, 0x21B, 0x21B, 0x1C2, 0x1C2, 0x1C2, 0x21B, 0x1C2 };
993 static const uint16 lp_lockout_start
[] = {
994 0x206, 0x206, 0x206, 0x206, 0x263, 0x263, 0x263, 0x206, 0x263 };
995 // PAL: changed 0x2c to 0x0c; NTSC: changed 0x21 to 0x0b
996 static const uint16 lp_lockout_end
[] = {
997 0x00B, 0x00B, 0x00B, 0x00B, 0x00C, 0x00C, 0x00C, 0x00B, 0x00C };
999 PRINT(("CTheater100::SetLuminanceProcessor(%c)\n", "NJ4MNCB6S"[standard
]));
1001 SetRegister(VIP_LP_AGC_CLAMP_CNTL0
, SYNCTIP_REF0
, synctip_ref0
[standard
] << 0);
1002 SetRegister(VIP_LP_AGC_CLAMP_CNTL0
, SYNCTIP_REF1
, (uint32
)synctip_ref1
[standard
] << 8);
1003 SetRegister(VIP_LP_AGC_CLAMP_CNTL0
, CLAMP_REF
, (uint32
)clamp_ref
[standard
] << 16);
1004 SetRegister(VIP_LP_AGC_CLAMP_CNTL0
, AGC_PEAKWHITE
, (uint32
)agc_peakwhite
[standard
] << 24);
1005 SetRegister(VIP_LP_AGC_CLAMP_CNTL1
, VBI_PEAKWHITE
, (uint32
)vbi_peakwhite
[standard
] << 0);
1007 SetRegister(VIP_LP_WPA_CNTL0
, WPA_THRESHOLD
, wpa_threshold
[standard
] << 0);
1008 SetRegister(VIP_LP_WPA_CNTL1
, WPA_TRIGGER_LO
, wpa_trigger_lo
[standard
] << 0);
1009 SetRegister(VIP_LP_WPA_CNTL1
, WPA_TRIGGER_HI
, (uint32
)wpa_trigger_hi
[standard
] << 16);
1010 SetRegister(VIP_LP_VERT_LOCKOUT
, LP_LOCKOUT_START
, lp_lockout_start
[standard
] << 0);
1011 SetRegister(VIP_LP_VERT_LOCKOUT
, LP_LOCKOUT_END
, (uint32
)lp_lockout_end
[standard
] << 16);
1015 // setup brightness and contrast
1016 void CTheater100::SetLuminanceLevels(theater_standard standard
, int brightness
, int contrast
)
1018 double ref0
, setup
, gain
;
1020 ref0
= Register(VIP_LP_AGC_CLAMP_CNTL0
, SYNCTIP_REF0
);
1023 case C_THEATER_NTSC
:
1024 case C_THEATER_PAL_M
:
1025 case C_THEATER_NTSC_443
:
1026 setup
= 7.5 * ref0
/ 40.0;
1027 gain
= 219.0 / (92.5 * ref0
/ 40.0);
1030 case C_THEATER_NTSC_JAPAN
:
1032 gain
= 219.0 / (100.0 * ref0
/ 40.0);
1035 case C_THEATER_PAL_BDGHI
:
1036 case C_THEATER_PAL_N
:
1037 case C_THEATER_SECAM
:
1038 case C_THEATER_PAL_60
:
1039 case C_THEATER_PAL_NC
:
1041 gain
= 219.0 / (100.0 * ref0
/ 43.0);
1050 if (contrast
<= -100)
1053 /* set luminance processor constrast (7:0) */
1054 SetRegister(VIP_LP_CONTRAST
, CONTRAST
,
1055 int(64.0 * ((contrast
+ 100) / 100.0) * gain
) << 0);
1057 /* set luminance processor brightness (13:0) */
1058 SetRegister(VIP_LP_BRIGHTNESS
, BRIGHTNESS
,
1059 int(16.0 * ((brightness
- setup
) + 16.0 / ((contrast
+ 100) * gain
/ 100.0))) & BRIGHTNESS
);
1063 // setup chroma demodulator
1064 void CTheater100::SetChromaProcessor(theater_standard standard
)
1066 PRINT(("CTheater100::SetChromaProcessor(%c)\n", "NJ4MNCB6S"[standard
]));
1068 static const uint32 ch_dto_inc
[] = {
1069 0x400000, 0x400000, 0x400000, 0x400000, 0x400000, 0x400000, 0x400000, 0x400000, 0x3E7A28 };
1070 static const uint8 ch_pll_sgain
[] = {
1071 1, 1, 1, 1, 1, 1, 1, 1, 5 };
1072 static const uint8 ch_pll_fgain
[] = {
1073 2, 2, 2, 2, 2, 2, 2, 2, 6 };
1075 static const uint8 ch_height
[] = {
1076 0xCD, 0xCD, 0xCD, 0x91, 0x91, 0x9C, 0x9C, 0x9C, 0x66 };
1077 static const uint8 ch_kill_level
[] = {
1078 0x0C0, 0xC0, 0xC0, 0x8C, 0x8C, 0x90, 0x90, 0x90, 0x60 };
1079 static const uint8 ch_agc_error_lim
[] = {
1080 2, 2, 2, 2, 2, 2, 2, 2, 3 };
1081 static const uint8 ch_agc_filter_en
[] = {
1082 0, 0, 0, 0, 0, 0, 1, 0, 0 };
1083 static const uint8 ch_agc_loop_speed
[] = {
1084 0, 0, 0, 0, 0, 0, 0, 0, 0 };
1086 static const uint16 cr_burst_gain
[] = {
1087 0x7A, 0x71, 0x7A, 0x7A, 0x7A, 0x7A, 0x7A, 0x7A, 0x1FF };
1088 static const uint16 cb_burst_gain
[] = {
1089 0xAC, 0x9F, 0xAC, 0xAC, 0xAC, 0xAB, 0xAB, 0xAB, 0x1FF };
1090 static const uint16 crdr_active_gain
[] = {
1091 0x7A, 0x71, 0x7A, 0x7A, 0x7A, 0x7A, 0x7A, 0x7A, 0x11C };
1092 static const uint16 cbdb_active_gain
[] = {
1093 0xAC, 0x9F, 0xAC, 0xAC, 0xAC, 0xAB, 0xAB, 0xAB, 0x15A };
1094 static const uint16 cp_vert_lockout_start
[] = {
1095 0x207, 0x207, 0x207, 0x207, 0x269, 0x269, 0x269, 0x207, 0x269 };
1096 static const uint8 cp_vert_lockout_end
[] = {
1097 0x00E, 0x00E, 0x00E, 0x00E, 0x00E, 0x012, 0x012, 0x00E, 0x012 };
1099 SetRegister(VIP_CP_PLL_CNTL0
, CH_DTO_INC
, ch_dto_inc
[standard
] << 0);
1100 SetRegister(VIP_CP_PLL_CNTL0
, CH_PLL_SGAIN
, (uint32
)ch_pll_sgain
[standard
] << 24);
1101 SetRegister(VIP_CP_PLL_CNTL0
, CH_PLL_FGAIN
, (uint32
)ch_pll_fgain
[standard
] << 28);
1103 SetRegister(VIP_CP_AGC_CNTL
, CH_HEIGHT
, ch_height
[standard
] << 0);
1104 SetRegister(VIP_CP_AGC_CNTL
, CH_KILL_LEVEL
, (uint32
)ch_kill_level
[standard
] << 8);
1105 SetRegister(VIP_CP_AGC_CNTL
, CH_AGC_ERROR_LIM
, (uint32
)ch_agc_error_lim
[standard
] << 16);
1106 SetRegister(VIP_CP_AGC_CNTL
, CH_AGC_FILTER_EN
, (uint32
)ch_agc_filter_en
[standard
] << 18);
1107 SetRegister(VIP_CP_AGC_CNTL
, CH_AGC_LOOP_SPEED
, (uint32
)ch_agc_loop_speed
[standard
] << 19);
1109 SetRegister(VIP_CP_BURST_GAIN
, CR_BURST_GAIN
, cr_burst_gain
[standard
] << 0);
1110 SetRegister(VIP_CP_BURST_GAIN
, CB_BURST_GAIN
, (uint32
)cb_burst_gain
[standard
] << 16);
1112 SetRegister(VIP_CP_ACTIVE_GAIN
, CRDR_ACTIVE_GAIN
, crdr_active_gain
[standard
] << 0);
1113 SetRegister(VIP_CP_ACTIVE_GAIN
, CBDB_ACTIVE_GAIN
, (uint32
)cbdb_active_gain
[standard
] << 16);
1115 SetRegister(VIP_CP_VERT_LOCKOUT
, CP_LOCKOUT_START
, cp_vert_lockout_start
[standard
] << 0);
1116 SetRegister(VIP_CP_VERT_LOCKOUT
, CP_LOCKOUT_END
, (uint32
)cp_vert_lockout_end
[standard
] << 16);
1120 // set colour saturation and hue.
1121 // hue makes sense for NTSC only and seems to act as saturation for PAL
1122 void CTheater100::SetChromaLevels(theater_standard standard
, int saturation
, int hue
)
1125 double gain
, CRgain
, CBgain
;
1127 /* compute Cr/Cb gains */
1128 ref0
= Register(VIP_LP_AGC_CLAMP_CNTL0
, SYNCTIP_REF0
);
1131 case C_THEATER_NTSC
:
1132 case C_THEATER_NTSC_443
:
1133 case C_THEATER_PAL_M
:
1134 CRgain
= (40.0 / ref0
) * (100.0 / 92.5) * (1.0 / 0.877) * (112.0 / 70.1) / 1.5;
1135 CBgain
= (40.0 / ref0
) * (100.0 / 92.5) * (1.0 / 0.492) * (112.0 / 88.6) / 1.5;
1138 case C_THEATER_NTSC_JAPAN
:
1139 CRgain
= (40.0 / ref0
) * (100.0 / 100.0) * (1.0 / 0.877) * (112.0 / 70.1) / 1.5;
1140 CBgain
= (40.0 / ref0
) * (100.0 / 100.0) * (1.0 / 0.492) * (112.0 / 88.6) / 1.5;
1143 case C_THEATER_PAL_BDGHI
:
1144 case C_THEATER_PAL_60
:
1145 case C_THEATER_PAL_NC
:
1146 case C_THEATER_PAL_N
:
1147 CRgain
= (43.0 / ref0
) * (100.0 / 92.5) * (1.0 / 0.877) * (112.0 / 70.1) / 1.5;
1148 CBgain
= (43.0 / ref0
) * (100.0 / 92.5) * (1.0 / 0.492) * (112.0 / 88.6) / 1.5;
1151 case C_THEATER_SECAM
:
1152 CRgain
= 32.0 * 32768.0 / 280000.0 / (33554432.0 / 35.46985) * (1.597 / 1.902) / 1.5;
1153 CBgain
= 32.0 * 32768.0 / 230000.0 / (33554432.0 / 35.46985) * (1.267 / 1.505) / 1.5;
1157 PRINT(("CTheater100::SetChromaLevels() - Bad standard\n"));
1163 if (saturation
>= 0)
1164 gain
= 1.0 + 4.9 * saturation
/ 100.0;
1166 gain
= 1.0 + saturation
/ 100.0;
1168 SetRegister(VIP_CP_ACTIVE_GAIN
, CRDR_ACTIVE_GAIN
, int(128 * CRgain
* gain
) << 0);
1169 SetRegister(VIP_CP_ACTIVE_GAIN
, CBDB_ACTIVE_GAIN
, int(128 * CBgain
* gain
) << 16);
1172 hue
= (256 * hue
) / 360;
1174 hue
= (256 * (hue
+ 360)) / 360;
1176 SetRegister(VIP_CP_HUE_CNTL
, HUE_ADJ
, hue
<< 0);
1180 // these values are used by scaler as well
1181 static const uint16 h_active_start
[] = {
1182 0x06b, 0x06B, 0x07E, 0x067, 0x09A, 0x07D, 0x09A, 0x084, 0x095 };
1183 static const uint16 h_active_end
[] = {
1184 0x363, 0x363, 0x42A, 0x363, 0x439, 0x439, 0x439, 0x363, 0x439 };
1185 static const uint16 v_active_start
[] = {
1186 0x025, 0x025, 0x025, 0x025, 0x02E, 0x02E, 0x02E, 0x025, 0x02E };
1187 // PAL height is too small (572 instead of 576 lines), but changing 0x269 to 0x26d
1188 // leads to trouble, and the last 2 lines seem to be used for VBI data
1189 // (read: garbage) anyway
1190 static const uint16 v_active_end
[] = {
1191 0x204, 0x204, 0x204, 0x204, 0x269, 0x269, 0x269, 0x204, 0x269 };
1192 static const uint16 h_vbi_wind_start
[] = {
1193 0x064, 0x064, 0x064, 0x064, 0x084, 0x084, 0x084, 0x064, 0x084 };
1194 static const uint16 h_vbi_wind_end
[] = {
1195 0x366, 0x366, 0x366, 0x366, 0x41F, 0x41F, 0x41F, 0x366, 0x41F };
1196 static const uint16 v_vbi_wind_start
[] = {
1197 0x00b, 0x00b, 0x00b, 0x00b, 0x008, 0x008, 0x008, 0x00b, 0x008 };
1198 static const uint16 v_vbi_wind_end
[] = {
1199 0x024, 0x024, 0x024, 0x024, 0x02d, 0x02d, 0x02d, 0x024, 0x02d };
1201 void CTheater100::getActiveRange( theater_standard standard
, CRadeonRect
&rect
)
1204 h_active_start
[standard
], v_active_start
[standard
],
1205 h_active_end
[standard
], v_active_end
[standard
] );
1208 void CTheater100::getVBIRange( theater_standard standard
, CRadeonRect
&rect
)
1211 h_vbi_wind_start
[standard
], v_vbi_wind_start
[standard
],
1212 h_vbi_wind_end
[standard
], v_vbi_wind_end
[standard
] );
1215 // program clipping engine
1216 void CTheater100::SetClipWindow(theater_standard standard
, bool vbi
)
1218 // set horizontal active window
1219 SetRegister(VIP_H_ACTIVE_WINDOW
, H_ACTIVE_START
, h_active_start
[standard
] << 0);
1220 SetRegister(VIP_H_ACTIVE_WINDOW
, H_ACTIVE_END
, (uint32
)h_active_end
[standard
] << 16);
1222 // set vertical active window
1223 SetRegister(VIP_V_ACTIVE_WINDOW
, V_ACTIVE_START
, v_active_start
[standard
] << 0);
1224 SetRegister(VIP_V_ACTIVE_WINDOW
, V_ACTIVE_END
, (uint32
)v_active_end
[standard
] << 16);
1226 // set horizontal VBI window
1227 SetRegister(VIP_H_VBI_WINDOW
, H_VBI_WIND_START
, h_vbi_wind_start
[standard
] << 0);
1228 SetRegister(VIP_H_VBI_WINDOW
, H_VBI_WIND_END
, (uint32
)h_vbi_wind_end
[standard
] << 16);
1230 // set vertical VBI window
1231 SetRegister(VIP_V_VBI_WINDOW
, V_VBI_WIND_START
, v_vbi_wind_start
[standard
] << 0);
1232 SetRegister(VIP_V_VBI_WINDOW
, V_VBI_WIND_END
, (uint32
)v_vbi_wind_end
[standard
] << 16);
1234 // set VBI scaler control
1235 SetRegister(VIP_VBI_SCALER_CONTROL
, (1 << 16) & VBI_SCALING_RATIO
);
1237 // enable/disable VBI capture
1238 SetRegister(VIP_VBI_CONTROL
, VBI_CAPTURE_ENABLE
,
1239 vbi
? VBI_CAPTURE_EN
: VBI_CAPTURE_DIS
);
1241 PRINT(("CTheater100::SetClipWindow(active=%d/%d/%d/%d, vbi=%d/%d/%d/%d)\n",
1242 Register(VIP_H_ACTIVE_WINDOW
, H_ACTIVE_START
) >> 0,
1243 Register(VIP_H_ACTIVE_WINDOW
, H_ACTIVE_END
) >> 16,
1244 Register(VIP_V_ACTIVE_WINDOW
, V_ACTIVE_START
) >> 0,
1245 Register(VIP_V_ACTIVE_WINDOW
, V_ACTIVE_END
) >> 16,
1246 Register(VIP_H_VBI_WINDOW
, H_VBI_WIND_START
) >> 0,
1247 Register(VIP_H_VBI_WINDOW
, H_VBI_WIND_END
) >> 16,
1248 Register(VIP_V_VBI_WINDOW
, V_VBI_WIND_START
) >> 0,
1249 Register(VIP_V_VBI_WINDOW
, V_VBI_WIND_END
) >> 16));
1254 // setup capture scaler.
1255 void CTheater100::SetScaler(theater_standard standard
, int hactive
, int vactive
, bool deinterlace
)
1257 int oddOffset
, evenOffset
;
1258 uint16 h_active_width
, v_active_height
;
1260 // ASSERT(vactive <= 511);
1262 // TK: Gatos uses different values here
1263 h_active_width
= h_active_end
[standard
] - h_active_start
[standard
] + 1;
1264 v_active_height
= v_active_end
[standard
] - v_active_start
[standard
] + 1;
1266 // for PAL, we have 572 lines only, but need 576 lines;
1267 // my attempts to find those missing lines all failed, so if the application requests
1268 // 576 lines, we had to upscale the video which is not supported by hardware;
1269 // solution: restrict to 572 lines - the scaler will fill out the missing lines with black
1270 if( vactive
> v_active_height
)
1271 vactive
= v_active_height
;
1275 evenOffset
= oddOffset
= 512 - (int) ((512 * vactive
) / v_active_height
);
1279 evenOffset
= (int) ((512 * vactive
) / v_active_height
);
1280 oddOffset
= 2048 - evenOffset
;
1283 // set scale input window
1284 SetRegister(VIP_SCALER_IN_WINDOW
, H_IN_WIND_START
, h_active_start
[standard
] << 0);
1285 SetRegister(VIP_SCALER_IN_WINDOW
, V_IN_WIND_START
, (uint32
)v_active_start
[standard
] << 16);
1287 SetRegister(VIP_SCALER_OUT_WINDOW
, H_OUT_WIND_WIDTH
, hactive
<< 0);
1288 SetRegister(VIP_SCALER_OUT_WINDOW
, V_OUT_WIND_HEIGHT
, (vactive
/ 2) << 16);
1290 SetRegister(VIP_H_SCALER_CONTROL
, H_SCALE_RATIO
, (((uint32
)h_active_width
<< 16) / hactive
) << 0);
1291 SetRegister(VIP_V_SCALER_CONTROL
, V_SCALE_RATIO
, ((vactive
<< 11) / v_active_height
) << 0);
1293 // enable horizontal and vertical scaler
1294 SetRegister(VIP_H_SCALER_CONTROL
, H_BYPASS
,
1295 h_active_width
== hactive
? H_BYPASS
: 0);
1296 SetRegister(VIP_V_SCALER_CONTROL
, V_BYPASS
,
1297 v_active_height
== vactive
? V_BYPASS
: 0);
1299 // set deinterlace control
1300 SetRegister(VIP_V_SCALER_CONTROL
, V_DEINTERLACE_ON
, deinterlace
? V_DEINTERLACE_ON
: 0);
1301 SetRegister(VIP_V_DEINTERLACE_CONTROL
, EVENF_OFFSET
, evenOffset
<< 0);
1302 SetRegister(VIP_V_DEINTERLACE_CONTROL
, ODDF_OFFSET
, oddOffset
<< 11);
1304 SetRegister(VIP_V_SCALER_CONTROL
, V_DEINTERLACE_ON
, deinterlace
? V_DEINTERLACE_ON
: 0);
1306 PRINT(("CTheater100::SetScaler(active=%d/%d/%d/%d, scale=%d/%d)\n",
1307 Register(VIP_SCALER_IN_WINDOW
, H_IN_WIND_START
) >> 0,
1308 Register(VIP_SCALER_IN_WINDOW
, V_IN_WIND_START
) >> 16,
1310 Register(VIP_H_SCALER_CONTROL
, H_SCALE_RATIO
),
1311 Register(VIP_V_SCALER_CONTROL
, V_SCALE_RATIO
)));
1314 int CTheater100::CurrentLine()
1316 return Register(VIP_VS_LINE_COUNT
) & VS_LINE_COUNT
;
1319 void CTheater100::PrintToStream()
1321 PRINT(("<<< Rage Theater Registers >>>\n"));
1322 for (int index
= 0x0400; index
<= 0x06ff; index
+= 4) {
1323 int value
= Register(index
);
1324 value
= value
; // unused var if debug is off
1325 PRINT(("REG_0x%04x = 0x%08x\n", index
, value
));