* 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 {
bool valid;
+2 -2
View File
@@ -156,8 +156,8 @@ radeon_set_display_mode(display_mode *mode)
// *** CRT controler mode set
// TODO : program SS
pll_set(0, mode->timing.pixel_clock, id);
// TODO : check if pll 0 is used and use pll 1 if so
pll_set(ATOM_PPLL1, mode->timing.pixel_clock, id);
// TODO : check if ATOM_PPLL1 is used and use ATOM_PPLL2 if so
display_crtc_set_dtd(id, mode);
// TODO : vvvv : atombios_crtc_set_base
+62 -70
View File
@@ -6,7 +6,6 @@
* Alexander von Gluck, [email protected]
*/
#include "accelerant_protos.h"
#include "accelerant.h"
#include "bios.h"
@@ -82,14 +81,13 @@ pll_compute_post_divider(uint32 targetClock)
status_t
pll_compute(uint32 pixelClock, uint32 *dotclockOut, uint32 *referenceOut,
uint32 *feedbackOut, uint32 *feedbackFracOut, uint32 *postOut)
{
uint32 targetClock = pixelClock / 10;
uint32 postDivider = pll_compute_post_divider(targetClock);
uint32 referenceDivider = REF_DIV_MIN;
uint32 feedbackDivider = 0;
uint32 feedbackDividerFrac = 0;
pll_compute(pll_info *pll) {
uint32 targetClock = pll->pixel_clock / 10;
pll->post_div = pll_compute_post_divider(targetClock);
pll->reference_div = REF_DIV_MIN;
pll->feedback_div = 0;
pll->feedback_div_frac = 0;
// if RADEON_PLL_USE_REF_DIV
// ref_div = pll->reference_div;
@@ -108,61 +106,58 @@ pll_compute(uint32 pixelClock, uint32 *dotclockOut, uint32 *referenceOut,
// frac_fb_div = 0;
// }
// } else {
while (referenceDivider <= REF_DIV_LIMIT) {
while (pll->reference_div <= REF_DIV_LIMIT) {
// get feedback divider
uint32 retroEncabulator = postDivider * referenceDivider;
uint32 retroEncabulator = pll->post_div * pll->reference_div;
retroEncabulator *= targetClock;
feedbackDivider = retroEncabulator / PLL_REFERENCE_DEFAULT;
feedbackDividerFrac = retroEncabulator % PLL_REFERENCE_DEFAULT;
pll->feedback_div = retroEncabulator / PLL_REFERENCE_DEFAULT;
pll->feedback_div_frac = retroEncabulator % PLL_REFERENCE_DEFAULT;
if (feedbackDivider > FB_DIV_LIMIT)
feedbackDivider = FB_DIV_LIMIT;
else if (feedbackDivider < FB_DIV_MIN)
feedbackDivider = FB_DIV_MIN;
if (pll->feedback_div > FB_DIV_LIMIT)
pll->feedback_div = FB_DIV_LIMIT;
else if (pll->feedback_div < FB_DIV_MIN)
pll->feedback_div = FB_DIV_MIN;
if (feedbackDividerFrac >= (PLL_REFERENCE_DEFAULT / 2))
feedbackDivider++;
if (pll->feedback_div_frac >= (PLL_REFERENCE_DEFAULT / 2))
pll->feedback_div++;
feedbackDividerFrac = 0;
if (referenceDivider == 0 || postDivider == 0 || targetClock == 0) {
TRACE("%s: Caught division by zero\n",
__func__);
pll->feedback_div_frac = 0;
if (pll->reference_div == 0
|| pll->post_div == 0
|| targetClock == 0) {
TRACE("%s: Caught division by zero\n", __func__);
return B_ERROR;
}
uint32 tmp = (PLL_REFERENCE_DEFAULT * feedbackDivider)
/ (postDivider * referenceDivider);
uint32 tmp = (PLL_REFERENCE_DEFAULT * pll->feedback_div)
/ (pll->post_div * pll->reference_div);
tmp = (tmp * 10000) / targetClock;
if (tmp > (10000 + MAX_TOLERANCE))
referenceDivider++;
pll->reference_div++;
else if (tmp >= (10000 - MAX_TOLERANCE))
break;
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",
__func__);
return B_ERROR;
}
*dotclockOut = ((PLL_REFERENCE_DEFAULT * feedbackDivider * 10)
+ (PLL_REFERENCE_DEFAULT * feedbackDividerFrac))
/ (referenceDivider * postDivider * 10);
*feedbackOut = feedbackDivider;
*feedbackFracOut = feedbackDividerFrac;
*referenceOut = referenceDivider;
*postOut = postDivider;
pll->dot_clock = ((PLL_REFERENCE_DEFAULT * pll->feedback_div * 10)
+ (PLL_REFERENCE_DEFAULT * pll->feedback_div_frac))
/ (pll->reference_div * pll->post_div * 10);
TRACE("%s: pixel clock: %" B_PRIu32 " gives:"
" feedbackDivider = %" B_PRIu32 ".%" B_PRIu32
"; referenceDivider = %" B_PRIu32 "; postDivider = %" B_PRIu32
"; dotClock = %" B_PRIu32 "\n", __func__, pixelClock, feedbackDivider,
feedbackDividerFrac, referenceDivider, postDivider, *dotclockOut);
"; dotClock = %" B_PRIu32 "\n", __func__, pll->pixel_clock,
pll->feedback_div, pll->feedback_div_frac, pll->reference_div,
pll->post_div, pll->dot_clock);
return B_OK;
}
@@ -175,19 +170,19 @@ union adjust_pixel_clock {
uint32
pll_adjust(uint32 pixelClock, uint8 crtc_id)
pll_adjust(pll_info *pll, uint8 crtc_id)
{
uint32 flags = 0;
flags |= PLL_PREFER_LOW_REF_DIV;
pll->flags |= PLL_PREFER_LOW_REF_DIV;
// TODO : PLL flags
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 encoder_id = gConnector[connector_index]->encoder.object_id;
uint32 encoder_mode = display_get_encoder_mode(connector_index);
pll_info *pll = &gConnector[connector_index]->encoder.pll;
if (info.device_chipset >= (RADEON_R600 | 0x20)) {
union adjust_pixel_clock args;
@@ -269,16 +264,15 @@ pll_adjust(uint32 pixelClock, uint8 crtc_id)
status_t
pll_set(uint8 pll_id, uint32 pixelClock, uint8 crtc_id)
{
uint32 dotclock = 0;
uint32 reference = 0;
uint32 feedback = 0;
uint32 feedbackFrac = 0;
uint32 post = 0;
uint32 connector_index = gDisplay[crtc_id]->connector_index;
pll_info *pll = &gConnector[connector_index]->encoder.pll;
pll->pixel_clock = pixelClock;
pll->id = pll_id;
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,
&feedbackFrac, &post);
pll_compute(pll);
int index = GetIndexIntoMasterTable(COMMAND, SetPixelClock);
union set_pixel_clock args;
@@ -288,37 +282,35 @@ pll_set(uint8 pll_id, uint32 pixelClock, uint8 crtc_id)
uint8 crev;
atom_parse_cmd_header(gAtomContext, index, &frev, &crev);
uint32 connector_index = gDisplay[crtc_id]->connector_index;
switch (crev) {
case 1:
args.v1.usPixelClock = B_HOST_TO_LENDIAN_INT16(adjustedClock / 10);
args.v1.usRefDiv = B_HOST_TO_LENDIAN_INT16(reference);
args.v1.usFbDiv = B_HOST_TO_LENDIAN_INT16(feedback);
args.v1.ucFracFbDiv = feedbackFrac;
args.v1.ucPostDiv = post;
args.v1.ucPpll = pll_id;
args.v1.usRefDiv = B_HOST_TO_LENDIAN_INT16(pll->reference_div);
args.v1.usFbDiv = B_HOST_TO_LENDIAN_INT16(pll->feedback_div);
args.v1.ucFracFbDiv = pll->feedback_div_frac;
args.v1.ucPostDiv = pll->post_div;
args.v1.ucPpll = pll->id;
args.v1.ucCRTC = crtc_id;
args.v1.ucRefDivSrc = 1;
break;
case 2:
args.v2.usPixelClock = B_HOST_TO_LENDIAN_INT16(adjustedClock / 10);
args.v2.usRefDiv = B_HOST_TO_LENDIAN_INT16(reference);
args.v2.usFbDiv = B_HOST_TO_LENDIAN_INT16(feedback);
args.v2.ucFracFbDiv = feedbackFrac;
args.v2.ucPostDiv = post;
args.v2.ucPpll = pll_id;
args.v2.usRefDiv = B_HOST_TO_LENDIAN_INT16(pll->reference_div);
args.v2.usFbDiv = B_HOST_TO_LENDIAN_INT16(pll->feedback_div);
args.v2.ucFracFbDiv = pll->feedback_div_frac;
args.v2.ucPostDiv = pll->post_div;
args.v2.ucPpll = pll->id;
args.v2.ucCRTC = crtc_id;
args.v2.ucRefDivSrc = 1;
break;
case 3:
args.v3.usPixelClock = B_HOST_TO_LENDIAN_INT16(adjustedClock / 10);
args.v3.usRefDiv = B_HOST_TO_LENDIAN_INT16(reference);
args.v3.usFbDiv = B_HOST_TO_LENDIAN_INT16(feedback);
args.v3.ucFracFbDiv = feedbackFrac;
args.v3.ucPostDiv = post;
args.v3.ucPpll = pll_id;
args.v3.ucMiscInfo = (pll_id << 2);
args.v3.usRefDiv = B_HOST_TO_LENDIAN_INT16(pll->reference_div);
args.v3.usFbDiv = B_HOST_TO_LENDIAN_INT16(pll->feedback_div);
args.v3.ucFracFbDiv = pll->feedback_div_frac;
args.v3.ucPostDiv = pll->post_div;
args.v3.ucPpll = pll->id;
args.v3.ucMiscInfo = (pll->id << 2);
// if (ss_enabled && (ss->type & ATOM_EXTERNAL_SS_MASK))
// args.v3.ucMiscInfo |= PIXEL_CLOCK_MISC_REF_DIV_SRC;
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",
__func__, adjustedClock, pixelClock);
__func__, adjustedClock, pll->pixel_clock);
return atom_execute_table(gAtomContext, index, (uint32 *)&args);
}
+48 -4
View File
@@ -9,6 +9,9 @@
#define RADEON_HD_PLL_H
#include "accelerant.h"
#define MAX_TOLERANCE 10
#define PLL_MIN_DEFAULT 16000
@@ -41,10 +44,51 @@
#define PLL_PREFER_MINM_OVER_MAXP (1 << 14)
uint32 pll_adjust(uint32 pixelClock, uint8 crtc_id);
status_t pll_compute(uint32 pixelClock, uint32 *dotclockOut,
uint32 *referenceOut, uint32 *feedbackOut, uint32 *feedbackFracOut,
uint32 *postOut);
struct pll_info {
/* pixel clock to be programmed (kHz)*/
uint32 pixel_clock;
/* 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);