* move pll info into pll_info struct.

* reduce the number of unique storage uint32's


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@42826 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Alexander von Gluck IV
2011-10-11 22:23:31 +00:00
parent 4431610388
commit e7d0abae23
4 changed files with 112 additions and 111 deletions
@@ -101,41 +101,6 @@ struct register_info {
}; };
struct pll_info {
/* reference frequency */
uint32 reference_freq;
/* fixed dividers */
uint32 reference_div;
uint32 post_div;
/* pll in/out limits */
uint32 pll_in_min;
uint32 pll_in_max;
uint32 pll_out_min;
uint32 pll_out_max;
uint32 lcd_pll_out_min;
uint32 lcd_pll_out_max;
uint32 best_vco;
/* divider limits */
uint32 min_ref_div;
uint32 max_ref_div;
uint32 min_post_div;
uint32 max_post_div;
uint32 min_feedback_div;
uint32 max_feedback_div;
uint32 min_frac_feedback_div;
uint32 max_frac_feedback_div;
/* flags for the current clock */
uint32 flags;
/* pll id */
uint32 id;
};
typedef struct { typedef struct {
bool valid; bool valid;
+2 -2
View File
@@ -156,8 +156,8 @@ radeon_set_display_mode(display_mode *mode)
// *** CRT controler mode set // *** CRT controler mode set
// TODO : program SS // TODO : program SS
pll_set(0, mode->timing.pixel_clock, id); pll_set(ATOM_PPLL1, mode->timing.pixel_clock, id);
// TODO : check if pll 0 is used and use pll 1 if so // TODO : check if ATOM_PPLL1 is used and use ATOM_PPLL2 if so
display_crtc_set_dtd(id, mode); display_crtc_set_dtd(id, mode);
// TODO : vvvv : atombios_crtc_set_base // TODO : vvvv : atombios_crtc_set_base
+62 -70
View File
@@ -6,7 +6,6 @@
* Alexander von Gluck, [email protected] * Alexander von Gluck, [email protected]
*/ */
#include "accelerant_protos.h" #include "accelerant_protos.h"
#include "accelerant.h" #include "accelerant.h"
#include "bios.h" #include "bios.h"
@@ -82,14 +81,13 @@ pll_compute_post_divider(uint32 targetClock)
status_t status_t
pll_compute(uint32 pixelClock, uint32 *dotclockOut, uint32 *referenceOut, pll_compute(pll_info *pll) {
uint32 *feedbackOut, uint32 *feedbackFracOut, uint32 *postOut)
{ uint32 targetClock = pll->pixel_clock / 10;
uint32 targetClock = pixelClock / 10; pll->post_div = pll_compute_post_divider(targetClock);
uint32 postDivider = pll_compute_post_divider(targetClock); pll->reference_div = REF_DIV_MIN;
uint32 referenceDivider = REF_DIV_MIN; pll->feedback_div = 0;
uint32 feedbackDivider = 0; pll->feedback_div_frac = 0;
uint32 feedbackDividerFrac = 0;
// if RADEON_PLL_USE_REF_DIV // if RADEON_PLL_USE_REF_DIV
// ref_div = pll->reference_div; // ref_div = pll->reference_div;
@@ -108,61 +106,58 @@ pll_compute(uint32 pixelClock, uint32 *dotclockOut, uint32 *referenceOut,
// frac_fb_div = 0; // frac_fb_div = 0;
// } // }
// } else { // } else {
while (referenceDivider <= REF_DIV_LIMIT) { while (pll->reference_div <= REF_DIV_LIMIT) {
// get feedback divider // get feedback divider
uint32 retroEncabulator = postDivider * referenceDivider; uint32 retroEncabulator = pll->post_div * pll->reference_div;
retroEncabulator *= targetClock; retroEncabulator *= targetClock;
feedbackDivider = retroEncabulator / PLL_REFERENCE_DEFAULT; pll->feedback_div = retroEncabulator / PLL_REFERENCE_DEFAULT;
feedbackDividerFrac = retroEncabulator % PLL_REFERENCE_DEFAULT; pll->feedback_div_frac = retroEncabulator % PLL_REFERENCE_DEFAULT;
if (feedbackDivider > FB_DIV_LIMIT) if (pll->feedback_div > FB_DIV_LIMIT)
feedbackDivider = FB_DIV_LIMIT; pll->feedback_div = FB_DIV_LIMIT;
else if (feedbackDivider < FB_DIV_MIN) else if (pll->feedback_div < FB_DIV_MIN)
feedbackDivider = FB_DIV_MIN; pll->feedback_div = FB_DIV_MIN;
if (feedbackDividerFrac >= (PLL_REFERENCE_DEFAULT / 2)) if (pll->feedback_div_frac >= (PLL_REFERENCE_DEFAULT / 2))
feedbackDivider++; pll->feedback_div++;
feedbackDividerFrac = 0; pll->feedback_div_frac = 0;
if (referenceDivider == 0 || postDivider == 0 || targetClock == 0) { if (pll->reference_div == 0
TRACE("%s: Caught division by zero\n", || pll->post_div == 0
__func__); || targetClock == 0) {
TRACE("%s: Caught division by zero\n", __func__);
return B_ERROR; return B_ERROR;
} }
uint32 tmp = (PLL_REFERENCE_DEFAULT * feedbackDivider) uint32 tmp = (PLL_REFERENCE_DEFAULT * pll->feedback_div)
/ (postDivider * referenceDivider); / (pll->post_div * pll->reference_div);
tmp = (tmp * 10000) / targetClock; tmp = (tmp * 10000) / targetClock;
if (tmp > (10000 + MAX_TOLERANCE)) if (tmp > (10000 + MAX_TOLERANCE))
referenceDivider++; pll->reference_div++;
else if (tmp >= (10000 - MAX_TOLERANCE)) else if (tmp >= (10000 - MAX_TOLERANCE))
break; break;
else else
referenceDivider++; pll->reference_div++;
} }
// } // }
if (referenceDivider == 0 || postDivider == 0) { if (pll->reference_div == 0 || pll->post_div == 0) {
TRACE("%s: Caught division by zero of post or reference divider\n", TRACE("%s: Caught division by zero of post or reference divider\n",
__func__); __func__);
return B_ERROR; return B_ERROR;
} }
*dotclockOut = ((PLL_REFERENCE_DEFAULT * feedbackDivider * 10) pll->dot_clock = ((PLL_REFERENCE_DEFAULT * pll->feedback_div * 10)
+ (PLL_REFERENCE_DEFAULT * feedbackDividerFrac)) + (PLL_REFERENCE_DEFAULT * pll->feedback_div_frac))
/ (referenceDivider * postDivider * 10); / (pll->reference_div * pll->post_div * 10);
*feedbackOut = feedbackDivider;
*feedbackFracOut = feedbackDividerFrac;
*referenceOut = referenceDivider;
*postOut = postDivider;
TRACE("%s: pixel clock: %" B_PRIu32 " gives:" TRACE("%s: pixel clock: %" B_PRIu32 " gives:"
" feedbackDivider = %" B_PRIu32 ".%" B_PRIu32 " feedbackDivider = %" B_PRIu32 ".%" B_PRIu32
"; referenceDivider = %" B_PRIu32 "; postDivider = %" B_PRIu32 "; referenceDivider = %" B_PRIu32 "; postDivider = %" B_PRIu32
"; dotClock = %" B_PRIu32 "\n", __func__, pixelClock, feedbackDivider, "; dotClock = %" B_PRIu32 "\n", __func__, pll->pixel_clock,
feedbackDividerFrac, referenceDivider, postDivider, *dotclockOut); pll->feedback_div, pll->feedback_div_frac, pll->reference_div,
pll->post_div, pll->dot_clock);
return B_OK; return B_OK;
} }
@@ -175,19 +170,19 @@ union adjust_pixel_clock {
uint32 uint32
pll_adjust(uint32 pixelClock, uint8 crtc_id) pll_adjust(pll_info *pll, uint8 crtc_id)
{ {
uint32 flags = 0; pll->flags |= PLL_PREFER_LOW_REF_DIV;
flags |= PLL_PREFER_LOW_REF_DIV;
// TODO : PLL flags // TODO : PLL flags
radeon_shared_info &info = *gInfo->shared_info; radeon_shared_info &info = *gInfo->shared_info;
uint32 adjustedClock = pixelClock; uint32 pixelClock = pll->pixel_clock;
uint32 adjustedClock = pll->pixel_clock;
uint32 connector_index = gDisplay[crtc_id]->connector_index; uint32 connector_index = gDisplay[crtc_id]->connector_index;
uint32 encoder_id = gConnector[connector_index]->encoder.object_id; uint32 encoder_id = gConnector[connector_index]->encoder.object_id;
uint32 encoder_mode = display_get_encoder_mode(connector_index); uint32 encoder_mode = display_get_encoder_mode(connector_index);
pll_info *pll = &gConnector[connector_index]->encoder.pll;
if (info.device_chipset >= (RADEON_R600 | 0x20)) { if (info.device_chipset >= (RADEON_R600 | 0x20)) {
union adjust_pixel_clock args; union adjust_pixel_clock args;
@@ -269,16 +264,15 @@ pll_adjust(uint32 pixelClock, uint8 crtc_id)
status_t status_t
pll_set(uint8 pll_id, uint32 pixelClock, uint8 crtc_id) pll_set(uint8 pll_id, uint32 pixelClock, uint8 crtc_id)
{ {
uint32 dotclock = 0; uint32 connector_index = gDisplay[crtc_id]->connector_index;
uint32 reference = 0; pll_info *pll = &gConnector[connector_index]->encoder.pll;
uint32 feedback = 0; pll->pixel_clock = pixelClock;
uint32 feedbackFrac = 0; pll->id = pll_id;
uint32 post = 0;
uint32 adjustedClock = pll_adjust(pixelClock, crtc_id); // get any needed clock adjustments, set reference/post dividers, set flags
uint32 adjustedClock = pll_adjust(pll, crtc_id);
pll_compute(adjustedClock, &dotclock, &reference, &feedback, pll_compute(pll);
&feedbackFrac, &post);
int index = GetIndexIntoMasterTable(COMMAND, SetPixelClock); int index = GetIndexIntoMasterTable(COMMAND, SetPixelClock);
union set_pixel_clock args; union set_pixel_clock args;
@@ -288,37 +282,35 @@ pll_set(uint8 pll_id, uint32 pixelClock, uint8 crtc_id)
uint8 crev; uint8 crev;
atom_parse_cmd_header(gAtomContext, index, &frev, &crev); atom_parse_cmd_header(gAtomContext, index, &frev, &crev);
uint32 connector_index = gDisplay[crtc_id]->connector_index;
switch (crev) { switch (crev) {
case 1: case 1:
args.v1.usPixelClock = B_HOST_TO_LENDIAN_INT16(adjustedClock / 10); args.v1.usPixelClock = B_HOST_TO_LENDIAN_INT16(adjustedClock / 10);
args.v1.usRefDiv = B_HOST_TO_LENDIAN_INT16(reference); args.v1.usRefDiv = B_HOST_TO_LENDIAN_INT16(pll->reference_div);
args.v1.usFbDiv = B_HOST_TO_LENDIAN_INT16(feedback); args.v1.usFbDiv = B_HOST_TO_LENDIAN_INT16(pll->feedback_div);
args.v1.ucFracFbDiv = feedbackFrac; args.v1.ucFracFbDiv = pll->feedback_div_frac;
args.v1.ucPostDiv = post; args.v1.ucPostDiv = pll->post_div;
args.v1.ucPpll = pll_id; args.v1.ucPpll = pll->id;
args.v1.ucCRTC = crtc_id; args.v1.ucCRTC = crtc_id;
args.v1.ucRefDivSrc = 1; args.v1.ucRefDivSrc = 1;
break; break;
case 2: case 2:
args.v2.usPixelClock = B_HOST_TO_LENDIAN_INT16(adjustedClock / 10); args.v2.usPixelClock = B_HOST_TO_LENDIAN_INT16(adjustedClock / 10);
args.v2.usRefDiv = B_HOST_TO_LENDIAN_INT16(reference); args.v2.usRefDiv = B_HOST_TO_LENDIAN_INT16(pll->reference_div);
args.v2.usFbDiv = B_HOST_TO_LENDIAN_INT16(feedback); args.v2.usFbDiv = B_HOST_TO_LENDIAN_INT16(pll->feedback_div);
args.v2.ucFracFbDiv = feedbackFrac; args.v2.ucFracFbDiv = pll->feedback_div_frac;
args.v2.ucPostDiv = post; args.v2.ucPostDiv = pll->post_div;
args.v2.ucPpll = pll_id; args.v2.ucPpll = pll->id;
args.v2.ucCRTC = crtc_id; args.v2.ucCRTC = crtc_id;
args.v2.ucRefDivSrc = 1; args.v2.ucRefDivSrc = 1;
break; break;
case 3: case 3:
args.v3.usPixelClock = B_HOST_TO_LENDIAN_INT16(adjustedClock / 10); args.v3.usPixelClock = B_HOST_TO_LENDIAN_INT16(adjustedClock / 10);
args.v3.usRefDiv = B_HOST_TO_LENDIAN_INT16(reference); args.v3.usRefDiv = B_HOST_TO_LENDIAN_INT16(pll->reference_div);
args.v3.usFbDiv = B_HOST_TO_LENDIAN_INT16(feedback); args.v3.usFbDiv = B_HOST_TO_LENDIAN_INT16(pll->feedback_div);
args.v3.ucFracFbDiv = feedbackFrac; args.v3.ucFracFbDiv = pll->feedback_div_frac;
args.v3.ucPostDiv = post; args.v3.ucPostDiv = pll->post_div;
args.v3.ucPpll = pll_id; args.v3.ucPpll = pll->id;
args.v3.ucMiscInfo = (pll_id << 2); args.v3.ucMiscInfo = (pll->id << 2);
// if (ss_enabled && (ss->type & ATOM_EXTERNAL_SS_MASK)) // if (ss_enabled && (ss->type & ATOM_EXTERNAL_SS_MASK))
// args.v3.ucMiscInfo |= PIXEL_CLOCK_MISC_REF_DIV_SRC; // args.v3.ucMiscInfo |= PIXEL_CLOCK_MISC_REF_DIV_SRC;
args.v3.ucTransmitterId args.v3.ucTransmitterId
@@ -332,7 +324,7 @@ pll_set(uint8 pll_id, uint32 pixelClock, uint8 crtc_id)
} }
TRACE("%s: set adjusted pixel clock %" B_PRIu32 " (was %" B_PRIu32 ")\n", TRACE("%s: set adjusted pixel clock %" B_PRIu32 " (was %" B_PRIu32 ")\n",
__func__, adjustedClock, pixelClock); __func__, adjustedClock, pll->pixel_clock);
return atom_execute_table(gAtomContext, index, (uint32 *)&args); return atom_execute_table(gAtomContext, index, (uint32 *)&args);
} }
+48 -4
View File
@@ -9,6 +9,9 @@
#define RADEON_HD_PLL_H #define RADEON_HD_PLL_H
#include "accelerant.h"
#define MAX_TOLERANCE 10 #define MAX_TOLERANCE 10
#define PLL_MIN_DEFAULT 16000 #define PLL_MIN_DEFAULT 16000
@@ -41,10 +44,51 @@
#define PLL_PREFER_MINM_OVER_MAXP (1 << 14) #define PLL_PREFER_MINM_OVER_MAXP (1 << 14)
uint32 pll_adjust(uint32 pixelClock, uint8 crtc_id); struct pll_info {
status_t pll_compute(uint32 pixelClock, uint32 *dotclockOut, /* pixel clock to be programmed (kHz)*/
uint32 *referenceOut, uint32 *feedbackOut, uint32 *feedbackFracOut, uint32 pixel_clock;
uint32 *postOut);
/* dot clock (kHz) */
uint32 dot_clock;
/* flags for the current clock */
uint32 flags;
/* pll id */
uint32 id;
/* reference frequency */
uint32 reference_freq;
/* fixed dividers */
uint32 post_div;
uint32 reference_div;
uint32 feedback_div;
uint32 feedback_div_frac;
/* pll in/out limits */
uint32 pll_in_min;
uint32 pll_in_max;
uint32 pll_out_min;
uint32 pll_out_max;
uint32 lcd_pll_out_min;
uint32 lcd_pll_out_max;
uint32 best_vco;
/* divider limits */
uint32 min_ref_div;
uint32 max_ref_div;
uint32 min_post_div;
uint32 max_post_div;
uint32 min_feedback_div;
uint32 max_feedback_div;
uint32 min_frac_feedback_div;
uint32 max_frac_feedback_div;
};
uint32 pll_adjust(pll_info *pll, uint8 crtc_id);
status_t pll_compute(pll_info *pll);
status_t pll_set(uint8 pll_id, uint32 pixelClock, uint8 crtc_id); status_t pll_set(uint8 pll_id, uint32 pixelClock, uint8 crtc_id);