91,6 → 91,87 |
return mclk; |
} |
|
#ifdef CONFIG_OF |
/* |
* Read XTAL (ref clock), SCLK and MCLK from Open Firmware device |
* tree. Hopefully, ATI OF driver is kind enough to fill these |
*/ |
static bool __devinit radeon_read_clocks_OF(struct drm_device *dev) |
{ |
struct radeon_device *rdev = dev->dev_private; |
struct device_node *dp = rdev->pdev->dev.of_node; |
const u32 *val; |
struct radeon_pll *p1pll = &rdev->clock.p1pll; |
struct radeon_pll *p2pll = &rdev->clock.p2pll; |
struct radeon_pll *spll = &rdev->clock.spll; |
struct radeon_pll *mpll = &rdev->clock.mpll; |
|
if (dp == NULL) |
return false; |
val = of_get_property(dp, "ATY,RefCLK", NULL); |
if (!val || !*val) { |
printk(KERN_WARNING "radeonfb: No ATY,RefCLK property !\n"); |
return false; |
} |
p1pll->reference_freq = p2pll->reference_freq = (*val) / 10; |
p1pll->reference_div = RREG32_PLL(RADEON_PPLL_REF_DIV) & 0x3ff; |
if (p1pll->reference_div < 2) |
p1pll->reference_div = 12; |
p2pll->reference_div = p1pll->reference_div; |
|
/* These aren't in the device-tree */ |
if (rdev->family >= CHIP_R420) { |
p1pll->pll_in_min = 100; |
p1pll->pll_in_max = 1350; |
p1pll->pll_out_min = 20000; |
p1pll->pll_out_max = 50000; |
p2pll->pll_in_min = 100; |
p2pll->pll_in_max = 1350; |
p2pll->pll_out_min = 20000; |
p2pll->pll_out_max = 50000; |
} else { |
p1pll->pll_in_min = 40; |
p1pll->pll_in_max = 500; |
p1pll->pll_out_min = 12500; |
p1pll->pll_out_max = 35000; |
p2pll->pll_in_min = 40; |
p2pll->pll_in_max = 500; |
p2pll->pll_out_min = 12500; |
p2pll->pll_out_max = 35000; |
} |
/* not sure what the max should be in all cases */ |
rdev->clock.max_pixel_clock = 35000; |
|
spll->reference_freq = mpll->reference_freq = p1pll->reference_freq; |
spll->reference_div = mpll->reference_div = |
RREG32_PLL(RADEON_M_SPLL_REF_FB_DIV) & |
RADEON_M_SPLL_REF_DIV_MASK; |
|
val = of_get_property(dp, "ATY,SCLK", NULL); |
if (val && *val) |
rdev->clock.default_sclk = (*val) / 10; |
else |
rdev->clock.default_sclk = |
radeon_legacy_get_engine_clock(rdev); |
|
val = of_get_property(dp, "ATY,MCLK", NULL); |
if (val && *val) |
rdev->clock.default_mclk = (*val) / 10; |
else |
rdev->clock.default_mclk = |
radeon_legacy_get_memory_clock(rdev); |
|
DRM_INFO("Using device-tree clock info\n"); |
|
return true; |
} |
#else |
static bool radeon_read_clocks_OF(struct drm_device *dev) |
{ |
return false; |
} |
#endif /* CONFIG_OF */ |
|
void radeon_get_clock_info(struct drm_device *dev) |
{ |
struct radeon_device *rdev = dev->dev_private; |
105,6 → 186,8 |
ret = radeon_atom_get_clock_info(dev); |
else |
ret = radeon_combios_get_clock_info(dev); |
if (!ret) |
ret = radeon_read_clocks_OF(dev); |
|
if (ret) { |
if (p1pll->reference_div < 2) { |
246,6 → 329,14 |
mpll->max_feedback_div = 0xff; |
mpll->best_vco = 0; |
|
if (!rdev->clock.default_sclk) |
rdev->clock.default_sclk = radeon_get_engine_clock(rdev); |
if ((!rdev->clock.default_mclk) && rdev->asic->get_memory_clock) |
rdev->clock.default_mclk = radeon_get_memory_clock(rdev); |
|
rdev->pm.current_sclk = rdev->clock.default_sclk; |
rdev->pm.current_mclk = rdev->clock.default_mclk; |
|
} |
|
/* 10 khz */ |
816,53 → 907,3 |
} |
} |
|
static void radeon_apply_clock_quirks(struct radeon_device *rdev) |
{ |
uint32_t tmp; |
|
/* XXX make sure engine is idle */ |
|
if (rdev->family < CHIP_RS600) { |
tmp = RREG32_PLL(RADEON_SCLK_CNTL); |
if (ASIC_IS_R300(rdev) || ASIC_IS_RV100(rdev)) |
tmp |= RADEON_SCLK_FORCE_CP | RADEON_SCLK_FORCE_VIP; |
if ((rdev->family == CHIP_RV250) |
|| (rdev->family == CHIP_RV280)) |
tmp |= |
RADEON_SCLK_FORCE_DISP1 | RADEON_SCLK_FORCE_DISP2; |
if ((rdev->family == CHIP_RV350) |
|| (rdev->family == CHIP_RV380)) |
tmp |= R300_SCLK_FORCE_VAP; |
if (rdev->family == CHIP_R420) |
tmp |= R300_SCLK_FORCE_PX | R300_SCLK_FORCE_TX; |
WREG32_PLL(RADEON_SCLK_CNTL, tmp); |
} else if (rdev->family < CHIP_R600) { |
tmp = RREG32_PLL(AVIVO_CP_DYN_CNTL); |
tmp |= AVIVO_CP_FORCEON; |
WREG32_PLL(AVIVO_CP_DYN_CNTL, tmp); |
|
tmp = RREG32_PLL(AVIVO_E2_DYN_CNTL); |
tmp |= AVIVO_E2_FORCEON; |
WREG32_PLL(AVIVO_E2_DYN_CNTL, tmp); |
|
tmp = RREG32_PLL(AVIVO_IDCT_DYN_CNTL); |
tmp |= AVIVO_IDCT_FORCEON; |
WREG32_PLL(AVIVO_IDCT_DYN_CNTL, tmp); |
} |
} |
|
int radeon_static_clocks_init(struct drm_device *dev) |
{ |
struct radeon_device *rdev = dev->dev_private; |
|
/* XXX make sure engine is idle */ |
|
if (radeon_dynclks != -1) { |
if (radeon_dynclks) { |
if (rdev->asic->set_clock_gating) |
radeon_set_clock_gating(rdev, 1); |
} |
} |
radeon_apply_clock_quirks(rdev); |
return 0; |
} |