diff --git a/headers/private/graphics/intel_extreme/intel_extreme.h b/headers/private/graphics/intel_extreme/intel_extreme.h new file mode 100644 index 0000000000..7f02819248 --- /dev/null +++ b/headers/private/graphics/intel_extreme/intel_extreme.h @@ -0,0 +1,158 @@ +/* + * Copyright 2006, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Axel Dörfler, axeld@pinc-software.de + */ +#ifndef INTEL_EXTREME_H +#define INTEL_EXTREME_H + + +#include +#include +#include + + +#define VENDOR_ID_INTEL 0x8086 +#define DEVICE_ID_i865 0x2572 + +#define DEVICE_NAME "intel_extreme" +#define INTEL_ACCELERANT_NAME "intel_extreme.accelerant" + +#define INTEL_COOKIE_MAGIC 'intl' +#define INTEL_FREE_COOKIE_MAGIC 'itlf' + +// info about PLL on graphics card +struct pll_info { + uint32 reference_frequency; + uint32 max_frequency; + uint32 min_frequency; + uint32 divisor_register; +}; + +struct intel_shared_info { + int32 type; + area_id mode_list_area; // area containing display mode list + uint32 mode_count; + + display_mode current_mode; + uint32 bytes_per_row; + uint32 dpms_mode; + + area_id registers_area; // area of memory mapped registers + area_id frame_buffer_area; // area of frame buffer + uint8 *frame_buffer; // pointer to frame buffer (visible by all apps!) + uint8 *physical_frame_buffer; + + uint32 graphics_memory_size; + struct pll_info pll_info; +}; + +struct intel_info { + uint32 cookie_magic; + int32 open_count; + int32 id; + pci_info *pci; + uint8 *registers; + area_id registers_area; + struct intel_shared_info *shared_info; + area_id shared_area; + uint8 *frame_buffer; + area_id frame_buffer_area; +}; + +//----------------- ioctl() interface ---------------- + +// magic code for ioctls +#define INTEL_PRIVATE_DATA_MAGIC 'itic' + +// list ioctls +enum { + INTEL_GET_PRIVATE_DATA = B_DEVICE_OP_CODES_END + 1, + + INTEL_GET_DEVICE_NAME, + INTEL_ALLOC_LOCAL_MEMORY, + INTEL_FREE_LOCAL_MEMORY +}; + +// retrieve the area_id of the kernel/accelerant shared info +struct intel_get_private_data { + uint32 magic; // magic number + area_id shared_info_area; +}; + +// allocate graphics memory +struct intel_allocate_graphics_memory { + uint32 magic; + uint32 size; + uint32 fb_offset; + uint32 handle; +}; + +// free graphics memory +struct intel_free_graphics_memory { + uint32 magic; + uint32 handle; +}; + +//---------------------------------------------------------- +// Register definitions, taken from X driver + +#define INTEL_DISPLAY_HTOTAL 0x60000 +#define INTEL_DISPLAY_HBLANK 0x60004 +#define INTEL_DISPLAY_HSYNC 0x60008 +#define INTEL_DISPLAY_VTOTAL 0x6000c +#define INTEL_DISPLAY_VBLANK 0x60010 +#define INTEL_DISPLAY_VSYNC 0x60014 +#define INTEL_DISPLAY_IMAGE_SIZE 0x6001c + +#define INTEL_DISPLAY_CONTROL 0x70180 +#define INTEL_DISPLAY_BASE 0x70184 +#define INTEL_DISPLAY_BYTES_PER_ROW 0x70188 +#define DISPLAY_CONTROL_ENABLED (1UL << 31) +#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 (7UL << 26) + +#define INTEL_DISPLAY_PIPE_CONTROL 0x70008 +#define DISPLAY_PIPE_ENABLED (1UL << 31) + +#define INTEL_DISPLAY_PLL 0x06014 +#define INTEL_DISPLAY_PLL_DIVISOR_0 0x06040 +#define INTEL_DISPLAY_PLL_DIVISOR_1 0x06044 +#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_DIVIDE_4X (1UL << 23) +#define DISPLAY_PLL_POST_DIVISOR_MASK 0x001f0000 +#define DISPLAY_PLL_POST_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 INTEL_DISPLAY_ANALOG_PORT 0x61100 +#define DISPLAY_MONITOR_PORT_ENABLED (1UL << 31) +#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) + +//---------------------------------------------------------- + +extern status_t intel_extreme_init(intel_info &info); +extern void intel_extreme_uninit(intel_info &info); + +#endif /* INTEL_EXTREME_H */ diff --git a/headers/private/graphics/intel_extreme/lock.h b/headers/private/graphics/intel_extreme/lock.h new file mode 100644 index 0000000000..3c11f24c02 --- /dev/null +++ b/headers/private/graphics/intel_extreme/lock.h @@ -0,0 +1,57 @@ +/* + * Copyright 2006, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Axel Dörfler, axeld@pinc-software.de + */ +#ifndef LOCK_H +#define LOCK_H + + +#include + + +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; +} + +#endif /* LOCK_H */ diff --git a/headers/private/graphics/intel_extreme/utility.h b/headers/private/graphics/intel_extreme/utility.h new file mode 100644 index 0000000000..eae3c06660 --- /dev/null +++ b/headers/private/graphics/intel_extreme/utility.h @@ -0,0 +1,13 @@ +/* + * Copyright 2006, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Axel Dörfler, axeld@pinc-software.de + */ +#ifndef UTILITY_H +#define UTILITY_H + +#define ROUND_TO_PAGE_SIZE(x) (((x) + (B_PAGE_SIZE) - 1) & ~((B_PAGE_SIZE) - 1)) + +#endif /* UTILITY_H */ diff --git a/src/add-ons/accelerants/Jamfile b/src/add-ons/accelerants/Jamfile index 61031b11d3..923283b154 100644 --- a/src/add-ons/accelerants/Jamfile +++ b/src/add-ons/accelerants/Jamfile @@ -2,6 +2,7 @@ SubDir HAIKU_TOP src add-ons accelerants ; SubInclude HAIKU_TOP src add-ons accelerants common ; SubInclude HAIKU_TOP src add-ons accelerants et6x00 ; +SubInclude HAIKU_TOP src add-ons accelerants intel_extreme ; SubInclude HAIKU_TOP src add-ons accelerants matrox ; SubInclude HAIKU_TOP src add-ons accelerants neomagic ; SubInclude HAIKU_TOP src add-ons accelerants nvidia ; diff --git a/src/add-ons/accelerants/intel_extreme/Jamfile b/src/add-ons/accelerants/intel_extreme/Jamfile new file mode 100644 index 0000000000..195a98490c --- /dev/null +++ b/src/add-ons/accelerants/intel_extreme/Jamfile @@ -0,0 +1,17 @@ +SubDir HAIKU_TOP src add-ons accelerants intel_extreme ; + +SetSubDirSupportedPlatformsBeOSCompatible ; + +UsePrivateHeaders graphics ; +UsePrivateHeaders [ FDirName graphics intel_extreme ] ; +UsePrivateHeaders [ FDirName graphics common ] ; + +Addon intel_extreme.accelerant : accelerants : + accelerant.cpp + dpms.cpp + engine.cpp + hooks.cpp + mode.cpp + : false + : be +; diff --git a/src/add-ons/accelerants/intel_extreme/accelerant.cpp b/src/add-ons/accelerants/intel_extreme/accelerant.cpp new file mode 100644 index 0000000000..9afa155f8e --- /dev/null +++ b/src/add-ons/accelerants/intel_extreme/accelerant.cpp @@ -0,0 +1,274 @@ +/* + * Copyright 2006, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Axel Dörfler, axeld@pinc-software.de + */ + + +#include "accelerant_protos.h" +#include "accelerant.h" + +#include +#include +#include +#include + + +#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 < B_OK ? (status_t)fArea : B_OK; } + void Keep(); + + private: + area_id fArea; +}; + + +AreaCloner::AreaCloner() + : + fArea(-1) +{ +} + + +AreaCloner::~AreaCloner() +{ + if (fArea >= B_OK) + 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 + + intel_get_private_data data; + data.magic = INTEL_PRIVATE_DATA_MAGIC; + + if (ioctl(device, INTEL_GET_PRIVATE_DATA, &data, sizeof(intel_get_private_data)) != 0) { + free(gInfo); + return B_ERROR; + } + + AreaCloner sharedCloner; + gInfo->shared_info_area = sharedCloner.Clone("intel extreme 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); + return status; + } + + AreaCloner regsCloner; + gInfo->regs_area = regsCloner.Clone("intel extreme 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; + + gInfo->regs = NULL; + gInfo->shared_info = NULL; + + // close the file handle ONLY if we're the clone + // (this is what Be tells us ;) + if (gInfo->is_clone) + close(gInfo->device); + + free(gInfo); +} + + +// #pragma mark - public accelerant functions + + +/** Init primary accelerant */ + +status_t +intel_init_accelerant(int device) +{ + syslog(LOG_ERR, "intel_extreme.accelerant here!\n"); + + status_t status = init_common(device, false); + if (status != B_OK) + return status; + + status = create_mode_list(); + if (status != B_OK) { + uninit_common(); + return status; + } + + return B_OK; +} + + +ssize_t +intel_accelerant_clone_info_size(void) +{ + // clone info is device name, so return its maximum size + return B_PATH_NAME_LENGTH; +} + + +void +intel_get_accelerant_clone_info(void *info) +{ + ioctl(gInfo->device, INTEL_GET_DEVICE_NAME, info, B_PATH_NAME_LENGTH); +} + + +status_t +intel_clone_accelerant(void *info) +{ + TRACE(("intel_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 fd; + + 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 +intel_uninit_accelerant(void) +{ + TRACE(("intel_uninit_accelerant()\n")); + + // delete accelerant instance data + delete_area(gInfo->mode_list_area); + gInfo->mode_list = NULL; + + uninit_common(); +} + + +status_t +intel_get_accelerant_device_info(accelerant_device_info *info) +{ + info->version = B_ACCELERANT_VERSION; + strcpy(info->name, "Intel Extreme Graphics 2"); + strcpy(info->chipset, "i865G"); + // TODO: provide some more insight here once we support more than that one chip... + 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 +intel_accelerant_retrace_semaphore() +{ + return -1; +} + diff --git a/src/add-ons/accelerants/intel_extreme/accelerant.h b/src/add-ons/accelerants/intel_extreme/accelerant.h new file mode 100644 index 0000000000..a35fa9b222 --- /dev/null +++ b/src/add-ons/accelerants/intel_extreme/accelerant.h @@ -0,0 +1,53 @@ +/* + * Copyright 2006, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Axel Dörfler, axeld@pinc-software.de + */ +#ifndef INTEL_EXTREME_ACCELERANT_H +#define INTEL_EXTREME_ACCELERANT_H + + +#include "intel_extreme.h" + + +typedef struct accelerant_info { + vuint8 *regs; + area_id regs_area; + + intel_shared_info *shared_info; + area_id shared_info_area; + + display_mode *mode_list; // cloned list of standard display modes + area_id mode_list_area; + + int device; + bool is_clone; +} accelerant_info; + +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; +} + + +// dpms.cpp +extern void enable_display_plane(bool enable); +extern void set_display_power_mode(uint32 mode); + +// modes.cpp +extern status_t create_mode_list(void); + +#endif /* INTEL_EXTREME_ACCELERANT_H */ diff --git a/src/add-ons/accelerants/intel_extreme/accelerant_protos.h b/src/add-ons/accelerants/intel_extreme/accelerant_protos.h new file mode 100644 index 0000000000..f3c04bb065 --- /dev/null +++ b/src/add-ons/accelerants/intel_extreme/accelerant_protos.h @@ -0,0 +1,87 @@ +/* + * Copyright 2006, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Axel Dörfler, axeld@pinc-software.de + */ +#ifndef ACCELERANT_PROTOS_H +#define ACCELERANT_PROTOS_H + + +#include +#include "video_overlay.h" + + +#ifdef __cplusplus +extern "C" { +#endif + +// 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); +void intel_uninit_accelerant(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); +status_t intel_get_mode_list(display_mode *dm); +status_t intel_propose_display_mode(display_mode *target, const display_mode *low, + const display_mode *high); +status_t intel_set_display_mode(display_mode *mode); +status_t intel_get_display_mode(display_mode *currentMode); +status_t intel_get_frame_buffer_config(frame_buffer_config *config); +status_t intel_get_pixel_clock_limits(display_mode *mode, uint32 *low, uint32 *high); +status_t intel_move_display(uint16 hDisplayStart, uint16 vDisplayStart); +status_t intel_get_timing_constraints(display_timing_constraints *constraints); +void intel_set_indexed_colors(uint count, uint8 first, uint8 *colorData, uint32 flags); + +// DPMS +uint32 intel_dpms_capabilities(void); +uint32 intel_dpms_mode(void); +status_t intel_set_dpms_mode(uint32 flags); + +// cursor +status_t intel_set_cursor_shape(uint16 width, uint16 height, uint16 hotX, uint16 hotX, + uint8 *andMask, uint8 *xorMask); +void intel_move_cursor(uint16 x, uint16 y); +void intel_show_cursor(bool isVisible); + +// accelerant engine +uint32 intel_accelerant_engine_count(void); +status_t intel_acquire_engine(uint32 capabilities, uint32 maxWait, + sync_token *syncToken, engine_token **_engineToken); +status_t intel_release_engine(engine_token *engineToken, sync_token *syncToken); +void intel_wait_engine_idle(void); +status_t intel_get_sync_token(engine_token *engineToken, sync_token *syncToken); +status_t intel_sync_to_token(sync_token *syncToken); + +// 2D acceleration +void intel_screen_to_screen_blit(engine_token *engineToken, blit_params *list, uint32 count); +void intel_fill_rectangle(engine_token *engineToken, uint32 color, fill_rect_params *list, + uint32 count); +void intel_invert_rectangle(engine_token *engineToken, fill_rect_params *list, uint32 count); +void intel_fill_span(engine_token *engineToken, uint32 color, uint16 *list, uint32 count); + +// overlay +uint32 intel_overlay_count(const display_mode *dm); +const uint32 *intel_overlay_supported_spaces(const display_mode *dm); +uint32 intel_overlay_supported_features(uint32 a_color_space); +const overlay_buffer *intel_allocate_overlay_buffer(color_space space, uint16 width, + uint16 height); +status_t intel_release_overlay_buffer(const overlay_buffer *buffer); +status_t intel_get_overlay_constraints(const display_mode *mode, const overlay_buffer *buffer, + overlay_constraints *constraints); +overlay_token intel_allocate_overlay(void); +status_t intel_release_overlay(overlay_token overlayToken); +status_t intel_configure_overlay(overlay_token overlayToken, const overlay_buffer *buffer, + const overlay_window *window, const overlay_view *view); + +#ifdef __cplusplus +} +#endif + +#endif /* ACCELERANT_PROTOS_H */ diff --git a/src/add-ons/accelerants/intel_extreme/dpms.cpp b/src/add-ons/accelerants/intel_extreme/dpms.cpp new file mode 100644 index 0000000000..d6addf3ef9 --- /dev/null +++ b/src/add-ons/accelerants/intel_extreme/dpms.cpp @@ -0,0 +1,106 @@ +/* + * Copyright 2006, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Axel Dörfler, axeld@pinc-software.de + */ + + +#include "accelerant_protos.h" +#include "accelerant.h" + + +void +enable_display_plane(bool enable) +{ + uint32 oldValue = read32(INTEL_DISPLAY_CONTROL); + + if (enable) { + // when enabling the display, the register values are updated automatically + write32(INTEL_DISPLAY_CONTROL, oldValue | DISPLAY_CONTROL_ENABLED); + } else { + // when disabling it, we have to trigger the update using a write to + // the display base address + write32(INTEL_DISPLAY_CONTROL, oldValue & ~DISPLAY_CONTROL_ENABLED); + write32(INTEL_DISPLAY_BASE, 0); + } +} + + +static void +enable_display_pipe(bool enable) +{ + uint32 oldValue = read32(INTEL_DISPLAY_PIPE_CONTROL); + if (enable) + write32(INTEL_DISPLAY_PIPE_CONTROL, oldValue | DISPLAY_PIPE_ENABLED); + else + write32(INTEL_DISPLAY_PIPE_CONTROL, oldValue & ~DISPLAY_PIPE_ENABLED); +} + + +void +set_display_power_mode(uint32 mode) +{ + uint32 monitorMode = 0; + + if (mode == B_DPMS_ON) { + enable_display_pipe(true); + enable_display_plane(true); + } + + // TODO: wait for vblank! + snooze(10000); + + switch (mode) { + case B_DPMS_ON: + monitorMode = DISPLAY_MONITOR_ON; + break; + case B_DPMS_SUSPEND: + monitorMode = DISPLAY_MONITOR_SUSPEND; + break; + case B_DPMS_STAND_BY: + monitorMode = DISPLAY_MONITOR_STAND_BY; + break; + case B_DPMS_OFF: + monitorMode = DISPLAY_MONITOR_OFF; + break; + } + + write32(INTEL_DISPLAY_ANALOG_PORT, (read32(INTEL_DISPLAY_ANALOG_PORT) + & ~(DISPLAY_MONITOR_MODE_MASK | DISPLAY_MONITOR_PORT_ENABLED)) + | monitorMode | (mode != B_DPMS_OFF ? DISPLAY_MONITOR_PORT_ENABLED : 0)); + + if (mode != B_DPMS_ON) { + enable_display_plane(false); + enable_display_pipe(false); + } +} + + +// #pragma mark - + + +uint32 +intel_dpms_capabilities(void) +{ + return B_DPMS_ON | B_DPMS_SUSPEND | B_DPMS_STAND_BY | B_DPMS_OFF; +} + + +uint32 +intel_dpms_mode(void) +{ + return gInfo->shared_info->dpms_mode; +} + + +status_t +intel_set_dpms_mode(uint32 mode) +{ + gInfo->shared_info->dpms_mode = mode; + set_display_power_mode(mode); + + return B_OK; +} + diff --git a/src/add-ons/accelerants/intel_extreme/engine.cpp b/src/add-ons/accelerants/intel_extreme/engine.cpp new file mode 100644 index 0000000000..7017d78ce7 --- /dev/null +++ b/src/add-ons/accelerants/intel_extreme/engine.cpp @@ -0,0 +1,64 @@ +/* + * Copyright 2006, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Axel Dörfler, axeld@pinc-software.de + */ + + +#include "accelerant_protos.h" +#include "intel_extreme.h" + + +static engine_token sEngineToken = {1, 0 /*B_2D_ACCELERATION*/, NULL}; + + +// public function: return number of hardware engine + +uint32 +intel_accelerant_engine_count(void) +{ + return 1; +} + + +status_t +intel_acquire_engine(uint32 capabilities, uint32 maxWait, sync_token *syncToken, + engine_token **_engineToken) +{ + *_engineToken = &sEngineToken; + + return B_OK; +} + + +status_t +intel_release_engine(engine_token *engineToken, sync_token *syncToken) +{ + if (syncToken != NULL) + syncToken->engine_id = engineToken->engine_id; + + return B_OK; +} + + +void +intel_wait_engine_idle(void) +{ +} + + +status_t +intel_get_sync_token(engine_token *engineToken, sync_token *syncToken) +{ + return B_OK; +} + + +status_t +intel_sync_to_token(sync_token *syncToken) +{ + return B_OK; +} + diff --git a/src/add-ons/accelerants/intel_extreme/hooks.cpp b/src/add-ons/accelerants/intel_extreme/hooks.cpp new file mode 100644 index 0000000000..4138812a67 --- /dev/null +++ b/src/add-ons/accelerants/intel_extreme/hooks.cpp @@ -0,0 +1,106 @@ +/* + * Copyright 2006, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Axel Dörfler, axeld@pinc-software.de + */ + + +#include "accelerant_protos.h" + + +extern "C" void * +get_accelerant_hook(uint32 feature, void *data) +{ + switch (feature) { + /* general */ + case B_INIT_ACCELERANT: + return intel_init_accelerant; + case B_UNINIT_ACCELERANT: + return intel_uninit_accelerant; + case B_CLONE_ACCELERANT: + return intel_clone_accelerant; + case B_ACCELERANT_CLONE_INFO_SIZE: + return intel_accelerant_clone_info_size; + case B_GET_ACCELERANT_CLONE_INFO: + return intel_get_accelerant_clone_info; + case B_GET_ACCELERANT_DEVICE_INFO: + return intel_get_accelerant_device_info; + case B_ACCELERANT_RETRACE_SEMAPHORE: + return intel_accelerant_retrace_semaphore; + + /* mode configuration */ + case B_ACCELERANT_MODE_COUNT: + return intel_accelerant_mode_count; + case B_GET_MODE_LIST: + return intel_get_mode_list; + case B_PROPOSE_DISPLAY_MODE: + return intel_propose_display_mode; + case B_SET_DISPLAY_MODE: + return intel_set_display_mode; + case B_GET_DISPLAY_MODE: + return intel_get_display_mode; + case B_GET_FRAME_BUFFER_CONFIG: + return intel_get_frame_buffer_config; + case B_GET_PIXEL_CLOCK_LIMITS: + return intel_get_pixel_clock_limits; + case B_MOVE_DISPLAY: + return intel_move_display; + case B_SET_INDEXED_COLORS: + return intel_set_indexed_colors; + case B_GET_TIMING_CONSTRAINTS: + return intel_get_timing_constraints; + + /* DPMS */ + case B_DPMS_CAPABILITIES: + return intel_dpms_capabilities; + case B_DPMS_MODE: + return intel_dpms_mode; + case B_SET_DPMS_MODE: + return intel_set_dpms_mode; + + /* cursor managment */ +/* case B_SET_CURSOR_SHAPE: + return intel_set_cursor_shape; + case B_MOVE_CURSOR: + return intel_move_cursor; + case B_SHOW_CURSOR: + return intel_show_cursor; +*/ + /* engine/synchronization */ + case B_ACCELERANT_ENGINE_COUNT: + return intel_accelerant_engine_count; + case B_ACQUIRE_ENGINE: + return intel_acquire_engine; + case B_RELEASE_ENGINE: + return intel_release_engine; + case B_WAIT_ENGINE_IDLE: + return intel_wait_engine_idle; + case B_GET_SYNC_TOKEN: + return intel_get_sync_token; + case B_SYNC_TO_TOKEN: + return intel_sync_to_token; + + /* 2D acceleration */ +/* HOOK(SCREEN_TO_SCREEN_BLIT); + HOOK(FILL_RECTANGLE); + HOOK(INVERT_RECTANGLE); + HOOK(FILL_SPAN); +*/ + // overlay +/* HOOK(OVERLAY_COUNT); + HOOK(OVERLAY_SUPPORTED_SPACES); + HOOK(OVERLAY_SUPPORTED_FEATURES); + HOOK(ALLOCATE_OVERLAY_BUFFER); + HOOK(RELEASE_OVERLAY_BUFFER); + HOOK(GET_OVERLAY_CONSTRAINTS); + HOOK(ALLOCATE_OVERLAY); + HOOK(RELEASE_OVERLAY); + HOOK(CONFIGURE_OVERLAY); +*/ + } + + return NULL; +} + diff --git a/src/add-ons/accelerants/intel_extreme/mode.cpp b/src/add-ons/accelerants/intel_extreme/mode.cpp new file mode 100644 index 0000000000..1da38bef16 --- /dev/null +++ b/src/add-ons/accelerants/intel_extreme/mode.cpp @@ -0,0 +1,390 @@ +/* + * Copyright 2006, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Axel Dörfler, axeld@pinc-software.de + */ + + +#include "accelerant_protos.h" +#include "accelerant.h" +#include "utility.h" + + +#define TRACE_MODE +#ifdef TRACE_MODE +extern "C" void _sPrintf(const char *format, ...); +# define TRACE(x) _sPrintf x +#else +# define TRACE(x) ; +#endif + + +#define T_POSITIVE_SYNC (B_POSITIVE_HSYNC | B_POSITIVE_VSYNC) +#define MODE_FLAGS (B_8_BIT_DAC | /*B_HARDWARE_CURSOR |*/ B_PARALLEL_ACCESS | B_DPMS /*| B_SUPPORTS_OVERLAYS*/) + + +static const display_mode kBaseModeList[] = { + {{25175, 640, 656, 752, 800, 350, 387, 389, 449, B_POSITIVE_HSYNC}, B_CMAP8, 640, 350, 0, 0, MODE_FLAGS}, /* 640x350 - www.epanorama.net/documents/pc/vga_timing.html) */ + {{25175, 640, 656, 752, 800, 400, 412, 414, 449, B_POSITIVE_VSYNC}, B_CMAP8, 640, 400, 0, 0, MODE_FLAGS}, /* 640x400 - www.epanorama.net/documents/pc/vga_timing.html) */ + {{25175, 640, 656, 752, 800, 480, 490, 492, 525, 0}, B_CMAP8, 640, 480, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@60Hz_(640X480X8.Z1) */ + {{27500, 640, 672, 768, 864, 480, 488, 494, 530, 0}, B_CMAP8, 640, 480, 0, 0, MODE_FLAGS}, /* 640X480X60Hz */ + {{30500, 640, 672, 768, 864, 480, 517, 523, 588, 0}, B_CMAP8, 640, 480, 0, 0, MODE_FLAGS}, /* SVGA_640X480X60HzNI */ + {{31500, 640, 664, 704, 832, 480, 489, 492, 520, 0}, B_CMAP8, 640, 480, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@70-72Hz_(640X480X8.Z1) */ + {{31500, 640, 656, 720, 840, 480, 481, 484, 500, 0}, B_CMAP8, 640, 480, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@75Hz_(640X480X8.Z1) */ + {{36000, 640, 696, 752, 832, 480, 481, 484, 509, 0}, B_CMAP8, 640, 480, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@85Hz_(640X480X8.Z1) */ + {{38100, 800, 832, 960, 1088, 600, 602, 606, 620, 0}, B_CMAP8, 800, 600, 0, 0, MODE_FLAGS}, /* SVGA_800X600X56HzNI */ + {{40000, 800, 840, 968, 1056, 600, 601, 605, 628, T_POSITIVE_SYNC}, B_CMAP8, 800, 600, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@60Hz_(800X600X8.Z1) */ + {{49500, 800, 816, 896, 1056, 600, 601, 604, 625, T_POSITIVE_SYNC}, B_CMAP8, 800, 600, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@75Hz_(800X600X8.Z1) */ + {{50000, 800, 856, 976, 1040, 600, 637, 643, 666, T_POSITIVE_SYNC}, B_CMAP8, 800, 600, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@70-72Hz_(800X600X8.Z1) */ + {{56250, 800, 832, 896, 1048, 600, 601, 604, 631, T_POSITIVE_SYNC}, B_CMAP8, 800, 600, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@85Hz_(800X600X8.Z1) */ + {{65000, 1024, 1048, 1184, 1344, 768, 771, 777, 806, 0}, B_CMAP8, 1024, 768, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@60Hz_(1024X768X8.Z1) */ + {{75000, 1024, 1048, 1184, 1328, 768, 771, 777, 806, 0}, B_CMAP8, 1024, 768, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@70-72Hz_(1024X768X8.Z1) */ + {{78750, 1024, 1040, 1136, 1312, 768, 769, 772, 800, T_POSITIVE_SYNC}, B_CMAP8, 1024, 768, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@75Hz_(1024X768X8.Z1) */ + {{94500, 1024, 1072, 1168, 1376, 768, 769, 772, 808, T_POSITIVE_SYNC}, B_CMAP8, 1024, 768, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@85Hz_(1024X768X8.Z1) */ + {{94200, 1152, 1184, 1280, 1472, 864, 865, 868, 914, T_POSITIVE_SYNC}, B_CMAP8, 1152, 864, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@70Hz_(1152X864X8.Z1) */ + {{108000, 1152, 1216, 1344, 1600, 864, 865, 868, 900, T_POSITIVE_SYNC}, B_CMAP8, 1152, 864, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@75Hz_(1152X864X8.Z1) */ + {{121500, 1152, 1216, 1344, 1568, 864, 865, 868, 911, T_POSITIVE_SYNC}, B_CMAP8, 1152, 864, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@85Hz_(1152X864X8.Z1) */ + {{108000, 1280, 1328, 1440, 1688, 1024, 1025, 1028, 1066, T_POSITIVE_SYNC}, B_CMAP8, 1280, 1024, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@60Hz_(1280X1024X8.Z1) */ + {{135000, 1280, 1296, 1440, 1688, 1024, 1025, 1028, 1066, T_POSITIVE_SYNC}, B_CMAP8, 1280, 1024, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@75Hz_(1280X1024X8.Z1) */ + {{157500, 1280, 1344, 1504, 1728, 1024, 1025, 1028, 1072, T_POSITIVE_SYNC}, B_CMAP8, 1280, 1024, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@85Hz_(1280X1024X8.Z1) */ + {{162000, 1600, 1664, 1856, 2160, 1200, 1201, 1204, 1250, T_POSITIVE_SYNC}, B_CMAP8, 1600, 1200, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@60Hz_(1600X1200X8.Z1) */ + {{175500, 1600, 1664, 1856, 2160, 1200, 1201, 1204, 1250, T_POSITIVE_SYNC}, B_CMAP8, 1600, 1200, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@65Hz_(1600X1200X8.Z1) */ + {{189000, 1600, 1664, 1856, 2160, 1200, 1201, 1204, 1250, T_POSITIVE_SYNC}, B_CMAP8, 1600, 1200, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@70Hz_(1600X1200X8.Z1) */ + {{202500, 1600, 1664, 1856, 2160, 1200, 1201, 1204, 1250, T_POSITIVE_SYNC}, B_CMAP8, 1600, 1200, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@75Hz_(1600X1200X8.Z1) */ + {{216000, 1600, 1664, 1856, 2160, 1200, 1201, 1204, 1250, T_POSITIVE_SYNC}, B_CMAP8, 1600, 1200, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@80Hz_(1600X1200X8.Z1) */ + {{229500, 1600, 1664, 1856, 2160, 1200, 1201, 1204, 1250, T_POSITIVE_SYNC}, B_CMAP8, 1600, 1200, 0, 0, MODE_FLAGS} /* Vesa_Monitor_@85Hz_(1600X1200X8.Z1) */ +}; +static const uint32 kNumBaseModes = sizeof(kBaseModeList) / sizeof(display_mode); +static const uint32 kMaxNumModes = kNumBaseModes * 4; + + +/** Creates the initial mode list of the primary accelerant. + * It's called from intel_init_accelerant(). + */ + +status_t +create_mode_list(void) +{ + color_space spaces[4] = {B_RGB32_LITTLE, B_RGB16_LITTLE, B_RGB15_LITTLE, B_CMAP8}; + size_t size = ROUND_TO_PAGE_SIZE(kMaxNumModes * sizeof(display_mode)); + display_mode *list; + + gInfo->mode_list_area = create_area("intel extreme modes", (void **)&list, B_ANY_ADDRESS, + size, B_NO_LOCK, B_READ_AREA | B_WRITE_AREA); + if (gInfo->mode_list_area < B_OK) + return gInfo->mode_list_area; + + // for now, just copy all of the modes with different color spaces + + const display_mode *source = kBaseModeList; + uint32 count = 0; + + for (uint32 i = 0; i < kNumBaseModes; i++) { + for (uint32 j = 0; j < (sizeof(spaces) / sizeof(color_space)); j++) { + list[count] = *source; + list[count].space = spaces[j]; + + count++; + } + + source++; + } + + gInfo->mode_list = list; + gInfo->shared_info->mode_list_area = gInfo->mode_list_area; + gInfo->shared_info->mode_count = count; + + return B_OK; +} + + +static void +compute_pll_divisors(const display_mode ¤t, uint32 &postDivisor, + uint32 &nDivisor, uint32 &m1Divisor, uint32 &m2Divisor) +{ + float requestedPixelClock = current.timing.pixel_clock / 1000.0f; + float referenceClock = gInfo->shared_info->pll_info.reference_frequency / 1000.0f; + + TRACE(("required MHz: %g\n", requestedPixelClock)); + + float best = requestedPixelClock; + uint32 bestP = 0, bestN = 0, bestM = 0; + + // Note, the limits are taken from the X driver; they have not yet been tested + + for (uint32 p = 3; p < 31; p++) { + for (uint32 n = 3; n < 16; n++) { + for (uint32 m1 = 6; m1 < 26; m1++) { + for (uint32 m2 = 6; m2 < 16; m2++) { + uint32 m = m1 * 5 + m2; + float error = fabs(requestedPixelClock - ((referenceClock * m) / n) / (p*4)); + if (error < best) { + best = error; + bestP = p; + bestN = n; + bestM = m; + if (error == 0) + break; + } + } + } + } + } + + postDivisor = bestP; + nDivisor = bestN; + + TRACE(("found: %g MHz (p = %lu, n = %lu, m = %lu (m1 = %lu, m2 = %lu)\n", + ((referenceClock * bestM) / bestN) / (bestP*4), bestP, bestN, bestM, + m1Divisor, m2Divisor)); + + m1Divisor = bestM / 5; + m2Divisor = bestM % 5; + while (m2Divisor < 6) { + m1Divisor--; + m2Divisor += 5; + } +} + + +static void +get_color_space_format(const display_mode &mode, uint32 &colorMode, uint32 &bytesPerRow) +{ + uint32 bytesPerPixel; + + switch (mode.space) { + case B_RGB32_LITTLE: + colorMode = DISPLAY_CONTROL_RGB32; + bytesPerPixel = 4; + break; + case B_RGB16_LITTLE: + colorMode = DISPLAY_CONTROL_RGB16; + bytesPerPixel = 2; + break; + case B_RGB15_LITTLE: + colorMode = DISPLAY_CONTROL_RGB15; + bytesPerPixel = 2; + break; + case B_CMAP8: + default: + colorMode = DISPLAY_CONTROL_CMAP8; + bytesPerPixel = 1; + break; + } + + bytesPerRow = mode.virtual_width * bytesPerPixel; +} + + +// #pragma mark - + + +uint32 +intel_accelerant_mode_count(void) +{ + TRACE(("intel_accelerant_mode_count()\n")); + return gInfo->shared_info->mode_count; +} + + +status_t +intel_get_mode_list(display_mode *modeList) +{ + TRACE(("intel_get_mode_info()\n")); + memcpy(modeList, gInfo->mode_list, gInfo->shared_info->mode_count * sizeof(display_mode)); + return B_OK; +} + + +status_t +intel_propose_display_mode(display_mode *target, const display_mode *low, + const display_mode *high) +{ + TRACE(("intel_propose_display_mode()\n")); + + // just search for the specified mode in the list + + for (uint32 i = 0; i < gInfo->shared_info->mode_count; i++) { + display_mode *current = &gInfo->mode_list[i]; + + // TODO: improve this, ie. adapt pixel clock to allowed values!!! + + if (target->virtual_width != current->virtual_width + || target->virtual_height != current->virtual_height + || target->space != current->space) + continue; + + *target = *current; + return B_OK; + } + return B_BAD_VALUE; +} + + +status_t +intel_set_display_mode(display_mode *mode) +{ + if (mode == NULL) + return B_BAD_VALUE; + + display_mode current = *mode; + + set_display_power_mode(B_DPMS_OFF); + + uint32 colorMode, bytesPerRow; + get_color_space_format(current, colorMode, bytesPerRow); + + // update timing parameters + + write32(INTEL_DISPLAY_HTOTAL, ((uint32)(current.timing.h_total - 1) << 16) + | ((uint32)current.timing.h_display - 1)); + write32(INTEL_DISPLAY_HBLANK, ((uint32)(current.timing.h_total - 1) << 16) + | ((uint32)current.timing.h_display - 1)); + write32(INTEL_DISPLAY_HSYNC, ((uint32)(current.timing.h_sync_end - 1) << 16) + | ((uint32)current.timing.h_sync_start - 1)); + + write32(INTEL_DISPLAY_VTOTAL, ((uint32)(current.timing.v_total - 1) << 16) + | ((uint32)current.timing.v_display - 1)); + write32(INTEL_DISPLAY_VBLANK, ((uint32)(current.timing.v_total - 1) << 16) + | ((uint32)current.timing.v_display - 1)); + write32(INTEL_DISPLAY_VSYNC, ((uint32)(current.timing.v_sync_end - 1) << 16) + | ((uint32)current.timing.v_sync_start - 1)); + + write32(INTEL_DISPLAY_IMAGE_SIZE, ((uint32)(current.timing.h_display - 1) << 16) + | ((uint32)current.timing.v_display - 1)); + + write32(INTEL_DISPLAY_ANALOG_PORT, (read32(INTEL_DISPLAY_ANALOG_PORT) + & ~(DISPLAY_MONITOR_POLARITY_MASK | DISPLAY_MONITOR_VGA_POLARITY)) + | ((current.timing.flags & B_POSITIVE_HSYNC) != 0 ? DISPLAY_MONITOR_POSITIVE_HSYNC : 0) + | ((current.timing.flags & B_POSITIVE_VSYNC) != 0 ? DISPLAY_MONITOR_POSITIVE_VSYNC : 0)); + + uint32 postDivisor, nDivisor, m1Divisor, m2Divisor; + compute_pll_divisors(current, postDivisor, nDivisor, m1Divisor, m2Divisor); + + // switch divisor register with every mode change (not required) + uint32 divisorRegister; + if (gInfo->shared_info->pll_info.divisor_register == INTEL_DISPLAY_PLL_DIVISOR_0) + divisorRegister = INTEL_DISPLAY_PLL_DIVISOR_1; + else + divisorRegister = INTEL_DISPLAY_PLL_DIVISOR_0; + + write32(divisorRegister, + (((nDivisor - 2) << DISPLAY_PLL_N_DIVISOR_SHIFT) & DISPLAY_PLL_N_DIVISOR_MASK) + | (((m1Divisor - 2) << DISPLAY_PLL_M1_DIVISOR_SHIFT) & DISPLAY_PLL_M1_DIVISOR_MASK) + | (((m2Divisor - 2) << DISPLAY_PLL_M2_DIVISOR_SHIFT) & DISPLAY_PLL_M2_DIVISOR_MASK)); + write32(INTEL_DISPLAY_PLL, DISPLAY_PLL_ENABLED | DISPLAY_PLL_2X_CLOCK + | DISPLAY_PLL_NO_VGA_CONTROL | DISPLAY_PLL_DIVIDE_4X + | (((postDivisor - 2) << DISPLAY_PLL_POST_DIVISOR_SHIFT) & DISPLAY_PLL_POST_DIVISOR_MASK) + | (divisorRegister == INTEL_DISPLAY_PLL_DIVISOR_1 ? DISPLAY_PLL_DIVISOR_1 : 0)); + +TRACE(("pll regs: %08lx, 0: %08lx, 1: %08lx\n", read32(INTEL_DISPLAY_PLL), + read32(INTEL_DISPLAY_PLL_DIVISOR_0), read32(INTEL_DISPLAY_PLL_DIVISOR_1))); +uint32 divisor = read32(divisorRegister); +TRACE((" POST %ld\n", + (read32(INTEL_DISPLAY_PLL) & DISPLAY_PLL_POST_DIVISOR_MASK) >> DISPLAY_PLL_POST_DIVISOR_SHIFT)); +TRACE((" 0: N %ld, M1 %ld, M2 %ld\n", + (divisor & DISPLAY_PLL_N_DIVISOR_MASK) >> DISPLAY_PLL_N_DIVISOR_SHIFT, + (divisor & DISPLAY_PLL_M1_DIVISOR_MASK) >> DISPLAY_PLL_M1_DIVISOR_SHIFT, + (divisor & DISPLAY_PLL_M2_DIVISOR_MASK) >> DISPLAY_PLL_M2_DIVISOR_SHIFT)); +divisor = read32(INTEL_DISPLAY_PLL_DIVISOR_1); +TRACE((" 1: N %ld, M1 %ld, M2 %ld\n", + (divisor & DISPLAY_PLL_N_DIVISOR_MASK) >> DISPLAY_PLL_N_DIVISOR_SHIFT, + (divisor & DISPLAY_PLL_M1_DIVISOR_MASK) >> DISPLAY_PLL_M1_DIVISOR_SHIFT, + (divisor & DISPLAY_PLL_M2_DIVISOR_MASK) >> DISPLAY_PLL_M2_DIVISOR_SHIFT)); + +uint32 n = ((divisor & DISPLAY_PLL_N_DIVISOR_MASK) >> DISPLAY_PLL_N_DIVISOR_SHIFT) + 2; +uint32 m1 = ((divisor & DISPLAY_PLL_M1_DIVISOR_MASK) >> DISPLAY_PLL_M1_DIVISOR_SHIFT) + 2; +uint32 m2 = ((divisor & DISPLAY_PLL_M2_DIVISOR_MASK) >> DISPLAY_PLL_M2_DIVISOR_SHIFT) + 2; +uint32 p = ((read32(INTEL_DISPLAY_PLL) & DISPLAY_PLL_POST_DIVISOR_MASK) >> DISPLAY_PLL_POST_DIVISOR_SHIFT) + 2; +//uint32 p2 = (read32(INTEL_DISPLAY_PLL) & DISPLAY_PLL_DIVIDE_4X) ? 2 : 1; +float clock = ((gInfo->shared_info->pll_info.reference_frequency / 1000.0f * (5*m1 + m2)) / n) / (p * 4); +TRACE((" n = %lu, m1 = %lu, m2 = %lu, p = %lu\n", n, m1, m2, p)); +TRACE((" Clock frequency: %g MHz\n", clock)); +TRACE((" h_total %ld, v_total %ld, refresh: %g\n", current.timing.h_total, current.timing.v_total, + clock * 1000000.0f / (current.timing.h_total * current.timing.v_total))); + + write32(INTEL_DISPLAY_CONTROL, (read32(INTEL_DISPLAY_CONTROL) + & ~DISPLAY_CONTROL_COLOR_MASK) | colorMode); + + set_display_power_mode(gInfo->shared_info->dpms_mode); + + // changing bytes per row seems to be ignored if the plane/pipe is turned off + write32(INTEL_DISPLAY_BYTES_PER_ROW, bytesPerRow); + write32(INTEL_DISPLAY_BASE, 0); + // triggers writing back double-buffered registers + + // update shared info + gInfo->shared_info->bytes_per_row = bytesPerRow; + gInfo->shared_info->current_mode = current; + + return B_OK; +} + + +status_t +intel_get_display_mode(display_mode *_currentMode) +{ + TRACE(("intel_get_display_mode()\n")); + *_currentMode = gInfo->shared_info->current_mode; + return B_OK; +} + + +status_t +intel_get_frame_buffer_config(frame_buffer_config *config) +{ + TRACE(("intel_get_frame_buffer_config()\n")); + + config->frame_buffer = gInfo->shared_info->frame_buffer; + config->frame_buffer_dma = gInfo->shared_info->physical_frame_buffer; + config->bytes_per_row = gInfo->shared_info->bytes_per_row; + + return B_OK; +} + + +status_t +intel_get_pixel_clock_limits(display_mode *mode, uint32 *_low, uint32 *_high) +{ + TRACE(("intel_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.max_frequency) + low = gInfo->shared_info->pll_info.max_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; + + return B_OK; +} + + +status_t +intel_move_display(uint16 horizontalStart, uint16 verticalStart) +{ + return B_ERROR; +} + + +status_t +intel_get_timing_constraints(display_timing_constraints *constraints) +{ + return B_ERROR; +} + + +void +intel_set_indexed_colors(uint count, uint8 first, uint8 *colorData, uint32 flags) +{ +} + diff --git a/src/add-ons/kernel/drivers/graphics/Jamfile b/src/add-ons/kernel/drivers/graphics/Jamfile index ce54ef93e5..0810dd48d0 100644 --- a/src/add-ons/kernel/drivers/graphics/Jamfile +++ b/src/add-ons/kernel/drivers/graphics/Jamfile @@ -2,6 +2,7 @@ SubDir HAIKU_TOP src add-ons kernel drivers graphics ; SubInclude HAIKU_TOP src add-ons kernel drivers graphics common ; SubInclude HAIKU_TOP src add-ons kernel drivers graphics et6x00 ; +SubInclude HAIKU_TOP src add-ons kernel drivers graphics intel_extreme ; SubInclude HAIKU_TOP src add-ons kernel drivers graphics matrox ; SubInclude HAIKU_TOP src add-ons kernel drivers graphics neomagic ; SubInclude HAIKU_TOP src add-ons kernel drivers graphics nvidia ; diff --git a/src/add-ons/kernel/drivers/graphics/intel_extreme/Jamfile b/src/add-ons/kernel/drivers/graphics/intel_extreme/Jamfile new file mode 100644 index 0000000000..1e59e38319 --- /dev/null +++ b/src/add-ons/kernel/drivers/graphics/intel_extreme/Jamfile @@ -0,0 +1,19 @@ +SubDir HAIKU_TOP src add-ons kernel drivers graphics intel_extreme ; + +SetSubDirSupportedPlatformsBeOSCompatible ; + +UsePrivateHeaders [ FDirName graphics intel_extreme ] ; +UsePrivateHeaders [ FDirName graphics common ] ; +UsePrivateHeaders graphics kernel ; + +KernelAddon intel_extreme : kernel drivers bin : + driver.cpp + device.cpp + intel_extreme.cpp + + kernel_cpp.cpp +; + +SEARCH on [ FGristFiles + kernel_cpp.cpp + ] = [ FDirName $(HAIKU_TOP) src system kernel util ] ; diff --git a/src/add-ons/kernel/drivers/graphics/intel_extreme/device.cpp b/src/add-ons/kernel/drivers/graphics/intel_extreme/device.cpp new file mode 100644 index 0000000000..d947d730a5 --- /dev/null +++ b/src/add-ons/kernel/drivers/graphics/intel_extreme/device.cpp @@ -0,0 +1,237 @@ +/* + * Copyright 2006, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Axel Dörfler, axeld@pinc-software.de + */ + + +#include "driver.h" +#include "device.h" +#include "intel_extreme.h" +#include "utility.h" + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + + +#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 +}; + + +static status_t +checkDeviceInfo(struct intel_info *info) +{ + if (!info || info->cookie_magic != INTEL_COOKIE_MAGIC) + return B_BAD_VALUE; + + return B_OK; +} + + +// #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; + } + intel_info *info = gDeviceInfo[id]; + *_cookie = info; + + acquire_lock(&gLock); + + status_t status = B_OK; + + if (info->open_count++ == 0) { + // this device has been opened for the first time, so + // we allocate needed resources and initialize the structure + + info->cookie_magic = INTEL_COOKIE_MAGIC; + info->id = id; + info->pci = gPCIInfo[id]; + info->registers = (uint8 *)gPCIInfo[id]->u.h0.base_registers[0]; + + status = intel_extreme_init(*info); + } + + release_lock(&gLock); + + return status; +} + + +static status_t +device_close(void *data) +{ + TRACE((DEVICE_NAME ": close\n")); + struct intel_info *info; + + if (checkDeviceInfo(info = (intel_info *)data) != B_OK) + return B_BAD_VALUE; + + info->cookie_magic = INTEL_FREE_COOKIE_MAGIC; + + return B_OK; +} + + +static status_t +device_free(void *data) +{ + struct intel_info *info = (intel_info *)data; + status_t retval = B_NO_ERROR; + + if (info == NULL || info->cookie_magic != INTEL_FREE_COOKIE_MAGIC) + retval = B_BAD_VALUE; + + acquire_lock(&gLock); + + if (info->open_count-- == 1) { + // release info structure + info->cookie_magic = 0; + intel_extreme_uninit(*info); + } + + release_lock(&gLock); + + return retval; +} + + +static status_t +device_ioctl(void *data, uint32 op, void *buffer, size_t bufferLength) +{ + struct intel_info *info; + + if (checkDeviceInfo(info = (intel_info *)data) != B_OK) + return B_BAD_VALUE; + + switch (op) { + case B_GET_ACCELERANT_SIGNATURE: + strcpy((char *)buffer, INTEL_ACCELERANT_NAME); + TRACE((DEVICE_NAME ": accelerant: %s\n", INTEL_ACCELERANT_NAME)); + return B_OK; + + // needed to share data between kernel and accelerant + case INTEL_GET_PRIVATE_DATA: + { + intel_get_private_data *data = (intel_get_private_data *)buffer; + + if (data->magic == INTEL_PRIVATE_DATA_MAGIC) { + data->shared_info_area = info->shared_area; + return B_OK; + } + break; + } + + // needed for cloning + case INTEL_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 INTEL_ALLOC_LOCAL_MEMORY: + { + intel_alloc_local_mem *allocMemory = (intel_alloc_local_mem *)buffer; + + if (allocMemory->magic == INTEL_PRIVATE_DATA_MAGIC) { + return mem_alloc(di->local_memmgr, allocMemory->size, dev, + &allocMemory->handle, &am->fb_offset); + } + break; + } + + case INTEL_FREE_LOCAL_MEMORY: + { + intel_free_local_mem *freeMemory = (intel_free_local_mem *)buffer; + + if (freeMemory->magic == INTEL_PRIVATE_DATA_MAGIC) + return mem_free(di->local_memmgr, freeMemory->handle, dev); + 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; +} + diff --git a/src/add-ons/kernel/drivers/graphics/intel_extreme/device.h b/src/add-ons/kernel/drivers/graphics/intel_extreme/device.h new file mode 100644 index 0000000000..5b0fe46e4e --- /dev/null +++ b/src/add-ons/kernel/drivers/graphics/intel_extreme/device.h @@ -0,0 +1,18 @@ +/* + * Copyright 2006, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Axel Dörfler, axeld@pinc-software.de + */ +#ifndef DEVICE_H +#define DEVICE_H + + +#include + + +/* The published PCI bus interface device hooks */ +extern device_hooks gDeviceHooks; + +#endif /* DEVICE_H */ diff --git a/src/add-ons/kernel/drivers/graphics/intel_extreme/driver.cpp b/src/add-ons/kernel/drivers/graphics/intel_extreme/driver.cpp new file mode 100644 index 0000000000..602c523345 --- /dev/null +++ b/src/add-ons/kernel/drivers/graphics/intel_extreme/driver.cpp @@ -0,0 +1,209 @@ +/* + * Copyright 2006, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Axel Dörfler, axeld@pinc-software.de + */ + + +#include "driver.h" +#include "device.h" +#include "lock.h" + +#include +#include +#include +#include + +#include +#include +#include +#include + +#define TRACE_DRIVER +#ifdef TRACE_DRIVER +# define TRACE(x) dprintf x +#else +# define TRACE(x) ; +#endif + +#define MAX_CARDS 4 + +int32 api_version = B_CUR_DRIVER_API_VERSION; + +char *gDeviceNames[MAX_CARDS + 1]; +intel_info *gDeviceInfo[MAX_CARDS]; +pci_info *gPCIInfo[MAX_CARDS]; +pci_module_info *gPCI; +lock gLock; + + +extern "C" { + status_t init_hardware(void); + status_t init_driver(void); + void uninit_driver(void); + const char **publish_devices(void); + device_hooks *find_device(const char *name); +} + + +static status_t +get_next_intel_extreme(int32 *_cookie, pci_info &info) +{ + int32 index = *_cookie; + + // find devices + for (; gPCI->get_nth_pci_info(index, &info) == B_OK; index++) { + if (info.vendor_id == VENDOR_ID_INTEL + && info.device_id == DEVICE_ID_i865) { + *_cookie = index + 1; + return B_OK; + } + } + + return B_ENTRY_NOT_FOUND; +} + + +const char ** +publish_devices(void) +{ + TRACE((DEVICE_NAME ": publish_devices()\n")); + return (const char **)gDeviceNames; +} + + +status_t +init_hardware(void) +{ + status_t status; + + TRACE((DEVICE_NAME ": init_hardware()\n")); + + if ((status = get_module(B_PCI_MODULE_NAME,(module_info **)&gPCI)) != B_OK) { + TRACE((DEVICE_NAME ": pci module unavailable\n")); + return status; + } + + int32 cookie = 0; + pci_info info; + status = get_next_intel_extreme(&cookie, info); +dprintf("found: %s\n", strerror(status)); + + put_module(B_PCI_MODULE_NAME); + return status; +} + + +status_t +init_driver(void) +{ + status_t status; + TRACE((DEVICE_NAME ": init_driver()\n")); + + if ((status = get_module(B_PCI_MODULE_NAME,(module_info **)&gPCI)) != B_OK) { + TRACE((DEVICE_NAME ": pci module unavailable\n")); + return status; + } + + // find devices + + int32 found = 0; + + for (int32 cookie = 0; found < MAX_CARDS;) { + pci_info *info = (pci_info *)malloc(sizeof(pci_info)); + status = get_next_intel_extreme(&cookie, *info); + if (status < B_OK) { + free(info); + break; + } + + // enable bus mastering for device +// pci->write_pci_config(info->bus, info->device, info->function, +// PCI_command, 2, +// PCI_command_master | pci->read_pci_config( +// info->bus, info->device, info->function, +// PCI_command, 2)); + + gPCIInfo[found++] = info; + dprintf(DEVICE_NAME ": (%ld) revision = 0x%x\n", found, info->revision); + } + + if (found == 0) { + put_module(B_PCI_MODULE_NAME); + return ENODEV; + } + + // create device name list & allocate device info structure + { + int32 index = 0; + char name[64]; + + for (; index < found; index++) { + pci_info *info = gPCIInfo[index]; + sprintf(name, "graphics/%04X_%04X_%02X%02X%02X", + info->vendor_id, info->device_id, + info->bus, info->device, + info->function); + gDeviceNames[index] = strdup(name); + + if ((gDeviceInfo[index] = (intel_info *)malloc(sizeof(intel_info))) != NULL) + memset(gDeviceInfo[index], 0, sizeof(intel_info)); + else + free(gDeviceNames[index]); + } + gDeviceNames[index] = NULL; + } + + return init_lock(&gLock, "intel extreme ksync"); +} + + +void +uninit_driver(void) +{ + TRACE((DEVICE_NAME ": uninit_driver()\n")); + + uninit_lock(&gLock); + + // free device related structures + char *name; + for (int32 index = 0; (name = gDeviceNames[index]) != NULL; index++) { + free(gDeviceInfo[index]); + free(gPCIInfo[index]); + free(name); + } + + put_module(B_PCI_MODULE_NAME); +} + + +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; +} + +/* +void +wake_driver(void) +{ + // for compatibility with Dano, only +} + + +void +suspend_driver(void) +{ + // for compatibility with Dano, only +} +*/ diff --git a/src/add-ons/kernel/drivers/graphics/intel_extreme/driver.h b/src/add-ons/kernel/drivers/graphics/intel_extreme/driver.h new file mode 100644 index 0000000000..dc7ae5b8a3 --- /dev/null +++ b/src/add-ons/kernel/drivers/graphics/intel_extreme/driver.h @@ -0,0 +1,60 @@ +/* + * Copyright 2006, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Axel Dörfler, axeld@pinc-software.de + */ +#ifndef DRIVER_H +#define DRIVER_H + + +#include +#include + +#include "intel_extreme.h" +#include "lock.h" + +// PCI Communications + +#define IO_PORT_PCI_ACCESS true +//#define MEMORY_MAPPED_PCI_ACCESS true + +#if IO_PORT_PCI_ACCESS +# define write8(address,value) (*pci->write_io_8)((address),(value)) +# define write16(address,value) (*pci->write_io_16)((address),(value)) +# define write32(address,value) (*pci->write_io_32)((address),(value)) +# define read8(address) ((*pci->read_io_8)(address)) +# define read16(address) ((*pci->read_io_16)(address)) +# define read32(address) ((*pci->read_io_32)(address)) +#else /* MEMORY_MAPPED_PCI_ACCESS */ +# 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)) +#endif + + +extern char *gDeviceNames[]; +extern intel_info *gDeviceInfo[]; +extern pci_info *gPCIInfo[]; +extern pci_module_info *gPCI; +extern struct lock 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 */ diff --git a/src/add-ons/kernel/drivers/graphics/intel_extreme/intel_extreme.cpp b/src/add-ons/kernel/drivers/graphics/intel_extreme/intel_extreme.cpp new file mode 100644 index 0000000000..44edcb7c6e --- /dev/null +++ b/src/add-ons/kernel/drivers/graphics/intel_extreme/intel_extreme.cpp @@ -0,0 +1,197 @@ +/* + * Copyright 2006, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Axel Dörfler, axeld@pinc-software.de + */ + + +#include "intel_extreme.h" +#include "driver.h" +#include "utility.h" + +#include + +#include +#include +#include +#include + +// ToDo: do this correctly +extern "C" void write_isa_io(uchar bus, uchar port, uchar offset); +extern "C" uchar read_isa_io(uchar bus, uchar port, uchar offset); + + +class PhysicalMemoryMapper { + public: + PhysicalMemoryMapper(); + ~PhysicalMemoryMapper(); + + 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 Keep(); + + private: + area_id fArea; +}; + + +PhysicalMemoryMapper::PhysicalMemoryMapper() + : + fArea(-1) +{ +} + + +PhysicalMemoryMapper::~PhysicalMemoryMapper() +{ + if (fArea >= B_OK) + delete_area(fArea); +} + + +area_id +PhysicalMemoryMapper::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 +PhysicalMemoryMapper::Keep() +{ + fArea = -1; +} + + +// #pragma mark - + + +#define DUMPED_BLOCK_SIZE 16 + +void +dumpBlock(int file, const uint8 *buffer, int size) +{ + int i; + + for (i = 0; i < size;) { + int start = i; + char line[512]; + + int pos = sprintf(line, "%06x: ", start); + + for (; i < start+DUMPED_BLOCK_SIZE; i++) { + if (!(i % 4)) + pos += snprintf(line + pos, sizeof(line) - pos, " "); + + if (i >= size) + break; + + pos += snprintf(line + pos, sizeof(line) - pos, "%02x", + *(buffer + i)); + } + pos += snprintf(line + pos, sizeof(line) - pos, "\n"); + write(file, line, pos); + } +} + + +status_t +intel_extreme_init(intel_info &info) +{ + info.shared_area = create_area("intel extreme shared info", + (void **)&info.shared_info, B_ANY_KERNEL_ADDRESS, + ROUND_TO_PAGE_SIZE(sizeof(intel_shared_info)), + B_FULL_LOCK, 0); + if (info.shared_area < B_OK) + return info.shared_area; + + memset((void *)info.shared_info, 0, sizeof(intel_shared_info)); + + // get chipset info + + // TODO: read this out of the PCI configuration of the PCI bridge + size_t memorySize = 8 * 1024 * 1024; + + // map frame buffer, try to map it write combined + + PhysicalMemoryMapper fbMapper; + info.frame_buffer_area = fbMapper.Map("intel extreme frame buffer", + (void *)info.pci->u.h0.base_registers[0], + memorySize, B_ANY_KERNEL_BLOCK_ADDRESS | B_MTR_WC, + B_READ_AREA | B_WRITE_AREA, (void **)&info.frame_buffer); + if (fbMapper.InitCheck() < B_OK) { + // try again without write combining + dprintf(DEVICE_NAME ": enabling write combined mode failed.\n"); + + info.frame_buffer_area = fbMapper.Map("intel extreme frame buffer", + (void *)info.pci->u.h0.base_registers[0], + memorySize/*info.pci->u.h0.base_register_sizes[0]*/, B_ANY_KERNEL_BLOCK_ADDRESS, + B_READ_AREA | B_WRITE_AREA, (void **)&info.frame_buffer); + } + if (fbMapper.InitCheck() < B_OK) { + dprintf(DEVICE_NAME ": could not map frame buffer!\n"); + return info.frame_buffer_area; + } + + // memory mapped I/O + + PhysicalMemoryMapper mmioMapper; + info.registers_area = mmioMapper.Map("intel extreme mmio", + (void *)info.pci->u.h0.base_registers[1], + info.pci->u.h0.base_register_sizes[1], + B_ANY_KERNEL_BLOCK_ADDRESS, + B_READ_AREA | B_WRITE_AREA, + (void **)&info.registers); + if (mmioMapper.InitCheck() < B_OK) { + dprintf(DEVICE_NAME ": could not map memory I/O!\n"); + return info.registers_area; + } + +#if 0 +// dump registers to a file +int file = open("/boot/home/intel_extreme_registers", O_CREAT | O_TRUNC | O_WRONLY, 0666); +if (file >= 0) { + dumpBlock(file, info.registers, info.pci->u.h0.base_register_sizes[1]); + close(file); + sync(); +} else + dprintf("intel_extreme: could not log (%s)!!\n", strerror(errno)); +#endif + + // no errors, so keep mappings + fbMapper.Keep(); + mmioMapper.Keep(); + + info.shared_info->frame_buffer_area = info.frame_buffer_area; + info.shared_info->registers_area = info.registers_area; + info.shared_info->frame_buffer = info.frame_buffer; + info.shared_info->physical_frame_buffer = (uint8 *)info.pci->u.h0.base_registers[0]; + + info.shared_info->graphics_memory_size = memorySize; + info.shared_info->dpms_mode = B_DPMS_ON; + info.shared_info->pll_info.reference_frequency = 48000; // 48 kHz + info.shared_info->pll_info.min_frequency = 100000; // 100 MHz (not tested) + info.shared_info->pll_info.max_frequency = 350000; // 350 MHz RAM DAC speed + info.shared_info->pll_info.divisor_register = INTEL_DISPLAY_PLL_DIVISOR_0; + + dprintf(DEVICE_NAME "intel_extreme_init() completed successfully!\n"); + + return B_OK; +} + + +void +intel_extreme_uninit(intel_info &info) +{ + dprintf(DEVICE_NAME": intel_extreme_uninit()\n"); + + delete_area(info.frame_buffer_area); + delete_area(info.registers_area); + delete_area(info.shared_area); +} +