xf86-video-ati: Branch 'atombios-support' - 5 commits
Alex Deucher
agd5f at kemper.freedesktop.org
Tue Dec 11 11:08:38 PST 2007
src/radeon.h | 8 ++
src/radeon_bios.c | 18 ++--
src/radeon_crtc.c | 193 ++++++++++++++++++++++++++++++++++++----------------
src/radeon_driver.c | 9 ++
src/radeon_output.c | 66 +++++++++++------
src/radeon_probe.h | 4 -
6 files changed, 206 insertions(+), 92 deletions(-)
New commits:
commit 372bf41818fdafc6a9d2914aee3a8e359f668f02
Author: Alex Deucher <alex at botch2.(none)>
Date: Tue Dec 11 14:04:58 2007 -0500
RADEON: handle HMDI properly (untested) and fix some merge leftovers
diff --git a/src/radeon_output.c b/src/radeon_output.c
index d872205..4dc47ce 100644
--- a/src/radeon_output.c
+++ b/src/radeon_output.c
@@ -290,6 +290,8 @@ avivo_display_ddc_connected(ScrnInfoPtr pScrn, xf86OutputPtr output)
MonType = MT_LCD;
else if (radeon_output->type == OUTPUT_DVI_D)
MonType = MT_DFP;
+ else if (radeon_output->type == OUTPUT_HDMI)
+ MonType = MT_DFP;
else if (radeon_output->type == OUTPUT_DVI_I && (MonInfo->rawData[0x14] & 0x80)) /* if it's digital and DVI */
MonType = MT_DFP;
else
@@ -388,6 +390,8 @@ RADEONDisplayDDCConnected(ScrnInfoPtr pScrn, xf86OutputPtr output)
MonType = MT_LCD;
else if (radeon_output->type == OUTPUT_DVI_D)
MonType = MT_DFP;
+ else if (radeon_output->type == OUTPUT_HDMI)
+ MonType = MT_DFP;
else if (radeon_output->type == OUTPUT_DVI_I && (MonInfo->rawData[0x14] & 0x80)) /* if it's digital and DVI */
MonType = MT_DFP;
else
@@ -655,11 +659,18 @@ legacy_dac_detect(ScrnInfoPtr pScrn, xf86OutputPtr output)
RADEONMonitorType found = MT_NONE;
if (OUTPUT_IS_TV) {
- if (info->InternalTVOut) {
- if (radeon_output->load_detection)
- found = radeon_detect_tv(pScrn);
+ if (xf86ReturnOptValBool(info->Options, OPTION_FORCE_TVOUT, FALSE)) {
+ if (radeon_output->type == OUTPUT_STV)
+ radeon_output->MonType = MT_STV;
else
- found = MT_NONE;
+ radeon_output->MonType = MT_CTV;
+ } else {
+ if (info->InternalTVOut) {
+ if (radeon_output->load_detection)
+ radeon_output->MonType = radeon_detect_tv(pScrn);
+ else
+ radeon_output->MonType = MT_NONE;
+ }
}
} else {
if (radeon_output->DACType == DAC_PRIMARY) {
@@ -693,24 +704,16 @@ void RADEONConnectorFindMonitor(ScrnInfoPtr pScrn, xf86OutputPtr output)
if (!radeon_output->MonType) {
if (radeon_output->type == OUTPUT_LVDS)
radeon_output->MonType = MT_LCD;
- else if (OUTPUT_IS_TV)
- radeon_output->MonType = MT_NONE;
- else
- radeon_output->MonType = atombios_dac_detect(pScrn, output);
- }
- } else if (radeon_output->type == OUTPUT_STV || radeon_output->type == OUTPUT_CTV) {
- if (xf86ReturnOptValBool(info->Options, OPTION_FORCE_TVOUT, FALSE)) {
- if (radeon_output->type == OUTPUT_STV)
- radeon_output->MonType = MT_STV;
- else
- radeon_output->MonType = MT_CTV;
- } else {
- if (info->InternalTVOut) {
- if (radeon_output->load_detection)
- radeon_output->MonType = radeon_detect_tv(pScrn);
- else
+ else if (OUTPUT_IS_TV) {
+ if (xf86ReturnOptValBool(info->Options, OPTION_FORCE_TVOUT, FALSE)) {
+ if (radeon_output->type == OUTPUT_STV)
+ radeon_output->MonType = MT_STV;
+ else
+ radeon_output->MonType = MT_CTV;
+ } else
radeon_output->MonType = MT_NONE;
- }
+ } else
+ radeon_output->MonType = atombios_dac_detect(pScrn, output);
}
} else {
radeon_output->MonType = RADEONDisplayDDCConnected(pScrn, output);
@@ -1735,11 +1738,11 @@ radeon_detect(xf86OutputPtr output)
radeon_output->MonType = MT_CV;
else if (radeon_output->type == OUTPUT_DVI_D)
radeon_output->MonType = MT_DFP;
+ else if (radeon_output->type == OUTPUT_HDMI)
+ radeon_output->MonType = MT_DFP;
else if (radeon_output->type == OUTPUT_DVI_A)
radeon_output->MonType = MT_CRT;
else if (radeon_output->type == OUTPUT_DVI_I) {
- if (radeon_output->MonType == MT_NONE)
- connected = FALSE;
if (radeon_output->DVIType == DVI_ANALOG)
radeon_output->MonType = MT_CRT;
else if (radeon_output->DVIType == DVI_DIGITAL)
@@ -2296,6 +2299,9 @@ void RADEONSetOutputType(ScrnInfoPtr pScrn, RADEONOutputPrivatePtr radeon_output
output = OUTPUT_CTV; break;
case CONNECTOR_LVDS:
output = OUTPUT_LVDS; break;
+ case CONNECTOR_HDMI_TYPE_A:
+ case CONNECTOR_HDMI_TYPE_B:
+ output = OUTPUT_HDMI; break;
case CONNECTOR_DIGITAL:
case CONNECTOR_NONE:
case CONNECTOR_UNSUPPORTED:
@@ -3236,6 +3242,7 @@ Bool RADEONSetupConnectors(ScrnInfoPtr pScrn)
int i = 0;
int num_vga = 0;
int num_dvi = 0;
+ int num_hdmi = 0;
/* We first get the information about all connectors from BIOS.
* This is how the card is phyiscally wired up.
@@ -3342,6 +3349,9 @@ Bool RADEONSetupConnectors(ScrnInfoPtr pScrn)
num_dvi++;
} else if (info->BiosConnector[i].ConnectorType == CONNECTOR_VGA) {
num_vga++;
+ } else if ((info->BiosConnector[i].ConnectorType == CONNECTOR_HDMI_TYPE_A) ||
+ (info->BiosConnector[i].ConnectorType == CONNECTOR_HDMI_TYPE_B)) {
+ num_hdmi++;
}
}
}
@@ -3385,6 +3395,14 @@ Bool RADEONSetupConnectors(ScrnInfoPtr pScrn)
} else {
output = xf86OutputCreate(pScrn, &radeon_output_funcs, "VGA-0");
}
+ } else if ((info->BiosConnector[i].ConnectorType == CONNECTOR_HDMI_TYPE_A) ||
+ (info->BiosConnector[i].ConnectorType == CONNECTOR_HDMI_TYPE_B)) {
+ if (num_hdmi > 1) {
+ output = xf86OutputCreate(pScrn, &radeon_output_funcs, "HDMI-1");
+ num_hdmi--;
+ } else {
+ output = xf86OutputCreate(pScrn, &radeon_output_funcs, "HDMI-0");
+ }
} else
output = xf86OutputCreate(pScrn, &radeon_output_funcs, OutputType[radeon_output->type]);
diff --git a/src/radeon_probe.h b/src/radeon_probe.h
index c0b2694..df07149 100644
--- a/src/radeon_probe.h
+++ b/src/radeon_probe.h
@@ -63,7 +63,7 @@ typedef enum
MT_CTV = 4,
MT_STV = 5,
MT_CV = 6,
- MT_HDMI = 7,
+ MT_HDMI = 7, // this should really just be MT_DFP
MT_DP = 8
} RADEONMonitorType;
commit 3c22ad977c25d5ca2811821fcac6bb8ecd79994a
Merge: c9a0cee... f3d2ec3...
Author: Alex Deucher <alex at botch2.(none)>
Date: Tue Dec 11 13:11:15 2007 -0500
Merge branch 'master' of ssh://agd5f@git.freedesktop.org/git/xorg/driver/xf86-video-ati into atombios-support
fix conflicts
diff --cc src/radeon_crtc.c
index 1ea6d2b,8984428..fa2aba0
--- a/src/radeon_crtc.c
+++ b/src/radeon_crtc.c
@@@ -699,11 -767,11 +781,10 @@@ RADEONInitPLLRegisters(ScrnInfoPtr pScr
#endif
save->ppll_div_3 = (save->feedback_div | (post_div->bitvalue << 16));
- save->htotal_cntl = 0;
+ save->htotal_cntl = mode->HTotal & 0x7;
- save->vclk_ecp_cntl = (info->SavedReg.vclk_ecp_cntl &
- ~RADEON_VCLK_SRC_SEL_MASK) | RADEON_VCLK_SRC_SEL_PPLLCLK;
-
+ save->vclk_ecp_cntl = (info->SavedReg->vclk_ecp_cntl &
+ ~RADEON_VCLK_SRC_SEL_MASK) | RADEON_VCLK_SRC_SEL_PPLLCLK;
-
}
/* Define PLL2 registers for requested video mode */
@@@ -764,17 -826,20 +839,19 @@@ RADEONInitPLL2Registers(ScrnInfoPtr pSc
(unsigned)save->dot_clock_freq_2,
(unsigned)save->pll_output_freq_2,
save->feedback_div_2,
+ save->reference_div_2,
save->post_div_2);
- save->p2pll_ref_div = pll->reference_div;
+ save->p2pll_ref_div = save->reference_div_2;
+
save->p2pll_div_0 = (save->feedback_div_2 |
(post_div->bitvalue << 16));
- save->htotal_cntl2 = 0;
- save->pixclks_cntl = ((info->SavedReg->pixclks_cntl &
- ~(RADEON_PIX2CLK_SRC_SEL_MASK)) |
- RADEON_PIX2CLK_SRC_SEL_P2PLLCLK);
+ save->htotal_cntl2 = mode->HTotal & 0x7;
- save->pixclks_cntl = ((info->SavedReg.pixclks_cntl &
++ save->pixclks_cntl = ((info->SavedReg->pixclks_cntl &
+ ~(RADEON_PIX2CLK_SRC_SEL_MASK)) |
+ RADEON_PIX2CLK_SRC_SEL_P2PLLCLK);
-
}
static void
@@@ -849,27 -914,27 +926,27 @@@ legacy_crtc_mode_set(xf86CrtcPtr crtc,
switch (radeon_crtc->crtc_id) {
case 0:
ErrorF("init crtc1\n");
- RADEONInitCrtcRegisters(crtc, &info->ModeReg, adjusted_mode);
- RADEONInitCrtcBase(crtc, &info->ModeReg, x, y);
+ RADEONInitCrtcRegisters(crtc, info->ModeReg, adjusted_mode);
+ RADEONInitCrtcBase(crtc, info->ModeReg, x, y);
- dot_clock = adjusted_mode->Clock / 1000.0;
- if (dot_clock) {
+ dot_clock = adjusted_mode->Clock / 1000.0;
+ if (dot_clock) {
ErrorF("init pll1\n");
- RADEONInitPLLRegisters(pScrn, info, info->ModeReg, &info->pll, dot_clock);
- } else {
- info->ModeReg->ppll_ref_div = info->SavedReg->ppll_ref_div;
- info->ModeReg->ppll_div_3 = info->SavedReg->ppll_div_3;
- info->ModeReg->htotal_cntl = info->SavedReg->htotal_cntl;
- }
- RADEONInitPLLRegisters(pScrn, &info->ModeReg, &info->pll, adjusted_mode);
++ RADEONInitPLLRegisters(pScrn, info->ModeReg, &info->pll, adjusted_mode);
+ } else {
- info->ModeReg.ppll_ref_div = info->SavedReg.ppll_ref_div;
- info->ModeReg.ppll_div_3 = info->SavedReg.ppll_div_3;
- info->ModeReg.htotal_cntl = info->SavedReg.htotal_cntl;
++ info->ModeReg->ppll_ref_div = info->SavedReg->ppll_ref_div;
++ info->ModeReg->ppll_div_3 = info->SavedReg->ppll_div_3;
++ info->ModeReg->htotal_cntl = info->SavedReg->htotal_cntl;
+ }
break;
case 1:
ErrorF("init crtc2\n");
- RADEONInitCrtc2Registers(crtc, info->ModeReg, adjusted_mode);
- RADEONInitCrtc2Registers(crtc, &info->ModeReg, adjusted_mode);
- RADEONInitCrtc2Base(crtc, &info->ModeReg, x, y);
++ RADEONInitCrtc2Registers(crtc, info->ModeReg, adjusted_mode);
+ RADEONInitCrtc2Base(crtc, info->ModeReg, x, y);
- dot_clock = adjusted_mode->Clock / 1000.0;
- if (dot_clock) {
+ dot_clock = adjusted_mode->Clock / 1000.0;
+ if (dot_clock) {
ErrorF("init pll2\n");
- RADEONInitPLL2Registers(pScrn, info->ModeReg, &info->pll, dot_clock, no_odd_post_div);
- }
- RADEONInitPLL2Registers(pScrn, &info->ModeReg, &info->pll, adjusted_mode);
++ RADEONInitPLL2Registers(pScrn, info->ModeReg, &info->pll, adjusted_mode);
+ }
break;
}
diff --cc src/radeon_probe.h
index a7d873e,66ece94..c0b2694
--- a/src/radeon_probe.h
+++ b/src/radeon_probe.h
@@@ -232,287 -221,10 +232,289 @@@ typedef struct _RADEONOutputPrivateRec
int SupportedTVStds;
Bool tv_on;
int load_detection;
+
+ char *name;
+ int output_id;
+ int devices;
} RADEONOutputPrivateRec, *RADEONOutputPrivatePtr;
+struct avivo_pll_state {
+ CARD32 ref_div_src;
+ CARD32 ref_div;
+ CARD32 fb_div;
+ CARD32 post_div_src;
+ CARD32 post_div;
+ CARD32 ext_ppll_cntl;
+ CARD32 pll_cntl;
+ CARD32 int_ss_cntl;
+};
+
+
+struct avivo_crtc_state {
+ CARD32 pll_source;
+ CARD32 h_total;
+ CARD32 h_blank_start_end;
+ CARD32 h_sync_a;
+ CARD32 h_sync_a_cntl;
+ CARD32 h_sync_b;
+ CARD32 h_sync_b_cntl;
+ CARD32 v_total;
+ CARD32 v_blank_start_end;
+ CARD32 v_sync_a;
+ CARD32 v_sync_a_cntl;
+ CARD32 v_sync_b;
+ CARD32 v_sync_b_cntl;
+ CARD32 control;
+ CARD32 blank_control;
+ CARD32 interlace_control;
+ CARD32 stereo_control;
+ CARD32 cursor_control;
+};
+
+struct avivo_grph_state {
+ CARD32 enable;
+ CARD32 control;
+ CARD32 prim_surf_addr;
+ CARD32 sec_surf_addr;
+ CARD32 pitch;
+ CARD32 x_offset;
+ CARD32 y_offset;
+ CARD32 x_start;
+ CARD32 y_start;
+ CARD32 x_end;
+ CARD32 y_end;
+
+ CARD32 viewport_start;
+ CARD32 viewport_size;
+ CARD32 scl_enable;
+};
+
+struct avivo_dac_state {
+ CARD32 enable;
+ CARD32 source_select;
+ CARD32 force_output_cntl;
+ CARD32 powerdown;
+};
+
+struct avivo_dig_state {
+ CARD32 cntl;
+ CARD32 bit_depth_cntl;
+ CARD32 data_sync;
+ CARD32 transmitter_enable;
+ CARD32 transmitter_cntl;
+ CARD32 source_select;
+};
+
+struct avivo_state
+{
+ CARD32 hdp_fb_location;
+ CARD32 mc_memory_map;
+ CARD32 vga_memory_base;
+ CARD32 vga_fb_start;
+
+ CARD32 vga1_cntl;
+ CARD32 vga2_cntl;
+
+ CARD32 crtc_master_en;
+ CARD32 crtc_tv_control;
+
+ CARD32 lvtma_pwrseq_cntl;
+ CARD32 lvtma_pwrseq_state;
+
+ struct avivo_pll_state pll1;
+ struct avivo_pll_state pll2;
+
+ struct avivo_crtc_state crtc1;
+ struct avivo_crtc_state crtc2;
+
+ struct avivo_grph_state grph1;
+ struct avivo_grph_state grph2;
+
+ struct avivo_dac_state daca;
+ struct avivo_dac_state dacb;
+
+ struct avivo_dig_state tmds1;
+ struct avivo_dig_state tmds2;
+
+};
+
+/*
+ * Maximum length of horizontal/vertical code timing tables for state storage
+ */
+#define MAX_H_CODE_TIMING_LEN 32
+#define MAX_V_CODE_TIMING_LEN 32
+
+typedef struct {
+ struct avivo_state avivo;
+
+ /* Common registers */
+ CARD32 ovr_clr;
+ CARD32 ovr_wid_left_right;
+ CARD32 ovr_wid_top_bottom;
+ CARD32 ov0_scale_cntl;
+ CARD32 mpp_tb_config;
+ CARD32 mpp_gp_config;
+ CARD32 subpic_cntl;
+ CARD32 viph_control;
+ CARD32 i2c_cntl_1;
+ CARD32 gen_int_cntl;
+ CARD32 cap0_trig_cntl;
+ CARD32 cap1_trig_cntl;
+ CARD32 bus_cntl;
+ CARD32 bios_4_scratch;
+ CARD32 bios_5_scratch;
+ CARD32 bios_6_scratch;
+ CARD32 surface_cntl;
+ CARD32 surfaces[8][3];
+ CARD32 mc_agp_location;
+ CARD32 mc_agp_location_hi;
+ CARD32 mc_fb_location;
+ CARD32 display_base_addr;
+ CARD32 display2_base_addr;
+ CARD32 ov0_base_addr;
+
+ /* Other registers to save for VT switches */
+ CARD32 dp_datatype;
+ CARD32 rbbm_soft_reset;
+ CARD32 clock_cntl_index;
+ CARD32 amcgpio_en_reg;
+ CARD32 amcgpio_mask;
+
+ /* CRTC registers */
+ CARD32 crtc_gen_cntl;
+ CARD32 crtc_ext_cntl;
+ CARD32 dac_cntl;
+ CARD32 crtc_h_total_disp;
+ CARD32 crtc_h_sync_strt_wid;
+ CARD32 crtc_v_total_disp;
+ CARD32 crtc_v_sync_strt_wid;
+ CARD32 crtc_offset;
+ CARD32 crtc_offset_cntl;
+ CARD32 crtc_pitch;
+ CARD32 disp_merge_cntl;
+ CARD32 grph_buffer_cntl;
+ CARD32 crtc_more_cntl;
+ CARD32 crtc_tile_x0_y0;
+
+ /* CRTC2 registers */
+ CARD32 crtc2_gen_cntl;
+ CARD32 dac_macro_cntl;
+ CARD32 dac2_cntl;
+ CARD32 disp_output_cntl;
+ CARD32 disp_tv_out_cntl;
+ CARD32 disp_hw_debug;
+ CARD32 disp2_merge_cntl;
+ CARD32 grph2_buffer_cntl;
+ CARD32 crtc2_h_total_disp;
+ CARD32 crtc2_h_sync_strt_wid;
+ CARD32 crtc2_v_total_disp;
+ CARD32 crtc2_v_sync_strt_wid;
+ CARD32 crtc2_offset;
+ CARD32 crtc2_offset_cntl;
+ CARD32 crtc2_pitch;
+ CARD32 crtc2_tile_x0_y0;
+
+ /* Flat panel registers */
+ CARD32 fp_crtc_h_total_disp;
+ CARD32 fp_crtc_v_total_disp;
+ CARD32 fp_gen_cntl;
+ CARD32 fp2_gen_cntl;
+ CARD32 fp_h_sync_strt_wid;
+ CARD32 fp_h2_sync_strt_wid;
+ CARD32 fp_horz_stretch;
+ CARD32 fp_panel_cntl;
+ CARD32 fp_v_sync_strt_wid;
+ CARD32 fp_v2_sync_strt_wid;
+ CARD32 fp_vert_stretch;
+ CARD32 lvds_gen_cntl;
+ CARD32 lvds_pll_cntl;
+ CARD32 tmds_pll_cntl;
+ CARD32 tmds_transmitter_cntl;
+
+ /* Computed values for PLL */
+ CARD32 dot_clock_freq;
+ CARD32 pll_output_freq;
+ int feedback_div;
++ int reference_div;
+ int post_div;
+
+ /* PLL registers */
+ unsigned ppll_ref_div;
+ unsigned ppll_div_3;
+ CARD32 htotal_cntl;
+ CARD32 vclk_ecp_cntl;
+
+ /* Computed values for PLL2 */
+ CARD32 dot_clock_freq_2;
+ CARD32 pll_output_freq_2;
+ int feedback_div_2;
++ int reference_div_2;
+ int post_div_2;
+
+ /* PLL2 registers */
+ CARD32 p2pll_ref_div;
+ CARD32 p2pll_div_0;
+ CARD32 htotal_cntl2;
+ CARD32 pixclks_cntl;
+
+ /* Pallet */
+ Bool palette_valid;
+ CARD32 palette[256];
+ CARD32 palette2[256];
+
+ CARD32 rs480_unk_e30;
+ CARD32 rs480_unk_e34;
+ CARD32 rs480_unk_e38;
+ CARD32 rs480_unk_e3c;
+
+ /* TV out registers */
+ CARD32 tv_master_cntl;
+ CARD32 tv_htotal;
+ CARD32 tv_hsize;
+ CARD32 tv_hdisp;
+ CARD32 tv_hstart;
+ CARD32 tv_vtotal;
+ CARD32 tv_vdisp;
+ CARD32 tv_timing_cntl;
+ CARD32 tv_vscaler_cntl1;
+ CARD32 tv_vscaler_cntl2;
+ CARD32 tv_sync_size;
+ CARD32 tv_vrestart;
+ CARD32 tv_hrestart;
+ CARD32 tv_frestart;
+ CARD32 tv_ftotal;
+ CARD32 tv_clock_sel_cntl;
+ CARD32 tv_clkout_cntl;
+ CARD32 tv_data_delay_a;
+ CARD32 tv_data_delay_b;
+ CARD32 tv_dac_cntl;
+ CARD32 tv_pll_cntl;
+ CARD32 tv_pll_cntl1;
+ CARD32 tv_pll_fine_cntl;
+ CARD32 tv_modulator_cntl1;
+ CARD32 tv_modulator_cntl2;
+ CARD32 tv_frame_lock_cntl;
+ CARD32 tv_pre_dac_mux_cntl;
+ CARD32 tv_rgb_cntl;
+ CARD32 tv_y_saw_tooth_cntl;
+ CARD32 tv_y_rise_cntl;
+ CARD32 tv_y_fall_cntl;
+ CARD32 tv_uv_adr;
+ CARD32 tv_upsamp_and_gain_cntl;
+ CARD32 tv_gain_limit_settings;
+ CARD32 tv_linear_gain_settings;
+ CARD32 tv_crc_cntl;
+ CARD32 tv_sync_cntl;
+ CARD32 gpiopad_a;
+ CARD32 pll_test_cntl;
+
+ CARD16 h_code_timing[MAX_H_CODE_TIMING_LEN];
+ CARD16 v_code_timing[MAX_V_CODE_TIMING_LEN];
+
+} RADEONSaveRec, *RADEONSavePtr;
+
#define RADEON_MAX_CRTC 2
-#define RADEON_MAX_BIOS_CONNECTOR 8
+#define RADEON_MAX_BIOS_CONNECTOR 16
typedef struct
{
commit f3d2ec3a5ae61215c792018320158750e7aa937c
Author: Alex Deucher <alex at botch2.(none)>
Date: Tue Dec 11 11:57:27 2007 -0500
RADEON: rewrite PLL computation
Algorithm adapted from BeOS radeon driver with some tweaks by me.
Actually calulate and use the reference divider rather than using the bios default.
Also, always calculate the PLL, rather than falling back to bios dividers.
This should fix bugs 12913, 13590, 13533, possibly others.
diff --git a/src/radeon.h b/src/radeon.h
index fe491e8..b7f9288 100644
--- a/src/radeon.h
+++ b/src/radeon.h
@@ -288,6 +288,7 @@ typedef struct {
CARD32 dot_clock_freq;
CARD32 pll_output_freq;
int feedback_div;
+ int reference_div;
int post_div;
/* PLL registers */
@@ -300,6 +301,7 @@ typedef struct {
CARD32 dot_clock_freq_2;
CARD32 pll_output_freq_2;
int feedback_div_2;
+ int reference_div_2;
int post_div_2;
/* PLL2 registers */
@@ -370,6 +372,14 @@ typedef struct {
CARD32 min_pll_freq;
CARD32 max_pll_freq;
CARD16 xclk;
+
+ CARD32 min_ref_div;
+ CARD32 max_ref_div;
+ CARD32 min_feedback_div;
+ CARD32 max_feedback_div;
+ CARD32 pll_in_min;
+ CARD32 pll_in_max;
+ CARD32 best_vco;
} RADEONPLLRec, *RADEONPLLPtr;
typedef struct {
diff --git a/src/radeon_crtc.c b/src/radeon_crtc.c
index b1d216d..8984428 100644
--- a/src/radeon_crtc.c
+++ b/src/radeon_crtc.c
@@ -612,13 +612,96 @@ static int RADEONDiv(int n, int d)
return (n + (d / 2)) / d;
}
+static CARD32 RADEONDiv64(CARD64 n, CARD32 d)
+{
+ return (n + (d / 2)) / d;
+}
+
+static void
+RADEONComputePLL(RADEONPLLPtr pll,
+ unsigned long freq,
+ CARD32 *chosen_dot_clock_freq,
+ CARD32 *chosen_feedback_div,
+ CARD32 *chosen_reference_div,
+ CARD32 *chosen_post_div)
+{
+ int post_divs[] = {1, 2, 4, 8, 3, 6, 12, 0};
+
+ int i;
+
+ CARD32 best_vco = pll->best_vco;
+ CARD32 best_post_div = 1;
+ CARD32 best_ref_div = 1;
+ CARD32 best_feedback_div = 1;
+ CARD32 best_freq = 1;
+ CARD32 best_error = 0xffffffff;
+ CARD32 best_vco_diff = 1;
+
+ ErrorF("freq: %d\n", freq);
+
+ for (i = 0; post_divs[i]; i++) {
+ int post_div = post_divs[i];
+ CARD32 ref_div;
+ CARD32 vco = (freq / 10000) * post_div;
+
+ if (vco < pll->min_pll_freq || vco > pll->max_pll_freq)
+ continue;
+
+ for (ref_div = pll->min_ref_div; ref_div <= pll->max_ref_div; ++ref_div) {
+ CARD32 feedback_div, current_freq, error, vco_diff;
+ CARD32 pll_in = pll->reference_freq / ref_div;
+
+ if (pll_in < pll->pll_in_min || pll_in > pll->pll_in_max)
+ continue;
+
+ feedback_div = RADEONDiv64((CARD64)freq * ref_div * post_div,
+ pll->reference_freq * 10000);
+
+ if (feedback_div < pll->min_feedback_div || feedback_div > pll->max_feedback_div)
+ continue;
+
+ current_freq = RADEONDiv64((CARD64)pll->reference_freq * 10000 * feedback_div,
+ ref_div * post_div);
+
+ error = abs(current_freq - freq);
+ vco_diff = abs(vco - best_vco);
+
+ if ((best_vco == 0 && error < best_error) ||
+ (best_vco != 0 &&
+ (error < best_error - 100 ||
+ (abs(error - best_error) < 100 && vco_diff < best_vco_diff )))) {
+ best_post_div = post_div;
+ best_ref_div = ref_div;
+ best_feedback_div = feedback_div;
+ best_freq = current_freq;
+ best_error = error;
+ best_vco_diff = vco_diff;
+ }
+ }
+ }
+
+ ErrorF("best_freq: %d\n", best_freq);
+ ErrorF("best_feedback_div: %d\n", best_feedback_div);
+ ErrorF("best_ref_div: %d\n", best_ref_div);
+ ErrorF("best_post_div: %d\n", best_post_div);
+
+ *chosen_dot_clock_freq = best_freq;
+ *chosen_feedback_div = best_feedback_div;
+ *chosen_reference_div = best_ref_div;
+ *chosen_post_div = best_post_div;
+
+}
+
/* Define PLL registers for requested video mode */
static void
-RADEONInitPLLRegisters(ScrnInfoPtr pScrn, RADEONInfoPtr info,
- RADEONSavePtr save, RADEONPLLPtr pll,
- double dot_clock)
+RADEONInitPLLRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save,
+ RADEONPLLPtr pll, DisplayModePtr mode)
{
- unsigned long freq = dot_clock * 100;
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ CARD32 feedback_div = 0;
+ CARD32 reference_div = 0;
+ CARD32 post_divider = 0;
+ CARD32 freq = 0;
struct {
int divider;
@@ -640,21 +723,20 @@ RADEONInitPLLRegisters(ScrnInfoPtr pScrn, RADEONInfoPtr info,
{ 0, 0 }
};
+ RADEONComputePLL(pll, mode->Clock * 1000, &freq, &feedback_div, &reference_div, &post_divider);
+
+#if 0
if (info->UseBiosDividers) {
save->ppll_ref_div = info->RefDivider;
save->ppll_div_3 = info->FeedbackDivider | (info->PostDivider << 16);
save->htotal_cntl = 0;
return;
}
-
- if (freq > pll->max_pll_freq) freq = pll->max_pll_freq;
- if (freq * 12 < pll->min_pll_freq) freq = pll->min_pll_freq / 12;
+#endif
for (post_div = &post_divs[0]; post_div->divider; ++post_div) {
- save->pll_output_freq = post_div->divider * freq;
-
- if (save->pll_output_freq >= pll->min_pll_freq
- && save->pll_output_freq <= pll->max_pll_freq) break;
+ if (post_div->divider == post_divider)
+ break;
}
if (!post_div->divider) {
@@ -662,20 +744,20 @@ RADEONInitPLLRegisters(ScrnInfoPtr pScrn, RADEONInfoPtr info,
post_div = &post_divs[0];
}
- save->dot_clock_freq = freq;
- save->feedback_div = RADEONDiv(pll->reference_div
- * save->pll_output_freq,
- pll->reference_freq);
- save->post_div = post_div->divider;
+ save->dot_clock_freq = freq / 10000;
+ save->feedback_div = feedback_div;
+ save->reference_div = reference_div;
+ save->post_div = post_divider;
xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
- "dc=%u, of=%u, fd=%d, pd=%d\n",
+ "dc=%u, of=%u, fd=%d, rd=%d, pd=%d\n",
(unsigned)save->dot_clock_freq,
(unsigned)save->pll_output_freq,
save->feedback_div,
+ save->reference_div,
save->post_div);
- save->ppll_ref_div = pll->reference_div;
+ save->ppll_ref_div = save->reference_div;
#if defined(__powerpc__)
/* apparently programming this otherwise causes a hang??? */
@@ -685,21 +767,23 @@ RADEONInitPLLRegisters(ScrnInfoPtr pScrn, RADEONInfoPtr info,
#endif
save->ppll_div_3 = (save->feedback_div | (post_div->bitvalue << 16));
- save->htotal_cntl = 0;
+ save->htotal_cntl = mode->HTotal & 0x7;
- save->vclk_ecp_cntl = (info->SavedReg.vclk_ecp_cntl &
- ~RADEON_VCLK_SRC_SEL_MASK) | RADEON_VCLK_SRC_SEL_PPLLCLK;
+ save->vclk_ecp_cntl = (info->SavedReg.vclk_ecp_cntl &
+ ~RADEON_VCLK_SRC_SEL_MASK) | RADEON_VCLK_SRC_SEL_PPLLCLK;
}
/* Define PLL2 registers for requested video mode */
static void
RADEONInitPLL2Registers(ScrnInfoPtr pScrn, RADEONSavePtr save,
- RADEONPLLPtr pll, double dot_clock,
- int no_odd_postdiv)
+ RADEONPLLPtr pll, DisplayModePtr mode)
{
- RADEONInfoPtr info = RADEONPTR(pScrn);
- unsigned long freq = dot_clock * 100;
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ CARD32 feedback_div = 0;
+ CARD32 reference_div = 0;
+ CARD32 post_divider = 0;
+ CARD32 freq = 0;
struct {
int divider;
@@ -720,18 +804,11 @@ RADEONInitPLL2Registers(ScrnInfoPtr pScrn, RADEONSavePtr save,
{ 0, 0 }
};
- if (freq > pll->max_pll_freq) freq = pll->max_pll_freq;
- if (freq * 12 < pll->min_pll_freq) freq = pll->min_pll_freq / 12;
+ RADEONComputePLL(pll, mode->Clock * 1000, &freq, &feedback_div, &reference_div, &post_divider);
for (post_div = &post_divs[0]; post_div->divider; ++post_div) {
- /* Odd post divider value don't work properly on the second digital
- * output
- */
- if (no_odd_postdiv && (post_div->divider & 1))
- continue;
- save->pll_output_freq_2 = post_div->divider * freq;
- if (save->pll_output_freq_2 >= pll->min_pll_freq
- && save->pll_output_freq_2 <= pll->max_pll_freq) break;
+ if (post_div->divider == post_divider)
+ break;
}
if (!post_div->divider) {
@@ -739,27 +816,29 @@ RADEONInitPLL2Registers(ScrnInfoPtr pScrn, RADEONSavePtr save,
post_div = &post_divs[0];
}
- save->dot_clock_freq_2 = freq;
- save->feedback_div_2 = RADEONDiv(pll->reference_div
- * save->pll_output_freq_2,
- pll->reference_freq);
- save->post_div_2 = post_div->divider;
+ save->dot_clock_freq_2 = freq / 10000;
+ save->feedback_div_2 = feedback_div;
+ save->reference_div_2 = reference_div;
+ save->post_div_2 = post_divider;
xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
- "dc=%u, of=%u, fd=%d, pd=%d\n",
+ "dc=%u, of=%u, fd=%d, rd=%d, pd=%d\n",
(unsigned)save->dot_clock_freq_2,
(unsigned)save->pll_output_freq_2,
save->feedback_div_2,
+ save->reference_div_2,
save->post_div_2);
- save->p2pll_ref_div = pll->reference_div;
+ save->p2pll_ref_div = save->reference_div_2;
+
save->p2pll_div_0 = (save->feedback_div_2 |
(post_div->bitvalue << 16));
- save->htotal_cntl2 = 0;
- save->pixclks_cntl = ((info->SavedReg.pixclks_cntl &
- ~(RADEON_PIX2CLK_SRC_SEL_MASK)) |
- RADEON_PIX2CLK_SRC_SEL_P2PLLCLK);
+ save->htotal_cntl2 = mode->HTotal & 0x7;
+
+ save->pixclks_cntl = ((info->SavedReg.pixclks_cntl &
+ ~(RADEON_PIX2CLK_SRC_SEL_MASK)) |
+ RADEON_PIX2CLK_SRC_SEL_P2PLLCLK);
}
@@ -837,25 +916,25 @@ radeon_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode,
ErrorF("init crtc1\n");
RADEONInitCrtcRegisters(crtc, &info->ModeReg, adjusted_mode);
RADEONInitCrtcBase(crtc, &info->ModeReg, x, y);
- dot_clock = adjusted_mode->Clock / 1000.0;
- if (dot_clock) {
+ dot_clock = adjusted_mode->Clock / 1000.0;
+ if (dot_clock) {
ErrorF("init pll1\n");
- RADEONInitPLLRegisters(pScrn, info, &info->ModeReg, &info->pll, dot_clock);
- } else {
- info->ModeReg.ppll_ref_div = info->SavedReg.ppll_ref_div;
- info->ModeReg.ppll_div_3 = info->SavedReg.ppll_div_3;
- info->ModeReg.htotal_cntl = info->SavedReg.htotal_cntl;
- }
+ RADEONInitPLLRegisters(pScrn, &info->ModeReg, &info->pll, adjusted_mode);
+ } else {
+ info->ModeReg.ppll_ref_div = info->SavedReg.ppll_ref_div;
+ info->ModeReg.ppll_div_3 = info->SavedReg.ppll_div_3;
+ info->ModeReg.htotal_cntl = info->SavedReg.htotal_cntl;
+ }
break;
case 1:
ErrorF("init crtc2\n");
- RADEONInitCrtc2Registers(crtc, &info->ModeReg, adjusted_mode);
+ RADEONInitCrtc2Registers(crtc, &info->ModeReg, adjusted_mode);
RADEONInitCrtc2Base(crtc, &info->ModeReg, x, y);
- dot_clock = adjusted_mode->Clock / 1000.0;
- if (dot_clock) {
+ dot_clock = adjusted_mode->Clock / 1000.0;
+ if (dot_clock) {
ErrorF("init pll2\n");
- RADEONInitPLL2Registers(pScrn, &info->ModeReg, &info->pll, dot_clock, no_odd_post_div);
- }
+ RADEONInitPLL2Registers(pScrn, &info->ModeReg, &info->pll, adjusted_mode);
+ }
break;
}
diff --git a/src/radeon_driver.c b/src/radeon_driver.c
index 50f78eb..4b5008e 100644
--- a/src/radeon_driver.c
+++ b/src/radeon_driver.c
@@ -1063,6 +1063,15 @@ static void RADEONGetClockInfo(ScrnInfoPtr pScrn)
info->RamWidth / 16);
}
+ /* card limits for computing PLLs */
+ pll->min_ref_div = 2;
+ pll->max_ref_div = 0x3ff;
+ pll->min_feedback_div = 4;
+ pll->max_feedback_div = 0x7ff;
+ pll->pll_in_min = 40;
+ pll->pll_in_max = 100;
+ pll->best_vco = 0;
+
xf86DrvMsg (pScrn->scrnIndex, X_INFO,
"PLL parameters: rf=%u rd=%u min=%u max=%u; xclk=%u\n",
pll->reference_freq,
commit 9b125312ab6edc585e4f5931a6a6de81e13b6acc
Author: Alex Deucher <alex at t41p.hsd1.va.comcast.net>
Date: Mon Dec 10 13:53:15 2007 -0500
RADEON: only update crtc values when RMX is active
diff --git a/src/radeon_output.c b/src/radeon_output.c
index 11a2a8a..d041d54 100644
--- a/src/radeon_output.c
+++ b/src/radeon_output.c
@@ -800,7 +800,7 @@ radeon_mode_fixup(xf86OutputPtr output, DisplayModePtr mode,
}
/* update timing for LVDS and DFP if RMX is active */
- if ((radeon_output->MonType == MT_LCD) || (radeon_output->Flags & RADEON_USE_RMX)) {
+ if (radeon_output->Flags & RADEON_USE_RMX) {
/* set to the panel's native mode */
adjusted_mode->HTotal = radeon_output->PanelXRes + radeon_output->HBlank;
adjusted_mode->HSyncStart = radeon_output->PanelXRes + radeon_output->HOverPlus;
commit 3a161e1b5d80361e318ced8da5c19e797749d693
Author: Alex Deucher <alex at botch2.(none)>
Date: Mon Dec 10 00:57:26 2007 -0500
RADEON: bios PLL cleanup
diff --git a/src/radeon_bios.c b/src/radeon_bios.c
index 1b46746..bc908b5 100644
--- a/src/radeon_bios.c
+++ b/src/radeon_bios.c
@@ -469,15 +469,6 @@ Bool RADEONGetClockInfoFromBIOS (ScrnInfoPtr pScrn)
info->sclk = RADEON_BIOS32(pll_info_block + 8) / 100.0;
info->mclk = RADEON_BIOS32(pll_info_block + 12) / 100.0;
- if (info->sclk == 0) info->sclk = 200;
- if (info->mclk == 0) info->mclk = 200;
-
- xf86DrvMsg(pScrn->scrnIndex, X_INFO, "ref_freq: %d, min_pll: %u, "
- "max_pll: %u, xclk: %d, sclk: %f, mclk: %f\n",
- pll->reference_freq, (unsigned)pll->min_pll_freq,
- (unsigned)pll->max_pll_freq, pll->xclk, info->sclk,
- info->mclk);
-
} else {
pll_info_block = RADEON_BIOS16 (info->ROMHeaderStart + 0x30);
@@ -490,8 +481,17 @@ Bool RADEONGetClockInfoFromBIOS (ScrnInfoPtr pScrn)
info->sclk = RADEON_BIOS16(pll_info_block + 8) / 100.0;
info->mclk = RADEON_BIOS16(pll_info_block + 10) / 100.0;
}
+
+ if (info->sclk == 0) info->sclk = 200;
+ if (info->mclk == 0) info->mclk = 200;
}
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "ref_freq: %d, min_pll: %u, "
+ "max_pll: %u, xclk: %d, sclk: %f, mclk: %f\n",
+ pll->reference_freq, (unsigned)pll->min_pll_freq,
+ (unsigned)pll->max_pll_freq, pll->xclk, info->sclk,
+ info->mclk);
+
return TRUE;
}
More information about the xorg-commit
mailing list