radeon: fix computing difference

Also fix clang warning self-assign.

Pointed by clang.

Change-Id: I0e104420414fecece87015a0af9a4535ccfc8263
Reviewed-on: https://review.haiku-os.org/c/haiku/+/2401
Reviewed-by: waddlesplash <[email protected]>
This commit is contained in:
X512
2020-03-23 01:30:23 +00:00
committed by waddlesplash
parent 39be4f89f5
commit fc179324b0
2 changed files with 202 additions and 202 deletions
+97 -97
View File
@@ -3,7 +3,7 @@
Part of Radeon accelerant
Public functions to provide 2D hardware acceleration
*/
@@ -22,12 +22,12 @@
// et - ignored
// list - list of rectangles
// count - number of rectangles
void SCREEN_TO_SCREEN_BLIT_DMA(engine_token *et, blit_params *list, uint32 count)
void SCREEN_TO_SCREEN_BLIT_DMA(engine_token *et, blit_params *list, uint32 count)
{
virtual_card *vc = ai->vc;
SHOW_FLOW0( 4, "" );
(void)et;
while( count > 0 ) {
@@ -35,15 +35,15 @@ void SCREEN_TO_SCREEN_BLIT_DMA(engine_token *et, blit_params *list, uint32 count
START_IB();
WRITE_IB_PACKET3_HEAD( RADEON_CP_PACKET3_CNTL_BITBLT_MULTI, count,
WRITE_IB_PACKET3_HEAD( RADEON_CP_PACKET3_CNTL_BITBLT_MULTI, count,
INDIRECT_BUFFER_SIZE, 3, 2 );
*buffer++ = RADEON_GMC_BRUSH_NONE
| (vc->datatype << RADEON_GMC_DST_DATATYPE_SHIFT)
| RADEON_GMC_SRC_DATATYPE_COLOR
| RADEON_ROP3_S
| RADEON_DP_SRC_SOURCE_MEMORY;
for( ; sub_count > 0; --sub_count, ++list ) {
*buffer++ = (list->src_left << 16) | list->src_top;
*buffer++ = (list->dest_left << 16) | list->dest_top;
@@ -52,7 +52,7 @@ void SCREEN_TO_SCREEN_BLIT_DMA(engine_token *et, blit_params *list, uint32 count
SUBMIT_IB_VC();
}
++ai->si->engine.count;
}
@@ -64,9 +64,9 @@ void SCREEN_TO_SCREEN_BLIT_PIO(engine_token *et, blit_params *list, uint32 count
int xdir;
int ydir;
virtual_card *vc = ai->vc;
SHOW_FLOW0( 4, "" );
Radeon_WaitForFifo ( ai , 1 );
// Setup for Screen to screen blit
@@ -76,33 +76,33 @@ void SCREEN_TO_SCREEN_BLIT_PIO(engine_token *et, blit_params *list, uint32 count
| RADEON_ROP3_S
| RADEON_DP_SRC_SOURCE_MEMORY
| RADEON_GMC_SRC_PITCH_OFFSET_CNTL));
for( ; count > 0; --count, ++list ) {
// make sure there is space in the FIFO for 4 register writes
Radeon_WaitForFifo ( ai , 4 );
xdir = ((list->src_left < list->dest_left) && (list->src_top == list->dest_top)) ? -1 : 1;
ydir = (list->src_top < list->dest_top) ? -1 : 1;
if (xdir < 0) list->src_left += list->width , list->dest_left += list->width ;
if (ydir < 0) list->src_top += list->height , list->dest_top += list->height ;
OUTREG(ai->regs, RADEON_DP_CNTL, ((xdir >= 0 ? RADEON_DST_X_LEFT_TO_RIGHT : 0)
OUTREG(ai->regs, RADEON_DP_CNTL, ((xdir >= 0 ? RADEON_DST_X_LEFT_TO_RIGHT : 0)
| (ydir >= 0 ? RADEON_DST_Y_TOP_TO_BOTTOM : 0)));
// Tell the engine where the source data resides.
OUTREG( ai->regs, RADEON_SRC_Y_X, (list->src_top << 16 ) | list->src_left);
OUTREG( ai->regs, RADEON_DST_Y_X, (list->dest_top << 16 ) | list->dest_left);
// this is the blt initiator.
OUTREG( ai->regs, RADEON_DST_HEIGHT_WIDTH, ((list->height + 1) << 16 ) | (list->width + 1));
}
++ai->si->engine.count;
et = et;
(void)et;
}
@@ -112,21 +112,21 @@ void SCREEN_TO_SCREEN_BLIT_PIO(engine_token *et, blit_params *list, uint32 count
// colorIndex - fill colour
// list - list of rectangles
// count - number of rectangles
void FILL_RECTANGLE_DMA(engine_token *et, uint32 colorIndex,
fill_rect_params *list, uint32 count)
void FILL_RECTANGLE_DMA(engine_token *et, uint32 colorIndex,
fill_rect_params *list, uint32 count)
{
virtual_card *vc = ai->vc;
SHOW_FLOW0( 4, "" );
(void)et;
while( count > 0 ) {
uint32 sub_count;
START_IB();
WRITE_IB_PACKET3_HEAD( RADEON_CP_PACKET3_CNTL_PAINT_MULTI, count,
WRITE_IB_PACKET3_HEAD( RADEON_CP_PACKET3_CNTL_PAINT_MULTI, count,
INDIRECT_BUFFER_SIZE, 2, 3 );
*buffer++ = RADEON_GMC_BRUSH_SOLID_COLOR
@@ -137,11 +137,11 @@ void FILL_RECTANGLE_DMA(engine_token *et, uint32 colorIndex,
for( ; sub_count > 0; --sub_count, ++list ) {
*buffer++ = (list->left << 16) | list->top;
*buffer++ =
((list->right - list->left + 1) << 16) |
*buffer++ =
((list->right - list->left + 1) << 16) |
(list->bottom - list->top + 1);
}
SUBMIT_IB_VC();
}
@@ -156,31 +156,31 @@ void FILL_RECTANGLE_DMA(engine_token *et, uint32 colorIndex,
// count - number of rectangles
#define BRUSH_SOLIDCOLOR 0x00000d00
void FILL_RECTANGLE_PIO(engine_token *et, uint32 colorIndex, fill_rect_params *list, uint32 count)
void FILL_RECTANGLE_PIO(engine_token *et, uint32 colorIndex, fill_rect_params *list, uint32 count)
{
virtual_card *vc = ai->vc;
SHOW_FLOW( 4, "colorIndex", colorIndex);
Radeon_WaitForFifo(ai, 3);
OUTREG(ai->regs, RADEON_DP_GUI_MASTER_CNTL, ((vc->datatype << RADEON_GMC_DST_DATATYPE_SHIFT)
| RADEON_GMC_BRUSH_SOLID_COLOR
| RADEON_GMC_SRC_DATATYPE_COLOR
| RADEON_ROP3_P));
// Set brush colour
// Set brush colour
OUTREG(ai->regs, RADEON_DP_BRUSH_FRGD_CLR, colorIndex);
OUTREG(ai->regs, RADEON_DP_CNTL, (RADEON_DST_X_LEFT_TO_RIGHT | RADEON_DST_Y_TOP_TO_BOTTOM));
for( ; count > 0; --count, ++list )
for( ; count > 0; --count, ++list )
{
Radeon_WaitForFifo(ai, 2);
OUTREG(ai->regs, RADEON_DST_Y_X, (list->top << 16) | list->left);
OUTREG(ai->regs, RADEON_DST_WIDTH_HEIGHT, ((list->right - list->left + 1) << 16) | (list->bottom - list->top + 1));
}
++ai->si->engine.count;
et = et;
(void)et;
}
@@ -189,23 +189,23 @@ void FILL_RECTANGLE_PIO(engine_token *et, uint32 colorIndex, fill_rect_params *l
// et - ignored
// list - list of rectangles
// count - number of rectangles
void INVERT_RECTANGLE_DMA(engine_token *et, fill_rect_params *list, uint32 count)
void INVERT_RECTANGLE_DMA(engine_token *et, fill_rect_params *list, uint32 count)
{
virtual_card *vc = ai->vc;
SHOW_FLOW0( 4, "" );
(void)et;
while( count > 0 ) {
uint32 sub_count;
START_IB();
// take core to leave space for ROP reset!
WRITE_IB_PACKET3_HEAD( RADEON_CP_PACKET3_CNTL_PAINT_MULTI, count,
WRITE_IB_PACKET3_HEAD( RADEON_CP_PACKET3_CNTL_PAINT_MULTI, count,
INDIRECT_BUFFER_SIZE - 2, 2, 2 );
*buffer++ = RADEON_GMC_BRUSH_NONE
| (vc->datatype << RADEON_GMC_DST_DATATYPE_SHIFT)
| RADEON_GMC_SRC_DATATYPE_COLOR
@@ -213,11 +213,11 @@ void INVERT_RECTANGLE_DMA(engine_token *et, fill_rect_params *list, uint32 count
for( ; sub_count > 0; --sub_count, ++list ) {
*buffer++ = (list->left << 16) | list->top;
*buffer++ =
((list->right - list->left + 1) << 16) |
*buffer++ =
((list->right - list->left + 1) << 16) |
(list->bottom - list->top + 1);
}
// we have to reset ROP, else we get garbage during next
// CPU access; it looks like some cache coherency/forwarding
// problem as it goes away later on; things like flushing the
@@ -239,12 +239,12 @@ void INVERT_RECTANGLE_DMA(engine_token *et, fill_rect_params *list, uint32 count
}
void INVERT_RECTANGLE_PIO(engine_token *et, fill_rect_params *list, uint32 count)
void INVERT_RECTANGLE_PIO(engine_token *et, fill_rect_params *list, uint32 count)
{
virtual_card *vc = ai->vc;
SHOW_FLOW0( 4, "" );
Radeon_WaitForFifo(ai, 3);
OUTREG(ai->regs, RADEON_DP_GUI_MASTER_CNTL, ((vc->datatype << RADEON_GMC_DST_DATATYPE_SHIFT)
| RADEON_GMC_BRUSH_NONE
@@ -254,17 +254,17 @@ void INVERT_RECTANGLE_PIO(engine_token *et, fill_rect_params *list, uint32 count
OUTREG(ai->regs, RADEON_DP_CNTL, (RADEON_DST_X_LEFT_TO_RIGHT | RADEON_DST_Y_TOP_TO_BOTTOM));
for( ; count > 0; --count, ++list )
for( ; count > 0; --count, ++list )
{
Radeon_WaitForFifo(ai, 2);
OUTREG(ai->regs, RADEON_DST_Y_X, (list->top << 16) | list->left);
OUTREG(ai->regs, RADEON_DST_WIDTH_HEIGHT, ((list->right - list->left + 1) << 16) | (list->bottom - list->top + 1));
}
++ai->si->engine.count;
et = et;
(void)et;
}
// fill horizontal spans on screen
@@ -272,39 +272,39 @@ void INVERT_RECTANGLE_PIO(engine_token *et, fill_rect_params *list, uint32 count
// colorIndex - fill colour
// list - list of spans
// count - number of spans
void FILL_SPAN_DMA(engine_token *et, uint32 colorIndex, uint16 *list, uint32 count)
void FILL_SPAN_DMA(engine_token *et, uint32 colorIndex, uint16 *list, uint32 count)
{
virtual_card *vc = ai->vc;
SHOW_FLOW0( 4, "" );
(void)et;
while( count > 0 ) {
uint32 sub_count;
START_IB();
WRITE_IB_PACKET3_HEAD( RADEON_CP_PACKET3_CNTL_PAINT_MULTI, count,
WRITE_IB_PACKET3_HEAD( RADEON_CP_PACKET3_CNTL_PAINT_MULTI, count,
INDIRECT_BUFFER_SIZE , 2, 3 );
*buffer++ = RADEON_GMC_BRUSH_SOLID_COLOR
| (vc->datatype << RADEON_GMC_DST_DATATYPE_SHIFT)
| RADEON_GMC_SRC_DATATYPE_COLOR
| RADEON_ROP3_P;
*buffer++ = colorIndex;
for( ; sub_count > 0; --sub_count ) {
uint16 y, x, width;
y = *list++;
x = *list++;
width = *list++ - x + 1;
*buffer++ = (x << 16) | y;
*buffer++ = (width << 16) | 1;
}
SUBMIT_IB_VC();
}
@@ -317,45 +317,45 @@ void FILL_SPAN_DMA(engine_token *et, uint32 colorIndex, uint16 *list, uint32 cou
// colorIndex - fill colour
// list - list of spans
// count - number of spans
void FILL_SPAN_PIO(engine_token *et, uint32 colorIndex, uint16 *list, uint32 count)
void FILL_SPAN_PIO(engine_token *et, uint32 colorIndex, uint16 *list, uint32 count)
{
virtual_card *vc = ai->vc;
//int offset = 0;
uint16 y, x, width;
SHOW_FLOW0( 4, "" );
Radeon_WaitForFifo( ai , 1);
OUTREG( ai->regs, RADEON_DP_GUI_MASTER_CNTL, 0
| RADEON_GMC_BRUSH_SOLID_COLOR
| (vc->datatype << RADEON_GMC_DST_DATATYPE_SHIFT)
| RADEON_GMC_SRC_DATATYPE_COLOR
| RADEON_ROP3_P);
if ( ai->si->asic >= rt_rv200 ) {
Radeon_WaitForFifo( ai , 1);
OUTREG( ai->regs, RADEON_DST_LINE_PATCOUNT, 0x55 << RADEON_BRES_CNTL_SHIFT);
}
Radeon_WaitForFifo( ai , 1);
OUTREG( ai->regs, RADEON_DP_BRUSH_FRGD_CLR, colorIndex);
OUTREG( ai->regs, RADEON_DP_BRUSH_FRGD_CLR, colorIndex);
for( ; count > 0; --count ) {
Radeon_WaitForFifo( ai , 2);
y = *list++;
x = *list++;
width = *list++ - x + 1;
OUTREG( ai->regs, RADEON_DST_LINE_START, (y << 16) | x);
OUTREG( ai->regs, RADEON_DST_LINE_END, ((y) << 16) | (x + width));
}
++ai->si->engine.count;
et = et;
(void)et;
}
@@ -398,7 +398,7 @@ void Radeon_Init2D( accelerator_info *ai )
{
SHOW_FLOW0( 3, "" );
// forget about 3D
// forget about 3D
if ( ai->si->acc_dma ) {
START_IB();
WRITE_IB_REG( RADEON_RB3D_CNTL, 0 );
@@ -415,38 +415,38 @@ void Radeon_FillStateBuffer( accelerator_info *ai, uint32 datatype )
virtual_card *vc = ai->vc;
uint32 pitch_offset;
uint32 *buffer = NULL, *buffer_start = NULL;
SHOW_FLOW0( 4, "" );
// set offset of frame buffer and pitch
pitch_offset =
((ai->si->memory[mt_local].virtual_addr_start + vc->fb_offset) >> 10) |
pitch_offset =
((ai->si->memory[mt_local].virtual_addr_start + vc->fb_offset) >> 10) |
((vc->pitch >> 6) << 22);
if ( ai->si->acc_dma ) {
// make sure buffer is not used
Radeon_InvalidateStateBuffer( ai, vc->state_buffer_idx );
buffer = buffer_start = Radeon_GetIndirectBufferPtr( ai, vc->state_buffer_idx );
WRITE_IB_REG( RADEON_DEFAULT_OFFSET, pitch_offset );
WRITE_IB_REG( RADEON_DST_PITCH_OFFSET, pitch_offset );
WRITE_IB_REG( RADEON_SRC_PITCH_OFFSET, pitch_offset );
// no sissors
WRITE_IB_REG( RADEON_DEFAULT_SC_BOTTOM_RIGHT,
// no sissors
WRITE_IB_REG( RADEON_DEFAULT_SC_BOTTOM_RIGHT,
(RADEON_DEFAULT_SC_RIGHT_MAX | RADEON_DEFAULT_SC_BOTTOM_MAX));
// general fluff
WRITE_IB_REG( RADEON_DP_GUI_MASTER_CNTL,
WRITE_IB_REG( RADEON_DP_GUI_MASTER_CNTL,
(datatype << RADEON_GMC_DST_DATATYPE_SHIFT)
| RADEON_GMC_CLR_CMP_CNTL_DIS
| RADEON_GMC_BRUSH_SOLID_COLOR
| RADEON_GMC_BRUSH_SOLID_COLOR
| RADEON_GMC_SRC_DATATYPE_COLOR
| RADEON_ROP3_P
| RADEON_DP_SRC_SOURCE_MEMORY
| RADEON_GMC_WR_MSK_DIS );
// most of this init is probably not necessary
// as we neither draw lines nor use brushes
WRITE_IB_REG( RADEON_DP_BRUSH_FRGD_CLR, 0xffffffff);
@@ -454,7 +454,7 @@ void Radeon_FillStateBuffer( accelerator_info *ai, uint32 datatype )
WRITE_IB_REG( RADEON_DP_SRC_FRGD_CLR, 0xffffffff);
WRITE_IB_REG( RADEON_DP_SRC_BKGD_CLR, 0x00000000);
WRITE_IB_REG( RADEON_DP_WRITE_MASK, 0xffffffff);
// this is required
vc->state_buffer_size = buffer - buffer_start;
@@ -463,21 +463,21 @@ void Radeon_FillStateBuffer( accelerator_info *ai, uint32 datatype )
OUTREG( ai->regs, RADEON_DEFAULT_OFFSET, pitch_offset );
OUTREG( ai->regs, RADEON_DST_PITCH_OFFSET, pitch_offset );
OUTREG( ai->regs, RADEON_SRC_PITCH_OFFSET, pitch_offset );
// no sissors
// no sissors
OUTREG( ai->regs, RADEON_DEFAULT_SC_BOTTOM_RIGHT, (RADEON_DEFAULT_SC_RIGHT_MAX
| RADEON_DEFAULT_SC_BOTTOM_MAX));
// general fluff
OUTREG( ai->regs, RADEON_DP_GUI_MASTER_CNTL,
OUTREG( ai->regs, RADEON_DP_GUI_MASTER_CNTL,
(datatype << RADEON_GMC_DST_DATATYPE_SHIFT)
| RADEON_GMC_CLR_CMP_CNTL_DIS
| RADEON_GMC_BRUSH_SOLID_COLOR
| RADEON_GMC_BRUSH_SOLID_COLOR
| RADEON_GMC_SRC_DATATYPE_COLOR
| RADEON_ROP3_P
| RADEON_DP_SRC_SOURCE_MEMORY
| RADEON_GMC_WR_MSK_DIS );
// most of this init is probably not necessary
// as we neither draw lines nor use brushes
OUTREG( ai->regs, RADEON_DP_BRUSH_FRGD_CLR, 0xffffffff);
@@ -487,7 +487,7 @@ void Radeon_FillStateBuffer( accelerator_info *ai, uint32 datatype )
OUTREG( ai->regs, RADEON_DP_WRITE_MASK, 0xffffffff);
}
ai->si->active_vc = vc->id;
}
@@ -496,7 +496,7 @@ void Radeon_FillStateBuffer( accelerator_info *ai, uint32 datatype )
void Radeon_AllocateVirtualCardStateBuffer( accelerator_info *ai )
{
virtual_card *vc = ai->vc;
vc->state_buffer_idx = Radeon_AllocIndirectBuffer( ai, false );
// mark as being unused
vc->state_buffer_size = -1;
+105 -105
View File
@@ -1,9 +1,9 @@
/*
Copyright (c) 2002-2004, Thomas Kurschel
Part of Radeon accelerant
Takes care of PLL
*/
@@ -17,29 +17,29 @@
#include "set_mode.h"
static void Radeon_PLLWaitForReadUpdateComplete(
static void Radeon_PLLWaitForReadUpdateComplete(
accelerator_info *ai, int crtc_idx )
{
int i;
// we should wait forever, but
// 1. this is unsafe
// 2. some r300 loop forever (reported by XFree86)
for( i = 0; i < 10000; ++i ) {
if( (Radeon_INPLL( ai->regs, ai->si->asic, crtc_idx == 0 ? RADEON_PPLL_REF_DIV : RADEON_P2PLL_REF_DIV )
if( (Radeon_INPLL( ai->regs, ai->si->asic, crtc_idx == 0 ? RADEON_PPLL_REF_DIV : RADEON_P2PLL_REF_DIV )
& RADEON_PPLL_ATOMIC_UPDATE_R) == 0 )
return;
}
}
static void Radeon_PLLWriteUpdate(
static void Radeon_PLLWriteUpdate(
accelerator_info *ai, int crtc_idx )
{
Radeon_PLLWaitForReadUpdateComplete( ai, crtc_idx );
Radeon_OUTPLLP( ai->regs, ai->si->asic,
Radeon_OUTPLLP( ai->regs, ai->si->asic,
crtc_idx == 0 ? RADEON_PPLL_REF_DIV : RADEON_P2PLL_REF_DIV,
RADEON_PPLL_ATOMIC_UPDATE_W,
RADEON_PPLL_ATOMIC_UPDATE_W,
~RADEON_PPLL_ATOMIC_UPDATE_W );
}
@@ -48,7 +48,7 @@ static void Radeon_PLLWriteUpdate(
// freq - whished frequency in Hz
// fixed_post_div - if != 0, fixed divider to be used
// dividers - filled with proper dividers
void Radeon_CalcPLLDividers(
void Radeon_CalcPLLDividers(
const pll_info *pll, uint32 freq, uint fixed_post_div, pll_dividers *dividers )
{
// the PLL gets the reference
@@ -63,24 +63,24 @@ void Radeon_CalcPLLDividers(
// pll_out = vco / post_div / extra_post_div
// = ref_freq * feedback_div * extra_feedback_div / (ref_div * post_div * extra_post_div)
// where extra_post_div _may_ be choosable between 1 and 2
// synonyms are:
// ref_div = M
// feedback_div = N
// post_div = P
int
int
min_post_div_idx, max_post_div_idx,
post_div_idx, extra_post_div_idx,
best_post_div_idx, best_extra_post_div_idx;
uint32
best_ref_div, best_feedback_div, best_freq;
int32
best_error, best_vco_dev;
best_error = 999999999;
// make compiler happy
best_post_div_idx = 0;
best_extra_post_div_idx = 0;
@@ -91,42 +91,42 @@ void Radeon_CalcPLLDividers(
if( fixed_post_div == 0 ) {
min_post_div_idx = 0;
for(
max_post_div_idx = 0;
pll->post_divs[max_post_div_idx].divider != 0;
for(
max_post_div_idx = 0;
pll->post_divs[max_post_div_idx].divider != 0;
++max_post_div_idx )
;
--max_post_div_idx;
} else {
for(
min_post_div_idx = 0;
pll->post_divs[min_post_div_idx].divider != fixed_post_div;
for(
min_post_div_idx = 0;
pll->post_divs[min_post_div_idx].divider != fixed_post_div;
++min_post_div_idx )
;
max_post_div_idx = min_post_div_idx;
//SHOW_FLOW( 2, "idx of fixed post divider: %d", min_post_div_idx );
}
// post dividers are quite restrictive, so they provide little search space only
for( extra_post_div_idx = 0; pll->extra_post_divs[extra_post_div_idx].divider != 0; ++extra_post_div_idx ) {
for( post_div_idx = min_post_div_idx; post_div_idx <= max_post_div_idx; ++post_div_idx ) {
uint32 ref_div;
uint32 post_div =
pll->post_divs[post_div_idx].divider
uint32 post_div =
pll->post_divs[post_div_idx].divider
* pll->extra_post_divs[extra_post_div_idx].divider;
// post devider determines VCO frequency, so determine and verify it;
// freq is in Hz, everything else is in 10 kHz units
// we use 10 kHz units as long as possible to avoid uint32 overflows
uint32 vco = (freq / 10000) * post_div;
//SHOW_FLOW( 2, "post_div=%d, vco=%d", post_div, vco );
if( vco < pll->vco_min || vco > pll->vco_max )
continue;
//SHOW_FLOW0( 2, "jau" );
// we can either iterate through feedback or reference dividers;
@@ -134,40 +134,40 @@ void Radeon_CalcPLLDividers(
for( ref_div = pll->min_ref_div; ref_div <= pll->max_ref_div; ++ref_div ) {
uint32 feedback_div, cur_freq;
int32 error, vco_dev;
// this implies the frequency of the lock unit
uint32 pll_in = pll->ref_freq / ref_div;
if( pll_in < pll->pll_in_min || pll_in > pll->pll_in_max )
continue;
// well, only one variable is left
// well, only one variable is left
// timing is almost certainly valid, time to use Hz units
feedback_div = RoundDiv64(
(int64)freq * ref_div * post_div,
feedback_div = RoundDiv64(
(int64)freq * ref_div * post_div,
pll->ref_freq * 10000 * pll->extra_feedback_div);
if( feedback_div < pll->min_feedback_div ||
feedback_div > pll->max_feedback_div )
continue;
// let's see what we've got
cur_freq = RoundDiv64(
(int64)pll->ref_freq * 10000 * feedback_div * pll->extra_feedback_div,
cur_freq = RoundDiv64(
(int64)pll->ref_freq * 10000 * feedback_div * pll->extra_feedback_div,
ref_div * post_div );
// absolute error in terms of output clock
error = abs( cur_freq - freq );
// absolute error in terms of output clock
error = abs( (int32)cur_freq - (int32)freq );
// deviation from perfect VCO clock
vco_dev = abs( vco - pll->best_vco );
vco_dev = abs( (int32)vco - (int32)(pll->best_vco) );
// if there is no optimal VCO frequency, choose setting with less error;
// if there is an optimal VCO frequency, choose new settings if
// - error is reduced significantly (100 Hz or more), or
// - output frequency is almost the same (less then 100 Hz difference) but
// VCO frequency is closer to best frequency
// VCO frequency is closer to best frequency
if( (pll->best_vco == 0 && error < best_error) ||
(pll->best_vco != 0 &&
(pll->best_vco != 0 &&
(error < best_error - 100 ||
(abs( error - best_error ) < 100 && vco_dev < best_vco_dev ))))
{
@@ -193,57 +193,57 @@ void Radeon_CalcPLLDividers(
dividers->freq = best_freq;
/*SHOW_FLOW( 2, "post_code=%d, post=%d, extra_post_code=%d, extra_post=%d, ref=%d, feedback=%d, freq=%d",
dividers->post_code, dividers->post, dividers->extra_post_code,
dividers->post_code, dividers->post, dividers->extra_post_code,
dividers->extra_post, dividers->ref, dividers->feedback, dividers->freq );*/
}
// with a TV timing given, find a corresponding CRT timing.
// both timing must meet at the end of a frame, but as the PLL has a
// limited frequency granularity, you don't really get a CRT timing
// both timing must meet at the end of a frame, but as the PLL has a
// limited frequency granularity, you don't really get a CRT timing
// with precisely the same frame rate; the solution is to tweak the CRT
// image a bit by making it wider/taller/smaller until the frame rate
// drift is under a given threshold;
// drift is under a given threshold;
// we follow two aims:
// - primary, keep frame rate in sync
// - secondary, only tweak as much as unavoidable
void Radeon_MatchCRTPLL(
const pll_info *pll,
uint32 tv_v_total, uint32 tv_h_total, uint32 tv_frame_size_adjust, uint32 freq,
const display_mode *mode, uint32 max_v_tweak, uint32 max_h_tweak,
uint32 max_frame_rate_drift, uint32 fixed_post_div,
void Radeon_MatchCRTPLL(
const pll_info *pll,
uint32 tv_v_total, uint32 tv_h_total, uint32 tv_frame_size_adjust, uint32 freq,
const display_mode *mode, uint32 max_v_tweak, uint32 max_h_tweak,
uint32 max_frame_rate_drift, uint32 fixed_post_div,
pll_dividers *dividers,
display_mode *tweaked_mode )
{
uint32 v_tweak;
int32 v_tweak_dir;
uint32 pix_per_tv_frame;
SHOW_FLOW( 2, "fixed post divider: %d", fixed_post_div );
// number of TV pixels per frame
pix_per_tv_frame = tv_v_total * tv_h_total + tv_frame_size_adjust;
// starting with original data we tweak total horizontal and vertical size
// more and more until we find a proper CRT clock frequency
for( v_tweak = 0; v_tweak <= max_v_tweak; ++v_tweak ) {
for( v_tweak_dir = -1; v_tweak_dir <= 1; v_tweak_dir += 2 ) {
uint32 h_tweak;
int32 h_tweak_dir;
uint32 v_total = mode->timing.v_total + v_tweak * v_tweak_dir;
for( h_tweak = 0; h_tweak <= max_h_tweak; ++h_tweak ) {
for( h_tweak_dir = -1; h_tweak_dir <= 1; h_tweak_dir += 2 ) {
uint32 pix_per_crt_frame, frame_rate_drift;
uint32 crt_freq;
uint32 abs_crt_error;
uint32 h_total = mode->timing.h_total + h_tweak * h_tweak_dir;
// number of CRT pixels per frame
pix_per_crt_frame = v_total * h_total;
// frame rate must be:
// frame_rate = freq / pix_per_tv_half_frame
// because of interlace, we must use half frames
@@ -253,14 +253,14 @@ void Radeon_MatchCRTPLL(
// = freq / (pix_per_tv_frame / 2) * pix_per_crt_frame
// formula is reordered as usual to improve accuracy
crt_freq = (uint64)freq * pix_per_crt_frame * 2 / pix_per_tv_frame;
Radeon_CalcPLLDividers( pll, crt_freq, fixed_post_div, dividers );
// get absolute CRT clock error per second
abs_crt_error = abs( dividers->freq - crt_freq );
abs_crt_error = abs( (int32)(dividers->freq) - (int32)crt_freq );
//SHOW_INFO( 2, "whished=%d, is=%d", crt_freq, dividers->freq );
// convert it to relative CRT clock error:
// rel_error = abs_crt_error / crt_freq
// now to absolute TV clock error per second:
@@ -274,14 +274,14 @@ void Radeon_MatchCRTPLL(
// frame_rate_drift = abs_crt_error / crt_freq * pix_per_tv_frame * frame_rate / frame_rate
// = abs_crt_error / crt_freq * pix_per_tv_frame
frame_rate_drift = (uint64)abs_crt_error * pix_per_tv_frame / freq;
// if drift is within threshold, we take this setting and stop
// searching (later iteration will increasingly tweak screen size,
// and we don't really want that)
if( frame_rate_drift <= max_frame_rate_drift ) {
SHOW_INFO( 2, "frame_rate_drift=%d, crt_freq=%d, v_total=%d, h_total=%d",
SHOW_INFO( 2, "frame_rate_drift=%d, crt_freq=%d, v_total=%d, h_total=%d",
frame_rate_drift, crt_freq, v_total, h_total );
tweaked_mode->timing.pixel_clock = crt_freq;
tweaked_mode->timing.v_total = v_total;
tweaked_mode->timing.h_total = h_total;
@@ -345,7 +345,7 @@ static pll_divider_map tv_post_divs[] = {
// get PLL parameters of TV PLL
void Radeon_GetTVPLLConfiguration( const general_pll_info *general_pll, pll_info *pll,
void Radeon_GetTVPLLConfiguration( const general_pll_info *general_pll, pll_info *pll,
bool internal_encoder )
{
pll->post_divs = tv_post_divs;
@@ -376,16 +376,16 @@ void Radeon_GetTVCRTPLLConfiguration( const general_pll_info *general_pll, pll_i
pll->post_divs = post_divs;
pll->extra_post_divs = extra_post_divs;
pll->ref_freq = general_pll->ref_freq;
// in sample code, these limits are set in a strange way;
// as a first shot, I use the BIOS provided limits
/*pll->vco_min = general_pll->min_pll_freq;
pll->vco_max = general_pll->max_pll_freq;*/
// in sample code, they use a variable post divider during calculation, but
// use a fixed post divider for programming - the variable post divider is
// multiplied to the feedback divider;
// because of the fixed post divider (3), the VCO always runs far out of
// multiplied to the feedback divider;
// because of the fixed post divider (3), the VCO always runs far out of
// its stable frequency range, so we have hack the limits
pll->vco_min = 4000;
pll->vco_max = general_pll->max_pll_freq;
@@ -404,11 +404,11 @@ void Radeon_GetTVCRTPLLConfiguration( const general_pll_info *general_pll, pll_i
// calc PLL dividers for CRT
// mode->timing.pixel_clock must be in Hz because required accuracy in TV-Out mode
void Radeon_CalcCRTPLLDividers(
void Radeon_CalcCRTPLLDividers(
const general_pll_info *general_pll, const display_mode *mode, pll_dividers *dividers )
{
pll_info pll;
pll_info pll;
pll.post_divs = post_divs;
pll.extra_post_divs = extra_post_divs;
pll.ref_freq = general_pll->ref_freq;
@@ -429,17 +429,17 @@ void Radeon_CalcCRTPLLDividers(
}
// calculate PLL registers
// calculate PLL registers
// mode->timing.pixel_clock must be in Hz because required accuracy in TV-Out mode
// (old: freq is in 10kHz)
void Radeon_CalcPLLRegisters(
void Radeon_CalcPLLRegisters(
const display_mode *mode, const pll_dividers *dividers, pll_regs *values )
{
values->dot_clock_freq = dividers->freq;
values->feedback_div = dividers->feedback;
values->post_div = dividers->post;
values->pll_output_freq = dividers->freq * dividers->post;
values->ppll_ref_div = dividers->ref;
values->ppll_div_3 = (dividers->feedback | (dividers->post_code << 16));
// this is mad: the PLL controls the horizontal length in sub-byte precision!
@@ -451,17 +451,17 @@ void Radeon_CalcPLLRegisters(
}
// write values into PLL registers
void Radeon_ProgramPLL(
void Radeon_ProgramPLL(
accelerator_info *ai, int crtc_idx, pll_regs *values )
{
vuint8 *regs = ai->regs;
radeon_type asic = ai->si->asic;
SHOW_FLOW0( 2, "" );
// use some other PLL for pixel clock source to not fiddling with PLL
// while somebody is using it
Radeon_OUTPLLP( regs, asic, crtc_idx == 0 ? RADEON_VCLK_ECP_CNTL : RADEON_PIXCLKS_CNTL,
Radeon_OUTPLLP( regs, asic, crtc_idx == 0 ? RADEON_VCLK_ECP_CNTL : RADEON_PIXCLKS_CNTL,
RADEON_VCLK_SRC_CPU_CLK, ~RADEON_VCLK_SRC_SEL_MASK );
Radeon_OUTPLLP( regs, asic,
@@ -472,48 +472,48 @@ void Radeon_ProgramPLL(
~(RADEON_PPLL_RESET
| RADEON_PPLL_ATOMIC_UPDATE_EN
| RADEON_PPLL_VGA_ATOMIC_UPDATE_EN) );
// select divider 3 (well, only required for first PLL)
OUTREGP( regs, RADEON_CLOCK_CNTL_INDEX,
RADEON_PLL_DIV_SEL_DIV3,
~RADEON_PLL_DIV_SEL_MASK );
RADEONPllErrataAfterIndex(regs, asic);
if( ai->si->new_pll && crtc_idx == 0 ) {
// starting with r300, the reference divider of the first PLL was
// moved to another bit position; at the old location, you only
// starting with r300, the reference divider of the first PLL was
// moved to another bit position; at the old location, you only
// find the "BIOS suggested divider"; no clue why they did that
Radeon_OUTPLLP( regs, asic,
RADEON_PPLL_REF_DIV,
values->ppll_ref_div << RADEON_PPLL_REF_DIV_ACC_SHIFT,
RADEON_PPLL_REF_DIV,
values->ppll_ref_div << RADEON_PPLL_REF_DIV_ACC_SHIFT,
~RADEON_PPLL_REF_DIV_ACC_MASK );
} else {
Radeon_OUTPLLP( regs, asic,
crtc_idx == 0 ? RADEON_PPLL_REF_DIV : RADEON_P2PLL_REF_DIV,
values->ppll_ref_div,
crtc_idx == 0 ? RADEON_PPLL_REF_DIV : RADEON_P2PLL_REF_DIV,
values->ppll_ref_div,
~RADEON_PPLL_REF_DIV_MASK );
}
Radeon_OUTPLLP( regs, asic,
crtc_idx == 0 ? RADEON_PPLL_DIV_3 : RADEON_P2PLL_DIV_0,
values->ppll_div_3,
crtc_idx == 0 ? RADEON_PPLL_DIV_3 : RADEON_P2PLL_DIV_0,
values->ppll_div_3,
~RADEON_PPLL_FB3_DIV_MASK );
Radeon_OUTPLLP( regs, asic,
crtc_idx == 0 ? RADEON_PPLL_DIV_3 : RADEON_P2PLL_DIV_0,
values->ppll_div_3,
crtc_idx == 0 ? RADEON_PPLL_DIV_3 : RADEON_P2PLL_DIV_0,
values->ppll_div_3,
~RADEON_PPLL_POST3_DIV_MASK );
Radeon_PLLWriteUpdate( ai, crtc_idx );
Radeon_PLLWaitForReadUpdateComplete( ai, crtc_idx );
Radeon_OUTPLL( regs, asic,
crtc_idx == 0 ? RADEON_HTOTAL_CNTL : RADEON_HTOTAL2_CNTL,
crtc_idx == 0 ? RADEON_HTOTAL_CNTL : RADEON_HTOTAL2_CNTL,
values->htotal_cntl );
Radeon_OUTPLLP( regs, asic,
crtc_idx == 0 ? RADEON_PPLL_CNTL : RADEON_P2PLL_CNTL, 0,
Radeon_OUTPLLP( regs, asic,
crtc_idx == 0 ? RADEON_PPLL_CNTL : RADEON_P2PLL_CNTL, 0,
~(RADEON_PPLL_RESET
| RADEON_PPLL_SLEEP
| RADEON_PPLL_ATOMIC_UPDATE_EN
@@ -524,6 +524,6 @@ void Radeon_ProgramPLL(
// use PLL for pixel clock again
Radeon_OUTPLLP( regs, asic,
crtc_idx == 0 ? RADEON_VCLK_ECP_CNTL : RADEON_PIXCLKS_CNTL,
crtc_idx == 0 ? RADEON_VCLK_ECP_CNTL : RADEON_PIXCLKS_CNTL,
RADEON_VCLK_SRC_PPLL_CLK, ~RADEON_VCLK_SRC_SEL_MASK );
}