1 /* Authors: 2 Mark Watson 2000, 3 Rudolf Cornelissen 1/2003-12/2003 4 5 Thanx to Petr Vandrovec for writing matroxfb. 6 */ 7 8 #define MODULE_BIT 0x00100000 9 10 #include "std.h" 11 12 typedef struct { 13 uint32 h_total; 14 uint32 h_display; 15 uint32 h_sync_length; 16 uint32 front_porch; 17 uint32 back_porch; 18 uint32 color_burst; 19 uint32 v_total; 20 float chroma_subcarrier; 21 } gx50_maven_timing; 22 23 void gxx0_maventv_PAL_init(uint8* buffer); 24 void gxx0_maventv_NTSC_init(uint8* buffer); 25 void gx50_maventv_PAL_timing(gx50_maven_timing *m_timing); 26 void gx50_maventv_NTSC_timing(gx50_maven_timing *m_timing); 27 28 //fixme: setup fixed CRTC2 modes for all modes and block other modes: 29 // - 640x480, 800x600, 1024x768 NTSC and PAL overscan compensated modes (desktop) 30 // - 640x480, 720x480 NTSC and 768x576, 720x576 non-overscan compensated modes (video) 31 //fixme: try to implement 'fast' and 'slow' settings for all modes, 32 // so buffer duplication or skipping won't be neccesary for realtime video. 33 //fixme: try to setup the CRTC2 in interlaced mode for the video modes on <= G400MAX cards. 34 35 /* find 'exact' valid video PLL setting */ 36 status_t g100_g400max_maventv_vid_pll_find( 37 display_mode target, unsigned int * ht_new, unsigned int * ht_last_line, 38 uint8 * m_result, uint8 * n_result, uint8 * p_result) 39 { 40 int m = 0, n = 0, p = 0, m_max; 41 float diff, diff_smallest = 999999999; 42 int best[5], h_total_mod; 43 float fields_sec, f_vco; 44 /* We need to be exact, so work with clockperiods per field instead of with frequency. 45 * Make sure however we truncate these clocks to be integers! 46 * (The NTSC field frequency would otherwise prevent the 'whole number of clocks per field' 47 * check done in this routine later on...) */ 48 uint32 vco_clks_field, max_pclks_field, req_pclks_field; 49 /* We need this variable to be a float, because we need to be able to verify if this 50 * represents a whole number of clocks per field later on! */ 51 float calc_pclks_field; 52 53 LOG(2,("MAVENTV: searching for EXACT videoclock match\n")); 54 55 /* determine the max. reference-frequency postscaler setting for the current card */ 56 //fixme: check G100 and G200 m_max if exist and possible... 57 switch(si->ps.card_type) 58 { 59 /* case G100: 60 LOG(2,("MAVENTV: G100 restrictions apply\n")); 61 m_max = 32; 62 break; 63 case G200: 64 LOG(2,("MAVENTV: G200 restrictions apply\n")); 65 m_max = 32; 66 break; 67 */ default: 68 LOG(2,("MAVENTV: G400/G400MAX restrictions apply\n")); 69 m_max = 32; 70 break; 71 } 72 73 /* set number of fields per second to generate */ 74 if ((target.flags & TV_BITS) == TV_PAL) 75 fields_sec = 50.0; 76 else 77 fields_sec = 59.94; 78 79 /* determine the max. pixelclock for the current videomode */ 80 switch (target.space) 81 { 82 case B_RGB16_LITTLE: 83 max_pclks_field = (si->ps.max_dac2_clock_16 * 1000000) / fields_sec; 84 break; 85 case B_RGB32_LITTLE: 86 max_pclks_field = (si->ps.max_dac2_clock_32 * 1000000) / fields_sec; 87 break; 88 default: 89 /* use fail-safe value */ 90 max_pclks_field = (si->ps.max_dac2_clock_32 * 1000000) / fields_sec; 91 break; 92 } 93 /* if some dualhead mode is active, an extra restriction might apply */ 94 if ((target.flags & DUALHEAD_BITS) && (target.space == B_RGB32_LITTLE)) 95 max_pclks_field = (si->ps.max_dac2_clock_32dh * 1000000) / fields_sec; 96 97 /* Checkout all possible Htotal settings within the current granularity step 98 * of CRTC2 to get a real close videoclock match! 99 * (The MAVEN apparantly has a granularity of 1 pixel, while CRTC2 has 8 pixels) */ 100 for (h_total_mod = 0; h_total_mod < 8; h_total_mod++) 101 { 102 LOG(2,("MAVENTV: trying h_total modification of +%d...\n", h_total_mod)); 103 104 /* Calculate videoclock to be a bit to high so we can compensate for an exact 105 * match via h_total_lastline.. */ 106 *ht_new = target.timing.h_total + h_total_mod + 2; 107 108 /* Make sure the requested pixelclock is within the PLL's operational limits */ 109 /* lower limit is min_video_vco divided by highest postscaler-factor */ 110 req_pclks_field = *ht_new * target.timing.v_total; 111 if (req_pclks_field < (((si->ps.min_video_vco * 1000000) / fields_sec) / 8.0)) 112 { 113 req_pclks_field = (((si->ps.min_video_vco * 1000000) / fields_sec) / 8.0); 114 LOG(4,("MAVENTV: WARNING, clamping at lowest possible videoclock\n")); 115 } 116 /* upper limit is given by pins in combination with current active mode */ 117 if (req_pclks_field > max_pclks_field) 118 { 119 req_pclks_field = max_pclks_field; 120 LOG(4,("MAVENTV: WARNING, clamping at highest possible videoclock\n")); 121 } 122 123 /* iterate through all valid PLL postscaler settings */ 124 for (p=0x01; p < 0x10; p = p<<1) 125 { 126 /* calc the needed number of VCO clocks per field for this postscaler setting */ 127 vco_clks_field = req_pclks_field * p; 128 129 /* check if this is within range of the VCO specs */ 130 if ((vco_clks_field >= ((si->ps.min_video_vco * 1000000) / fields_sec)) && 131 (vco_clks_field <= ((si->ps.max_video_vco * 1000000) / fields_sec))) 132 { 133 /* iterate trough all valid reference-frequency postscaler settings */ 134 for (m = 2; m <= m_max; m++) 135 { 136 /* calculate VCO postscaler setting for current setup.. */ 137 n = (int)(((vco_clks_field * m) / ((si->ps.f_ref * 1000000) / fields_sec)) + 0.5); 138 /* ..and check for validity */ 139 if ((n < 8) || (n > 128)) continue; 140 141 /* special TVmode stuff starts here (rest is in fact standard): */ 142 /* calculate number of videoclocks per field */ 143 calc_pclks_field = 144 (((uint32)((si->ps.f_ref * 1000000) / fields_sec)) * n) / ((float)(m * p)); 145 146 /* we need a whole number of clocks per field, otherwise it won't work correctly. 147 * (TVout will flicker, green fields will occur) */ 148 if (calc_pclks_field != (uint32)calc_pclks_field) continue; 149 150 /* check if we have the min. needed number of clocks per field for a sync lock */ 151 if (calc_pclks_field < ((*ht_new * (target.timing.v_total - 1)) + 2)) continue; 152 153 /* calc number of clocks we have for the last field line */ 154 *ht_last_line = calc_pclks_field - (*ht_new * (target.timing.v_total - 1)); 155 156 /* check if we haven't got too much clocks in the last field line for a sync lock */ 157 if (*ht_last_line > *ht_new) continue; 158 159 /* we have a match! */ 160 /* calculate the difference between a full line and the last line */ 161 diff = *ht_new - *ht_last_line; 162 163 /* if this last_line comes closer to a full line than earlier 'hits' then use it */ 164 if (diff < diff_smallest) 165 { 166 /* log results */ 167 if (diff_smallest == 999999999) 168 LOG(2,("MAVENTV: MATCH, ")); 169 else 170 LOG(2,("MAVENTV: better MATCH,")); 171 f_vco = (si->ps.f_ref / m) * n; 172 LOG(2,("found vid VCO freq %fMhz, pixclk %fMhz\n", f_vco, (f_vco / p))); 173 LOG(2,("MAVENTV: mnp(ex. filter) 0x%02x 0x%02x 0x%02x, h_total %d, ht_lastline %d\n", 174 (m - 1), (n - 1), (p - 1), (*ht_new - 2), (*ht_last_line - 2))); 175 176 /* remember this best match */ 177 diff_smallest = diff; 178 best[0] = m; 179 best[1] = n; 180 best[2] = p; 181 /* h_total to use for this setting: 182 * exclude the 'calculate clock a bit too high' trick */ 183 best[3] = *ht_new - 2; 184 /* ht_last_line to use for this setting: 185 * exclude the 'calculate clock a bit too high' trick */ 186 best[4] = *ht_last_line - 2; 187 } 188 } 189 } 190 } 191 } 192 LOG(2,("MAVENTV: search completed.\n")); 193 194 /* setup the scalers programming values for found optimum setting */ 195 m = best[0] - 1; 196 n = best[1] - 1; 197 p = best[2] - 1; 198 199 /* if no match was found set fixed PLL frequency so we have something valid at least */ 200 if (diff_smallest == 999999999) 201 { 202 LOG(4,("MAVENTV: WARNING, no MATCH found!\n")); 203 204 if (si->ps.f_ref == 27.000) 205 { 206 /* set 13.5Mhz */ 207 m = 0x03; 208 n = 0x07; 209 p = 0x03; 210 } 211 else 212 { 213 /* set 14.31818Mhz */ 214 m = 0x01; 215 n = 0x07; 216 p = 0x03; 217 } 218 best[3] = target.timing.h_total; 219 best[4] = target.timing.h_total; 220 } 221 222 /* calc the needed PLL loopbackfilter setting belonging to current VCO speed */ 223 f_vco = (si->ps.f_ref / (m + 1)) * (n + 1); 224 LOG(2,("MAVENTV: using vid VCO frequency %fMhz\n", f_vco)); 225 226 switch(si->ps.card_type) 227 { 228 /* case G100: 229 case G200: 230 for(;;) 231 { 232 if (f_vco >= 180) {p |= (0x03 << 3); break;}; 233 if (f_vco >= 140) {p |= (0x02 << 3); break;}; 234 if (f_vco >= 100) {p |= (0x01 << 3); break;}; 235 break; 236 } 237 break; 238 */ default: 239 for(;;) 240 { 241 if (f_vco >= 240) {p |= (0x03 << 3); break;}; 242 if (f_vco >= 170) {p |= (0x02 << 3); break;}; 243 if (f_vco >= 110) {p |= (0x01 << 3); break;}; 244 break; 245 } 246 break; 247 } 248 249 /* return results */ 250 *m_result = m; 251 *n_result = n; 252 *p_result = p; 253 *ht_new = best[3]; 254 *ht_last_line = best[4]; 255 256 /* display the found pixelclock values */ 257 LOG(2,("MAVENTV: vid PLL check: got %fMHz, mnp 0x%02x 0x%02x 0x%02x\n", 258 (f_vco / ((p & 0x07) + 1)), m, n, p)); 259 LOG(2,("MAVENTV: new h_total %d, ht_lastline %d\n", *ht_new, *ht_last_line)); 260 261 /* return status */ 262 if (diff_smallest == 999999999) return B_ERROR; 263 return B_OK; 264 } 265 266 /* Notes about timing: 267 * Note: 268 * all horizontal timing is measured in pixelclock periods; 269 * all? vertical timing is measured in field? lines. */ 270 271 /* Note: 272 * <= G400MAX cards have a fixed 27Mhz(?) clock for TV timing register values, 273 * while on G450/G550 these need to be calculated based on the video pixelclock. */ 274 275 276 /* Notes about signal strengths: 277 * Note: 278 * G400 and earlier cards have a fixed reference voltage of +2.6 Volt; 279 * G450 and G550 cards MAVEN DACs have a switchable ref voltage of +1.5/+2.0 Volt. 280 * 281 * This voltage is used to feed the videosignals: 282 * - Hsync pulse level; 283 * - Lowest active video output level; 284 * - Highest active video output level. 285 * These actual voltages are set via 10bit DACs. 286 * 287 * G450/G550: 288 * The color burst amplitude videosignal is fed by 80% of the above mentioned 289 * ref. voltage, and is set via an 8bit DAC. 290 * On G400 and earlier cards the ref. voltage is different, and also differs 291 * for PAL and NTSC mode. */ 292 293 /* Note: 294 * Increasing the distance between the highest and lowest active video output 295 * level increases contrast; decreasing it decreases contrast. */ 296 297 /* Note: 298 * Increasing both the highest and lowest active video output level with the 299 * same amount increases brightness; decreasing it decreases brightness. */ 300 301 /* Note: 302 * Increasing the Hsync pulse level increases the black level, so decreases 303 * brightness and contrast. */ 304 305 /* Preset maven PAL output (625lines, 50Hz mode) */ 306 void gxx0_maventv_PAL_init(uint8* buffer) 307 { 308 uint16 value; 309 310 /* Chroma subcarrier divider */ 311 buffer[0x00] = 0x2A; 312 buffer[0x01] = 0x09; 313 buffer[0x02] = 0x8A; 314 buffer[0x03] = 0xCB; 315 316 buffer[0x04] = 0x00; 317 buffer[0x05] = 0x00; 318 buffer[0x06] = 0xF9; 319 buffer[0x07] = 0x00; 320 /* Hsync pulse length */ 321 buffer[0x08] = 0x7E; 322 /* color burst length */ 323 buffer[0x09] = 0x44; 324 /* back porch length */ 325 buffer[0x0a] = 0x9C; 326 327 /* color burst amplitude */ 328 /* if (si->ps.card_type <= G400MAX) 329 { 330 buffer[0x0b] = 0x3e; 331 } 332 else 333 { 334 */ buffer[0x0b] = 0x48; 335 // } 336 337 buffer[0x0c] = 0x21; 338 buffer[0x0d] = 0x00; 339 340 // if (si->ps.card_type <= G400MAX) 341 // { 342 /* Lowest active video output level. 343 * Warning: make sure this stays above (or equals) the sync pulse level! */ 344 // value = 0x0ea; 345 // buffer[0x0e] = ((value >> 2) & 0xff); 346 // buffer[0x0f] = (value & 0x03); 347 /* horizontal sync pulse level */ 348 // buffer[0x10] = ((value >> 2) & 0xff); 349 // buffer[0x11] = (value & 0x03); 350 // } 351 // else 352 { 353 /* Lowest active video output level. 354 * Warning: make sure this stays above (or equals) the sync pulse level! */ 355 value = 0x130; 356 buffer[0x0e] = ((value >> 2) & 0xff); 357 buffer[0x0f] = (value & 0x03); 358 /* horizontal sync pulse level */ 359 buffer[0x10] = ((value >> 2) & 0xff); 360 buffer[0x11] = (value & 0x03); 361 } 362 363 buffer[0x12] = 0x1A; 364 buffer[0x13] = 0x2A; 365 366 /* functional unit */ 367 buffer[0x14] = 0x1C; 368 buffer[0x15] = 0x3D; 369 buffer[0x16] = 0x14; 370 371 /* vertical total */ //(=625) 372 /* b9-2 */ 373 buffer[0x17] = 0x9C; 374 /* b1-0 in b1-0 */ 375 buffer[0x18] = 0x01; 376 377 buffer[0x19] = 0x00; 378 buffer[0x1a] = 0xFE; 379 buffer[0x1b] = 0x7E; 380 buffer[0x1c] = 0x60; 381 buffer[0x1d] = 0x05; 382 383 /* Highest active video output level. 384 * Warning: make sure this stays above the lowest active video output level! */ 385 /* if (si->ps.card_type <= G400MAX) 386 { 387 value = 0x24f; 388 buffer[0x1e] = ((value >> 2) & 0xff); 389 buffer[0x1f] = (value & 0x03); 390 } 391 else 392 */ { 393 value = 0x300; 394 buffer[0x1e] = ((value >> 2) & 0xff); 395 buffer[0x1f] = (value & 0x03); 396 } 397 398 /* saturation (field?) #1 */ 399 // if (si->ps.card_type <= G400MAX) 400 // buffer[0x20] = 0x72; 401 // else 402 buffer[0x20] = 0xA5; 403 404 buffer[0x21] = 0x07; 405 406 /* saturation (field?) #2 */ 407 // if (si->ps.card_type <= G400MAX) 408 // buffer[0x22] = 0x72; 409 // else 410 buffer[0x22] = 0xA5; 411 412 buffer[0x23] = 0x00; 413 buffer[0x24] = 0x00; 414 /* hue? */ 415 buffer[0x25] = 0x00; 416 417 buffer[0x26] = 0x08; 418 buffer[0x27] = 0x04; 419 buffer[0x28] = 0x00; 420 buffer[0x29] = 0x1A; 421 422 /* functional unit */ 423 buffer[0x2a] = 0x55; 424 buffer[0x2b] = 0x01; 425 426 /* front porch length */ 427 buffer[0x2c] = 0x26; 428 429 /* functional unit */ 430 buffer[0x2d] = 0x07; 431 buffer[0x2e] = 0x7E; 432 433 /* functional unit */ 434 buffer[0x2f] = 0x02; 435 buffer[0x30] = 0x54; 436 437 /* horizontal visible */ 438 value = 0x580; 439 buffer[0x31] = ((value >> 3) & 0xff); 440 buffer[0x32] = (value & 0x07); 441 442 /* upper blanking (in field lines) */ 443 buffer[0x33] = 0x14; //=((v_total - v_sync_end)/2) -1 444 445 buffer[0x34] = 0x49; 446 buffer[0x35] = 0x00; 447 buffer[0x36] = 0x00; 448 buffer[0x37] = 0xA3; 449 buffer[0x38] = 0xC8; 450 buffer[0x39] = 0x22; 451 buffer[0x3a] = 0x02; 452 buffer[0x3b] = 0x22; 453 454 /* functional unit */ 455 buffer[0x3c] = 0x3F; 456 buffer[0x3d] = 0x03; 457 } 458 459 /* Preset maven NTSC output (525lines, 59.94Hz mode) */ 460 void gxx0_maventv_NTSC_init(uint8* buffer) 461 { 462 uint16 value; 463 464 /* Chroma subcarrier frequency */ 465 buffer[0x00] = 0x21; 466 buffer[0x01] = 0xF0; 467 buffer[0x02] = 0x7C; 468 buffer[0x03] = 0x1F; 469 470 buffer[0x04] = 0x00; 471 buffer[0x05] = 0x00;//b1 = ON enables colorbar testimage 472 buffer[0x06] = 0xF9;//b0 = ON enables MAVEN TV output 473 buffer[0x07] = 0x00;//influences the colorburst signal amplitude somehow 474 475 /* Hsync pulse length */ 476 buffer[0x08] = 0x7E; 477 /* color burst length */ 478 buffer[0x09] = 0x43; 479 /* back porch length */ 480 buffer[0x0a] = 0x7E; 481 482 /* color burst amplitude */ 483 // if (si->ps.card_type <= G400MAX) 484 // { 485 // buffer[0x0b] = 0x46; 486 // } 487 // else 488 { 489 buffer[0x0b] = 0x48; 490 } 491 492 buffer[0x0c] = 0x00; 493 buffer[0x0d] = 0x00; 494 495 // if (si->ps.card_type <= G400MAX) 496 // { 497 /* Lowest active video output level. 498 * Warning: make sure this stays above (or equals) the sync pulse level! */ 499 // value = 0x0ea; 500 // buffer[0x0e] = ((value >> 2) & 0xff); 501 // buffer[0x0f] = (value & 0x03); 502 /* horizontal sync pulse level */ 503 // buffer[0x10] = ((value >> 2) & 0xff); 504 // buffer[0x11] = (value & 0x03); 505 // } 506 // else 507 { 508 /* Lowest active video output level. 509 * Warning: make sure this stays above (or equals) the sync pulse level! */ 510 value = 0x130; 511 buffer[0x0e] = ((value >> 2) & 0xff); 512 buffer[0x0f] = (value & 0x03); 513 /* horizontal sync pulse level */ 514 buffer[0x10] = ((value >> 2) & 0xff); 515 buffer[0x11] = (value & 0x03); 516 } 517 518 buffer[0x12] = 0x17; 519 buffer[0x13] = 0x21; 520 521 /* functional unit */ 522 buffer[0x14] = 0x1B; 523 buffer[0x15] = 0x1B; 524 buffer[0x16] = 0x24; 525 526 /* vertical total */ 527 /* b9-2 */ 528 buffer[0x17] = 0x83; 529 /* b1-0 in b1-0 */ 530 buffer[0x18] = 0x01; 531 532 buffer[0x19] = 0x00;//mv register? 533 buffer[0x1a] = 0x0F; 534 buffer[0x1b] = 0x0F; 535 buffer[0x1c] = 0x60; 536 buffer[0x1d] = 0x05; 537 538 /* Highest active video output level. 539 * Warning: make sure this stays above the lowest active video output level! */ 540 /* if (si->ps.card_type <= G400MAX) 541 { 542 value = 0x24f; 543 buffer[0x1e] = ((value >> 2) & 0xff); 544 buffer[0x1f] = (value & 0x03); 545 } 546 else 547 */ { 548 value = 0x300; 549 buffer[0x1e] = ((value >> 2) & 0xff); 550 buffer[0x1f] = (value & 0x03); 551 } 552 553 /* color saturation #1 (Y-B ?) */ 554 // if (si->ps.card_type <= G400MAX) 555 // buffer[0x20] = 0x5F; 556 // else 557 buffer[0x20] = 0x9C; 558 559 buffer[0x21] = 0x04; 560 561 /* color saturation #2 (Y-R ?) */ 562 // if (si->ps.card_type <= G400MAX) 563 // buffer[0x22] = 0x5F; 564 // else 565 buffer[0x22] = 0x9C; 566 567 buffer[0x23] = 0x01; 568 buffer[0x24] = 0x02; 569 570 /* hue: preset at 0 degrees */ 571 buffer[0x25] = 0x00; 572 573 buffer[0x26] = 0x0A; 574 buffer[0x27] = 0x05;//sync stuff 575 buffer[0x28] = 0x00; 576 buffer[0x29] = 0x10;//field line-length stuff 577 578 /* functional unit */ 579 buffer[0x2a] = 0xFF; 580 buffer[0x2b] = 0x03; 581 582 /* front porch length */ 583 buffer[0x2c] = 0x24; 584 585 /* functional unit */ 586 buffer[0x2d] = 0x0F; 587 buffer[0x2e] = 0x78; 588 589 /* functional unit */ 590 buffer[0x2f] = 0x00; 591 buffer[0x30] = 0x00; 592 593 /* horizontal visible */ 594 /* b10-3 */ 595 buffer[0x31] = 0xB2; 596 /* b2-0 in b2-0 */ 597 buffer[0x32] = 0x04; 598 599 /* upper blanking (in field lines) */ 600 buffer[0x33] = 0x14; 601 602 buffer[0x34] = 0x02;//colorphase or so stuff. 603 buffer[0x35] = 0x00; 604 buffer[0x36] = 0x00; 605 buffer[0x37] = 0xA3; 606 buffer[0x38] = 0xC8; 607 buffer[0x39] = 0x15; 608 buffer[0x3a] = 0x05; 609 buffer[0x3b] = 0x3B; 610 611 /* functional unit */ 612 buffer[0x3c] = 0x3C; 613 buffer[0x3d] = 0x00; 614 } 615 616 void gx50_maventv_PAL_timing(gx50_maven_timing *m_timing) 617 { 618 /* values are given in picoseconds */ 619 m_timing->h_total = 64000000; 620 /* the sum of the signal duration below should match h_total! */ 621 m_timing->h_display = 52148148; 622 m_timing->h_sync_length = 4666667; 623 m_timing->front_porch = 1407407; 624 m_timing->back_porch = 5777778; 625 /* colorburst is 'superimposed' on the above timing */ 626 m_timing->color_burst = 2518518; 627 /* number of lines per frame */ 628 m_timing->v_total = 625; 629 /* color carrier frequency in Mhz */ 630 m_timing->chroma_subcarrier = 4.43361875; 631 } 632 633 void gx50_maventv_NTSC_timing(gx50_maven_timing *m_timing) 634 { 635 /* values are given in picoseconds */ 636 m_timing->h_total = 63555556; 637 /* the sum of the signal duration below should match h_total! */ 638 m_timing->h_display = 52888889; 639 m_timing->h_sync_length = 4666667; 640 m_timing->front_porch = 1333333; 641 m_timing->back_porch = 4666667; 642 /* colorburst is 'superimposed' on the above timing */ 643 m_timing->color_burst = 2418418; 644 /* number of lines per frame */ 645 m_timing->v_total = 525; 646 /* color carrier frequency in Mhz */ 647 m_timing->chroma_subcarrier = 3.579545454; 648 } 649 650 int maventv_init(display_mode target) 651 { 652 uint8 val; 653 uint8 m_result, n_result, p_result; 654 unsigned int ht_new, ht_last_line; 655 float calc_pclk = 0; 656 /* use a display_mode copy because we might tune it for TVout compatibility */ 657 display_mode tv_target = target; 658 /* used as buffer for TVout signal to generate */ 659 uint8 maventv_regs[64]; 660 /* used in G450/G550 to calculate TVout signal timing dependant on pixelclock; 661 * <= G400MAX use fixed settings because base-clock here is the fixed crystal 662 * frequency. */ 663 //fixme: if <=G400 cards with MAVEN and crystal of 14.31818Mhz exist, modify!?! 664 gx50_maven_timing m_timing; 665 666 /* preset new TVout mode */ 667 if ((tv_target.flags & TV_BITS) == TV_PAL) 668 { 669 LOG(4, ("MAVENTV: PAL TVout\n")); 670 gxx0_maventv_PAL_init(maventv_regs); 671 gx50_maventv_PAL_timing(&m_timing); 672 } 673 else 674 { 675 LOG(4, ("MAVENTV: NTSC TVout\n")); 676 gxx0_maventv_NTSC_init(maventv_regs); 677 gx50_maventv_NTSC_timing(&m_timing); 678 } 679 680 /* enter mode-program mode */ 681 // if (si->ps.card_type <= G400MAX) MAVW(PGM, 0x01); 682 // else 683 // { 684 // DXIW(TVO_IDX, ENMAV_PGM); 685 // DXIW(TVO_DATA, 0x01); 686 // } 687 688 /* tune new TVout mode */ 689 // if (si->ps.card_type <= G400MAX) 690 { 691 /* setup TV-mode 'copy' of CRTC2, setup PLL, inputs, outputs and sync-locks */ 692 // MAVW(MONSET, 0x00); 693 // MAVW(MONEN, 0xA2); 694 695 /* xmiscctrl */ 696 //unknown regs: 697 // MAVWW(WREG_0X8E_L, 0x1EFF); 698 // MAVW(BREG_0XC6, 0x01); 699 700 // MAVW(LOCK, 0x01); 701 // MAVW(OUTMODE, 0x08); 702 // MAVW(LUMA, 0x78); 703 // MAVW(STABLE, 0x02); 704 // MAVW(MONEN, 0xB3); 705 706 /* setup video PLL */ 707 g100_g400max_maventv_vid_pll_find( 708 tv_target, &ht_new, &ht_last_line, &m_result, &n_result, &p_result); 709 // MAVW(PIXPLLM, m_result); 710 // MAVW(PIXPLLN, n_result); 711 // MAVW(PIXPLLP, (p_result | 0x80)); 712 713 // MAVW(MONSET, 0x20); 714 715 // MAVW(TEST, 0x10); 716 717 /* htotal - 2 */ 718 // MAVWW(HTOTALL, ht_new); 719 720 /* last line in field can have different length */ 721 /* hlen - 2 */ 722 // MAVWW(LASTLINEL, ht_last_line); 723 724 /* horizontal vidrst pos: 0 <= vidrst pos <= htotal - 2 */ 725 // MAVWW(HVIDRSTL, (ht_last_line - si->crtc_delay - 726 // (tv_target.timing.h_sync_end - tv_target.timing.h_sync_start))); 727 //ORG (does the same but with limit checks but these limits should never occur!): 728 // slen = tv_target.timing.h_sync_end - tv_target.timing.h_sync_start; 729 // hcrt = tv_target.timing.h_total - slen - si->crtc_delay; 730 // if (ht_last_line < tv_target.timing.h_total) hcrt += ht_last_line; 731 // if (hcrt > tv_target.timing.h_total) hcrt -= tv_target.timing.h_total; 732 // if (hcrt + 2 > tv_target.timing.h_total) hcrt = 0; /* or issue warning? */ 733 // MAVWW(HVIDRSTL, hcrt); 734 735 /* who knows */ 736 // MAVWW(HSYNCSTRL, 0x0004);//must be 4!! 737 738 /* hblanking end: 100% */ 739 // MAVWW(HSYNCLENL, (tv_target.timing.h_total - tv_target.timing.h_sync_end)); 740 741 /* vertical line count - 1 */ 742 // MAVWW(VTOTALL, (tv_target.timing.v_total - 1)); 743 744 /* vertical vidrst pos */ 745 // MAVWW(VVIDRSTL, (tv_target.timing.v_total - 2)); 746 747 /* something end... [A6]+1..[A8] */ 748 // MAVWW(VSYNCSTRL, 0x0001); 749 750 /* vblanking end: stop vblanking */ 751 // MAVWW(VSYNCLENL, (tv_target.timing.v_sync_end - tv_target.timing.v_sync_start - 1)); 752 //org: no visible diff: 753 //MAVWW(VSYNCLENL, (tv_target.timing.v_total - tv_target.timing.v_sync_start - 1)); 754 755 /* something start... 0..[A4]-1 */ 756 // MAVWW(VDISPLAYL, 0x0000); 757 //std setmode (no visible difference) 758 //MAVWW(VDISPLAYL, (tv_target.timing.v_total - 1)); 759 760 /* ... */ 761 // MAVWW(WREG_0X98_L, 0x0000); 762 763 /* moves picture up/down and so on... */ 764 // MAVWW(VSOMETHINGL, 0x0001); /* Fix this... 0..VTotal */ 765 766 { 767 uint32 h_display_tv; 768 uint8 h_scale_tv; 769 770 unsigned int ib_min_length; 771 unsigned int ib_length; 772 int index; 773 774 /* calc hor scale-back factor from input to output picture (in 1.7 format) 775 * the MAVEN has 736 pixels fixed visible? outputline length for TVout */ 776 //fixme: shouldn't this be 768 (= PAL 1:1 output 4:3 ratio format)?!? 777 h_scale_tv = (736 << 7) / tv_target.timing.h_total;//should be PLL corrected 778 LOG(4,("MAVENTV: horizontal scale-back factor is: %f\n", (h_scale_tv / 128.0))); 779 780 /* limit values to MAVEN capabilities (scale-back factor is 0.5-1.0) */ 781 //fixme: how about lowres upscaling? 782 if (h_scale_tv > 0x80) 783 { 784 h_scale_tv = 0x80; 785 LOG(4,("MAVENTV: limiting horizontal scale-back factor to: %f\n", (h_scale_tv / 128.0))); 786 } 787 if (h_scale_tv < 0x40) 788 { 789 h_scale_tv = 0x40; 790 LOG(4,("MAVENTV: limiting horizontal scale-back factor to: %f\n", (h_scale_tv / 128.0))); 791 } 792 /* make sure we get no round-off error artifacts on screen */ 793 h_scale_tv--; 794 795 /* calc difference in (wanted output picture width (excl. hsync_length)) and 796 * (fixed total output line length (=768)), 797 * based on input picture and scaling factor */ 798 /* (MAVEN trick (part 1) to get output picture width to fit into just 8 bits) */ 799 h_display_tv = ((768 - 1) << 7) - 800 (((tv_target.timing.h_total - tv_target.timing.h_sync_end) /* is left margin */ 801 + tv_target.timing.h_display - 8) 802 * h_scale_tv); 803 /* convert result from 25.7 to 32.0 format */ 804 h_display_tv = h_display_tv >> 7; 805 LOG(4,("MAVENTV: displaying output on %d picture pixels\n", 806 ((768 - 1) - h_display_tv))); 807 808 /* half result: MAVEN trick (part 2) 809 * (258 - 768 pixels, only even number per line is possible) */ 810 h_display_tv = h_display_tv >> 1; 811 /* limit value to register contraints */ 812 if (h_display_tv > 0xFF) h_display_tv = 0xFF; 813 // MAVW(HSCALETV, h_scale_tv); 814 // MAVW(HDISPLAYTV, h_display_tv); 815 816 817 /* calculate line inputbuffer length */ 818 /* It must be between (including): 819 * ((input picture left margin) + (input picture hor. resolution) + 4) 820 * AND 821 * (input picture total line length) (PLL corrected) */ 822 823 /* calculate minimal line input buffer length */ 824 ib_min_length = ((tv_target.timing.h_total - tv_target.timing.h_sync_end) + 825 tv_target.timing.h_display + 4); 826 827 /* calculate optimal line input buffer length (so top of picture is OK too) */ 828 /* The following formula applies: 829 * optimal buffer length = ((((0x78 * i) - R) / hor. scaling factor) + Q) 830 * 831 * where (in 4.8 format!) 832 * R Qmin Qmax 833 * 0x0E0 0x5AE 0x5BF 834 * 0x100 0x5CF 0x5FF 835 * 0x180 0x653 0x67F 836 * 0x200 0x6F8 0x6FF 837 */ 838 index = 1; 839 do 840 { 841 ib_length = ((((((0x7800 << 7) * index) - (0x100 << 7)) / h_scale_tv) + 0x05E7) >> 8); 842 index++; 843 } while (ib_length < ib_min_length); 844 LOG(4,("MAVENTV: optimal line inputbuffer length: %d\n", ib_length)); 845 846 if (ib_length >= ht_new + 2) 847 { 848 ib_length = ib_min_length; 849 LOG(4,("MAVENTV: limiting line inputbuffer length, setting minimal usable: %d\n", ib_length)); 850 } 851 // MAVWW(HDISPLAYL, ib_length); 852 } 853 854 { 855 uint16 t_scale_tv; 856 uint32 v_display_tv; 857 858 /* calc total scale-back factor from input to output picture */ 859 { 860 uint32 out_clocks; 861 uint32 in_clocks; 862 863 //takes care of green stripes: 864 /* calc output clocks per frame */ 865 out_clocks = m_timing.v_total * (ht_new + 2); 866 867 /* calc input clocks per frame */ 868 in_clocks = (tv_target.timing.v_total - 1) * (ht_new + 2) + ht_last_line + 2; 869 870 /* calc total scale-back factor from input to output picture in 1.15 format */ 871 t_scale_tv = ((((uint64)out_clocks) << 15) / in_clocks); 872 LOG(4,("MAVENTV: total scale-back factor is: %f\n", (t_scale_tv / 32768.0))); 873 874 /* min. scale-back factor is 1.0 for 1:1 output */ 875 if (t_scale_tv > 0x8000) 876 { 877 t_scale_tv = 0x8000; 878 LOG(4,("MAVENTV: limiting total scale-back factor to: %f\n", (t_scale_tv / 32768.0))); 879 } 880 } 881 882 /*calc output picture height based on input picture and scaling factor */ 883 //warning: v_display was 'one' lower originally! 884 v_display_tv = 885 ((tv_target.timing.v_sync_end - tv_target.timing.v_sync_start) /* is sync length */ 886 + (tv_target.timing.v_total - tv_target.timing.v_sync_end) /* is upper margin */ 887 + tv_target.timing.v_display) 888 * t_scale_tv; 889 /* convert result from 17.15 to 32.0 format */ 890 v_display_tv = (v_display_tv >> 15); 891 LOG(4,("MAVENTV: displaying output on %d picture frame-lines\n", v_display_tv)); 892 893 /* half result, and compensate for internal register offset 894 * (MAVEN trick to get it to fit into just 8 bits). 895 * (allowed output frame height is 292 - 802 lines, only even numbers) */ 896 v_display_tv = (v_display_tv >> 1) - 146; 897 /* limit value to register contraints */ 898 if (v_display_tv > 0xFF) v_display_tv = 0xFF; 899 /* make sure we get no round-off error artifacts on screen */ 900 t_scale_tv--; 901 902 // MAVWW(TSCALETVL, t_scale_tv); 903 // MAVW(VDISPLAYTV, v_display_tv); 904 } 905 906 // MAVW(TEST, 0x00); 907 908 /* gamma correction registers */ 909 // MAVW(GAMMA1, 0x00); 910 // MAVW(GAMMA2, 0x00); 911 // MAVW(GAMMA3, 0x00); 912 // MAVW(GAMMA4, 0x1F); 913 // MAVW(GAMMA5, 0x10); 914 // MAVW(GAMMA6, 0x10); 915 // MAVW(GAMMA7, 0x10); 916 // MAVW(GAMMA8, 0x64); /* 100 */ 917 // MAVW(GAMMA9, 0xC8); /* 200 */ 918 919 /* set flickerfilter */ 920 /* OFF: is dependant on MAVEN chip version(?): ENG_TVO_B = $40, else $00. 921 * ON : always set $a2. */ 922 // MAVW(FFILTER, 0xa2); 923 924 /* 0x10 or anything ored with it */ 925 //fixme? linux uses 0x14... 926 // MAVW(TEST, (MAVR(TEST) & 0x10)); 927 928 /* output: SVideo/Composite */ 929 // MAVW(OUTMODE, 0x08); 930 } 931 // else /* card_type is >= G450 */ 932 { 933 //fixme: setup an intermediate buffer if vertical res is different than settings below! 934 //fixme: setup 2D or 3D engine to do screen_to_screen_scaled_filtered_blit between the buffers 935 // during vertical retrace! 936 if ((tv_target.flags & TV_BITS) == TV_PAL) 937 { 938 int diff; 939 940 /* defined by the PAL standard */ 941 tv_target.timing.v_total = m_timing.v_total; 942 /* we need to center the image on TV vertically. 943 * note that 576 is the maximum supported resolution for the PAL standard, 944 * this is already overscanning by approx 8-10% */ 945 diff = 576 - tv_target.timing.v_display; 946 /* if we cannot display the current vertical resolution fully, clip it */ 947 if (diff < 0) 948 { 949 tv_target.timing.v_display = 576; 950 diff = 0; 951 } 952 /* now center the image on TV by centering the vertical sync pulse */ 953 tv_target.timing.v_sync_start = tv_target.timing.v_display + 1 + (diff / 2); 954 tv_target.timing.v_sync_end = tv_target.timing.v_sync_start + 1; 955 } 956 else 957 { 958 int diff; 959 960 /* defined by the NTSC standard */ 961 tv_target.timing.v_total = m_timing.v_total; 962 /* we need to center the image on TV vertically. 963 * note that 480 is the maximum supported resolution for the NTSC standard, 964 * this is already overscanning by approx 8-10% */ 965 diff = 480 - tv_target.timing.v_display; 966 /* if we cannot display the current vertical resolution fully, clip it */ 967 if (diff < 0) 968 { 969 tv_target.timing.v_display = 480; 970 diff = 0; 971 } 972 /* now center the image on TV by centering the vertical sync pulse */ 973 tv_target.timing.v_sync_start = tv_target.timing.v_display + 1 + (diff / 2); 974 tv_target.timing.v_sync_end = tv_target.timing.v_sync_start + 1; 975 } 976 977 /* setup video PLL for G450/G550: 978 * this can be done in the normal way because the MAVEN works in slave mode! 979 * NOTE: must be done before programming CRTC2, or interlaced startup may fail. */ 980 981 //fixme: make sure videoPLL is powered up: XPWRCTRL b1=1 982 { 983 uint16 front_porch, back_porch, h_sync_length, burst_length, h_total, h_display; 984 uint32 chromasc; 985 uint64 pix_period; 986 uint16 h_total_wanted, leftover; 987 988 /* calculate tv_h_display in 'half pixelclocks' and adhere to MAVEN restrictions. 989 * ('half pixelclocks' exist because the MAVEN uses them...) */ 990 h_display = (((tv_target.timing.h_display << 1) + 3) & ~0x03); 991 if (h_display > 2044) h_display = 2044; 992 /* copy result to MAVEN TV mode */ 993 maventv_regs[0x31] = (h_display >> 3); 994 maventv_regs[0x32] = (h_display & 0x07); 995 996 /* calculate needed video pixelclock in kHz. 997 * NOTE: 998 * The clock calculated is based on MAVEN output, so each pixelclock period 999 * is in fact a 'half pixelclock' period compared to monitor mode use. */ 1000 tv_target.timing.pixel_clock = 1001 ((((uint64)h_display) * 1000000000) / m_timing.h_display); 1002 1003 /* tune display_mode adhering to CRTC2 restrictions */ 1004 /* (truncate h_display to 'whole pixelclocks') */ 1005 tv_target.timing.h_display = ((h_display >> 1) & ~0x07); 1006 tv_target.timing.h_sync_start = tv_target.timing.h_display + 8; 1007 1008 // g450_g550_maven_vid_pll_find(tv_target, &calc_pclk, &m_result, &n_result, &p_result, 1); 1009 /* adjust mode to actually used pixelclock */ 1010 tv_target.timing.pixel_clock = (calc_pclk * 1000); 1011 1012 /* program videoPLL */ 1013 // DXIW(VIDPLLM, m_result); 1014 // DXIW(VIDPLLN, n_result); 1015 // DXIW(VIDPLLP, p_result); 1016 1017 /* calculate videoclock 'half' period duration in picoseconds */ 1018 pix_period = (1000000000 / ((float)tv_target.timing.pixel_clock)) + 0.5; 1019 LOG(4,("MAVENTV: TV videoclock period is %d picoseconds\n", pix_period)); 1020 1021 /* calculate number of 'half' clocks per line according to pixelclock set */ 1022 /* fixme: try to setup the modes in such a way that 1023 * (h_total_clk % 16) == 0 because of the CRTC2 restrictions: 1024 * we want to loose the truncating h_total trick below if possible! */ 1025 /* Note: 1026 * This is here so we can see the wanted and calc'd timing difference. */ 1027 h_total_wanted = ((m_timing.h_total / ((float)pix_period)) + 0.5); 1028 LOG(4,("MAVENTV: TV h_total should be %d units\n", h_total_wanted)); 1029 1030 /* calculate chroma subcarrier value to setup: 1031 * do this as exact as possible because this signal is very sensitive.. */ 1032 chromasc = 1033 ((((uint64)0x100000000) * (m_timing.chroma_subcarrier / calc_pclk)) + 0.5); 1034 /* copy result to MAVEN TV mode */ 1035 maventv_regs[0] = ((chromasc >> 24) & 0xff); 1036 maventv_regs[1] = ((chromasc >> 16) & 0xff); 1037 maventv_regs[2] = ((chromasc >> 8) & 0xff); 1038 maventv_regs[3] = ((chromasc >> 0) & 0xff); 1039 LOG(4,("MAVENTV: TV chroma subcarrier divider set is $%08x\n", chromasc)); 1040 1041 /* calculate front porch in 'half pixelclocks' */ 1042 /* we always round up because of the h_total truncating 'trick' below, 1043 * which works in combination with the existing difference between 1044 * h_total_clk and h_total */ 1045 //fixme: prevent this if possible! 1046 front_porch = ((m_timing.front_porch / ((float)pix_period)) + 1); 1047 /* value must be even */ 1048 front_porch &= ~0x01; 1049 1050 /* calculate back porch in 'half pixelclocks' */ 1051 /* we always round up because of the h_total truncating 'trick' below, 1052 * which works in combination with the existing difference between 1053 * h_total_clk and h_total */ 1054 //fixme: prevent this if possible! 1055 back_porch = ((m_timing.back_porch / ((float)pix_period)) + 1); 1056 /* value must be even */ 1057 back_porch &= ~0x01; 1058 1059 /* calculate h_sync length in 'half pixelclocks' */ 1060 /* we always round up because of the h_total truncating 'trick' below, 1061 * which works in combination with the existing difference between 1062 * h_total_clk and h_total */ 1063 //fixme: prevent this if possible! 1064 h_sync_length = ((m_timing.h_sync_length / ((float)pix_period)) + 1); 1065 /* value must be even */ 1066 h_sync_length &= ~0x01; 1067 1068 /* calculate h_total in 'half pixelclocks' */ 1069 h_total = h_display + front_porch + back_porch + h_sync_length; 1070 1071 LOG(4,("MAVENTV: TV front_porch is %d clocks\n", front_porch)); 1072 LOG(4,("MAVENTV: TV back_porch is %d clocks\n", back_porch)); 1073 LOG(4,("MAVENTV: TV h_sync_length is %d clocks\n", h_sync_length)); 1074 LOG(4,("MAVENTV: TV h_display is %d clocks \n", h_display)); 1075 LOG(4,("MAVENTV: TV h_total is %d clocks\n", h_total)); 1076 1077 /* calculate color_burst length in 'half pixelclocks' */ 1078 burst_length = (((m_timing.color_burst /*- 1*/) / ((float)pix_period)) + 0.5); 1079 LOG(4,("MAVENTV: TV color_burst is %d clocks.\n", burst_length)); 1080 1081 /* copy result to MAVEN TV mode */ 1082 maventv_regs[0x09] = burst_length; 1083 1084 /* Calculate line length 'rest' that remains after truncating 1085 * h_total to adhere to the CRTC2 timing restrictions. */ 1086 leftover = h_total & 0x0F; 1087 /* if some 'rest' exists, we need to compensate for it... */ 1088 /* Note: 1089 * It's much better to prevent this from happening because this 1090 * 'trick' will decay TVout timing! (timing is nolonger official) */ 1091 if (leftover) 1092 { 1093 /* truncate line length to adhere to CRTC2 restrictions */ 1094 front_porch -= leftover; 1095 h_total -= leftover; 1096 1097 /* now set line length to closest CRTC2 valid match */ 1098 if (leftover < 3) 1099 { 1100 /* 1 <= old rest <= 2: 1101 * Truncated line length is closest match. */ 1102 LOG(4,("MAVENTV: CRTC2 h_total leftover discarded (< 3)\n")); 1103 } 1104 else 1105 { 1106 if (leftover < 10) 1107 { 1108 /* 3 <= old rest <= 9: 1109 * We use the NTSC killer circuitry to get closest match. 1110 * (The 'g400_crtc2_set_timing' routine will enable it 1111 * because of the illegal h_total timing we create here.) */ 1112 front_porch += 4; 1113 h_total += 4; 1114 LOG(4,("MAVENTV: CRTC2 h_total leftover corrected via killer (> 2, < 10)\n")); 1115 } 1116 else 1117 { 1118 /* 10 <= old rest <= 15: 1119 * Set closest valid CRTC2 match. */ 1120 front_porch += 16; 1121 h_total += 16; 1122 LOG(4,("MAVENTV: CRTC2 h_total leftover corrected via increase (> 9, < 16)\n")); 1123 } 1124 } 1125 } 1126 1127 /* (linux) fixme: maybe MAVEN has requirement 800 < h_total < 1184 */ 1128 maventv_regs[0x2C] = front_porch; 1129 maventv_regs[0x0A] = back_porch; 1130 maventv_regs[0x08] = h_sync_length; 1131 1132 /* change h_total to represent 'whole pixelclocks' */ 1133 h_total = h_total >> 1; 1134 1135 /* tune display_mode adhering to CRTC2 restrictions */ 1136 tv_target.timing.h_sync_end = (h_total & ~0x07) - 8; 1137 /* h_total is checked before being programmed! (NTSC killer circuitry) */ 1138 tv_target.timing.h_total = h_total; 1139 } 1140 1141 /* output Y/C and CVBS signals (| $40 needed for SCART) */ 1142 // DXIW(TVO_IDX, 0x80); 1143 // DXIW(TVO_DATA, 0x03); 1144 1145 /* select input colorspace */ 1146 //fixme?: has no effect on output picture on monitor or TV... 1147 //DXIW(TVO_IDX, 0x81); 1148 //DXIW(TVO_DATA, 0x00); 1149 1150 /* calculate vertical sync point */ 1151 { 1152 int upper; 1153 1154 /* set 625 lines for PAL or 525 lines for NTSC */ 1155 maventv_regs[0x17] = m_timing.v_total / 4; 1156 maventv_regs[0x18] = m_timing.v_total & 3; 1157 1158 /* calculate upper blanking range in field lines */ 1159 upper = (m_timing.v_total - tv_target.timing.v_sync_end) >> 1; 1160 1161 /* blank TVout above the line number calculated */ 1162 maventv_regs[0x33] = upper - 1; 1163 1164 /* set calculated vertical sync point */ 1165 // DXIW(TVO_IDX, 0x82); 1166 // DXIW(TVO_DATA, (upper & 0xff)); 1167 // DXIW(TVO_IDX, 0x83); 1168 // DXIW(TVO_DATA, ((upper >> 8) & 0xff)); 1169 LOG(4,("MAVENTV: TV upper blanking range set is %d\n", upper)); 1170 } 1171 1172 /* set fized horizontal sync point */ 1173 // DXIW(TVO_IDX, 0x84); 1174 // DXIW(TVO_DATA, 0x01); 1175 // DXIW(TVO_IDX, 0x85); 1176 // DXIW(TVO_DATA, 0x00); 1177 1178 /* connect DAC1 to CON1, CRTC2/'DAC2' to CON2 (TVout mode) */ 1179 // DXIW(OUTPUTCONN,0x0d); 1180 } 1181 1182 /* program new TVout mode */ 1183 for (val = 0x00; val <= 0x3D; val++) 1184 { 1185 /* if (si->ps.card_type <= G400MAX) 1186 { 1187 i2c_maven_write(val, maventv_regs[val]); 1188 } 1189 else 1190 */ { 1191 // DXIW(TVO_IDX, val); 1192 // DXIW(TVO_DATA, maventv_regs[val]); 1193 } 1194 } 1195 1196 /* leave mode-program mode */ 1197 // if (si->ps.card_type <= G400MAX) MAVW(PGM, 0x00); 1198 // else 1199 // { 1200 // DXIW(TVO_IDX, ENMAV_PGM); 1201 // DXIW(TVO_DATA, 0x00); 1202 1203 /* Select 2.0 Volt MAVEN DAC ref. so we have enough contrast/brightness range */ 1204 // DXIW(GENIOCTRL, DXIR(GENIOCTRL) | 0x40); 1205 // DXIW(GENIODATA, 0x00); 1206 // } 1207 1208 /* setup CRTC2 timing */ 1209 head2_set_timing(tv_target); 1210 1211 /* start whole thing if needed */ 1212 // if (si->ps.card_type <= G400MAX) MAVW(RESYNC, 0x20); 1213 1214 return 0; 1215 } 1216