Work in progress of a Radeon HD 3200 driver to change the display mode (status when I leave the coding spring). At least it shows a picture but with a wrong scaling.
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@36243 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright 2006-2008, Haiku, Inc. All Rights Reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Axel Dörfler, [email protected]
|
||||
*/
|
||||
#ifndef AREA_KEEPER_H
|
||||
#define AREA_KEEPER_H
|
||||
|
||||
|
||||
#include <KernelExport.h>
|
||||
#include <OS.h>
|
||||
|
||||
#include <util/kernel_cpp.h>
|
||||
|
||||
|
||||
class AreaKeeper {
|
||||
public:
|
||||
AreaKeeper();
|
||||
~AreaKeeper();
|
||||
|
||||
area_id Create(const char *name, void **_virtualAddress, uint32 spec,
|
||||
size_t size, uint32 lock, uint32 protection);
|
||||
area_id Map(const char *name, void *physicalAddress, size_t numBytes,
|
||||
uint32 spec, uint32 protection, void **_virtualAddress);
|
||||
|
||||
status_t InitCheck() { return fArea < B_OK ? (status_t)fArea : B_OK; }
|
||||
void Detach();
|
||||
|
||||
private:
|
||||
area_id fArea;
|
||||
};
|
||||
|
||||
|
||||
AreaKeeper::AreaKeeper()
|
||||
:
|
||||
fArea(-1)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
AreaKeeper::~AreaKeeper()
|
||||
{
|
||||
if (fArea >= B_OK)
|
||||
delete_area(fArea);
|
||||
}
|
||||
|
||||
|
||||
area_id
|
||||
AreaKeeper::Create(const char *name, void **_virtualAddress, uint32 spec,
|
||||
size_t size, uint32 lock, uint32 protection)
|
||||
{
|
||||
fArea = create_area(name, _virtualAddress, spec, size, lock, protection);
|
||||
return fArea;
|
||||
}
|
||||
|
||||
|
||||
area_id
|
||||
AreaKeeper::Map(const char *name, void *physicalAddress, size_t numBytes,
|
||||
uint32 spec, uint32 protection, void **_virtualAddress)
|
||||
{
|
||||
fArea = map_physical_memory(name, physicalAddress, numBytes, spec, protection,
|
||||
_virtualAddress);
|
||||
return fArea;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
AreaKeeper::Detach()
|
||||
{
|
||||
fArea = -1;
|
||||
}
|
||||
|
||||
#endif // AREA_KEEPER_H
|
||||
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Copyright 2006, Haiku, Inc. All Rights Reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Axel Dörfler, [email protected]
|
||||
*/
|
||||
#ifndef LOCK_H
|
||||
#define LOCK_H
|
||||
|
||||
|
||||
#include <OS.h>
|
||||
|
||||
|
||||
typedef struct lock {
|
||||
sem_id sem;
|
||||
vint32 count;
|
||||
} lock;
|
||||
|
||||
|
||||
static inline status_t
|
||||
init_lock(struct lock *lock, const char *name)
|
||||
{
|
||||
lock->sem = create_sem(0, name);
|
||||
lock->count = 0;
|
||||
|
||||
return lock->sem < B_OK ? lock->sem : B_OK;
|
||||
}
|
||||
|
||||
|
||||
static inline void
|
||||
uninit_lock(struct lock *lock)
|
||||
{
|
||||
delete_sem(lock->sem);
|
||||
}
|
||||
|
||||
|
||||
static inline status_t
|
||||
acquire_lock(struct lock *lock)
|
||||
{
|
||||
if (atomic_add(&lock->count, 1) > 0)
|
||||
return acquire_sem(lock->sem);
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
static inline status_t
|
||||
release_lock(struct lock *lock)
|
||||
{
|
||||
if (atomic_add(&lock->count, -1) > 1)
|
||||
return release_sem(lock->sem);
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
class Autolock {
|
||||
public:
|
||||
Autolock(struct lock &lock)
|
||||
:
|
||||
fLock(&lock)
|
||||
{
|
||||
fStatus = acquire_lock(fLock);
|
||||
}
|
||||
|
||||
~Autolock()
|
||||
{
|
||||
if (fStatus == B_OK)
|
||||
release_lock(fLock);
|
||||
}
|
||||
|
||||
bool
|
||||
IsLocked() const
|
||||
{
|
||||
return fStatus == B_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
status_t fStatus;
|
||||
struct lock *fLock;
|
||||
};
|
||||
|
||||
#endif /* LOCK_H */
|
||||
@@ -0,0 +1,655 @@
|
||||
/*
|
||||
* Copyright 2006-2009, Haiku, Inc. All Rights Reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Axel Dörfler, [email protected]
|
||||
*/
|
||||
#ifndef RADEON_HD_H
|
||||
#define RADEON_HD_H
|
||||
|
||||
|
||||
#include "lock.h"
|
||||
|
||||
#include <Accelerant.h>
|
||||
#include <Drivers.h>
|
||||
#include <PCI.h>
|
||||
|
||||
|
||||
#define VENDOR_ID_ATI 0x8086
|
||||
|
||||
#define RADEON_TYPE_FAMILY_MASK 0xf000
|
||||
#define RADEON_TYPE_GROUP_MASK 0xfff0
|
||||
#define RADEON_TYPE_MODEL_MASK 0xffff
|
||||
// families
|
||||
#define RADEON_TYPE_7xx 0x1000
|
||||
#define RADEON_TYPE_8xx 0x2000
|
||||
#define RADEON_TYPE_9xx 0x4000
|
||||
// groups
|
||||
#define RADEON_TYPE_83x (RADEON_TYPE_8xx | 0x0010)
|
||||
#define RADEON_TYPE_85x (RADEON_TYPE_8xx | 0x0020)
|
||||
#define RADEON_TYPE_91x (RADEON_TYPE_9xx | 0x0040)
|
||||
#define RADEON_TYPE_94x (RADEON_TYPE_9xx | 0x0080)
|
||||
#define RADEON_TYPE_96x (RADEON_TYPE_9xx | 0x0100)
|
||||
#define RADEON_TYPE_Gxx (RADEON_TYPE_9xx | 0x0200)
|
||||
#define RADEON_TYPE_G4x (RADEON_TYPE_9xx | 0x0400)
|
||||
// models
|
||||
#define RADEON_TYPE_MOBILE 0x0008
|
||||
#define RADEON_TYPE_915 (RADEON_TYPE_91x)
|
||||
#define RADEON_TYPE_945 (RADEON_TYPE_94x)
|
||||
#define RADEON_TYPE_945M (RADEON_TYPE_94x | RADEON_TYPE_MOBILE)
|
||||
#define RADEON_TYPE_965 (RADEON_TYPE_96x)
|
||||
#define RADEON_TYPE_965M (RADEON_TYPE_96x | RADEON_TYPE_MOBILE)
|
||||
#define RADEON_TYPE_G33 (RADEON_TYPE_Gxx)
|
||||
#define RADEON_TYPE_G45 (RADEON_TYPE_G4x)
|
||||
#define RADEON_TYPE_GM45 (RADEON_TYPE_G4x | RADEON_TYPE_MOBILE)
|
||||
|
||||
#define DEVICE_NAME "radeon_hd"
|
||||
#define RADEON_ACCELERANT_NAME "radeon_hd.accelerant"
|
||||
|
||||
struct DeviceType {
|
||||
uint32 type;
|
||||
|
||||
DeviceType(int t)
|
||||
{
|
||||
type = t;
|
||||
}
|
||||
|
||||
DeviceType& operator=(int t)
|
||||
{
|
||||
type = t;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool InFamily(uint32 family) const
|
||||
{
|
||||
return (type & RADEON_TYPE_FAMILY_MASK) == family;
|
||||
}
|
||||
|
||||
bool InGroup(uint32 group) const
|
||||
{
|
||||
return (type & RADEON_TYPE_GROUP_MASK) == group;
|
||||
}
|
||||
|
||||
bool IsModel(uint32 model) const
|
||||
{
|
||||
return (type & RADEON_TYPE_MODEL_MASK) == model;
|
||||
}
|
||||
};
|
||||
|
||||
// info about PLL on graphics card
|
||||
struct pll_info {
|
||||
uint32 reference_frequency;
|
||||
uint32 max_frequency;
|
||||
uint32 min_frequency;
|
||||
uint32 divisor_register;
|
||||
};
|
||||
|
||||
struct ring_buffer {
|
||||
struct lock lock;
|
||||
uint32 register_base;
|
||||
uint32 offset;
|
||||
uint32 size;
|
||||
uint32 position;
|
||||
uint32 space_left;
|
||||
uint8* base;
|
||||
};
|
||||
|
||||
struct overlay_registers;
|
||||
|
||||
struct radeon_shared_info {
|
||||
area_id mode_list_area; // area containing display mode list
|
||||
uint32 mode_count;
|
||||
|
||||
display_mode current_mode;
|
||||
uint32 bytes_per_row;
|
||||
uint32 bits_per_pixel;
|
||||
uint32 dpms_mode;
|
||||
|
||||
area_id registers_area; // area of memory mapped registers
|
||||
uint8* status_page;
|
||||
addr_t physical_status_page;
|
||||
uint8* graphics_memory;
|
||||
addr_t physical_graphics_memory;
|
||||
uint32 graphics_memory_size;
|
||||
|
||||
addr_t frame_buffer;
|
||||
uint32 frame_buffer_offset;
|
||||
|
||||
struct lock accelerant_lock;
|
||||
struct lock engine_lock;
|
||||
|
||||
ring_buffer primary_ring_buffer;
|
||||
|
||||
int32 overlay_channel_used;
|
||||
bool overlay_active;
|
||||
uint32 overlay_token;
|
||||
addr_t physical_overlay_registers;
|
||||
uint32 overlay_offset;
|
||||
|
||||
bool hardware_cursor_enabled;
|
||||
sem_id vblank_sem;
|
||||
|
||||
uint8* cursor_memory;
|
||||
addr_t physical_cursor_memory;
|
||||
uint32 cursor_buffer_offset;
|
||||
uint32 cursor_format;
|
||||
bool cursor_visible;
|
||||
uint16 cursor_hot_x;
|
||||
uint16 cursor_hot_y;
|
||||
|
||||
DeviceType device_type;
|
||||
char device_identifier[32];
|
||||
struct pll_info pll_info;
|
||||
};
|
||||
|
||||
//----------------- ioctl() interface ----------------
|
||||
|
||||
// magic code for ioctls
|
||||
#define RADEON_PRIVATE_DATA_MAGIC 'rdhd'
|
||||
|
||||
// list ioctls
|
||||
enum {
|
||||
RADEON_GET_PRIVATE_DATA = B_DEVICE_OP_CODES_END + 1,
|
||||
|
||||
RADEON_GET_DEVICE_NAME,
|
||||
RADEON_ALLOCATE_GRAPHICS_MEMORY,
|
||||
RADEON_FREE_GRAPHICS_MEMORY
|
||||
};
|
||||
|
||||
// retrieve the area_id of the kernel/accelerant shared info
|
||||
struct radeon_get_private_data {
|
||||
uint32 magic; // magic number
|
||||
area_id shared_info_area;
|
||||
};
|
||||
|
||||
// allocate graphics memory
|
||||
struct radeon_allocate_graphics_memory {
|
||||
uint32 magic;
|
||||
uint32 size;
|
||||
uint32 alignment;
|
||||
uint32 flags;
|
||||
uint32 buffer_base;
|
||||
};
|
||||
|
||||
// free graphics memory
|
||||
struct radeon_free_graphics_memory {
|
||||
uint32 magic;
|
||||
uint32 buffer_base;
|
||||
};
|
||||
|
||||
//----------------------------------------------------------
|
||||
// Register definitions, taken from X driver
|
||||
|
||||
// PCI bridge memory management
|
||||
#define RADEON_GRAPHICS_MEMORY_CONTROL 0x52 // GGC - (G)MCH Graphics Control Register
|
||||
#define MEMORY_CONTROL_ENABLED 0x0004
|
||||
#define MEMORY_MASK 0x0001
|
||||
#define STOLEN_MEMORY_MASK 0x00f0
|
||||
#define i965_GTT_MASK 0x000e
|
||||
#define G33_GTT_MASK 0x0300
|
||||
#define G4X_GTT_MASK 0x0f00 // GGMS (GSM Memory Size) mask
|
||||
|
||||
// models i830 and up
|
||||
#define i830_LOCAL_MEMORY_ONLY 0x10
|
||||
#define i830_STOLEN_512K 0x20
|
||||
#define i830_STOLEN_1M 0x30
|
||||
#define i830_STOLEN_8M 0x40
|
||||
#define i830_FRAME_BUFFER_64M 0x01
|
||||
#define i830_FRAME_BUFFER_128M 0x00
|
||||
|
||||
// models i855 and up
|
||||
#define i855_STOLEN_MEMORY_1M 0x10
|
||||
#define i855_STOLEN_MEMORY_4M 0x20
|
||||
#define i855_STOLEN_MEMORY_8M 0x30
|
||||
#define i855_STOLEN_MEMORY_16M 0x40
|
||||
#define i855_STOLEN_MEMORY_32M 0x50
|
||||
#define i855_STOLEN_MEMORY_48M 0x60
|
||||
#define i855_STOLEN_MEMORY_64M 0x70
|
||||
#define i855_STOLEN_MEMORY_128M 0x80
|
||||
#define i855_STOLEN_MEMORY_256M 0x90
|
||||
|
||||
#define G4X_STOLEN_MEMORY_96MB 0xa0 // GMS - Graphics Mode Select
|
||||
#define G4X_STOLEN_MEMORY_160MB 0xb0
|
||||
#define G4X_STOLEN_MEMORY_224MB 0xc0
|
||||
#define G4X_STOLEN_MEMORY_352MB 0xd0
|
||||
|
||||
|
||||
// graphics page translation table
|
||||
#define RADEON_PAGE_TABLE_CONTROL 0x02020
|
||||
#define PAGE_TABLE_ENABLED 0x00000001
|
||||
#define RADEON_PAGE_TABLE_ERROR 0x02024
|
||||
#define RADEON_HARDWARE_STATUS_PAGE 0x02080
|
||||
#define i915_GTT_BASE 0x1c
|
||||
#define i830_GTT_BASE 0x10000 // (- 0x2ffff)
|
||||
#define i830_GTT_SIZE 0x20000
|
||||
#define i965_GTT_BASE 0x80000 // (- 0xfffff)
|
||||
#define i965_GTT_SIZE 0x80000
|
||||
#define i965_GTT_128K (2 << 1)
|
||||
#define i965_GTT_256K (1 << 1)
|
||||
#define i965_GTT_512K (0 << 1)
|
||||
#define G33_GTT_1M (1 << 8)
|
||||
#define G33_GTT_2M (2 << 8)
|
||||
#define G4X_GTT_NONE 0x000 // GGMS - GSM Memory Size
|
||||
#define G4X_GTT_1M_NO_IVT 0x100 // no Intel Virtualization Tech.
|
||||
#define G4X_GTT_2M_NO_IVT 0x300
|
||||
#define G4X_GTT_2M_IVT 0x900 // with Intel Virt. Tech.
|
||||
#define G4X_GTT_3M_IVT 0xa00
|
||||
#define G4X_GTT_4M_IVT 0xb00
|
||||
|
||||
|
||||
#define GTT_ENTRY_VALID 0x01
|
||||
#define GTT_ENTRY_LOCAL_MEMORY 0x02
|
||||
#define GTT_PAGE_SHIFT 12
|
||||
|
||||
// interrupts
|
||||
#define RADEON_INTERRUPT_ENABLED 0x020a0
|
||||
#define RADEON_INTERRUPT_IDENTITY 0x020a4
|
||||
#define RADEON_INTERRUPT_MASK 0x020a8
|
||||
#define RADEON_INTERRUPT_STATUS 0x020ac
|
||||
#define INTERRUPT_VBLANK (1 << 7)
|
||||
|
||||
// ring buffer
|
||||
#define RADEON_PRIMARY_RING_BUFFER 0x02030
|
||||
#define RADEON_SECONDARY_RING_BUFFER_0 0x02100
|
||||
#define RADEON_SECONDARY_RING_BUFFER_1 0x02110
|
||||
// offsets for the ring buffer base registers above
|
||||
#define RING_BUFFER_TAIL 0x0
|
||||
#define RING_BUFFER_HEAD 0x4
|
||||
#define RING_BUFFER_START 0x8
|
||||
#define RING_BUFFER_CONTROL 0xc
|
||||
#define RADEON_RING_BUFFER_SIZE_MASK 0x001ff000
|
||||
#define RADEON_RING_BUFFER_HEAD_MASK 0x001ffffc
|
||||
#define RADEON_RING_BUFFER_ENABLED 1
|
||||
|
||||
// display ports
|
||||
#define RADEON_DISPLAY_A_ANALOG_PORT 0x61100
|
||||
#define DISPLAY_MONITOR_PORT_ENABLED (1UL << 31)
|
||||
#define DISPLAY_MONITOR_PIPE_B (1UL << 30)
|
||||
#define DISPLAY_MONITOR_VGA_POLARITY (1UL << 15)
|
||||
#define DISPLAY_MONITOR_MODE_MASK (3UL << 10)
|
||||
#define DISPLAY_MONITOR_ON 0
|
||||
#define DISPLAY_MONITOR_SUSPEND (1UL << 10)
|
||||
#define DISPLAY_MONITOR_STAND_BY (2UL << 10)
|
||||
#define DISPLAY_MONITOR_OFF (3UL << 10)
|
||||
#define DISPLAY_MONITOR_POLARITY_MASK (3UL << 3)
|
||||
#define DISPLAY_MONITOR_POSITIVE_HSYNC (1UL << 3)
|
||||
#define DISPLAY_MONITOR_POSITIVE_VSYNC (2UL << 3)
|
||||
#define RADEON_DISPLAY_A_DIGITAL_PORT 0x61120
|
||||
#define RADEON_DISPLAY_C_DIGITAL 0x61160
|
||||
#define RADEON_DISPLAY_LVDS_PORT 0x61180
|
||||
#define LVDS_POST2_RATE_SLOW 14 // PLL Divisors
|
||||
#define LVDS_POST2_RATE_FAST 7
|
||||
#define LVDS_CLKB_POWER_MASK (3 << 4)
|
||||
#define LVDS_CLKB_POWER_UP (3 << 4)
|
||||
#define LVDS_PORT_EN (1 << 31)
|
||||
#define LVDS_A0A2_CLKA_POWER_UP (3 << 8)
|
||||
#define LVDS_PIPEB_SELECT (1 << 30)
|
||||
#define LVDS_B0B3PAIRS_POWER_UP (3 << 2)
|
||||
#define LVDS_PLL_MODE_LVDS (2 << 26)
|
||||
|
||||
// PLL flags
|
||||
#define DISPLAY_PLL_ENABLED (1UL << 31)
|
||||
#define DISPLAY_PLL_2X_CLOCK (1UL << 30)
|
||||
#define DISPLAY_PLL_SYNC_LOCK_ENABLED (1UL << 29)
|
||||
#define DISPLAY_PLL_NO_VGA_CONTROL (1UL << 28)
|
||||
#define DISPLAY_PLL_MODE_ANALOG (1UL << 26)
|
||||
#define DISPLAY_PLL_DIVIDE_HIGH (1UL << 24)
|
||||
#define DISPLAY_PLL_DIVIDE_4X (1UL << 23)
|
||||
#define DISPLAY_PLL_POST1_DIVIDE_2 (1UL << 21)
|
||||
#define DISPLAY_PLL_POST1_DIVISOR_MASK 0x001f0000
|
||||
#define DISPLAY_PLL_9xx_POST1_DIVISOR_MASK 0x00ff0000
|
||||
#define DISPLAY_PLL_POST1_DIVISOR_SHIFT 16
|
||||
#define DISPLAY_PLL_DIVISOR_1 (1UL << 8)
|
||||
#define DISPLAY_PLL_N_DIVISOR_MASK 0x001f0000
|
||||
#define DISPLAY_PLL_M1_DIVISOR_MASK 0x00001f00
|
||||
#define DISPLAY_PLL_M2_DIVISOR_MASK 0x0000001f
|
||||
#define DISPLAY_PLL_N_DIVISOR_SHIFT 16
|
||||
#define DISPLAY_PLL_M1_DIVISOR_SHIFT 8
|
||||
#define DISPLAY_PLL_M2_DIVISOR_SHIFT 0
|
||||
#define DISPLAY_PLL_PULSE_PHASE_SHIFT 9
|
||||
|
||||
// display A
|
||||
#define RADEON_DISPLAY_A_HTOTAL 0x60000
|
||||
#define RADEON_DISPLAY_A_HBLANK 0x60004
|
||||
#define RADEON_DISPLAY_A_HSYNC 0x60008
|
||||
#define RADEON_DISPLAY_A_VTOTAL 0x6000c
|
||||
#define RADEON_DISPLAY_A_VBLANK 0x60010
|
||||
#define RADEON_DISPLAY_A_VSYNC 0x60014
|
||||
#define RADEON_DISPLAY_A_IMAGE_SIZE 0x6001c
|
||||
|
||||
#define RADEON_DISPLAY_A_CONTROL 0x70180
|
||||
#define RADEON_DISPLAY_A_BASE 0x70184
|
||||
#define RADEON_DISPLAY_A_BYTES_PER_ROW 0x70188
|
||||
#define RADEON_DISPLAY_A_SURFACE 0x7019c // i965 and up only
|
||||
#define DISPLAY_CONTROL_ENABLED (1UL << 31)
|
||||
#define DISPLAY_CONTROL_GAMMA (1UL << 30)
|
||||
#define DISPLAY_CONTROL_COLOR_MASK (0x0fUL << 26)
|
||||
#define DISPLAY_CONTROL_CMAP8 (2UL << 26)
|
||||
#define DISPLAY_CONTROL_RGB15 (4UL << 26)
|
||||
#define DISPLAY_CONTROL_RGB16 (5UL << 26)
|
||||
#define DISPLAY_CONTROL_RGB32 (6UL << 26)
|
||||
|
||||
#define RADEON_VGA_DISPLAY_CONTROL 0x71400
|
||||
#define VGA_DISPLAY_DISABLED (1UL << 31)
|
||||
|
||||
#define RADEON_DISPLAY_A_PALETTE 0x0a000
|
||||
|
||||
#define RADEON_DISPLAY_A_PIPE_CONTROL 0x70008
|
||||
#define DISPLAY_PIPE_ENABLED (1UL << 31)
|
||||
#define RADEON_DISPLAY_A_PIPE_STATUS 0x70024
|
||||
#define DISPLAY_PIPE_VBLANK_ENABLED (1UL << 17)
|
||||
#define DISPLAY_PIPE_VBLANK_STATUS (1UL << 1)
|
||||
|
||||
#define RADEON_DISPLAY_A_PLL 0x06014
|
||||
#define RADEON_DISPLAY_A_PLL_DIVISOR_0 0x06040
|
||||
#define RADEON_DISPLAY_A_PLL_DIVISOR_1 0x06044
|
||||
|
||||
// display B
|
||||
#define RADEON_DISPLAY_B_HTOTAL 0x61000
|
||||
#define RADEON_DISPLAY_B_HBLANK 0x61004
|
||||
#define RADEON_DISPLAY_B_HSYNC 0x61008
|
||||
#define RADEON_DISPLAY_B_VTOTAL 0x6100c
|
||||
#define RADEON_DISPLAY_B_VBLANK 0x61010
|
||||
#define RADEON_DISPLAY_B_VSYNC 0x61014
|
||||
|
||||
#define RADEON_DISPLAY_B_DIGITAL_PORT 0x61140
|
||||
#define RADEON_DISPLAY_B_PIPE_SIZE 0x71190
|
||||
|
||||
#define RADEON_DISPLAY_B_PIPE_CONTROL 0x71008
|
||||
|
||||
#define RADEON_DISPLAY_B_CONTROL 0x71180
|
||||
#define RADEON_DISPLAY_B_BASE 0x71184
|
||||
#define RADEON_DISPLAY_B_BYTES_PER_ROW 0x71188
|
||||
#define RADEON_DISPLAY_B_POS 0x7118C
|
||||
|
||||
#define RADEON_DISPLAY_B_IMAGE_SIZE 0x6101c
|
||||
#define RADEON_DISPLAY_B_SURFACE 0x7119c // i965 and up only
|
||||
|
||||
#define RADEON_DISPLAY_B_PALETTE 0x0a800
|
||||
|
||||
#define RADEON_DISPLAY_B_PLL 0x06018
|
||||
#define RADEON_DISPLAY_B_PLL_MULTIPLIER_DIVISOR 0x06020
|
||||
#define RADEON_DISPLAY_B_PLL_DIVISOR_0 0x06048
|
||||
#define RADEON_DISPLAY_B_PLL_DIVISOR_1 0x0604c
|
||||
|
||||
// LVDS panel
|
||||
#define RADEON_PANEL_STATUS 0x61200
|
||||
#define PANEL_STATUS_POWER_ON (1UL << 31)
|
||||
#define RADEON_PANEL_CONTROL 0x61204
|
||||
#define PANEL_CONTROL_POWER_TARGET_ON (1UL << 0)
|
||||
#define RADEON_PANEL_FIT_CONTROL 0x61230
|
||||
#define RADEON_PANEL_FIT_RATIOS 0x61234
|
||||
|
||||
// cursor
|
||||
#define RADEON_CURSOR_CONTROL 0x70080
|
||||
#define RADEON_CURSOR_BASE 0x70084
|
||||
#define RADEON_CURSOR_POSITION 0x70088
|
||||
#define RADEON_CURSOR_PALETTE 0x70090 // (- 0x7009f)
|
||||
#define RADEON_CURSOR_SIZE 0x700a0
|
||||
#define CURSOR_ENABLED (1UL << 31)
|
||||
#define CURSOR_FORMAT_2_COLORS (0UL << 24)
|
||||
#define CURSOR_FORMAT_3_COLORS (1UL << 24)
|
||||
#define CURSOR_FORMAT_4_COLORS (2UL << 24)
|
||||
#define CURSOR_FORMAT_ARGB (4UL << 24)
|
||||
#define CURSOR_FORMAT_XRGB (5UL << 24)
|
||||
#define CURSOR_POSITION_NEGATIVE 0x8000
|
||||
#define CURSOR_POSITION_MASK 0x3fff
|
||||
|
||||
// ring buffer commands
|
||||
|
||||
#define COMMAND_NOOP 0x00
|
||||
#define COMMAND_WAIT_FOR_EVENT (0x03 << 23)
|
||||
#define COMMAND_WAIT_FOR_OVERLAY_FLIP (1 << 16)
|
||||
|
||||
#define COMMAND_FLUSH (0x04 << 23)
|
||||
|
||||
// overlay flip
|
||||
#define COMMAND_OVERLAY_FLIP (0x11 << 23)
|
||||
#define COMMAND_OVERLAY_CONTINUE (0 << 21)
|
||||
#define COMMAND_OVERLAY_ON (1 << 21)
|
||||
#define COMMAND_OVERLAY_OFF (2 << 21)
|
||||
#define OVERLAY_UPDATE_COEFFICIENTS 0x1
|
||||
|
||||
// 2D acceleration
|
||||
#define XY_COMMAND_SOURCE_BLIT 0x54c00006
|
||||
#define XY_COMMAND_COLOR_BLIT 0x54000004
|
||||
#define XY_COMMAND_SETUP_MONO_PATTERN 0x44400007
|
||||
#define XY_COMMAND_SCANLINE_BLIT 0x49400001
|
||||
#define COMMAND_COLOR_BLIT 0x50000003
|
||||
#define COMMAND_BLIT_RGBA 0x00300000
|
||||
|
||||
#define COMMAND_MODE_SOLID_PATTERN 0x80
|
||||
#define COMMAND_MODE_CMAP8 0x00
|
||||
#define COMMAND_MODE_RGB15 0x02
|
||||
#define COMMAND_MODE_RGB16 0x01
|
||||
#define COMMAND_MODE_RGB32 0x03
|
||||
|
||||
// i2c
|
||||
|
||||
#define RADEON_I2C_IO_A 0x5010
|
||||
#define RADEON_I2C_IO_B 0x5014
|
||||
#define RADEON_I2C_IO_C 0x5018
|
||||
#define RADEON_I2C_IO_D 0x501c
|
||||
#define RADEON_I2C_IO_E 0x5020
|
||||
#define RADEON_I2C_IO_F 0x5024
|
||||
#define RADEON_I2C_IO_G 0x5028
|
||||
#define RADEON_I2C_IO_H 0x502c
|
||||
|
||||
#define I2C_CLOCK_DIRECTION_MASK (1 << 0)
|
||||
#define I2C_CLOCK_DIRECTION_OUT (1 << 1)
|
||||
#define I2C_CLOCK_VALUE_MASK (1 << 2)
|
||||
#define I2C_CLOCK_VALUE_OUT (1 << 3)
|
||||
#define I2C_CLOCK_VALUE_IN (1 << 4)
|
||||
#define I2C_DATA_DIRECTION_MASK (1 << 8)
|
||||
#define I2C_DATA_DIRECTION_OUT (1 << 9)
|
||||
#define I2C_DATA_VALUE_MASK (1 << 10)
|
||||
#define I2C_DATA_VALUE_OUT (1 << 11)
|
||||
#define I2C_DATA_VALUE_IN (1 << 12)
|
||||
#define I2C_RESERVED ((1 << 13) | (1 << 5))
|
||||
|
||||
// overlay
|
||||
|
||||
#define RADEON_OVERLAY_UPDATE 0x30000
|
||||
#define RADEON_OVERLAY_TEST 0x30004
|
||||
#define RADEON_OVERLAY_STATUS 0x30008
|
||||
#define RADEON_OVERLAY_EXTENDED_STATUS 0x3000c
|
||||
#define RADEON_OVERLAY_GAMMA_5 0x30010
|
||||
#define RADEON_OVERLAY_GAMMA_4 0x30014
|
||||
#define RADEON_OVERLAY_GAMMA_3 0x30018
|
||||
#define RADEON_OVERLAY_GAMMA_2 0x3001c
|
||||
#define RADEON_OVERLAY_GAMMA_1 0x30020
|
||||
#define RADEON_OVERLAY_GAMMA_0 0x30024
|
||||
|
||||
struct overlay_scale {
|
||||
uint32 _reserved0 : 3;
|
||||
uint32 horizontal_scale_fraction : 12;
|
||||
uint32 _reserved1 : 1;
|
||||
uint32 horizontal_downscale_factor : 3;
|
||||
uint32 _reserved2 : 1;
|
||||
uint32 vertical_scale_fraction : 12;
|
||||
};
|
||||
|
||||
#define OVERLAY_FORMAT_RGB15 0x2
|
||||
#define OVERLAY_FORMAT_RGB16 0x3
|
||||
#define OVERLAY_FORMAT_RGB32 0x1
|
||||
#define OVERLAY_FORMAT_YCbCr422 0x8
|
||||
#define OVERLAY_FORMAT_YCbCr411 0x9
|
||||
#define OVERLAY_FORMAT_YCbCr420 0xc
|
||||
|
||||
#define OVERLAY_MIRROR_NORMAL 0x0
|
||||
#define OVERLAY_MIRROR_HORIZONTAL 0x1
|
||||
#define OVERLAY_MIRROR_VERTICAL 0x2
|
||||
|
||||
// The real overlay registers are written to using an update buffer
|
||||
|
||||
struct overlay_registers {
|
||||
uint32 buffer_rgb0;
|
||||
uint32 buffer_rgb1;
|
||||
uint32 buffer_u0;
|
||||
uint32 buffer_v0;
|
||||
uint32 buffer_u1;
|
||||
uint32 buffer_v1;
|
||||
// (0x18) OSTRIDE - overlay stride
|
||||
uint16 stride_rgb;
|
||||
uint16 stride_uv;
|
||||
// (0x1c) YRGB_VPH - Y/RGB vertical phase
|
||||
uint16 vertical_phase0_rgb;
|
||||
uint16 vertical_phase1_rgb;
|
||||
// (0x20) UV_VPH - UV vertical phase
|
||||
uint16 vertical_phase0_uv;
|
||||
uint16 vertical_phase1_uv;
|
||||
// (0x24) HORZ_PH - horizontal phase
|
||||
uint16 horizontal_phase_rgb;
|
||||
uint16 horizontal_phase_uv;
|
||||
// (0x28) INIT_PHS - initial phase shift
|
||||
uint32 initial_vertical_phase0_shift_rgb0 : 4;
|
||||
uint32 initial_vertical_phase1_shift_rgb0 : 4;
|
||||
uint32 initial_horizontal_phase_shift_rgb0 : 4;
|
||||
uint32 initial_vertical_phase0_shift_uv : 4;
|
||||
uint32 initial_vertical_phase1_shift_uv : 4;
|
||||
uint32 initial_horizontal_phase_shift_uv : 4;
|
||||
uint32 _reserved0 : 8;
|
||||
// (0x2c) DWINPOS - destination window position
|
||||
uint16 window_left;
|
||||
uint16 window_top;
|
||||
// (0x30) DWINSZ - destination window size
|
||||
uint16 window_width;
|
||||
uint16 window_height;
|
||||
// (0x34) SWIDTH - source width
|
||||
uint16 source_width_rgb;
|
||||
uint16 source_width_uv;
|
||||
// (0x38) SWITDHSW - source width in 8 byte steps
|
||||
uint16 source_bytes_per_row_rgb;
|
||||
uint16 source_bytes_per_row_uv;
|
||||
uint16 source_height_rgb;
|
||||
uint16 source_height_uv;
|
||||
overlay_scale scale_rgb;
|
||||
overlay_scale scale_uv;
|
||||
// (0x48) OCLRC0 - overlay color correction 0
|
||||
uint32 brightness_correction : 8; // signed, -128 to 127
|
||||
uint32 _reserved1 : 10;
|
||||
uint32 contrast_correction : 9; // fixed point: 3.6 bits
|
||||
uint32 _reserved2 : 5;
|
||||
// (0x4c) OCLRC1 - overlay color correction 1
|
||||
uint32 saturation_cos_correction : 10; // fixed point: 3.7 bits
|
||||
uint32 _reserved3 : 6;
|
||||
uint32 saturation_sin_correction : 11; // signed fixed point: 3.7 bits
|
||||
uint32 _reserved4 : 5;
|
||||
// (0x50) DCLRKV - destination color key value
|
||||
uint32 color_key_blue : 8;
|
||||
uint32 color_key_green : 8;
|
||||
uint32 color_key_red : 8;
|
||||
uint32 _reserved5 : 8;
|
||||
// (0x54) DCLRKM - destination color key mask
|
||||
uint32 color_key_mask_blue : 8;
|
||||
uint32 color_key_mask_green : 8;
|
||||
uint32 color_key_mask_red : 8;
|
||||
uint32 _reserved6 : 7;
|
||||
uint32 color_key_enabled : 1;
|
||||
// (0x58) SCHRKVH - source chroma key high value
|
||||
uint32 source_chroma_key_high_red : 8;
|
||||
uint32 source_chroma_key_high_blue : 8;
|
||||
uint32 source_chroma_key_high_green : 8;
|
||||
uint32 _reserved7 : 8;
|
||||
// (0x5c) SCHRKVL - source chroma key low value
|
||||
uint32 source_chroma_key_low_red : 8;
|
||||
uint32 source_chroma_key_low_blue : 8;
|
||||
uint32 source_chroma_key_low_green : 8;
|
||||
uint32 _reserved8 : 8;
|
||||
// (0x60) SCHRKEN - source chroma key enable
|
||||
uint32 _reserved9 : 24;
|
||||
uint32 source_chroma_key_red_enabled : 1;
|
||||
uint32 source_chroma_key_blue_enabled : 1;
|
||||
uint32 source_chroma_key_green_enabled : 1;
|
||||
uint32 _reserved10 : 5;
|
||||
// (0x64) OCONFIG - overlay configuration
|
||||
uint32 _reserved11 : 3;
|
||||
uint32 color_control_output_mode : 1;
|
||||
uint32 yuv_to_rgb_bypass : 1;
|
||||
uint32 _reserved12 : 11;
|
||||
uint32 gamma2_enabled : 1;
|
||||
uint32 _reserved13 : 1;
|
||||
uint32 select_pipe : 1;
|
||||
uint32 slot_time : 8;
|
||||
uint32 _reserved14 : 5;
|
||||
// (0x68) OCOMD - overlay command
|
||||
uint32 overlay_enabled : 1;
|
||||
uint32 active_field : 1;
|
||||
uint32 active_buffer : 2;
|
||||
uint32 test_mode : 1;
|
||||
uint32 buffer_field_mode : 1;
|
||||
uint32 _reserved15 : 1;
|
||||
uint32 tv_flip_field_enabled : 1;
|
||||
uint32 _reserved16 : 1;
|
||||
uint32 tv_flip_field_parity : 1;
|
||||
uint32 source_format : 4;
|
||||
uint32 ycbcr422_order : 2;
|
||||
uint32 _reserved18 : 1;
|
||||
uint32 mirroring_mode : 2;
|
||||
uint32 _reserved19 : 13;
|
||||
|
||||
uint32 _reserved20;
|
||||
|
||||
uint32 start_0y;
|
||||
uint32 start_1y;
|
||||
uint32 start_0u;
|
||||
uint32 start_0v;
|
||||
uint32 start_1u;
|
||||
uint32 start_1v;
|
||||
uint32 _reserved21[6];
|
||||
#if 0
|
||||
// (0x70) AWINPOS - alpha blend window position
|
||||
uint32 awinpos;
|
||||
// (0x74) AWINSZ - alpha blend window size
|
||||
uint32 awinsz;
|
||||
|
||||
uint32 _reserved21[10];
|
||||
#endif
|
||||
|
||||
// (0xa0) FASTHSCALE - fast horizontal downscale (strangely enough,
|
||||
// the next two registers switch the usual Y/RGB vs. UV order)
|
||||
uint16 horizontal_scale_uv;
|
||||
uint16 horizontal_scale_rgb;
|
||||
// (0xa4) UVSCALEV - vertical downscale
|
||||
uint16 vertical_scale_uv;
|
||||
uint16 vertical_scale_rgb;
|
||||
|
||||
uint32 _reserved22[86];
|
||||
|
||||
// (0x200) polyphase filter coefficients
|
||||
uint16 vertical_coefficients_rgb[128];
|
||||
uint16 horizontal_coefficients_rgb[128];
|
||||
|
||||
uint32 _reserved23[64];
|
||||
|
||||
// (0x500)
|
||||
uint16 vertical_coefficients_uv[128];
|
||||
uint16 horizontal_coefficients_uv[128];
|
||||
};
|
||||
|
||||
// i965 overlay support is currently realized using its 3D hardware
|
||||
#define RADEON_i965_OVERLAY_STATE_SIZE 36864
|
||||
#define RADEON_i965_3D_CONTEXT_SIZE 32768
|
||||
|
||||
inline bool
|
||||
radeon_uses_physical_overlay(radeon_shared_info &info)
|
||||
{
|
||||
return !info.device_type.InGroup(RADEON_TYPE_Gxx);
|
||||
}
|
||||
|
||||
|
||||
struct hardware_status {
|
||||
uint32 interrupt_status_register;
|
||||
uint32 _reserved0[3];
|
||||
void* primary_ring_head_storage;
|
||||
uint32 _reserved1[3];
|
||||
void* secondary_ring_0_head_storage;
|
||||
void* secondary_ring_1_head_storage;
|
||||
uint32 _reserved2[2];
|
||||
void* binning_head_storage;
|
||||
uint32 _reserved3[3];
|
||||
uint32 store[1008];
|
||||
};
|
||||
|
||||
#endif /* RADEON_HD_H */
|
||||
@@ -0,0 +1,13 @@
|
||||
/*
|
||||
* Copyright 2006, Haiku, Inc. All Rights Reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Axel Dörfler, [email protected]
|
||||
*/
|
||||
#ifndef UTILITY_H
|
||||
#define UTILITY_H
|
||||
|
||||
#define ROUND_TO_PAGE_SIZE(x) (((x) + (B_PAGE_SIZE) - 1) & ~((B_PAGE_SIZE) - 1))
|
||||
|
||||
#endif /* UTILITY_H */
|
||||
@@ -9,6 +9,7 @@ SubInclude HAIKU_TOP src add-ons accelerants neomagic ;
|
||||
SubInclude HAIKU_TOP src add-ons accelerants nvidia_gpgpu ;
|
||||
SubInclude HAIKU_TOP src add-ons accelerants nvidia ;
|
||||
SubInclude HAIKU_TOP src add-ons accelerants radeon ;
|
||||
SubInclude HAIKU_TOP src add-ons accelerants radeon_hd ;
|
||||
SubInclude HAIKU_TOP src add-ons accelerants s3 ;
|
||||
SubInclude HAIKU_TOP src add-ons accelerants tdfx ;
|
||||
SubInclude HAIKU_TOP src add-ons accelerants vesa ;
|
||||
|
||||
@@ -134,22 +134,6 @@ init_common(int device, bool isClone)
|
||||
sharedCloner.Keep();
|
||||
regsCloner.Keep();
|
||||
|
||||
// The overlay registers, hardware status, and cursor memory share
|
||||
// a single area with the shared_info
|
||||
|
||||
gInfo->overlay_registers = (struct overlay_registers *)
|
||||
(gInfo->shared_info->graphics_memory
|
||||
+ gInfo->shared_info->overlay_offset);
|
||||
|
||||
if (gInfo->shared_info->device_type.InGroup(INTEL_TYPE_96x)) {
|
||||
// allocate some extra memory for the 3D context
|
||||
if (intel_allocate_memory(INTEL_i965_3D_CONTEXT_SIZE,
|
||||
B_APERTURE_NON_RESERVED, gInfo->context_base) == B_OK) {
|
||||
gInfo->context_offset = gInfo->context_base
|
||||
- (addr_t)gInfo->shared_info->graphics_memory;
|
||||
}
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -21,12 +21,12 @@ void spin(bigtime_t delay);
|
||||
|
||||
// general
|
||||
status_t intel_init_accelerant(int fd);
|
||||
ssize_t intel_accelerant_clone_info_size(void);
|
||||
void intel_get_accelerant_clone_info(void *data);
|
||||
status_t intel_clone_accelerant(void *data);
|
||||
//ssize_t intel_accelerant_clone_info_size(void);
|
||||
//void intel_get_accelerant_clone_info(void *data);
|
||||
//status_t intel_clone_accelerant(void *data);
|
||||
void intel_uninit_accelerant(void);
|
||||
status_t intel_get_accelerant_device_info(accelerant_device_info *info);
|
||||
sem_id intel_accelerant_retrace_semaphore(void);
|
||||
//status_t intel_get_accelerant_device_info(accelerant_device_info *info);
|
||||
//sem_id intel_accelerant_retrace_semaphore(void);
|
||||
|
||||
// modes & constraints
|
||||
uint32 intel_accelerant_mode_count(void);
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
SubDir HAIKU_TOP src add-ons accelerants radeon_hd ;
|
||||
|
||||
SetSubDirSupportedPlatformsBeOSCompatible ;
|
||||
|
||||
UsePrivateHeaders graphics ;
|
||||
UsePrivateHeaders [ FDirName graphics radeon_hd ] ;
|
||||
UsePrivateHeaders [ FDirName graphics common ] ;
|
||||
|
||||
Addon radeon_hd.accelerant :
|
||||
accelerant.cpp
|
||||
engine.cpp
|
||||
hooks.cpp
|
||||
memory.cpp
|
||||
mode.cpp
|
||||
: be libaccelerantscommon.a
|
||||
;
|
||||
|
||||
Package haiku-radeon_hd-cvs :
|
||||
radeon_hd.accelerant :
|
||||
boot home config add-ons accelerants ;
|
||||
|
||||
@@ -0,0 +1,289 @@
|
||||
/*
|
||||
* Copyright 2006-2009, Haiku, Inc. All Rights Reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Axel Dörfler, [email protected]
|
||||
*/
|
||||
|
||||
|
||||
#include "accelerant_protos.h"
|
||||
#include "accelerant.h"
|
||||
|
||||
#include "utility.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <syslog.h>
|
||||
|
||||
#include <AGP.h>
|
||||
|
||||
|
||||
#define TRACE_ACCELERANT
|
||||
#ifdef TRACE_ACCELERANT
|
||||
extern "C" void _sPrintf(const char *format, ...);
|
||||
# define TRACE(x) _sPrintf x
|
||||
#else
|
||||
# define TRACE(x) ;
|
||||
#endif
|
||||
|
||||
|
||||
struct accelerant_info *gInfo;
|
||||
|
||||
|
||||
class AreaCloner {
|
||||
public:
|
||||
AreaCloner();
|
||||
~AreaCloner();
|
||||
|
||||
area_id Clone(const char *name, void **_address,
|
||||
uint32 spec, uint32 protection,
|
||||
area_id sourceArea);
|
||||
status_t InitCheck()
|
||||
{ return fArea < 0 ? (status_t)fArea : B_OK; }
|
||||
void Keep();
|
||||
|
||||
private:
|
||||
area_id fArea;
|
||||
};
|
||||
|
||||
|
||||
AreaCloner::AreaCloner()
|
||||
:
|
||||
fArea(-1)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
AreaCloner::~AreaCloner()
|
||||
{
|
||||
if (fArea >= 0)
|
||||
delete_area(fArea);
|
||||
}
|
||||
|
||||
|
||||
area_id
|
||||
AreaCloner::Clone(const char *name, void **_address, uint32 spec,
|
||||
uint32 protection, area_id sourceArea)
|
||||
{
|
||||
fArea = clone_area(name, _address, spec, protection, sourceArea);
|
||||
return fArea;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
AreaCloner::Keep()
|
||||
{
|
||||
fArea = -1;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
/*! This is the common accelerant_info initializer. It is called by
|
||||
both, the first accelerant and all clones.
|
||||
*/
|
||||
static status_t
|
||||
init_common(int device, bool isClone)
|
||||
{
|
||||
// initialize global accelerant info structure
|
||||
|
||||
gInfo = (accelerant_info *)malloc(sizeof(accelerant_info));
|
||||
if (gInfo == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
memset(gInfo, 0, sizeof(accelerant_info));
|
||||
|
||||
gInfo->is_clone = isClone;
|
||||
gInfo->device = device;
|
||||
|
||||
// get basic info from driver
|
||||
|
||||
radeon_get_private_data data;
|
||||
data.magic = RADEON_PRIVATE_DATA_MAGIC;
|
||||
|
||||
if (ioctl(device, RADEON_GET_PRIVATE_DATA, &data,
|
||||
sizeof(radeon_get_private_data)) != 0) {
|
||||
free(gInfo);
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
AreaCloner sharedCloner;
|
||||
gInfo->shared_info_area = sharedCloner.Clone("radeon hd shared info",
|
||||
(void **)&gInfo->shared_info, B_ANY_ADDRESS, B_READ_AREA | B_WRITE_AREA,
|
||||
data.shared_info_area);
|
||||
status_t status = sharedCloner.InitCheck();
|
||||
if (status < B_OK) {
|
||||
free(gInfo);
|
||||
TRACE(("radeon_init_accelerant() failed shared area%i, %i\n", data.shared_info_area,
|
||||
gInfo->shared_info_area));
|
||||
return status;
|
||||
}
|
||||
|
||||
AreaCloner regsCloner;
|
||||
gInfo->regs_area = regsCloner.Clone("radeon hd regs",
|
||||
(void **)&gInfo->regs, B_ANY_ADDRESS, B_READ_AREA | B_WRITE_AREA,
|
||||
gInfo->shared_info->registers_area);
|
||||
status = regsCloner.InitCheck();
|
||||
if (status < B_OK) {
|
||||
free(gInfo);
|
||||
return status;
|
||||
}
|
||||
|
||||
sharedCloner.Keep();
|
||||
regsCloner.Keep();
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
/*! Clean up data common to both primary and cloned accelerant */
|
||||
static void
|
||||
uninit_common(void)
|
||||
{
|
||||
delete_area(gInfo->regs_area);
|
||||
delete_area(gInfo->shared_info_area);
|
||||
|
||||
gInfo->regs_area = gInfo->shared_info_area = -1;
|
||||
|
||||
// close the file handle ONLY if we're the clone
|
||||
if (gInfo->is_clone)
|
||||
close(gInfo->device);
|
||||
|
||||
free(gInfo);
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - public accelerant functions
|
||||
|
||||
|
||||
/*! Init primary accelerant */
|
||||
status_t
|
||||
radeon_init_accelerant(int device)
|
||||
{
|
||||
TRACE(("radeon_init_accelerant()\n"));
|
||||
|
||||
status_t status = init_common(device, false);
|
||||
if (status != B_OK)
|
||||
return status;
|
||||
|
||||
radeon_shared_info &info = *gInfo->shared_info;
|
||||
|
||||
init_lock(&info.accelerant_lock, "radeon hd accelerant");
|
||||
init_lock(&info.engine_lock, "radeon hd engine");
|
||||
|
||||
|
||||
status = create_mode_list();
|
||||
if (status != B_OK) {
|
||||
uninit_common();
|
||||
return status;
|
||||
}
|
||||
|
||||
TRACE(("radeon_init_accelerant() done\n"));
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
ssize_t
|
||||
radeon_accelerant_clone_info_size(void)
|
||||
{
|
||||
TRACE(("radeon_accelerant_clone_info_size()\n"));
|
||||
// clone info is device name, so return its maximum size
|
||||
return B_PATH_NAME_LENGTH;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
radeon_get_accelerant_clone_info(void *info)
|
||||
{
|
||||
TRACE(("radeon_get_accelerant_clone_info()\n"));
|
||||
ioctl(gInfo->device, RADEON_GET_DEVICE_NAME, info, B_PATH_NAME_LENGTH);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
radeon_clone_accelerant(void *info)
|
||||
{
|
||||
TRACE(("radeon_clone_accelerant()\n"));
|
||||
|
||||
// create full device name
|
||||
char path[B_PATH_NAME_LENGTH];
|
||||
strcpy(path, "/dev/");
|
||||
#ifdef __HAIKU__
|
||||
strlcat(path, (const char *)info, sizeof(path));
|
||||
#else
|
||||
strcat(path, (const char *)info);
|
||||
#endif
|
||||
|
||||
int fd = open(path, B_READ_WRITE);
|
||||
if (fd < 0)
|
||||
return errno;
|
||||
|
||||
status_t status = init_common(fd, true);
|
||||
if (status != B_OK)
|
||||
goto err1;
|
||||
|
||||
// get read-only clone of supported display modes
|
||||
status = gInfo->mode_list_area = clone_area(
|
||||
"intel extreme cloned modes", (void **)&gInfo->mode_list,
|
||||
B_ANY_ADDRESS, B_READ_AREA, gInfo->shared_info->mode_list_area);
|
||||
if (status < B_OK)
|
||||
goto err2;
|
||||
|
||||
return B_OK;
|
||||
|
||||
err2:
|
||||
uninit_common();
|
||||
err1:
|
||||
close(fd);
|
||||
return status;
|
||||
}
|
||||
*/
|
||||
|
||||
/*! This function is called for both, the primary accelerant and all of
|
||||
its clones.
|
||||
*/
|
||||
void
|
||||
radeon_uninit_accelerant(void)
|
||||
{
|
||||
TRACE(("radeon_uninit_accelerant()\n"));
|
||||
|
||||
gInfo->mode_list = NULL;
|
||||
|
||||
radeon_shared_info &info = *gInfo->shared_info;
|
||||
|
||||
uninit_lock(&info.accelerant_lock);
|
||||
uninit_lock(&info.engine_lock);
|
||||
|
||||
uninit_common();
|
||||
}
|
||||
|
||||
/*
|
||||
status_t
|
||||
radeon_get_accelerant_device_info(accelerant_device_info *info)
|
||||
{
|
||||
TRACE(("radeon_get_accelerant_device_info()\n"));
|
||||
|
||||
info->version = B_ACCELERANT_VERSION;
|
||||
strcpy(info->name, gInfo->shared_info->device_type.InFamily(RADEON_TYPE_7xx)
|
||||
? "Intel Extreme Graphics 1" : "Intel Extreme Graphics 2");
|
||||
strcpy(info->chipset, gInfo->shared_info->device_identifier);
|
||||
strcpy(info->serial_no, "None");
|
||||
|
||||
info->memory = gInfo->shared_info->graphics_memory_size;
|
||||
info->dac_speed = gInfo->shared_info->pll_info.max_frequency;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
sem_id
|
||||
radeon_accelerant_retrace_semaphore()
|
||||
{
|
||||
TRACE(("radeon_accelerant_retrace_semaphore()\n"));
|
||||
return gInfo->shared_info->vblank_sem;
|
||||
}*/
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright 2006-2008, Haiku, Inc. All Rights Reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Axel Dörfler, [email protected]
|
||||
*/
|
||||
#ifndef RADEON_HD_ACCELERANT_H
|
||||
#define RADEON_HD_ACCELERANT_H
|
||||
|
||||
|
||||
#include "radeon_hd.h"
|
||||
|
||||
|
||||
#include <edid.h>
|
||||
|
||||
|
||||
struct accelerant_info {
|
||||
vuint8 *regs;
|
||||
area_id regs_area;
|
||||
|
||||
radeon_shared_info *shared_info;
|
||||
area_id shared_info_area;
|
||||
|
||||
display_mode *mode_list; // cloned list of standard display modes
|
||||
area_id mode_list_area;
|
||||
|
||||
edid1_info edid_info;
|
||||
bool has_edid;
|
||||
|
||||
int device;
|
||||
bool is_clone;
|
||||
|
||||
// LVDS panel mode passed from the bios/startup.
|
||||
display_mode lvds_panel_mode;
|
||||
};
|
||||
|
||||
#define HEAD_MODE_A_ANALOG 0x01
|
||||
#define HEAD_MODE_B_DIGITAL 0x02
|
||||
#define HEAD_MODE_CLONE 0x03
|
||||
#define HEAD_MODE_LVDS_PANEL 0x08
|
||||
|
||||
extern accelerant_info *gInfo;
|
||||
|
||||
// register access
|
||||
|
||||
inline uint32
|
||||
read32(uint32 offset)
|
||||
{
|
||||
return *(volatile uint32 *)(gInfo->regs + offset);
|
||||
}
|
||||
|
||||
inline void
|
||||
write32(uint32 offset, uint32 value)
|
||||
{
|
||||
*(volatile uint32 *)(gInfo->regs + offset) = value;
|
||||
}
|
||||
|
||||
// memory.cpp
|
||||
extern void radeon_free_memory(uint32 base);
|
||||
extern status_t radeon_allocate_memory(size_t size, uint32 flags, uint32 &base);
|
||||
|
||||
// modes.cpp
|
||||
extern status_t create_mode_list(void);
|
||||
|
||||
#endif /* RADEON_HD_ACCELERANT_H */
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright 2006-2007, Haiku, Inc. All Rights Reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Axel Dörfler, [email protected]
|
||||
*/
|
||||
#ifndef ACCELERANT_PROTOS_H
|
||||
#define ACCELERANT_PROTOS_H
|
||||
|
||||
|
||||
#include <Accelerant.h>
|
||||
#include "video_overlay.h"
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void spin(bigtime_t delay);
|
||||
|
||||
// general
|
||||
status_t radeon_init_accelerant(int fd);
|
||||
ssize_t radeon_accelerant_clone_info_size(void);
|
||||
void radeon_get_accelerant_clone_info(void *data);
|
||||
status_t radeon_clone_accelerant(void *data);
|
||||
void radeon_uninit_accelerant(void);
|
||||
status_t radeon_get_accelerant_device_info(accelerant_device_info *info);
|
||||
sem_id radeon_accelerant_retrace_semaphore(void);
|
||||
|
||||
// modes & constraints
|
||||
uint32 radeon_accelerant_mode_count(void);
|
||||
status_t radeon_get_mode_list(display_mode *dm);
|
||||
status_t radeon_set_display_mode(display_mode *mode);
|
||||
status_t radeon_get_display_mode(display_mode *currentMode);
|
||||
status_t radeon_get_frame_buffer_config(frame_buffer_config *config);
|
||||
status_t radeon_get_pixel_clock_limits(display_mode *mode, uint32 *low, uint32 *high);
|
||||
|
||||
// accelerant engine
|
||||
status_t radeon_acquire_engine(uint32 capabilities, uint32 maxWait,
|
||||
sync_token *syncToken, engine_token **_engineToken);
|
||||
status_t radeon_release_engine(engine_token *engineToken, sync_token *syncToken);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ACCELERANT_PROTOS_H */
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright 2006-2007, Haiku, Inc. All Rights Reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Axel Dörfler, [email protected]
|
||||
*/
|
||||
|
||||
|
||||
#include <Debug.h>
|
||||
|
||||
#include "accelerant.h"
|
||||
#include "accelerant_protos.h"
|
||||
|
||||
|
||||
#undef TRACE
|
||||
|
||||
//#define TRACE_ENGINE
|
||||
#ifdef TRACE_ENGINE
|
||||
# define TRACE(x) _sPrintf x
|
||||
#else
|
||||
# define TRACE(x) ;
|
||||
#endif
|
||||
|
||||
|
||||
static engine_token sEngineToken = {1, 0 /*B_2D_ACCELERATION*/, NULL};
|
||||
|
||||
|
||||
// #pragma mark - engine management
|
||||
|
||||
|
||||
status_t
|
||||
radeon_acquire_engine(uint32 capabilities, uint32 maxWait, sync_token *syncToken,
|
||||
engine_token **_engineToken)
|
||||
{
|
||||
TRACE(("radeon_acquire_engine()\n"));
|
||||
*_engineToken = &sEngineToken;
|
||||
|
||||
if (acquire_lock(&gInfo->shared_info->engine_lock) != B_OK)
|
||||
return B_ERROR;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
radeon_release_engine(engine_token *engineToken, sync_token *syncToken)
|
||||
{
|
||||
TRACE(("radeon_release_engine()\n"));
|
||||
if (syncToken != NULL)
|
||||
syncToken->engine_id = engineToken->engine_id;
|
||||
|
||||
release_lock(&gInfo->shared_info->engine_lock);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright 2006-2009, Haiku, Inc. All Rights Reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Axel Dörfler, [email protected]
|
||||
*/
|
||||
|
||||
|
||||
#include "accelerant_protos.h"
|
||||
#include "accelerant.h"
|
||||
|
||||
|
||||
extern "C" void *
|
||||
get_accelerant_hook(uint32 feature, void *data)
|
||||
{
|
||||
switch (feature) {
|
||||
/* general */
|
||||
case B_INIT_ACCELERANT:
|
||||
return (void*)radeon_init_accelerant;
|
||||
case B_UNINIT_ACCELERANT:
|
||||
return (void*)radeon_uninit_accelerant;
|
||||
/*case B_CLONE_ACCELERANT:
|
||||
return (void*)radeon_clone_accelerant;
|
||||
case B_ACCELERANT_CLONE_INFO_SIZE:
|
||||
return (void*)radeon_accelerant_clone_info_size;
|
||||
case B_GET_ACCELERANT_CLONE_INFO:
|
||||
return (void*)radeon_get_accelerant_clone_info;
|
||||
case B_GET_ACCELERANT_DEVICE_INFO:
|
||||
return (void*)radeon_get_accelerant_device_info;
|
||||
case B_ACCELERANT_RETRACE_SEMAPHORE:
|
||||
return (void*)radeon_accelerant_retrace_semaphore;
|
||||
*/
|
||||
/* mode configuration */
|
||||
case B_ACCELERANT_MODE_COUNT:
|
||||
return (void*)radeon_accelerant_mode_count;
|
||||
case B_GET_MODE_LIST:
|
||||
return (void*)radeon_get_mode_list;
|
||||
case B_SET_DISPLAY_MODE:
|
||||
return (void*)radeon_set_display_mode;
|
||||
case B_GET_DISPLAY_MODE:
|
||||
return (void*)radeon_get_display_mode;
|
||||
|
||||
case B_GET_FRAME_BUFFER_CONFIG:
|
||||
return (void*)radeon_get_frame_buffer_config;
|
||||
case B_GET_PIXEL_CLOCK_LIMITS:
|
||||
return (void*)radeon_get_pixel_clock_limits;
|
||||
|
||||
case B_ACQUIRE_ENGINE:
|
||||
return (void*)radeon_acquire_engine;
|
||||
case B_RELEASE_ENGINE:
|
||||
return (void*)radeon_release_engine;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright 2006-2008, Haiku, Inc. All Rights Reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Axel Dörfler, [email protected]
|
||||
*/
|
||||
|
||||
|
||||
#include "accelerant.h"
|
||||
#include "radeon_hd.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
|
||||
|
||||
//#define TRACE_MEMORY
|
||||
#ifdef TRACE_MEMORY
|
||||
extern "C" void _sPrintf(const char *format, ...);
|
||||
# define TRACE(x) _sPrintf x
|
||||
#else
|
||||
# define TRACE(x) ;
|
||||
#endif
|
||||
|
||||
|
||||
void
|
||||
radeon_free_memory(uint32 base)
|
||||
{
|
||||
if (base == 0)
|
||||
return;
|
||||
|
||||
radeon_free_graphics_memory freeMemory;
|
||||
freeMemory.magic = RADEON_PRIVATE_DATA_MAGIC;
|
||||
freeMemory.buffer_base = base;
|
||||
|
||||
ioctl(gInfo->device, RADEON_FREE_GRAPHICS_MEMORY, &freeMemory,
|
||||
sizeof(freeMemory));
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
radeon_allocate_memory(size_t size, uint32 flags, uint32 &base)
|
||||
{
|
||||
radeon_allocate_graphics_memory allocMemory;
|
||||
allocMemory.magic = RADEON_PRIVATE_DATA_MAGIC;
|
||||
allocMemory.size = size;
|
||||
allocMemory.alignment = 0;
|
||||
allocMemory.flags = flags;
|
||||
|
||||
if (ioctl(gInfo->device, RADEON_ALLOCATE_GRAPHICS_MEMORY, &allocMemory,
|
||||
sizeof(allocMemory)) < 0)
|
||||
return errno;
|
||||
|
||||
base = allocMemory.buffer_base;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,361 @@
|
||||
/*
|
||||
* Copyright 2006-2009, Haiku, Inc. All Rights Reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Support for i915 chipset and up based on the X driver,
|
||||
* Copyright 2006-2007 Intel Corporation.
|
||||
*
|
||||
* Authors:
|
||||
* Axel Dörfler, [email protected]
|
||||
*/
|
||||
|
||||
|
||||
#include "accelerant_protos.h"
|
||||
#include "accelerant.h"
|
||||
#include "utility.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
#include <create_display_modes.h>
|
||||
#include <ddc.h>
|
||||
#include <edid.h>
|
||||
|
||||
|
||||
#define TRACE_MODE
|
||||
#ifdef TRACE_MODE
|
||||
extern "C" void _sPrintf(const char *format, ...);
|
||||
# define TRACE(x) _sPrintf x
|
||||
#else
|
||||
# define TRACE(x) ;
|
||||
#endif
|
||||
|
||||
|
||||
static display_mode gDisplayMode;
|
||||
|
||||
|
||||
status_t
|
||||
create_mode_list(void)
|
||||
{
|
||||
gDisplayMode.timing.pixel_clock = 71500;
|
||||
gDisplayMode.timing.h_display = 1366; /* in pixels (not character clocks) */
|
||||
gDisplayMode.timing.h_sync_start = 1406;
|
||||
gDisplayMode.timing.h_sync_end = 1438;
|
||||
gDisplayMode.timing.h_total = 1510;
|
||||
gDisplayMode.timing.v_display = 768; /* in lines */
|
||||
gDisplayMode.timing.v_sync_start = 771;
|
||||
gDisplayMode.timing.v_sync_end = 777;
|
||||
gDisplayMode.timing.v_total = 789;
|
||||
gDisplayMode.timing.flags = 0; /* sync polarity, etc. */
|
||||
|
||||
gDisplayMode.space = B_RGB32_LITTLE; /* pixel configuration */
|
||||
gDisplayMode.virtual_width = 1366; /* in pixels */
|
||||
gDisplayMode.virtual_height = 768; /* in lines */
|
||||
gDisplayMode.h_display_start = 0; /* first displayed pixel in line */
|
||||
gDisplayMode.v_display_start = 0; /* first displayed line */
|
||||
gDisplayMode.flags = 0; /* mode flags (Some drivers use this */
|
||||
|
||||
gInfo->mode_list = &gDisplayMode;
|
||||
gInfo->shared_info->mode_count = 1;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
uint32
|
||||
radeon_accelerant_mode_count(void)
|
||||
{
|
||||
TRACE(("radeon_accelerant_mode_count()\n"));
|
||||
|
||||
return gInfo->shared_info->mode_count;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
radeon_get_mode_list(display_mode *modeList)
|
||||
{
|
||||
TRACE(("radeon_get_mode_info()\n"));
|
||||
memcpy(modeList, gInfo->mode_list,
|
||||
gInfo->shared_info->mode_count * sizeof(display_mode));
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
inline void
|
||||
write32AtMask(uint32 adress, uint32 value, uint32 mask)
|
||||
{
|
||||
uint32 temp;
|
||||
temp = read32(adress);
|
||||
temp &= ~mask;
|
||||
temp |= value & mask;
|
||||
write32(adress, temp);
|
||||
}
|
||||
|
||||
|
||||
enum {
|
||||
/* CRTC1 registers */
|
||||
D1CRTC_H_TOTAL = 0x6000,
|
||||
D1CRTC_H_BLANK_START_END = 0x6004,
|
||||
D1CRTC_H_SYNC_A = 0x6008,
|
||||
D1CRTC_H_SYNC_A_CNTL = 0x600C,
|
||||
D1CRTC_H_SYNC_B = 0x6010,
|
||||
D1CRTC_H_SYNC_B_CNTL = 0x6014,
|
||||
|
||||
D1CRTC_V_TOTAL = 0x6020,
|
||||
D1CRTC_V_BLANK_START_END = 0x6024,
|
||||
D1CRTC_V_SYNC_A = 0x6028,
|
||||
D1CRTC_V_SYNC_A_CNTL = 0x602C,
|
||||
D1CRTC_V_SYNC_B = 0x6030,
|
||||
D1CRTC_V_SYNC_B_CNTL = 0x6034,
|
||||
|
||||
D1CRTC_CONTROL = 0x6080,
|
||||
D1CRTC_BLANK_CONTROL = 0x6084,
|
||||
D1CRTC_INTERLACE_CONTROL = 0x6088,
|
||||
D1CRTC_BLACK_COLOR = 0x6098,
|
||||
D1CRTC_STATUS = 0x609C,
|
||||
D1CRTC_COUNT_CONTROL = 0x60B4,
|
||||
|
||||
/* D1GRPH registers */
|
||||
D1GRPH_ENABLE = 0x6100,
|
||||
D1GRPH_CONTROL = 0x6104,
|
||||
D1GRPH_LUT_SEL = 0x6108,
|
||||
D1GRPH_SWAP_CNTL = 0x610C,
|
||||
D1GRPH_PRIMARY_SURFACE_ADDRESS = 0x6110,
|
||||
D1GRPH_SECONDARY_SURFACE_ADDRESS = 0x6118,
|
||||
D1GRPH_PITCH = 0x6120,
|
||||
D1GRPH_SURFACE_OFFSET_X = 0x6124,
|
||||
D1GRPH_SURFACE_OFFSET_Y = 0x6128,
|
||||
D1GRPH_X_START = 0x612C,
|
||||
D1GRPH_Y_START = 0x6130,
|
||||
D1GRPH_X_END = 0x6134,
|
||||
D1GRPH_Y_END = 0x6138,
|
||||
D1GRPH_UPDATE = 0x6144,
|
||||
|
||||
/* D1MODE */
|
||||
D1MODE_DESKTOP_HEIGHT = 0x652C,
|
||||
D1MODE_VLINE_START_END = 0x6538,
|
||||
D1MODE_VLINE_STATUS = 0x653C,
|
||||
D1MODE_VIEWPORT_START = 0x6580,
|
||||
D1MODE_VIEWPORT_SIZE = 0x6584,
|
||||
D1MODE_EXT_OVERSCAN_LEFT_RIGHT = 0x6588,
|
||||
D1MODE_EXT_OVERSCAN_TOP_BOTTOM = 0x658C,
|
||||
D1MODE_DATA_FORMAT = 0x6528
|
||||
};
|
||||
|
||||
|
||||
static void
|
||||
get_color_space_format(const display_mode &mode, uint32 &colorMode,
|
||||
uint32 &bytesPerRow, uint32 &bitsPerPixel)
|
||||
{
|
||||
uint32 bytesPerPixel;
|
||||
|
||||
switch (mode.space) {
|
||||
case B_RGB32_LITTLE:
|
||||
colorMode = DISPLAY_CONTROL_RGB32;
|
||||
bytesPerPixel = 4;
|
||||
bitsPerPixel = 32;
|
||||
break;
|
||||
case B_RGB16_LITTLE:
|
||||
colorMode = DISPLAY_CONTROL_RGB16;
|
||||
bytesPerPixel = 2;
|
||||
bitsPerPixel = 16;
|
||||
break;
|
||||
case B_RGB15_LITTLE:
|
||||
colorMode = DISPLAY_CONTROL_RGB15;
|
||||
bytesPerPixel = 2;
|
||||
bitsPerPixel = 15;
|
||||
break;
|
||||
case B_CMAP8:
|
||||
default:
|
||||
colorMode = DISPLAY_CONTROL_CMAP8;
|
||||
bytesPerPixel = 1;
|
||||
bitsPerPixel = 8;
|
||||
break;
|
||||
}
|
||||
|
||||
bytesPerRow = mode.virtual_width * bytesPerPixel;
|
||||
|
||||
// Make sure bytesPerRow is a multiple of 64
|
||||
// TODO: check if the older chips have the same restriction!
|
||||
if ((bytesPerRow & 63) != 0)
|
||||
bytesPerRow = (bytesPerRow + 63) & ~63;
|
||||
}
|
||||
|
||||
#define D1_REG_OFFSET 0x0000
|
||||
#define D2_REG_OFFSET 0x0800
|
||||
|
||||
|
||||
static void
|
||||
DxModeSet(display_mode *mode)
|
||||
{
|
||||
uint32 regOffset = D1_REG_OFFSET;
|
||||
|
||||
display_timing& displayTiming = mode->timing;
|
||||
|
||||
|
||||
/* enable read requests */
|
||||
write32AtMask(regOffset + D1CRTC_CONTROL, 0, 0x01000000);
|
||||
|
||||
/* Horizontal */
|
||||
write32(regOffset + D1CRTC_H_TOTAL, displayTiming.h_total - 1);
|
||||
|
||||
uint16 blankStart = displayTiming.h_sync_end;
|
||||
uint16 blankEnd = displayTiming.h_total;
|
||||
write32(regOffset + D1CRTC_H_BLANK_START_END,
|
||||
blankStart | (blankEnd << 16));
|
||||
|
||||
write32(regOffset + D1CRTC_H_SYNC_A,
|
||||
(displayTiming.h_sync_end - displayTiming.h_sync_start) << 16);
|
||||
//write32(regOffset + D1CRTC_H_SYNC_A_CNTL, Mode->Flags & V_NHSYNC);
|
||||
//!!!write32(regOffset + D1CRTC_H_SYNC_A_CNTL, V_NHSYNC);
|
||||
|
||||
/* Vertical */
|
||||
write32(regOffset + D1CRTC_V_TOTAL, displayTiming.v_total - 1);
|
||||
|
||||
blankStart = displayTiming.v_sync_end;
|
||||
blankEnd = displayTiming.v_total;
|
||||
write32(regOffset + D1CRTC_V_BLANK_START_END,
|
||||
blankStart | (blankEnd << 16));
|
||||
|
||||
/* set interlaced */
|
||||
//if (Mode->Flags & V_INTERLACE) {
|
||||
if (0) {
|
||||
write32(regOffset + D1CRTC_INTERLACE_CONTROL, 0x1);
|
||||
write32(regOffset + D1MODE_DATA_FORMAT, 0x1);
|
||||
} else {
|
||||
write32(regOffset + D1CRTC_INTERLACE_CONTROL, 0x0);
|
||||
write32(regOffset + D1MODE_DATA_FORMAT, 0x0);
|
||||
}
|
||||
|
||||
write32(regOffset + D1CRTC_V_SYNC_A,
|
||||
(displayTiming.v_sync_end - displayTiming.v_sync_start) << 16);
|
||||
//write32(regOffset + D1CRTC_V_SYNC_A_CNTL, Mode->Flags & V_NVSYNC);
|
||||
//!!!write32(regOffset + D1CRTC_V_SYNC_A_CNTL, V_NVSYNC);
|
||||
|
||||
/* set D1CRTC_HORZ_COUNT_BY2_EN to 0; should only be set to 1 on 30bpp DVI modes */
|
||||
write32AtMask(regOffset + D1CRTC_COUNT_CONTROL, 0x0, 0x1);
|
||||
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
radeon_set_display_mode(display_mode *mode)
|
||||
{
|
||||
//DxModeSet(mode);
|
||||
|
||||
|
||||
uint32 colorMode, bytesPerRow, bitsPerPixel;
|
||||
get_color_space_format(*mode, colorMode, bytesPerRow, bitsPerPixel);
|
||||
|
||||
uint32 regOffset = D1_REG_OFFSET;
|
||||
|
||||
write32AtMask(regOffset + D1GRPH_ENABLE, 1, 0x00000001);
|
||||
|
||||
/* disable R/B swap, disable tiling, disable 16bit alpha, etc. */
|
||||
write32(regOffset + D1GRPH_CONTROL, 0);
|
||||
|
||||
switch (mode->space) {
|
||||
case B_CMAP8:
|
||||
write32AtMask(regOffset + D1GRPH_CONTROL, 0, 0x00000703);
|
||||
break;
|
||||
case B_RGB15_LITTLE:
|
||||
write32AtMask(regOffset + D1GRPH_CONTROL, 0x000001, 0x00000703);
|
||||
break;
|
||||
case B_RGB16_LITTLE:
|
||||
write32AtMask(regOffset + D1GRPH_CONTROL, 0x000101, 0x00000703);
|
||||
break;
|
||||
case B_RGB24_LITTLE:
|
||||
case B_RGB32_LITTLE:
|
||||
default:
|
||||
write32AtMask(regOffset + D1GRPH_CONTROL, 0x000002, 0x00000703);
|
||||
break;
|
||||
/* TODO: 64bpp ;p */
|
||||
}
|
||||
|
||||
/* Make sure that we are not swapping colours around */
|
||||
//if (rhdPtr->ChipSet > RHD_R600)
|
||||
write32(regOffset + D1GRPH_SWAP_CNTL, 0);
|
||||
/* R5xx - RS690 case is GRPH_CONTROL bit 16 */
|
||||
|
||||
#define R6XX_CONFIG_FB_BASE 0x542C /* AKA CONFIG_F0_BASE */
|
||||
|
||||
uint32 fbIntAddress = read32(R6XX_CONFIG_FB_BASE);
|
||||
|
||||
uint32 offset = gInfo->shared_info->frame_buffer_offset;
|
||||
write32(regOffset + D1GRPH_PRIMARY_SURFACE_ADDRESS,
|
||||
fbIntAddress + offset);
|
||||
write32(regOffset + D1GRPH_PITCH, bytesPerRow / 4);
|
||||
write32(regOffset + D1GRPH_SURFACE_OFFSET_X, 0);
|
||||
write32(regOffset + D1GRPH_SURFACE_OFFSET_Y, 0);
|
||||
write32(regOffset + D1GRPH_X_START, 0);
|
||||
write32(regOffset + D1GRPH_Y_START, 0);
|
||||
write32(regOffset + D1GRPH_X_END, mode->virtual_width);
|
||||
write32(regOffset + D1GRPH_Y_END, mode->virtual_height);
|
||||
|
||||
/* D1Mode registers */
|
||||
write32(regOffset + D1MODE_DESKTOP_HEIGHT, mode->virtual_height);
|
||||
|
||||
// update shared info
|
||||
gInfo->shared_info->bytes_per_row = bytesPerRow;
|
||||
gInfo->shared_info->current_mode = *mode;
|
||||
gInfo->shared_info->bits_per_pixel = bitsPerPixel;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
radeon_get_display_mode(display_mode *_currentMode)
|
||||
{
|
||||
TRACE(("radeon_get_display_mode()\n"));
|
||||
|
||||
*_currentMode = gDisplayMode;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
radeon_get_frame_buffer_config(frame_buffer_config *config)
|
||||
{
|
||||
TRACE(("radeon_get_frame_buffer_config()\n"));
|
||||
|
||||
uint32 offset = gInfo->shared_info->frame_buffer_offset;
|
||||
|
||||
config->frame_buffer = gInfo->shared_info->graphics_memory + offset;
|
||||
config->frame_buffer_dma
|
||||
= (uint8 *)gInfo->shared_info->physical_graphics_memory + offset;
|
||||
config->bytes_per_row = gInfo->shared_info->bytes_per_row;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
radeon_get_pixel_clock_limits(display_mode *mode, uint32 *_low, uint32 *_high)
|
||||
{
|
||||
TRACE(("radeon_get_pixel_clock_limits()\n"));
|
||||
/*
|
||||
if (_low != NULL) {
|
||||
// lower limit of about 48Hz vertical refresh
|
||||
uint32 totalClocks = (uint32)mode->timing.h_total * (uint32)mode->timing.v_total;
|
||||
uint32 low = (totalClocks * 48L) / 1000L;
|
||||
if (low < gInfo->shared_info->pll_info.min_frequency)
|
||||
low = gInfo->shared_info->pll_info.min_frequency;
|
||||
else if (low > gInfo->shared_info->pll_info.max_frequency)
|
||||
return B_ERROR;
|
||||
|
||||
*_low = low;
|
||||
}
|
||||
|
||||
if (_high != NULL)
|
||||
*_high = gInfo->shared_info->pll_info.max_frequency;
|
||||
*/
|
||||
*_low = 48L;
|
||||
*_high = 100 * 1000000L;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ SubInclude HAIKU_TOP src add-ons kernel drivers graphics neomagic ;
|
||||
SubInclude HAIKU_TOP src add-ons kernel drivers graphics nvidia ;
|
||||
SubInclude HAIKU_TOP src add-ons kernel drivers graphics nvidia_gpgpu ;
|
||||
SubInclude HAIKU_TOP src add-ons kernel drivers graphics radeon ;
|
||||
SubInclude HAIKU_TOP src add-ons kernel drivers graphics radeon_hd ;
|
||||
SubInclude HAIKU_TOP src add-ons kernel drivers graphics s3 ;
|
||||
SubInclude HAIKU_TOP src add-ons kernel drivers graphics tdfx ;
|
||||
SubInclude HAIKU_TOP src add-ons kernel drivers graphics skeleton ;
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
SubDir HAIKU_TOP src add-ons kernel drivers graphics radeon_hd ;
|
||||
|
||||
SetSubDirSupportedPlatformsBeOSCompatible ;
|
||||
|
||||
UsePrivateHeaders [ FDirName graphics radeon_hd ] ;
|
||||
UsePrivateHeaders [ FDirName graphics common ] ;
|
||||
UsePrivateHeaders graphics kernel ;
|
||||
UsePrivateHeaders shared ;
|
||||
|
||||
KernelAddon radeon_hd :
|
||||
driver.cpp
|
||||
device.cpp
|
||||
radeon_hd.cpp
|
||||
: libgraphicscommon.a
|
||||
;
|
||||
|
||||
SEARCH on [ FGristFiles
|
||||
kernel_cpp.cpp
|
||||
] = [ FDirName $(HAIKU_TOP) src system kernel util ] ;
|
||||
|
||||
Package haiku-radeon_hd-cvs :
|
||||
radeon_hd :
|
||||
boot home config add-ons kernel drivers bin ;
|
||||
PackageDriverSymLink haiku-radeon_hd-cvs : graphics radeon_hd ;
|
||||
@@ -0,0 +1,272 @@
|
||||
/*
|
||||
* Copyright 2006-2009, Haiku, Inc. All Rights Reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Axel Dörfler, [email protected]
|
||||
*/
|
||||
|
||||
|
||||
#include "driver.h"
|
||||
#include "device.h"
|
||||
#include "radeon_hd.h"
|
||||
#include "utility.h"
|
||||
|
||||
#include <OS.h>
|
||||
#include <KernelExport.h>
|
||||
#include <Drivers.h>
|
||||
#include <PCI.h>
|
||||
#include <SupportDefs.h>
|
||||
#include <graphic_driver.h>
|
||||
#include <image.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
//#define DEBUG_COMMANDS
|
||||
|
||||
#define TRACE_DEVICE
|
||||
#ifdef TRACE_DEVICE
|
||||
# define TRACE(x) dprintf x
|
||||
#else
|
||||
# define TRACE(x) ;
|
||||
#endif
|
||||
|
||||
|
||||
/* device hooks prototypes */
|
||||
|
||||
static status_t device_open(const char *name, uint32 flags, void **_cookie);
|
||||
static status_t device_close(void *data);
|
||||
static status_t device_free(void *data);
|
||||
static status_t device_ioctl(void *data, uint32 opcode, void *buffer, size_t length);
|
||||
static status_t device_read(void *data, off_t offset, void *buffer, size_t *length);
|
||||
static status_t device_write(void *data, off_t offset, const void *buffer, size_t *length);
|
||||
|
||||
|
||||
device_hooks gDeviceHooks = {
|
||||
device_open,
|
||||
device_close,
|
||||
device_free,
|
||||
device_ioctl,
|
||||
device_read,
|
||||
device_write,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
|
||||
#ifdef DEBUG_COMMANDS
|
||||
static int
|
||||
getset_register(int argc, char **argv)
|
||||
{
|
||||
if (argc < 2 || argc > 3) {
|
||||
kprintf("usage: %s <register> [set-to-value]\n", argv[0]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32 reg = parse_expression(argv[1]);
|
||||
uint32 value = 0;
|
||||
bool set = argc == 3;
|
||||
if (set)
|
||||
value = parse_expression(argv[2]);
|
||||
|
||||
kprintf("radeon_extreme register %#lx\n", reg);
|
||||
|
||||
radeon_info &info = *gDeviceInfo[0];
|
||||
uint32 oldValue = read32(info.registers + reg);
|
||||
|
||||
kprintf(" %svalue: %#lx (%lu)\n", set ? "old " : "", oldValue, oldValue);
|
||||
|
||||
if (set) {
|
||||
write32(info.registers + reg, value);
|
||||
|
||||
value = read32(info.registers + reg);
|
||||
kprintf(" new value: %#lx (%lu)\n", value, value);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif // DEBUG_COMMANDS
|
||||
|
||||
|
||||
// #pragma mark - Device Hooks
|
||||
|
||||
|
||||
static status_t
|
||||
device_open(const char *name, uint32 /*flags*/, void **_cookie)
|
||||
{
|
||||
TRACE((DEVICE_NAME ": open(name = %s)\n", name));
|
||||
int32 id;
|
||||
|
||||
// find accessed device
|
||||
{
|
||||
char *thisName;
|
||||
|
||||
// search for device name
|
||||
for (id = 0; (thisName = gDeviceNames[id]) != NULL; id++) {
|
||||
if (!strcmp(name, thisName))
|
||||
break;
|
||||
}
|
||||
if (!thisName)
|
||||
return B_BAD_VALUE;
|
||||
}
|
||||
TRACE((DEVICE_NAME ": device id %i\n", id));
|
||||
|
||||
radeon_info *info = gDeviceInfo[id];
|
||||
|
||||
mutex_lock(&gLock);
|
||||
|
||||
if (info->open_count == 0) {
|
||||
// this device has been opened for the first time, so
|
||||
// we allocate needed resources and initialize the structure
|
||||
info->init_status = radeon_hd_init(*info);
|
||||
if (info->init_status == B_OK) {
|
||||
info->open_count++;
|
||||
}
|
||||
}
|
||||
|
||||
mutex_unlock(&gLock);
|
||||
|
||||
if (info->init_status == B_OK)
|
||||
*_cookie = info;
|
||||
|
||||
return info->init_status;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
device_close(void */*data*/)
|
||||
{
|
||||
TRACE((DEVICE_NAME ": close\n"));
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
device_free(void *data)
|
||||
{
|
||||
struct radeon_info *info = (radeon_info *)data;
|
||||
|
||||
mutex_lock(&gLock);
|
||||
|
||||
if (info->open_count-- == 1) {
|
||||
// release info structure
|
||||
info->init_status = B_NO_INIT;
|
||||
radeon_hd_uninit(*info);
|
||||
}
|
||||
mutex_unlock(&gLock);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
device_ioctl(void *data, uint32 op, void *buffer, size_t bufferLength)
|
||||
{
|
||||
struct radeon_info *info = (radeon_info *)data;
|
||||
|
||||
switch (op) {
|
||||
case B_GET_ACCELERANT_SIGNATURE:
|
||||
strcpy((char *)buffer, RADEON_ACCELERANT_NAME);
|
||||
TRACE((DEVICE_NAME ": accelerant: %s\n", RADEON_ACCELERANT_NAME));
|
||||
return B_OK;
|
||||
|
||||
// needed to share data between kernel and accelerant
|
||||
case RADEON_GET_PRIVATE_DATA:
|
||||
{
|
||||
radeon_get_private_data *data = (radeon_get_private_data *)buffer;
|
||||
|
||||
if (data->magic == RADEON_PRIVATE_DATA_MAGIC) {
|
||||
data->shared_info_area = info->shared_area;
|
||||
return B_OK;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// needed for cloning
|
||||
case RADEON_GET_DEVICE_NAME:
|
||||
#ifdef __HAIKU__
|
||||
if (user_strlcpy((char *)buffer, gDeviceNames[info->id],
|
||||
B_PATH_NAME_LENGTH) < B_OK)
|
||||
return B_BAD_ADDRESS;
|
||||
#else
|
||||
strncpy((char *)buffer, gDeviceNames[info->id], B_PATH_NAME_LENGTH);
|
||||
((char *)buffer)[B_PATH_NAME_LENGTH - 1] = '\0';
|
||||
#endif
|
||||
return B_OK;
|
||||
|
||||
// graphics mem manager
|
||||
case RADEON_ALLOCATE_GRAPHICS_MEMORY:
|
||||
{
|
||||
radeon_allocate_graphics_memory allocMemory;
|
||||
#ifdef __HAIKU__
|
||||
if (user_memcpy(&allocMemory, buffer,
|
||||
sizeof(radeon_allocate_graphics_memory)) < B_OK)
|
||||
return B_BAD_ADDRESS;
|
||||
#else
|
||||
memcpy(&allocMemory, buffer, sizeof(radeon_allocate_graphics_memory));
|
||||
#endif
|
||||
|
||||
if (allocMemory.magic != RADEON_PRIVATE_DATA_MAGIC)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
status_t status = radeon_allocate_memory(*info, allocMemory.size,
|
||||
allocMemory.alignment, allocMemory.flags,
|
||||
(addr_t *)&allocMemory.buffer_base);
|
||||
if (status == B_OK) {
|
||||
// copy result
|
||||
#ifdef __HAIKU__
|
||||
if (user_memcpy(buffer, &allocMemory,
|
||||
sizeof(radeon_allocate_graphics_memory)) < B_OK)
|
||||
return B_BAD_ADDRESS;
|
||||
#else
|
||||
memcpy(buffer, &allocMemory,
|
||||
sizeof(radeon_allocate_graphics_memory));
|
||||
#endif
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
case RADEON_FREE_GRAPHICS_MEMORY:
|
||||
{
|
||||
radeon_free_graphics_memory freeMemory;
|
||||
#ifdef __HAIKU__
|
||||
if (user_memcpy(&freeMemory, buffer,
|
||||
sizeof(radeon_free_graphics_memory)) < B_OK)
|
||||
return B_BAD_ADDRESS;
|
||||
#else
|
||||
memcpy(&freeMemory, buffer, sizeof(radeon_free_graphics_memory));
|
||||
#endif
|
||||
|
||||
if (freeMemory.magic == RADEON_PRIVATE_DATA_MAGIC)
|
||||
return radeon_free_memory(*info, freeMemory.buffer_base);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
TRACE((DEVICE_NAME ": ioctl() unknown message %ld (length = %ld)\n",
|
||||
op, bufferLength));
|
||||
break;
|
||||
}
|
||||
|
||||
return B_DEV_INVALID_IOCTL;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
device_read(void */*data*/, off_t /*pos*/, void */*buffer*/, size_t *_length)
|
||||
{
|
||||
*_length = 0;
|
||||
return B_NOT_ALLOWED;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
device_write(void */*data*/, off_t /*pos*/, const void */*buffer*/, size_t *_length)
|
||||
{
|
||||
*_length = 0;
|
||||
return B_NOT_ALLOWED;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* Copyright 2006, Haiku, Inc. All Rights Reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Axel Dörfler, [email protected]
|
||||
*/
|
||||
#ifndef DEVICE_H
|
||||
#define DEVICE_H
|
||||
|
||||
|
||||
#include <Drivers.h>
|
||||
|
||||
|
||||
/* The published PCI bus interface device hooks */
|
||||
extern device_hooks gDeviceHooks;
|
||||
|
||||
#endif /* DEVICE_H */
|
||||
@@ -0,0 +1,228 @@
|
||||
/*
|
||||
Copyright (c) 2002, Thomas Kurschel
|
||||
|
||||
|
||||
*/
|
||||
|
||||
#include "driver.h"
|
||||
#include "device.h"
|
||||
#include "lock.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <AGP.h>
|
||||
#include <KernelExport.h>
|
||||
#include <OS.h>
|
||||
#include <PCI.h>
|
||||
#include <SupportDefs.h>
|
||||
|
||||
|
||||
#define TRACE_DRIVER
|
||||
#ifdef TRACE_DRIVER
|
||||
# define TRACE(x) dprintf x
|
||||
#else
|
||||
# define TRACE(x) ;
|
||||
#endif
|
||||
|
||||
#define MAX_CARDS 1
|
||||
|
||||
|
||||
// list of supported devices
|
||||
const struct supported_device {
|
||||
uint32 device_id;
|
||||
int32 type;
|
||||
const char* name;
|
||||
} kSupportedDevices[] = {
|
||||
{0x9612, 0, "HD 3200"}
|
||||
};
|
||||
|
||||
|
||||
const uint32 kATIVendorId = 0x1002;
|
||||
|
||||
|
||||
int32 api_version = B_CUR_DRIVER_API_VERSION;
|
||||
|
||||
|
||||
char* gDeviceNames[MAX_CARDS + 1];
|
||||
radeon_info* gDeviceInfo[MAX_CARDS];
|
||||
pci_module_info* gPCI;
|
||||
agp_gart_module_info* gGART;
|
||||
mutex gLock;
|
||||
|
||||
|
||||
static status_t
|
||||
get_next_radeon_hd(int32 *_cookie, pci_info &info, uint32 &type)
|
||||
{
|
||||
int32 index = *_cookie;
|
||||
|
||||
// find devices
|
||||
|
||||
for (; gPCI->get_nth_pci_info(index, &info) == B_OK; index++) {
|
||||
// check vendor
|
||||
if (info.vendor_id != kATIVendorId
|
||||
|| info.class_base != PCI_display
|
||||
|| info.class_sub != PCI_vga)
|
||||
continue;
|
||||
|
||||
// check device
|
||||
for (uint32 i = 0; i < sizeof(kSupportedDevices)
|
||||
/ sizeof(kSupportedDevices[0]); i++) {
|
||||
if (info.device_id == kSupportedDevices[i].device_id) {
|
||||
type = i;
|
||||
*_cookie = index + 1;
|
||||
return B_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return B_ENTRY_NOT_FOUND;
|
||||
}
|
||||
|
||||
|
||||
extern "C" const char **
|
||||
publish_devices(void)
|
||||
{
|
||||
TRACE((DEVICE_NAME ": publish_devices()\n"));
|
||||
return (const char **)gDeviceNames;
|
||||
}
|
||||
|
||||
|
||||
extern "C" status_t
|
||||
init_hardware(void)
|
||||
{
|
||||
TRACE((DEVICE_NAME ": init_hardware()\n"));
|
||||
|
||||
status_t status = get_module(B_PCI_MODULE_NAME,(module_info **)&gPCI);
|
||||
if (status != B_OK) {
|
||||
TRACE((DEVICE_NAME ": pci module unavailable\n"));
|
||||
return status;
|
||||
}
|
||||
|
||||
int32 cookie = 0;
|
||||
uint32 type;
|
||||
pci_info info;
|
||||
status = get_next_radeon_hd(&cookie, info, type);
|
||||
|
||||
put_module(B_PCI_MODULE_NAME);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
extern "C" status_t
|
||||
init_driver(void)
|
||||
{
|
||||
TRACE((DEVICE_NAME ": init_driver()\n"));
|
||||
|
||||
status_t status = get_module(B_PCI_MODULE_NAME, (module_info**)&gPCI);
|
||||
if (status != B_OK) {
|
||||
TRACE((DEVICE_NAME ": pci module unavailable\n"));
|
||||
return status;
|
||||
}
|
||||
|
||||
status = get_module(B_AGP_GART_MODULE_NAME, (module_info**)&gGART);
|
||||
if (status != B_OK) {
|
||||
TRACE((DEVICE_NAME ": AGP GART module unavailable\n"));
|
||||
put_module(B_PCI_MODULE_NAME);
|
||||
return status;
|
||||
}
|
||||
|
||||
mutex_init(&gLock, "intel extreme ksync");
|
||||
|
||||
// find devices
|
||||
|
||||
int32 found = 0;
|
||||
|
||||
for (int32 cookie = 0; found < MAX_CARDS;) {
|
||||
pci_info* info = (pci_info*)malloc(sizeof(pci_info));
|
||||
if (info == NULL)
|
||||
break;
|
||||
|
||||
uint32 type;
|
||||
status = get_next_radeon_hd(&cookie, *info, type);
|
||||
if (status < B_OK) {
|
||||
free(info);
|
||||
break;
|
||||
}
|
||||
|
||||
// create device names & allocate device info structure
|
||||
|
||||
char name[64];
|
||||
sprintf(name, "graphics/radeon_hd_%02x%02x%02x",
|
||||
info->bus, info->device,
|
||||
info->function);
|
||||
|
||||
gDeviceNames[found] = strdup(name);
|
||||
if (gDeviceNames[found] == NULL)
|
||||
break;
|
||||
|
||||
gDeviceInfo[found] = (radeon_info*)malloc(sizeof(radeon_info));
|
||||
if (gDeviceInfo[found] == NULL) {
|
||||
free(gDeviceNames[found]);
|
||||
break;
|
||||
}
|
||||
|
||||
// initialize the structure for later use
|
||||
|
||||
memset(gDeviceInfo[found], 0, sizeof(radeon_info));
|
||||
gDeviceInfo[found]->init_status = B_NO_INIT;
|
||||
gDeviceInfo[found]->id = found;
|
||||
gDeviceInfo[found]->pci = info;
|
||||
gDeviceInfo[found]->registers = (uint8 *)info->u.h0.base_registers[0];
|
||||
gDeviceInfo[found]->device_identifier = kSupportedDevices[type].name;
|
||||
gDeviceInfo[found]->device_type = kSupportedDevices[type].type;
|
||||
|
||||
dprintf(DEVICE_NAME ": (%ld) %s, revision = 0x%x\n", found,
|
||||
kSupportedDevices[type].name, info->revision);
|
||||
|
||||
found++;
|
||||
}
|
||||
|
||||
gDeviceNames[found] = NULL;
|
||||
|
||||
if (found == 0) {
|
||||
mutex_destroy(&gLock);
|
||||
put_module(B_AGP_GART_MODULE_NAME);
|
||||
put_module(B_PCI_MODULE_NAME);
|
||||
return ENODEV;
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
extern "C" void
|
||||
uninit_driver(void)
|
||||
{
|
||||
TRACE((DEVICE_NAME ": uninit_driver()\n"));
|
||||
|
||||
mutex_destroy(&gLock);
|
||||
|
||||
// free device related structures
|
||||
char* name;
|
||||
for (int32 index = 0; (name = gDeviceNames[index]) != NULL; index++) {
|
||||
free(gDeviceInfo[index]);
|
||||
free(name);
|
||||
}
|
||||
|
||||
put_module(B_AGP_GART_MODULE_NAME);
|
||||
put_module(B_PCI_MODULE_NAME);
|
||||
}
|
||||
|
||||
|
||||
extern "C" device_hooks*
|
||||
find_device(const char* name)
|
||||
{
|
||||
int index;
|
||||
|
||||
TRACE((DEVICE_NAME ": find_device()\n"));
|
||||
|
||||
for (index = 0; gDeviceNames[index] != NULL; index++) {
|
||||
if (!strcmp(name, gDeviceNames[index]))
|
||||
return &gDeviceHooks;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright 2006-2009, Haiku, Inc. All Rights Reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Axel Dörfler, [email protected]
|
||||
*/
|
||||
#ifndef DRIVER_H
|
||||
#define DRIVER_H
|
||||
|
||||
|
||||
#include <KernelExport.h>
|
||||
#include <PCI.h>
|
||||
|
||||
|
||||
#include <kernel/lock.h>
|
||||
|
||||
|
||||
#include "radeon_hd_private.h"
|
||||
|
||||
|
||||
// PCI Communications
|
||||
|
||||
#define read8(address) (*((volatile uint8*)(address)))
|
||||
#define read16(address) (*((volatile uint16*)(address)))
|
||||
#define read32(address) (*((volatile uint32*)(address)))
|
||||
#define write8(address, data) (*((volatile uint8*)(address)) = (data))
|
||||
#define write16(address, data) (*((volatile uint16*)(address)) = (data))
|
||||
#define write32(address, data) (*((volatile uint32*)(address)) = (data))
|
||||
|
||||
|
||||
extern char* gDeviceNames[];
|
||||
extern radeon_info* gDeviceInfo[];
|
||||
extern pci_module_info* gPCI;
|
||||
extern agp_gart_module_info* gGART;
|
||||
extern mutex gLock;
|
||||
|
||||
|
||||
static inline uint32
|
||||
get_pci_config(pci_info* info, uint8 offset, uint8 size)
|
||||
{
|
||||
return gPCI->read_pci_config(info->bus, info->device, info->function,
|
||||
offset, size);
|
||||
}
|
||||
|
||||
|
||||
static inline void
|
||||
set_pci_config(pci_info* info, uint8 offset, uint8 size, uint32 value)
|
||||
{
|
||||
gPCI->write_pci_config(info->bus, info->device, info->function, offset,
|
||||
size, value);
|
||||
}
|
||||
|
||||
#endif /* DRIVER_H */
|
||||
@@ -0,0 +1,293 @@
|
||||
/*
|
||||
* Copyright 2006-2009, Haiku, Inc. All Rights Reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Axel Dörfler, [email protected]
|
||||
*/
|
||||
|
||||
|
||||
#include "radeon_hd.h"
|
||||
|
||||
#include "AreaKeeper.h"
|
||||
#include "driver.h"
|
||||
#include "utility.h"
|
||||
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <driver_settings.h>
|
||||
#include <util/kernel_cpp.h>
|
||||
|
||||
|
||||
#define TRACE_DEVICE
|
||||
#ifdef TRACE_DEVICE
|
||||
# define TRACE(x) dprintf x
|
||||
#else
|
||||
# define TRACE(x) ;
|
||||
#endif
|
||||
|
||||
|
||||
static void
|
||||
init_overlay_registers(overlay_registers *registers)
|
||||
{
|
||||
memset(registers, 0, B_PAGE_SIZE);
|
||||
|
||||
registers->contrast_correction = 0x48;
|
||||
registers->saturation_cos_correction = 0x9a;
|
||||
// this by-passes contrast and saturation correction
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
read_settings(bool &hardwareCursor)
|
||||
{
|
||||
hardwareCursor = false;
|
||||
|
||||
void *settings = load_driver_settings("radeon_extreme");
|
||||
if (settings != NULL) {
|
||||
hardwareCursor = get_driver_boolean_parameter(settings,
|
||||
"hardware_cursor", true, true);
|
||||
|
||||
unload_driver_settings(settings);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int32
|
||||
release_vblank_sem(radeon_info &info)
|
||||
{
|
||||
int32 count;
|
||||
if (get_sem_count(info.shared_info->vblank_sem, &count) == B_OK
|
||||
&& count < 0) {
|
||||
release_sem_etc(info.shared_info->vblank_sem, -count,
|
||||
B_DO_NOT_RESCHEDULE);
|
||||
return B_INVOKE_SCHEDULER;
|
||||
}
|
||||
|
||||
return B_HANDLED_INTERRUPT;
|
||||
}
|
||||
|
||||
|
||||
static int32
|
||||
radeon_interrupt_handler(void *data)
|
||||
{
|
||||
radeon_info &info = *(radeon_info *)data;
|
||||
|
||||
uint32 identity = read16(info.registers + RADEON_INTERRUPT_IDENTITY);
|
||||
if (identity == 0)
|
||||
return B_UNHANDLED_INTERRUPT;
|
||||
|
||||
int32 handled = B_HANDLED_INTERRUPT;
|
||||
|
||||
if ((identity & INTERRUPT_VBLANK) != 0) {
|
||||
handled = release_vblank_sem(info);
|
||||
|
||||
// make sure we'll get another one of those
|
||||
write32(info.registers + RADEON_DISPLAY_A_PIPE_STATUS,
|
||||
DISPLAY_PIPE_VBLANK_STATUS);
|
||||
}
|
||||
|
||||
// setting the bit clears it!
|
||||
write16(info.registers + RADEON_INTERRUPT_IDENTITY, identity);
|
||||
|
||||
return handled;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
init_interrupt_handler(radeon_info &info)
|
||||
{
|
||||
info.shared_info->vblank_sem = create_sem(0, "radeon hd vblank");
|
||||
if (info.shared_info->vblank_sem < B_OK)
|
||||
return;
|
||||
|
||||
status_t status = B_OK;
|
||||
|
||||
// We need to change the owner of the sem to the calling team (usually the
|
||||
// app_server), because userland apps cannot acquire kernel semaphores
|
||||
thread_id thread = find_thread(NULL);
|
||||
thread_info threadInfo;
|
||||
if (get_thread_info(thread, &threadInfo) != B_OK
|
||||
|| set_sem_owner(info.shared_info->vblank_sem, threadInfo.team) != B_OK) {
|
||||
status = B_ERROR;
|
||||
}
|
||||
|
||||
if (status == B_OK && info.pci->u.h0.interrupt_pin != 0x00
|
||||
&& info.pci->u.h0.interrupt_line != 0xff) {
|
||||
// we've gotten an interrupt line for us to use
|
||||
|
||||
info.fake_interrupts = false;
|
||||
|
||||
status = install_io_interrupt_handler(info.pci->u.h0.interrupt_line,
|
||||
&radeon_interrupt_handler, (void *)&info, 0);
|
||||
if (status == B_OK) {
|
||||
// enable interrupts - we only want VBLANK interrupts
|
||||
write16(info.registers + RADEON_INTERRUPT_ENABLED,
|
||||
read16(info.registers + RADEON_INTERRUPT_ENABLED)
|
||||
| INTERRUPT_VBLANK);
|
||||
write16(info.registers + RADEON_INTERRUPT_MASK, ~INTERRUPT_VBLANK);
|
||||
|
||||
write32(info.registers + RADEON_DISPLAY_A_PIPE_STATUS,
|
||||
DISPLAY_PIPE_VBLANK_STATUS);
|
||||
write16(info.registers + RADEON_INTERRUPT_IDENTITY, ~0);
|
||||
}
|
||||
}
|
||||
if (status < B_OK) {
|
||||
// There is no interrupt reserved for us, or we couldn't install our
|
||||
// interrupt handler, let's fake the vblank interrupt for our clients
|
||||
// using a timer interrupt
|
||||
info.fake_interrupts = true;
|
||||
|
||||
// TODO: fake interrupts!
|
||||
status = B_ERROR;
|
||||
}
|
||||
|
||||
if (status < B_OK) {
|
||||
delete_sem(info.shared_info->vblank_sem);
|
||||
info.shared_info->vblank_sem = B_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
status_t
|
||||
radeon_free_memory(radeon_info &info, addr_t base)
|
||||
{
|
||||
return gGART->free_memory(info.aperture, base);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
radeon_allocate_memory(radeon_info &info, size_t size, size_t alignment,
|
||||
uint32 flags, addr_t *_base, addr_t *_physicalBase)
|
||||
{
|
||||
return gGART->allocate_memory(info.aperture, size, alignment,
|
||||
flags, _base, _physicalBase);
|
||||
}
|
||||
|
||||
|
||||
enum _rs780MCRegs {
|
||||
RS78_MC_SYSTEM_STATUS = 0x0,
|
||||
RS78_MC_FB_LOCATION = 0x10,
|
||||
RS78_K8_FB_LOCATION = 0x11,
|
||||
RS78_MC_MISC_UMA_CNTL = 0x12
|
||||
};
|
||||
|
||||
|
||||
status_t
|
||||
radeon_hd_init(radeon_info &info)
|
||||
{
|
||||
int fbIndex = 0;
|
||||
int mmioIndex = 1;
|
||||
if (info.device_type.InFamily(RADEON_TYPE_9xx)) {
|
||||
// For some reason Intel saw the need to change the order of the
|
||||
// mappings with the introduction of the i9xx family
|
||||
mmioIndex = 0;
|
||||
fbIndex = 2;
|
||||
}
|
||||
|
||||
// memory mapped I/O
|
||||
|
||||
// TODO: registers are mapped twice (by us and radeon_gart), maybe we
|
||||
// can share it between the drivers
|
||||
|
||||
#define RHD_FB_BAR 0
|
||||
#define RHD_MMIO_BAR 2
|
||||
|
||||
|
||||
AreaKeeper sharedCreator;
|
||||
info.shared_area = sharedCreator.Create("radeon hd shared info",
|
||||
(void **)&info.shared_info, B_ANY_KERNEL_ADDRESS,
|
||||
ROUND_TO_PAGE_SIZE(sizeof(radeon_shared_info)), B_FULL_LOCK, 0);
|
||||
if (info.shared_area < B_OK) {
|
||||
return info.shared_area;
|
||||
}
|
||||
|
||||
memset((void *)info.shared_info, 0, sizeof(radeon_shared_info));
|
||||
|
||||
AreaKeeper mmioMapper;
|
||||
info.registers_area = mmioMapper.Map("radeon hd mmio",
|
||||
(void *)info.pci->u.h0.base_registers[RHD_MMIO_BAR],
|
||||
info.pci->u.h0.base_register_sizes[RHD_MMIO_BAR],
|
||||
B_ANY_KERNEL_ADDRESS, B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA,
|
||||
(void **)&info.registers);
|
||||
if (mmioMapper.InitCheck() < B_OK) {
|
||||
dprintf(DEVICE_NAME ": could not map memory I/O!\n");
|
||||
return info.registers_area;
|
||||
}
|
||||
|
||||
AreaKeeper frambufferMapper;
|
||||
info.framebuffer_area = frambufferMapper.Map("radeon hd framebuffer",
|
||||
(void *)info.pci->u.h0.base_registers[RHD_FB_BAR],
|
||||
info.pci->u.h0.base_register_sizes[RHD_FB_BAR],
|
||||
B_ANY_KERNEL_ADDRESS, B_READ_AREA | B_WRITE_AREA,
|
||||
(void **)&info.shared_info->graphics_memory);
|
||||
if (frambufferMapper.InitCheck() < B_OK) {
|
||||
dprintf(DEVICE_NAME ": could not map framebuffer!\n");
|
||||
return info.framebuffer_area;
|
||||
}
|
||||
|
||||
sharedCreator.Detach();
|
||||
mmioMapper.Detach();
|
||||
frambufferMapper.Detach();
|
||||
|
||||
info.shared_info->registers_area = info.registers_area;
|
||||
info.shared_info->frame_buffer_offset = 0;
|
||||
info.shared_info->physical_graphics_memory = info.pci->u.h0.base_registers[RHD_FB_BAR];
|
||||
|
||||
//?? init_interrupt_handler(info);
|
||||
|
||||
#define R6XX_CONFIG_MEMSIZE 0x5428
|
||||
|
||||
uint32 fbLocation = read32(info.registers + RS78_K8_FB_LOCATION);
|
||||
TRACE((DEVICE_NAME "radeon_hd_init() fb pci location %x, intern location %x \n",
|
||||
info.shared_info->graphics_memory, fbLocation));
|
||||
|
||||
uint32 ramSize = read32(info.registers + R6XX_CONFIG_MEMSIZE) >> 10;
|
||||
TRACE((DEVICE_NAME "radeon_hd_init() ram size %i \n", ramSize));
|
||||
|
||||
|
||||
|
||||
/*TRACE((DEVICE_NAME "radeon_hd_init() fb size %i \n",
|
||||
info.pci->u.h0.base_register_sizes[RHD_FB_BAR]));
|
||||
|
||||
uint8* fbPosition = info.shared_info->graphics_memory;
|
||||
fbPosition += 90000;
|
||||
for (int i = 0; i < 90000; i++) {
|
||||
*fbPosition = 255;
|
||||
fbPosition++;
|
||||
*fbPosition = 0;
|
||||
fbPosition++;
|
||||
*fbPosition = 0;
|
||||
fbPosition++;
|
||||
}
|
||||
fbPosition += 90000;
|
||||
for (int i = 0; i < 90000; i++) {
|
||||
*fbPosition = 255;
|
||||
fbPosition++;
|
||||
*fbPosition = 0;
|
||||
fbPosition++;
|
||||
*fbPosition = 0;
|
||||
fbPosition++;
|
||||
}*/
|
||||
|
||||
TRACE((DEVICE_NAME "radeon_hd_init() completed successfully!\n"));
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
radeon_hd_uninit(radeon_info &info)
|
||||
{
|
||||
TRACE((DEVICE_NAME ": radeon_extreme_uninit()\n"));
|
||||
|
||||
delete_area(info.shared_area);
|
||||
delete_area(info.registers_area);
|
||||
delete_area(info.framebuffer_area);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright 2006-2008, Haiku, Inc. All Rights Reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Axel Dörfler, [email protected]
|
||||
*/
|
||||
#ifndef RADEON_RD_PRIVATE_H
|
||||
#define RADEON_RD_PRIVATE_H
|
||||
|
||||
|
||||
#include <AGP.h>
|
||||
#include <KernelExport.h>
|
||||
#include <PCI.h>
|
||||
|
||||
|
||||
#include "radeon_hd.h"
|
||||
#include "lock.h"
|
||||
|
||||
|
||||
struct radeon_info {
|
||||
int32 open_count;
|
||||
status_t init_status;
|
||||
int32 id;
|
||||
pci_info* pci;
|
||||
addr_t aperture_base;
|
||||
aperture_id aperture;
|
||||
uint8* registers;
|
||||
area_id registers_area;
|
||||
area_id framebuffer_area;
|
||||
|
||||
struct radeon_shared_info* shared_info;
|
||||
area_id shared_area;
|
||||
|
||||
struct overlay_registers* overlay_registers;
|
||||
|
||||
bool fake_interrupts;
|
||||
|
||||
const char* device_identifier;
|
||||
DeviceType device_type;
|
||||
};
|
||||
|
||||
extern status_t radeon_free_memory(radeon_info& info, addr_t offset);
|
||||
extern status_t radeon_allocate_memory(radeon_info& info, size_t size,
|
||||
size_t alignment, uint32 flags, addr_t* _offset,
|
||||
addr_t* _physicalBase = NULL);
|
||||
extern status_t radeon_hd_init(radeon_info& info);
|
||||
extern void radeon_hd_uninit(radeon_info& info);
|
||||
|
||||
#endif /* RADEON_RD_PRIVATE_H */
|
||||
Reference in New Issue
Block a user