summaryrefslogtreecommitdiff
path: root/driver/xf86-video-ati/src/radeon_crtc.c
diff options
context:
space:
mode:
authorMatthieu Herrb <matthieu@cvs.openbsd.org>2012-01-25 21:33:36 +0000
committerMatthieu Herrb <matthieu@cvs.openbsd.org>2012-01-25 21:33:36 +0000
commit46e73e726a6a3567a4bb19b06c59826b9c6767d1 (patch)
tree8df52bebcc8ecbe55a8f8be1afae536b5fb46319 /driver/xf86-video-ati/src/radeon_crtc.c
parentee1cf1e0a2b9e0f7070a4d1efa6b426373e8ba67 (diff)
Update to xf86-video-ati 6.14.3. Tested by many.
Diffstat (limited to 'driver/xf86-video-ati/src/radeon_crtc.c')
-rw-r--r--driver/xf86-video-ati/src/radeon_crtc.c464
1 files changed, 370 insertions, 94 deletions
diff --git a/driver/xf86-video-ati/src/radeon_crtc.c b/driver/xf86-video-ati/src/radeon_crtc.c
index 2badca1ec..d0daa484a 100644
--- a/driver/xf86-video-ati/src/radeon_crtc.c
+++ b/driver/xf86-video-ati/src/radeon_crtc.c
@@ -32,6 +32,8 @@
#include <string.h>
#include <stdio.h>
+#include <assert.h>
+#include <math.h>
/* X and server generic header files */
#include "xf86.h"
@@ -77,6 +79,9 @@ radeon_crtc_dpms(xf86CrtcPtr crtc, int mode)
if ((mode == DPMSModeOn) && radeon_crtc->enabled)
return;
+ if (mode == DPMSModeOff)
+ radeon_crtc_modeset_ioctl(crtc, FALSE);
+
if (IS_AVIVO_VARIANT || info->r4xx_atom) {
atombios_crtc_dpms(crtc, mode);
} else {
@@ -97,6 +102,11 @@ radeon_crtc_dpms(xf86CrtcPtr crtc, int mode)
}
}
+ if (mode != DPMSModeOff) {
+ radeon_crtc_modeset_ioctl(crtc, TRUE);
+ radeon_crtc_load_lut(crtc);
+ }
+
if (mode == DPMSModeOn)
radeon_crtc->enabled = TRUE;
else
@@ -115,9 +125,6 @@ radeon_crtc_mode_prepare(xf86CrtcPtr crtc)
{
RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private;
- if (radeon_crtc->initialized)
- radeon_crtc_dpms(crtc, DPMSModeOff);
-
if (radeon_crtc->enabled)
crtc->funcs->hide_cursor(crtc);
}
@@ -127,21 +134,27 @@ static uint32_t RADEONDiv(CARD64 n, uint32_t d)
return (n + (d / 2)) / d;
}
-void
-RADEONComputePLL(RADEONPLLPtr pll,
- unsigned long freq,
- uint32_t *chosen_dot_clock_freq,
- uint32_t *chosen_feedback_div,
- uint32_t *chosen_reference_div,
- uint32_t *chosen_post_div,
- int flags)
+static void
+RADEONComputePLL_old(RADEONPLLPtr pll,
+ unsigned long freq,
+ uint32_t *chosen_dot_clock_freq,
+ uint32_t *chosen_feedback_div,
+ uint32_t *chosen_frac_feedback_div,
+ uint32_t *chosen_reference_div,
+ uint32_t *chosen_post_div,
+ int flags)
{
uint32_t min_ref_div = pll->min_ref_div;
uint32_t max_ref_div = pll->max_ref_div;
+ uint32_t min_post_div = pll->min_post_div;
+ uint32_t max_post_div = pll->max_post_div;
+ uint32_t min_fractional_feed_div = 0;
+ uint32_t max_fractional_feed_div = 0;
uint32_t best_vco = pll->best_vco;
uint32_t best_post_div = 1;
uint32_t best_ref_div = 1;
uint32_t best_feedback_div = 1;
+ uint32_t best_frac_feedback_div = 0;
uint32_t best_freq = -1;
uint32_t best_error = 0xffffffff;
uint32_t best_vco_diff = 1;
@@ -165,7 +178,15 @@ RADEONComputePLL(RADEONPLLPtr pll,
}
}
- for (post_div = pll->min_post_div; post_div <= pll->max_post_div; ++post_div) {
+ if (flags & RADEON_PLL_USE_POST_DIV)
+ min_post_div = max_post_div = pll->post_div;
+
+ if (flags & RADEON_PLL_USE_FRAC_FB_DIV) {
+ min_fractional_feed_div = pll->min_frac_feedback_div;
+ max_fractional_feed_div = pll->max_frac_feedback_div;
+ }
+
+ for (post_div = min_post_div; post_div <= max_post_div; ++post_div) {
uint32_t ref_div;
if ((flags & RADEON_PLL_NO_ODD_POST_DIV) && (post_div & 1))
@@ -182,7 +203,7 @@ RADEONComputePLL(RADEONPLLPtr pll,
}
for (ref_div = min_ref_div; ref_div <= max_ref_div; ++ref_div) {
- uint32_t feedback_div, current_freq, error, vco_diff;
+ uint32_t feedback_div, current_freq = 0, error, vco_diff;
uint32_t pll_in = pll->reference_freq / ref_div;
uint32_t min_feed_div = pll->min_feedback_div;
uint32_t max_feed_div = pll->max_feedback_div+1;
@@ -192,11 +213,15 @@ RADEONComputePLL(RADEONPLLPtr pll,
while (min_feed_div < max_feed_div) {
uint32_t vco;
+ uint32_t min_frac_feed_div = min_fractional_feed_div;
+ uint32_t max_frac_feed_div = max_fractional_feed_div+1;
+ uint32_t frac_feedback_div;
+ CARD64 tmp;
feedback_div = (min_feed_div+max_feed_div)/2;
- vco = RADEONDiv((CARD64)pll->reference_freq * feedback_div,
- ref_div);
+ tmp = (CARD64)pll->reference_freq * feedback_div;
+ vco = RADEONDiv(tmp, ref_div);
if (vco < pll->pll_out_min) {
min_feed_div = feedback_div+1;
@@ -206,45 +231,59 @@ RADEONComputePLL(RADEONPLLPtr pll,
continue;
}
- current_freq = RADEONDiv((CARD64)pll->reference_freq * 10000 * feedback_div,
- ref_div * post_div);
-
- error = abs(current_freq - freq);
- vco_diff = abs(vco - best_vco);
-
- if ((best_vco == 0 && error < best_error) ||
- (best_vco != 0 &&
- (error < best_error - 100 ||
- (abs(error - best_error) < 100 && vco_diff < best_vco_diff )))) {
- best_post_div = post_div;
- best_ref_div = ref_div;
- best_feedback_div = feedback_div;
- best_freq = current_freq;
- best_error = error;
- best_vco_diff = vco_diff;
- } else if (current_freq == freq) {
- if (best_freq == -1) {
- best_post_div = post_div;
- best_ref_div = ref_div;
- best_feedback_div = feedback_div;
- best_freq = current_freq;
- best_error = error;
- best_vco_diff = vco_diff;
- } else if (((flags & RADEON_PLL_PREFER_LOW_REF_DIV) && (ref_div < best_ref_div)) ||
- ((flags & RADEON_PLL_PREFER_HIGH_REF_DIV) && (ref_div > best_ref_div)) ||
- ((flags & RADEON_PLL_PREFER_LOW_FB_DIV) && (feedback_div < best_feedback_div)) ||
- ((flags & RADEON_PLL_PREFER_HIGH_FB_DIV) && (feedback_div > best_feedback_div)) ||
- ((flags & RADEON_PLL_PREFER_LOW_POST_DIV) && (post_div < best_post_div)) ||
- ((flags & RADEON_PLL_PREFER_HIGH_POST_DIV) && (post_div > best_post_div))) {
+ while (min_frac_feed_div < max_frac_feed_div) {
+ frac_feedback_div = (min_frac_feed_div+max_frac_feed_div)/2;
+ tmp = (CARD64)pll->reference_freq * 10000 * feedback_div;
+ tmp += (CARD64)pll->reference_freq * 1000 * frac_feedback_div;
+ current_freq = RADEONDiv(tmp, ref_div * post_div);
+
+ if (flags & RADEON_PLL_PREFER_CLOSEST_LOWER) {
+ error = freq - current_freq;
+ error = (int32_t)error < 0 ? 0xffffffff : error;
+ } else
+ error = abs(current_freq - freq);
+ vco_diff = abs(vco - best_vco);
+
+ if ((best_vco == 0 && error < best_error) ||
+ (best_vco != 0 &&
+ (error < best_error - 100 ||
+ (abs(error - best_error) < 100 && vco_diff < best_vco_diff )))) {
best_post_div = post_div;
best_ref_div = ref_div;
best_feedback_div = feedback_div;
+ best_frac_feedback_div = frac_feedback_div;
best_freq = current_freq;
best_error = error;
best_vco_diff = vco_diff;
+ } else if (current_freq == freq) {
+ if (best_freq == -1) {
+ best_post_div = post_div;
+ best_ref_div = ref_div;
+ best_feedback_div = feedback_div;
+ best_frac_feedback_div = frac_feedback_div;
+ best_freq = current_freq;
+ best_error = error;
+ best_vco_diff = vco_diff;
+ } else if (((flags & RADEON_PLL_PREFER_LOW_REF_DIV) && (ref_div < best_ref_div)) ||
+ ((flags & RADEON_PLL_PREFER_HIGH_REF_DIV) && (ref_div > best_ref_div)) ||
+ ((flags & RADEON_PLL_PREFER_LOW_FB_DIV) && (feedback_div < best_feedback_div)) ||
+ ((flags & RADEON_PLL_PREFER_HIGH_FB_DIV) && (feedback_div > best_feedback_div)) ||
+ ((flags & RADEON_PLL_PREFER_LOW_POST_DIV) && (post_div < best_post_div)) ||
+ ((flags & RADEON_PLL_PREFER_HIGH_POST_DIV) && (post_div > best_post_div))) {
+ best_post_div = post_div;
+ best_ref_div = ref_div;
+ best_feedback_div = feedback_div;
+ best_frac_feedback_div = frac_feedback_div;
+ best_freq = current_freq;
+ best_error = error;
+ best_vco_diff = vco_diff;
+ }
}
+ if (current_freq < freq)
+ min_frac_feed_div = frac_feedback_div+1;
+ else
+ max_frac_feed_div = frac_feedback_div;
}
-
if (current_freq < freq)
min_feed_div = feedback_div+1;
else
@@ -255,6 +294,7 @@ RADEONComputePLL(RADEONPLLPtr pll,
ErrorF("best_freq: %u\n", (unsigned int)best_freq);
ErrorF("best_feedback_div: %u\n", (unsigned int)best_feedback_div);
+ ErrorF("best_frac_feedback_div: %u\n", (unsigned int)best_frac_feedback_div);
ErrorF("best_ref_div: %u\n", (unsigned int)best_ref_div);
ErrorF("best_post_div: %u\n", (unsigned int)best_post_div);
@@ -262,11 +302,181 @@ RADEONComputePLL(RADEONPLLPtr pll,
FatalError("Couldn't find valid PLL dividers\n");
*chosen_dot_clock_freq = best_freq / 10000;
*chosen_feedback_div = best_feedback_div;
+ *chosen_frac_feedback_div = best_frac_feedback_div;
*chosen_reference_div = best_ref_div;
*chosen_post_div = best_post_div;
}
+static Bool
+calc_fb_div(RADEONPLLPtr pll,
+ unsigned long freq,
+ int flags,
+ int post_div,
+ int ref_div,
+ int *fb_div,
+ int *fb_div_frac)
+{
+ float ffreq = freq / 10;
+ float vco_freq = ffreq * post_div;
+ float feedback_divider = vco_freq * ref_div / pll->reference_freq;
+
+ if (flags & RADEON_PLL_USE_FRAC_FB_DIV) {
+ feedback_divider = floor((feedback_divider * 10.0) + 0.5) * 0.1;
+
+ *fb_div = floor(feedback_divider);
+ *fb_div_frac = fmod(feedback_divider, 1.0) * 10.0;
+
+ } else {
+ *fb_div = floor(feedback_divider + 0.5);
+ *fb_div_frac = 0;
+ }
+ if ((*fb_div < pll->min_feedback_div) || (*fb_div > pll->max_feedback_div))
+ return FALSE;
+ else
+ return TRUE;
+}
+
+static Bool
+calc_fb_ref_div(RADEONPLLPtr pll,
+ unsigned long freq,
+ int flags,
+ int post_div,
+ int *fb_div,
+ int *fb_div_frac,
+ int *ref_div)
+{
+ float ffreq = freq / 10;
+ float max_error = ffreq * 0.0025;
+ float vco, error, pll_out;
+
+ for ((*ref_div) = pll->min_ref_div; (*ref_div) < pll->max_ref_div; ++(*ref_div)) {
+ if (calc_fb_div(pll, freq, flags, post_div, (*ref_div), fb_div, fb_div_frac)) {
+ vco = pll->reference_freq * ((*fb_div) + ((*fb_div_frac) * 0.1)) / (*ref_div);
+
+ if ((vco < pll->pll_out_min) || (vco > pll->pll_out_max))
+ continue;
+
+ pll_out = vco / post_div;
+
+ error = pll_out - ffreq;
+ if ((fabs(error) <= max_error) && (error >= 0))
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+static void
+RADEONComputePLL_new(RADEONPLLPtr pll,
+ unsigned long freq,
+ uint32_t *chosen_dot_clock_freq,
+ uint32_t *chosen_feedback_div,
+ uint32_t *chosen_frac_feedback_div,
+ uint32_t *chosen_reference_div,
+ uint32_t *chosen_post_div,
+ int flags)
+{
+ float ffreq = freq / 10;
+ float vco_frequency;
+ int fb_div = 0, fb_div_frac = 0, post_div = 0, ref_div = 0;
+ uint32_t best_freq = 0;
+
+ if (flags & RADEON_PLL_USE_POST_DIV) {
+ post_div = pll->post_div;
+ if ((post_div < pll->min_post_div) || (post_div > pll->max_post_div))
+ goto done;
+ vco_frequency = ffreq * post_div;
+ if ((vco_frequency < pll->pll_out_min) || (vco_frequency > pll->pll_out_max))
+ goto done;
+
+ if (flags & RADEON_PLL_USE_REF_DIV) {
+ ref_div = pll->reference_div;
+ if ((ref_div < pll->min_ref_div) || (ref_div > pll->max_ref_div))
+ goto done;
+ if (!calc_fb_div(pll, freq, flags, post_div, ref_div, &fb_div, &fb_div_frac))
+ goto done;
+ }
+ } else {
+ for (post_div = pll->max_post_div; post_div >= pll->min_post_div; --post_div) {
+ if (flags & RADEON_PLL_LEGACY) {
+ if ((post_div == 5) ||
+ (post_div == 7) ||
+ (post_div == 9) ||
+ (post_div == 10) ||
+ (post_div == 11))
+ continue;
+ }
+ if ((flags & RADEON_PLL_NO_ODD_POST_DIV) && (post_div & 1))
+ continue;
+
+ vco_frequency = ffreq * post_div;
+ if ((vco_frequency < pll->pll_out_min) || (vco_frequency > pll->pll_out_max))
+ continue;
+ if (flags & RADEON_PLL_USE_REF_DIV) {
+ ref_div = pll->reference_div;
+ if ((ref_div < pll->min_ref_div) || (ref_div > pll->max_ref_div))
+ goto done;
+ if (calc_fb_div(pll, freq, flags, post_div, ref_div, &fb_div, &fb_div_frac))
+ break;
+ } else {
+ if (calc_fb_ref_div(pll, freq, flags, post_div, &fb_div, &fb_div_frac, &ref_div))
+ break;
+ }
+ }
+ }
+
+ best_freq = pll->reference_freq * 10 * fb_div;
+ best_freq += pll->reference_freq * fb_div_frac;
+ best_freq = best_freq / (ref_div * post_div);
+
+ ErrorF("best_freq: %u\n", (unsigned int)best_freq);
+ ErrorF("best_feedback_div: %u\n", (unsigned int)fb_div);
+ ErrorF("best_frac_feedback_div: %u\n", (unsigned int)fb_div_frac);
+ ErrorF("best_ref_div: %u\n", (unsigned int)ref_div);
+ ErrorF("best_post_div: %u\n", (unsigned int)post_div);
+
+done:
+ if (best_freq == 0)
+ FatalError("Couldn't find valid PLL dividers\n");
+
+ *chosen_dot_clock_freq = best_freq;
+ *chosen_feedback_div = fb_div;
+ *chosen_frac_feedback_div = fb_div_frac;
+ *chosen_reference_div = ref_div;
+ *chosen_post_div = post_div;
+
+}
+
+void
+RADEONComputePLL(xf86CrtcPtr crtc,
+ RADEONPLLPtr pll,
+ unsigned long freq,
+ uint32_t *chosen_dot_clock_freq,
+ uint32_t *chosen_feedback_div,
+ uint32_t *chosen_frac_feedback_div,
+ uint32_t *chosen_reference_div,
+ uint32_t *chosen_post_div,
+ int flags)
+{
+ RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private;
+
+ switch (radeon_crtc->pll_algo) {
+ case RADEON_PLL_OLD:
+ RADEONComputePLL_old(pll, freq, chosen_dot_clock_freq,
+ chosen_feedback_div, chosen_frac_feedback_div,
+ chosen_reference_div, chosen_post_div, flags);
+ break;
+ case RADEON_PLL_NEW:
+ /* disable frac fb dividers */
+ flags &= ~RADEON_PLL_USE_FRAC_FB_DIV;
+ RADEONComputePLL_new(pll, freq, chosen_dot_clock_freq,
+ chosen_feedback_div, chosen_frac_feedback_div,
+ chosen_reference_div, chosen_post_div, flags);
+ break;
+ }
+}
+
static void
radeon_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode,
DisplayModePtr adjusted_mode, int x, int y)
@@ -287,8 +497,6 @@ radeon_crtc_mode_commit(xf86CrtcPtr crtc)
{
if (crtc->scrn->pScreen != NULL)
xf86_reload_cursors(crtc->scrn->pScreen);
-
- radeon_crtc_dpms(crtc, DPMSModeOn);
}
void
@@ -303,63 +511,68 @@ radeon_crtc_load_lut(xf86CrtcPtr crtc)
if (!crtc->enabled)
return;
- if (IS_AVIVO_VARIANT) {
- OUTREG(AVIVO_DC_LUTA_CONTROL + radeon_crtc->crtc_offset, 0);
+ if (IS_DCE4_VARIANT) {
+ OUTREG(EVERGREEN_DC_LUT_CONTROL + radeon_crtc->crtc_offset, 0);
- OUTREG(AVIVO_DC_LUTA_BLACK_OFFSET_BLUE + radeon_crtc->crtc_offset, 0);
- OUTREG(AVIVO_DC_LUTA_BLACK_OFFSET_GREEN + radeon_crtc->crtc_offset, 0);
- OUTREG(AVIVO_DC_LUTA_BLACK_OFFSET_RED + radeon_crtc->crtc_offset, 0);
+ OUTREG(EVERGREEN_DC_LUT_BLACK_OFFSET_BLUE + radeon_crtc->crtc_offset, 0);
+ OUTREG(EVERGREEN_DC_LUT_BLACK_OFFSET_GREEN + radeon_crtc->crtc_offset, 0);
+ OUTREG(EVERGREEN_DC_LUT_BLACK_OFFSET_RED + radeon_crtc->crtc_offset, 0);
- OUTREG(AVIVO_DC_LUTA_WHITE_OFFSET_BLUE + radeon_crtc->crtc_offset, 0x0000ffff);
- OUTREG(AVIVO_DC_LUTA_WHITE_OFFSET_GREEN + radeon_crtc->crtc_offset, 0x0000ffff);
- OUTREG(AVIVO_DC_LUTA_WHITE_OFFSET_RED + radeon_crtc->crtc_offset, 0x0000ffff);
- }
+ OUTREG(EVERGREEN_DC_LUT_WHITE_OFFSET_BLUE + radeon_crtc->crtc_offset, 0x0000ffff);
+ OUTREG(EVERGREEN_DC_LUT_WHITE_OFFSET_GREEN + radeon_crtc->crtc_offset, 0x0000ffff);
+ OUTREG(EVERGREEN_DC_LUT_WHITE_OFFSET_RED + radeon_crtc->crtc_offset, 0x0000ffff);
- PAL_SELECT(radeon_crtc->crtc_id);
+ OUTREG(EVERGREEN_DC_LUT_RW_MODE + radeon_crtc->crtc_offset, 0);
+ OUTREG(EVERGREEN_DC_LUT_WRITE_EN_MASK + radeon_crtc->crtc_offset, 0x00000007);
- if (IS_AVIVO_VARIANT) {
- OUTREG(AVIVO_DC_LUT_RW_MODE, 0);
- OUTREG(AVIVO_DC_LUT_WRITE_EN_MASK, 0x0000003f);
- }
+ for (i = 0; i < 256; i++) {
+ OUTREG(EVERGREEN_DC_LUT_RW_INDEX + radeon_crtc->crtc_offset, i);
+ OUTREG(EVERGREEN_DC_LUT_30_COLOR + radeon_crtc->crtc_offset,
+ (((radeon_crtc->lut_r[i]) << 20) |
+ ((radeon_crtc->lut_g[i]) << 10) |
+ (radeon_crtc->lut_b[i])));
+ }
+ } else {
+ if (IS_AVIVO_VARIANT) {
+ OUTREG(AVIVO_DC_LUTA_CONTROL + radeon_crtc->crtc_offset, 0);
- for (i = 0; i < 256; i++) {
- OUTPAL(i, radeon_crtc->lut_r[i], radeon_crtc->lut_g[i], radeon_crtc->lut_b[i]);
- }
+ OUTREG(AVIVO_DC_LUTA_BLACK_OFFSET_BLUE + radeon_crtc->crtc_offset, 0);
+ OUTREG(AVIVO_DC_LUTA_BLACK_OFFSET_GREEN + radeon_crtc->crtc_offset, 0);
+ OUTREG(AVIVO_DC_LUTA_BLACK_OFFSET_RED + radeon_crtc->crtc_offset, 0);
+
+ OUTREG(AVIVO_DC_LUTA_WHITE_OFFSET_BLUE + radeon_crtc->crtc_offset, 0x0000ffff);
+ OUTREG(AVIVO_DC_LUTA_WHITE_OFFSET_GREEN + radeon_crtc->crtc_offset, 0x0000ffff);
+ OUTREG(AVIVO_DC_LUTA_WHITE_OFFSET_RED + radeon_crtc->crtc_offset, 0x0000ffff);
+ }
+
+ PAL_SELECT(radeon_crtc->crtc_id);
+
+ if (IS_AVIVO_VARIANT) {
+ OUTREG(AVIVO_DC_LUT_RW_MODE, 0);
+ OUTREG(AVIVO_DC_LUT_WRITE_EN_MASK, 0x0000003f);
+ }
+
+ for (i = 0; i < 256; i++) {
+ OUTPAL(i, radeon_crtc->lut_r[i], radeon_crtc->lut_g[i], radeon_crtc->lut_b[i]);
+ }
- if (IS_AVIVO_VARIANT) {
- OUTREG(AVIVO_D1GRPH_LUT_SEL + radeon_crtc->crtc_offset, radeon_crtc->crtc_id);
+ if (IS_AVIVO_VARIANT)
+ OUTREG(AVIVO_D1GRPH_LUT_SEL + radeon_crtc->crtc_offset, radeon_crtc->crtc_id);
}
}
-
static void
radeon_crtc_gamma_set(xf86CrtcPtr crtc, uint16_t *red, uint16_t *green,
uint16_t *blue, int size)
{
RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private;
- ScrnInfoPtr pScrn = crtc->scrn;
- int i, j;
-
- if (pScrn->depth == 16) {
- for (i = 0; i < 64; i++) {
- if (i <= 31) {
- for (j = 0; j < 8; j++) {
- radeon_crtc->lut_r[i * 8 + j] = red[i] >> 6;
- radeon_crtc->lut_b[i * 8 + j] = blue[i] >> 6;
- }
- }
+ int i;
- for (j = 0; j < 4; j++) {
- radeon_crtc->lut_g[i * 4 + j] = green[i] >> 6;
- }
- }
- } else {
- for (i = 0; i < 256; i++) {
- radeon_crtc->lut_r[i] = red[i] >> 6;
- radeon_crtc->lut_g[i] = green[i] >> 6;
- radeon_crtc->lut_b[i] = blue[i] >> 6;
- }
+ for (i = 0; i < 256; i++) {
+ radeon_crtc->lut_r[i] = red[i] >> 6;
+ radeon_crtc->lut_g[i] = green[i] >> 6;
+ radeon_crtc->lut_b[i] = blue[i] >> 6;
}
radeon_crtc_load_lut(crtc);
@@ -413,7 +626,7 @@ radeon_crtc_shadow_allocate (xf86CrtcPtr crtc, int width, int height)
RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private;
unsigned long rotate_pitch;
unsigned long rotate_offset;
- int align = 4096, size;
+ int size;
int cpp = pScrn->bitsPerPixel / 8;
/* No rotation without accel */
@@ -432,7 +645,8 @@ radeon_crtc_shadow_allocate (xf86CrtcPtr crtc, int width, int height)
* setter for offscreen area locking in EXA currently. So, we just
* allocate offscreen memory and fake up a pixmap header for it.
*/
- rotate_offset = radeon_legacy_allocate_memory(pScrn, &radeon_crtc->crtc_rotate_mem, size, align);
+ rotate_offset = radeon_legacy_allocate_memory(pScrn, &radeon_crtc->crtc_rotate_mem,
+ size, RADEON_GPU_PAGE_SIZE, RADEON_GEM_DOMAIN_VRAM);
if (rotate_offset == 0)
return NULL;
@@ -512,7 +726,14 @@ radeon_crtc_set_origin(xf86CrtcPtr crtc, int x, int y)
RADEONInfoPtr info = RADEONPTR(pScrn);
unsigned char *RADEONMMIO = info->MMIO;
- if (IS_AVIVO_VARIANT) {
+
+ if (IS_DCE4_VARIANT) {
+ x &= ~3;
+ y &= ~1;
+ atombios_lock_crtc(info->atomBIOS, radeon_crtc->crtc_id, 1);
+ OUTREG(EVERGREEN_VIEWPORT_START + radeon_crtc->crtc_offset, (x << 16) | y);
+ atombios_lock_crtc(info->atomBIOS, radeon_crtc->crtc_id, 0);
+ } else if (IS_AVIVO_VARIANT) {
x &= ~3;
y &= ~1;
atombios_lock_crtc(info->atomBIOS, radeon_crtc->crtc_id, 1);
@@ -570,6 +791,10 @@ RADEONInitDispBandwidth(ScrnInfoPtr pScrn)
int pixel_bytes1 = info->CurrentLayout.pixel_bytes;
int pixel_bytes2 = info->CurrentLayout.pixel_bytes;
+ /* XXX fix me */
+ if (IS_DCE4_VARIANT)
+ return;
+
if (xf86_config->num_crtc == 2) {
if (xf86_config->crtc[1]->enabled &&
xf86_config->crtc[0]->enabled) {
@@ -602,6 +827,7 @@ Bool RADEONAllocateControllers(ScrnInfoPtr pScrn, int mask)
{
RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn);
RADEONInfoPtr info = RADEONPTR(pScrn);
+ int i;
if (!xf86ReturnOptValBool(info->Options, OPTION_NOACCEL, FALSE)) {
radeon_crtc_funcs.shadow_create = radeon_crtc_shadow_create;
@@ -629,6 +855,7 @@ Bool RADEONAllocateControllers(ScrnInfoPtr pScrn, int mask)
pRADEONEnt->Controller[0]->can_tile = 1;
else
pRADEONEnt->Controller[0]->can_tile = 0;
+ pRADEONEnt->Controller[0]->pll_id = -1;
}
if (mask & 2) {
@@ -642,18 +869,67 @@ Bool RADEONAllocateControllers(ScrnInfoPtr pScrn, int mask)
pRADEONEnt->Controller[1] = xnfcalloc(sizeof(RADEONCrtcPrivateRec), 1);
if (!pRADEONEnt->Controller[1])
{
- xfree(pRADEONEnt->Controller[0]);
+ free(pRADEONEnt->Controller[0]);
return FALSE;
}
pRADEONEnt->pCrtc[1]->driver_private = pRADEONEnt->Controller[1];
pRADEONEnt->Controller[1]->crtc_id = 1;
- pRADEONEnt->Controller[1]->crtc_offset = AVIVO_D2CRTC_H_TOTAL - AVIVO_D1CRTC_H_TOTAL;
+ if (IS_DCE4_VARIANT)
+ pRADEONEnt->Controller[1]->crtc_offset = EVERGREEN_CRTC1_REGISTER_OFFSET;
+ else
+ pRADEONEnt->Controller[1]->crtc_offset = AVIVO_D2CRTC_H_TOTAL - AVIVO_D1CRTC_H_TOTAL;
pRADEONEnt->Controller[1]->initialized = FALSE;
if (info->allowColorTiling)
pRADEONEnt->Controller[1]->can_tile = 1;
else
pRADEONEnt->Controller[1]->can_tile = 0;
+ pRADEONEnt->Controller[1]->pll_id = -1;
+ }
+
+ /* 6 crtcs on DCE4 chips */
+ if (IS_DCE4_VARIANT && ((mask & 3) == 3) && !IS_DCE41_VARIANT) {
+ for (i = 2; i < RADEON_MAX_CRTC; i++) {
+ pRADEONEnt->pCrtc[i] = xf86CrtcCreate(pScrn, &radeon_crtc_funcs);
+ if (!pRADEONEnt->pCrtc[i])
+ return FALSE;
+
+ pRADEONEnt->Controller[i] = xnfcalloc(sizeof(RADEONCrtcPrivateRec), 1);
+ if (!pRADEONEnt->Controller[i])
+ {
+ free(pRADEONEnt->Controller[i]);
+ return FALSE;
+ }
+
+ pRADEONEnt->pCrtc[i]->driver_private = pRADEONEnt->Controller[i];
+ pRADEONEnt->Controller[i]->crtc_id = i;
+ switch (i) {
+ case 0:
+ pRADEONEnt->Controller[i]->crtc_offset = EVERGREEN_CRTC0_REGISTER_OFFSET;
+ break;
+ case 1:
+ pRADEONEnt->Controller[i]->crtc_offset = EVERGREEN_CRTC1_REGISTER_OFFSET;
+ break;
+ case 2:
+ pRADEONEnt->Controller[i]->crtc_offset = EVERGREEN_CRTC2_REGISTER_OFFSET;
+ break;
+ case 3:
+ pRADEONEnt->Controller[i]->crtc_offset = EVERGREEN_CRTC3_REGISTER_OFFSET;
+ break;
+ case 4:
+ pRADEONEnt->Controller[i]->crtc_offset = EVERGREEN_CRTC4_REGISTER_OFFSET;
+ break;
+ case 5:
+ pRADEONEnt->Controller[i]->crtc_offset = EVERGREEN_CRTC5_REGISTER_OFFSET;
+ break;
+ }
+ pRADEONEnt->Controller[i]->initialized = FALSE;
+ if (info->allowColorTiling)
+ pRADEONEnt->Controller[i]->can_tile = 1;
+ else
+ pRADEONEnt->Controller[i]->can_tile = 0;
+ pRADEONEnt->Controller[i]->pll_id = -1;
+ }
}
return TRUE;