* Large refactoring of display detection and storage
* Create new display.c/h for display management * Rename global gCRT to gDisplay * Add CRT connection type into gDisplay * Add CRT connection index into gDisplay * Refactor registers for each display into gDisplay via regs * We now shouldn't freak out too badly on multi-monitors git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@42462 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -15,6 +15,7 @@ Addon radeon_hd.accelerant :
|
|||||||
pll.cpp
|
pll.cpp
|
||||||
mc.cpp
|
mc.cpp
|
||||||
dac.cpp
|
dac.cpp
|
||||||
|
display.cpp
|
||||||
tmds.cpp
|
tmds.cpp
|
||||||
mode.cpp
|
mode.cpp
|
||||||
bios.cpp
|
bios.cpp
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
#include "accelerant_protos.h"
|
#include "accelerant_protos.h"
|
||||||
#include "accelerant.h"
|
#include "accelerant.h"
|
||||||
|
|
||||||
|
#include "display.h"
|
||||||
#include "utility.h"
|
#include "utility.h"
|
||||||
#include "pll.h"
|
#include "pll.h"
|
||||||
#include "mc.h"
|
#include "mc.h"
|
||||||
@@ -34,8 +35,7 @@ extern "C" void _sPrintf(const char *format, ...);
|
|||||||
|
|
||||||
|
|
||||||
struct accelerant_info *gInfo;
|
struct accelerant_info *gInfo;
|
||||||
struct register_info *gRegister;
|
crt_info *gDisplay[MAX_DISPLAY];
|
||||||
crt_info *gCRT[MAX_CRT];
|
|
||||||
|
|
||||||
|
|
||||||
class AreaCloner {
|
class AreaCloner {
|
||||||
@@ -97,22 +97,23 @@ init_common(int device, bool isClone)
|
|||||||
// initialize global accelerant info structure
|
// initialize global accelerant info structure
|
||||||
|
|
||||||
gInfo = (accelerant_info *)malloc(sizeof(accelerant_info));
|
gInfo = (accelerant_info *)malloc(sizeof(accelerant_info));
|
||||||
gRegister = (register_info *)malloc(sizeof(register_info));
|
|
||||||
|
|
||||||
if (gInfo == NULL || gRegister == NULL)
|
if (gInfo == NULL)
|
||||||
return B_NO_MEMORY;
|
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(gInfo, 0, sizeof(accelerant_info));
|
||||||
memset(gRegister, 0, sizeof(register_info));
|
|
||||||
|
|
||||||
for (uint32 id = 0; id < MAX_CRT; id++)
|
for (uint32 id = 0; id < MAX_DISPLAY; id++) {
|
||||||
memset(gCRT[id], 0, sizeof(crt_info));
|
gDisplay[id] = (crt_info *)malloc(sizeof(crt_info));
|
||||||
|
if (gDisplay[id] == NULL)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
memset(gDisplay[id], 0, sizeof(crt_info));
|
||||||
|
|
||||||
|
gDisplay[id]->regs = (register_info *)malloc(sizeof(register_info));
|
||||||
|
if (gDisplay[id]->regs == NULL)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
memset(gDisplay[id]->regs, 0, sizeof(register_info));
|
||||||
|
}
|
||||||
|
|
||||||
gInfo->is_clone = isClone;
|
gInfo->is_clone = isClone;
|
||||||
gInfo->device = device;
|
gInfo->device = device;
|
||||||
@@ -177,169 +178,13 @@ uninit_common(void)
|
|||||||
close(gInfo->device);
|
close(gInfo->device);
|
||||||
|
|
||||||
free(gInfo);
|
free(gInfo);
|
||||||
free(gRegister);
|
|
||||||
|
|
||||||
for (uint32 id = 0; id < MAX_CRT; id++)
|
for (uint32 id = 0; id < MAX_DISPLAY; id++) {
|
||||||
free(gCRT[id]);
|
if (gDisplay[id]->regs != NULL)
|
||||||
|
free(gDisplay[id]->regs);
|
||||||
|
if (gDisplay[id] != NULL)
|
||||||
|
free(gDisplay[id]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*! Populate gRegister with device dependant register locations */
|
|
||||||
status_t
|
|
||||||
init_registers(uint8 crtid)
|
|
||||||
{
|
|
||||||
radeon_shared_info &info = *gInfo->shared_info;
|
|
||||||
|
|
||||||
if (info.device_chipset >= RADEON_R800) {
|
|
||||||
uint32 offset = 0;
|
|
||||||
|
|
||||||
// AMD Eyefinity on Evergreen GPUs
|
|
||||||
if (crtid == 1) {
|
|
||||||
offset = EVERGREEN_CRTC1_REGISTER_OFFSET;
|
|
||||||
gRegister->vgaControl = D2VGA_CONTROL;
|
|
||||||
} else if (crtid == 2) {
|
|
||||||
offset = EVERGREEN_CRTC2_REGISTER_OFFSET;
|
|
||||||
gRegister->vgaControl = EVERGREEN_D3VGA_CONTROL;
|
|
||||||
} else if (crtid == 3) {
|
|
||||||
offset = EVERGREEN_CRTC3_REGISTER_OFFSET;
|
|
||||||
gRegister->vgaControl = EVERGREEN_D4VGA_CONTROL;
|
|
||||||
} else if (crtid == 4) {
|
|
||||||
offset = EVERGREEN_CRTC4_REGISTER_OFFSET;
|
|
||||||
gRegister->vgaControl = EVERGREEN_D5VGA_CONTROL;
|
|
||||||
} else if (crtid == 5) {
|
|
||||||
offset = EVERGREEN_CRTC5_REGISTER_OFFSET;
|
|
||||||
gRegister->vgaControl = EVERGREEN_D6VGA_CONTROL;
|
|
||||||
} else {
|
|
||||||
offset = EVERGREEN_CRTC0_REGISTER_OFFSET;
|
|
||||||
gRegister->vgaControl = D1VGA_CONTROL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Evergreen+ is crtoffset + register
|
|
||||||
gRegister->grphEnable = offset + EVERGREEN_GRPH_ENABLE;
|
|
||||||
gRegister->grphControl = offset + EVERGREEN_GRPH_CONTROL;
|
|
||||||
gRegister->grphSwapControl = offset + EVERGREEN_GRPH_SWAP_CONTROL;
|
|
||||||
gRegister->grphPrimarySurfaceAddr
|
|
||||||
= offset + EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS;
|
|
||||||
gRegister->grphSecondarySurfaceAddr
|
|
||||||
= offset + EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS;
|
|
||||||
|
|
||||||
gRegister->grphPrimarySurfaceAddrHigh
|
|
||||||
= offset + EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH;
|
|
||||||
gRegister->grphSecondarySurfaceAddrHigh
|
|
||||||
= offset + EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH;
|
|
||||||
|
|
||||||
gRegister->grphPitch = offset + EVERGREEN_GRPH_PITCH;
|
|
||||||
gRegister->grphSurfaceOffsetX
|
|
||||||
= offset + EVERGREEN_GRPH_SURFACE_OFFSET_X;
|
|
||||||
gRegister->grphSurfaceOffsetY
|
|
||||||
= offset + EVERGREEN_GRPH_SURFACE_OFFSET_Y;
|
|
||||||
gRegister->grphXStart = offset + EVERGREEN_GRPH_X_START;
|
|
||||||
gRegister->grphYStart = offset + EVERGREEN_GRPH_Y_START;
|
|
||||||
gRegister->grphXEnd = offset + EVERGREEN_GRPH_X_END;
|
|
||||||
gRegister->grphYEnd = offset + EVERGREEN_GRPH_Y_END;
|
|
||||||
gRegister->crtControl = offset + EVERGREEN_CRTC_CONTROL;
|
|
||||||
gRegister->modeDesktopHeight = offset + EVERGREEN_DESKTOP_HEIGHT;
|
|
||||||
gRegister->modeDataFormat = offset + EVERGREEN_DATA_FORMAT;
|
|
||||||
gRegister->viewportStart = offset + EVERGREEN_VIEWPORT_START;
|
|
||||||
gRegister->viewportSize = offset + EVERGREEN_VIEWPORT_SIZE;
|
|
||||||
|
|
||||||
} else if (info.device_chipset >= RADEON_R600
|
|
||||||
&& info.device_chipset < RADEON_R800) {
|
|
||||||
|
|
||||||
// r600 - r700 are D1 or D2 based on primary / secondary crt
|
|
||||||
gRegister->vgaControl
|
|
||||||
= crtid == 1 ? D2VGA_CONTROL : D1VGA_CONTROL;
|
|
||||||
gRegister->grphEnable
|
|
||||||
= crtid == 1 ? D2GRPH_ENABLE : D1GRPH_ENABLE;
|
|
||||||
gRegister->grphControl
|
|
||||||
= crtid == 1 ? D2GRPH_CONTROL : D1GRPH_CONTROL;
|
|
||||||
gRegister->grphSwapControl
|
|
||||||
= crtid == 1 ? D2GRPH_SWAP_CNTL : D1GRPH_SWAP_CNTL;
|
|
||||||
gRegister->grphPrimarySurfaceAddr
|
|
||||||
= crtid == 1 ? D2GRPH_PRIMARY_SURFACE_ADDRESS
|
|
||||||
: D1GRPH_PRIMARY_SURFACE_ADDRESS;
|
|
||||||
gRegister->grphSecondarySurfaceAddr
|
|
||||||
= crtid == 1 ? D2GRPH_SECONDARY_SURFACE_ADDRESS
|
|
||||||
: D1GRPH_SECONDARY_SURFACE_ADDRESS;
|
|
||||||
|
|
||||||
// Surface Address high only used on r770+
|
|
||||||
gRegister->grphPrimarySurfaceAddrHigh
|
|
||||||
= crtid == 1 ? R700_D2GRPH_PRIMARY_SURFACE_ADDRESS_HIGH
|
|
||||||
: R700_D1GRPH_PRIMARY_SURFACE_ADDRESS_HIGH;
|
|
||||||
gRegister->grphSecondarySurfaceAddrHigh
|
|
||||||
= crtid == 1 ? R700_D2GRPH_SECONDARY_SURFACE_ADDRESS_HIGH
|
|
||||||
: R700_D1GRPH_SECONDARY_SURFACE_ADDRESS_HIGH;
|
|
||||||
|
|
||||||
gRegister->grphPitch
|
|
||||||
= crtid == 1 ? D2GRPH_PITCH : D1GRPH_PITCH;
|
|
||||||
gRegister->grphSurfaceOffsetX
|
|
||||||
= crtid == 1 ? D2GRPH_SURFACE_OFFSET_X : D1GRPH_SURFACE_OFFSET_X;
|
|
||||||
gRegister->grphSurfaceOffsetY
|
|
||||||
= crtid == 1 ? D2GRPH_SURFACE_OFFSET_Y : D1GRPH_SURFACE_OFFSET_Y;
|
|
||||||
gRegister->grphXStart
|
|
||||||
= crtid == 1 ? D2GRPH_X_START : D1GRPH_X_START;
|
|
||||||
gRegister->grphYStart
|
|
||||||
= crtid == 1 ? D2GRPH_Y_START : D1GRPH_Y_START;
|
|
||||||
gRegister->grphXEnd
|
|
||||||
= crtid == 1 ? D2GRPH_X_END : D1GRPH_X_END;
|
|
||||||
gRegister->grphYEnd
|
|
||||||
= crtid == 1 ? D2GRPH_Y_END : D1GRPH_Y_END;
|
|
||||||
gRegister->crtControl
|
|
||||||
= crtid == 1 ? D2CRTC_CONTROL : D1CRTC_CONTROL;
|
|
||||||
gRegister->modeDesktopHeight
|
|
||||||
= crtid == 1 ? D2MODE_DESKTOP_HEIGHT : D1MODE_DESKTOP_HEIGHT;
|
|
||||||
gRegister->modeDataFormat
|
|
||||||
= crtid == 1 ? D2MODE_DATA_FORMAT : D1MODE_DATA_FORMAT;
|
|
||||||
gRegister->viewportStart
|
|
||||||
= crtid == 1 ? D2MODE_VIEWPORT_START : D1MODE_VIEWPORT_START;
|
|
||||||
gRegister->viewportSize
|
|
||||||
= crtid == 1 ? D2MODE_VIEWPORT_SIZE : D1MODE_VIEWPORT_SIZE;
|
|
||||||
} else {
|
|
||||||
// this really shouldn't happen unless a driver PCIID chipset is wrong
|
|
||||||
TRACE("%s, unknown Radeon chipset: r%X\n", __func__,
|
|
||||||
info.device_chipset);
|
|
||||||
return B_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Populate common registers
|
|
||||||
// TODO : Wait.. this doesn't work with Eyefinity > crt 1.
|
|
||||||
gRegister->crtid = crtid;
|
|
||||||
|
|
||||||
gRegister->modeCenter
|
|
||||||
= crtid == 1 ? D2MODE_CENTER : D1MODE_CENTER;
|
|
||||||
gRegister->grphUpdate
|
|
||||||
= crtid == 1 ? D2GRPH_UPDATE : D1GRPH_UPDATE;
|
|
||||||
gRegister->crtHPolarity
|
|
||||||
= crtid == 1 ? D2CRTC_H_SYNC_A_CNTL : D1CRTC_H_SYNC_A_CNTL;
|
|
||||||
gRegister->crtVPolarity
|
|
||||||
= crtid == 1 ? D2CRTC_V_SYNC_A_CNTL : D1CRTC_V_SYNC_A_CNTL;
|
|
||||||
gRegister->crtHTotal
|
|
||||||
= crtid == 1 ? D2CRTC_H_TOTAL : D1CRTC_H_TOTAL;
|
|
||||||
gRegister->crtVTotal
|
|
||||||
= crtid == 1 ? D2CRTC_V_TOTAL : D1CRTC_V_TOTAL;
|
|
||||||
gRegister->crtHSync
|
|
||||||
= crtid == 1 ? D2CRTC_H_SYNC_A : D1CRTC_H_SYNC_A;
|
|
||||||
gRegister->crtVSync
|
|
||||||
= crtid == 1 ? D2CRTC_V_SYNC_A : D1CRTC_V_SYNC_A;
|
|
||||||
gRegister->crtHBlank
|
|
||||||
= crtid == 1 ? D2CRTC_H_BLANK_START_END : D1CRTC_H_BLANK_START_END;
|
|
||||||
gRegister->crtVBlank
|
|
||||||
= crtid == 1 ? D2CRTC_V_BLANK_START_END : D1CRTC_V_BLANK_START_END;
|
|
||||||
gRegister->crtInterlace
|
|
||||||
= crtid == 1 ? D2CRTC_INTERLACE_CONTROL : D1CRTC_INTERLACE_CONTROL;
|
|
||||||
gRegister->crtCountControl
|
|
||||||
= crtid == 1 ? D2CRTC_COUNT_CONTROL : D1CRTC_COUNT_CONTROL;
|
|
||||||
gRegister->sclUpdate
|
|
||||||
= crtid == 1 ? D2SCL_UPDATE : D1SCL_UPDATE;
|
|
||||||
gRegister->sclEnable
|
|
||||||
= crtid == 1 ? D2SCL_ENABLE : D1SCL_ENABLE;
|
|
||||||
gRegister->sclTapControl
|
|
||||||
= crtid == 1 ? D2SCL_TAP_CONTROL : D1SCL_TAP_CONTROL;
|
|
||||||
|
|
||||||
TRACE("%s, registers for ATI chipset r%X crt #%d loaded\n", __func__,
|
|
||||||
info.device_chipset, crtid);
|
|
||||||
|
|
||||||
return B_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -361,9 +206,7 @@ radeon_init_accelerant(int device)
|
|||||||
init_lock(&info.accelerant_lock, "radeon hd accelerant");
|
init_lock(&info.accelerant_lock, "radeon hd accelerant");
|
||||||
init_lock(&info.engine_lock, "radeon hd engine");
|
init_lock(&info.engine_lock, "radeon hd engine");
|
||||||
|
|
||||||
status = init_registers(0);
|
status = detect_displays();
|
||||||
// Initilize registers for crt0 to begin
|
|
||||||
|
|
||||||
if (status != B_OK)
|
if (status != B_OK)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
|
|||||||
@@ -20,8 +20,8 @@
|
|||||||
#include <edid.h>
|
#include <edid.h>
|
||||||
|
|
||||||
|
|
||||||
#define MAX_CRT 6
|
#define MAX_DISPLAY 2
|
||||||
// eyefinity limit
|
// Maximum displays (more then two requires AtomBIOS)
|
||||||
|
|
||||||
|
|
||||||
struct accelerant_info {
|
struct accelerant_info {
|
||||||
@@ -46,7 +46,6 @@ struct accelerant_info {
|
|||||||
|
|
||||||
|
|
||||||
struct register_info {
|
struct register_info {
|
||||||
uint16 crtid;
|
|
||||||
uint16 vgaControl;
|
uint16 vgaControl;
|
||||||
uint16 grphEnable;
|
uint16 grphEnable;
|
||||||
uint16 grphUpdate;
|
uint16 grphUpdate;
|
||||||
@@ -86,8 +85,10 @@ struct register_info {
|
|||||||
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint16 location;
|
bool active;
|
||||||
uint16 locationIndex;
|
uint32 connection_type;
|
||||||
|
uint8 connection_id;
|
||||||
|
register_info *regs;
|
||||||
uint32 vfreq_max;
|
uint32 vfreq_max;
|
||||||
uint32 vfreq_min;
|
uint32 vfreq_min;
|
||||||
uint32 hfreq_max;
|
uint32 hfreq_max;
|
||||||
@@ -95,10 +96,10 @@ typedef struct {
|
|||||||
} crt_info;
|
} crt_info;
|
||||||
|
|
||||||
|
|
||||||
#define HEAD_MODE_A_ANALOG 0x01
|
// crt_info connection_type
|
||||||
#define HEAD_MODE_B_DIGITAL 0x02
|
#define CONNECTION_DAC 0x0001
|
||||||
#define HEAD_MODE_CLONE 0x03
|
#define CONNECTION_TMDS 0x0002
|
||||||
#define HEAD_MODE_LVDS_PANEL 0x08
|
#define CONNECTION_LVDS 0x0003
|
||||||
|
|
||||||
// register MMIO modes
|
// register MMIO modes
|
||||||
#define OUT 0x1 // direct MMIO calls
|
#define OUT 0x1 // direct MMIO calls
|
||||||
@@ -109,11 +110,7 @@ typedef struct {
|
|||||||
|
|
||||||
|
|
||||||
extern accelerant_info *gInfo;
|
extern accelerant_info *gInfo;
|
||||||
extern register_info *gRegister;
|
extern crt_info *gDisplay[MAX_DISPLAY];
|
||||||
extern crt_info *gCRT[MAX_CRT];
|
|
||||||
|
|
||||||
|
|
||||||
status_t init_registers(uint8 crtid);
|
|
||||||
|
|
||||||
|
|
||||||
// register access
|
// register access
|
||||||
|
|||||||
@@ -0,0 +1,261 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2006-2011, Haiku, Inc. All Rights Reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Alexander von Gluck, [email protected]
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "accelerant_protos.h"
|
||||||
|
#include "accelerant.h"
|
||||||
|
#include "display.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
|
||||||
|
#define TRACE_DISPLAY
|
||||||
|
#ifdef TRACE_DISPLAY
|
||||||
|
extern "C" void _sPrintf(const char *format, ...);
|
||||||
|
# define TRACE(x...) _sPrintf("radeon_hd: " x)
|
||||||
|
#else
|
||||||
|
# define TRACE(x...) ;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*! Populate regs with device dependant register locations */
|
||||||
|
status_t
|
||||||
|
init_registers(register_info* regs, uint8 crtid)
|
||||||
|
{
|
||||||
|
memset(regs, 0, sizeof(register_info));
|
||||||
|
|
||||||
|
radeon_shared_info &info = *gInfo->shared_info;
|
||||||
|
|
||||||
|
if (info.device_chipset >= RADEON_R800) {
|
||||||
|
uint32 offset = 0;
|
||||||
|
|
||||||
|
// AMD Eyefinity on Evergreen GPUs
|
||||||
|
if (crtid == 1) {
|
||||||
|
offset = EVERGREEN_CRTC1_REGISTER_OFFSET;
|
||||||
|
regs->vgaControl = D2VGA_CONTROL;
|
||||||
|
} else if (crtid == 2) {
|
||||||
|
offset = EVERGREEN_CRTC2_REGISTER_OFFSET;
|
||||||
|
regs->vgaControl = EVERGREEN_D3VGA_CONTROL;
|
||||||
|
} else if (crtid == 3) {
|
||||||
|
offset = EVERGREEN_CRTC3_REGISTER_OFFSET;
|
||||||
|
regs->vgaControl = EVERGREEN_D4VGA_CONTROL;
|
||||||
|
} else if (crtid == 4) {
|
||||||
|
offset = EVERGREEN_CRTC4_REGISTER_OFFSET;
|
||||||
|
regs->vgaControl = EVERGREEN_D5VGA_CONTROL;
|
||||||
|
} else if (crtid == 5) {
|
||||||
|
offset = EVERGREEN_CRTC5_REGISTER_OFFSET;
|
||||||
|
regs->vgaControl = EVERGREEN_D6VGA_CONTROL;
|
||||||
|
} else {
|
||||||
|
offset = EVERGREEN_CRTC0_REGISTER_OFFSET;
|
||||||
|
regs->vgaControl = D1VGA_CONTROL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Evergreen+ is crtoffset + register
|
||||||
|
regs->grphEnable = offset + EVERGREEN_GRPH_ENABLE;
|
||||||
|
regs->grphControl = offset + EVERGREEN_GRPH_CONTROL;
|
||||||
|
regs->grphSwapControl = offset + EVERGREEN_GRPH_SWAP_CONTROL;
|
||||||
|
regs->grphPrimarySurfaceAddr
|
||||||
|
= offset + EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS;
|
||||||
|
regs->grphSecondarySurfaceAddr
|
||||||
|
= offset + EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS;
|
||||||
|
|
||||||
|
regs->grphPrimarySurfaceAddrHigh
|
||||||
|
= offset + EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH;
|
||||||
|
regs->grphSecondarySurfaceAddrHigh
|
||||||
|
= offset + EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH;
|
||||||
|
|
||||||
|
regs->grphPitch = offset + EVERGREEN_GRPH_PITCH;
|
||||||
|
regs->grphSurfaceOffsetX
|
||||||
|
= offset + EVERGREEN_GRPH_SURFACE_OFFSET_X;
|
||||||
|
regs->grphSurfaceOffsetY
|
||||||
|
= offset + EVERGREEN_GRPH_SURFACE_OFFSET_Y;
|
||||||
|
regs->grphXStart = offset + EVERGREEN_GRPH_X_START;
|
||||||
|
regs->grphYStart = offset + EVERGREEN_GRPH_Y_START;
|
||||||
|
regs->grphXEnd = offset + EVERGREEN_GRPH_X_END;
|
||||||
|
regs->grphYEnd = offset + EVERGREEN_GRPH_Y_END;
|
||||||
|
regs->crtControl = offset + EVERGREEN_CRTC_CONTROL;
|
||||||
|
regs->modeDesktopHeight = offset + EVERGREEN_DESKTOP_HEIGHT;
|
||||||
|
regs->modeDataFormat = offset + EVERGREEN_DATA_FORMAT;
|
||||||
|
regs->viewportStart = offset + EVERGREEN_VIEWPORT_START;
|
||||||
|
regs->viewportSize = offset + EVERGREEN_VIEWPORT_SIZE;
|
||||||
|
|
||||||
|
} else if (info.device_chipset >= RADEON_R600
|
||||||
|
&& info.device_chipset < RADEON_R800) {
|
||||||
|
|
||||||
|
// r600 - r700 are D1 or D2 based on primary / secondary crt
|
||||||
|
regs->vgaControl
|
||||||
|
= crtid == 1 ? D2VGA_CONTROL : D1VGA_CONTROL;
|
||||||
|
regs->grphEnable
|
||||||
|
= crtid == 1 ? D2GRPH_ENABLE : D1GRPH_ENABLE;
|
||||||
|
regs->grphControl
|
||||||
|
= crtid == 1 ? D2GRPH_CONTROL : D1GRPH_CONTROL;
|
||||||
|
regs->grphSwapControl
|
||||||
|
= crtid == 1 ? D2GRPH_SWAP_CNTL : D1GRPH_SWAP_CNTL;
|
||||||
|
regs->grphPrimarySurfaceAddr
|
||||||
|
= crtid == 1 ? D2GRPH_PRIMARY_SURFACE_ADDRESS
|
||||||
|
: D1GRPH_PRIMARY_SURFACE_ADDRESS;
|
||||||
|
regs->grphSecondarySurfaceAddr
|
||||||
|
= crtid == 1 ? D2GRPH_SECONDARY_SURFACE_ADDRESS
|
||||||
|
: D1GRPH_SECONDARY_SURFACE_ADDRESS;
|
||||||
|
|
||||||
|
// Surface Address high only used on r770+
|
||||||
|
regs->grphPrimarySurfaceAddrHigh
|
||||||
|
= crtid == 1 ? R700_D2GRPH_PRIMARY_SURFACE_ADDRESS_HIGH
|
||||||
|
: R700_D1GRPH_PRIMARY_SURFACE_ADDRESS_HIGH;
|
||||||
|
regs->grphSecondarySurfaceAddrHigh
|
||||||
|
= crtid == 1 ? R700_D2GRPH_SECONDARY_SURFACE_ADDRESS_HIGH
|
||||||
|
: R700_D1GRPH_SECONDARY_SURFACE_ADDRESS_HIGH;
|
||||||
|
|
||||||
|
regs->grphPitch
|
||||||
|
= crtid == 1 ? D2GRPH_PITCH : D1GRPH_PITCH;
|
||||||
|
regs->grphSurfaceOffsetX
|
||||||
|
= crtid == 1 ? D2GRPH_SURFACE_OFFSET_X : D1GRPH_SURFACE_OFFSET_X;
|
||||||
|
regs->grphSurfaceOffsetY
|
||||||
|
= crtid == 1 ? D2GRPH_SURFACE_OFFSET_Y : D1GRPH_SURFACE_OFFSET_Y;
|
||||||
|
regs->grphXStart
|
||||||
|
= crtid == 1 ? D2GRPH_X_START : D1GRPH_X_START;
|
||||||
|
regs->grphYStart
|
||||||
|
= crtid == 1 ? D2GRPH_Y_START : D1GRPH_Y_START;
|
||||||
|
regs->grphXEnd
|
||||||
|
= crtid == 1 ? D2GRPH_X_END : D1GRPH_X_END;
|
||||||
|
regs->grphYEnd
|
||||||
|
= crtid == 1 ? D2GRPH_Y_END : D1GRPH_Y_END;
|
||||||
|
regs->crtControl
|
||||||
|
= crtid == 1 ? D2CRTC_CONTROL : D1CRTC_CONTROL;
|
||||||
|
regs->modeDesktopHeight
|
||||||
|
= crtid == 1 ? D2MODE_DESKTOP_HEIGHT : D1MODE_DESKTOP_HEIGHT;
|
||||||
|
regs->modeDataFormat
|
||||||
|
= crtid == 1 ? D2MODE_DATA_FORMAT : D1MODE_DATA_FORMAT;
|
||||||
|
regs->viewportStart
|
||||||
|
= crtid == 1 ? D2MODE_VIEWPORT_START : D1MODE_VIEWPORT_START;
|
||||||
|
regs->viewportSize
|
||||||
|
= crtid == 1 ? D2MODE_VIEWPORT_SIZE : D1MODE_VIEWPORT_SIZE;
|
||||||
|
} else {
|
||||||
|
// this really shouldn't happen unless a driver PCIID chipset is wrong
|
||||||
|
TRACE("%s, unknown Radeon chipset: r%X\n", __func__,
|
||||||
|
info.device_chipset);
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Populate common registers
|
||||||
|
// TODO : Wait.. this doesn't work with Eyefinity > crt 1.
|
||||||
|
|
||||||
|
regs->modeCenter
|
||||||
|
= crtid == 1 ? D2MODE_CENTER : D1MODE_CENTER;
|
||||||
|
regs->grphUpdate
|
||||||
|
= crtid == 1 ? D2GRPH_UPDATE : D1GRPH_UPDATE;
|
||||||
|
regs->crtHPolarity
|
||||||
|
= crtid == 1 ? D2CRTC_H_SYNC_A_CNTL : D1CRTC_H_SYNC_A_CNTL;
|
||||||
|
regs->crtVPolarity
|
||||||
|
= crtid == 1 ? D2CRTC_V_SYNC_A_CNTL : D1CRTC_V_SYNC_A_CNTL;
|
||||||
|
regs->crtHTotal
|
||||||
|
= crtid == 1 ? D2CRTC_H_TOTAL : D1CRTC_H_TOTAL;
|
||||||
|
regs->crtVTotal
|
||||||
|
= crtid == 1 ? D2CRTC_V_TOTAL : D1CRTC_V_TOTAL;
|
||||||
|
regs->crtHSync
|
||||||
|
= crtid == 1 ? D2CRTC_H_SYNC_A : D1CRTC_H_SYNC_A;
|
||||||
|
regs->crtVSync
|
||||||
|
= crtid == 1 ? D2CRTC_V_SYNC_A : D1CRTC_V_SYNC_A;
|
||||||
|
regs->crtHBlank
|
||||||
|
= crtid == 1 ? D2CRTC_H_BLANK_START_END : D1CRTC_H_BLANK_START_END;
|
||||||
|
regs->crtVBlank
|
||||||
|
= crtid == 1 ? D2CRTC_V_BLANK_START_END : D1CRTC_V_BLANK_START_END;
|
||||||
|
regs->crtInterlace
|
||||||
|
= crtid == 1 ? D2CRTC_INTERLACE_CONTROL : D1CRTC_INTERLACE_CONTROL;
|
||||||
|
regs->crtCountControl
|
||||||
|
= crtid == 1 ? D2CRTC_COUNT_CONTROL : D1CRTC_COUNT_CONTROL;
|
||||||
|
regs->sclUpdate
|
||||||
|
= crtid == 1 ? D2SCL_UPDATE : D1SCL_UPDATE;
|
||||||
|
regs->sclEnable
|
||||||
|
= crtid == 1 ? D2SCL_ENABLE : D1SCL_ENABLE;
|
||||||
|
regs->sclTapControl
|
||||||
|
= crtid == 1 ? D2SCL_TAP_CONTROL : D1SCL_TAP_CONTROL;
|
||||||
|
|
||||||
|
TRACE("%s, registers for ATI chipset r%X crt #%d loaded\n", __func__,
|
||||||
|
info.device_chipset, crtid);
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
detect_crt_ranges(uint32 crtid)
|
||||||
|
{
|
||||||
|
edid1_info *edid = &gInfo->shared_info->edid_info;
|
||||||
|
|
||||||
|
// TODO : VESA edid is just for primary monitor
|
||||||
|
|
||||||
|
// EDID spec states 4 descriptor blocks
|
||||||
|
for (uint32 index = 0; index < EDID1_NUM_DETAILED_MONITOR_DESC; 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;
|
||||||
|
gDisplay[crtid]->vfreq_min = range.min_v; /* in Hz */
|
||||||
|
gDisplay[crtid]->vfreq_max = range.max_v;
|
||||||
|
gDisplay[crtid]->hfreq_min = range.min_h; /* in kHz */
|
||||||
|
gDisplay[crtid]->hfreq_max = range.max_h;
|
||||||
|
TRACE("CRT %d : v_min %d : v_max %d : h_min %d : h_max %d\n",
|
||||||
|
crtid, gDisplay[crtid]->vfreq_min, gDisplay[crtid]->vfreq_max,
|
||||||
|
gDisplay[crtid]->hfreq_min, gDisplay[crtid]->hfreq_max);
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
detect_displays()
|
||||||
|
{
|
||||||
|
// reset known displays
|
||||||
|
for (uint32 id = 0; id < MAX_DISPLAY; id++)
|
||||||
|
gDisplay[id]->active = false;
|
||||||
|
|
||||||
|
uint32 index = 0;
|
||||||
|
|
||||||
|
// Probe for DAC monitors connected
|
||||||
|
for (uint32 id = 0; id < 2; id++) {
|
||||||
|
if (DACSense(id)) {
|
||||||
|
gDisplay[index]->active = true;
|
||||||
|
gDisplay[index]->connection_type = CONNECTION_DAC;
|
||||||
|
gDisplay[index]->connection_id = id;
|
||||||
|
init_registers(gDisplay[index]->regs, index);
|
||||||
|
detect_crt_ranges(index);
|
||||||
|
if (index < MAX_DISPLAY)
|
||||||
|
index++;
|
||||||
|
else
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Probe for TMDS monitors connected
|
||||||
|
for (uint32 id = 0; id < 1; id++) {
|
||||||
|
if (TMDSSense(id)) {
|
||||||
|
gDisplay[index]->active = true;
|
||||||
|
gDisplay[index]->connection_type = CONNECTION_TMDS;
|
||||||
|
gDisplay[index]->connection_id = id;
|
||||||
|
init_registers(gDisplay[index]->regs, index);
|
||||||
|
detect_crt_ranges(index);
|
||||||
|
if (index < MAX_DISPLAY)
|
||||||
|
index++;
|
||||||
|
else
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2006-2011, Haiku, Inc. All Rights Reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Alexander von Gluck, [email protected]
|
||||||
|
*/
|
||||||
|
#ifndef RADEON_HD_DISPLAY_H
|
||||||
|
#define RADEON_HD_DISPLAY_H
|
||||||
|
|
||||||
|
|
||||||
|
status_t init_registers(register_info* reg, uint8 crtid);
|
||||||
|
status_t detect_crt_ranges(uint32 crtid);
|
||||||
|
status_t detect_displays();
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* RADEON_HD_DISPLAY_H */
|
||||||
@@ -38,8 +38,6 @@ create_mode_list(void)
|
|||||||
const color_space kRadeonHDSpaces[] = {B_RGB32_LITTLE, B_RGB24_LITTLE,
|
const color_space kRadeonHDSpaces[] = {B_RGB32_LITTLE, B_RGB24_LITTLE,
|
||||||
B_RGB16_LITTLE, B_RGB15_LITTLE, B_CMAP8};
|
B_RGB16_LITTLE, B_RGB15_LITTLE, B_CMAP8};
|
||||||
|
|
||||||
detect_crt_ranges();
|
|
||||||
|
|
||||||
gInfo->mode_list_area = create_display_modes("radeon HD modes",
|
gInfo->mode_list_area = create_display_modes("radeon HD modes",
|
||||||
gInfo->shared_info->has_edid ? &gInfo->shared_info->edid_info : NULL,
|
gInfo->shared_info->has_edid ? &gInfo->shared_info->edid_info : NULL,
|
||||||
NULL, 0, kRadeonHDSpaces,
|
NULL, 0, kRadeonHDSpaces,
|
||||||
@@ -141,14 +139,17 @@ CardBlankSet(uint8 crtid, bool blank)
|
|||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
CardFBSet(display_mode *mode)
|
CardFBSet(uint8 crtid, display_mode *mode)
|
||||||
{
|
{
|
||||||
|
register_info* regs = gDisplay[crtid]->regs;
|
||||||
|
|
||||||
uint32 colorMode;
|
uint32 colorMode;
|
||||||
uint32 bytesPerRow;
|
uint32 bytesPerRow;
|
||||||
uint32 bitsPerPixel;
|
uint32 bitsPerPixel;
|
||||||
|
|
||||||
get_color_space_format(*mode, colorMode, bytesPerRow, bitsPerPixel);
|
get_color_space_format(*mode, colorMode, bytesPerRow, bitsPerPixel);
|
||||||
|
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
// TMDSAllIdle // DVI / HDMI
|
// TMDSAllIdle // DVI / HDMI
|
||||||
// LVTMAAllIdle // DVI
|
// LVTMAAllIdle // DVI
|
||||||
@@ -160,68 +161,68 @@ CardFBSet(display_mode *mode)
|
|||||||
MCFBSetup(Read32(OUT, R6XX_CONFIG_FB_BASE), mcFbSize);
|
MCFBSetup(Read32(OUT, R6XX_CONFIG_FB_BASE), mcFbSize);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Write32(CRT, gRegister->grphUpdate, (1<<16));
|
Write32(CRT, regs->grphUpdate, (1<<16));
|
||||||
// Lock for update (isn't this normally the other way around on VGA?
|
// Lock for update (isn't this normally the other way around on VGA?
|
||||||
|
|
||||||
// framebuffersize = w * h * bpp = fb bits / 8 = bytes needed
|
// framebuffersize = w * h * bpp = fb bits / 8 = bytes needed
|
||||||
uint64_t fbAddress = gInfo->shared_info->frame_buffer_phys;
|
uint64_t fbAddress = gInfo->shared_info->frame_buffer_phys;
|
||||||
|
|
||||||
// Tell GPU which frame buffer address to draw from
|
// Tell GPU which frame buffer address to draw from
|
||||||
Write32(CRT, gRegister->grphPrimarySurfaceAddr,
|
Write32(CRT, regs->grphPrimarySurfaceAddr,
|
||||||
fbAddress & 0xffffffff);
|
fbAddress & 0xffffffff);
|
||||||
Write32(CRT, gRegister->grphSecondarySurfaceAddr,
|
Write32(CRT, regs->grphSecondarySurfaceAddr,
|
||||||
fbAddress & 0xffffffff);
|
fbAddress & 0xffffffff);
|
||||||
|
|
||||||
if (gInfo->shared_info->device_chipset >= (RADEON_R700 | 0x70)) {
|
if (gInfo->shared_info->device_chipset >= (RADEON_R700 | 0x70)) {
|
||||||
Write32(CRT, gRegister->grphPrimarySurfaceAddrHigh,
|
Write32(CRT, regs->grphPrimarySurfaceAddrHigh,
|
||||||
(fbAddress >> 32) & 0xf);
|
(fbAddress >> 32) & 0xf);
|
||||||
Write32(CRT, gRegister->grphSecondarySurfaceAddrHigh,
|
Write32(CRT, regs->grphSecondarySurfaceAddrHigh,
|
||||||
(fbAddress >> 32) & 0xf);
|
(fbAddress >> 32) & 0xf);
|
||||||
}
|
}
|
||||||
|
|
||||||
Write32(CRT, gRegister->grphControl, 0);
|
Write32(CRT, regs->grphControl, 0);
|
||||||
// Reset stored depth, format, etc
|
// Reset stored depth, format, etc
|
||||||
|
|
||||||
// set color mode on video card
|
// set color mode on video card
|
||||||
switch (mode->space) {
|
switch (mode->space) {
|
||||||
case B_CMAP8:
|
case B_CMAP8:
|
||||||
Write32Mask(CRT, gRegister->grphControl,
|
Write32Mask(CRT, regs->grphControl,
|
||||||
0, 0x00000703);
|
0, 0x00000703);
|
||||||
break;
|
break;
|
||||||
case B_RGB15_LITTLE:
|
case B_RGB15_LITTLE:
|
||||||
Write32Mask(CRT, gRegister->grphControl,
|
Write32Mask(CRT, regs->grphControl,
|
||||||
0x000001, 0x00000703);
|
0x000001, 0x00000703);
|
||||||
break;
|
break;
|
||||||
case B_RGB16_LITTLE:
|
case B_RGB16_LITTLE:
|
||||||
Write32Mask(CRT, gRegister->grphControl,
|
Write32Mask(CRT, regs->grphControl,
|
||||||
0x000101, 0x00000703);
|
0x000101, 0x00000703);
|
||||||
break;
|
break;
|
||||||
case B_RGB24_LITTLE:
|
case B_RGB24_LITTLE:
|
||||||
case B_RGB32_LITTLE:
|
case B_RGB32_LITTLE:
|
||||||
default:
|
default:
|
||||||
Write32Mask(CRT, gRegister->grphControl,
|
Write32Mask(CRT, regs->grphControl,
|
||||||
0x000002, 0x00000703);
|
0x000002, 0x00000703);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
Write32(CRT, gRegister->grphSwapControl, 0);
|
Write32(CRT, regs->grphSwapControl, 0);
|
||||||
// only for chipsets > r600
|
// only for chipsets > r600
|
||||||
// R5xx - RS690 case is GRPH_CONTROL bit 16
|
// R5xx - RS690 case is GRPH_CONTROL bit 16
|
||||||
|
|
||||||
Write32Mask(CRT, gRegister->grphEnable, 1, 0x00000001);
|
Write32Mask(CRT, regs->grphEnable, 1, 0x00000001);
|
||||||
// Enable graphics
|
// Enable graphics
|
||||||
|
|
||||||
Write32(CRT, gRegister->grphSurfaceOffsetX, 0);
|
Write32(CRT, regs->grphSurfaceOffsetX, 0);
|
||||||
Write32(CRT, gRegister->grphSurfaceOffsetY, 0);
|
Write32(CRT, regs->grphSurfaceOffsetY, 0);
|
||||||
Write32(CRT, gRegister->grphXStart, 0);
|
Write32(CRT, regs->grphXStart, 0);
|
||||||
Write32(CRT, gRegister->grphYStart, 0);
|
Write32(CRT, regs->grphYStart, 0);
|
||||||
Write32(CRT, gRegister->grphXEnd, mode->virtual_width);
|
Write32(CRT, regs->grphXEnd, mode->virtual_width);
|
||||||
Write32(CRT, gRegister->grphYEnd, mode->virtual_height);
|
Write32(CRT, regs->grphYEnd, mode->virtual_height);
|
||||||
Write32(CRT, gRegister->grphPitch, bytesPerRow / 4);
|
Write32(CRT, regs->grphPitch, bytesPerRow / 4);
|
||||||
|
|
||||||
Write32(CRT, gRegister->modeDesktopHeight, mode->virtual_height);
|
Write32(CRT, regs->modeDesktopHeight, mode->virtual_height);
|
||||||
|
|
||||||
Write32(CRT, gRegister->grphUpdate, 0);
|
Write32(CRT, regs->grphUpdate, 0);
|
||||||
// Unlock changed registers
|
// Unlock changed registers
|
||||||
|
|
||||||
// update shared info
|
// update shared info
|
||||||
@@ -232,18 +233,19 @@ CardFBSet(display_mode *mode)
|
|||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
CardModeSet(display_mode *mode)
|
CardModeSet(uint8 crtid, display_mode *mode)
|
||||||
{
|
{
|
||||||
display_timing& displayTiming = mode->timing;
|
display_timing& displayTiming = mode->timing;
|
||||||
|
register_info* regs = gDisplay[crtid]->regs;
|
||||||
|
|
||||||
TRACE("%s called to do %dx%d\n",
|
TRACE("%s called to do %dx%d\n",
|
||||||
__func__, displayTiming.h_display, displayTiming.v_display);
|
__func__, displayTiming.h_display, displayTiming.v_display);
|
||||||
|
|
||||||
// enable read requests
|
// enable read requests
|
||||||
Write32Mask(CRT, gRegister->grphControl, 0, 0x01000000);
|
Write32Mask(CRT, regs->grphControl, 0, 0x01000000);
|
||||||
|
|
||||||
// *** Horizontal
|
// *** Horizontal
|
||||||
Write32(CRT, gRegister->crtHTotal,
|
Write32(CRT, regs->crtHTotal,
|
||||||
displayTiming.h_total - 1);
|
displayTiming.h_total - 1);
|
||||||
|
|
||||||
// Blanking
|
// Blanking
|
||||||
@@ -251,55 +253,57 @@ CardModeSet(display_mode *mode)
|
|||||||
+ displayTiming.h_display - displayTiming.h_sync_start;
|
+ displayTiming.h_display - displayTiming.h_sync_start;
|
||||||
uint16 blankEnd = displayTiming.h_total - displayTiming.h_sync_start;
|
uint16 blankEnd = displayTiming.h_total - displayTiming.h_sync_start;
|
||||||
|
|
||||||
Write32(CRT, gRegister->crtHBlank,
|
Write32(CRT, regs->crtHBlank,
|
||||||
blankStart | (blankEnd << 16));
|
blankStart | (blankEnd << 16));
|
||||||
|
|
||||||
Write32(CRT, gRegister->crtHSync,
|
Write32(CRT, regs->crtHSync,
|
||||||
(displayTiming.h_sync_end - displayTiming.h_sync_start) << 16);
|
(displayTiming.h_sync_end - displayTiming.h_sync_start) << 16);
|
||||||
|
|
||||||
// set flag for neg. H sync. M76 Register Reference Guide 2-256
|
// set flag for neg. H sync. M76 Register Reference Guide 2-256
|
||||||
Write32Mask(CRT, gRegister->crtHPolarity,
|
Write32Mask(CRT, regs->crtHPolarity,
|
||||||
displayTiming.flags & B_POSITIVE_HSYNC ? 0 : 1, 0x1);
|
displayTiming.flags & B_POSITIVE_HSYNC ? 0 : 1, 0x1);
|
||||||
|
|
||||||
// *** Vertical
|
// *** Vertical
|
||||||
Write32(CRT, gRegister->crtVTotal,
|
Write32(CRT, regs->crtVTotal,
|
||||||
displayTiming.v_total - 1);
|
displayTiming.v_total - 1);
|
||||||
|
|
||||||
blankStart = displayTiming.v_total
|
blankStart = displayTiming.v_total
|
||||||
+ displayTiming.v_display - displayTiming.v_sync_start;
|
+ displayTiming.v_display - displayTiming.v_sync_start;
|
||||||
blankEnd = displayTiming.v_total - displayTiming.v_sync_start;
|
blankEnd = displayTiming.v_total - displayTiming.v_sync_start;
|
||||||
|
|
||||||
Write32(CRT, gRegister->crtVBlank,
|
Write32(CRT, regs->crtVBlank,
|
||||||
blankStart | (blankEnd << 16));
|
blankStart | (blankEnd << 16));
|
||||||
|
|
||||||
// Set Interlace if specified within mode line
|
// Set Interlace if specified within mode line
|
||||||
if (displayTiming.flags & B_TIMING_INTERLACED) {
|
if (displayTiming.flags & B_TIMING_INTERLACED) {
|
||||||
Write32(CRT, gRegister->crtInterlace, 0x1);
|
Write32(CRT, regs->crtInterlace, 0x1);
|
||||||
Write32(CRT, gRegister->modeDataFormat, 0x1);
|
Write32(CRT, regs->modeDataFormat, 0x1);
|
||||||
} else {
|
} else {
|
||||||
Write32(CRT, gRegister->crtInterlace, 0x0);
|
Write32(CRT, regs->crtInterlace, 0x0);
|
||||||
Write32(CRT, gRegister->modeDataFormat, 0x0);
|
Write32(CRT, regs->modeDataFormat, 0x0);
|
||||||
}
|
}
|
||||||
|
|
||||||
Write32(CRT, gRegister->crtVSync,
|
Write32(CRT, regs->crtVSync,
|
||||||
(displayTiming.v_sync_end - displayTiming.v_sync_start) << 16);
|
(displayTiming.v_sync_end - displayTiming.v_sync_start) << 16);
|
||||||
|
|
||||||
// set flag for neg. V sync. M76 Register Reference Guide 2-258
|
// set flag for neg. V sync. M76 Register Reference Guide 2-258
|
||||||
Write32Mask(CRT, gRegister->crtVPolarity,
|
Write32Mask(CRT, regs->crtVPolarity,
|
||||||
displayTiming.flags & B_POSITIVE_VSYNC ? 0 : 1, 0x1);
|
displayTiming.flags & B_POSITIVE_VSYNC ? 0 : 1, 0x1);
|
||||||
|
|
||||||
/* set D1CRTC_HORZ_COUNT_BY2_EN to 0;
|
/* set D1CRTC_HORZ_COUNT_BY2_EN to 0;
|
||||||
should only be set to 1 on 30bpp DVI modes
|
should only be set to 1 on 30bpp DVI modes
|
||||||
*/
|
*/
|
||||||
Write32Mask(CRT, gRegister->crtCountControl, 0x0, 0x1);
|
Write32Mask(CRT, regs->crtCountControl, 0x0, 0x1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
CardModeScale(display_mode *mode)
|
CardModeScale(uint8 crtid, display_mode *mode)
|
||||||
{
|
{
|
||||||
|
register_info* regs = gDisplay[crtid]->regs;
|
||||||
|
|
||||||
// No scaling
|
// No scaling
|
||||||
Write32(CRT, gRegister->sclUpdate, (1<<16));// Lock
|
Write32(CRT, regs->sclUpdate, (1<<16));// Lock
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
Write32(CRT, D1MODE_EXT_OVERSCAN_LEFT_RIGHT,
|
Write32(CRT, D1MODE_EXT_OVERSCAN_LEFT_RIGHT,
|
||||||
@@ -308,52 +312,40 @@ CardModeScale(display_mode *mode)
|
|||||||
(OVERSCAN << 16) | OVERSCAN); // TOP | BOTTOM
|
(OVERSCAN << 16) | OVERSCAN); // TOP | BOTTOM
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Write32(CRT, gRegister->viewportStart, 0);
|
Write32(CRT, regs->viewportStart, 0);
|
||||||
Write32(CRT, gRegister->viewportSize,
|
Write32(CRT, regs->viewportSize,
|
||||||
mode->timing.v_display | (mode->timing.h_display << 16));
|
mode->timing.v_display | (mode->timing.h_display << 16));
|
||||||
Write32(CRT, gRegister->sclEnable, 0);
|
Write32(CRT, regs->sclEnable, 0);
|
||||||
Write32(CRT, gRegister->sclTapControl, 0);
|
Write32(CRT, regs->sclTapControl, 0);
|
||||||
Write32(CRT, gRegister->modeCenter, 2);
|
Write32(CRT, regs->modeCenter, 2);
|
||||||
// D1MODE_DATA_FORMAT?
|
// D1MODE_DATA_FORMAT?
|
||||||
Write32(CRT, gRegister->sclUpdate, 0); // Unlock
|
Write32(CRT, regs->sclUpdate, 0); // Unlock
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
radeon_set_display_mode(display_mode *mode)
|
radeon_set_display_mode(display_mode *mode)
|
||||||
{
|
{
|
||||||
uint8 crtNumber = 0;
|
uint8 display_id = 0;
|
||||||
uint8 dacNumber = 0;
|
|
||||||
|
|
||||||
init_registers(crtNumber);
|
CardFBSet(display_id, mode);
|
||||||
|
CardModeSet(display_id, mode);
|
||||||
|
CardModeScale(display_id, mode);
|
||||||
|
|
||||||
// TODO Populate gCRT with interface connection
|
// If this is DAC, set our PLL
|
||||||
if (DACSense(0))
|
if ((gDisplay[display_id]->connection_type & CONNECTION_DAC) != 0) {
|
||||||
dacNumber = 0;
|
PLLSet(gDisplay[display_id]->connection_id, mode->timing.pixel_clock);
|
||||||
else if (DACSense(1))
|
DACSet(gDisplay[display_id]->connection_id, display_id);
|
||||||
dacNumber = 1;
|
|
||||||
|
|
||||||
TMDSSense(0); // DVI / HDMI
|
|
||||||
|
|
||||||
CardFBSet(mode);
|
|
||||||
CardModeSet(mode);
|
|
||||||
CardModeScale(mode);
|
|
||||||
|
|
||||||
PLLSet(dacNumber, mode->timing.pixel_clock);
|
|
||||||
// Set pixel clock
|
|
||||||
|
|
||||||
Write32(CRT, D1GRPH_LUT_SEL, 0);
|
|
||||||
|
|
||||||
DACSet(dacNumber, crtNumber);
|
|
||||||
|
|
||||||
// TODO : Shutdown unused PLL/DAC
|
// TODO : Shutdown unused PLL/DAC
|
||||||
|
|
||||||
// Power up the output
|
// Power up the output
|
||||||
PLLPower(dacNumber, RHD_POWER_ON);
|
PLLPower(gDisplay[display_id]->connection_id, RHD_POWER_ON);
|
||||||
DACPower(dacNumber, RHD_POWER_ON);
|
DACPower(gDisplay[display_id]->connection_id, RHD_POWER_ON);
|
||||||
|
}
|
||||||
|
|
||||||
// Ensure screen isn't blanked
|
// Ensure screen isn't blanked
|
||||||
CardBlankSet(crtNumber, false);
|
CardBlankSet(display_id, false);
|
||||||
|
|
||||||
int32 crtstatus = Read32(CRT, D1CRTC_STATUS);
|
int32 crtstatus = Read32(CRT, D1CRTC_STATUS);
|
||||||
TRACE("CRT0 Status: 0x%X\n", crtstatus);
|
TRACE("CRT0 Status: 0x%X\n", crtstatus);
|
||||||
@@ -430,16 +422,17 @@ is_mode_supported(display_mode *mode)
|
|||||||
if (is_mode_sane(mode) != B_OK)
|
if (is_mode_sane(mode) != B_OK)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
// TODO : is_mode_supported on *which* display?
|
||||||
uint32 crtid = 0;
|
uint32 crtid = 0;
|
||||||
|
|
||||||
// if we have edid info, check frequency adginst crt reported valid ranges
|
// if we have edid info, check frequency adginst crt reported valid ranges
|
||||||
if (gInfo->shared_info->has_edid) {
|
if (gInfo->shared_info->has_edid) {
|
||||||
|
|
||||||
uint32 hfreq = mode->timing.pixel_clock / mode->timing.h_total;
|
uint32 hfreq = mode->timing.pixel_clock / mode->timing.h_total;
|
||||||
if (hfreq > gCRT[crtid]->hfreq_max + 1
|
if (hfreq > gDisplay[crtid]->hfreq_max + 1
|
||||||
|| hfreq < gCRT[crtid]->hfreq_min - 1) {
|
|| hfreq < gDisplay[crtid]->hfreq_min - 1) {
|
||||||
TRACE("!!! hfreq : %d , hfreq_min : %d, hfreq_max : %d\n",
|
TRACE("!!! hfreq : %d , hfreq_min : %d, hfreq_max : %d\n",
|
||||||
hfreq, gCRT[crtid]->hfreq_min, gCRT[crtid]->hfreq_max);
|
hfreq, gDisplay[crtid]->hfreq_min, gDisplay[crtid]->hfreq_max);
|
||||||
TRACE("!!! %dx%d falls outside of CRT %d's valid "
|
TRACE("!!! %dx%d falls outside of CRT %d's valid "
|
||||||
"horizontal range.\n", mode->timing.h_display,
|
"horizontal range.\n", mode->timing.h_display,
|
||||||
mode->timing.v_display, crtid);
|
mode->timing.v_display, crtid);
|
||||||
@@ -449,10 +442,10 @@ is_mode_supported(display_mode *mode)
|
|||||||
uint32 vfreq = mode->timing.pixel_clock / ((mode->timing.v_total
|
uint32 vfreq = mode->timing.pixel_clock / ((mode->timing.v_total
|
||||||
* mode->timing.h_total) / 1000);
|
* mode->timing.h_total) / 1000);
|
||||||
|
|
||||||
if (vfreq > gCRT[crtid]->vfreq_max + 1
|
if (vfreq > gDisplay[crtid]->vfreq_max + 1
|
||||||
|| vfreq < gCRT[crtid]->vfreq_min - 1) {
|
|| vfreq < gDisplay[crtid]->vfreq_min - 1) {
|
||||||
TRACE("!!! vfreq : %d , vfreq_min : %d, vfreq_max : %d\n",
|
TRACE("!!! vfreq : %d , vfreq_min : %d, vfreq_max : %d\n",
|
||||||
vfreq, gCRT[crtid]->vfreq_min, gCRT[crtid]->vfreq_max);
|
vfreq, gDisplay[crtid]->vfreq_min, gDisplay[crtid]->vfreq_max);
|
||||||
TRACE("!!! %dx%d falls outside of CRT %d's valid vertical range\n",
|
TRACE("!!! %dx%d falls outside of CRT %d's valid vertical range\n",
|
||||||
mode->timing.h_display, mode->timing.v_display, crtid);
|
mode->timing.h_display, mode->timing.v_display, crtid);
|
||||||
return false;
|
return false;
|
||||||
@@ -518,33 +511,3 @@ is_mode_sane(display_mode *mode)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// 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;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -25,7 +25,7 @@
|
|||||||
#define OVERSCAN 0
|
#define OVERSCAN 0
|
||||||
// TODO : Overscan and scaling support
|
// TODO : Overscan and scaling support
|
||||||
|
|
||||||
status_t detect_crt_ranges();
|
|
||||||
status_t create_mode_list(void);
|
status_t create_mode_list(void);
|
||||||
bool is_mode_supported(display_mode* mode);
|
bool is_mode_supported(display_mode* mode);
|
||||||
status_t is_mode_sane(display_mode *mode);
|
status_t is_mode_sane(display_mode *mode);
|
||||||
|
|||||||
@@ -345,8 +345,8 @@ PLLSetLowLegacy(uint8 pllIndex, uint32 pixelClock, uint16 reference,
|
|||||||
Write32(PLL, pllExtPostDivSrc, 0x01);
|
Write32(PLL, pllExtPostDivSrc, 0x01);
|
||||||
// Set source as PLL
|
// Set source as PLL
|
||||||
|
|
||||||
// TODO : better way to grab crt to work on?
|
// TODO : for now we assume crt 0, needs refactoring
|
||||||
PLLCRTCGrab(pllIndex, gRegister->crtid);
|
PLLCRTCGrab(pllIndex, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -461,8 +461,8 @@ PLLSetLowR620(uint8 pllIndex, uint32 pixelClock, uint16 reference,
|
|||||||
Write32Mask(PLL, pllCntl, 0, 0x80000000);
|
Write32Mask(PLL, pllCntl, 0, 0x80000000);
|
||||||
// needed and undocumented
|
// needed and undocumented
|
||||||
|
|
||||||
// TODO : better way to grab crt to work on?
|
// TODO : for now we assume crt 0, needs refactoring
|
||||||
PLLCRTCGrab(pllIndex, gRegister->crtid);
|
PLLCRTCGrab(pllIndex, 0);
|
||||||
|
|
||||||
if (hasDccg)
|
if (hasDccg)
|
||||||
DCCGCLKSet(pllIndex, RV620_DCCGCLK_GRAB);
|
DCCGCLKSet(pllIndex, RV620_DCCGCLK_GRAB);
|
||||||
|
|||||||
Reference in New Issue
Block a user