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