1 /****************************************************************************** 2 / 3 / File: Theater.cpp 4 / 5 / Description: ATI Rage Theater Video Decoder interface. 6 / 7 / Copyright 2001, Carlos Hasan 8 / 9 *******************************************************************************/ 10 11 #include <Debug.h> 12 #include "Theater100.h" 13 #include "Theater.h" 14 #include "TheatreReg.h" 15 #include "lendian_bitfield.h" 16 17 CTheater100::CTheater100(CRadeon & radeon, int device) 18 :CTheater(radeon, device) 19 { 20 PRINT(("CTheater100::CTheater100()\n")); 21 22 if( fPort.InitCheck() == B_OK ) { 23 radeon_video_tuner tuner; 24 radeon_video_decoder video; 25 26 radeon.GetMMParameters(tuner, video, fClock, 27 fTunerPort, fCompositePort, fSVideoPort); 28 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")); 32 33 //fDevice = fPort.FindVIPDevice( C_THEATER100_VIP_DEVICE_ID ); 34 35 } 36 37 if( InitCheck() != B_OK ) 38 PRINT(("CTheater100::CTheater100() - Rage Theater not found!\n")); 39 } 40 41 CTheater100::~CTheater100() 42 { 43 PRINT(("CTheater100::~CTheater100()\n")); 44 45 if( InitCheck() == B_OK ) 46 SetEnable(false, false); 47 } 48 49 status_t CTheater100::InitCheck() const 50 { 51 status_t res; 52 53 res = fPort.InitCheck(); 54 if( res != B_OK ) 55 return res; 56 57 return (fDevice >= C_VIP_PORT_DEVICE_0 && fDevice <= C_VIP_PORT_DEVICE_3) ? B_OK : B_ERROR; 58 } 59 60 void CTheater100::Reset() 61 { 62 PRINT(("CTheater100::Reset()\n")); 63 64 SetHue(0); 65 SetBrightness(0); 66 SetSaturation(0); 67 SetContrast(0); 68 SetSharpness(false); 69 } 70 71 // disable/enable capturing 72 void CTheater100::SetEnable(bool enable, bool vbi) 73 { 74 PRINT(("CTheater100::SetEnable(%d, %d)\n", enable, vbi)); 75 76 #if 0 77 //@ reset ADC? 78 SetRegister(VIP_ADC_CNTL, ADC_CPRESET, ADC_CPRESET); 79 snooze(1000); 80 SetRegister(VIP_ADC_CNTL, ADC_CPRESET, 0); 81 snooze(1000); 82 SetRegister(VIP_ADC_CNTL, ADC_PDWN, ADC_PDWN_DOWN); 83 #endif 84 85 86 WaitVSYNC(); 87 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); 91 92 /* select the reference clock for the Video In */ 93 SetRegister(VIP_CLOCK_SEL_CNTL, VIN_CLK_SEL, VIN_CLK_SEL_REF_CLK); 94 95 /* reset the VIN/L54 PLL clocks */ 96 SetRegister(VIP_PLL_CNTL1, VINRST, VINRST); 97 SetRegister(VIP_PLL_CNTL1, L54RST, L54RST); 98 99 /* power down the ADC block */ 100 SetRegister(VIP_ADC_CNTL, ADC_PDWN, ADC_PDWN); 101 102 /* set DVS port to input mode */ 103 SetRegister(VIP_DVS_PORT_CTRL, DVS_DIRECTION, DVS_DIRECTION_INPUT); 104 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); 108 109 if (enable) { 110 WaitVSYNC(); 111 112 SetClock(fStandard, fClock); 113 SetADC(fStandard, fSource); 114 SetLuminanceProcessor(fStandard); 115 SetChromaProcessor(fStandard); 116 SetVSYNC(fStandard); 117 SetClipWindow(fStandard, vbi); 118 SetCombFilter(fStandard, fSource); 119 SetHSYNC(fStandard); 120 SetSyncGenerator(fStandard); 121 SetScaler(fStandard, fHActive, fVActive, fDeinterlace); 122 123 /* Enable ADC block */ 124 SetRegister(VIP_ADC_CNTL, ADC_PDWN, ADC_PDWN_UP); 125 126 WaitVSYNC(); 127 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); 131 132 /* set DVS port to output mode */ 133 SetRegister(VIP_DVS_PORT_CTRL, DVS_DIRECTION, DVS_DIRECTION_OUTPUT); 134 135 //WaitHSYNC(); 136 137 /* restore luminance and chroma settings */ 138 SetLuminanceLevels(fStandard, fBrightness, fContrast); 139 SetChromaLevels(fStandard, fSaturation, fHue); 140 } 141 } 142 143 void CTheater100::SetStandard(theater_standard standard, theater_source source) 144 { 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)); 150 151 fStandard = standard; 152 fSource = source; 153 } 154 155 void CTheater100::SetSize(int hactive, int vactive) 156 { 157 PRINT(("CTheater100::SetSize(%d, %d)\n", hactive, vactive)); 158 159 fHActive = hactive; 160 fVActive = vactive; 161 } 162 163 void CTheater100::SetDeinterlace(bool deinterlace) 164 { 165 PRINT(("CTheater100::SetDeinterlace(%d)\n", deinterlace)); 166 167 fDeinterlace = deinterlace; 168 } 169 170 void CTheater100::SetSharpness(int sharpness) 171 { 172 PRINT(("CTheater100::SetSharpness(%d)\n", sharpness)); 173 174 SetRegister(VIP_H_SCALER_CONTROL, H_SHARPNESS, sharpness << 25); 175 } 176 177 void CTheater100::SetBrightness(int brightness) 178 { 179 PRINT(("CTheater100::SetBrightness(%d)\n", brightness)); 180 181 fBrightness = brightness; 182 SetLuminanceLevels(fStandard, fBrightness, fContrast); 183 } 184 185 void CTheater100::SetContrast(int contrast) 186 { 187 PRINT(("CTheater100::SetContrast(%d)\n", contrast)); 188 189 fContrast = contrast; 190 SetLuminanceLevels(fStandard, fBrightness, fContrast); 191 } 192 193 void CTheater100::SetSaturation(int saturation) 194 { 195 PRINT(("CTheater100::SetSaturation(%d)\n", saturation)); 196 197 fSaturation = saturation; 198 SetChromaLevels(fStandard, fSaturation, fHue); 199 } 200 201 void CTheater100::SetHue(int hue) 202 { 203 PRINT(("CTheater100::SetHue(%d)\n", hue)); 204 205 fHue = hue; 206 SetChromaLevels(fStandard, fSaturation, fHue); 207 } 208 209 210 // set pixel clock 211 void CTheater100::SetClock(theater_standard standard, radeon_video_clock clock) 212 { 213 // set VIN PLL clock dividers 214 int referenceDivider, feedbackDivider, postDivider; 215 216 switch (standard) { 217 case C_THEATER_NTSC: 218 case C_THEATER_NTSC_JAPAN: 219 if (clock == C_RADEON_VIDEO_CLOCK_29_49892_MHZ) { 220 referenceDivider = 0x39; 221 feedbackDivider = 0x14c; 222 postDivider = 0x6; 223 } 224 else { 225 referenceDivider = 0x0b; 226 feedbackDivider = 0x46; 227 postDivider = 0x6; 228 } 229 break; 230 case C_THEATER_NTSC_443: 231 if (clock == C_RADEON_VIDEO_CLOCK_29_49892_MHZ) { 232 referenceDivider = 0x23; 233 feedbackDivider = 0x88; 234 postDivider = 0x7; 235 } 236 else { 237 referenceDivider = 0x2c; 238 feedbackDivider = 0x121; 239 postDivider = 0x5; 240 } 241 break; 242 case C_THEATER_PAL_M: 243 if (clock == C_RADEON_VIDEO_CLOCK_29_49892_MHZ) { 244 referenceDivider = 0x2c; 245 feedbackDivider = 0x12b; 246 postDivider = 0x7; 247 } 248 else { 249 referenceDivider = 0x0b; 250 feedbackDivider = 0x46; 251 postDivider = 0x6; 252 } 253 break; 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; 261 postDivider = 0x6; 262 } 263 else { 264 referenceDivider = 0x2c; 265 feedbackDivider = 0x121; 266 postDivider = 0x5; 267 } 268 break; 269 case C_THEATER_PAL_NC: 270 if (clock == C_RADEON_VIDEO_CLOCK_29_49892_MHZ) { 271 referenceDivider = 0x23; 272 feedbackDivider = 0x88; 273 postDivider = 0x7; 274 } 275 else { 276 referenceDivider = 0x37; 277 feedbackDivider = 0x1d3; 278 postDivider = 0x8; 279 } 280 break; 281 default: 282 PRINT(("CTheater100::SetClock() - Bad standard\n")); 283 return; 284 } 285 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); 290 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); 295 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); 300 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))); 304 } 305 306 307 // setup analog-digital converter 308 void CTheater100::SetADC(theater_standard standard, theater_source source) 309 { 310 PRINT(("CTheater100::SetADC(%c, %c)\n", "NJ4MNCB6S"[standard], "TCS"[source])); 311 312 // set HW_DEBUG before setting the standard 313 SetRegister(VIP_HW_DEBUG, 0x0000f000); 314 315 // select the video standard 316 switch (standard) { 317 case C_THEATER_NTSC: 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); 322 break; 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); 328 break; 329 case C_THEATER_SECAM: 330 SetRegister(VIP_STANDARD_SELECT, STANDARD_SEL, STANDARD_SECAM); 331 break; 332 default: 333 PRINT(("CTheater100::SetADC() - Bad standard\n")); 334 return; 335 } 336 337 // select input connector and Y/C mode 338 switch (source) { 339 case C_THEATER_TUNER: 340 SetRegister(VIP_ADC_CNTL, INPUT_SELECT, fTunerPort); 341 SetRegister(VIP_STANDARD_SELECT, YC_MODE, YC_MODE_COMPOSITE); 342 break; 343 case C_THEATER_COMPOSITE: 344 SetRegister(VIP_ADC_CNTL, INPUT_SELECT, fCompositePort); 345 SetRegister(VIP_STANDARD_SELECT, YC_MODE, YC_MODE_COMPOSITE); 346 break; 347 case C_THEATER_SVIDEO: 348 SetRegister(VIP_ADC_CNTL, INPUT_SELECT, fSVideoPort); 349 SetRegister(VIP_STANDARD_SELECT, YC_MODE, YC_MODE_SVIDEO); 350 break; 351 default: 352 PRINT(("CTheater100::SetADC() - Bad source\n")); 353 return; 354 } 355 356 SetRegister(VIP_ADC_CNTL, I_CLAMP_SEL, I_CLAMP_SEL_22); 357 SetRegister(VIP_ADC_CNTL, I_AGC_SEL, I_AGC_SEL_7); 358 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); 366 switch (standard) { 367 case C_THEATER_NTSC: 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); 372 break; 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); 379 break; 380 } 381 SetRegister(VIP_ADC_CNTL, ADC_PAICM, 1 << 18); 382 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); 386 387 SetRegister(VIP_ADC_CNTL, ADC_IMUXOFF, 0 << 26); 388 SetRegister(VIP_ADC_CNTL, ADC_CPRESET, 0 << 27); 389 } 390 391 392 // setup horizontal sync PLL 393 void CTheater100::SetHSYNC(theater_standard standard) 394 { 395 static const uint16 hs_line_total[] = { 396 0x38E, 0x38E, 0x46F, 0x38D, 0x46F, 0x395, 0x46F, 0x467, 0x46F }; 397 398 static const uint32 hs_dto_inc[] = { 399 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x3E7A2 }; 400 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 }; 406 407 static const uint8 gen_lock_delay[] = { 408 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10 }; 409 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 }; 414 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 }; 419 420 421 // set number of samples per line 422 SetRegister(VIP_HS_PLINE, HS_LINE_TOTAL, hs_line_total[standard]); 423 424 SetRegister(VIP_HS_DTOINC, HS_DTO_INC, hs_dto_inc[standard]); 425 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); 428 429 SetRegister(VIP_HS_GENLOCKDELAY, GEN_LOCK_DELAY, gen_lock_delay[standard]); 430 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); 434 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); 437 438 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)); 445 } 446 447 448 // wait until horizontal scaler is locked 449 void CTheater100::WaitHSYNC() 450 { 451 for (int timeout = 0; timeout < 1000; timeout++) { 452 if (Register(VIP_HS_PULSE_WIDTH, HS_GENLOCKED) != 0) 453 return; 454 snooze(20); 455 } 456 PRINT(("CTheater100::WaitHSYNC() - wait for HSync locking time out!\n")); 457 } 458 459 460 // setup vertical sync and field detector 461 void CTheater100::SetVSYNC(theater_standard standard) 462 { 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 }; 479 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); 482 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]); 486 487 SetRegister(VIP_VS_FIELD_ID_CNTL, VS_FIELD_ID_LOCATION, vs_field_id_location[standard] << 0); 488 489 // auto-detect fields 490 SetRegister(VIP_VS_COUNTER_CNTL, FIELD_DETECT_MODE, FIELD_DETECT_DETECTED); 491 492 // don't flip fields 493 SetRegister(VIP_VS_COUNTER_CNTL, FIELD_FLIP_EN, 0 ); 494 495 PRINT(("CTheater100::SetVSYNC(total=%d)\n", 496 Register(VIP_VS_FRAME_TOTAL, VS_FRAME_TOTAL))); 497 } 498 499 // wait until a visible line is viewed 500 void CTheater100::WaitVSYNC() 501 { 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) 505 return; 506 snooze(20); 507 } 508 PRINT(("CTheater100::WaitVSYNC() - wait for VBI timed out!\n")); 509 } 510 511 512 // setup timing generator 513 void CTheater100::SetSyncGenerator(theater_standard standard) 514 { 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 }; 519 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 }; 524 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 }; 531 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); 535 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); 538 539 SetRegister(VIP_SG_UVGATE_GATE, UV_INT_START, uv_int_start[standard] << 0); 540 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); 543 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)); 552 } 553 554 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) 558 { 559 enum { 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 568 }; 569 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 573 typedef struct { 574 LBITFIELD32_12 ( 575 comb_hck : 8, 576 comb_vck : 8, 577 comb_filter_en : 1, 578 comb_adaptiv_en : 1, 579 comb_bpfmuxsel : 3, 580 comb_coutsel : 2, 581 comb_sumdiff0sel : 1, 582 comb_sumdiff1sel : 2, 583 comb_yvlpfsel : 1, 584 comb_dlylinesel : 2, 585 comb_ydlyinsel : 2, 586 comb_ysubbw : 1 587 ); 588 } comb_cntl0; 589 590 typedef struct { 591 LBITFIELD32_7 ( 592 comb_ydlyoutsel : 2, 593 comb_coresize : 2, 594 comb_ysuben : 1, 595 comb_youtsel : 1, 596 comb_syncpfsel : 2, 597 comb_synclpfrst : 1, 598 comb_debug : 1 599 ); 600 } comb_cntl1; 601 602 typedef struct { 603 LBITFIELD32_4 ( 604 comb_hyk0 : 8, 605 comb_vyk0 : 8, 606 comb_hyk1 : 8, 607 comb_vyk1 : 8 608 ); 609 } comb_cntl2; 610 611 typedef struct { 612 LBITFIELD32_2 ( 613 comb_tap0length : 16, 614 comb_tap1length : 12 615 ); 616 } comb_line_length; 617 618 typedef struct { 619 const uint8 *types; 620 const comb_cntl0 *cntl0; 621 const comb_cntl1 *cntl1; 622 const comb_cntl2 *cntl2; 623 const comb_line_length *line_length; 624 } comb_settings; 625 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, 635 0 636 }; 637 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 } 647 }; 648 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 } 658 }; 659 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 } 669 }; 670 671 static const comb_line_length comb_line_length_ntsc_m[] = { 672 { 0x38A, 0x718 }, 673 { 0x38A, 0x718 }, 674 { 0x38A, 0x718 }, 675 { 0x38A, 0x718 }, 676 { 0x38A, 0x718 }, 677 { 0, 0 }, 678 { 0x38A, 0 }, 679 { 0x38A, 0x718 } 680 }; 681 682 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, 691 0 692 }; 693 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 } 702 }; 703 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 } 712 }; 713 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 } 722 }; 723 724 static const comb_line_length comb_line_length_ntsc_433[] = { 725 { 0x462, 0x8C9 }, 726 { 0x462, 0x8C9 }, 727 { 0x462, 0x8C9 }, 728 { 0x462, 0x8C9 }, 729 { 0, 0 }, 730 { 0x462, 0x8C9 }, 731 { 0x462, 0x8C9 } 732 }; 733 734 735 static const uint8 comb_types_pal_m[] = { 736 _2Tap_C_combed_Y_Sub, 737 YC_mode_2Tap_YV_filter, 738 0 739 }; 740 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 } 744 }; 745 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 } 749 }; 750 751 static const comb_cntl2 comb_cntl2_pal_m[] = { 752 { 0xFF, 0xFF, 0xFF, 0xFF }, 753 { 0xFF, 0xFF, 0xFF, 0xFF } 754 }; 755 756 static const comb_line_length comb_line_length_pal_m[] = { 757 { 0x389, 0 }, 758 { 0x389, 0 } 759 }; 760 761 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, 766 0 767 }; 768 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 } 773 }; 774 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 } 779 }; 780 781 static const comb_cntl2 comb_cntl2_pal_n[] = { 782 { 0x10, 0x10, 0x16, 0x16 }, 783 { 0xFF, 0xFF, 0xFF, 0xFF }, 784 { 0xFF, 0xFF, 0xFF, 0xFF } 785 }; 786 787 static const comb_line_length comb_line_length_pal_n[] = { 788 { 0x46B, 0x8DA }, 789 { 0x46C, 0 }, 790 { 0x46C, 0 } 791 }; 792 793 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, 798 0 799 }; 800 801 // used to represent an N/A for easier copy'n'paste 802 #define X 0 803 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 } 808 }; 809 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 } 814 }; 815 816 static const comb_cntl2 comb_cntl2_pal_nc[] = { 817 { 0x10, 0x10, 0x16, 0x16 }, 818 { 0xFF, 0xFF, 0xFF, 0xFF }, 819 { 0xFF, 0xFF, 0xFF, 0xFF } 820 }; 821 822 static const comb_line_length comb_line_length_pal_nc[] = { 823 { 0x391, 0x726 }, 824 { 0x394, X }, 825 { 0x394, X } 826 }; 827 828 829 static const uint8 comb_types_pal[] = { 830 _3Tap_2D_adaptive_Comb, 831 _2Tap_C_combed_Y_Sub, 832 YC_mode_2Tap_YV_filter, 833 0 834 }; 835 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 } 840 }; 841 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 } 846 }; 847 848 static const comb_cntl2 comb_cntl2_pal[] = { 849 { 2, 1, 8, 6 }, 850 { 0xFF, 0xFF, 0xFF, 0xFF }, 851 { 0xFF, 0xFF, 0xFF, 0xFF } 852 }; 853 854 static const comb_line_length comb_line_length_pal[] = { 855 { 0x46B, 0x8DA }, 856 { 0x46C, X }, 857 { 0x46C, X } 858 }; 859 860 861 static const uint8 comb_types_pal_60[] = { 862 _2Tap_C_combed_Y_Sub, 863 YC_mode_2Tap_YV_filter, 864 0 865 }; 866 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 } 870 }; 871 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 } 875 }; 876 877 static const comb_cntl2 comb_cntl2_pal_60[] = { 878 { 0xFF, 0xFF, 0xFF, 0xFF }, 879 { 0xFF, 0xFF, 0xFF, 0xFF } 880 }; 881 882 static const comb_line_length comb_line_length_pal_60[] = { 883 { 0x463, 0 }, 884 { 0x463, 0 } 885 }; 886 887 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, 891 0, 892 }; 893 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 } 897 }; 898 899 static const comb_cntl1 comb_cntl1_secam[] = { 900 { 1, 0, 1, 0, 2, 0, 0 }, 901 { 1, X, 0, 0, 2, 0, 0 } 902 }; 903 904 static const comb_cntl2 comb_cntl2_secam[] = { 905 { 0xFF, 0xFF, 0xFF, 0xFF }, 906 { 0xFF, 0xFF, 0xFF, 0xFF } 907 }; 908 909 static const comb_line_length comb_line_length_secam[] = { 910 { 0x46A, 0 }, 911 { 0x46A, 0 } 912 }; 913 914 #undef X 915 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 } 926 }; 927 928 int min_type, max_type, type; 929 const comb_settings *settings; 930 int i = 0; 931 932 PRINT(("CTheater100::SetCombFilter(%c, %c)\n", "NJ4MNCB6S"[standard], "TCS"[source])); 933 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; 939 } else { 940 min_type = YC_mode_Comb_filter_off; 941 max_type = YC_mode_3Tap_YV_filter; 942 } 943 944 settings = &comb_settings_list[standard]; 945 946 for( type = min_type; type <= max_type; ++type ) { 947 for( i = 0; settings->types[i]; ++i ) { 948 if( settings->types[i] == type ) 949 break; 950 } 951 952 if( settings->types[i] != 0 ) 953 break; 954 } 955 956 if( type > max_type ) { 957 PRINT(("CTheater100::SetCombFilter() - No settings for this standard and input type combination!!!\n")); 958 return; 959 } 960 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)); 965 966 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); 970 } 971 972 973 // setup luma processor 974 void CTheater100::SetLuminanceProcessor(theater_standard standard) 975 { 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 }; 986 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 }; 998 999 PRINT(("CTheater100::SetLuminanceProcessor(%c)\n", "NJ4MNCB6S"[standard])); 1000 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); 1006 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); 1012 } 1013 1014 1015 // setup brightness and contrast 1016 void CTheater100::SetLuminanceLevels(theater_standard standard, int brightness, int contrast) 1017 { 1018 double ref0, setup, gain; 1019 1020 ref0 = Register(VIP_LP_AGC_CLAMP_CNTL0, SYNCTIP_REF0); 1021 1022 switch (standard) { 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); 1028 break; 1029 1030 case C_THEATER_NTSC_JAPAN: 1031 setup = 0.0; 1032 gain = 219.0 / (100.0 * ref0 / 40.0); 1033 break; 1034 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: 1040 setup = 0.0; 1041 gain = 219.0 / (100.0 * ref0 / 43.0); 1042 break; 1043 1044 default: 1045 setup = 0.0; 1046 gain = 0.0; 1047 break; 1048 } 1049 1050 if (contrast <= -100) 1051 contrast = -99; 1052 1053 /* set luminance processor constrast (7:0) */ 1054 SetRegister(VIP_LP_CONTRAST, CONTRAST, 1055 int(64.0 * ((contrast + 100) / 100.0) * gain) << 0); 1056 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); 1060 } 1061 1062 1063 // setup chroma demodulator 1064 void CTheater100::SetChromaProcessor(theater_standard standard) 1065 { 1066 PRINT(("CTheater100::SetChromaProcessor(%c)\n", "NJ4MNCB6S"[standard])); 1067 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 }; 1074 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 }; 1085 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 }; 1098 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); 1102 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); 1108 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); 1111 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); 1114 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); 1117 } 1118 1119 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) 1123 { 1124 int ref0; 1125 double gain, CRgain, CBgain; 1126 1127 /* compute Cr/Cb gains */ 1128 ref0 = Register(VIP_LP_AGC_CLAMP_CNTL0, SYNCTIP_REF0); 1129 1130 switch (standard) { 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; 1136 break; 1137 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; 1141 break; 1142 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; 1149 break; 1150 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; 1154 break; 1155 1156 default: 1157 PRINT(("CTheater100::SetChromaLevels() - Bad standard\n")); 1158 CRgain = 0.0; 1159 CBgain = 0.0; 1160 break; 1161 } 1162 1163 if (saturation >= 0) 1164 gain = 1.0 + 4.9 * saturation / 100.0; 1165 else 1166 gain = 1.0 + saturation / 100.0; 1167 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); 1170 1171 if (hue >= 0) 1172 hue = (256 * hue) / 360; 1173 else 1174 hue = (256 * (hue + 360)) / 360; 1175 1176 SetRegister(VIP_CP_HUE_CNTL, HUE_ADJ, hue << 0); 1177 } 1178 1179 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 }; 1200 1201 void CTheater100::getActiveRange( theater_standard standard, CRadeonRect &rect ) 1202 { 1203 rect.SetTo( 1204 h_active_start[standard], v_active_start[standard], 1205 h_active_end[standard], v_active_end[standard] ); 1206 } 1207 1208 void CTheater100::getVBIRange( theater_standard standard, CRadeonRect &rect ) 1209 { 1210 rect.SetTo( 1211 h_vbi_wind_start[standard], v_vbi_wind_start[standard], 1212 h_vbi_wind_end[standard], v_vbi_wind_end[standard] ); 1213 } 1214 1215 // program clipping engine 1216 void CTheater100::SetClipWindow(theater_standard standard, bool vbi) 1217 { 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); 1221 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); 1225 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); 1229 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); 1233 1234 // set VBI scaler control 1235 SetRegister(VIP_VBI_SCALER_CONTROL, (1 << 16) & VBI_SCALING_RATIO); 1236 1237 // enable/disable VBI capture 1238 SetRegister(VIP_VBI_CONTROL, VBI_CAPTURE_ENABLE, 1239 vbi ? VBI_CAPTURE_EN : VBI_CAPTURE_DIS); 1240 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)); 1250 1251 } 1252 1253 1254 // setup capture scaler. 1255 void CTheater100::SetScaler(theater_standard standard, int hactive, int vactive, bool deinterlace) 1256 { 1257 int oddOffset, evenOffset; 1258 uint16 h_active_width, v_active_height; 1259 1260 // ASSERT(vactive <= 511); 1261 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; 1265 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; 1272 1273 if (deinterlace) { 1274 // progressive scan 1275 evenOffset = oddOffset = 512 - (int) ((512 * vactive) / v_active_height); 1276 } 1277 else { 1278 // interlaced 1279 evenOffset = (int) ((512 * vactive) / v_active_height); 1280 oddOffset = 2048 - evenOffset; 1281 } 1282 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); 1286 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); 1289 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); 1292 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); 1298 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); 1303 1304 SetRegister(VIP_V_SCALER_CONTROL, V_DEINTERLACE_ON, deinterlace ? V_DEINTERLACE_ON : 0); 1305 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, 1309 hactive, vactive, 1310 Register(VIP_H_SCALER_CONTROL, H_SCALE_RATIO), 1311 Register(VIP_V_SCALER_CONTROL, V_SCALE_RATIO))); 1312 } 1313 1314 int CTheater100::CurrentLine() 1315 { 1316 return Register(VIP_VS_LINE_COUNT) & VS_LINE_COUNT; 1317 } 1318 1319 void CTheater100::PrintToStream() 1320 { 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)); 1326 } 1327 } 1328