Committed patch by Euan Kirkhope to improve routing problems with Radeon cards;

this should fix bug #1293.
I've tested it here on two machines, one works better now, the other stayed the
same (Radeon 9250, and a laptop FireGL (id 4c66) version). This apparently also
fixed bug #1394.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@21930 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler 2007-08-13 17:22:32 +00:00
parent 8f4f70a56d
commit f9a5b215cd
12 changed files with 366 additions and 83 deletions

View File

@ -35,6 +35,7 @@
# define RADEON_FP2_PANEL_FORMAT (1 << 3)
# define RADEON_FP2_SOURCE_SEL_MASK (3 << 10)
# define RADEON_FP2_SOURCE_SEL_CRTC2 (1 << 10)
# define RADEON_FP2_SOURCE_SEL_RMX (2 << 10)
# define RADEON_FP2_SRC_SEL_MASK (3 << 13)
# define RADEON_FP2_SRC_SEL_CRTC2 (1 << 13)
# define RADEON_FP2_FP_POL (1 << 16)
@ -68,6 +69,12 @@
# define RADEON_VERT_STRETCH_BLEND (1 << 26)
# define RADEON_VERT_AUTO_RATIO_EN (1 << 27)
# define RADEON_VERT_STRETCH_RESERVED 0xf1000000
#define RADEON_TMDS_PLL_CNTL 0x02a8
#define RADEON_TMDS_TRANSMITTER_CNTL 0x02a4
# define RADEON_TMDS_TRANSMITTER_PLLEN 1
# define RADEON_TMDS_TRANSMITTER_PLLRST 2
#define RADEON_FP_H_SYNC_STRT_WID 0x02c4
#define RADEON_FP_V_SYNC_STRT_WID 0x02c8
@ -80,6 +87,9 @@
# define RADEON_LVDS_DIGON (1 << 18)
# define RADEON_LVDS_BLON (1 << 19)
# define RADEON_LVDS_SEL_CRTC2 (1 << 23)
#define RADEON_LVDS_PLL_CNTL 0x02d4
# define RADEON_HSYNC_DELAY_SHIFT 28
# define RADEON_HSYNC_DELAY_MASK (0xf << 28)
#define RADEON_FP_CRTC2_H_TOTAL_DISP 0x0350
#define RADEON_FP_CRTC2_V_TOTAL_DISP 0x0354

View File

@ -348,6 +348,11 @@ typedef struct {
uint32 best_vco; // preferred VCO frequency (0 for don't care)
} pll_info;
// info for ext tmds pll
typedef struct {
uint32 freq;
uint32 value;
} tmds_pll_info;
// one overlay buffer
typedef struct overlay_buffer_node {
@ -520,24 +525,24 @@ typedef struct {
uint16 device_id; // PCI device id
uint8 revision; // PCI device revision
//bool has_crtc2; // has second CRTC
radeon_type asic; // ASIC version
bool is_mobility; // mobility version
bool is_igp; // might need to know if it's an integrated chip
bool is_mobility; // mobility version
bool is_igp; // might need to know if it's an integrated chip
bool is_atombios;
tv_chip_type tv_chip; // type of TV-Out encoder
tv_chip_type tv_chip; // type of TV-Out encoder
bool new_pll; // r300 style PLL
bool has_no_i2c; // I2C is broken
uint16 panel_pwr_delay;// delay for LCD backlight to stabilise
uint8 theatre_channel;// VIP channel of Rage Theatre (if applicable)
bool has_no_i2c; // I2C is broken
uint16 panel_pwr_delay; // delay for LCD backlight to stabilise
uint8 theatre_channel; // VIP channel of Rage Theatre (if applicable)
general_pll_info pll;
tmds_pll_info tmds_pll[4];
area_id regs_area; // area of memory mapped registers
area_id ROM_area; // area of ROM
//area_id fb_area; // area of frame buffer
void *framebuffer_pci; // physical address of frame buffer (aka local memory)
// this is a hack needed by BeOS
// this is a hack needed by BeOS
crtc_info crtc[2]; // info about each crtc
uint8 num_crtc; // number of physical heads
@ -557,6 +562,8 @@ typedef struct {
uint32 active_vc; // currently selected virtual card in terms of 2D acceleration
uint32 dac_cntl2; // content of dac_cntl2 register
uint32 tmds_pll_cntl; // undocumented here be dragons
uint32 tmds_transmitter_cntl; // undocumented here be dragons
overlay_info pending_overlay; // overlay to be shown
overlay_info active_overlay; // overlay shown

View File

@ -148,6 +148,10 @@ Radeon_ProposeDisplayMode(shared_info *si, crtc_info *crtc,
int eff_virtual_width;
fp_info *flatpanel = &si->flatpanels[crtc->flatpanel_port];
SHOW_FLOW( 4, "CRTC %d, DVI %d", (crtc == &si->crtc[0]) ? 0 : 1, crtc->flatpanel_port );
SHOW_FLOW( 4, "X %d, virtX %d", target->timing.h_display, target->virtual_width);
SHOW_FLOW( 4, "fpRes %dx%d", flatpanel->panel_xres, flatpanel->panel_yres);
// save refresh rate - we want to leave this (artifical) value untouched
// don't use floating point, we are in kernel mode
target_refresh =
@ -163,7 +167,7 @@ Radeon_ProposeDisplayMode(shared_info *si, crtc_info *crtc,
// for flat panels, check maximum resolution;
// all the other tricks (like fixed resolution and resulting scaling)
// are done automagically by set_display_mode
if( (crtc->chosen_displays & (dd_lvds | dd_dvi | dd_dvi_ext)) != 0 ) {
if( (crtc->chosen_displays & (dd_lvds | dd_dvi)) != 0 ) {
if( target->timing.h_display > flatpanel->panel_xres )
target->timing.h_display = flatpanel->panel_xres;
@ -171,6 +175,17 @@ Radeon_ProposeDisplayMode(shared_info *si, crtc_info *crtc,
target->timing.v_display = flatpanel->panel_yres;
}
// for secondary flat panels there is no RMX unit for
// scaling up lower resolutions. Until we can do centered timings
// we need to disable the screen unless it is the native resolution.
// if the DVI input has a scaler we would need to know about it somehow...
if( (crtc->chosen_displays & dd_dvi_ext) != 0 ) {
SHOW_FLOW0( 4, "external (secondary) DVI cannot support non-native resolutions" );
if( ( target->timing.h_display != flatpanel->panel_xres ) ||
( target->timing.v_display != flatpanel->panel_yres ) )
return B_ERROR;
}
/*
// the TV-Out encoder can "only" handle up to 1024x768
if( (head->chosen_displays & (dd_ctv | dd_stv)) != 0 ) {
@ -325,7 +340,7 @@ Radeon_ProposeDisplayMode(shared_info *si, crtc_info *crtc,
if( target->timing.pixel_clock / 10 > pll->max_pll_freq ||
target->timing.pixel_clock / 10 * 12 < pll->min_pll_freq )
{
SHOW_ERROR( 2, "pixel_clock (%ld) out of range (%d, %d)", target->timing.pixel_clock,
SHOW_ERROR( 4, "pixel_clock (%ld) out of range (%d, %d)", target->timing.pixel_clock,
pll->max_pll_freq * 10, pll->min_pll_freq / 12 );
return B_ERROR;
}
@ -371,7 +386,7 @@ Radeon_ProposeDisplayMode(shared_info *si, crtc_info *crtc,
// make sure we haven't shrunk virtual height too much
if (target->virtual_height < target->timing.v_display) {
SHOW_ERROR( 2, "not enough memory for this mode (could show only %d of %d lines)",
SHOW_ERROR( 4, "not enough memory for this mode (could show only %d of %d lines)",
target->virtual_height, target->timing.v_display );
return B_ERROR;
}
@ -516,11 +531,11 @@ static void addFPMode( accelerator_info *ai )
{
shared_info *si = ai->si;
fp_info *fp_info = &si->flatpanels[0];
fp_info *fp_info = &si->flatpanels[0]; //todo fix the hardcoding what about ext dvi?
if( (ai->vc->connected_displays & (dd_dvi | dd_lvds)) != 0 ) {
if( (ai->vc->connected_displays & (dd_dvi | dd_dvi_ext | dd_lvds)) != 0 ) {
display_mode mode;
SHOW_FLOW0( 2, "" );
mode.virtual_width = mode.timing.h_display = fp_info->panel_xres;
mode.virtual_height = mode.timing.v_display = fp_info->panel_yres;
@ -631,14 +646,14 @@ PROPOSE_DISPLAY_MODE(display_mode *target, const display_mode *low,
Radeon_DetectMultiMode( vc, target );
Radeon_VerifyMultiMode( vc, si, target );
SHOW_FLOW0( 3, "wished:" );
SHOW_FLOW( 3, "H: %4d %4d %4d %4d (v=%4d)",
SHOW_FLOW0( 2, "wished:" );
SHOW_FLOW( 2, "H: %4d %4d %4d %4d (v=%4d)",
target->timing.h_display, target->timing.h_sync_start,
target->timing.h_sync_end, target->timing.h_total, target->virtual_width );
SHOW_FLOW( 3, "V: %4d %4d %4d %4d (h=%4d)",
SHOW_FLOW( 2, "V: %4d %4d %4d %4d (h=%4d)",
target->timing.v_display, target->timing.v_sync_start,
target->timing.v_sync_end, target->timing.v_total, target->virtual_height );
SHOW_FLOW( 3, "clk: %ld", target->timing.pixel_clock );
SHOW_FLOW( 2, "clk: %ld", target->timing.pixel_clock );
// we must assure that each ProposeMode call doesn't tweak the mode in
// a way that it cannot be handled by the other port anymore
@ -659,14 +674,14 @@ PROPOSE_DISPLAY_MODE(display_mode *target, const display_mode *low,
result2 = B_OK;
}
SHOW_INFO0( 4, "got:" );
SHOW_INFO( 4, "H: %4d %4d %4d %4d (v=%4d)",
SHOW_INFO0( 2, "got:" );
SHOW_INFO( 2, "H: %4d %4d %4d %4d (v=%4d)",
target->timing.h_display, target->timing.h_sync_start,
target->timing.h_sync_end, target->timing.h_total, target->virtual_width );
SHOW_INFO( 4, "V: %4d %4d %4d %4d (h=%4d)",
SHOW_INFO( 2, "V: %4d %4d %4d %4d (h=%4d)",
target->timing.v_display, target->timing.v_sync_start,
target->timing.v_sync_end, target->timing.v_total, target->virtual_height );
SHOW_INFO( 4, "clk: %ld", target->timing.pixel_clock );
SHOW_INFO( 2, "clk: %ld", target->timing.pixel_clock );
Radeon_HideMultiMode( vc, target );

View File

@ -23,11 +23,20 @@
#include "fp_regs.h"
#include "gpiopad_regs.h"
#include "pll_regs.h"
#include "tv_out_regs.h"
#include "config_regs.h"
#include "ddc_regs.h"
#include "pll_access.h"
#include "theatre_regs.h"
#include "set_mode.h"
#include "ddc.h"
#include "set_mode.h"
#include <string.h>
void Radeon_SetMode(
status_t Radeon_SetMode(
accelerator_info *ai, crtc_info *crtc, display_mode *mode, impactv_params *tv_params );
// round virtual width up to next valid size
@ -94,7 +103,7 @@ static void Radeon_InitCommonRegs(
// set display mode of one head;
// port restrictions, like fixed-sync TFTs connected to it, are taken care of
void Radeon_SetMode(
status_t Radeon_SetMode(
accelerator_info *ai, crtc_info *crtc, display_mode *mode, impactv_params *tv_params )
{
virtual_card *vc = ai->vc;
@ -126,11 +135,26 @@ void Radeon_SetMode(
// is determined by the physical resolution;
// also, all timing is fixed
if( (disp_devices & (dd_lvds | dd_dvi | dd_dvi_ext)) != 0 ) {
SHOW_FLOW0( 0, "requested resolution higher than native panel" );
if( mode->timing.h_display > fp_info->panel_xres )
mode->timing.h_display = fp_info->panel_xres;
if( mode->timing.v_display > fp_info->panel_yres )
mode->timing.v_display = fp_info->panel_yres;
if( (disp_devices & dd_dvi_ext) != 0 ) {
SHOW_FLOW0( 0, "requested resolution less than second native panel" );
if( mode->timing.h_display < fp_info->panel_xres )
mode->timing.h_display = fp_info->panel_xres;
if( mode->timing.v_display < fp_info->panel_yres )
mode->timing.v_display = fp_info->panel_yres;
//TODO at this point we know we are going to do centered timing
//need to set flags to a. blank the unused memory, b.center screen
//for now it's in the top corner, and surrounded by garbage.
// although if the DVI panels are the same size and we are cloning
// we can switch the FP2 source to RMX, and drive both screens from
// the RMX unit.
}
mode->timing.h_total = mode->timing.h_display + fp_info->h_blank;
mode->timing.h_sync_start = mode->timing.h_display + fp_info->h_over_plus;
mode->timing.h_sync_end = mode->timing.h_sync_start + fp_info->h_sync_width;
@ -254,6 +278,28 @@ void Radeon_SetMode(
Radeon_TheatreProgramTVRegisters( ai, &impactv_values );
}
// spit out some debug stuff in a radeontool stylee
SHOW_FLOW0( 0, "" );
SHOW_FLOW( 0, "RADEON_DAC_CNTL %08X ", INREG( regs, RADEON_DAC_CNTL ));
SHOW_FLOW( 0, "RADEON_DAC_CNTL2 %08X ", INREG( regs, RADEON_DAC_CNTL2 ));
SHOW_FLOW( 0, "RADEON_TV_DAC_CNTL %08X ", INREG( regs, RADEON_TV_DAC_CNTL ));
SHOW_FLOW( 0, "RADEON_DISP_OUTPUT_CNTL %08X ", INREG( regs, RADEON_DISP_OUTPUT_CNTL ));
SHOW_FLOW( 0, "RADEON_AUX_SC_CNTL %08X ", INREG( regs, RADEON_AUX_SC_CNTL ));
SHOW_FLOW( 0, "RADEON_CRTC_EXT_CNTL %08X ", INREG( regs, RADEON_CRTC_EXT_CNTL ));
SHOW_FLOW( 0, "RADEON_CRTC_GEN_CNTL %08X ", INREG( regs, RADEON_CRTC_GEN_CNTL ));
SHOW_FLOW( 0, "RADEON_CRTC2_GEN_CNTL %08X ", INREG( regs, RADEON_CRTC2_GEN_CNTL ));
SHOW_FLOW( 0, "RADEON_DISP_MISC_CNTL %08X ", INREG( regs, RADEON_DISP_MISC_CNTL ));
SHOW_FLOW( 0, "RADEON_FP_GEN_CNTL %08X ", INREG( regs, RADEON_FP_GEN_CNTL ));
SHOW_FLOW( 0, "RADEON_FP2_GEN_CNTL %08X ", INREG( regs, RADEON_FP2_GEN_CNTL ));
SHOW_FLOW( 0, "RADEON_LVDS_GEN_CNTL %08X ", INREG( regs, RADEON_LVDS_GEN_CNTL ));
SHOW_FLOW( 0, "RADEON_TMDS_PLL_CNTL %08X ", INREG( regs, RADEON_TMDS_PLL_CNTL ));
SHOW_FLOW( 0, "RADEON_TMDS_TRANSMITTER_CNTL %08X ", INREG( regs, RADEON_TMDS_TRANSMITTER_CNTL ));
SHOW_FLOW( 0, "RADEON_FP_H_SYNC_STRT_WID %08X ", INREG( regs, RADEON_FP_H_SYNC_STRT_WID ));
SHOW_FLOW( 0, "RADEON_FP_V_SYNC_STRT_WID %08X ", INREG( regs, RADEON_FP_V_SYNC_STRT_WID ));
SHOW_FLOW( 0, "RADEON_FP_H2_SYNC_STRT_WID %08X ", INREG( regs, RADEON_FP_H2_SYNC_STRT_WID ));
SHOW_FLOW( 0, "RADEON_FP_V2_SYNC_STRT_WID %08X ", INREG( regs, RADEON_FP_V2_SYNC_STRT_WID ));
// spit end
crtc->active_displays = disp_devices;
// programming is over, so hardware can be used again
@ -263,6 +309,8 @@ void Radeon_SetMode(
// TBD: this won't work if another virtual card was using it,
// but currently, virtual cards don't work anyway...
si->active_overlay.crtc_idx = -1;
return B_OK;
}
@ -432,6 +480,8 @@ status_t SET_DISPLAY_MODE(
{
routing_regs routing_values;
impactv_params tv_params;
status_t err1 , err2;
err1 = err2 = B_OK;
// we first switch off all output, so the monitor(s) won't get invalid signals
if( vc->assigned_crtc[0] ) {
@ -451,10 +501,14 @@ status_t SET_DISPLAY_MODE(
// then change the mode
if( vc->used_crtc[0] )
Radeon_SetMode( ai, &si->crtc[0], &mode, &tv_params );
err1 = Radeon_SetMode( ai, &si->crtc[0], &mode, &tv_params );
if( vc->used_crtc[1] )
Radeon_SetMode( ai, &si->crtc[1], &mode, &tv_params );
err2 = Radeon_SetMode( ai, &si->crtc[1], &mode, &tv_params );
SHOW_FLOW( 2, "SetModes 1=%s, 2=%s",
(err1 == B_OK) ? "OK" : "FAIL", (err2 == B_OK) ? "OK" : "FAIL");
// setup signal routing
Radeon_ReadMonitorRoutingRegs( ai, &routing_values );
Radeon_CalcMonitorRouting( ai, &tv_params, &routing_values );
@ -462,9 +516,9 @@ status_t SET_DISPLAY_MODE(
// finally, switch display(s) on
if( vc->used_crtc[0] )
Radeon_SetDPMS( ai, 0, B_DPMS_ON );
Radeon_SetDPMS( ai, 0, (err1 == B_OK) ? B_DPMS_ON : B_DPMS_SUSPEND );
if( vc->used_crtc[1] )
Radeon_SetDPMS( ai, 1, B_DPMS_ON );
Radeon_SetDPMS( ai, 1, (err2 == B_OK) ? B_DPMS_ON : B_DPMS_SUSPEND );
OUTREGP( ai->regs, RADEON_CRTC_EXT_CNTL, 0, ~RADEON_CRTC_DISPLAY_DIS );
}

View File

@ -108,7 +108,7 @@ void Radeon_ProgramRMXRegisters(
accelerator_info *ai, fp_regs *values )
{
vuint8 *regs = ai->regs;
SHOW_FLOW0( 2, "" );
OUTREG( regs, RADEON_FP_HORZ_STRETCH, values->fp_horz_stretch );
OUTREG( regs, RADEON_FP_VERT_STRETCH, values->fp_vert_stretch );
}
@ -119,9 +119,11 @@ void Radeon_ReadFPRegisters(
{
vuint8 *regs = ai->regs;
values->fp_gen_cntl = INREG( regs, RADEON_FP_GEN_CNTL );
values->fp2_gen_cntl = INREG( regs, RADEON_FP2_GEN_CNTL );
values->lvds_gen_cntl = INREG( regs, RADEON_LVDS_GEN_CNTL );
values->fp_gen_cntl = INREG( regs, RADEON_FP_GEN_CNTL );
values->fp2_gen_cntl = INREG( regs, RADEON_FP2_GEN_CNTL );
values->lvds_gen_cntl = INREG( regs, RADEON_LVDS_GEN_CNTL );
values->tmds_pll_cntl = INREG( regs, RADEON_TMDS_PLL_CNTL );
values->tmds_trans_cntl = INREG( regs, RADEON_TMDS_TRANSMITTER_CNTL );
values->fp_h_sync_strt_wid = INREG( regs, RADEON_FP_H_SYNC_STRT_WID );
values->fp_v_sync_strt_wid = INREG( regs, RADEON_FP_V_SYNC_STRT_WID );
values->fp2_h_sync_strt_wid = INREG( regs, RADEON_FP_H2_SYNC_STRT_WID );
@ -130,9 +132,14 @@ void Radeon_ReadFPRegisters(
values->bios_5_scratch = INREG( regs, RADEON_BIOS_5_SCRATCH );
values->bios_6_scratch = INREG( regs, RADEON_BIOS_6_SCRATCH );
SHOW_FLOW( 2, "before: fp_gen_cntl=%08lx, horz=%08lx, vert=%08lx, lvds_gen_cntl=%08lx",
values->fp_gen_cntl, values->fp_horz_stretch, values->fp_vert_stretch,
values->lvds_gen_cntl );
if (ai->si->asic == rt_rv280) {
// bit 22 of TMDS_PLL_CNTL is read-back inverted
values->tmds_pll_cntl ^= (1 << 22);
}
SHOW_FLOW( 2, "before: fp_gen_cntl=%08lx, horz=%08lx, vert=%08lx, lvds_gen_cntl=%08lx",
values->fp_gen_cntl, values->fp_horz_stretch, values->fp_vert_stretch,
values->lvds_gen_cntl );
}
// calculcate flat panel crtc registers;
@ -141,20 +148,27 @@ void Radeon_CalcFPRegisters(
accelerator_info *ai, crtc_info *crtc,
fp_info *fp_port, crtc_regs *crtc_values, fp_regs *values )
{
int i;
uint32 tmp = values->tmds_pll_cntl & 0xfffff;
// setup synchronization position
// (most values are ignored according to fp_gen_cntl, but at least polarity
// and pixel precise horizontal sync position are always used)
if( fp_port->is_fp2 ) {
SHOW_FLOW0( 2, "is_fp2" );
values->fp2_h_sync_strt_wid = crtc_values->crtc_h_sync_strt_wid;
values->fp2_v_sync_strt_wid = crtc_values->crtc_v_sync_strt_wid;
} else {
SHOW_FLOW0( 2, "fp1" );
values->fp_h_sync_strt_wid = crtc_values->crtc_h_sync_strt_wid;
values->fp_v_sync_strt_wid = crtc_values->crtc_v_sync_strt_wid;
}
if( fp_port->is_fp2 )
values->fp2_gen_cntl = 0;
else {
if( fp_port->is_fp2 ) {
// should retain POST values (esp bit 28)
values->fp2_gen_cntl &= (0xFFFF0000);
} else {
// setup magic CRTC shadowing
values->fp_gen_cntl &=
~(RADEON_FP_RMX_HVSYNC_CONTROL_EN |
@ -169,29 +183,64 @@ void Radeon_CalcFPRegisters(
RADEON_FP_CRTC_DONT_SHADOW_HEND;
}
for (i = 0; i < 4; i++) {
if (ai->si->tmds_pll[i].freq == 0)
break;
if ((uint32)(fp_port->dot_clock) < ai->si->tmds_pll[i].freq) {
tmp = ai->si->tmds_pll[i].value ;
break;
}
}
if (IS_R300_VARIANT || (ai->si->asic == rt_rv280)) {
if (tmp & 0xfff00000) {
values->tmds_pll_cntl = tmp;
} else {
values->tmds_pll_cntl = ai->si->tmds_pll_cntl & 0xfff00000;
values->tmds_pll_cntl |= tmp;
}
} else {
values->tmds_pll_cntl = tmp;
}
values->tmds_trans_cntl = ai->si->tmds_transmitter_cntl
& ~(RADEON_TMDS_TRANSMITTER_PLLRST);
if (IS_R300_VARIANT || (ai->si->asic == rt_r200) || (ai->si->num_crtc == 1))
values->tmds_trans_cntl &= ~(RADEON_TMDS_TRANSMITTER_PLLEN);
else // weird, RV chips got this bit reversed?
values->tmds_trans_cntl |= (RADEON_TMDS_TRANSMITTER_PLLEN);
// enable proper transmitter
if( (crtc->chosen_displays & dd_lvds) != 0 ) {
// using LVDS means there cannot be a DVI monitor
SHOW_FLOW0( 2, "lvds" );
values->lvds_gen_cntl |= (RADEON_LVDS_ON | RADEON_LVDS_BLON);
values->fp_gen_cntl &= ~(RADEON_FP_FPON | RADEON_FP_TMDS_EN);
} else if( !fp_port->is_fp2 ) {
// DVI on internal transmitter
SHOW_FLOW0( 2, "DVI INT" );
values->fp_gen_cntl |= RADEON_FP_FPON | RADEON_FP_TMDS_EN;
// enabling 8 bit data may be dangerous; BIOS should have taken care of that
values->fp_gen_cntl |= RADEON_FP_PANEL_FORMAT;
} else {
// DVI on external transmitter
SHOW_FLOW0( 2, "DVI EXT" );
values->fp2_gen_cntl |= RADEON_FP2_FPON | RADEON_FP_PANEL_FORMAT;
values->fp2_gen_cntl &= ~RADEON_FP2_BLANK_EN;
//hack in missing bits test...
//values->fp2_gen_cntl |= (1 << 22) | (1 << 28);
if( ai->si->asic >= rt_r200 )
values->fp2_gen_cntl |= RADEON_FP2_DV0_EN;
}
SHOW_FLOW( 2, "after: fp_gen_cntl=%08lx, horz=%08lx, vert=%08lx, lvds_gen_cntl=%08lx",
values->fp_gen_cntl, values->fp_horz_stretch, values->fp_vert_stretch,
SHOW_FLOW( 2, "after: fp_gen_cntl=%08lx, fp2_gen_cntl=%08lx, horz=%08lx, vert=%08lx, lvds_gen_cntl=%08lx",
values->fp_gen_cntl, values->fp2_gen_cntl, values->fp_horz_stretch, values->fp_vert_stretch,
values->lvds_gen_cntl );
}
@ -209,11 +258,15 @@ void Radeon_ProgramFPRegisters(
OUTREGP( regs, RADEON_FP_GEN_CNTL, values->fp_gen_cntl, RADEON_FP_SEL_CRTC2 );
if( fp_port->is_fp2 ) {
SHOW_FLOW0( 2, "is_fp2" );
OUTREGP( regs, RADEON_FP2_GEN_CNTL, values->fp2_gen_cntl,
~(RADEON_FP2_SOURCE_SEL_MASK | RADEON_FP2_SRC_SEL_MASK));
OUTREGP( regs, RADEON_FP2_GEN_CNTL, values->fp2_gen_cntl,
RADEON_FP2_SOURCE_SEL_CRTC2 | RADEON_FP2_SRC_SEL_CRTC2 );
OUTREG( regs, RADEON_FP_H2_SYNC_STRT_WID, values->fp2_h_sync_strt_wid );
OUTREG( regs, RADEON_FP_V2_SYNC_STRT_WID, values->fp2_v_sync_strt_wid );
} else {
SHOW_FLOW0( 2, "is_fp1" );
OUTREG( regs, RADEON_FP_H_SYNC_STRT_WID, values->fp_h_sync_strt_wid );
OUTREG( regs, RADEON_FP_V_SYNC_STRT_WID, values->fp_v_sync_strt_wid );
}

View File

@ -269,19 +269,19 @@ static bool Radeon_DetectTVCRT_R300( accelerator_info *ai )
RADEON_DAC_FORCE_DATA_SEL_RGB |
(0x1b6 << RADEON_DAC_FORCE_DATA_SHIFT ));
old_dac_cntl2 = INREG( regs, RADEON_DAC_CNTL2 );
old_dac_cntl2 = INREG( regs, RADEON_DAC_CNTL2 );
// enable CRT mode of TV-DAC and enable comparator
tmp = old_dac_cntl2 | RADEON_DAC2_CLK_SEL_CRT | RADEON_DAC2_CMP_EN;
tmp = old_dac_cntl2 | RADEON_DAC2_CLK_SEL_CRT | RADEON_DAC2_CMP_EN;
OUTREG( regs, RADEON_DAC_CNTL2, tmp );
OUTREG( regs, RADEON_DAC_CNTL2, tmp );
snooze( 10000 );
snooze( 10000 );
// check connection of blue data signal to see whether there is a CRT
// check connection of blue data signal to see whether there is a CRT
found = (INREG( regs, RADEON_DAC_CNTL2 ) & RADEON_DAC2_CMP_OUT_B) != 0;
// clean up the mess
// clean up the mess
OUTREG( regs, RADEON_DAC_CNTL2, old_dac_cntl2 );
OUTREG( regs, RADEON_DAC_EXT_CNTL, 0 );
OUTREG( regs, RADEON_TV_DAC_CNTL, old_tv_dac_cntl );
@ -289,7 +289,7 @@ static bool Radeon_DetectTVCRT_R300( accelerator_info *ai )
OUTREGP( regs, RADEON_GPIOPAD_A, old_radeon_gpiopad_a, ~1 );
return found;
return found;
}
@ -800,9 +800,9 @@ static void Radeon_FindFPTiming_StandardTiming(
}
// read edid data of flat panel and setup its timing accordingly
static status_t Radeon_StoreFPEDID( accelerator_info *ai, const edid1_info *edid )
static status_t Radeon_StoreFPEDID( accelerator_info *ai, int port, const edid1_info *edid )
{
fp_info *fp = &ai->si->flatpanels[0];
fp_info *fp = &ai->si->flatpanels[port];
uint32 max_hsize, max_vsize;
//SHOW_FLOW0( 2, "EDID data read from DVI port via DDC2:" );
@ -954,10 +954,12 @@ void Radeon_DetectDisplays( accelerator_info *ai )
// use DDC to detect monitors - if we can read DDC, there must be a monitor
for ( i = 0; i < 2; i++ )
{
if (routes->port_info[i].mon_type != mt_unknown ) {
SHOW_FLOW0( 2, "known type, skpping detection" );
continue;
}
//TODO could skip edid reading instead if we already have it, but what
//if monitors have been hot swapped? Also rely on edid for DVI-D detection
//if (routes->port_info[i].mon_type != mt_unknown ) {
// SHOW_FLOW0( 2, "known type, skpping detection" );
// continue;
//}
memset( &routes->port_info[i].edid , 0, sizeof(edid1_info) );
switch ( routes->port_info[i].ddc_type ) {
@ -993,9 +995,10 @@ void Radeon_DetectDisplays( accelerator_info *ai )
// both LDVS and TMDS are disable, we still need to treat it as a LVDS panel.
if ( routes->port_info[i].tmds_type == tmds_ext ){
// store info about DVI-connected flat-panel
if( Radeon_StoreFPEDID( ai, &routes->port_info[i].edid ) == B_OK ) {
if( Radeon_StoreFPEDID( ai, i, &routes->port_info[i].edid ) == B_OK ) {
SHOW_INFO0( 2, "Found Ext Laptop DVI" );
routes->port_info[i].mon_type = mt_dfp;
ai->si->flatpanels[i].is_fp2 = true;
displays |= dd_dvi_ext;
} else {
SHOW_ERROR0( 2, "Disabled Ext DVI - invalid EDID" );
@ -1003,7 +1006,7 @@ void Radeon_DetectDisplays( accelerator_info *ai )
} else {
if( INREG( ai->regs, RADEON_FP_GEN_CNTL) & (1 << 7) || ( !si->is_mobility ) ) {
// store info about DVI-connected flat-panel
if( Radeon_StoreFPEDID( ai, &routes->port_info[i].edid ) == B_OK ) {
if( Radeon_StoreFPEDID( ai, i, &routes->port_info[i].edid ) == B_OK ) {
SHOW_INFO0( 2, "Found DVI" );
routes->port_info[i].mon_type = mt_dfp;
displays |= dd_dvi;
@ -1015,6 +1018,7 @@ void Radeon_DetectDisplays( accelerator_info *ai )
routes->port_info[i].mon_type = mt_lcd;
displays |= dd_lvds;
}
ai->si->flatpanels[1].is_fp2 = FALSE;
}
} else {
// must be the analog portion of DVI
@ -1049,7 +1053,7 @@ void Radeon_DetectDisplays( accelerator_info *ai )
if ( si->is_mobility && (INREG( ai->regs, RADEON_FP2_GEN_CNTL) & RADEON_FP2_FPON)) {
SHOW_INFO0( 2, "Found Ext Laptop DVI" );
routes->port_info[1].mon_type = mt_dfp;
displays |= dd_dvi;
displays |= dd_dvi_ext;
}
}

View File

@ -634,8 +634,11 @@ static void assignDefaultMonitorRoute(
else if( ai->si->num_crtc > 1 && (crtc2_displays & ~(dd_stv | dd_ctv)) == 0 && vc->assigned_crtc[1] )
crtc2_displays |= dd_tv_crt;
}
SHOW_FLOW( 3, "CRTC1: 0x%x, CRTC2: 0x%x", crtc1_displays, crtc2_displays );
if( (display_devices & dd_dvi_ext) != 0 )
crtc2_displays |= dd_dvi_ext;
SHOW_FLOW( 2, "CRTC1: 0x%x, CRTC2: 0x%x", crtc1_displays, crtc2_displays );
*crtc1 = crtc1_displays;
*crtc2 = crtc2_displays;
@ -651,7 +654,7 @@ void Radeon_SetupDefaultMonitorRouting(
shared_info *si = ai->si;
display_device_e display_devices = vc->connected_displays;
if (ai->si->settings.force_lcd) {
if (ai->si->settings.force_lcd) {
use_laptop_panel = true;
SHOW_FLOW0( 2, "LCD Forced Used by Kernel Settings");
}

View File

@ -32,7 +32,7 @@ extern int debug_level_error;
#define DEBUG_MSG_PREFIX "Radeon - "
#define DEBUG_MAX_LEVEL_FLOW 2
#define DEBUG_MAX_LEVEL_FLOW 3
#include "debug_ext.h"

View File

@ -98,17 +98,19 @@ typedef struct {
typedef struct {
uint32 fp_gen_cntl;
uint32 fp_panel_cntl;
uint32 lvds_gen_cntl;
uint32 lvds_gen_cntl;
uint32 tmds_pll_cntl;
uint32 tmds_trans_cntl;
uint32 fp_h_sync_strt_wid;
uint32 fp_v_sync_strt_wid;
uint32 fp2_gen_cntl;
uint32 fp2_h_sync_strt_wid;
uint32 fp2_h_sync_strt_wid;
uint32 fp2_v_sync_strt_wid;
// RMX registers
uint32 fp_horz_stretch;
uint32 fp_vert_stretch;
uint32 fp_vert_stretch;
// Bios values used by Mobility Asics
uint32 bios_4_scratch;

View File

@ -31,14 +31,33 @@
#define RADEON_BIOS8(v) (di->rom.rom_ptr[v])
#define RADEON_BIOS16(v) ((di->rom.rom_ptr[v]) | \
(di->rom.rom_ptr[(v) + 1] << 8))
(di->rom.rom_ptr[(v) + 1] << 8))
#define RADEON_BIOS32(v) ((di->rom.rom_ptr[v]) | \
(di->rom.rom_ptr[(v) + 1] << 8) \
(di->rom.rom_ptr[(v) + 2] << 16) \
(di->rom.rom_ptr[(v) + 3] << 24))
(di->rom.rom_ptr[(v) + 1] << 8) | \
(di->rom.rom_ptr[(v) + 2] << 16) | \
(di->rom.rom_ptr[(v) + 3] << 24))
static const char ati_rom_sig[] = "761295520";
static const tmds_pll_info default_tmds_pll[14][4] =
{
{{12000, 0xa1b}, {0xffffffff, 0xa3f}, {0, 0}, {0, 0}}, // r100
{{12000, 0xa1b}, {0xffffffff, 0xa3f}, {0, 0}, {0, 0}}, // rv100
{{0, 0}, {0, 0}, {0, 0}, {0, 0}}, // rs100
{{15000, 0xa1b}, {0xffffffff, 0xa3f}, {0, 0}, {0, 0}}, // rv200
{{12000, 0xa1b}, {0xffffffff, 0xa3f}, {0, 0}, {0, 0}}, // rs200
{{15000, 0xa1b}, {0xffffffff, 0xa3f}, {0, 0}, {0, 0}}, // r200
{{15500, 0x81b}, {0xffffffff, 0x83f}, {0, 0}, {0, 0}}, // rv250
{{0, 0}, {0, 0}, {0, 0}, {0, 0}}, // rs300
{{13000, 0x400f4}, {15000, 0x400f7}, {0xffffffff, 0x40111}, {0, 0}}, // rv280
{{0xffffffff, 0xb01cb}, {0, 0}, {0, 0}, {0, 0}}, // r300
{{0xffffffff, 0xb01cb}, {0, 0}, {0, 0}, {0, 0}}, // r350
{{15000, 0xb0155}, {0xffffffff, 0xb01cb}, {0, 0}, {0, 0}}, // rv350
{{15000, 0xb0155}, {0xffffffff, 0xb01cb}, {0, 0}, {0, 0}}, // rv380
{{0xffffffff, 0xb01cb}, {0, 0}, {0, 0}, {0, 0}}, // r420
};
// find address of ROM;
// this code is really nasty as maintaining the radeon signatures
// is almost impossible (the signatures provided by ATI are always out-dated);
@ -691,6 +710,108 @@ static void Radeon_RevEnvDFPTiming( device_info *di )
>> RADEON_CRTC_V_SYNC_WID_SHIFT);
}
//snaffled from X.org hope it works...
static void Radeon_GetTMDSInfoFromBios( device_info *di )
{
uint32 tmp, maxfreq;
uint32 found = FALSE;
int i, n;
uint16 bios_header;
bios_header = RADEON_BIOS16( 0x48 );
for (i = 0; i < 4; i++) {
di->tmds_pll[i].value = 0;
di->tmds_pll[i].freq = 0;
}
if (di->is_atombios)
{
int master_data_start;
master_data_start = RADEON_BIOS16( bios_header + 32 );
if((tmp = RADEON_BIOS16 (master_data_start + 18))) {
maxfreq = RADEON_BIOS16(tmp + 4);
for (i = 0; i < 4; i++) {
di->tmds_pll[i].freq = RADEON_BIOS16(tmp + i * 6 + 6);
// This assumes each field in TMDS_PLL has 6 bit as in R300/R420
di->tmds_pll[i].value = ((RADEON_BIOS8(tmp + i * 6 + 8) & 0x3f) |
((RADEON_BIOS8(tmp + i * 6 + 10) & 0x3f) << 6) |
((RADEON_BIOS8(tmp + i * 6 + 9) & 0xf) << 12) |
((RADEON_BIOS8(tmp + i * 6 + 11) & 0xf) << 16));
SHOW_ERROR( 2, "TMDS PLL from BIOS: %ld %lx",
di->tmds_pll[i].freq, di->tmds_pll[i].value);
if (maxfreq == di->tmds_pll[i].freq) {
di->tmds_pll[i].freq = 0xffffffff;
break;
}
}
found = TRUE;
}
} else {
tmp = RADEON_BIOS16(bios_header + 0x34);
if (tmp) {
SHOW_ERROR( 2, "DFP table revision: %d", RADEON_BIOS8(tmp));
if (RADEON_BIOS8(tmp) == 3) {
n = RADEON_BIOS8(tmp + 5) + 1;
if (n > 4)
n = 4;
for (i = 0; i < n; i++) {
di->tmds_pll[i].value = RADEON_BIOS32(tmp + i * 10 + 0x08);
di->tmds_pll[i].freq = RADEON_BIOS16(tmp + i * 10 + 0x10);
}
found = TRUE;
} else if (RADEON_BIOS8(tmp) == 4) {
int stride = 0;
n = RADEON_BIOS8(tmp + 5) + 1;
if (n > 4)
n = 4;
for (i = 0; i < n; i++) {
di->tmds_pll[i].value = RADEON_BIOS32(tmp + stride + 0x08);
di->tmds_pll[i].freq = RADEON_BIOS16(tmp + stride + 0x10);
if (i == 0)
stride += 10;
else
stride += 6;
}
found = TRUE;
}
// revision 4 has some problem as it appears in RV280,
// comment it off for now, use default instead
/*
else if (RADEON_BIOS8(tmp) == 4) {
int stride = 0;
n = RADEON_BIOS8(tmp + 5) + 1;
if (n > 4) n = 4;
for (i = 0; i < n; i++) {
di->tmds_pll[i].value = RADEON_BIOS32(tmp + stride + 0x08);
di->tmds_pll[i].freq = RADEON_BIOS16(tmp + stride + 0x10);
if (i == 0)
stride += 10;
else
stride += 6;
}
found = TRUE;
}
*/
}
}
if (found == FALSE) {
for (i = 0; i < 4; i++) {
di->tmds_pll[i].value = default_tmds_pll[di->asic][i].value;
di->tmds_pll[i].freq = default_tmds_pll[di->asic][i].freq;
SHOW_ERROR( 2, "TMDS PLL from DEFAULTS: %ld %lx",
di->tmds_pll[i].freq, di->tmds_pll[i].value);
}
}
}
/*
// get everything in terms of monitors connected to the card
@ -964,6 +1085,12 @@ status_t Radeon_ReadBIOSData( device_info *di )
di->routing.port_info[0].dac_type = dac_unknown;
di->routing.port_info[0].tmds_type = tmds_unknown;
di->routing.port_info[0].connector_type = connector_none;
di->routing.port_info[1].mon_type = mt_unknown;
di->routing.port_info[1].ddc_type = ddc_none_detected;
di->routing.port_info[1].dac_type = dac_unknown;
di->routing.port_info[1].tmds_type = tmds_unknown;
di->routing.port_info[1].connector_type = connector_none;
if ( !Radeon_GetConnectorInfoFromBIOS( di ) )
{
@ -981,6 +1108,7 @@ status_t Radeon_ReadBIOSData( device_info *di )
}
Radeon_GetFPData( di );
Radeon_GetTMDSInfoFromBios( di );
Radeon_DetectRAM( di );
Radeon_UnmapDevice( di );

View File

@ -15,6 +15,7 @@
*/
#include "dac_regs.h"
#include "tv_out_regs.h"
#include "fp_regs.h"
#include "mmio.h"
#include "radeon_driver.h"
@ -266,20 +267,17 @@ status_t Radeon_FirstOpen( device_info *di )
// so we let the first accelerant take care of it
si->theatre_channel = -1;
/* si->ports[0].disp_type = di->disp_type[0];
si->ports[1].disp_type = di->disp_type[1];*/
si->crtc[0].crtc_idx = 0;
si->crtc[0].flatpanel_port = 0;
si->crtc[1].crtc_idx = 1;
si->crtc[1].flatpanel_port = 1;
si->num_crtc = di->num_crtc;
si->flatpanels[0] = di->fp_info;
if (di->is_mobility)
si->flatpanels[0] = di->fp_info;
si->pll = di->pll;
/* si->ram = di->ram;
strcpy( si->ram_type, di->ram_type );*/
//si->local_mem_size = di->local_mem_size;
// create virtual card info; don't allow access by apps -
// they'll clone it
sprintf( buffer, "%04X_%04X_%02X%02X%02X virtual card 0",
@ -306,7 +304,7 @@ status_t Radeon_FirstOpen( device_info *di )
di->vc->assigned_crtc[0] = true;
di->vc->assigned_crtc[1] = si->num_crtc > 1;
di->vc->controlled_displays =
dd_tv_crt | dd_crt | dd_lvds | dd_dvi | dd_ctv | dd_stv;
dd_tv_crt | dd_crt | dd_lvds | dd_dvi | dd_dvi_ext | dd_ctv | dd_stv;
di->vc->fb_mem_handle = 0;
di->vc->cursor.mem_handle = 0;
@ -324,13 +322,21 @@ status_t Radeon_FirstOpen( device_info *di )
if( di->asic == rt_rv100 && di->is_mobility)
di->dac2_cntl = INREG( di->regs, RADEON_DAC_CNTL2 );
memcpy(&si->tmds_pll, &di->tmds_pll, sizeof(di->tmds_pll));
si->tmds_pll_cntl = INREG( di->regs, RADEON_TMDS_PLL_CNTL);
si->tmds_transmitter_cntl = INREG( di->regs, RADEON_TMDS_TRANSMITTER_CNTL);
// print these out to capture bios status...
if ( di->is_mobility ) {
SHOW_INFO0( 4, "Copy of Laptop Display Regs for Reference:");
SHOW_INFO( 4, "LVDS CNTL = %8lx", INREG( di->regs, RADEON_LVDS_GEN_CNTL ));
SHOW_INFO( 4, "FP1 CNTL = %8lx", INREG( di->regs, RADEON_FP_GEN_CNTL ));
SHOW_INFO( 4, "FP2 CNTL = %8lx", INREG( di->regs, RADEON_FP2_GEN_CNTL ));
}
// if ( di->is_mobility ) {
SHOW_INFO0( 2, "Copy of Laptop Display Regs for Reference:");
SHOW_INFO( 2, "LVDS GEN = %8lx", INREG( di->regs, RADEON_LVDS_GEN_CNTL ));
SHOW_INFO( 2, "LVDS PLL = %8lx", INREG( di->regs, RADEON_LVDS_PLL_CNTL ));
SHOW_INFO( 2, "TMDS PLL = %8lx", INREG( di->regs, RADEON_TMDS_PLL_CNTL ));
SHOW_INFO( 2, "TMDS TRANS = %8lx", INREG( di->regs, RADEON_TMDS_TRANSMITTER_CNTL ));
SHOW_INFO( 2, "FP1 GEN = %8lx", INREG( di->regs, RADEON_FP_GEN_CNTL ));
SHOW_INFO( 2, "FP2 GEN = %8lx", INREG( di->regs, RADEON_FP2_GEN_CNTL ));
SHOW_INFO( 2, "TV DAC = %8lx", INREG( di->regs, RADEON_TV_DAC_CNTL )); //not setup right when ext dvi
// }
result = Radeon_InitPCIGART( di );
if( result < 0 )

View File

@ -116,6 +116,7 @@ typedef struct device_info {
disp_entity routing;
general_pll_info pll;
tmds_pll_info tmds_pll[4];
ram_info ram;
char ram_type[32]; // human-readable name of ram type
uint32 local_mem_size;