xf86-video-ati: Branch 'master' - 2 commits

Alex Deucher agd5f at kemper.freedesktop.org
Thu Apr 30 16:20:35 PDT 2009


 src/atombios_crtc.c              |  415 +++++++++++++++++++++++++++++++++++----
 src/radeon.h                     |    6 
 src/radeon_atombios.c            |   29 ++
 src/radeon_atombios.h            |    3 
 src/radeon_driver.c              |    9 
 src/radeon_exa_render.c          |    8 
 src/radeon_output.c              |   15 +
 src/radeon_probe.h               |    3 
 src/radeon_reg.h                 |   15 +
 src/radeon_textured_videofuncs.c |   16 -
 10 files changed, 467 insertions(+), 52 deletions(-)

New commits:
commit 1f70c9f05df9017d87b37f887e1eccd6d0568a02
Author: Alex Deucher <alexdeucher at gmail.com>
Date:   Thu Apr 30 19:18:13 2009 -0400

    R3xx-R5xx: don't set TX_OFFSET_RS in RS_INST_COUNT
    
    Isn't necessary and seems to cause problems for RS690 users

diff --git a/src/radeon_exa_render.c b/src/radeon_exa_render.c
index 831a6ff..99020a4 100644
--- a/src/radeon_exa_render.c
+++ b/src/radeon_exa_render.c
@@ -1499,7 +1499,7 @@ static Bool FUNC_NAME(R300PrepareComposite)(int op, PicturePtr pSrcPicture,
 			   R300_RS_COUNT_HIRES_EN));
 
 	    /* R300_INST_COUNT_RS - highest RS instruction used */
-	    OUT_ACCEL_REG(R300_RS_INST_COUNT, R300_INST_COUNT_RS(1) | R300_TX_OFFSET_RS(6));
+	    OUT_ACCEL_REG(R300_RS_INST_COUNT, R300_INST_COUNT_RS(1));
 
 	    OUT_ACCEL_REG(R300_US_CODE_OFFSET, (R300_ALU_CODE_OFFSET(0) |
 						R300_ALU_CODE_SIZE(0) |
@@ -1521,7 +1521,7 @@ static Bool FUNC_NAME(R300PrepareComposite)(int op, PicturePtr pSrcPicture,
 			  ((2 << R300_RS_COUNT_IT_COUNT_SHIFT) |
 			   R300_RS_COUNT_HIRES_EN));
 
-	    OUT_ACCEL_REG(R300_RS_INST_COUNT, R300_INST_COUNT_RS(0) | R300_TX_OFFSET_RS(6));
+	    OUT_ACCEL_REG(R300_RS_INST_COUNT, R300_INST_COUNT_RS(0));
 
 	    OUT_ACCEL_REG(R300_US_CODE_OFFSET, (R300_ALU_CODE_OFFSET(0) |
 						R300_ALU_CODE_SIZE(0) |
@@ -1748,7 +1748,7 @@ static Bool FUNC_NAME(R300PrepareComposite)(int op, PicturePtr pSrcPicture,
 			   R300_RS_COUNT_HIRES_EN));
 
 	    /* 2 RS instructions: 1 for tex0 (src), 1 for tex1 (mask) */
-	    OUT_ACCEL_REG(R300_RS_INST_COUNT, R300_INST_COUNT_RS(1) | R300_TX_OFFSET_RS(6));
+	    OUT_ACCEL_REG(R300_RS_INST_COUNT, R300_INST_COUNT_RS(1));
 
 	    OUT_ACCEL_REG(R500_US_CODE_ADDR, (R500_US_CODE_START_ADDR(0) |
 					      R500_US_CODE_END_ADDR(2)));
@@ -1760,7 +1760,7 @@ static Bool FUNC_NAME(R300PrepareComposite)(int op, PicturePtr pSrcPicture,
 			  ((2 << R300_RS_COUNT_IT_COUNT_SHIFT) |
 			   R300_RS_COUNT_HIRES_EN));
 
-	    OUT_ACCEL_REG(R300_RS_INST_COUNT, R300_INST_COUNT_RS(0) | R300_TX_OFFSET_RS(6));
+	    OUT_ACCEL_REG(R300_RS_INST_COUNT, R300_INST_COUNT_RS(0));
 
 	    OUT_ACCEL_REG(R500_US_CODE_ADDR, (R500_US_CODE_START_ADDR(0) |
 					      R500_US_CODE_END_ADDR(1)));
diff --git a/src/radeon_textured_videofuncs.c b/src/radeon_textured_videofuncs.c
index dd6f862..41e99b1 100644
--- a/src/radeon_textured_videofuncs.c
+++ b/src/radeon_textured_videofuncs.c
@@ -1257,7 +1257,7 @@ FUNC_NAME(R300DisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
 					  R300_RS_COUNT_HIRES_EN));
 
 	    /* R300_INST_COUNT_RS - highest RS instruction used */
-	    OUT_ACCEL_REG(R300_RS_INST_COUNT, R300_INST_COUNT_RS(1) | R300_TX_OFFSET_RS(6));
+	    OUT_ACCEL_REG(R300_RS_INST_COUNT, R300_INST_COUNT_RS(1));
 
 	    /* Pixel stack frame size. */
 	    OUT_ACCEL_REG(R300_US_PIXSIZE, 5);
@@ -1601,7 +1601,7 @@ FUNC_NAME(R300DisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
                           ((2 << R300_RS_COUNT_IT_COUNT_SHIFT) |
                            R300_RS_COUNT_HIRES_EN));
 	    /* R300_INST_COUNT_RS - highest RS instruction used */
-	    OUT_ACCEL_REG(R300_RS_INST_COUNT, R300_INST_COUNT_RS(0) | R300_TX_OFFSET_RS(6));
+	    OUT_ACCEL_REG(R300_RS_INST_COUNT, R300_INST_COUNT_RS(0));
 
 	    OUT_ACCEL_REG(R300_US_PIXSIZE, 0); /* highest temp used */
 
@@ -1738,7 +1738,7 @@ FUNC_NAME(R300DisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
 			  ((2 << R300_RS_COUNT_IT_COUNT_SHIFT) |
 			   R300_RS_COUNT_HIRES_EN));
 	    /* R300_INST_COUNT_RS - highest RS instruction used */
-	    OUT_ACCEL_REG(R300_RS_INST_COUNT, R300_INST_COUNT_RS(0) | R300_TX_OFFSET_RS(6));
+	    OUT_ACCEL_REG(R300_RS_INST_COUNT, R300_INST_COUNT_RS(0));
 
 	    OUT_ACCEL_REG(R300_US_PIXSIZE, 2); /* highest temp used */
 
@@ -1962,7 +1962,7 @@ FUNC_NAME(R300DisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
 			  ((2 << R300_RS_COUNT_IT_COUNT_SHIFT) |
 			   R300_RS_COUNT_HIRES_EN));
 	    /* R300_INST_COUNT_RS - highest RS instruction used */
-	    OUT_ACCEL_REG(R300_RS_INST_COUNT, R300_INST_COUNT_RS(0) | R300_TX_OFFSET_RS(6));
+	    OUT_ACCEL_REG(R300_RS_INST_COUNT, R300_INST_COUNT_RS(0));
 
 	    OUT_ACCEL_REG(R300_US_PIXSIZE, 1); /* highest temp used */
 
@@ -2688,7 +2688,7 @@ FUNC_NAME(R500DisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
 			   R300_RS_COUNT_HIRES_EN));
 
 	    /* R300_INST_COUNT_RS - highest RS instruction used */
-	    OUT_ACCEL_REG(R300_RS_INST_COUNT, R300_INST_COUNT_RS(1) | R300_TX_OFFSET_RS(6));
+	    OUT_ACCEL_REG(R300_RS_INST_COUNT, R300_INST_COUNT_RS(1));
 
 	    /* Pixel stack frame size. */
 	    OUT_ACCEL_REG(R300_US_PIXSIZE, 5);
@@ -3159,7 +3159,7 @@ FUNC_NAME(R500DisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
 			   R300_RS_COUNT_HIRES_EN));
 
 	    /* R300_INST_COUNT_RS - highest RS instruction used */
-	    OUT_ACCEL_REG(R300_RS_INST_COUNT, R300_INST_COUNT_RS(0) | R300_TX_OFFSET_RS(6));
+	    OUT_ACCEL_REG(R300_RS_INST_COUNT, R300_INST_COUNT_RS(0));
 
 	    /* Pixel stack frame size. */
 	    OUT_ACCEL_REG(R300_US_PIXSIZE, 0); /* highest temp used */
@@ -3323,7 +3323,7 @@ FUNC_NAME(R500DisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
 			   R300_RS_COUNT_HIRES_EN));
 
 	    /* R300_INST_COUNT_RS - highest RS instruction used */
-	    OUT_ACCEL_REG(R300_RS_INST_COUNT, R300_INST_COUNT_RS(0) | R300_TX_OFFSET_RS(6));
+	    OUT_ACCEL_REG(R300_RS_INST_COUNT, R300_INST_COUNT_RS(0));
 
 	    /* Pixel stack frame size. */
 	    OUT_ACCEL_REG(R300_US_PIXSIZE, 2); /* highest temp used */
@@ -3560,7 +3560,7 @@ FUNC_NAME(R500DisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
 			   R300_RS_COUNT_HIRES_EN));
 
 	    /* R300_INST_COUNT_RS - highest RS instruction used */
-	    OUT_ACCEL_REG(R300_RS_INST_COUNT, R300_INST_COUNT_RS(0) | R300_TX_OFFSET_RS(6));
+	    OUT_ACCEL_REG(R300_RS_INST_COUNT, R300_INST_COUNT_RS(0));
 
 	    /* Pixel stack frame size. */
 	    OUT_ACCEL_REG(R300_US_PIXSIZE, 1); /* highest temp used */
commit de17d36c1f710305870e3c636cae3f742f1cb6d6
Author: Alex Deucher <alexdeucher at gmail.com>
Date:   Thu Apr 30 19:13:09 2009 -0400

    AVIVO: first pass at display watermark setup
    
    This helps with flickering and blanking when
    there is contention for MC bandwidth.

diff --git a/src/atombios_crtc.c b/src/atombios_crtc.c
index 54c4578..f331800 100644
--- a/src/atombios_crtc.c
+++ b/src/atombios_crtc.c
@@ -675,9 +675,10 @@ RADEONInitDispBandwidthAVIVO(ScrnInfoPtr pScrn,
     unsigned char *RADEONMMIO = info->MMIO;
 
     uint32_t dc_lb_memory_split;
-    float mem_bw, peak_disp_bw;
-    float min_mem_eff = 0.8; /* XXX: taken from legacy method */
-    float pix_clk, pix_clk2; /* in MHz */
+    float available_bandwidth = 0;
+    float read_delay_latency = 1000;
+    int i;
+    Bool sideport = FALSE;
 
     /*
      * Set display0/1 priority up in the memory controller for
@@ -705,29 +706,6 @@ RADEONInitDispBandwidthAVIVO(ScrnInfoPtr pScrn,
 	    OUTMC(pScrn, RS690_MC_INIT_MISC_LAT_TIMER, mc_init_misc_lat_timer);
     }
 
-    /* XXX: fix me for AVIVO
-     * Determine if there is enough bandwidth for current display mode
-     */
-    mem_bw = info->mclk * (info->RamWidth / 8) * (info->IsDDR ? 2 : 1);
-
-    pix_clk = 0;
-    pix_clk2 = 0;
-    peak_disp_bw = 0;
-    if (mode1) {
-	pix_clk = mode1->Clock/1000.0;
-	peak_disp_bw += (pix_clk * pixel_bytes1);
-    }
-    if (mode2) {
-	pix_clk2 = mode2->Clock/1000.0;
-	peak_disp_bw += (pix_clk2 * pixel_bytes2);
-    }
-
-    if (peak_disp_bw >= mem_bw * min_mem_eff) {
-	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
-		   "You may not have enough display bandwidth for current mode\n"
-		   "If you have flickering problem, try to lower resolution, refresh rate, or color depth\n");
-    }
-
     /*
      * Line Buffer Setup
      * There is a single line buffer shared by both display controllers.
@@ -743,10 +721,8 @@ RADEONInitDispBandwidthAVIVO(ScrnInfoPtr pScrn,
      * 14:4; D2 allocation follows D1.
      */
 
-    /* is auto or manual better ? */
     dc_lb_memory_split = INREG(AVIVO_DC_LB_MEMORY_SPLIT) & ~AVIVO_DC_LB_MEMORY_SPLIT_MASK;
     dc_lb_memory_split &= ~AVIVO_DC_LB_MEMORY_SPLIT_SHIFT_MODE;
-#if 1
     /* auto */
     if (mode1 && mode2) {
 	if (mode1->HDisplay > mode2->HDisplay) {
@@ -766,7 +742,8 @@ RADEONInitDispBandwidthAVIVO(ScrnInfoPtr pScrn,
     } else if (mode2) {
 	dc_lb_memory_split |= AVIVO_DC_LB_MEMORY_SPLIT_D1_1Q_D2_3Q;
     }
-#else
+    OUTREG(AVIVO_DC_LB_MEMORY_SPLIT, dc_lb_memory_split);
+#if 0
     /* manual */
     dc_lb_memory_split |= AVIVO_DC_LB_MEMORY_SPLIT_SHIFT_MODE;
     dc_lb_memory_split &= ~(AVIVO_DC_LB_DISP1_END_ADR_MASK << AVIVO_DC_LB_DISP1_END_ADR_SHIFT);
@@ -779,11 +756,381 @@ RADEONInitDispBandwidthAVIVO(ScrnInfoPtr pScrn,
     OUTREG(AVIVO_DC_LB_MEMORY_SPLIT, dc_lb_memory_split);
 #endif
 
-    /*
-     * Watermark setup
-     * TODO...
-     * Unforunately, I haven't been able to dig up the avivo watermark programming
-     * guide yet. -AGD
+    // fixme
+    if (info->ChipFamily == CHIP_FAMILY_RS600)
+	return;
+
+    /* IGP bandwidth - get from integrated systems table
+     * SYSTEM_MEMORY_BANDWIDTH (Mbyte/s) = SYSTEM_MEMORY_CLOCK (MHz) * (1+DDR) * 8 * EFF * Num of channels
+     * SIDEPORT_MEMORY_BANDWIDTH = SIDEPORT_MEMORY_CLOCK * 2(byte) * 2(DDR) * 0.7(Eff)
+     * CORE_CLOCK_BANDWIDTH (Mbyte/s) = SCLK (MHz) * 16 / Dynamic Engine clock Divider
+     * HT_LINK_BANDWIDTH = HT_LINK_CLOCK * 2 * HT_LINK_WIDTH/8 * HT_LINK_EFF
+     * system read delay
+     * READ_DLY_MAX_LATENCY: 5000 ns
+     * sideport read delay
+     * READ_DLY_MAX_LATENCY: 370 * MCLK + 800 ns
+     * MCLK is the sideport memory clock period in ns (MCLK = 1000 / MCLKfreq MHz)
      */
 
+    if (info->IsIGP) {
+	float core_clock_bandwidth = ((float)info->pm.mode[info->pm.current_mode].sclk / 100) * 16 / 1;
+
+	if (sideport) {
+	    float sideport_memory_bandwidth = (info->igp_sideport_mclk / 2) * 2 * 2 * 0.7;
+	    float mclk = 1000 / info->igp_sideport_mclk;
+	    read_delay_latency = 370 * mclk * 800;
+	    available_bandwidth = MIN(sideport_memory_bandwidth, core_clock_bandwidth);
+	} else {
+	    float system_memory_bandwidth = (info->igp_system_mclk / 2) * (1 + 1) * 8 * 0.5 * 1;
+	    float ht_link_bandwidth = info->igp_ht_link_clk * 2 * (info->igp_ht_link_width / 8) * 0.8;
+	    read_delay_latency = 5000;
+	    available_bandwidth = MIN(system_memory_bandwidth, MIN(ht_link_bandwidth, core_clock_bandwidth));
+	}
+    }
+
+    /* calculate for each display */
+    for (i = 0; i < 2; i++) {
+	DisplayModePtr current = NULL;
+	//RADEONCrtcPrivatePtr radeon_crtc = pRADEONEnt->Controller[i];
+	float pclk, sclk, sclkfreq = 0;
+	float consumption_time, consumption_rate;
+	int num_line_pair, request_fifo_depth, lb_request_fifo_depth;
+	int max_req;
+	uint32_t lb_max_req_outstanding;
+	float line_time, active_time, chunk_time;
+	float worst_case_latency, tolerable_latency;
+	float fill_rate;
+	int priority_mark_max, priority_mark, priority_mark2;
+	int width, estimated_width;
+	/* FIXME: handle the scalers better */
+	Bool d1_scale_en = pRADEONEnt->Controller[0]->scaler_enabled;
+	Bool d2_scale_en = pRADEONEnt->Controller[1]->scaler_enabled;
+	float vtaps1 = 2; /* XXX */
+	float vsc1 = pRADEONEnt->Controller[0]->vsc;
+	float hsc1 = pRADEONEnt->Controller[0]->hsc;
+	float vtaps2 = 2; /* XXX */
+	float vsc2 = pRADEONEnt->Controller[1]->vsc;
+	float hsc2 = pRADEONEnt->Controller[1]->hsc;
+
+	if (i == 0)
+	    current = mode1;
+	else
+	    current = mode2;
+
+	if (current == NULL)
+	    continue;
+
+	/* Determine consumption rate
+	   pclk = pixel clock period(ns)
+	   vtaps = number of vertical taps,
+	   vsc = vertical scaling ratio, defined as source/destination
+	   hsc = horizontal scaling ration, defined as source/destination
+	*/
+
+	pclk = 1000 / ((float)current->Clock / 1000);
+
+	if (i == 0) {
+	    if (d1_scale_en)
+		consumption_time = pclk / ((MAX(vtaps1, vsc1) * hsc1) / vtaps1);
+	    else
+		consumption_time = pclk;
+	} else {
+	    if (d2_scale_en)
+		consumption_time = pclk / ((MAX(vtaps2, vsc2) * hsc2) / vtaps2);
+	    else
+		consumption_time = pclk;
+	}
+
+	consumption_rate = 1 / consumption_time;
+
+	/* Determine request line buffer fifo depth
+	   NumLinePair = Number of line pairs to request(1 = 2 lines, 2 = 4 lines)
+	   LBRequestFifoDepth = Number of chunk requests the LB can put into the request FIFO for a display
+	   width = viewport width in pixels
+	*/
+	if (i == 0) {
+	    if (vsc1 > 2)
+		num_line_pair = 2;
+	    else
+		num_line_pair = 1;
+	} else {
+	    if (vsc2 > 2)
+		num_line_pair = 2;
+	    else
+		num_line_pair = 1;
+	}
+
+	width = current->CrtcHDisplay;
+	request_fifo_depth = ceil(width/256) * num_line_pair;
+	if (request_fifo_depth < 4)
+	    lb_request_fifo_depth = 4;
+	else
+	    lb_request_fifo_depth = request_fifo_depth;
+
+	if (info->IsIGP) {
+	    if ((info->ChipFamily == CHIP_FAMILY_RS690) ||
+		(info->ChipFamily == CHIP_FAMILY_RS740))
+		OUTREG(RS690_DCP_CONTROL, 0);
+	    else if ((info->ChipFamily == CHIP_FAMILY_RS780) ||
+		     (info->ChipFamily == CHIP_FAMILY_RS880))
+		OUTREG(RS690_DCP_CONTROL, 2);
+	    max_req = lb_request_fifo_depth - 1;
+	} else
+	    max_req = lb_request_fifo_depth;
+
+	/*ErrorF("max_req %d: 0x%x\n", i, max_req);*/
+
+	lb_max_req_outstanding = INREG(AVIVO_LB_MAX_REQ_OUTSTANDING);
+	if (i == 0) {
+	    lb_max_req_outstanding &= ~(AVIVO_LB_D1_MAX_REQ_OUTSTANDING_MASK << AVIVO_LB_D1_MAX_REQ_OUTSTANDING_SHIFT);
+	    lb_max_req_outstanding |= (max_req & AVIVO_LB_D1_MAX_REQ_OUTSTANDING_MASK) << AVIVO_LB_D1_MAX_REQ_OUTSTANDING_SHIFT;
+	} else {
+	    lb_max_req_outstanding &= ~(AVIVO_LB_D2_MAX_REQ_OUTSTANDING_MASK << AVIVO_LB_D2_MAX_REQ_OUTSTANDING_SHIFT);
+	    lb_max_req_outstanding |= (max_req & AVIVO_LB_D2_MAX_REQ_OUTSTANDING_MASK) << AVIVO_LB_D2_MAX_REQ_OUTSTANDING_SHIFT;
+	}
+	OUTREG(AVIVO_LB_MAX_REQ_OUTSTANDING, lb_max_req_outstanding);
+
+	/* Determine line time
+	   LineTime = total time for one line of displayhtotal = total number of horizontal pixels
+	   pclk = pixel clock period(ns)
+	*/
+	line_time = current->CrtcHTotal * pclk;
+
+	/* Determine active time
+	   ActiveTime = time of active region of display within one line,
+	   hactive = total number of horizontal active pixels
+	   htotal = total number of horizontal pixels
+	*/
+	active_time = line_time * current->CrtcHDisplay / current->CrtcHTotal;
+
+	/* Determine chunk time
+	   ChunkTime = the time it takes the DCP to send one chunk of data
+	   to the LB which consists of pipeline delay and inter chunk gap
+	   sclk = system clock(ns)
+	*/
+	if (info->IsIGP) {
+	    sclk = 1000 / (available_bandwidth / 16);
+	    /* Sclkfreq = sclk in MHz = 1000/sclk (because sclk is in ns). */
+	    sclkfreq = 1000 / sclk;
+	    chunk_time = sclk * 256 * 1.3;
+	} else {
+	    sclk = 1000 / ((float)info->pm.mode[info->pm.current_mode].sclk / 100);
+	    chunk_time = sclk * 600;
+	}
+
+	/* Determine the worst case latency
+	   NumLinePair = Number of line pairs to request(1 = 2 lines, 2 = 4 lines)
+	   WorstCaseLatency = The worst case time from urgent to when the MC starts
+	   to return data
+	   READ_DELAY_IDLE_MAX = constant of 1us
+	   ChunkTime = the time it takes the DCP to send one chunk of data to the LB
+	   which consists of pipeline delay and
+	   inter chunk gap
+	*/
+	if (info->IsIGP) {
+	    if (num_line_pair > 1)
+		worst_case_latency = read_delay_latency + 3 * chunk_time;
+	    else
+		worst_case_latency = read_delay_latency + 2 * chunk_time;
+	} else {
+	    if (num_line_pair > 1)
+		worst_case_latency = read_delay_latency + 3 * chunk_time;
+	    else
+		worst_case_latency = read_delay_latency + chunk_time;
+	}
+
+	/* Determine the tolerable latency
+	   TolerableLatency = Any given request has only 1 line time for the data to be returned
+	   LBRequestFifoDepth = Number of chunk requests the LB can put into the request FIFO for a display
+	   LineTime = total time for one line of display
+	   ChunkTime = the time it takes the DCP to send one chunk of data to the LB which consists of
+	   pipeline delay and inter chunk gap
+	*/
+	if ((2 + lb_request_fifo_depth) >= request_fifo_depth)
+	    tolerable_latency = line_time;
+	else
+	    tolerable_latency = line_time - (request_fifo_depth - lb_request_fifo_depth - 2) * chunk_time;
+
+	if (mode1 && mode2) {
+	    int d1bpp, d2bpp;
+	    int d1_graph_enable = 1;
+	    int d2_graph_enable = 1;
+	    int d1_ovl_enable = 0;
+	    int d2_ovl_enable = 0;
+	    int d1grph_depth, d2grph_depth;
+	    int d1ovl_depth = 0;
+	    int d2ovl_depth = 0;
+	    int d1_num_line_pair, d2_num_line_pair;
+	    float d1_fill_rate_coeff, d2_fill_rate_coeff;
+
+	    switch (pixel_bytes1) {
+	    case 2:
+		d1grph_depth = 1;
+		break;
+	    case 4:
+		d1grph_depth = 2;
+		break;
+	    default:
+		d1grph_depth = 0;
+		break;
+	    }
+
+	    switch (pixel_bytes2) {
+	    case 2:
+		d2grph_depth = 1;
+		break;
+	    case 4:
+		d2grph_depth = 2;
+		break;
+	    default:
+		d2grph_depth = 0;
+		break;
+	    }
+
+	    /* If both displays are active, determine line buffer fill rate */
+	    if (d1_scale_en && (vsc1 > 2))
+		d1_num_line_pair = 2;
+	    else
+		d1_num_line_pair = 1;
+
+	    if (d2_scale_en && (vsc2 > 2))
+		d2_num_line_pair = 2;
+	    else
+		d2_num_line_pair = 1;
+
+	    if (info->IsIGP) {
+		d1bpp = (d1_graph_enable * pow(2, d1grph_depth) * 8) + (d1_ovl_enable * pow(2, d1ovl_depth) * 8);
+		d2bpp = (d2_graph_enable * pow(2, d2grph_depth) * 8) + (d2_ovl_enable * pow(2, d2ovl_depth) * 8);
+
+		if (d1bpp > 64)
+		    d1_fill_rate_coeff = d1bpp * d1_num_line_pair;
+		else
+		    d1_fill_rate_coeff = d1_num_line_pair;
+
+		if (d2bpp > 64)
+		    d2_fill_rate_coeff = d2bpp * d2_num_line_pair;
+		else
+		    d2_fill_rate_coeff = d2_num_line_pair;
+
+		fill_rate = sclkfreq / (d1_fill_rate_coeff + d2_fill_rate_coeff);
+	    } else {
+		d1bpp = (d1grph_depth + d1ovl_depth) * 16;
+		d2bpp = (d2grph_depth + d2ovl_depth) * 16;
+
+		if (d1bpp > 64)
+		    d1_fill_rate_coeff = d1bpp / d1_num_line_pair;
+		else
+		    d1_fill_rate_coeff = d1_num_line_pair;
+
+		if (d2bpp > 64)
+		    d2_fill_rate_coeff = d2bpp / d2_num_line_pair;
+		else
+		    d2_fill_rate_coeff = d2_num_line_pair;
+
+		fill_rate = sclk / (d1_fill_rate_coeff + d2_fill_rate_coeff);
+
+		/* Convert line buffer fill rate from period to frequency */
+		fill_rate = 1 / fill_rate;
+	    }
+	} else {
+	    int dxbpp;
+	    int dx_grph_enable = 1;
+	    int dx_ovl_enable = 0;
+	    int dxgrph_depth;
+	    int dxovl_depth = 0;
+	    int cpp;
+
+	    if (i == 0)
+		cpp = pixel_bytes1;
+	    else
+		cpp = pixel_bytes2;
+
+	    switch (cpp) {
+	    case 2:
+		dxgrph_depth = 1;
+		break;
+	    case 4:
+		dxgrph_depth = 2;
+		break;
+	    default:
+		dxgrph_depth = 0;
+		break;
+	    }
+
+	    /* If only one display active, the line buffer fill rate becomes */
+	    if (info->IsIGP) {
+		dxbpp = (dx_grph_enable * pow(2, dxgrph_depth) * 8) + (dx_ovl_enable * pow(2, dxovl_depth) * 8);
+		if (dxbpp > 64)
+		    fill_rate = sclkfreq / dxbpp / num_line_pair;
+		else
+		    fill_rate = sclkfreq / num_line_pair;
+	    } else {
+		dxbpp = (dxgrph_depth + dxovl_depth) * 16;
+
+		if (dxbpp > 64)
+		    fill_rate = sclk / dxbpp / num_line_pair;
+		else
+		    fill_rate = sclk / num_line_pair;
+
+		/* Convert line buffer fill rate from period to frequency */
+		fill_rate = 1 / fill_rate;
+	    }
+	}
+
+	/* Determine the maximum priority mark
+	   width = viewport width in pixels
+	*/
+	priority_mark_max = ceil(width/16);
+
+	/* Determine estimated width */
+	estimated_width = (tolerable_latency - worst_case_latency) / consumption_time;
+
+	/* Determine priority mark based on active time */
+	if (info->IsIGP) {
+	    if (estimated_width > width)
+		priority_mark = 10;
+	    else
+		priority_mark = priority_mark_max - ceil(estimated_width / 16);
+	} else {
+	    if (estimated_width > width)
+		priority_mark = priority_mark_max;
+	    else
+		priority_mark = priority_mark_max - ceil(estimated_width / 16);
+	}
+
+	/* Determine priority mark 2 based on worst case latency,
+	   consumption rate, fill rate and active time
+	*/
+	if (info->IsIGP) {
+	    if (consumption_rate > fill_rate)
+		priority_mark2 = ceil((worst_case_latency * consumption_rate + (consumption_rate - fill_rate) * active_time) / 1000 / 16);
+	    else
+		priority_mark2 = ceil(worst_case_latency * consumption_rate / 1000 / 16);
+	} else {
+	    if (consumption_rate > fill_rate)
+		priority_mark2 = ceil(worst_case_latency * consumption_rate + (consumption_rate - fill_rate) * active_time / 16);
+	    else
+		priority_mark2 = ceil(worst_case_latency * consumption_rate / 16);
+	}
+
+	/* Determine final priority mark and clamp if necessary */
+	priority_mark = max(priority_mark, priority_mark2);
+	if (priority_mark < 0)
+	    priority_mark = 0;
+	else if (priority_mark > priority_mark_max)
+	    priority_mark = priority_mark_max;
+
+	/*ErrorF("priority_mark %d: 0x%x\n", i, priority_mark);*/
+
+	/* Determine which display to program priority mark for */
+	/* FIXME: program DxMODE_PRIORITY_B_CNT for slower sclk */
+	if (i == 0) {
+	    OUTREG(AVIVO_D1MODE_PRIORITY_A_CNT, (priority_mark & AVIVO_DxMODE_PRIORITY_MARK_MASK));
+	    OUTREG(AVIVO_D1MODE_PRIORITY_B_CNT, (priority_mark & AVIVO_DxMODE_PRIORITY_MARK_MASK));
+	} else {
+	    OUTREG(AVIVO_D2MODE_PRIORITY_A_CNT, (priority_mark & AVIVO_DxMODE_PRIORITY_MARK_MASK));
+	    OUTREG(AVIVO_D2MODE_PRIORITY_B_CNT, (priority_mark & AVIVO_DxMODE_PRIORITY_MARK_MASK));
+	}
+    }
+
 }
diff --git a/src/radeon.h b/src/radeon.h
index 706f26e..9ce251a 100644
--- a/src/radeon.h
+++ b/src/radeon.h
@@ -929,6 +929,12 @@ typedef struct {
     /* pm */
     RADEONPowerManagement pm;
 
+    /* igp info */
+    float igp_sideport_mclk;
+    float igp_system_mclk;
+    float igp_ht_link_clk;
+    float igp_ht_link_width;
+
 } RADEONInfoRec, *RADEONInfoPtr;
 
 #define RADEONWaitForFifo(pScrn, entries)				\
diff --git a/src/radeon_atombios.c b/src/radeon_atombios.c
index 389b145..110a7cc 100644
--- a/src/radeon_atombios.c
+++ b/src/radeon_atombios.c
@@ -2027,6 +2027,35 @@ RADEONGetATOMLVDSInfo(ScrnInfoPtr pScrn, radeon_lvds_ptr lvds)
 	       native_mode->VBlank, native_mode->VOverPlus, native_mode->VSyncWidth);
 }
 
+void
+RADEONATOMGetIGPInfo(ScrnInfoPtr pScrn)
+{
+    RADEONInfoPtr  info       = RADEONPTR(pScrn);
+    atomDataTablesPtr atomDataPtr;
+    unsigned short size;
+    uint8_t crev, frev;
+
+    atomDataPtr = info->atomBIOS->atomDataPtr;
+
+    if (!rhdAtomGetTableRevisionAndSize((ATOM_COMMON_TABLE_HEADER *)(atomDataPtr->IntegratedSystemInfo.base), &frev, &crev, &size))
+	return;
+
+    switch (crev) {
+    case 1:
+	info->igp_sideport_mclk = atomDataPtr->IntegratedSystemInfo.IntegratedSystemInfo->ulBootUpMemoryClock / 100.0;
+	info->igp_system_mclk = le16_to_cpu(atomDataPtr->IntegratedSystemInfo.IntegratedSystemInfo->usK8MemoryClock);
+	info->igp_ht_link_clk = le16_to_cpu(atomDataPtr->IntegratedSystemInfo.IntegratedSystemInfo->usFSBClock);
+	info->igp_ht_link_width = atomDataPtr->IntegratedSystemInfo.IntegratedSystemInfo->ucHTLinkWidth;
+	break;
+    case 2:
+	info->igp_sideport_mclk = atomDataPtr->IntegratedSystemInfo.IntegratedSystemInfo_v2->ulBootUpSidePortClock / 100.0;
+	info->igp_system_mclk = atomDataPtr->IntegratedSystemInfo.IntegratedSystemInfo_v2->ulBootUpUMAClock / 100.0;
+	info->igp_ht_link_clk = atomDataPtr->IntegratedSystemInfo.IntegratedSystemInfo_v2->ulHTLinkFreq / 100.0;
+	info->igp_ht_link_width = le16_to_cpu(atomDataPtr->IntegratedSystemInfo.IntegratedSystemInfo_v2->usMinHTLinkWidth);
+	break;
+    }
+}
+
 Bool
 RADEONGetATOMTVInfo(xf86OutputPtr output)
 {
diff --git a/src/radeon_atombios.h b/src/radeon_atombios.h
index b81cbbb..81e5a33 100644
--- a/src/radeon_atombios.h
+++ b/src/radeon_atombios.h
@@ -272,6 +272,9 @@ typedef struct _atomBiosHandle {
 extern Bool
 RADEONATOMGetTVTimings(ScrnInfoPtr pScrn, int index, SET_CRTC_TIMING_PARAMETERS_PS_ALLOCATION *crtc_timing, int32_t *pixel_clock);
 
+extern void
+RADEONATOMGetIGPInfo(ScrnInfoPtr pScrn);
+
 extern uint32_t
 radeon_get_device_index(uint32_t device_support);
 extern radeon_encoder_ptr
diff --git a/src/radeon_driver.c b/src/radeon_driver.c
index 9cbfd0d..a56df49 100644
--- a/src/radeon_driver.c
+++ b/src/radeon_driver.c
@@ -2723,12 +2723,15 @@ static Bool RADEONPreInitControllers(ScrnInfoPtr pScrn)
 	mask = 1;
     else
 	mask = 2;
-	
+
     if (!RADEONAllocateControllers(pScrn, mask))
 	return FALSE;
 
     RADEONGetClockInfo(pScrn);
 
+    if (info->IsAtomBios && info->IsIGP)
+	RADEONATOMGetIGPInfo(pScrn);
+
     if (!RADEONSetupConnectors(pScrn)) {
 	return FALSE;
     }
@@ -2737,7 +2740,7 @@ static Bool RADEONPreInitControllers(ScrnInfoPtr pScrn)
 	/* fixup outputs for zaphod */
 	RADEONFixZaphodOutputs(pScrn);
     }
-      
+
     RADEONPrintPortMap(pScrn);
 
     info->first_load_no_devices = FALSE;
@@ -3037,8 +3040,6 @@ Bool RADEONPreInit(ScrnInfoPtr pScrn, int flags)
 	}
     }
 
-    ErrorF("after xf86InitialConfiguration\n");
-
     RADEONSetPitch(pScrn);
 
    /* Set display resolution */
diff --git a/src/radeon_output.c b/src/radeon_output.c
index 67d94fe..634fd65 100644
--- a/src/radeon_output.c
+++ b/src/radeon_output.c
@@ -430,8 +430,11 @@ radeon_mode_fixup(xf86OutputPtr output, DisplayModePtr mode,
     RADEONInfoPtr info = RADEONPTR(output->scrn);
     RADEONOutputPrivatePtr radeon_output = output->driver_private;
     radeon_native_mode_ptr native_mode = &radeon_output->native_mode;
+    xf86CrtcPtr crtc = output->crtc;
+    RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private;
 
     radeon_output->Flags &= ~RADEON_USE_RMX;
+    radeon_crtc->scaler_enabled = FALSE;
 
     /*
      *  Refresh the Crtc values without INTERLACE_HALVE_V
@@ -442,14 +445,15 @@ radeon_mode_fixup(xf86OutputPtr output, DisplayModePtr mode,
     /* decide if we are using RMX */
     if ((radeon_output->active_device & (ATOM_DEVICE_LCD_SUPPORT | ATOM_DEVICE_DFP_SUPPORT))
 	&& radeon_output->rmx_type != RMX_OFF) {
-	xf86CrtcPtr crtc = output->crtc;
-	RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private;
 
 	if (IS_AVIVO_VARIANT || radeon_crtc->crtc_id == 0) {
 	    if (mode->HDisplay < native_mode->PanelXRes ||
 		mode->VDisplay < native_mode->PanelYRes) {
 		radeon_output->Flags |= RADEON_USE_RMX;
+		radeon_crtc->scaler_enabled = TRUE;
 		if (IS_AVIVO_VARIANT) {
+		    radeon_crtc->hsc = (float)mode->HDisplay / (float)native_mode->PanelXRes;
+		    radeon_crtc->vsc = (float)mode->VDisplay / (float)native_mode->PanelYRes;
 		    /* set to the panel's native mode */
 		    adjusted_mode->HDisplay = native_mode->PanelXRes;
 		    adjusted_mode->VDisplay = native_mode->PanelYRes;
@@ -495,6 +499,13 @@ radeon_mode_fixup(xf86OutputPtr output, DisplayModePtr mode,
 	}
     }
 
+    /* FIXME: vsc/hsc */
+    if (radeon_output->active_device & (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT)) {
+	radeon_crtc->scaler_enabled = TRUE;
+	radeon_crtc->hsc = (float)mode->HDisplay / (float)640;
+	radeon_crtc->vsc = (float)mode->VDisplay / (float)480;
+    }
+
     if (IS_AVIVO_VARIANT) {
 	/* hw bug */
 	if ((mode->Flags & V_INTERLACE)
diff --git a/src/radeon_probe.h b/src/radeon_probe.h
index dbccd85..8e902e3 100644
--- a/src/radeon_probe.h
+++ b/src/radeon_probe.h
@@ -160,6 +160,9 @@ typedef struct _RADEONCrtcPrivateRec {
     Bool enabled;
     Bool initialized;
     Bool cursor_enabled;
+    Bool scaler_enabled;
+    float vsc;
+    float hsc;
 } RADEONCrtcPrivateRec, *RADEONCrtcPrivatePtr;
 
 typedef struct _radeon_encoder {
diff --git a/src/radeon_reg.h b/src/radeon_reg.h
index 85923d1..d230a20 100644
--- a/src/radeon_reg.h
+++ b/src/radeon_reg.h
@@ -3730,6 +3730,19 @@
 #       define AVIVO_DC_LB_MEMORY_SPLIT_SHIFT_MODE (1 << 2)
 #       define AVIVO_DC_LB_DISP1_END_ADR_SHIFT  4
 #       define AVIVO_DC_LB_DISP1_END_ADR_MASK   0x7ff
+#define AVIVO_D1MODE_PRIORITY_A_CNT             0x6548
+#       define AVIVO_DxMODE_PRIORITY_MARK_MASK  0x7fff
+#       define AVIVO_DxMODE_PRIORITY_OFF        (1 << 16)
+#       define AVIVO_DxMODE_PRIORITY_ALWAYS_ON  (1 << 20)
+#       define AVIVO_DxMODE_PRIORITY_FORCE_MASK (1 << 24)
+#define AVIVO_D1MODE_PRIORITY_B_CNT             0x654c
+#define AVIVO_D2MODE_PRIORITY_A_CNT             0x6d48
+#define AVIVO_D2MODE_PRIORITY_B_CNT             0x6d4c
+#define AVIVO_LB_MAX_REQ_OUTSTANDING            0x6d58
+#       define AVIVO_LB_D1_MAX_REQ_OUTSTANDING_MASK    0xf
+#       define AVIVO_LB_D1_MAX_REQ_OUTSTANDING_SHIFT   0
+#       define AVIVO_LB_D2_MAX_REQ_OUTSTANDING_MASK    0xf
+#       define AVIVO_LB_D2_MAX_REQ_OUTSTANDING_SHIFT   16
 
 #define AVIVO_D1MODE_DATA_FORMAT                0x6528
 #       define AVIVO_D1MODE_INTERLEAVE_EN       (1 << 0)
@@ -3791,6 +3804,8 @@
 #define AVIVO_D2CUR_SIZE                        0x6c10
 #define AVIVO_D2CUR_POSITION                    0x6c14
 
+#define RS690_DCP_CONTROL                       0x6c9c
+
 #define AVIVO_D2MODE_DATA_FORMAT                0x6d28
 #define AVIVO_D2MODE_DESKTOP_HEIGHT             0x6d2c
 #define AVIVO_D2MODE_VIEWPORT_START             0x6d80


More information about the xorg-commit mailing list