wip prep commit in lieu of gfx subsystem update changes.
[AROS.git] / workbench / devs / monitors / IntelGMA / intelgma_init.c
blob0fa79586b38c8f58c966bd170c57713e972210f3
1 /*
2 Copyright © 2010-2017, The AROS Development Team. All rights reserved.
3 $Id$
4 */
6 #include <aros/debug.h>
7 #include <aros/symbolsets.h>
8 #include <oop/oop.h>
9 #include <graphics/driver.h>
10 #include <proto/exec.h>
11 #include <proto/graphics.h>
12 #include <proto/oop.h>
13 #include <hidd/gfx.h>
14 #include <hidd/pci.h>
15 #include <hidd/i2c.h>
17 #include <strings.h>
18 #include <stdlib.h>
20 #include "intelgma_hidd.h"
21 #include "intelG45_regs.h"
22 #include "compositing.h"
24 static uint32_t min(uint32_t a, uint32_t b)
26 if (a < b)
27 return a;
28 else
29 return b;
32 static BOOL IsCompatible(UWORD product_id)
34 return
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
46 product_id == 0x2582
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)
98 ULONG size = 0;
100 switch (readl(sd->Card.MMIO + G45_GATT_CONTROL) >> 1 & 0x7)
102 case 0:
103 size = 512 * KBYTES;
104 break;
105 case 1:
106 size = 256 * KBYTES;
107 break;
108 case 2:
109 size = 128 * KBYTES;
110 break;
111 case 3:
112 size = 1 * MBYTES;
113 break;
114 case 4:
115 size = 2 * MBYTES;
116 break;
117 case 5:
118 size = 1 * MBYTES + 512 * KBYTES;
119 break;
122 return size;
125 static BOOL probe_monitor(struct g45staticdata *sd, uint32_t port)
127 BOOL result = FALSE;
129 bug("[GMA] Attempting to detect connected monitor\n");
130 sd->DDCPort = port;
131 bug("[GMA] Probing GPIO%c\n", 'A' + (port - G45_GPIOA)/4);
132 OOP_Object *i2c = OOP_NewObject(sd->IntelI2C, NULL, NULL);
134 if (i2c)
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" },
142 { TAG_DONE, 0UL }
145 bug("[GMA] I2C device found\n");
147 OOP_Object *obj = OOP_NewObject(NULL, CLID_Hidd_I2CDevice, attrs);
149 if (obj)
151 uint8_t edid[128];
152 char wb[2] = {0, 0};
153 struct pHidd_I2CDevice_WriteRead msg;
154 uint8_t chksum = 0;
155 int i;
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];
161 msg.writeLength = 1;
163 OOP_DoMethod(obj, &msg.mID);
165 for (i=0; i < 128; i++)
166 chksum += edid[i];
168 if (chksum == 0 &&
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)
172 result = TRUE;
173 if (edid[0x14] & 0x80)
175 bug("[GMA] Digital device\n");
177 else
179 bug("[GMA] Analog device\n");
183 OOP_DisposeObject(obj);
186 else bug("[GMA] No I2C device found\n");
188 OOP_DisposeObject(i2c);
191 return result;
194 static
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))
200 AROS_USERFUNC_INIT
202 struct g45staticdata *sd = hook->h_Data;
203 ULONG max_gfx_mem_size;
204 IPTR ProductID;
205 IPTR VendorID;
206 IPTR RevisionID;
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))
217 UWORD MGCC;
219 if (HIDD_PCIDevice_Obtain(pciDevice, "IntelGMA"))
221 D(bug("[GMA] Failed to obtain device, already owned\n"));
222 return;
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;
238 break;
239 case G45_MGCC_GMS_4M:
240 sd->Card.Stolen_size = 0x00400000;
241 break;
242 case G45_MGCC_GMS_8M:
243 sd->Card.Stolen_size = 0x00800000;
244 break;
245 case G45_MGCC_GMS_16M:
246 sd->Card.Stolen_size = 0x01000000;
247 break;
248 case G45_MGCC_GMS_32M:
249 sd->Card.Stolen_size = 0x02000000;
250 break;
251 case G45_MGCC_GMS_48M:
252 sd->Card.Stolen_size = 0x03000000;
253 break;
254 case G45_MGCC_GMS_64M:
255 sd->Card.Stolen_size = 0x04000000;
256 break;
259 sd->ProductID = ProductID;
261 IPTR mmio_base, window_base, gatt_base;
262 IPTR mmio_size, window_size, gatt_size;
263 OOP_Object *driver;
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 */
269 { TAG_DONE, 0UL },
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);
283 mmio_size /= 2;
284 gatt_base = mmio_base + mmio_size;
285 gatt_size = GetGATTSize(sd);
287 else
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;
329 uint32_t val;
331 /* SCL as output */
332 val = G45_GPIO_CLOCK_DIR_MASK | G45_GPIO_CLOCK_DIR_VAL;
333 /* update SCL value */
334 val |= G45_GPIO_CLOCK_DATA_MASK;
335 /* SDA as output */
336 val = G45_GPIO_DATA_DIR_MASK | G45_GPIO_DATA_DIR_VAL;
337 /* update SDA value */
338 val |= G45_GPIO_DATA_MASK;
340 /* set SCL */
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.
352 * Get 8KB of it. */
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
359 * aligned) */
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);
364 else
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]);
387 BOOL lvds = FALSE;
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 ))
397 lvds = FALSE;
399 if( lvds )
401 bug("[GMA] lvds Enabled\n");
402 sd->pipe = PIPE_B;
403 GetSync(sd,&sd->lvds_fixed,PIPE_B);
405 else
407 bug("[GMA] analog VGA connector Enabled\n");
408 sd->pipe = PIPE_A;
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,
418 640, 480,
419 656, 752, 800,
420 490, 492, 525, 0);
422 /* Clear initial buffer */
423 uint32_t i,
424 *pixel = (uint32_t *)(sd->initialBitMap + sd->Card.Framebuffer);
425 for(i = 0; i < 640 * 480; i++)
426 *pixel++ = 0;
429 * URGENT FIXME!!!
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);
441 AROS_LIBFUNC_EXIT
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 },
450 {TAG_DONE, 0UL }
453 int G45_Init(struct g45staticdata *sd)
455 D(bug("[GMA] Init\n"));
457 #ifdef __i386__
458 /* Temporary workaround for testing on old kickstart - sonic */
459 sd->MemPool = CreatePool(MEMF_CLEAR | MEMF_PUBLIC | MEMF_SEM_PROTECTED, 8192, 4096);
460 #else
461 sd->MemPool = CreatePool(MEMF_CLEAR | MEMF_PUBLIC | MEMF_SEM_PROTECTED | MEMF_31BIT, 8192, 4096);
462 #endif
463 if (!sd->MemPool)
464 return FALSE;
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));
481 if (sd->tr)
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,
491 h_Data: sd,
494 HIDD_PCI_EnumDevices(sd->PCIObject, &FindHook, Requirements);
496 if (sd->PCIDevice)
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);
522 return TRUE;
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);
533 return FALSE;
536 ADD2LIBS((STRPTR)"gfx.hidd", 0, static struct Library *, __gfxbase);