* malloc an array of pointers to hold active crt info, mode, limits, etc.
Plan to move gRegister into the crt struct at some point. * Few style fixes * Added function to probe edid of attached monitors and populate CRT info * Disable VGA control modifications temporarly while I hammer out some issues. * Fix radeon card model checks (bitwise & is not |) * Finally fix? blanking start / end calculations using porch * Use mask for setting sync polarity * Add overscan (8 pixels is default?) * Disable PLLSet/Power for the moment as it seems to muck things up. * is_mode_supported now validates if a mode line is with the monitors h/v sync frequencies (how does is_mode_supported know what crt the os wants?) * PLL Write/Read don't actually use the PLL Write/Read functions (thanks AMD!) * Added better PLL legacy (r600-r610) support * Consistantly give no DCCG on legacy cards. * Tracing! git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@42191 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
58ddd30b23
commit
d1d65a79cb
@ -34,6 +34,7 @@ extern "C" void _sPrintf(const char *format, ...);
|
||||
|
||||
struct accelerant_info *gInfo;
|
||||
struct register_info *gRegister;
|
||||
crt_info *gCRT[MAX_CRT];
|
||||
|
||||
|
||||
class AreaCloner {
|
||||
@ -100,9 +101,18 @@ init_common(int device, bool isClone)
|
||||
if (gInfo == NULL || gRegister == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
for (uint32 id = 0; id < MAX_CRT; id++) {
|
||||
gCRT[id] = (crt_info *)malloc(sizeof(crt_info));
|
||||
if (gCRT[id] == NULL)
|
||||
return B_NO_MEMORY;
|
||||
}
|
||||
|
||||
memset(gInfo, 0, sizeof(accelerant_info));
|
||||
memset(gRegister, 0, sizeof(register_info));
|
||||
|
||||
for (uint32 id = 0; id < MAX_CRT; id++)
|
||||
memset(gCRT[id], 0, sizeof(crt_info));
|
||||
|
||||
gInfo->is_clone = isClone;
|
||||
gInfo->device = device;
|
||||
|
||||
@ -167,6 +177,9 @@ uninit_common(void)
|
||||
|
||||
free(gInfo);
|
||||
free(gRegister);
|
||||
|
||||
for (uint32 id = 0; id < MAX_CRT; id++)
|
||||
free(gCRT[id]);
|
||||
}
|
||||
|
||||
|
||||
@ -177,7 +190,7 @@ init_registers(uint8 crtid)
|
||||
radeon_shared_info &info = *gInfo->shared_info;
|
||||
|
||||
if (info.device_chipset >= RADEON_R800) {
|
||||
uint16_t offset = 0;
|
||||
uint32 offset = 0;
|
||||
|
||||
// AMD Eyefinity on Evergreen GPUs
|
||||
if (crtid == 1) {
|
||||
|
@ -18,6 +18,10 @@
|
||||
#include <edid.h>
|
||||
|
||||
|
||||
#define MAX_CRT 6
|
||||
// eyefinity limit
|
||||
|
||||
|
||||
struct accelerant_info {
|
||||
vuint8 *regs;
|
||||
area_id regs_area;
|
||||
@ -77,6 +81,14 @@ struct register_info {
|
||||
};
|
||||
|
||||
|
||||
typedef struct {
|
||||
uint32 vfreq_max;
|
||||
uint32 vfreq_min;
|
||||
uint32 hfreq_max;
|
||||
uint32 hfreq_min;
|
||||
} crt_info;
|
||||
|
||||
|
||||
#define HEAD_MODE_A_ANALOG 0x01
|
||||
#define HEAD_MODE_B_DIGITAL 0x02
|
||||
#define HEAD_MODE_CLONE 0x03
|
||||
@ -89,8 +101,10 @@ struct register_info {
|
||||
#define PLL 0x4 // PLL calls
|
||||
#define MC 0x5 // Memory Controler calls
|
||||
|
||||
|
||||
extern accelerant_info *gInfo;
|
||||
extern register_info *gRegister;
|
||||
extern crt_info *gCRT[MAX_CRT];
|
||||
|
||||
|
||||
status_t init_registers(uint8 crtid);
|
||||
@ -121,12 +135,12 @@ _read32MC(uint32 offset)
|
||||
_write32(RS600_MC_INDEX, ((offset & RS600_MC_INDEX_ADDR_MASK)
|
||||
| RS600_MC_INDEX_CITF_ARB0));
|
||||
return _read32(RS600_MC_DATA);
|
||||
} else if (info.device_chipset == (RADEON_R600 & 0x90)
|
||||
|| info.device_chipset == (RADEON_R700 & 0x40)) {
|
||||
} else if (info.device_chipset == (RADEON_R600 | 0x90)
|
||||
|| info.device_chipset == (RADEON_R700 | 0x40)) {
|
||||
_write32(RS690_MC_INDEX, (offset & RS690_MC_INDEX_ADDR_MASK));
|
||||
return _read32(RS690_MC_DATA);
|
||||
} else if (info.device_chipset == (RADEON_R700 & 0x80)
|
||||
|| info.device_chipset == (RADEON_R800 & 0x80)) {
|
||||
} else if (info.device_chipset == (RADEON_R700 | 0x80)
|
||||
|| info.device_chipset == (RADEON_R800 | 0x80)) {
|
||||
_write32(RS780_MC_INDEX, offset & RS780_MC_INDEX_ADDR_MASK);
|
||||
return _read32(RS780_MC_DATA);
|
||||
}
|
||||
@ -145,14 +159,14 @@ _write32MC(uint32 offset, uint32 data)
|
||||
_write32(RS600_MC_INDEX, ((offset & RS600_MC_INDEX_ADDR_MASK)
|
||||
| RS600_MC_INDEX_CITF_ARB0 | RS600_MC_INDEX_WR_EN));
|
||||
_write32(RS600_MC_DATA, data);
|
||||
} else if (info.device_chipset == (RADEON_R600 & 0x90)
|
||||
|| info.device_chipset == (RADEON_R700 & 0x40)) {
|
||||
} else if (info.device_chipset == (RADEON_R600 | 0x90)
|
||||
|| info.device_chipset == (RADEON_R700 | 0x40)) {
|
||||
_write32(RS690_MC_INDEX, ((offset & RS690_MC_INDEX_ADDR_MASK)
|
||||
| RS690_MC_INDEX_WR_EN));
|
||||
_write32(RS690_MC_DATA, data);
|
||||
_write32(RS690_MC_INDEX, RS690_MC_INDEX_WR_ACK);
|
||||
} else if (info.device_chipset == (RADEON_R700 & 0x80)
|
||||
|| info.device_chipset == (RADEON_R800 & 0x80)) {
|
||||
} else if (info.device_chipset == (RADEON_R700 | 0x80)
|
||||
|| info.device_chipset == (RADEON_R800 | 0x80)) {
|
||||
_write32(RS780_MC_INDEX, ((offset & RS780_MC_INDEX_ADDR_MASK)
|
||||
| RS780_MC_INDEX_WR_EN));
|
||||
_write32(RS780_MC_DATA, data);
|
||||
@ -187,7 +201,8 @@ Read32(uint32 subsystem, uint32 offset)
|
||||
case CRT:
|
||||
return _read32(offset);
|
||||
case PLL:
|
||||
return _read32PLL(offset);
|
||||
return _read32(offset);
|
||||
//return _read32PLL(offset);
|
||||
case MC:
|
||||
return _read32MC(offset);
|
||||
};
|
||||
@ -207,7 +222,8 @@ Write32(uint32 subsystem, uint32 offset, uint32 value)
|
||||
_write32(offset, value);
|
||||
return;
|
||||
case PLL:
|
||||
_write32PLL(offset, value);
|
||||
_write32(offset, value);
|
||||
//_write32PLL(offset, value);
|
||||
return;
|
||||
case MC:
|
||||
_write32MC(offset, value);
|
||||
@ -230,7 +246,8 @@ Write32Mask(uint32 subsystem, uint32 offset, uint32 value, uint32 mask)
|
||||
temp = _read32(offset);
|
||||
break;
|
||||
case PLL:
|
||||
temp = _read32PLL(offset);
|
||||
temp = _read32(offset);
|
||||
//temp = _read32PLL(offset);
|
||||
break;
|
||||
case MC:
|
||||
temp = _read32MC(offset);
|
||||
@ -251,7 +268,8 @@ Write32Mask(uint32 subsystem, uint32 offset, uint32 value, uint32 mask)
|
||||
_write32(offset, temp);
|
||||
return;
|
||||
case PLL:
|
||||
_write32PLL(offset, temp);
|
||||
_write32(offset, temp);
|
||||
//_write32PLL(offset, temp);
|
||||
return;
|
||||
case MC:
|
||||
_write32MC(offset, temp);
|
||||
|
@ -38,6 +38,8 @@ create_mode_list(void)
|
||||
const color_space kRadeonHDSpaces[] = {B_RGB32_LITTLE, B_RGB24_LITTLE,
|
||||
B_RGB16_LITTLE, B_RGB15_LITTLE, B_CMAP8};
|
||||
|
||||
detect_crt_ranges();
|
||||
|
||||
gInfo->mode_list_area = create_display_modes("radeon HD modes",
|
||||
gInfo->shared_info->has_edid ? &gInfo->shared_info->edid_info : NULL,
|
||||
NULL, 0, kRadeonHDSpaces,
|
||||
@ -148,12 +150,14 @@ CardFBSet(display_mode *mode)
|
||||
|
||||
get_color_space_format(*mode, colorMode, bytesPerRow, bitsPerPixel);
|
||||
|
||||
#if 0
|
||||
// Disable VGA mode to enable Radeon extended registers
|
||||
Write32Mask(VGA, VGA_RENDER_CONTROL, 0, 0x00030000);
|
||||
Write32Mask(VGA, VGA_MODE_CONTROL, 0, 0x00000030);
|
||||
Write32Mask(VGA, VGA_HDP_CONTROL, 0x00010010, 0x00010010);
|
||||
Write32Mask(VGA, gRegister->vgaControl, 0, D1VGA_MODE_ENABLE
|
||||
| D1VGA_TIMING_SELECT | D1VGA_SYNC_POLARITY_SELECT);
|
||||
#endif
|
||||
|
||||
// disable R/B swap, disable tiling, disable 16bit alpha, etc.
|
||||
Write32Mask(CRT, gRegister->grphEnable, 1, 0x00000001);
|
||||
@ -190,7 +194,7 @@ CardFBSet(display_mode *mode)
|
||||
uint64_t fbAddress = gInfo->shared_info->frame_buffer_phys;
|
||||
|
||||
// Tell GPU which frame buffer address to draw from
|
||||
if (gInfo->shared_info->device_chipset >= (uint16)(RADEON_R700 & 0x70)) {
|
||||
if (gInfo->shared_info->device_chipset >= (RADEON_R700 | 0x70)) {
|
||||
Write32(CRT, gRegister->grphPrimarySurfaceAddrHigh,
|
||||
(fbAddress >> 32) & 0xf);
|
||||
Write32(CRT, gRegister->grphSecondarySurfaceAddrHigh,
|
||||
@ -235,14 +239,15 @@ CardModeSet(display_mode *mode)
|
||||
Write32(CRT, gRegister->crtHTotal,
|
||||
displayTiming.h_total - 1);
|
||||
|
||||
#if 0
|
||||
// determine blanking based on passed modeline
|
||||
uint16 blankStart = displayTiming.h_display;
|
||||
uint16 blankEnd = displayTiming.h_total;
|
||||
// Calculate blanking
|
||||
uint16 frontPorch = displayTiming.h_sync_start - displayTiming.h_display;
|
||||
uint16 backPorch = displayTiming.h_total - displayTiming.h_sync_end;
|
||||
|
||||
uint16 blankStart = frontPorch - OVERSCAN;
|
||||
uint16 blankEnd = backPorch;
|
||||
|
||||
Write32(CRT, gRegister->crtHBlank,
|
||||
blankStart | (blankEnd << 16));
|
||||
#endif
|
||||
|
||||
Write32(CRT, gRegister->crtHSync,
|
||||
(displayTiming.h_sync_end - displayTiming.h_sync_start) << 16);
|
||||
@ -255,13 +260,14 @@ CardModeSet(display_mode *mode)
|
||||
Write32(CRT, gRegister->crtVTotal,
|
||||
displayTiming.v_total - 1);
|
||||
|
||||
#if 0
|
||||
blankStart = displayTiming.v_display;
|
||||
blankEnd = displayTiming.v_total;
|
||||
frontPorch = displayTiming.v_sync_start - displayTiming.v_display;
|
||||
backPorch = displayTiming.v_total - displayTiming.v_sync_end;
|
||||
|
||||
blankStart = frontPorch - OVERSCAN;
|
||||
blankEnd = backPorch;
|
||||
|
||||
Write32(CRT, gRegister->crtVBlank,
|
||||
blankStart | (blankEnd << 16));
|
||||
#endif
|
||||
|
||||
// Set Interlace if specified within mode line
|
||||
if (displayTiming.flags & B_TIMING_INTERLACED) {
|
||||
@ -276,9 +282,8 @@ CardModeSet(display_mode *mode)
|
||||
(displayTiming.v_sync_end - displayTiming.v_sync_start) << 16);
|
||||
|
||||
// set flag for neg. V sync. M76 Register Reference Guide 2-258
|
||||
// we don't need a mask here as this is the only param for Vertical
|
||||
Write32(CRT, gRegister->crtVPolarity,
|
||||
displayTiming.flags & B_POSITIVE_VSYNC ? 0 : 1);
|
||||
Write32Mask(CRT, gRegister->crtVPolarity,
|
||||
displayTiming.flags & B_POSITIVE_VSYNC ? 0 : 1, 0x1);
|
||||
|
||||
/* set D1CRTC_HORZ_COUNT_BY2_EN to 0;
|
||||
should only be set to 1 on 30bpp DVI modes
|
||||
@ -296,9 +301,9 @@ CardModeScale(display_mode *mode)
|
||||
|
||||
// For now, no overscan support
|
||||
Write32(CRT, D1MODE_EXT_OVERSCAN_LEFT_RIGHT,
|
||||
(0 << 16) | 0); // LEFT | RIGHT
|
||||
(OVERSCAN << 16) | OVERSCAN); // LEFT | RIGHT
|
||||
Write32(CRT, D1MODE_EXT_OVERSCAN_TOP_BOTTOM,
|
||||
(0 << 16) | 0); // TOP | BOTTOM
|
||||
(OVERSCAN << 16) | OVERSCAN); // TOP | BOTTOM
|
||||
|
||||
// No scaling
|
||||
Write32(CRT, gRegister->sclUpdate, (1<<16));// Lock
|
||||
@ -336,12 +341,21 @@ radeon_set_display_mode(display_mode *mode)
|
||||
|
||||
CardBlankSet(true);
|
||||
CardFBSet(mode);
|
||||
CardBlankSet(false);
|
||||
CardModeSet(mode);
|
||||
CardModeScale(mode);
|
||||
|
||||
#if 0
|
||||
PLLSet(0, mode->timing.pixel_clock);
|
||||
PLLPower(0, RHD_POWER_ON);
|
||||
DACPower(0, RHD_POWER_ON);
|
||||
CardBlankSet(false);
|
||||
#endif
|
||||
|
||||
// ensure graphics are enabled and powered on
|
||||
Write32Mask(CRT, D1GRPH_ENABLE, 0x00000001, 0x00000001);
|
||||
snooze(2);
|
||||
Write32Mask(CRT, D1CRTC_CONTROL, 0, 0x01000000); /* enable read requests */
|
||||
Write32Mask(CRT, D1CRTC_CONTROL, 1, 1);
|
||||
|
||||
int32 crtstatus = Read32(CRT, D1CRTC_STATUS);
|
||||
TRACE("CRT0 Status: 0x%X\n", crtstatus);
|
||||
@ -405,22 +419,47 @@ radeon_get_pixel_clock_limits(display_mode *mode, uint32 *_low, uint32 *_high)
|
||||
bool
|
||||
is_mode_supported(display_mode *mode)
|
||||
{
|
||||
TRACE("MODE: %d ; %d %d %d %d ; %d %d %d %d\n",
|
||||
mode->timing.pixel_clock, mode->timing.h_display,
|
||||
mode->timing.h_sync_start, mode->timing.h_sync_end,
|
||||
mode->timing.h_total, mode->timing.v_display,
|
||||
mode->timing.v_sync_start, mode->timing.v_sync_end,
|
||||
mode->timing.v_total);
|
||||
|
||||
// Validate modeline is within a sane range
|
||||
if (is_mode_sane(mode) != B_OK)
|
||||
return false;
|
||||
|
||||
// TODO : Look at min and max monitor freqs and verify selected
|
||||
// mode is within tolerances.
|
||||
#if 0
|
||||
int crtid = 0;
|
||||
uint32 crtid = 0;
|
||||
|
||||
edid1_detailed_monitor *monitor
|
||||
= &gInfo->shared_info->edid_info.detailed_monitor[crtid + 1];
|
||||
edid1_monitor_range& range = monitor->data.monitor_range;
|
||||
// if we have edid info, check frequency adginst crt reported valid ranges
|
||||
if (gInfo->shared_info->has_edid) {
|
||||
|
||||
TRACE("%s CRT Min/Max H %d/%d; CRT Min/Max V %d/%d\n", __func__,
|
||||
range.min_h, range.max_h, range.min_v, range.max_v);
|
||||
#endif
|
||||
uint32 hfreq = mode->timing.pixel_clock / mode->timing.h_total;
|
||||
if (hfreq > gCRT[crtid]->hfreq_max + 1
|
||||
|| hfreq < gCRT[crtid]->hfreq_min - 1) {
|
||||
TRACE("!!! hfreq : %d , hfreq_min : %d, hfreq_max : %d\n",
|
||||
hfreq, gCRT[crtid]->hfreq_min, gCRT[crtid]->hfreq_max);
|
||||
TRACE("!!! %dx%d falls outside of CRT %d's valid "
|
||||
"horizontal range.\n", mode->timing.h_display,
|
||||
mode->timing.v_display, crtid);
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32 vfreq = mode->timing.pixel_clock / ((mode->timing.v_total
|
||||
* mode->timing.h_total) / 1000);
|
||||
|
||||
if (vfreq > gCRT[crtid]->vfreq_max + 1
|
||||
|| vfreq < gCRT[crtid]->vfreq_min - 1) {
|
||||
TRACE("!!! vfreq : %d , vfreq_min : %d, vfreq_max : %d\n",
|
||||
vfreq, gCRT[crtid]->vfreq_min, gCRT[crtid]->vfreq_max);
|
||||
TRACE("!!! %dx%d falls outside of CRT %d's valid vertical range\n",
|
||||
mode->timing.h_display, mode->timing.v_display, crtid);
|
||||
return false;
|
||||
}
|
||||
TRACE("%dx%d is within CRT %d's valid frequency range\n",
|
||||
mode->timing.h_display, mode->timing.v_display, crtid);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -478,3 +517,34 @@ is_mode_sane(display_mode *mode)
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
// TODO : Move to a new "monitors.c" file
|
||||
status_t
|
||||
detect_crt_ranges()
|
||||
{
|
||||
edid1_info *edid = &gInfo->shared_info->edid_info;
|
||||
|
||||
int crtid = 0;
|
||||
// edid indexes are not in order
|
||||
|
||||
for (uint32 index = 0; index < MAX_CRT; index++) {
|
||||
|
||||
edid1_detailed_monitor *monitor
|
||||
= &edid->detailed_monitor[index];
|
||||
|
||||
if (monitor->monitor_desc_type
|
||||
== EDID1_MONITOR_RANGES) {
|
||||
edid1_monitor_range range = monitor->data.monitor_range;
|
||||
gCRT[crtid]->vfreq_min = range.min_v; /* in Hz */
|
||||
gCRT[crtid]->vfreq_max = range.max_v;
|
||||
gCRT[crtid]->hfreq_min = range.min_h; /* in kHz */
|
||||
gCRT[crtid]->hfreq_max = range.max_h;
|
||||
TRACE("CRT %d : v_min %d : v_max %d : h_min %d : h_max %d\n",
|
||||
crtid, gCRT[crtid]->vfreq_min, gCRT[crtid]->vfreq_max,
|
||||
gCRT[crtid]->hfreq_min, gCRT[crtid]->hfreq_max);
|
||||
crtid++;
|
||||
}
|
||||
|
||||
}
|
||||
return B_OK;
|
||||
}
|
||||
|
@ -21,7 +21,10 @@
|
||||
#define FMT1_REG_OFFSET 0x0000
|
||||
#define FMT2_REG_OFFSET 0x800
|
||||
|
||||
#define OVERSCAN 8
|
||||
// default overscan? Applied to all sides
|
||||
|
||||
status_t detect_crt_ranges();
|
||||
status_t create_mode_list(void);
|
||||
bool is_mode_supported(display_mode* mode);
|
||||
status_t is_mode_sane(display_mode *mode);
|
||||
|
@ -134,7 +134,6 @@ PLLCalculate(uint32 pixelClock, uint16 *reference, uint16 *feedback,
|
||||
status_t
|
||||
PLLPower(uint8 pllIndex, int command)
|
||||
{
|
||||
|
||||
uint16 pllControlReg = (pllIndex == 1) ? P2PLL_CNTL : P1PLL_CNTL;
|
||||
|
||||
bool hasDccg = DCCGCLKAvailable(pllIndex);
|
||||
@ -179,6 +178,8 @@ PLLPower(uint8 pllIndex, int command)
|
||||
default:
|
||||
TRACE("%s: PLL Power Shutdown\n", __func__);
|
||||
|
||||
radeon_shared_info &info = *gInfo->shared_info;
|
||||
|
||||
if (hasDccg)
|
||||
DCCGCLKSet(pllIndex, RV620_DCCGCLK_RELEASE);
|
||||
|
||||
@ -186,20 +187,22 @@ PLLPower(uint8 pllIndex, int command)
|
||||
// Reset
|
||||
snooze(2);
|
||||
|
||||
// Sometimes we have to keep an unused PLL running. Xorg Bug #18016
|
||||
if ((Read32(PLL, RV620_EXT1_DIFF_POST_DIV_CNTL)
|
||||
& RV62_EXT1_DIFF_DRIVER_ENABLE) == 0) {
|
||||
Write32Mask(PLL, pllControlReg, 0x02, 0x02);
|
||||
// Power Down
|
||||
} else {
|
||||
TRACE("%s: PHYA differential clock driver not disabled\n",
|
||||
__func__);
|
||||
if (info.device_chipset >= (RADEON_R600 | 0x20)) {
|
||||
// Sometimes we have to keep an unused PLL running. X Bug #18016
|
||||
if ((Read32(PLL, RV620_EXT1_DIFF_POST_DIV_CNTL)
|
||||
& RV62_EXT1_DIFF_DRIVER_ENABLE) == 0) {
|
||||
Write32Mask(PLL, pllControlReg, 0x02, 0x02);
|
||||
// Power Down
|
||||
} else {
|
||||
TRACE("%s: PHYA differential clock driver not disabled\n",
|
||||
__func__);
|
||||
}
|
||||
|
||||
snooze(200);
|
||||
|
||||
Write32Mask(PLL, pllControlReg, 0x2000, 0x2000);
|
||||
// Reset anti-glitch?
|
||||
}
|
||||
|
||||
snooze(200);
|
||||
|
||||
Write32Mask(PLL, pllControlReg, 0x2000, 0x2000);
|
||||
// Reset anti-glitch?
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
@ -209,22 +212,121 @@ PLLPower(uint8 pllIndex, int command)
|
||||
status_t
|
||||
PLLSet(uint8 pllIndex, uint32 pixelClock)
|
||||
{
|
||||
|
||||
TRACE("%s: enter to set pixel clock %d\n", __func__,
|
||||
(int)pixelClock);
|
||||
|
||||
radeon_shared_info &info = *gInfo->shared_info;
|
||||
|
||||
bool hasDccg = DCCGCLKAvailable(pllIndex);
|
||||
|
||||
TRACE("%s: card has DCCG = %c\n", __func__, hasDccg ? 'y' : 'n');
|
||||
|
||||
uint16 reference = 0;
|
||||
uint16 feedback = 0;
|
||||
uint16 post = 0;
|
||||
|
||||
PLLCalculate(pixelClock, &reference, &feedback, &post);
|
||||
|
||||
if (info.device_chipset >= (RADEON_R600 | 0x20)) {
|
||||
TRACE("%s : setting pixel clock %d on r620+\n", __func__,
|
||||
(int)pixelClock);
|
||||
PLLSetLowR620(pllIndex, pixelClock, reference,
|
||||
feedback, post);
|
||||
} else if (info.device_chipset < (RADEON_R600 | 0x20)) {
|
||||
TRACE("%s : setting pixel clock %d on r600-r610\n", __func__,
|
||||
(int)pixelClock);
|
||||
PLLSetLowLegacy(pllIndex, pixelClock, reference,
|
||||
feedback, post);
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PLLSetLowLegacy(uint8 pllIndex, uint32 pixelClock, uint16 reference,
|
||||
uint16 feedback, uint16 post)
|
||||
{
|
||||
uint32 feedbackTemp = feedback << 16;
|
||||
uint32 referenceTemp = reference;
|
||||
|
||||
radeon_shared_info &info = *gInfo->shared_info;
|
||||
|
||||
if (info.device_chipset == RADEON_R600)
|
||||
feedbackTemp |= 0x00000030;
|
||||
else if (info.device_chipset > RADEON_R600) {
|
||||
if (feedback <= 0x24)
|
||||
feedbackTemp |= 0x00000030;
|
||||
else if (feedback <= 0x3F)
|
||||
feedbackTemp |= 0x00000020;
|
||||
} else
|
||||
feedbackTemp |= Read32(PLL, EXT1_PPLL_FB_DIV) & 0x00000030;
|
||||
|
||||
uint32 postTemp = Read32(PLL, EXT1_PPLL_POST_DIV) & ~0x0000007F;
|
||||
postTemp |= post & 0x0000007F;
|
||||
|
||||
uint32 control;
|
||||
if (info.device_chipset == RADEON_R600)
|
||||
control = 0x01130704;
|
||||
else
|
||||
PLLControlTable(RV610PLLControl, feedback);
|
||||
|
||||
if (!control)
|
||||
control = Read32(PLL, EXT1_PPLL_CNTL);
|
||||
|
||||
Write32Mask(PLL, P1PLL_INT_SS_CNTL, 0, 0x00000001);
|
||||
// Disable Spread Spectrum
|
||||
|
||||
Write32(PLL, EXT1_PPLL_REF_DIV_SRC, 0x01); /* XTAL */
|
||||
Write32(PLL, EXT1_PPLL_POST_DIV_SRC, 0x00); /* source = reference */
|
||||
|
||||
Write32(PLL, EXT1_PPLL_UPDATE_LOCK, 0x01); /* lock */
|
||||
|
||||
Write32(PLL, EXT1_PPLL_REF_DIV, referenceTemp);
|
||||
Write32(PLL, EXT1_PPLL_FB_DIV, feedbackTemp);
|
||||
Write32(PLL, EXT1_PPLL_POST_DIV, postTemp);
|
||||
Write32(PLL, EXT1_PPLL_CNTL, control);
|
||||
|
||||
Write32Mask(PLL, EXT1_PPLL_UPDATE_CNTL, 0x00010000, 0x00010000);
|
||||
// No autoreset
|
||||
Write32Mask(PLL, P1PLL_CNTL, 0, 0x04);
|
||||
// Don't bypass calibration
|
||||
|
||||
/* We need to reset the anti glitch logic */
|
||||
Write32Mask(PLL, P1PLL_CNTL, 0, 0x00000002);
|
||||
// Power up
|
||||
|
||||
/* reset anti glitch logic */
|
||||
Write32Mask(PLL, P1PLL_CNTL, 0x00002000, 0x00002000);
|
||||
snooze(2);
|
||||
Write32Mask(PLL, P1PLL_CNTL, 0, 0x00002000);
|
||||
|
||||
/* powerdown and reset */
|
||||
Write32Mask(PLL, P1PLL_CNTL, 0x00000003, 0x00000003);
|
||||
snooze(2);
|
||||
|
||||
Write32(PLL, EXT1_PPLL_UPDATE_LOCK, 0);
|
||||
// Unlock
|
||||
Write32Mask(PLL, EXT1_PPLL_UPDATE_CNTL, 0, 0x01);
|
||||
// Done updating
|
||||
|
||||
Write32Mask(PLL, P1PLL_CNTL, 0, 0x02);
|
||||
// Power up PLL
|
||||
snooze(2);
|
||||
|
||||
PLLCalibrate(pllIndex);
|
||||
|
||||
Write32(PLL, EXT1_PPLL_POST_DIV_SRC, 0x01);
|
||||
// Set source as PLL
|
||||
|
||||
// TODO : If CRT2 ah-la R500PLLCRTCGrab
|
||||
PLLCRTCGrab(pllIndex, false);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PLLSetLowR620(uint8 pllIndex, uint32 pixelClock, uint16 reference,
|
||||
uint16 feedback, uint16 post)
|
||||
{
|
||||
radeon_shared_info &info = *gInfo->shared_info;
|
||||
|
||||
bool hasDccg = DCCGCLKAvailable(pllIndex);
|
||||
|
||||
TRACE("%s: card has DCCG = %c\n", __func__, hasDccg ? 'y' : 'n');
|
||||
|
||||
if (hasDccg)
|
||||
DCCGCLKSet(pllIndex, RV620_DCCGCLK_RESET);
|
||||
|
||||
@ -259,7 +361,8 @@ PLLSet(uint8 pllIndex, uint32 pixelClock)
|
||||
postDivider |= post & 0x0000007F;
|
||||
|
||||
uint32 control;
|
||||
if (info.device_chipset >= (RADEON_R600 & 0x70))
|
||||
|
||||
if (info.device_chipset >= (RADEON_R600 | 0x70))
|
||||
control = PLLControlTable(RV670PLLControl, feedback);
|
||||
else
|
||||
control = PLLControlTable(RV610PLLControl, feedback);
|
||||
@ -324,14 +427,12 @@ PLLSet(uint8 pllIndex, uint32 pixelClock)
|
||||
DCCGCLKSet(pllIndex, RV620_DCCGCLK_GRAB);
|
||||
|
||||
TRACE("%s: PLLSet exit\n", __func__);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
PLLCalibrate(uint8 pllIndex)
|
||||
{
|
||||
|
||||
uint16 pllControlReg = (pllIndex == 1) ? P2PLL_CNTL : P1PLL_CNTL;
|
||||
|
||||
Write32Mask(PLL, pllControlReg, 1, 0x01);
|
||||
@ -407,6 +508,11 @@ PLLCRTCGrab(uint8 pllIndex, bool crt2)
|
||||
bool
|
||||
DCCGCLKAvailable(uint8 pllIndex)
|
||||
{
|
||||
radeon_shared_info &info = *gInfo->shared_info;
|
||||
|
||||
if (info.device_chipset < (RADEON_R600 | 0x20))
|
||||
return false;
|
||||
|
||||
uint32 dccg = Read32(PLL, DCCG_DISP_CLK_SRCSEL) & 0x03;
|
||||
|
||||
if (dccg & 0x02)
|
||||
|
@ -42,6 +42,10 @@ struct PLL_Control {
|
||||
status_t PLLCalculate(uint32 pixelClock, uint16 *reference, uint16 *feedback,
|
||||
uint16 *post);
|
||||
status_t PLLSet(uint8 pllIndex, uint32 pixelClock);
|
||||
void PLLSetLowLegacy(uint8 pllIndex, uint32 pixelClock, uint16 reference,
|
||||
uint16 feedback, uint16 post);
|
||||
void PLLSetLowR620(uint8 pllIndex, uint32 pixelClock, uint16 reference,
|
||||
uint16 feedback, uint16 post);
|
||||
status_t PLLPower(uint8 pllIndex, int command);
|
||||
status_t PLLCalibrate(uint8 pllIndex);
|
||||
void PLLCRTCGrab(uint8 pllIndex, bool crt2);
|
||||
|
Loading…
x
Reference in New Issue
Block a user