Author: kallisti5 Date: 2011-10-12 00:23:31 +0200 (Wed, 12 Oct 2011) New Revision: 42826 Changeset: https://dev.haiku-os.org/changeset/42826 Modified: haiku/trunk/src/add-ons/accelerants/radeon_hd/accelerant.h haiku/trunk/src/add-ons/accelerants/radeon_hd/mode.cpp haiku/trunk/src/add-ons/accelerants/radeon_hd/pll.cpp haiku/trunk/src/add-ons/accelerants/radeon_hd/pll.h Log: * move pll info into pll_info struct. * reduce the number of unique storage uint32's Modified: haiku/trunk/src/add-ons/accelerants/radeon_hd/accelerant.h =================================================================== --- haiku/trunk/src/add-ons/accelerants/radeon_hd/accelerant.h 2011-10-11 18:13:36 UTC (rev 42825) +++ haiku/trunk/src/add-ons/accelerants/radeon_hd/accelerant.h 2011-10-11 22:23:31 UTC (rev 42826) @@ -101,41 +101,6 @@ }; -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; Modified: haiku/trunk/src/add-ons/accelerants/radeon_hd/mode.cpp =================================================================== --- haiku/trunk/src/add-ons/accelerants/radeon_hd/mode.cpp 2011-10-11 18:13:36 UTC (rev 42825) +++ haiku/trunk/src/add-ons/accelerants/radeon_hd/mode.cpp 2011-10-11 22:23:31 UTC (rev 42826) @@ -156,8 +156,8 @@ // *** 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 Modified: haiku/trunk/src/add-ons/accelerants/radeon_hd/pll.cpp =================================================================== --- haiku/trunk/src/add-ons/accelerants/radeon_hd/pll.cpp 2011-10-11 18:13:36 UTC (rev 42825) +++ haiku/trunk/src/add-ons/accelerants/radeon_hd/pll.cpp 2011-10-11 22:23:31 UTC (rev 42826) @@ -6,7 +6,6 @@ * Alexander von Gluck, kallisti5@xxxxxxxxxxx */ - #include "accelerant_protos.h" #include "accelerant.h" #include "bios.h" @@ -82,15 +81,14 @@ 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 @@ // 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); + pll->dot_clock = ((PLL_REFERENCE_DEFAULT * pll->feedback_div * 10) + + (PLL_REFERENCE_DEFAULT * pll->feedback_div_frac)) + / (pll->reference_div * pll->post_div * 10); - *feedbackOut = feedbackDivider; - *feedbackFracOut = feedbackDividerFrac; - *referenceOut = referenceDivider; - *postOut = postDivider; - 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 @@ 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 @@ 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 @@ 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 @@ } 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); } Modified: haiku/trunk/src/add-ons/accelerants/radeon_hd/pll.h =================================================================== --- haiku/trunk/src/add-ons/accelerants/radeon_hd/pll.h 2011-10-11 18:13:36 UTC (rev 42825) +++ haiku/trunk/src/add-ons/accelerants/radeon_hd/pll.h 2011-10-11 22:23:31 UTC (rev 42826) @@ -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);