26,7 → 26,7 |
#include <drm/drmP.h> |
#include <drm/drm_crtc_helper.h> |
#include <drm/radeon_drm.h> |
#include "radeon_fixed.h" |
#include <drm/drm_fixed.h> |
#include "radeon.h" |
#include "atom.h" |
|
272,7 → 272,7 |
if (!ref_div) |
return 1; |
|
vcoFreq = ((unsigned)ref_freq & fb_div) / ref_div; |
vcoFreq = ((unsigned)ref_freq * fb_div) / ref_div; |
|
/* |
* This is horribly crude: the VCO frequency range is divided into |
314,6 → 314,9 |
|
switch (mode) { |
case DRM_MODE_DPMS_ON: |
radeon_crtc->enabled = true; |
/* adjust pm to dpms changes BEFORE enabling crtcs */ |
radeon_pm_compute_clocks(rdev); |
if (radeon_crtc->crtc_id) |
WREG32_P(RADEON_CRTC2_GEN_CNTL, RADEON_CRTC2_EN, ~(RADEON_CRTC2_EN | mask)); |
else { |
335,6 → 338,9 |
RADEON_CRTC_DISP_REQ_EN_B)); |
WREG32_P(RADEON_CRTC_EXT_CNTL, mask, ~mask); |
} |
radeon_crtc->enabled = false; |
/* adjust pm to dpms changes AFTER disabling crtcs */ |
radeon_pm_compute_clocks(rdev); |
break; |
} |
} |
342,10 → 348,25 |
int radeon_crtc_set_base(struct drm_crtc *crtc, int x, int y, |
struct drm_framebuffer *old_fb) |
{ |
return radeon_crtc_do_set_base(crtc, old_fb, x, y, 0); |
} |
|
int radeon_crtc_set_base_atomic(struct drm_crtc *crtc, |
struct drm_framebuffer *fb, |
int x, int y, enum mode_set_atomic state) |
{ |
return radeon_crtc_do_set_base(crtc, fb, x, y, 1); |
} |
|
int radeon_crtc_do_set_base(struct drm_crtc *crtc, |
struct drm_framebuffer *fb, |
int x, int y, int atomic) |
{ |
struct drm_device *dev = crtc->dev; |
struct radeon_device *rdev = dev->dev_private; |
struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); |
struct radeon_framebuffer *radeon_fb; |
struct drm_framebuffer *target_fb; |
struct drm_gem_object *obj; |
struct radeon_bo *rbo; |
uint64_t base; |
356,16 → 377,23 |
uint32_t gen_cntl_reg, gen_cntl_val; |
int r; |
|
DRM_DEBUG("\n"); |
DRM_DEBUG_KMS("\n"); |
/* no fb bound */ |
if (!crtc->fb) { |
DRM_DEBUG("No FB bound\n"); |
if (!atomic && !crtc->fb) { |
DRM_DEBUG_KMS("No FB bound\n"); |
return 0; |
} |
|
if (atomic) { |
radeon_fb = to_radeon_framebuffer(fb); |
target_fb = fb; |
} |
else { |
radeon_fb = to_radeon_framebuffer(crtc->fb); |
target_fb = crtc->fb; |
} |
|
switch (crtc->fb->bits_per_pixel) { |
switch (target_fb->bits_per_pixel) { |
case 8: |
format = 2; |
break; |
387,7 → 415,7 |
|
/* Pin framebuffer & get tilling informations */ |
obj = radeon_fb->obj; |
rbo = obj->driver_private; |
rbo = gem_to_radeon_bo(obj); |
r = radeon_bo_reserve(rbo, false); |
if (unlikely(r != 0)) |
return r; |
409,13 → 437,13 |
|
crtc_offset_cntl = 0; |
|
pitch_pixels = crtc->fb->pitch / (crtc->fb->bits_per_pixel / 8); |
crtc_pitch = (((pitch_pixels * crtc->fb->bits_per_pixel) + |
((crtc->fb->bits_per_pixel * 8) - 1)) / |
(crtc->fb->bits_per_pixel * 8)); |
pitch_pixels = target_fb->pitch / (target_fb->bits_per_pixel / 8); |
crtc_pitch = (((pitch_pixels * target_fb->bits_per_pixel) + |
((target_fb->bits_per_pixel * 8) - 1)) / |
(target_fb->bits_per_pixel * 8)); |
crtc_pitch |= crtc_pitch << 16; |
|
|
crtc_offset_cntl |= RADEON_CRTC_GUI_TRIG_OFFSET_LEFT_EN; |
if (tiling_flags & RADEON_TILING_MACRO) { |
if (ASIC_IS_R300(rdev)) |
crtc_offset_cntl |= (R300_CRTC_X_Y_MODE_EN | |
437,7 → 465,7 |
crtc_tile_x0_y0 = x | (y << 16); |
base &= ~0x7ff; |
} else { |
int byteshift = crtc->fb->bits_per_pixel >> 4; |
int byteshift = target_fb->bits_per_pixel >> 4; |
int tile_addr = (((y >> 3) * pitch_pixels + x) >> (8 - byteshift)) << 11; |
base += tile_addr + ((x << byteshift) % 256) + ((y % 8) << 8); |
crtc_offset_cntl |= (y % 16); |
444,7 → 472,7 |
} |
} else { |
int offset = y * pitch_pixels + x; |
switch (crtc->fb->bits_per_pixel) { |
switch (target_fb->bits_per_pixel) { |
case 8: |
offset *= 1; |
break; |
474,6 → 502,7 |
gen_cntl_val = RREG32(gen_cntl_reg); |
gen_cntl_val &= ~(0xf << 8); |
gen_cntl_val |= (format << 8); |
gen_cntl_val &= ~RADEON_CRTC_VSTAT_MODE_MASK; |
WREG32(gen_cntl_reg, gen_cntl_val); |
|
crtc_offset = (u32)base; |
490,9 → 519,9 |
WREG32(RADEON_CRTC_OFFSET + radeon_crtc->crtc_offset, crtc_offset); |
WREG32(RADEON_CRTC_PITCH + radeon_crtc->crtc_offset, crtc_pitch); |
|
if (old_fb && old_fb != crtc->fb) { |
radeon_fb = to_radeon_framebuffer(old_fb); |
rbo = radeon_fb->obj->driver_private; |
if (!atomic && fb && fb != crtc->fb) { |
radeon_fb = to_radeon_framebuffer(fb); |
rbo = gem_to_radeon_bo(radeon_fb->obj); |
r = radeon_bo_reserve(rbo, false); |
if (unlikely(r != 0)) |
return r; |
522,7 → 551,7 |
uint32_t crtc_v_sync_strt_wid; |
bool is_tv = false; |
|
DRM_DEBUG("\n"); |
DRM_DEBUG_KMS("\n"); |
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { |
if (encoder->crtc == crtc) { |
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
603,6 → 632,10 |
? RADEON_CRTC2_INTERLACE_EN |
: 0)); |
|
/* rs4xx chips seem to like to have the crtc enabled when the timing is set */ |
if ((rdev->family == CHIP_RS400) || (rdev->family == CHIP_RS480)) |
crtc2_gen_cntl |= RADEON_CRTC2_EN; |
|
disp2_merge_cntl = RREG32(RADEON_DISP2_MERGE_CNTL); |
disp2_merge_cntl &= ~RADEON_DISP2_RGB_OFFSET_EN; |
|
630,6 → 663,10 |
? RADEON_CRTC_INTERLACE_EN |
: 0)); |
|
/* rs4xx chips seem to like to have the crtc enabled when the timing is set */ |
if ((rdev->family == CHIP_RS400) || (rdev->family == CHIP_RS480)) |
crtc_gen_cntl |= RADEON_CRTC_EN; |
|
crtc_ext_cntl = RREG32(RADEON_CRTC_EXT_CNTL); |
crtc_ext_cntl |= (RADEON_XCRT_CNT_EN | |
RADEON_CRTC_VSYNC_DIS | |
703,10 → 740,6 |
pll = &rdev->clock.p1pll; |
|
pll->flags = RADEON_PLL_LEGACY; |
if (radeon_new_pll == 1) |
pll->algo = PLL_ALGO_NEW; |
else |
pll->algo = PLL_ALGO_LEGACY; |
|
if (mode->clock > 200000) /* range limits??? */ |
pll->flags |= RADEON_PLL_PREFER_HIGH_FB_DIV; |
743,10 → 776,10 |
} |
} |
|
DRM_DEBUG("\n"); |
DRM_DEBUG_KMS("\n"); |
|
if (!use_bios_divs) { |
radeon_compute_pll(pll, mode->clock, |
radeon_compute_pll_legacy(pll, mode->clock, |
&freq, &feedback_div, &frac_fb_div, |
&reference_div, &post_divider); |
|
758,7 → 791,7 |
if (!post_div->divider) |
post_div = &post_divs[0]; |
|
DRM_DEBUG("dc=%u, fd=%d, rd=%d, pd=%d\n", |
DRM_DEBUG_KMS("dc=%u, fd=%d, rd=%d, pd=%d\n", |
(unsigned)freq, |
feedback_div, |
reference_div, |
827,12 → 860,12 |
| RADEON_P2PLL_SLEEP |
| RADEON_P2PLL_ATOMIC_UPDATE_EN)); |
|
DRM_DEBUG("Wrote2: 0x%08x 0x%08x 0x%08x (0x%08x)\n", |
DRM_DEBUG_KMS("Wrote2: 0x%08x 0x%08x 0x%08x (0x%08x)\n", |
(unsigned)pll_ref_div, |
(unsigned)pll_fb_post_div, |
(unsigned)htotal_cntl, |
RREG32_PLL(RADEON_P2PLL_CNTL)); |
DRM_DEBUG("Wrote2: rd=%u, fd=%u, pd=%u\n", |
DRM_DEBUG_KMS("Wrote2: rd=%u, fd=%u, pd=%u\n", |
(unsigned)pll_ref_div & RADEON_P2PLL_REF_DIV_MASK, |
(unsigned)pll_fb_post_div & RADEON_P2PLL_FB0_DIV_MASK, |
(unsigned)((pll_fb_post_div & |
856,7 → 889,7 |
} |
|
if (rdev->flags & RADEON_IS_MOBILITY) { |
/* A temporal workaround for the occational blanking on certain laptop panels. |
/* A temporal workaround for the occasional blanking on certain laptop panels. |
This appears to related to the PLL divider registers (fail to lock?). |
It occurs even when all dividers are the same with their old settings. |
In this case we really don't need to fiddle with PLL registers. |
933,12 → 966,12 |
| RADEON_PPLL_ATOMIC_UPDATE_EN |
| RADEON_PPLL_VGA_ATOMIC_UPDATE_EN)); |
|
DRM_DEBUG("Wrote: 0x%08x 0x%08x 0x%08x (0x%08x)\n", |
DRM_DEBUG_KMS("Wrote: 0x%08x 0x%08x 0x%08x (0x%08x)\n", |
pll_ref_div, |
pll_fb_post_div, |
(unsigned)htotal_cntl, |
RREG32_PLL(RADEON_PPLL_CNTL)); |
DRM_DEBUG("Wrote: rd=%d, fd=%d, pd=%d\n", |
DRM_DEBUG_KMS("Wrote: rd=%d, fd=%d, pd=%d\n", |
pll_ref_div & RADEON_PPLL_REF_DIV_MASK, |
pll_fb_post_div & RADEON_PPLL_FB3_DIV_MASK, |
(pll_fb_post_div & RADEON_PPLL_POST3_DIV_MASK) >> 16); |
958,6 → 991,12 |
struct drm_display_mode *mode, |
struct drm_display_mode *adjusted_mode) |
{ |
struct drm_device *dev = crtc->dev; |
struct radeon_device *rdev = dev->dev_private; |
|
/* adjust pm to upcoming mode change */ |
radeon_pm_compute_clocks(rdev); |
|
if (!radeon_crtc_scaling_mode_fixup(crtc, mode, adjusted_mode)) |
return false; |
return true; |
1020,6 → 1059,7 |
.mode_fixup = radeon_crtc_mode_fixup, |
.mode_set = radeon_crtc_mode_set, |
.mode_set_base = radeon_crtc_set_base, |
.mode_set_base_atomic = radeon_crtc_set_base_atomic, |
.prepare = radeon_crtc_prepare, |
.commit = radeon_crtc_commit, |
.load_lut = radeon_crtc_load_lut, |