diff options
author | Matthieu Herrb <matthieu@cvs.openbsd.org> | 2012-01-25 21:33:36 +0000 |
---|---|---|
committer | Matthieu Herrb <matthieu@cvs.openbsd.org> | 2012-01-25 21:33:36 +0000 |
commit | 46e73e726a6a3567a4bb19b06c59826b9c6767d1 (patch) | |
tree | 8df52bebcc8ecbe55a8f8be1afae536b5fb46319 /driver/xf86-video-ati/src/radeon_crtc.c | |
parent | ee1cf1e0a2b9e0f7070a4d1efa6b426373e8ba67 (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.c | 464 |
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; |