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