2 Copyright © 2010-2015, The AROS Development Team. All rights reserved.
6 #include <aros/debug.h>
7 #include <aros/symbolsets.h>
9 #include <graphics/driver.h>
10 #include <proto/exec.h>
11 #include <proto/graphics.h>
12 #include <proto/oop.h>
13 #include <hidd/graphics.h>
20 #include "intelG45_intern.h"
21 #include "intelG45_regs.h"
22 #include "compositing.h"
24 static uint32_t min(uint32_t a
, uint32_t b
)
32 static BOOL
IsCompatible(UWORD product_id
)
35 // || product_id == 0x0042
36 // || product_id == 0x0046
37 // || product_id == 0x0102
38 // || product_id == 0x0106
39 // || product_id == 0x010a
40 // || product_id == 0x0112
41 // || product_id == 0x0116
42 // || product_id == 0x0122
43 // || product_id == 0x0126
44 // || product_id == 0x2562
45 // || product_id == 0x2572
47 || product_id
== 0x258a
48 || product_id
== 0x2592
49 || product_id
== 0x2772
50 || product_id
== 0x27a2
51 || product_id
== 0x27ae
52 // || product_id == 0x2972
53 // || product_id == 0x2982
54 // || product_id == 0x2992
55 // || product_id == 0x29a2
56 // || product_id == 0x29b2
57 // || product_id == 0x29c2
58 // || product_id == 0x29d2
59 || product_id
== 0x2a02
60 || product_id
== 0x2a12
61 || product_id
== 0x2a42
62 || product_id
== 0x2e02
63 || product_id
== 0x2e12
64 || product_id
== 0x2e22
65 || product_id
== 0x2e32
66 || product_id
== 0x2e42
67 || product_id
== 0x2e92
68 // || product_id == 0x3577
69 // || product_id == 0x3582
70 // || product_id == 0x358e
71 // || product_id == 0xa001
72 || product_id
== 0xa011
76 static BOOL
NeedsPhysicalCursor(UWORD product_id
)
78 /* TRUE if one of i830, i85x, i915G(M), i945G(M) */
79 return product_id
== 0x2582
80 || product_id
== 0x258a
81 || product_id
== 0x2592
82 || product_id
== 0x2772
83 || product_id
== 0x27a2
84 || product_id
== 0x27ae
85 || product_id
== 0x3577
86 || product_id
== 0x3582
87 || product_id
== 0x358e;
90 static BOOL
HasQuadBARs(UWORD product_id
)
92 return product_id
> 0x2800
93 && product_id
< 0xa000;
96 static ULONG
GetGATTSize(struct g45staticdata
*sd
)
100 switch (readl(sd
->Card
.MMIO
+ G45_GATT_CONTROL
) >> 1 & 0x7)
118 size
= 1 * MBYTES
+ 512 * KBYTES
;
125 static BOOL
probe_monitor(struct g45staticdata
*sd
, uint32_t port
)
129 bug("[GMA] Attempting to detect connected monitor\n");
131 bug("[GMA] Probing GPIO%c\n", 'A' + (port
- G45_GPIOA
)/4);
132 OOP_Object
*i2c
= OOP_NewObject(sd
->IntelI2C
, NULL
, NULL
);
136 if (HIDD_I2C_ProbeAddress(i2c
, 0xa1))
138 struct TagItem attrs
[] = {
139 { aHidd_I2CDevice_Driver
, (IPTR
)i2c
},
140 { aHidd_I2CDevice_Address
, 0xa0 },
141 { aHidd_I2CDevice_Name
, (IPTR
)"Display" },
145 bug("[GMA] I2C device found\n");
147 OOP_Object
*obj
= OOP_NewObject(NULL
, CLID_Hidd_I2CDevice
, attrs
);
153 struct pHidd_I2CDevice_WriteRead msg
;
157 msg
.mID
= OOP_GetMethodID((STRPTR
)IID_Hidd_I2CDevice
, moHidd_I2CDevice_WriteRead
);
158 msg
.readBuffer
= &edid
[0];
159 msg
.readLength
= 128;
160 msg
.writeBuffer
= &wb
[0];
163 OOP_DoMethod(obj
, &msg
.mID
);
165 for (i
=0; i
< 128; i
++)
169 edid
[0] == 0 && edid
[1] == 0xff && edid
[2] == 0xff && edid
[3] == 0xff &&
170 edid
[4] == 0xff && edid
[5] == 0xff && edid
[6] == 0xff && edid
[7] == 0)
173 if (edid
[0x14] & 0x80)
175 bug("[GMA] Digital device\n");
179 bug("[GMA] Analog device\n");
183 OOP_DisposeObject(obj
);
186 else bug("[GMA] No I2C device found\n");
188 OOP_DisposeObject(i2c
);
195 AROS_UFH3(void, Enumerator
,
196 AROS_UFHA(struct Hook
*,hook
, A0
),
197 AROS_UFHA(OOP_Object
*, pciDevice
, A2
),
198 AROS_UFHA(APTR
, message
, A1
))
202 struct g45staticdata
*sd
= hook
->h_Data
;
203 ULONG max_gfx_mem_size
;
208 /* Get the Device's ProductID */
209 OOP_GetAttr(pciDevice
, aHidd_PCIDevice_ProductID
, &ProductID
);
210 OOP_GetAttr(pciDevice
, aHidd_PCIDevice_VendorID
, &VendorID
);
211 OOP_GetAttr(pciDevice
, aHidd_PCIDevice_RevisionID
, &RevisionID
);
213 D(bug("[GMA] Checking device %04x:%04x\n", VendorID
, ProductID
));
215 if (sd
->forced
|| IsCompatible(ProductID
))
219 if (HIDD_PCIDevice_Obtain(pciDevice
, "IntelGMA"))
221 D(bug("[GMA] Failed to obtain device, already owned\n"));
225 MGCC
= HIDD_PCIDevice_ReadConfigWord(pciDevice
, G45_MGCC
);
226 D(bug("[GMA] MGCC=%04x, BSM=%08x, MSAC=%08x\n", MGCC
,
227 HIDD_PCIDevice_ReadConfigLong(pciDevice
, G45_BSM
),
228 HIDD_PCIDevice_ReadConfigByte(pciDevice
, G45_MSAC
)));
230 /*-------- DO NOT CHANGE/REMOVE -------------*/
231 bug("\003\n"); /* Tell vga text mode debug output to die */
232 /*-------- DO NOT CHANGE/REMOVE -------------*/
234 switch (MGCC
& G45_MGCC_GMS_MASK
)
236 case G45_MGCC_GMS_1M
:
237 sd
->Card
.Stolen_size
= 0x00100000;
239 case G45_MGCC_GMS_4M
:
240 sd
->Card
.Stolen_size
= 0x00400000;
242 case G45_MGCC_GMS_8M
:
243 sd
->Card
.Stolen_size
= 0x00800000;
245 case G45_MGCC_GMS_16M
:
246 sd
->Card
.Stolen_size
= 0x01000000;
248 case G45_MGCC_GMS_32M
:
249 sd
->Card
.Stolen_size
= 0x02000000;
251 case G45_MGCC_GMS_48M
:
252 sd
->Card
.Stolen_size
= 0x03000000;
254 case G45_MGCC_GMS_64M
:
255 sd
->Card
.Stolen_size
= 0x04000000;
259 sd
->ProductID
= ProductID
;
261 IPTR mmio_base
, window_base
, gatt_base
;
262 IPTR mmio_size
, window_size
, gatt_size
;
264 struct TagItem attrs
[] =
266 { aHidd_PCIDevice_isIO
, TRUE
}, /* Listen to I/O transactions */
267 { aHidd_PCIDevice_isMEM
, TRUE
}, /* Listen to MEM transactions */
268 { aHidd_PCIDevice_isMaster
, TRUE
}, /* Can work in BusMaster */
272 OOP_SetAttrs(pciDevice
, attrs
);
273 OOP_GetAttr(pciDevice
, aHidd_PCIDevice_Driver
, (IPTR
*)&driver
);
275 if (HasQuadBARs(ProductID
))
277 OOP_GetAttr(pciDevice
, aHidd_PCIDevice_Base0
, &mmio_base
);
278 OOP_GetAttr(pciDevice
, aHidd_PCIDevice_Base2
, &window_base
);
280 OOP_GetAttr(pciDevice
, aHidd_PCIDevice_Size0
, &mmio_size
);
281 OOP_GetAttr(pciDevice
, aHidd_PCIDevice_Size2
, &window_size
);
284 gatt_base
= mmio_base
+ mmio_size
;
285 gatt_size
= GetGATTSize(sd
);
289 OOP_GetAttr(pciDevice
, aHidd_PCIDevice_Base0
, &mmio_base
);
290 OOP_GetAttr(pciDevice
, aHidd_PCIDevice_Base2
, &window_base
);
291 OOP_GetAttr(pciDevice
, aHidd_PCIDevice_Base3
, &gatt_base
);
293 OOP_GetAttr(pciDevice
, aHidd_PCIDevice_Size0
, &mmio_size
);
294 OOP_GetAttr(pciDevice
, aHidd_PCIDevice_Size2
, &window_size
);
295 OOP_GetAttr(pciDevice
, aHidd_PCIDevice_Size3
, &gatt_size
);
298 /* Gain access to PCI resource regions used */
299 sd
->Card
.Framebuffer
= HIDD_PCIDriver_MapPCI(driver
,
300 (APTR
)window_base
, window_size
);
301 sd
->Card
.Framebuffer_size
= window_size
;
302 sd
->Card
.MMIO
= HIDD_PCIDriver_MapPCI(driver
,
303 (APTR
)mmio_base
, mmio_size
);
304 sd
->Card
.GATT
= HIDD_PCIDriver_MapPCI(driver
,
305 (APTR
)gatt_base
, gatt_size
);
306 sd
->Card
.GATT_size
= gatt_size
;
308 /* Estimate the common size of the GATT and the graphics aperture.
309 * Substract 16MB for scratch area */
310 max_gfx_mem_size
= min(window_size
, gatt_size
* 1024) - 16 * MBYTES
;
312 D(bug("[GMA] GATT space for %d entries\n", gatt_size
/ 4));
314 D(bug("[GMA] Stolen memory size: %dMB\n", sd
->Card
.Stolen_size
>> 20));
315 D(bug("[GMA] Framebuffer window size: %d MB\n", sd
->Card
.Framebuffer_size
>> 20));
317 /* Virtual address of end of stolen graphics memory */
318 uintptr_t virtual = sd
->Card
.Stolen_size
- sd
->Card
.GATT_size
- 4096;
320 sd
->ScratchArea
= max_gfx_mem_size
;
321 D(bug("[GMA] Scratch area at %08x\n", sd
->ScratchArea
));
323 /* Add stolen memory to internal memory list */
324 AddTail((APTR
)&sd
->CardMem
,
325 (APTR
)ObtainGfxMemory(sd
, 0, virtual, TRUE
));
327 sd
->PCIDevice
= pciDevice
;
332 val
= G45_GPIO_CLOCK_DIR_MASK
| G45_GPIO_CLOCK_DIR_VAL
;
333 /* update SCL value */
334 val
|= G45_GPIO_CLOCK_DATA_MASK
;
336 val
= G45_GPIO_DATA_DIR_MASK
| G45_GPIO_DATA_DIR_VAL
;
337 /* update SDA value */
338 val
|= G45_GPIO_DATA_MASK
;
342 val
|= G45_GPIO_CLOCK_DATA_VAL
;
343 val
|= G45_GPIO_DATA_VAL
;
345 writel(val
, sd
->Card
.MMIO
+ G45_GPIOA
);
346 writel(val
, sd
->Card
.MMIO
+ G45_GPIOC
);
347 writel(val
, sd
->Card
.MMIO
+ G45_GPIOE
);
349 writel(0, sd
->Card
.MMIO
+ G45_GMBUS
);
351 /* Ring buffer. The very first allocation, therefore I take for granted it's aligned on 4K page boundary.
353 sd
->RingBufferPhys
= AllocGfxMem(sd
, 64 * 4096);
354 sd
->RingBuffer
= (intptr_t)sd
->RingBufferPhys
- (intptr_t)sd
->Card
.Framebuffer
;
355 sd
->RingBufferSize
= 64*4096;
356 sd
->RingBufferTail
= 0;
358 /* Reserve some memory for HW cursor (this is also assumed to be 4kB
360 sd
->CursorImage
= ((intptr_t)AllocGfxMem(sd
, 64 * 64 * 4))
361 - (intptr_t)sd
->Card
.Framebuffer
;
362 if (NeedsPhysicalCursor(ProductID
))
363 sd
->CursorBase
= G45_VirtualToPhysical(sd
, sd
->CursorImage
);
365 sd
->CursorBase
= sd
->CursorImage
;
367 D(bug("[GMA] Using ARGB cursor at graphics address %08x (physical address %08x)\n",
368 sd
->CursorImage
, sd
->CursorBase
));
369 sd
->CursorVisible
= FALSE
;
371 D(bug("[GMA] Initializing CMD ring buffer\n"));
373 writel(sd
->RingBuffer
, sd
->Card
.MMIO
+ G45_RING_BASE
);
374 writel(0, sd
->Card
.MMIO
+ G45_RING_TAIL
);
375 writel(0, sd
->Card
.MMIO
+ G45_RING_HEAD
);
376 writel((63 << G45_RING_CONTROL_LENGTH_SHIFT
) | G45_RING_CONTROL_ENABLE
, sd
->Card
.MMIO
+ G45_RING_CONTROL
);
378 sd
->Engine2DOwner
= NULL
;
380 sd
->HardwareStatusPage
= (void*)(((intptr_t)AllocPooled(sd
->MemPool
, 4096 + 4095) + 4095) & ~4095);
381 writel((ULONG
)(IPTR
)sd
->HardwareStatusPage
, sd
->Card
.MMIO
+ 0x2080);
383 // sd->HardwareStatusPage = (APTR)readl(sd->Card.MMIO + 0x2080);
384 D(bug("[GMA] Hardware status page: %08x\n", readl(sd
->Card
.MMIO
+ 0x2080)));
385 writel(1, &sd
->HardwareStatusPage
[16]);
389 // lvds port enabled ?
390 if( lvds_Enabled(sd
) ) lvds
= TRUE
;
392 // VGA port enabled by BIOS ?
393 if( adpa_Enabled(sd
)) lvds
= FALSE
;
395 // Final Test: try to read EDID information from VGA port
396 if (probe_monitor(sd
, G45_GPIOA
))
401 bug("[GMA] lvds Enabled\n");
403 GetSync(sd
,&sd
->lvds_fixed
,PIPE_B
);
407 bug("[GMA] analog VGA connector Enabled\n");
412 * Set up initial screen mode.
415 sd
->initialState
= AllocVecPooled(sd
->MemPool
, sizeof(GMAState_t
));
416 sd
->initialBitMap
= AllocBitmapArea(sd
, 640, 480, 4);
417 G45_InitMode(sd
, sd
->initialState
, 640, 480, 32, 25200, sd
->initialBitMap
,
422 /* Clear initial buffer */
424 *pixel
= (uint32_t *)(sd
->initialBitMap
+ sd
->Card
.Framebuffer
);
425 for(i
= 0; i
< 640 * 480; i
++)
430 * The driver must not modify hardware state before it's instantiated.
431 * AddDisplayDriverA() function intentionally takes class pointer, not an object.
432 * Before instantiating the driver it performs boot mode drivers check. If at
433 * least one of them is in use, it can't be shut down. This means the newly
434 * installed driver can conflict with it, if they ocassionally use the same hardware.
436 G45_LoadState(sd
, sd
->initialState
);
438 AddDisplayDriverA(sd
->IntelG45Class
, NULL
, NULL
);
444 const struct TagItem Requirements
[] =
446 {tHidd_PCI_Interface
, 0x00 },
447 {tHidd_PCI_Class
, 0x03 },
448 {tHidd_PCI_SubClass
, 0x00 },
449 {tHidd_PCI_VendorID
, 0x8086 },
453 int G45_Init(struct g45staticdata
*sd
)
455 D(bug("[GMA] Init\n"));
458 /* Temporary workaround for testing on old kickstart - sonic */
459 sd
->MemPool
= CreatePool(MEMF_CLEAR
| MEMF_PUBLIC
| MEMF_SEM_PROTECTED
, 8192, 4096);
461 sd
->MemPool
= CreatePool(MEMF_CLEAR
| MEMF_PUBLIC
| MEMF_SEM_PROTECTED
| MEMF_31BIT
, 8192, 4096);
466 InitSemaphore(&sd
->HWLock
);
467 InitSemaphore(&sd
->MultiBMLock
);
469 sd
->PCIDevice
= NULL
;
471 /* Initialize reusable MsgPort */
472 sd
->MsgPort
.mp_SigBit
= SIGB_SINGLE
;
473 sd
->MsgPort
.mp_Flags
= PA_SIGNAL
;
474 sd
->MsgPort
.mp_SigTask
= FindTask(NULL
);
475 sd
->MsgPort
.mp_Node
.ln_Type
= NT_MSGPORT
;
476 NEWLIST(&sd
->MsgPort
.mp_MsgList
);
478 NEWLIST((struct List
*)&sd
->CardMem
);
480 sd
->tr
= (struct timerequest
*)CreateIORequest(&sd
->MsgPort
, sizeof(struct timerequest
));
483 if (!OpenDevice((STRPTR
)"timer.device", UNIT_MICROHZ
, &sd
->tr
->tr_node
, 0))
485 D(bug("[GMA] UNIT_MICROHZ of timer.device opened\n"));
486 if ((sd
->PCIObject
= OOP_NewObject(NULL
, (STRPTR
)CLID_Hidd_PCI
, NULL
)))
488 struct Hook FindHook
=
490 h_Entry
: (IPTR (*)())Enumerator
,
494 HIDD_PCI_EnumDevices(sd
->PCIObject
, &FindHook
, Requirements
);
498 D(bug("[GMA] Found supported gfx card\n\003"));
500 sd
->mid_CopyMemBox8
= OOP_GetMethodID((STRPTR
)CLID_Hidd_BitMap
, moHidd_BitMap_CopyMemBox8
);
501 sd
->mid_CopyMemBox16
= OOP_GetMethodID((STRPTR
)CLID_Hidd_BitMap
, moHidd_BitMap_CopyMemBox16
);
502 sd
->mid_CopyMemBox32
= OOP_GetMethodID((STRPTR
)CLID_Hidd_BitMap
, moHidd_BitMap_CopyMemBox32
);
503 sd
->mid_PutMem32Image8
= OOP_GetMethodID((STRPTR
)CLID_Hidd_BitMap
, moHidd_BitMap_PutMem32Image8
);
504 sd
->mid_PutMem32Image16
= OOP_GetMethodID((STRPTR
)CLID_Hidd_BitMap
, moHidd_BitMap_PutMem32Image16
);
505 sd
->mid_GetMem32Image8
= OOP_GetMethodID((STRPTR
)CLID_Hidd_BitMap
, moHidd_BitMap_GetMem32Image8
);
506 sd
->mid_GetMem32Image16
= OOP_GetMethodID((STRPTR
)CLID_Hidd_BitMap
, moHidd_BitMap_GetMem32Image16
);
507 sd
->mid_Clear
= OOP_GetMethodID((STRPTR
)CLID_Hidd_BitMap
, moHidd_BitMap_Clear
);
508 sd
->mid_PutMemTemplate8
= OOP_GetMethodID((STRPTR
)CLID_Hidd_BitMap
, moHidd_BitMap_PutMemTemplate8
);
509 sd
->mid_PutMemTemplate16
= OOP_GetMethodID((STRPTR
)CLID_Hidd_BitMap
, moHidd_BitMap_PutMemTemplate16
);
510 sd
->mid_PutMemTemplate32
= OOP_GetMethodID((STRPTR
)CLID_Hidd_BitMap
, moHidd_BitMap_PutMemTemplate32
);
511 sd
->mid_PutMemPattern8
= OOP_GetMethodID((STRPTR
)CLID_Hidd_BitMap
, moHidd_BitMap_PutMemPattern8
);
512 sd
->mid_PutMemPattern16
= OOP_GetMethodID((STRPTR
)CLID_Hidd_BitMap
, moHidd_BitMap_PutMemPattern16
);
513 sd
->mid_PutMemPattern32
= OOP_GetMethodID((STRPTR
)CLID_Hidd_BitMap
, moHidd_BitMap_PutMemPattern32
);
514 sd
->mid_CopyLUTMemBox16
= OOP_GetMethodID((STRPTR
)CLID_Hidd_BitMap
, moHidd_BitMap_CopyLUTMemBox16
);
515 sd
->mid_CopyLUTMemBox32
= OOP_GetMethodID((STRPTR
)CLID_Hidd_BitMap
, moHidd_BitMap_CopyLUTMemBox32
);
516 sd
->mid_GetImage
= OOP_GetMethodID((STRPTR
)CLID_Hidd_BitMap
, moHidd_BitMap_GetImage
);
518 sd
->mid_BitMapPositionChanged
= OOP_GetMethodID((STRPTR
)IID_Hidd_Compositing
, moHidd_Compositing_BitMapPositionChanged
);
519 sd
->mid_BitMapRectChanged
= OOP_GetMethodID((STRPTR
)IID_Hidd_Compositing
, moHidd_Compositing_BitMapRectChanged
);
520 sd
->mid_ValidateBitMapPositionChange
= OOP_GetMethodID((STRPTR
)IID_Hidd_Compositing
, moHidd_Compositing_ValidateBitMapPositionChange
);
524 D(bug("[GMA] No supported cards found\n"));
525 OOP_DisposeObject(sd
->PCIObject
);
527 CloseDevice(&sd
->tr
->tr_node
);
529 DeleteIORequest(&sd
->tr
->tr_node
);
531 DeletePool(sd
->MemPool
);
536 ADD2LIBS((STRPTR
)"graphics.hidd", 0, static struct Library
*, __gfxbase
);