diff --git a/src/add-ons/accelerants/nvidia/engine/nv_brooktreetv.c b/src/add-ons/accelerants/nvidia/engine/nv_brooktreetv.c index 93d718e217..b48dabd94d 100644 --- a/src/add-ons/accelerants/nvidia/engine/nv_brooktreetv.c +++ b/src/add-ons/accelerants/nvidia/engine/nv_brooktreetv.c @@ -180,1208 +180,602 @@ bool BT_probe() return btfound; } -//matrox old stuff.. -typedef struct { - uint32 h_total; - uint32 h_display; - uint32 h_sync_length; - uint32 front_porch; - uint32 back_porch; - uint32 color_burst; - uint32 v_total; - float chroma_subcarrier; -} gx50_maven_timing; - -void gxx0_maventv_PAL_init(uint8* buffer); -void gxx0_maventv_NTSC_init(uint8* buffer); -void gx50_maventv_PAL_timing(gx50_maven_timing *m_timing); -void gx50_maventv_NTSC_timing(gx50_maven_timing *m_timing); - -//fixme: setup fixed CRTC2 modes for all modes and block other modes: -// - 640x480, 800x600, 1024x768 NTSC and PAL overscan compensated modes (desktop) -// - 640x480, 720x480 NTSC and 768x576, 720x576 non-overscan compensated modes (video) -//fixme: try to implement 'fast' and 'slow' settings for all modes, -// so buffer duplication or skipping won't be neccesary for realtime video. -//fixme: try to setup the CRTC2 in interlaced mode for the video modes on <= G400MAX cards. - -/* find 'exact' valid video PLL setting */ -status_t g100_g400max_maventv_vid_pll_find( - display_mode target, unsigned int * ht_new, unsigned int * ht_last_line, - uint8 * m_result, uint8 * n_result, uint8 * p_result) +static uint8 BT_init_PAL640() { - int m = 0, n = 0, p = 0, m_max; - float diff, diff_smallest = 999999999; - int best[5], h_total_mod; - float fields_sec, f_vco; - /* We need to be exact, so work with clockperiods per field instead of with frequency. - * Make sure however we truncate these clocks to be integers! - * (The NTSC field frequency would otherwise prevent the 'whole number of clocks per field' - * check done in this routine later on...) */ - uint32 vco_clks_field, max_pclks_field, req_pclks_field; - /* We need this variable to be a float, because we need to be able to verify if this - * represents a whole number of clocks per field later on! */ - float calc_pclks_field; + uint8 stat; - LOG(2,("MAVENTV: searching for EXACT videoclock match\n")); + uint8 buffer[35]; - /* determine the max. reference-frequency postscaler setting for the current card */ - //fixme: check G100 and G200 m_max if exist and possible... - switch(si->ps.card_type) - { -/* case G100: - LOG(2,("MAVENTV: G100 restrictions apply\n")); - m_max = 32; - break; - case G200: - LOG(2,("MAVENTV: G200 restrictions apply\n")); - m_max = 32; - break; -*/ default: - LOG(2,("MAVENTV: G400/G400MAX restrictions apply\n")); - m_max = 32; - break; - } + buffer[0] = si->ps.tv_encoder.adress + WR; //issue IIC write command + buffer[1] = 0x76; //select first bt register to write to + buffer[2] = 0x60; + buffer[3] = 0x80; + buffer[4] = 0x8a; + buffer[5] = 0xa6; + buffer[6] = 0x68; + buffer[7] = 0xc1; + buffer[8] = 0x2e; + buffer[9] = 0xf2; + buffer[10] = 0x27; + buffer[11] = 0x00; + buffer[12] = 0xb0; + buffer[13] = 0x0a; + buffer[14] = 0x0b; + buffer[15] = 0x71; + buffer[16] = 0x5a; + buffer[17] = 0xe0; + buffer[18] = 0x36; + buffer[19] = 0x00; + buffer[20] = 0x50; + buffer[21] = 0x72; + buffer[22] = 0x1c; + buffer[23] = 0x8d; //chip-pin CLKI is pixel clock (only non-default here!) + buffer[24] = 0x24; + buffer[25] = 0xf0; + buffer[26] = 0x58; + buffer[27] = 0x81; + buffer[28] = 0x49; + buffer[29] = 0x8c; + buffer[30] = 0x0c; + buffer[31] = 0x8c; + buffer[32] = 0x79; + buffer[33] = 0x26; + buffer[34] = 0x00; - /* set number of fields per second to generate */ - if ((target.flags & TV_BITS) == TV_PAL) - fields_sec = 50.0; - else - fields_sec = 59.94; + /* reset status */ + i2c_flag_error (-1); - /* determine the max. pixelclock for the current videomode */ - switch (target.space) - { - case B_RGB16_LITTLE: - max_pclks_field = (si->ps.max_dac2_clock_16 * 1000000) / fields_sec; - break; - case B_RGB32_LITTLE: - max_pclks_field = (si->ps.max_dac2_clock_32 * 1000000) / fields_sec; - break; - default: - /* use fail-safe value */ - max_pclks_field = (si->ps.max_dac2_clock_32 * 1000000) / fields_sec; - break; - } - /* if some dualhead mode is active, an extra restriction might apply */ - if ((target.flags & DUALHEAD_BITS) && (target.space == B_RGB32_LITTLE)) - max_pclks_field = (si->ps.max_dac2_clock_32dh * 1000000) / fields_sec; + i2c_bstart(si->ps.tv_encoder.bus); + i2c_writebuffer(si->ps.tv_encoder.bus, buffer, sizeof(buffer)); + i2c_bstop(si->ps.tv_encoder.bus); + /* log on errors */ + stat = i2c_flag_error(0); + if (stat) + LOG(4,("Brooktree: I2C errors occurred while setting mode PAL640\n")); - /* Checkout all possible Htotal settings within the current granularity step - * of CRTC2 to get a real close videoclock match! - * (The MAVEN apparantly has a granularity of 1 pixel, while CRTC2 has 8 pixels) */ - for (h_total_mod = 0; h_total_mod < 8; h_total_mod++) - { - LOG(2,("MAVENTV: trying h_total modification of +%d...\n", h_total_mod)); + return stat; +}//end BT_init_PAL640. - /* Calculate videoclock to be a bit to high so we can compensate for an exact - * match via h_total_lastline.. */ - *ht_new = target.timing.h_total + h_total_mod + 2; - - /* Make sure the requested pixelclock is within the PLL's operational limits */ - /* lower limit is min_video_vco divided by highest postscaler-factor */ - req_pclks_field = *ht_new * target.timing.v_total; - if (req_pclks_field < (((si->ps.min_video_vco * 1000000) / fields_sec) / 8.0)) - { - req_pclks_field = (((si->ps.min_video_vco * 1000000) / fields_sec) / 8.0); - LOG(4,("MAVENTV: WARNING, clamping at lowest possible videoclock\n")); - } - /* upper limit is given by pins in combination with current active mode */ - if (req_pclks_field > max_pclks_field) - { - req_pclks_field = max_pclks_field; - LOG(4,("MAVENTV: WARNING, clamping at highest possible videoclock\n")); - } - - /* iterate through all valid PLL postscaler settings */ - for (p=0x01; p < 0x10; p = p<<1) - { - /* calc the needed number of VCO clocks per field for this postscaler setting */ - vco_clks_field = req_pclks_field * p; - - /* check if this is within range of the VCO specs */ - if ((vco_clks_field >= ((si->ps.min_video_vco * 1000000) / fields_sec)) && - (vco_clks_field <= ((si->ps.max_video_vco * 1000000) / fields_sec))) - { - /* iterate trough all valid reference-frequency postscaler settings */ - for (m = 2; m <= m_max; m++) - { - /* calculate VCO postscaler setting for current setup.. */ - n = (int)(((vco_clks_field * m) / ((si->ps.f_ref * 1000000) / fields_sec)) + 0.5); - /* ..and check for validity */ - if ((n < 8) || (n > 128)) continue; - - /* special TVmode stuff starts here (rest is in fact standard): */ - /* calculate number of videoclocks per field */ - calc_pclks_field = - (((uint32)((si->ps.f_ref * 1000000) / fields_sec)) * n) / ((float)(m * p)); - - /* we need a whole number of clocks per field, otherwise it won't work correctly. - * (TVout will flicker, green fields will occur) */ - if (calc_pclks_field != (uint32)calc_pclks_field) continue; - - /* check if we have the min. needed number of clocks per field for a sync lock */ - if (calc_pclks_field < ((*ht_new * (target.timing.v_total - 1)) + 2)) continue; - - /* calc number of clocks we have for the last field line */ - *ht_last_line = calc_pclks_field - (*ht_new * (target.timing.v_total - 1)); - - /* check if we haven't got too much clocks in the last field line for a sync lock */ - if (*ht_last_line > *ht_new) continue; - - /* we have a match! */ - /* calculate the difference between a full line and the last line */ - diff = *ht_new - *ht_last_line; - - /* if this last_line comes closer to a full line than earlier 'hits' then use it */ - if (diff < diff_smallest) - { - /* log results */ - if (diff_smallest == 999999999) - LOG(2,("MAVENTV: MATCH, ")); - else - LOG(2,("MAVENTV: better MATCH,")); - f_vco = (si->ps.f_ref / m) * n; - LOG(2,("found vid VCO freq %fMhz, pixclk %fMhz\n", f_vco, (f_vco / p))); - LOG(2,("MAVENTV: mnp(ex. filter) 0x%02x 0x%02x 0x%02x, h_total %d, ht_lastline %d\n", - (m - 1), (n - 1), (p - 1), (*ht_new - 2), (*ht_last_line - 2))); - - /* remember this best match */ - diff_smallest = diff; - best[0] = m; - best[1] = n; - best[2] = p; - /* h_total to use for this setting: - * exclude the 'calculate clock a bit too high' trick */ - best[3] = *ht_new - 2; - /* ht_last_line to use for this setting: - * exclude the 'calculate clock a bit too high' trick */ - best[4] = *ht_last_line - 2; - } - } - } - } - } - LOG(2,("MAVENTV: search completed.\n")); - - /* setup the scalers programming values for found optimum setting */ - m = best[0] - 1; - n = best[1] - 1; - p = best[2] - 1; - - /* if no match was found set fixed PLL frequency so we have something valid at least */ - if (diff_smallest == 999999999) - { - LOG(4,("MAVENTV: WARNING, no MATCH found!\n")); - - if (si->ps.f_ref == 27.000) - { - /* set 13.5Mhz */ - m = 0x03; - n = 0x07; - p = 0x03; - } - else - { - /* set 14.31818Mhz */ - m = 0x01; - n = 0x07; - p = 0x03; - } - best[3] = target.timing.h_total; - best[4] = target.timing.h_total; - } - - /* calc the needed PLL loopbackfilter setting belonging to current VCO speed */ - f_vco = (si->ps.f_ref / (m + 1)) * (n + 1); - LOG(2,("MAVENTV: using vid VCO frequency %fMhz\n", f_vco)); - - switch(si->ps.card_type) - { -/* case G100: - case G200: - for(;;) - { - if (f_vco >= 180) {p |= (0x03 << 3); break;}; - if (f_vco >= 140) {p |= (0x02 << 3); break;}; - if (f_vco >= 100) {p |= (0x01 << 3); break;}; - break; - } - break; -*/ default: - for(;;) - { - if (f_vco >= 240) {p |= (0x03 << 3); break;}; - if (f_vco >= 170) {p |= (0x02 << 3); break;}; - if (f_vco >= 110) {p |= (0x01 << 3); break;}; - break; - } - break; - } - - /* return results */ - *m_result = m; - *n_result = n; - *p_result = p; - *ht_new = best[3]; - *ht_last_line = best[4]; - - /* display the found pixelclock values */ - LOG(2,("MAVENTV: vid PLL check: got %fMHz, mnp 0x%02x 0x%02x 0x%02x\n", - (f_vco / ((p & 0x07) + 1)), m, n, p)); - LOG(2,("MAVENTV: new h_total %d, ht_lastline %d\n", *ht_new, *ht_last_line)); - - /* return status */ - if (diff_smallest == 999999999) return B_ERROR; - return B_OK; -} - - /* Notes about timing: - * Note: - * all horizontal timing is measured in pixelclock periods; - * all? vertical timing is measured in field? lines. */ - - /* Note: - * <= G400MAX cards have a fixed 27Mhz(?) clock for TV timing register values, - * while on G450/G550 these need to be calculated based on the video pixelclock. */ - - - /* Notes about signal strengths: - * Note: - * G400 and earlier cards have a fixed reference voltage of +2.6 Volt; - * G450 and G550 cards MAVEN DACs have a switchable ref voltage of +1.5/+2.0 Volt. - * - * This voltage is used to feed the videosignals: - * - Hsync pulse level; - * - Lowest active video output level; - * - Highest active video output level. - * These actual voltages are set via 10bit DACs. - * - * G450/G550: - * The color burst amplitude videosignal is fed by 80% of the above mentioned - * ref. voltage, and is set via an 8bit DAC. - * On G400 and earlier cards the ref. voltage is different, and also differs - * for PAL and NTSC mode. */ - - /* Note: - * Increasing the distance between the highest and lowest active video output - * level increases contrast; decreasing it decreases contrast. */ - - /* Note: - * Increasing both the highest and lowest active video output level with the - * same amount increases brightness; decreasing it decreases brightness. */ - - /* Note: - * Increasing the Hsync pulse level increases the black level, so decreases - * brightness and contrast. */ - -/* Preset maven PAL output (625lines, 50Hz mode) */ -void gxx0_maventv_PAL_init(uint8* buffer) +static uint8 BT_init_PAL800() { - uint16 value; - - /* Chroma subcarrier divider */ - buffer[0x00] = 0x2A; - buffer[0x01] = 0x09; - buffer[0x02] = 0x8A; - buffer[0x03] = 0xCB; - - buffer[0x04] = 0x00; - buffer[0x05] = 0x00; - buffer[0x06] = 0xF9; - buffer[0x07] = 0x00; - /* Hsync pulse length */ - buffer[0x08] = 0x7E; - /* color burst length */ - buffer[0x09] = 0x44; - /* back porch length */ - buffer[0x0a] = 0x9C; - - /* color burst amplitude */ -/* if (si->ps.card_type <= G400MAX) - { - buffer[0x0b] = 0x3e; - } - else - { -*/ buffer[0x0b] = 0x48; -// } - - buffer[0x0c] = 0x21; - buffer[0x0d] = 0x00; - -// if (si->ps.card_type <= G400MAX) -// { - /* Lowest active video output level. - * Warning: make sure this stays above (or equals) the sync pulse level! */ -// value = 0x0ea; -// buffer[0x0e] = ((value >> 2) & 0xff); -// buffer[0x0f] = (value & 0x03); - /* horizontal sync pulse level */ -// buffer[0x10] = ((value >> 2) & 0xff); -// buffer[0x11] = (value & 0x03); -// } -// else - { - /* Lowest active video output level. - * Warning: make sure this stays above (or equals) the sync pulse level! */ - value = 0x130; - buffer[0x0e] = ((value >> 2) & 0xff); - buffer[0x0f] = (value & 0x03); - /* horizontal sync pulse level */ - buffer[0x10] = ((value >> 2) & 0xff); - buffer[0x11] = (value & 0x03); - } - - buffer[0x12] = 0x1A; - buffer[0x13] = 0x2A; + uint8 stat; - /* functional unit */ - buffer[0x14] = 0x1C; - buffer[0x15] = 0x3D; - buffer[0x16] = 0x14; + uint8 buffer[35]; + + buffer[0] = si->ps.tv_encoder.adress + WR; //issue IIC write command + buffer[1] = 0x76; //select first bt register to write to + buffer[2] = 0x00; + buffer[3] = 0x20; + buffer[4] = 0xaa; + buffer[5] = 0xca; + buffer[6] = 0x9a; + buffer[7] = 0x0d; + buffer[8] = 0x29; + buffer[9] = 0xfc; + buffer[10] = 0x39; + buffer[11] = 0x00; + buffer[12] = 0xc0; + buffer[13] = 0x8c; + buffer[14] = 0x03; + buffer[15] = 0xee; + buffer[16] = 0x5f; + buffer[17] = 0x58; + buffer[18] = 0x3a; + buffer[19] = 0x66; + buffer[20] = 0x96; + buffer[21] = 0x00; + buffer[22] = 0x00; + buffer[23] = 0x90; //chip-pin CLKI is pixel clock (only non-default here!) + buffer[24] = 0x24; + buffer[25] = 0xf0; + buffer[26] = 0x57; + buffer[27] = 0x80; + buffer[28] = 0x48; + buffer[29] = 0x8c; + buffer[30] = 0x18; + buffer[31] = 0x28; + buffer[32] = 0x87; + buffer[33] = 0x1f; + buffer[34] = 0x00; + + /* reset status */ + i2c_flag_error (-1); + + i2c_bstart(si->ps.tv_encoder.bus); + i2c_writebuffer(si->ps.tv_encoder.bus, buffer, sizeof(buffer)); + i2c_bstop(si->ps.tv_encoder.bus); + /* log on errors */ + stat = i2c_flag_error(0); + if (stat) + LOG(4,("Brooktree: I2C errors occurred while setting mode PAL800\n")); + + return stat; +}//end BT_init_PAL800. + +static uint8 BT_init_NTSC640() +{ + uint8 stat; - /* vertical total */ //(=625) - /* b9-2 */ - buffer[0x17] = 0x9C; - /* b1-0 in b1-0 */ - buffer[0x18] = 0x01; + uint8 buffer[35]; - buffer[0x19] = 0x00; - buffer[0x1a] = 0xFE; - buffer[0x1b] = 0x7E; - buffer[0x1c] = 0x60; - buffer[0x1d] = 0x05; + buffer[0] = si->ps.tv_encoder.adress + WR; //issue IIC write command + buffer[1] = 0x76; //select first bt register to write to + buffer[2] = 0x00; + buffer[3] = 0x80; + buffer[4] = 0x84; + buffer[5] = 0x96; + buffer[6] = 0x60; + buffer[7] = 0x7d; + buffer[8] = 0x22; + buffer[9] = 0xd4; + buffer[10] = 0x27; + buffer[11] = 0x00; + buffer[12] = 0x10; + buffer[13] = 0x7e; + buffer[14] = 0x03; + buffer[15] = 0x58; + buffer[16] = 0x4b; + buffer[17] = 0xe0; + buffer[18] = 0x36; + buffer[19] = 0x92; + buffer[20] = 0x54; + buffer[21] = 0x0e; + buffer[22] = 0x88; + buffer[23] = 0x8c; //chip-pin CLKI is pixel clock (only non-default here!) + buffer[24] = 0x0a; + buffer[25] = 0xe5; + buffer[26] = 0x76; + buffer[27] = 0x79; + buffer[28] = 0x44; + buffer[29] = 0x85; + buffer[30] = 0x00; + buffer[31] = 0x00; + buffer[32] = 0x80; + buffer[33] = 0x20; + buffer[34] = 0x00; - /* Highest active video output level. - * Warning: make sure this stays above the lowest active video output level! */ -/* if (si->ps.card_type <= G400MAX) + /* reset status */ + i2c_flag_error (-1); + + i2c_bstart(si->ps.tv_encoder.bus); + i2c_writebuffer(si->ps.tv_encoder.bus, buffer, sizeof(buffer)); + i2c_bstop(si->ps.tv_encoder.bus); + /* log on errors */ + stat = i2c_flag_error(0); + if (stat) + LOG(4,("Brooktree: I2C errors occurred while setting mode NTSC640\n")); + + return stat; +}//end BT_init_NTSC640. + +static uint8 BT_init_NTSC800() +{ + uint8 stat; + + uint8 buffer[35]; + + buffer[0] = si->ps.tv_encoder.adress + WR; //issue IIC write command + buffer[1] = 0x76; //select first bt register to write to + buffer[2] = 0xa0; + buffer[3] = 0x20; + buffer[4] = 0xb6; + buffer[5] = 0xce; + buffer[6] = 0x84; + buffer[7] = 0x55; + buffer[8] = 0x20; + buffer[9] = 0xd8; + buffer[10] = 0x39; + buffer[11] = 0x00; + buffer[12] = 0x70; + buffer[13] = 0x42; + buffer[14] = 0x03; + buffer[15] = 0xdf; + buffer[16] = 0x56; + buffer[17] = 0x58; + buffer[18] = 0x3a; + buffer[19] = 0xcd; + buffer[20] = 0x9c; + buffer[21] = 0x14; + buffer[22] = 0x3b; + buffer[23] = 0x91; //chip-pin CLKI is pixel clock (only non-default here!) + buffer[24] = 0x0a; + buffer[25] = 0xe5; + buffer[26] = 0x74; + buffer[27] = 0x77; + buffer[28] = 0x43; + buffer[29] = 0x85; + buffer[30] = 0xba; + buffer[31] = 0xe8; + buffer[32] = 0xa2; + buffer[33] = 0x17; + buffer[34] = 0x00; + + /* reset status */ + i2c_flag_error (-1); + + i2c_bstart(si->ps.tv_encoder.bus); + i2c_writebuffer(si->ps.tv_encoder.bus, buffer, sizeof(buffer)); + i2c_bstop(si->ps.tv_encoder.bus); + /* log on errors */ + stat = i2c_flag_error(0); + if (stat) + LOG(4,("Brooktree: I2C errors occurred while setting mode PAL800\n")); + + return stat; +}//end BT_init_NTSC800. + +static uint8 BT_init_PAL720() +{ + uint8 stat; + + uint8 buffer[35]; + + buffer[0] = si->ps.tv_encoder.adress + WR; //issue IIC write command + buffer[1] = 0x76; //select first bt register to write to + buffer[2] = 0xf0; + buffer[3] = 0xd0; + buffer[4] = 0x82; + buffer[5] = 0x9c; + buffer[6] = 0x5a; + buffer[7] = 0x31; + buffer[8] = 0x16; + buffer[9] = 0x22; + buffer[10] = 0xa6; + buffer[11] = 0x00; + buffer[12] = 0x78; + buffer[13] = 0x93; + buffer[14] = 0x03; + buffer[15] = 0x71; + buffer[16] = 0x2a; + buffer[17] = 0x40; + buffer[18] = 0x0a; + buffer[19] = 0x00; + buffer[20] = 0x50; + buffer[21] = 0x55; + buffer[22] = 0x55; + buffer[23] = 0x8c; //chip-pin CLKI is pixel clock (only non-default here!) + buffer[24] = 0x24; + buffer[25] = 0xf0; + buffer[26] = 0x59; + buffer[27] = 0x82; + buffer[28] = 0x49; + buffer[29] = 0x8c; + buffer[30] = 0x8e; + buffer[31] = 0xb0; + buffer[32] = 0xe6; + buffer[33] = 0x28; + buffer[34] = 0x00; + + /* reset status */ + i2c_flag_error (-1); + + i2c_bstart(si->ps.tv_encoder.bus); + i2c_writebuffer(si->ps.tv_encoder.bus, buffer, sizeof(buffer)); + i2c_bstop(si->ps.tv_encoder.bus); + /* log on errors */ + stat = i2c_flag_error(0); + if (stat) + LOG(4,("Brooktree: I2C errors occurred while setting mode PAL720\n")); + + return stat; +}//end BT_init_PAL720. + +static uint8 BT_init_NTSC720() +{ + uint8 stat; + + uint8 buffer[35]; + + buffer[0] = si->ps.tv_encoder.adress + WR; //issue IIC write command + buffer[1] = 0x76; //select first bt register to write to. + buffer[2] = 0xf0; //lsb h_clk_o: overscan comp = 0, so h_clk_o = 2 * h_clk_i (VSR=2 = scaling=1) + buffer[3] = 0xd0; //lsb h_active: h_active = 720 pixels wide port + buffer[4] = 0x83; //scope: OK hsync_width: (hsync_width / h_clk_o) * 63.55556uS = 4.70uS for NTSC + buffer[5] = 0x98; //scope: OK hburst_begin: (hburst_begin / h_clk_o) * 63.55556uS = 5.3uS for NTSC + buffer[6] = 0x5e; //scope: OK hburst_end: ((hburst_end + 128) / h_clk_o) * 63.55556uS = 7.94uS for NTSC + + //How to find the correct values for h_blank_o and v_blank_o: + // 1. Calculate h_blank_o according to initial setting guideline mentioned below; + // 2. Set v_blank_o in the neighbourhood of $18, so that TV picture does not have ghosts on right side in it while + // horizontal position is about OK; + // 3. Then tune h_blank_o for centered output on scope (look at front porch and back porch); + // 4. Now shift the TV output using Hsync_offset for centered output while looking at TV (in method 'SetBT_Hphase' above); + // 5. If no vertical shivering occurs when image is centered, you're done. Else: + // 6. Modify the RIVA (BeScreen) h_sync_start setting somewhat to get stable centered picture possible on TV AND!: + // 7. Make sure you update the Chrontel horizontal Phase setting also then! + + buffer[7] = 0x28; //scope: tuned. lsb h_blank_o: h_blank_o = horizontal viewport location on TV + //(guideline for initial setting: (h_blank_o / h_clk_0) * 63.55556uS = 9.5uS for NTSC) + buffer[8] = 0x18; //try-out; scope: checked against other modes, looks OK. v_blank_o: 1e active line ('pixel') + + buffer[9] = 0xf2; //v_active_o: = (active output lines + 2) / field (on TV) + buffer[10] = 0x26; //lsn = msn h_clk_o; + //b4-5 = msbits h_active; + //b7 = b8 v_avtive_o. + buffer[11] = 0x00; //h_fract is always 0. + buffer[12] = 0x78; //lsb h_clk_i: h_clk_i is horizontal total = 888. + buffer[13] = 0x90; //try-out; lsb h_blank_i: #clks between start sync and new line 1st pixel; copy to VGA delta-sync! + buffer[14] = 0x03; //b2-0 = msn h_clk_i; + //try-out: b3 = msn h_blank_i; + //b4 = vblankdly is always 0. + buffer[15] = 0x0d; //lsb v_lines_i: v_lines_i = 525 + buffer[16] = 0x1a; //try-out; v_blank_i: #input lines between start sync and new line (pixel); copy to VGA delta-sync! + //Make sure though that this value for the BT is *even*, or image will shiver a *lot* horizontally on TV. + buffer[17] = 0xe0; //lsb v_active_i: v_active_i = 480 + buffer[18] = 0x36; //b1-0 = msn v_lines_i; + //b3-2 = msn v_active_i; + //b5-4 = ylpf = 3; + //b7-6 = clpf = 0. + buffer[19] = 0x00; //lsb v_scale: v_scale = off = $1000 + buffer[20] = 0x50; //b5-0 = msn v_scale; + //scope: tuned. b7-6 = msn h_blank_o. + //(((PLL_INT + (PLL_FRACT/65536)) / 6) * 13500000) = PIXEL_CLK = (hor.tot. * v_lines_i * 60Hz) + buffer[21] = 0x98; //lsb PLL fract: PLL fract = 0x6e98 + buffer[22] = 0x6e; //msb PLL fract + buffer[23] = 0x8c; //b5-0 = PLL int: PLL int = 0x0c; + //b6 = by_pll: by_pll = 0; + //b7 = EN_XCLK: chip-pin CLKI is pixel clock. + buffer[24] = 0x0a; //b0 = ni_out is always 0; + //b1 = setup = 1 for NTSC; + //b2 = 625line = 0 for NTSC; + //b3 = vsync_dur = 1 for NTSC; + //b4 = dic_screset is always 0; + //b5 = pal_md = 0 for NTSC; + //b6 = eclip is always 0; + //b7 = reserved (en_scart) is always 0. + buffer[25] = 0xe5; //sync_amp $e5 for NTSC + buffer[26] = 0x75; //bst_amp $74-$76 for NTSC + buffer[27] = 0x78; //mcr: r-y $77-$79 for NTSC + buffer[28] = 0x44; //mcb: b-y $43-$44 for NTSC + buffer[29] = 0x85; //my: y $85 for NTSC + buffer[30] = 0x3c; //lsb msc: msc b31-0: NTSC formula: ((3579545 / pixelclk) * 2^32) = MSC + buffer[31] = 0x91; //msc = $20c2913c + buffer[32] = 0xc2; + buffer[33] = 0x20; //msb msc. + buffer[34] = 0x00; //phase_off always $00 + + /* reset status */ + i2c_flag_error (-1); + + i2c_bstart(si->ps.tv_encoder.bus); + i2c_writebuffer(si->ps.tv_encoder.bus, buffer, sizeof(buffer)); + i2c_bstop(si->ps.tv_encoder.bus); + /* log on errors */ + stat = i2c_flag_error(0); + if (stat) + LOG(4,("Brooktree: I2C errors occurred while setting mode NTSC720\n")); + + return stat; +}//end BT_init_NTSC720. + +static uint8 BT_init_PAL800_OS() +{ + uint8 stat; + + uint8 buffer[35]; + + buffer[0] = si->ps.tv_encoder.adress + WR; //issue IIC write command + buffer[1] = 0x76; //select first bt register to write to. + buffer[2] = 0x60; //lsb h_clk_o: overscan comp = 0, so h_clk_o = 2 * h_clk_i (VSR=2 = scaling=1) + buffer[3] = 0x20; //lsb h_active: h_active = 800 pixels wide port + buffer[4] = 0x8b; //scope: OK hsync_width: (hsync_width / h_clk_o) * 64.0uS = 4.70uS for PAL + buffer[5] = 0xa5; //scope: OK hburst_begin: (hburst_begin / h_clk_o) * 64.0uS = 5.6uS for PAL + buffer[6] = 0x6b; //scope: OK hburst_end: ((hburst_end + 128) / h_clk_o) * 64.0uS = 7.97uS for PAL + + //How to find the correct values for h_blank_o and v_blank_o: + // 1. Calculate h_blank_o according to initial setting guideline mentioned below; + // 2. Set v_blank_o in the neighbourhood of $18, so that TV picture does not have ghosts on right side in it while + // horizontal position is about OK; + // 3. Then tune h_blank_o for centered output on scope (look at front porch and back porch); + // 4. Now shift the TV output using Hsync_offset for centered output while looking at TV (in method 'SetBT_Hphase' above); + // 5. If no vertical shivering occurs when image is centered, you're done. Else: + // 6. Modify the RIVA (BeScreen) h_sync_start setting somewhat to get stable centered picture possible on TV AND!: + // 7. Make sure you update the Chrontel horizontal Phase setting also then! + + if (si->ps.tv_encoder.type >= CX25870)//set CX value { - value = 0x24f; - buffer[0x1e] = ((value >> 2) & 0xff); - buffer[0x1f] = (value & 0x03); + buffer[7] = 0xf4; + buffer[8] = 0x17; } else -*/ { - value = 0x300; - buffer[0x1e] = ((value >> 2) & 0xff); - buffer[0x1f] = (value & 0x03); + { //set BT value + buffer[7] = 0xc0;//scope: tuned. lsb h_blank_o: h_blank_o = horizontal viewport location on TV + //(guideline for initial setting: (h_blank_o / h_clk_0) * 64.0uS = 10.0uS for PAL) + buffer[8] = 0x18;//try-out; scope: checked against other modes, looks OK. v_blank_o: 1e active line ('pixel') } - /* saturation (field?) #1 */ -// if (si->ps.card_type <= G400MAX) -// buffer[0x20] = 0x72; -// else - buffer[0x20] = 0xA5; + buffer[9] = 0x2e; //v_active_o: = (active output lines + 2) / field (on TV) + buffer[10] = 0xb7; //lsn = msn h_clk_o; + //b4-5 = msbits h_active; + //b7 = b8 v_avtive_o. + buffer[11] = 0x00; //h_fract is always 0. + buffer[12] = 0xb0; //lsb h_clk_i: h_clk_i is horizontal total = 944. - buffer[0x21] = 0x07; + if (si->ps.tv_encoder.type >= CX25870)//set CX value + buffer[13] = 0x20; + else //set BT value + buffer[13] = 0x14;//try-out; lsb h_blank_i: #clks between start sync and new line 1st pixel; copy to VGA delta-sync! - /* saturation (field?) #2 */ -// if (si->ps.card_type <= G400MAX) -// buffer[0x22] = 0x72; -// else - buffer[0x22] = 0xA5; + buffer[14] = 0x03; //b2-0 = msn h_clk_i; + //try-out: b3 = msn h_blank_i; + //b4 = vblankdly is always 0. + buffer[15] = 0x71; //lsb v_lines_i: v_lines_i = 625 - buffer[0x23] = 0x00; - buffer[0x24] = 0x00; - /* hue? */ - buffer[0x25] = 0x00; + if (si->ps.tv_encoder.type >= CX25870)//set CX value + buffer[16] = 0x08; + else //set BT value + buffer[16] = 0x2a;//try-out; v_blank_i: #input lines between start sync and new line (pixel); copy to VGA delta-sync! + //Make sure though that this value for the BT is *even*, or image will shiver a *lot* horizontally on TV. - buffer[0x26] = 0x08; - buffer[0x27] = 0x04; - buffer[0x28] = 0x00; - buffer[0x29] = 0x1A; + buffer[17] = 0x58; //lsb v_active_i: v_active_i = 600 + buffer[18] = 0x3a; //b1-0 = msn v_lines_i; + //b3-2 = msn v_active_i; + //b5-4 = ylpf = 3; + //b7-6 = clpf = 0. + buffer[19] = 0x00; //lsb v_scale: v_scale = off = $1000 + buffer[20] = 0x10; //b5-0 = msn v_scale; + //scope: tuned. b7-6 = msn h_blank_o. + //(((PLL_INT + (PLL_FRACT/65536)) / 6) * 13500000) = PIXEL_CLK = (hor.tot. * v_lines_i * 50Hz) + buffer[21] = 0x72; //lsb PLL fract: PLL fract = 0x1c72 + buffer[22] = 0x1c; //msb PLL fract + buffer[23] = 0x8d; //b5-0 = PLL int: PLL int = 0x0d; + //b6 = by_pll: by_pll = 0; + //b7 = EN_XCLK: chip-pin CLKI is pixel clock. + buffer[24] = 0x24; //b0 = ni_out is always 0; + //b1 = setup = 0 for PAL; + //b2 = 625line = 1 for PAL; + //b3 = vsync_dur = 0 for PAL; + //b4 = dic_screset is always 0; + //b5 = pal_md = 1 for PAL; + //b6 = eclip is always 0; + //b7 = reserved (en_scart) is always 0. + buffer[25] = 0xf0; //sync_amp $f0 for PAL + buffer[26] = 0x57; //bst_amp $57-$58 for PAL + buffer[27] = 0x80; //mcr: r-y $80-$81 for PAL + buffer[28] = 0x48; //mcb: b-y $48-$49 for PAL + buffer[29] = 0x8c; //my: y $8c for PAL + buffer[30] = 0x31; //lsb msc: msc b31-0: PAL formula: ((4433619 / pixelclk) * 2^32) = MSC + buffer[31] = 0x8c; //msc = $26798c31 + buffer[32] = 0x79; + buffer[33] = 0x26; //msb msc. + buffer[34] = 0x00; //phase_off always $00 - /* functional unit */ - buffer[0x2a] = 0x55; - buffer[0x2b] = 0x01; + /* reset status */ + i2c_flag_error (-1); - /* front porch length */ - buffer[0x2c] = 0x26; + i2c_bstart(si->ps.tv_encoder.bus); + i2c_writebuffer(si->ps.tv_encoder.bus, buffer, sizeof(buffer)); + i2c_bstop(si->ps.tv_encoder.bus); + /* log on errors */ + stat = i2c_flag_error(0); + if (stat) + LOG(4,("Brooktree: I2C errors occurred while setting mode PAL800 OS\n")); - /* functional unit */ - buffer[0x2d] = 0x07; - buffer[0x2e] = 0x7E; + return stat; +}//end BT_init_PAL800_OS. - /* functional unit */ - buffer[0x2f] = 0x02; - buffer[0x30] = 0x54; - - /* horizontal visible */ - value = 0x580; - buffer[0x31] = ((value >> 3) & 0xff); - buffer[0x32] = (value & 0x07); - - /* upper blanking (in field lines) */ - buffer[0x33] = 0x14; //=((v_total - v_sync_end)/2) -1 - - buffer[0x34] = 0x49; - buffer[0x35] = 0x00; - buffer[0x36] = 0x00; - buffer[0x37] = 0xA3; - buffer[0x38] = 0xC8; - buffer[0x39] = 0x22; - buffer[0x3a] = 0x02; - buffer[0x3b] = 0x22; - - /* functional unit */ - buffer[0x3c] = 0x3F; - buffer[0x3d] = 0x03; -} - -/* Preset maven NTSC output (525lines, 59.94Hz mode) */ -void gxx0_maventv_NTSC_init(uint8* buffer) +static uint8 BT_init_NTSC640_OS() { - uint16 value; + uint8 stat; + + uint8 buffer[35]; - /* Chroma subcarrier frequency */ - buffer[0x00] = 0x21; - buffer[0x01] = 0xF0; - buffer[0x02] = 0x7C; - buffer[0x03] = 0x1F; + buffer[0] = si->ps.tv_encoder.adress + WR; //issue IIC write command + buffer[1] = 0x76; //select first bt register to write to. + buffer[2] = 0x20; //lsb h_clk_o: overscan comp = 0, so h_clk_o = 2 * h_clk_i (VSR=2 = scaling=1) + buffer[3] = 0x80; //lsb h_active: h_active = 640 pixels wide port + buffer[4] = 0x74; //scope: OK hsync_width: (hsync_width / h_clk_o) * 63.55556uS = 4.70uS for NTSC + buffer[5] = 0x83; //scope: OK hburst_begin: (hburst_begin / h_clk_o) * 63.55556uS = 5.3uS for NTSC + buffer[6] = 0x44; //scope: OK hburst_end: ((hburst_end + 128) / h_clk_o) * 63.55556uS = 7.94uS for NTSC - buffer[0x04] = 0x00; - buffer[0x05] = 0x00;//b1 = ON enables colorbar testimage - buffer[0x06] = 0xF9;//b0 = ON enables MAVEN TV output - buffer[0x07] = 0x00;//influences the colorburst signal amplitude somehow + //How to find the correct values for h_blank_o and v_blank_o: + // 1. Calculate h_blank_o according to initial setting guideline mentioned below; + // 2. Set v_blank_o in the neighbourhood of $18, so that TV picture does not have ghosts on right side in it while + // horizontal position is about OK; + // 3. Then tune h_blank_o for centered output on scope (look at front porch and back porch); + // 4. Now shift the TV output using Hsync_offset for centered output while looking at TV (in method 'SetBT_Hphase' above); + // 5. If no vertical shivering occurs when image is centered, you're done. Else: + // 6. Modify the RIVA (BeScreen) h_sync_start setting somewhat to get stable centered picture possible on TV AND!: + // 7. Make sure you update the Chrontel horizontal Phase setting also then! - /* Hsync pulse length */ - buffer[0x08] = 0x7E; - /* color burst length */ - buffer[0x09] = 0x43; - /* back porch length */ - buffer[0x0a] = 0x7E; + buffer[7] = 0xf7; //scope: tuned. lsb h_blank_o: h_blank_o = horizontal viewport location on TV: + //(guideline for initial setting: (h_blank_o / h_clk_0) * 63.55556uS = 9.5uS for NTSC) - /* color burst amplitude */ -// if (si->ps.card_type <= G400MAX) -// { -// buffer[0x0b] = 0x46; -// } -// else - { - buffer[0x0b] = 0x48; - } + if (si->ps.tv_encoder.type >= CX25870)//set CX value + buffer[8] = 0x1d; + else //set BT value + buffer[8] = 0x1c;//try-out; scope: checked against other modes, looks OK. v_blank_o: 1e active line ('pixel') - buffer[0x0c] = 0x00; - buffer[0x0d] = 0x00; + buffer[9] = 0xf2; //v_active_o: = (active output lines + 2) / field (on TV) + buffer[10] = 0x26; //lsn = msn h_clk_o; + //b4-5 = msbits h_active; + //b7 = b8 v_avtive_o. + buffer[11] = 0x00; //h_fract is always 0. + buffer[12] = 0x10; //lsb h_clk_i: h_clk_i is horizontal total = 784. + buffer[13] = 0x14; //try-out; lsb h_blank_i: #clks between start sync and new line 1st pixel; copy to VGA delta-sync! + buffer[14] = 0x03; //b2-0 = msn h_clk_i; + //try-out: b3 = msn h_blank_i; + //b4 = vblankdly is always 0. + buffer[15] = 0x0d; //lsb v_lines_i: v_lines_i = 525 + buffer[16] = 0x18; //try-out; v_blank_i: #input lines between start sync and new line (pixel); copy to VGA delta-sync! + //Make sure though that this value for the BT is *even*, or image will shiver a *lot* horizontally on TV. + buffer[17] = 0xe0; //lsb v_active_i: v_active_i = 480 + buffer[18] = 0x36; //b1-0 = msn v_lines_i; + //b3-2 = msn v_active_i; + //b5-4 = ylpf = 3; + //b7-6 = clpf = 0. + buffer[19] = 0x00; //lsb v_scale: v_scale = off = $1000 + buffer[20] = 0x10; //b5-0 = msn v_scale; + //scope: tuned. b7-6 = msn h_blank_o. + //(((PLL_INT + (PLL_FRACT/65536)) / 6) * 13500000) = PIXEL_CLK = (hor.tot. * v_lines_i * 60Hz) + buffer[21] = 0xdb; //lsb PLL fract: PLL fract = 0xf9db + buffer[22] = 0xf9; //msb PLL fract + buffer[23] = 0x8a; //b5-0 = PLL int: PLL int = 0x0a; + //b6 = by_pll: by_pll = 0; + //b7 = EN_XCLK: chip-pin CLKI is pixel clock. + buffer[24] = 0x0a; //b0 = ni_out is always 0; + //b1 = setup = 1 for NTSC; + //b2 = 625line = 0 for NTSC; + //b3 = vsync_dur = 1 for NTSC; + //b4 = dic_screset is always 0; + //b5 = pal_md = 0 for NTSC; + //b6 = eclip is always 0; + //b7 = reserved (en_scart) is always 0. + buffer[25] = 0xe5; //sync_amp $e5 for NTSC + buffer[26] = 0x75; //bst_amp $74-$76 for NTSC + buffer[27] = 0x78; //mcr: r-y $77-$79 for NTSC + buffer[28] = 0x44; //mcb: b-y $43-$44 for NTSC + buffer[29] = 0x85; //my: y $85 for NTSC + buffer[30] = 0x37; //lsb msc: msc b31-0: NTSC formula: ((3579545 / pixelclk) * 2^32) = MSC + buffer[31] = 0x12; //msc = $251b1237 + buffer[32] = 0x1b; + buffer[33] = 0x25; //msb msc. + buffer[34] = 0x00; //phase_off always $00 -// if (si->ps.card_type <= G400MAX) -// { - /* Lowest active video output level. - * Warning: make sure this stays above (or equals) the sync pulse level! */ -// value = 0x0ea; -// buffer[0x0e] = ((value >> 2) & 0xff); -// buffer[0x0f] = (value & 0x03); - /* horizontal sync pulse level */ -// buffer[0x10] = ((value >> 2) & 0xff); -// buffer[0x11] = (value & 0x03); -// } -// else - { - /* Lowest active video output level. - * Warning: make sure this stays above (or equals) the sync pulse level! */ - value = 0x130; - buffer[0x0e] = ((value >> 2) & 0xff); - buffer[0x0f] = (value & 0x03); - /* horizontal sync pulse level */ - buffer[0x10] = ((value >> 2) & 0xff); - buffer[0x11] = (value & 0x03); - } + /* reset status */ + i2c_flag_error (-1); - buffer[0x12] = 0x17; - buffer[0x13] = 0x21; + i2c_bstart(si->ps.tv_encoder.bus); + i2c_writebuffer(si->ps.tv_encoder.bus, buffer, sizeof(buffer)); + i2c_bstop(si->ps.tv_encoder.bus); + /* log on errors */ + stat = i2c_flag_error(0); + if (stat) + LOG(4,("Brooktree: I2C errors occurred while setting mode NTSC640 OS\n")); - /* functional unit */ - buffer[0x14] = 0x1B; - buffer[0x15] = 0x1B; - buffer[0x16] = 0x24; + return stat; +}//end BT_init_NTSC640_OS. - /* vertical total */ - /* b9-2 */ - buffer[0x17] = 0x83; - /* b1-0 in b1-0 */ - buffer[0x18] = 0x01; - - buffer[0x19] = 0x00;//mv register? - buffer[0x1a] = 0x0F; - buffer[0x1b] = 0x0F; - buffer[0x1c] = 0x60; - buffer[0x1d] = 0x05; - - /* Highest active video output level. - * Warning: make sure this stays above the lowest active video output level! */ -/* if (si->ps.card_type <= G400MAX) - { - value = 0x24f; - buffer[0x1e] = ((value >> 2) & 0xff); - buffer[0x1f] = (value & 0x03); - } - else -*/ { - value = 0x300; - buffer[0x1e] = ((value >> 2) & 0xff); - buffer[0x1f] = (value & 0x03); - } - - /* color saturation #1 (Y-B ?) */ -// if (si->ps.card_type <= G400MAX) -// buffer[0x20] = 0x5F; -// else - buffer[0x20] = 0x9C; - - buffer[0x21] = 0x04; - - /* color saturation #2 (Y-R ?) */ -// if (si->ps.card_type <= G400MAX) -// buffer[0x22] = 0x5F; -// else - buffer[0x22] = 0x9C; - - buffer[0x23] = 0x01; - buffer[0x24] = 0x02; - - /* hue: preset at 0 degrees */ - buffer[0x25] = 0x00; - - buffer[0x26] = 0x0A; - buffer[0x27] = 0x05;//sync stuff - buffer[0x28] = 0x00; - buffer[0x29] = 0x10;//field line-length stuff - - /* functional unit */ - buffer[0x2a] = 0xFF; - buffer[0x2b] = 0x03; - - /* front porch length */ - buffer[0x2c] = 0x24; - - /* functional unit */ - buffer[0x2d] = 0x0F; - buffer[0x2e] = 0x78; - - /* functional unit */ - buffer[0x2f] = 0x00; - buffer[0x30] = 0x00; - - /* horizontal visible */ - /* b10-3 */ - buffer[0x31] = 0xB2; - /* b2-0 in b2-0 */ - buffer[0x32] = 0x04; - - /* upper blanking (in field lines) */ - buffer[0x33] = 0x14; - - buffer[0x34] = 0x02;//colorphase or so stuff. - buffer[0x35] = 0x00; - buffer[0x36] = 0x00; - buffer[0x37] = 0xA3; - buffer[0x38] = 0xC8; - buffer[0x39] = 0x15; - buffer[0x3a] = 0x05; - buffer[0x3b] = 0x3B; - - /* functional unit */ - buffer[0x3c] = 0x3C; - buffer[0x3d] = 0x00; -} - -void gx50_maventv_PAL_timing(gx50_maven_timing *m_timing) +//fixme: resetup for brooktreetv, should cover all supported encoders later on.. +int maventv_init(display_mode target) { - /* values are given in picoseconds */ - m_timing->h_total = 64000000; - /* the sum of the signal duration below should match h_total! */ - m_timing->h_display = 52148148; - m_timing->h_sync_length = 4666667; - m_timing->front_porch = 1407407; - m_timing->back_porch = 5777778; - /* colorburst is 'superimposed' on the above timing */ - m_timing->color_burst = 2518518; - /* number of lines per frame */ - m_timing->v_total = 625; - /* color carrier frequency in Mhz */ - m_timing->chroma_subcarrier = 4.43361875; -} - -void gx50_maventv_NTSC_timing(gx50_maven_timing *m_timing) -{ - /* values are given in picoseconds */ - m_timing->h_total = 63555556; - /* the sum of the signal duration below should match h_total! */ - m_timing->h_display = 52888889; - m_timing->h_sync_length = 4666667; - m_timing->front_porch = 1333333; - m_timing->back_porch = 4666667; - /* colorburst is 'superimposed' on the above timing */ - m_timing->color_burst = 2418418; - /* number of lines per frame */ - m_timing->v_total = 525; - /* color carrier frequency in Mhz */ - m_timing->chroma_subcarrier = 3.579545454; -} - -int maventv_init(display_mode target) -{ - uint8 val; - uint8 m_result, n_result, p_result; - unsigned int ht_new, ht_last_line; - float calc_pclk = 0; /* use a display_mode copy because we might tune it for TVout compatibility */ display_mode tv_target = target; - /* used as buffer for TVout signal to generate */ - uint8 maventv_regs[64]; - /* used in G450/G550 to calculate TVout signal timing dependant on pixelclock; - * <= G400MAX use fixed settings because base-clock here is the fixed crystal - * frequency. */ - //fixme: if <=G400 cards with MAVEN and crystal of 14.31818Mhz exist, modify!?! - gx50_maven_timing m_timing; /* preset new TVout mode */ if ((tv_target.flags & TV_BITS) == TV_PAL) { LOG(4, ("MAVENTV: PAL TVout\n")); - gxx0_maventv_PAL_init(maventv_regs); - gx50_maventv_PAL_timing(&m_timing); } else { LOG(4, ("MAVENTV: NTSC TVout\n")); - gxx0_maventv_NTSC_init(maventv_regs); - gx50_maventv_NTSC_timing(&m_timing); } - /* enter mode-program mode */ -// if (si->ps.card_type <= G400MAX) MAVW(PGM, 0x01); -// else -// { -// DXIW(TVO_IDX, NVMAV_PGM); -// DXIW(TVO_DATA, 0x01); -// } - /* tune new TVout mode */ -// if (si->ps.card_type <= G400MAX) - { - /* setup TV-mode 'copy' of CRTC2, setup PLL, inputs, outputs and sync-locks */ -// MAVW(MONSET, 0x00); -// MAVW(MONEN, 0xA2); - /* xmiscctrl */ - //unknown regs: -// MAVWW(WREG_0X8E_L, 0x1EFF); -// MAVW(BREG_0XC6, 0x01); + /* set flickerfilter */ -// MAVW(LOCK, 0x01); -// MAVW(OUTMODE, 0x08); -// MAVW(LUMA, 0x78); -// MAVW(STABLE, 0x02); -// MAVW(MONEN, 0xB3); + /* output: SVideo/Composite */ - /* setup video PLL */ - g100_g400max_maventv_vid_pll_find( - tv_target, &ht_new, &ht_last_line, &m_result, &n_result, &p_result); -// MAVW(PIXPLLM, m_result); -// MAVW(PIXPLLN, n_result); -// MAVW(PIXPLLP, (p_result | 0x80)); - -// MAVW(MONSET, 0x20); - -// MAVW(TEST, 0x10); - - /* htotal - 2 */ -// MAVWW(HTOTALL, ht_new); - - /* last line in field can have different length */ - /* hlen - 2 */ -// MAVWW(LASTLINEL, ht_last_line); - - /* horizontal vidrst pos: 0 <= vidrst pos <= htotal - 2 */ -// MAVWW(HVIDRSTL, (ht_last_line - si->crtc_delay - -// (tv_target.timing.h_sync_end - tv_target.timing.h_sync_start))); - //ORG (does the same but with limit checks but these limits should never occur!): -// slen = tv_target.timing.h_sync_end - tv_target.timing.h_sync_start; -// hcrt = tv_target.timing.h_total - slen - si->crtc_delay; -// if (ht_last_line < tv_target.timing.h_total) hcrt += ht_last_line; -// if (hcrt > tv_target.timing.h_total) hcrt -= tv_target.timing.h_total; -// if (hcrt + 2 > tv_target.timing.h_total) hcrt = 0; /* or issue warning? */ -// MAVWW(HVIDRSTL, hcrt); - - /* who knows */ -// MAVWW(HSYNCSTRL, 0x0004);//must be 4!! - - /* hblanking end: 100% */ -// MAVWW(HSYNCLENL, (tv_target.timing.h_total - tv_target.timing.h_sync_end)); - - /* vertical line count - 1 */ -// MAVWW(VTOTALL, (tv_target.timing.v_total - 1)); - - /* vertical vidrst pos */ -// MAVWW(VVIDRSTL, (tv_target.timing.v_total - 2)); - - /* something end... [A6]+1..[A8] */ -// MAVWW(VSYNCSTRL, 0x0001); - - /* vblanking end: stop vblanking */ -// MAVWW(VSYNCLENL, (tv_target.timing.v_sync_end - tv_target.timing.v_sync_start - 1)); - //org: no visible diff: - //MAVWW(VSYNCLENL, (tv_target.timing.v_total - tv_target.timing.v_sync_start - 1)); - - /* something start... 0..[A4]-1 */ -// MAVWW(VDISPLAYL, 0x0000); - //std setmode (no visible difference) - //MAVWW(VDISPLAYL, (tv_target.timing.v_total - 1)); - - /* ... */ -// MAVWW(WREG_0X98_L, 0x0000); - - /* moves picture up/down and so on... */ -// MAVWW(VSOMETHINGL, 0x0001); /* Fix this... 0..VTotal */ - - { - uint32 h_display_tv; - uint8 h_scale_tv; - - unsigned int ib_min_length; - unsigned int ib_length; - int index; - - /* calc hor scale-back factor from input to output picture (in 1.7 format) - * the MAVEN has 736 pixels fixed visible? outputline length for TVout */ - //fixme: shouldn't this be 768 (= PAL 1:1 output 4:3 ratio format)?!? - h_scale_tv = (736 << 7) / tv_target.timing.h_total;//should be PLL corrected - LOG(4,("MAVENTV: horizontal scale-back factor is: %f\n", (h_scale_tv / 128.0))); - - /* limit values to MAVEN capabilities (scale-back factor is 0.5-1.0) */ - //fixme: how about lowres upscaling? - if (h_scale_tv > 0x80) - { - h_scale_tv = 0x80; - LOG(4,("MAVENTV: limiting horizontal scale-back factor to: %f\n", (h_scale_tv / 128.0))); - } - if (h_scale_tv < 0x40) - { - h_scale_tv = 0x40; - LOG(4,("MAVENTV: limiting horizontal scale-back factor to: %f\n", (h_scale_tv / 128.0))); - } - /* make sure we get no round-off error artifacts on screen */ - h_scale_tv--; - - /* calc difference in (wanted output picture width (excl. hsync_length)) and - * (fixed total output line length (=768)), - * based on input picture and scaling factor */ - /* (MAVEN trick (part 1) to get output picture width to fit into just 8 bits) */ - h_display_tv = ((768 - 1) << 7) - - (((tv_target.timing.h_total - tv_target.timing.h_sync_end) /* is left margin */ - + tv_target.timing.h_display - 8) - * h_scale_tv); - /* convert result from 25.7 to 32.0 format */ - h_display_tv = h_display_tv >> 7; - LOG(4,("MAVENTV: displaying output on %d picture pixels\n", - ((768 - 1) - h_display_tv))); - - /* half result: MAVEN trick (part 2) - * (258 - 768 pixels, only even number per line is possible) */ - h_display_tv = h_display_tv >> 1; - /* limit value to register contraints */ - if (h_display_tv > 0xFF) h_display_tv = 0xFF; -// MAVW(HSCALETV, h_scale_tv); -// MAVW(HDISPLAYTV, h_display_tv); - - - /* calculate line inputbuffer length */ - /* It must be between (including): - * ((input picture left margin) + (input picture hor. resolution) + 4) - * AND - * (input picture total line length) (PLL corrected) */ - - /* calculate minimal line input buffer length */ - ib_min_length = ((tv_target.timing.h_total - tv_target.timing.h_sync_end) + - tv_target.timing.h_display + 4); - - /* calculate optimal line input buffer length (so top of picture is OK too) */ - /* The following formula applies: - * optimal buffer length = ((((0x78 * i) - R) / hor. scaling factor) + Q) - * - * where (in 4.8 format!) - * R Qmin Qmax - * 0x0E0 0x5AE 0x5BF - * 0x100 0x5CF 0x5FF - * 0x180 0x653 0x67F - * 0x200 0x6F8 0x6FF - */ - index = 1; - do - { - ib_length = ((((((0x7800 << 7) * index) - (0x100 << 7)) / h_scale_tv) + 0x05E7) >> 8); - index++; - } while (ib_length < ib_min_length); - LOG(4,("MAVENTV: optimal line inputbuffer length: %d\n", ib_length)); - - if (ib_length >= ht_new + 2) - { - ib_length = ib_min_length; - LOG(4,("MAVENTV: limiting line inputbuffer length, setting minimal usable: %d\n", ib_length)); - } -// MAVWW(HDISPLAYL, ib_length); - } - - { - uint16 t_scale_tv; - uint32 v_display_tv; - - /* calc total scale-back factor from input to output picture */ - { - uint32 out_clocks; - uint32 in_clocks; - - //takes care of green stripes: - /* calc output clocks per frame */ - out_clocks = m_timing.v_total * (ht_new + 2); - - /* calc input clocks per frame */ - in_clocks = (tv_target.timing.v_total - 1) * (ht_new + 2) + ht_last_line + 2; - - /* calc total scale-back factor from input to output picture in 1.15 format */ - t_scale_tv = ((((uint64)out_clocks) << 15) / in_clocks); - LOG(4,("MAVENTV: total scale-back factor is: %f\n", (t_scale_tv / 32768.0))); - - /* min. scale-back factor is 1.0 for 1:1 output */ - if (t_scale_tv > 0x8000) - { - t_scale_tv = 0x8000; - LOG(4,("MAVENTV: limiting total scale-back factor to: %f\n", (t_scale_tv / 32768.0))); - } - } - - /*calc output picture height based on input picture and scaling factor */ - //warning: v_display was 'one' lower originally! - v_display_tv = - ((tv_target.timing.v_sync_end - tv_target.timing.v_sync_start) /* is sync length */ - + (tv_target.timing.v_total - tv_target.timing.v_sync_end) /* is upper margin */ - + tv_target.timing.v_display) - * t_scale_tv; - /* convert result from 17.15 to 32.0 format */ - v_display_tv = (v_display_tv >> 15); - LOG(4,("MAVENTV: displaying output on %d picture frame-lines\n", v_display_tv)); - - /* half result, and compensate for internal register offset - * (MAVEN trick to get it to fit into just 8 bits). - * (allowed output frame height is 292 - 802 lines, only even numbers) */ - v_display_tv = (v_display_tv >> 1) - 146; - /* limit value to register contraints */ - if (v_display_tv > 0xFF) v_display_tv = 0xFF; - /* make sure we get no round-off error artifacts on screen */ - t_scale_tv--; - -// MAVWW(TSCALETVL, t_scale_tv); -// MAVW(VDISPLAYTV, v_display_tv); - } - -// MAVW(TEST, 0x00); - - /* gamma correction registers */ -// MAVW(GAMMA1, 0x00); -// MAVW(GAMMA2, 0x00); -// MAVW(GAMMA3, 0x00); -// MAVW(GAMMA4, 0x1F); -// MAVW(GAMMA5, 0x10); -// MAVW(GAMMA6, 0x10); -// MAVW(GAMMA7, 0x10); -// MAVW(GAMMA8, 0x64); /* 100 */ -// MAVW(GAMMA9, 0xC8); /* 200 */ - - /* set flickerfilter */ - /* OFF: is dependant on MAVEN chip version(?): NV_TVO_B = $40, else $00. - * ON : always set $a2. */ -// MAVW(FFILTER, 0xa2); - - /* 0x10 or anything ored with it */ - //fixme? linux uses 0x14... -// MAVW(TEST, (MAVR(TEST) & 0x10)); - - /* output: SVideo/Composite */ -// MAVW(OUTMODE, 0x08); - } -// else /* card_type is >= G450 */ - { - //fixme: setup an intermediate buffer if vertical res is different than settings below! - //fixme: setup 2D or 3D engine to do screen_to_screen_scaled_filtered_blit between the buffers - // during vertical retrace! - if ((tv_target.flags & TV_BITS) == TV_PAL) - { - int diff; - - /* defined by the PAL standard */ - tv_target.timing.v_total = m_timing.v_total; - /* we need to center the image on TV vertically. - * note that 576 is the maximum supported resolution for the PAL standard, - * this is already overscanning by approx 8-10% */ - diff = 576 - tv_target.timing.v_display; - /* if we cannot display the current vertical resolution fully, clip it */ - if (diff < 0) - { - tv_target.timing.v_display = 576; - diff = 0; - } - /* now center the image on TV by centering the vertical sync pulse */ - tv_target.timing.v_sync_start = tv_target.timing.v_display + 1 + (diff / 2); - tv_target.timing.v_sync_end = tv_target.timing.v_sync_start + 1; - } - else - { - int diff; - - /* defined by the NTSC standard */ - tv_target.timing.v_total = m_timing.v_total; - /* we need to center the image on TV vertically. - * note that 480 is the maximum supported resolution for the NTSC standard, - * this is already overscanning by approx 8-10% */ - diff = 480 - tv_target.timing.v_display; - /* if we cannot display the current vertical resolution fully, clip it */ - if (diff < 0) - { - tv_target.timing.v_display = 480; - diff = 0; - } - /* now center the image on TV by centering the vertical sync pulse */ - tv_target.timing.v_sync_start = tv_target.timing.v_display + 1 + (diff / 2); - tv_target.timing.v_sync_end = tv_target.timing.v_sync_start + 1; - } - - /* setup video PLL for G450/G550: - * this can be done in the normal way because the MAVEN works in slave mode! - * NOTE: must be done before programming CRTC2, or interlaced startup may fail. */ - - //fixme: make sure videoPLL is powered up: XPWRCTRL b1=1 - { - uint16 front_porch, back_porch, h_sync_length, burst_length, h_total, h_display; - uint32 chromasc; - uint64 pix_period; - uint16 h_total_wanted, leftover; - - /* calculate tv_h_display in 'half pixelclocks' and adhere to MAVEN restrictions. - * ('half pixelclocks' exist because the MAVEN uses them...) */ - h_display = (((tv_target.timing.h_display << 1) + 3) & ~0x03); - if (h_display > 2044) h_display = 2044; - /* copy result to MAVEN TV mode */ - maventv_regs[0x31] = (h_display >> 3); - maventv_regs[0x32] = (h_display & 0x07); - - /* calculate needed video pixelclock in kHz. - * NOTE: - * The clock calculated is based on MAVEN output, so each pixelclock period - * is in fact a 'half pixelclock' period compared to monitor mode use. */ - tv_target.timing.pixel_clock = - ((((uint64)h_display) * 1000000000) / m_timing.h_display); - - /* tune display_mode adhering to CRTC2 restrictions */ - /* (truncate h_display to 'whole pixelclocks') */ - tv_target.timing.h_display = ((h_display >> 1) & ~0x07); - tv_target.timing.h_sync_start = tv_target.timing.h_display + 8; - -// g450_g550_maven_vid_pll_find(tv_target, &calc_pclk, &m_result, &n_result, &p_result, 1); - /* adjust mode to actually used pixelclock */ - tv_target.timing.pixel_clock = (calc_pclk * 1000); - - /* program videoPLL */ -// DXIW(VIDPLLM, m_result); -// DXIW(VIDPLLN, n_result); -// DXIW(VIDPLLP, p_result); - - /* calculate videoclock 'half' period duration in picoseconds */ - pix_period = (1000000000 / ((float)tv_target.timing.pixel_clock)) + 0.5; - LOG(4,("MAVENTV: TV videoclock period is %d picoseconds\n", pix_period)); - - /* calculate number of 'half' clocks per line according to pixelclock set */ - /* fixme: try to setup the modes in such a way that - * (h_total_clk % 16) == 0 because of the CRTC2 restrictions: - * we want to loose the truncating h_total trick below if possible! */ - /* Note: - * This is here so we can see the wanted and calc'd timing difference. */ - h_total_wanted = ((m_timing.h_total / ((float)pix_period)) + 0.5); - LOG(4,("MAVENTV: TV h_total should be %d units\n", h_total_wanted)); - - /* calculate chroma subcarrier value to setup: - * do this as exact as possible because this signal is very sensitive.. */ - chromasc = - ((((uint64)0x100000000) * (m_timing.chroma_subcarrier / calc_pclk)) + 0.5); - /* copy result to MAVEN TV mode */ - maventv_regs[0] = ((chromasc >> 24) & 0xff); - maventv_regs[1] = ((chromasc >> 16) & 0xff); - maventv_regs[2] = ((chromasc >> 8) & 0xff); - maventv_regs[3] = ((chromasc >> 0) & 0xff); - LOG(4,("MAVENTV: TV chroma subcarrier divider set is $%08x\n", chromasc)); - - /* calculate front porch in 'half pixelclocks' */ - /* we always round up because of the h_total truncating 'trick' below, - * which works in combination with the existing difference between - * h_total_clk and h_total */ - //fixme: prevent this if possible! - front_porch = ((m_timing.front_porch / ((float)pix_period)) + 1); - /* value must be even */ - front_porch &= ~0x01; - - /* calculate back porch in 'half pixelclocks' */ - /* we always round up because of the h_total truncating 'trick' below, - * which works in combination with the existing difference between - * h_total_clk and h_total */ - //fixme: prevent this if possible! - back_porch = ((m_timing.back_porch / ((float)pix_period)) + 1); - /* value must be even */ - back_porch &= ~0x01; - - /* calculate h_sync length in 'half pixelclocks' */ - /* we always round up because of the h_total truncating 'trick' below, - * which works in combination with the existing difference between - * h_total_clk and h_total */ - //fixme: prevent this if possible! - h_sync_length = ((m_timing.h_sync_length / ((float)pix_period)) + 1); - /* value must be even */ - h_sync_length &= ~0x01; - - /* calculate h_total in 'half pixelclocks' */ - h_total = h_display + front_porch + back_porch + h_sync_length; - - LOG(4,("MAVENTV: TV front_porch is %d clocks\n", front_porch)); - LOG(4,("MAVENTV: TV back_porch is %d clocks\n", back_porch)); - LOG(4,("MAVENTV: TV h_sync_length is %d clocks\n", h_sync_length)); - LOG(4,("MAVENTV: TV h_display is %d clocks \n", h_display)); - LOG(4,("MAVENTV: TV h_total is %d clocks\n", h_total)); - - /* calculate color_burst length in 'half pixelclocks' */ - burst_length = (((m_timing.color_burst /*- 1*/) / ((float)pix_period)) + 0.5); - LOG(4,("MAVENTV: TV color_burst is %d clocks.\n", burst_length)); - - /* copy result to MAVEN TV mode */ - maventv_regs[0x09] = burst_length; - - /* Calculate line length 'rest' that remains after truncating - * h_total to adhere to the CRTC2 timing restrictions. */ - leftover = h_total & 0x0F; - /* if some 'rest' exists, we need to compensate for it... */ - /* Note: - * It's much better to prevent this from happening because this - * 'trick' will decay TVout timing! (timing is nolonger official) */ - if (leftover) - { - /* truncate line length to adhere to CRTC2 restrictions */ - front_porch -= leftover; - h_total -= leftover; - - /* now set line length to closest CRTC2 valid match */ - if (leftover < 3) - { - /* 1 <= old rest <= 2: - * Truncated line length is closest match. */ - LOG(4,("MAVENTV: CRTC2 h_total leftover discarded (< 3)\n")); - } - else - { - if (leftover < 10) - { - /* 3 <= old rest <= 9: - * We use the NTSC killer circuitry to get closest match. - * (The 'g400_crtc2_set_timing' routine will enable it - * because of the illegal h_total timing we create here.) */ - front_porch += 4; - h_total += 4; - LOG(4,("MAVENTV: CRTC2 h_total leftover corrected via killer (> 2, < 10)\n")); - } - else - { - /* 10 <= old rest <= 15: - * Set closest valid CRTC2 match. */ - front_porch += 16; - h_total += 16; - LOG(4,("MAVENTV: CRTC2 h_total leftover corrected via increase (> 9, < 16)\n")); - } - } - } - - /* (linux) fixme: maybe MAVEN has requirement 800 < h_total < 1184 */ - maventv_regs[0x2C] = front_porch; - maventv_regs[0x0A] = back_porch; - maventv_regs[0x08] = h_sync_length; - - /* change h_total to represent 'whole pixelclocks' */ - h_total = h_total >> 1; - - /* tune display_mode adhering to CRTC2 restrictions */ - tv_target.timing.h_sync_end = (h_total & ~0x07) - 8; - /* h_total is checked before being programmed! (NTSC killer circuitry) */ - tv_target.timing.h_total = h_total; - } - - /* output Y/C and CVBS signals (| $40 needed for SCART) */ -// DXIW(TVO_IDX, 0x80); -// DXIW(TVO_DATA, 0x03); - - /* select input colorspace */ - //fixme?: has no effect on output picture on monitor or TV... - //DXIW(TVO_IDX, 0x81); - //DXIW(TVO_DATA, 0x00); - - /* calculate vertical sync point */ - { - int upper; - - /* set 625 lines for PAL or 525 lines for NTSC */ - maventv_regs[0x17] = m_timing.v_total / 4; - maventv_regs[0x18] = m_timing.v_total & 3; - - /* calculate upper blanking range in field lines */ - upper = (m_timing.v_total - tv_target.timing.v_sync_end) >> 1; - - /* blank TVout above the line number calculated */ - maventv_regs[0x33] = upper - 1; - - /* set calculated vertical sync point */ -// DXIW(TVO_IDX, 0x82); -// DXIW(TVO_DATA, (upper & 0xff)); -// DXIW(TVO_IDX, 0x83); -// DXIW(TVO_DATA, ((upper >> 8) & 0xff)); - LOG(4,("MAVENTV: TV upper blanking range set is %d\n", upper)); - } - - /* set fized horizontal sync point */ -// DXIW(TVO_IDX, 0x84); -// DXIW(TVO_DATA, 0x01); -// DXIW(TVO_IDX, 0x85); -// DXIW(TVO_DATA, 0x00); - - /* connect DAC1 to CON1, CRTC2/'DAC2' to CON2 (TVout mode) */ -// DXIW(OUTPUTCONN,0x0d); - } + /* calculate vertical sync point */ /* program new TVout mode */ - for (val = 0x00; val <= 0x3D; val++) - { -/* if (si->ps.card_type <= G400MAX) - { - i2c_maven_write(val, maventv_regs[val]); - } - else -*/ { -// DXIW(TVO_IDX, val); -// DXIW(TVO_DATA, maventv_regs[val]); - } - } - /* leave mode-program mode */ -// if (si->ps.card_type <= G400MAX) MAVW(PGM, 0x00); -// else -// { -// DXIW(TVO_IDX, NVMAV_PGM); -// DXIW(TVO_DATA, 0x00); - - /* Select 2.0 Volt MAVEN DAC ref. so we have enough contrast/brightness range */ -// DXIW(GENIOCTRL, DXIR(GENIOCTRL) | 0x40); -// DXIW(GENIODATA, 0x00); -// } - - /* setup CRTC2 timing */ + /* setup CRTC timing */ head2_set_timing(tv_target); /* start whole thing if needed */ -// if (si->ps.card_type <= G400MAX) MAVW(RESYNC, 0x20); return 0; } diff --git a/src/add-ons/accelerants/nvidia/engine/nv_proto.h b/src/add-ons/accelerants/nvidia/engine/nv_proto.h index 7a67bf19ca..3fbf185e02 100644 --- a/src/add-ons/accelerants/nvidia/engine/nv_proto.h +++ b/src/add-ons/accelerants/nvidia/engine/nv_proto.h @@ -60,9 +60,6 @@ status_t nv_dac2_set_pix_pll(display_mode target); /* Brooktree TV functions */ bool BT_probe(void); -status_t g100_g400max_maventv_vid_pll_find( - display_mode target, unsigned int * ht_new, unsigned int * ht_last_line, - uint8 * m_result, uint8 * n_result, uint8 * p_result); int maventv_init(display_mode target); /* CRTC1 functions */