2 * Copyright 2006-2010, Haiku, Inc. All Rights Reserved.
3 * Distributed under the terms of the MIT License.
6 * Axel Dörfler, axeld@pinc-software.de
10 #include "accelerant_protos.h"
11 #include "accelerant.h"
26 #define TRACE_ACCELERANT
27 #ifdef TRACE_ACCELERANT
28 # define TRACE(x...) _sPrintf("intel_extreme accelerant:" x)
33 #define ERROR(x...) _sPrintf("intel_extreme accelerant: " x)
34 #define CALLED(x...) TRACE("CALLED %s\n", __PRETTY_FUNCTION__)
37 struct accelerant_info
* gInfo
;
45 area_id
Clone(const char* name
, void** _address
,
46 uint32 spec
, uint32 protection
,
49 { return fArea
< 0 ? (status_t
)fArea
: B_OK
; }
57 AreaCloner::AreaCloner()
64 AreaCloner::~AreaCloner()
72 AreaCloner::Clone(const char* name
, void** _address
, uint32 spec
,
73 uint32 protection
, area_id sourceArea
)
75 fArea
= clone_area(name
, _address
, spec
, protection
, sourceArea
);
90 /*! This is the common accelerant_info initializer. It is called by
91 both, the first accelerant and all clones.
94 init_common(int device
, bool isClone
)
96 // initialize global accelerant info structure
98 gInfo
= (accelerant_info
*)malloc(sizeof(accelerant_info
));
102 memset(gInfo
, 0, sizeof(accelerant_info
));
104 gInfo
->is_clone
= isClone
;
105 gInfo
->device
= device
;
107 // get basic info from driver
109 intel_get_private_data data
;
110 data
.magic
= INTEL_PRIVATE_DATA_MAGIC
;
112 if (ioctl(device
, INTEL_GET_PRIVATE_DATA
, &data
,
113 sizeof(intel_get_private_data
)) != 0) {
118 AreaCloner sharedCloner
;
119 gInfo
->shared_info_area
= sharedCloner
.Clone("intel extreme shared info",
120 (void**)&gInfo
->shared_info
, B_ANY_ADDRESS
, B_READ_AREA
| B_WRITE_AREA
,
121 data
.shared_info_area
);
122 status_t status
= sharedCloner
.InitCheck();
128 AreaCloner regsCloner
;
129 gInfo
->regs_area
= regsCloner
.Clone("intel extreme regs",
130 (void**)&gInfo
->registers
, B_ANY_ADDRESS
, B_READ_AREA
| B_WRITE_AREA
,
131 gInfo
->shared_info
->registers_area
);
132 status
= regsCloner
.InitCheck();
141 // The overlay registers, hardware status, and cursor memory share
142 // a single area with the shared_info
144 if (gInfo
->shared_info
->overlay_offset
!= 0) {
145 gInfo
->overlay_registers
= (struct overlay_registers
*)
146 (gInfo
->shared_info
->graphics_memory
147 + gInfo
->shared_info
->overlay_offset
);
150 if (gInfo
->shared_info
->device_type
.InGroup(INTEL_TYPE_96x
)) {
151 // allocate some extra memory for the 3D context
152 if (intel_allocate_memory(INTEL_i965_3D_CONTEXT_SIZE
,
153 B_APERTURE_NON_RESERVED
, gInfo
->context_base
) == B_OK
) {
154 gInfo
->context_offset
= gInfo
->context_base
155 - (addr_t
)gInfo
->shared_info
->graphics_memory
;
163 /*! Clean up data common to both primary and cloned accelerant */
167 intel_free_memory(gInfo
->context_base
);
169 delete_area(gInfo
->regs_area
);
170 delete_area(gInfo
->shared_info_area
);
172 gInfo
->regs_area
= gInfo
->shared_info_area
= -1;
174 // close the file handle ONLY if we're the clone
176 close(gInfo
->device
);
182 // #pragma mark - public accelerant functions
185 /*! Init primary accelerant */
187 intel_init_accelerant(int device
)
191 status_t status
= init_common(device
, false);
195 intel_shared_info
&info
= *gInfo
->shared_info
;
197 init_lock(&info
.accelerant_lock
, "intel extreme accelerant");
198 init_lock(&info
.engine_lock
, "intel extreme engine");
200 setup_ring_buffer(info
.primary_ring_buffer
, "intel primary ring buffer");
202 // determine head depending on what's already enabled from the BIOS
203 // TODO: it would be nicer to retrieve this data via DDC - else the
204 // display is gone for good if the BIOS decides to only show the
205 // picture on the connected analog monitor!
206 gInfo
->head_mode
= 0;
207 if (read32(INTEL_DISPLAY_B_PIPE_CONTROL
) & DISPLAY_PIPE_ENABLED
)
208 gInfo
->head_mode
|= HEAD_MODE_B_DIGITAL
;
209 if (read32(INTEL_DISPLAY_A_PIPE_CONTROL
) & DISPLAY_PIPE_ENABLED
)
210 gInfo
->head_mode
|= HEAD_MODE_A_ANALOG
;
212 uint32 lvds
= read32(INTEL_DISPLAY_LVDS_PORT
);
214 // If we have an enabled display pipe we save the passed information and
215 // assume it is the valid panel size..
216 // Later we query for proper EDID info if it exists, or figure something
217 // else out. (Default modes, etc.)
218 bool hasPCH
= gInfo
->shared_info
->device_type
.HasPlatformControlHub();
219 if ((hasPCH
&& (lvds
& PCH_LVDS_DETECTED
) != 0)
220 || (!hasPCH
&& (lvds
& DISPLAY_PIPE_ENABLED
) != 0)) {
222 gInfo
->head_mode
|= HEAD_MODE_LVDS_PANEL
;
225 TRACE("head detected: %#x\n", gInfo
->head_mode
);
226 TRACE("adpa: %08" B_PRIx32
", dova: %08" B_PRIx32
", dovb: %08" B_PRIx32
227 ", lvds: %08" B_PRIx32
"\n",
228 read32(INTEL_DISPLAY_A_ANALOG_PORT
),
229 read32(INTEL_DISPLAY_A_DIGITAL_PORT
),
230 read32(INTEL_DISPLAY_B_DIGITAL_PORT
),
231 read32(INTEL_DISPLAY_LVDS_PORT
));
233 status
= create_mode_list();
234 if (status
!= B_OK
) {
244 intel_accelerant_clone_info_size(void)
247 // clone info is device name, so return its maximum size
248 return B_PATH_NAME_LENGTH
;
253 intel_get_accelerant_clone_info(void* info
)
256 ioctl(gInfo
->device
, INTEL_GET_DEVICE_NAME
, info
, B_PATH_NAME_LENGTH
);
261 intel_clone_accelerant(void* info
)
265 // create full device name
266 char path
[B_PATH_NAME_LENGTH
];
267 strcpy(path
, "/dev/");
269 strlcat(path
, (const char*)info
, sizeof(path
));
271 strcat(path
, (const char*)info
);
274 int fd
= open(path
, B_READ_WRITE
);
278 status_t status
= init_common(fd
, true);
282 // get read-only clone of supported display modes
283 status
= gInfo
->mode_list_area
= clone_area(
284 "intel extreme cloned modes", (void**)&gInfo
->mode_list
,
285 B_ANY_ADDRESS
, B_READ_AREA
, gInfo
->shared_info
->mode_list_area
);
299 /*! This function is called for both, the primary accelerant and all of
303 intel_uninit_accelerant(void)
307 // delete accelerant instance data
308 delete_area(gInfo
->mode_list_area
);
309 gInfo
->mode_list
= NULL
;
311 intel_shared_info
&info
= *gInfo
->shared_info
;
313 uninit_lock(&info
.accelerant_lock
);
314 uninit_lock(&info
.engine_lock
);
316 uninit_ring_buffer(info
.primary_ring_buffer
);
323 intel_get_accelerant_device_info(accelerant_device_info
* info
)
327 info
->version
= B_ACCELERANT_VERSION
;
328 strcpy(info
->name
, gInfo
->shared_info
->device_type
.InFamily(INTEL_TYPE_7xx
)
329 ? "Intel Extreme Graphics 1" : "Intel Extreme Graphics 2");
330 strcpy(info
->chipset
, gInfo
->shared_info
->device_identifier
);
331 strcpy(info
->serial_no
, "None");
333 info
->memory
= gInfo
->shared_info
->graphics_memory_size
;
334 info
->dac_speed
= gInfo
->shared_info
->pll_info
.max_frequency
;
341 intel_accelerant_retrace_semaphore()
344 return gInfo
->shared_info
->vblank_sem
;