Check for SYS/GL during library init. Reason is that
[AROS.git] / workbench / devs / monitors / IntelGMA / intelG45_class.c
blob9d906c44329e4f2f5770531470ec16cee9456635
1 /*
2 Copyright © 1995-2015, The AROS Development Team. All rights reserved.
3 $Id$
4 */
6 #define DEBUG 0
8 #include <aros/debug.h>
9 #include <aros/libcall.h>
10 #include <aros/asmcall.h>
11 #include <aros/symbolsets.h>
12 #include <utility/tagitem.h>
13 #include <hidd/graphics.h>
14 #include <hidd/i2c.h>
15 #include <graphics/displayinfo.h>
16 #include <proto/oop.h>
17 #include <proto/exec.h>
18 #include <proto/utility.h>
20 #include <stdio.h>
21 #include <stdint.h>
23 #include "intelG45_intern.h"
24 #include "intelG45_regs.h"
25 #include "gallium_intern.h"
26 #include "compositing.h"
28 #define sd ((struct g45staticdata*)SD(cl))
30 #define MAX_MODE_NAME_LEN 30
32 #define SYNC_TAG_COUNT 16
33 #define SYNC_LIST_COUNT (15 + 8 + 4)
35 #define DEBUG_POINTER 1
37 #ifdef DEBUG_POINTER
39 #define PRINT_POINTER(image, xsize, xmax, ymax) \
40 bug("[GMA] Pointer data:\n"); \
41 { \
42 ULONG *pix = (ULONG *)image; \
43 ULONG x, y; \
45 for (y = 0; y < ymax; y++) { \
46 for (x = 0; x < xmax; x++) \
47 bug("0x%08X ", pix[x]); \
48 bug("\n"); \
49 pix += xsize; \
50 } \
53 #else
54 #define PRINT_POINTER(image, xsize, xmax, ymax)
55 #endif
57 /* Definitions used in CVT formula */
58 #define M 600
59 #define C 40
60 #define K 128
61 #define J 20
62 #define DUTY_CYCLE(period) \
63 (((C - J) / 2 + J) * 1000 - (M / 2 * (period) / 1000))
64 #define MIN_DUTY_CYCLE 20 /* % */
65 #define MIN_V_PORCH 3 /* lines */
66 #define MIN_V_PORCH_TIME 550 /* us */
67 #define CLOCK_STEP 250000 /* Hz */
69 typedef struct {
70 uint16_t width;
71 uint16_t height;
73 uint16_t hstart;
74 uint16_t hend;
75 uint16_t htotal;
76 uint16_t vstart;
77 uint16_t vend;
78 uint16_t vtotal;
80 uint32_t pixel;
81 } sync_t;
83 /* Partial implementation of CVT formula */
84 void calcTimings(int x, int y, int vfreq, sync_t *sync)
86 ULONG h_period, h_freq, h_total, h_blank, h_front, h_sync, h_back,
87 v_total, v_front, v_sync, v_back, duty_cycle, pixel_freq;
89 sync->width = x;
90 sync->height = y;
92 /* Get horizontal period in microseconds */
93 h_period = (1000000000 / vfreq - MIN_V_PORCH_TIME * 1000)
94 / (y + MIN_V_PORCH);
96 /* Vertical front porch is fixed */
97 v_front = MIN_V_PORCH;
99 /* Use aspect ratio to determine V-sync lines */
100 if (x == y * 4 / 3)
101 v_sync = 4;
102 else if (x == y * 16 / 9)
103 v_sync = 5;
104 else if (x == y * 16 / 10)
105 v_sync = 6;
106 else if (x == y * 5 / 4)
107 v_sync = 7;
108 else if (x == y * 15 / 9)
109 v_sync = 7;
110 else
111 v_sync = 10;
113 /* Get vertical back porch */
114 v_back = MIN_V_PORCH_TIME * 1000 / h_period + 1;
115 if (v_back < MIN_V_PORCH)
116 v_back = MIN_V_PORCH;
117 v_back -= v_sync;
119 /* Get total lines per frame */
120 v_total = y + v_front + v_sync + v_back;
122 /* Get horizontal blanking pixels */
123 duty_cycle = DUTY_CYCLE(h_period);
124 if (duty_cycle < MIN_DUTY_CYCLE)
125 duty_cycle = MIN_DUTY_CYCLE;
127 h_blank = 10 * x * duty_cycle / (100000 - duty_cycle);
128 h_blank /= 2 * 8 * 10;
129 h_blank = h_blank * (2 * 8);
131 /* Get total pixels in a line */
132 h_total = x + h_blank;
134 /* Calculate frequencies for each pixel, line and field */
135 h_freq = 1000000000 / h_period;
136 pixel_freq = h_freq * h_total / CLOCK_STEP * CLOCK_STEP;
137 h_freq = pixel_freq / h_total;
139 /* Back porch is half of H-blank */
140 h_back = h_blank / 2;
142 /* H-sync is a fixed percentage of H-total */
143 h_sync = h_total / 100 * 8;
145 /* Front porch is whatever's left */
146 h_front = h_blank - h_sync - h_back;
148 /* Fill in VBE timings structure */
149 sync->htotal = h_total;
150 sync->hstart = x + h_front;
151 sync->hend = h_total - h_back;
152 sync->vtotal = v_total;
153 sync->vstart = y + v_front;
154 sync->vend = v_total - v_back;
155 sync->pixel = pixel_freq;
158 #define MAKE_SYNC(name,clock,hdisp,hstart,hend,htotal,vdisp,vstart,vend,vtotal,descr) \
159 struct TagItem sync_ ## name[]={ \
160 { aHidd_Sync_PixelClock, clock*1000 }, \
161 { aHidd_Sync_HDisp, hdisp }, \
162 { aHidd_Sync_HSyncStart, hstart }, \
163 { aHidd_Sync_HSyncEnd, hend }, \
164 { aHidd_Sync_HTotal, htotal }, \
165 { aHidd_Sync_VDisp, vdisp }, \
166 { aHidd_Sync_VSyncStart, vstart }, \
167 { aHidd_Sync_VSyncEnd, vend }, \
168 { aHidd_Sync_VTotal, vtotal }, \
169 { aHidd_Sync_Description, (IPTR)descr }, \
170 { TAG_DONE, 0UL }}
172 #define PUSH_TAG(ptr, tag, data) do { (*(ptr))->ti_Tag = (tag); (*(ptr))->ti_Data= (IPTR)(data); (*ptr)++; } while(0)
174 void createSync(OOP_Class *cl, int x, int y, int refresh, struct TagItem **tagsptr, struct TagItem **poolptr)
176 sync_t sync;
177 char *description = AllocVecPooled(sd->MemPool, MAX_MODE_NAME_LEN + 1);
178 snprintf(description, MAX_MODE_NAME_LEN, "GMA: %dx%d@%d", x, y, refresh);
179 calcTimings(x, y, refresh, &sync);
181 D(bug("[GMA] %s %d %d %d %d %d %d %d %d %d -HSync +VSync\n", description+5,
182 sync.pixel / 1000, sync.width, sync.hstart, sync.hend, sync.htotal,
183 sync.height, sync.vstart, sync.vend, sync.vtotal));
185 PUSH_TAG(tagsptr, aHidd_Gfx_SyncTags, *poolptr);
187 PUSH_TAG(poolptr, aHidd_Sync_Description, description);
188 PUSH_TAG(poolptr, aHidd_Sync_PixelClock, sync.pixel);
190 PUSH_TAG(poolptr, aHidd_Sync_HDisp, sync.width);
191 PUSH_TAG(poolptr, aHidd_Sync_HSyncStart, sync.hstart);
192 PUSH_TAG(poolptr, aHidd_Sync_HSyncEnd, sync.hend);
193 PUSH_TAG(poolptr, aHidd_Sync_HTotal, sync.htotal);
195 PUSH_TAG(poolptr, aHidd_Sync_VDisp, sync.height);
196 PUSH_TAG(poolptr, aHidd_Sync_VSyncStart, sync.vstart);
197 PUSH_TAG(poolptr, aHidd_Sync_VSyncEnd, sync.vend);
198 PUSH_TAG(poolptr, aHidd_Sync_VTotal, sync.vtotal);
200 PUSH_TAG(poolptr, aHidd_Sync_VMin, sync.height);
201 PUSH_TAG(poolptr, aHidd_Sync_VMax, 4096);
202 PUSH_TAG(poolptr, aHidd_Sync_HMin, sync.width);
203 PUSH_TAG(poolptr, aHidd_Sync_HMax, 4096);
205 PUSH_TAG(poolptr, aHidd_Sync_Flags, vHidd_Sync_VSyncPlus);
206 PUSH_TAG(poolptr, TAG_DONE, 0);
209 static VOID G45_parse_ddc(OOP_Class *cl, struct TagItem **tagsptr,
210 struct TagItem *poolptr, OOP_Object *obj)
212 struct pHidd_I2CDevice_WriteRead msg;
213 uint8_t edid[128];
214 char wb[2] = {0, 0};
215 int i;
216 uint8_t chksum = 0;
217 char *description;
219 D(bug("[GMA] Trying to parse the DDC data\n"));
221 msg.mID = OOP_GetMethodID((STRPTR)IID_Hidd_I2CDevice, moHidd_I2CDevice_WriteRead);
222 msg.readBuffer = &edid[0];
223 msg.readLength = 128;
224 msg.writeBuffer = &wb[0];
225 msg.writeLength = 1;
227 OOP_DoMethod(obj, &msg.mID);
229 for (i=0; i < 128; i++)
230 chksum += edid[i];
232 if (chksum == 0 &&
233 edid[0] == 0 && edid[1] == 0xff && edid[2] == 0xff && edid[3] == 0xff &&
234 edid[4] == 0xff && edid[5] == 0xff && edid[6] == 0xff && edid[7] == 0)
236 D(bug("[GMA] Valid EDID%d.%d header\n", edid[18], edid[19]));
238 D(bug("[GMA] Established timing: %02x %02x %02x\n", edid[35], edid[36], edid[37]));
239 if (edid[35] & 0x80)
240 createSync(cl, 720, 400, 70, tagsptr, &poolptr);
241 if (edid[35] & 0x40)
242 createSync(cl, 720, 400, 88, tagsptr, &poolptr);
243 if (edid[35] & 0x20)
244 createSync(cl, 640, 480, 60, tagsptr, &poolptr);
245 if (edid[35] & 0x10)
246 createSync(cl, 640, 480, 67, tagsptr, &poolptr);
247 if (edid[35] & 0x08)
248 createSync(cl, 640, 480, 72, tagsptr, &poolptr);
249 if (edid[35] & 0x04)
250 createSync(cl, 640, 480, 75, tagsptr, &poolptr);
251 if (edid[35] & 0x02)
252 createSync(cl, 800, 600, 56, tagsptr, &poolptr);
253 if (edid[35] & 0x01)
254 createSync(cl, 800, 600, 60, tagsptr, &poolptr);
255 if (edid[36] & 0x80)
256 createSync(cl, 800, 600, 72, tagsptr, &poolptr);
257 if (edid[36] & 0x40)
258 createSync(cl, 800, 600, 75, tagsptr, &poolptr);
259 if (edid[36] & 0x20)
260 createSync(cl, 832, 624, 75, tagsptr, &poolptr);
261 if (edid[36] & 0x08)
262 createSync(cl, 1024, 768, 60, tagsptr, &poolptr);
263 if (edid[36] & 0x04)
264 createSync(cl, 1024, 768, 70, tagsptr, &poolptr);
265 if (edid[36] & 0x02)
266 createSync(cl, 1024, 768, 75, tagsptr, &poolptr);
267 if (edid[36] & 0x01)
268 createSync(cl, 1280, 1024, 75, tagsptr, &poolptr);
270 //createSync(cl, 736, 566, 60, tagsptr, &poolptr);
272 D(bug("[GMA] Standard timing identification:\n"));
274 for (i=38; i < 54; i+=2)
276 int w, h = 0, freq;
277 w = edid[i] * 8 + 248;
278 if (w > 400)
280 freq = (edid[i+1] & 0x3f) + 60;
281 switch (edid[i+1] >> 6)
283 case 0: /* 16:10 */
284 h = (w * 10) / 16;
285 break;
286 case 1: /* 4:3 */
287 h = (w * 3) / 4;
288 break;
289 case 2: /* 5:4 */
290 h = (w * 4) / 5;
291 break;
292 case 3: /* 16:9 */
293 h = (w * 9) / 16;
294 break;
296 createSync(cl, w, h, freq, tagsptr, &poolptr);
300 for (i=54; i < 126; i+= 18)
302 if (edid[i] || edid[i+1])
304 int ha, hb, va, vb, hsync_o, hsync_w, vsync_o, vsync_w, pixel;
305 ha = edid[i+2];
306 hb = edid[i+3];
307 ha |= (edid[i+4] >> 4) << 8;
308 hb |= (edid[i+4] & 0x0f) << 8;
309 va = edid[i+5];
310 vb = edid[i+6];
311 va |= (edid[i+7] >> 4) << 8;
312 vb |= (edid[i+7] & 0x0f) << 8;
313 hsync_o = edid[i+8];
314 hsync_w = edid[i+9];
315 vsync_o = edid[i+10] >> 4;
316 vsync_w = edid[i+10] & 0x0f;
317 hsync_o |= 0x300 & ((edid[i+11] >> 6) << 8);
318 hsync_w |= 0x300 & ((edid[i+11] >> 4) << 8);
319 vsync_o |= 0x30 & ((edid[i+11] >> 2) << 4);
320 vsync_w |= 0x30 & ((edid[i+11]) << 4);
322 pixel = (edid[i] | (edid[i+1] << 8));
324 D(bug("[GMA] Modeline: "));
325 D(bug("%dx%d Pixel: %d0 kHz %d %d %d %d %d %d %d %d\n", ha, va, pixel,
326 ha, hb, hsync_o, hsync_w,
327 va, vb, vsync_o, vsync_w));
329 description = AllocVecPooled(sd->MemPool, MAX_MODE_NAME_LEN + 1);
330 snprintf(description, MAX_MODE_NAME_LEN, "GMA: %dx%d@%d N",
331 ha, va, (int)(((pixel * 10 / (uint32_t)(ha + hb)) * 1000)
332 / ((uint32_t)(va + vb))));
334 PUSH_TAG(tagsptr, aHidd_Gfx_SyncTags, poolptr);
336 PUSH_TAG(&poolptr, aHidd_Sync_Description, description);
337 PUSH_TAG(&poolptr, aHidd_Sync_PixelClock, pixel*10000);
339 PUSH_TAG(&poolptr, aHidd_Sync_HDisp, ha);
340 PUSH_TAG(&poolptr, aHidd_Sync_HSyncStart, ha+hsync_o);
341 PUSH_TAG(&poolptr, aHidd_Sync_HSyncEnd, ha+hsync_o+hsync_w);
342 PUSH_TAG(&poolptr, aHidd_Sync_HTotal, ha+hb);
344 PUSH_TAG(&poolptr, aHidd_Sync_VDisp, va);
345 PUSH_TAG(&poolptr, aHidd_Sync_VSyncStart, va+vsync_o);
346 PUSH_TAG(&poolptr, aHidd_Sync_VSyncEnd, va+vsync_o+vsync_w);
347 PUSH_TAG(&poolptr, aHidd_Sync_VTotal, va+vb);
349 PUSH_TAG(&poolptr, aHidd_Sync_VMin, va);
350 PUSH_TAG(&poolptr, aHidd_Sync_VMax, 4096);
351 PUSH_TAG(&poolptr, aHidd_Sync_HMin, ha);
352 PUSH_TAG(&poolptr, aHidd_Sync_HMax, 4096);
354 PUSH_TAG(&poolptr, aHidd_Sync_Flags, vHidd_Sync_VSyncPlus);
355 PUSH_TAG(&poolptr, TAG_DONE, 0);
358 else
360 switch (edid[i+3])
362 case 0xff:
363 D(bug("[GMA] Monitor Serial: %s\n", &edid[i+5]));
364 break;
365 case 0xfe:
366 D(bug("[GMA] ASCII String: %s\n", &edid[i+5]));
367 break;
368 case 0xfc:
369 D(bug("[GMA] Monitor Name: %s\n", &edid[i+5]));
370 break;
371 case 0xfd:
372 if (edid[i+10] == 0 && edid[i+11] == 0x0a)
374 D(bug("[GMA] Monitor limits: H: %d - %d kHz, V: %d - %d Hz, PixelClock: %dMHz\n",
375 edid[i+7], edid[i+8], edid[i+5], edid[i+6], edid[i+9]*10));
377 break;
378 default:
379 D(bug("[GMA] Entry %02x\n", edid[i+3]));
385 D(bug("[GMA] %d additional pages available\n", edid[126]));
387 else
388 D(bug("[GMA] Not a valid EDID data\n"));
392 OOP_Object *METHOD(INTELG45, Root, New)
394 D(bug("[GMA] Root New\n"));
396 struct TagItem *modetags, *tags;
397 struct TagItem *poolptr;
399 struct TagItem pftags_24bpp[] = {
400 { aHidd_PixFmt_RedShift, 8 }, /* 0 */
401 { aHidd_PixFmt_GreenShift, 16 }, /* 1 */
402 { aHidd_PixFmt_BlueShift, 24 }, /* 2 */
403 { aHidd_PixFmt_AlphaShift, 0 }, /* 3 */
404 { aHidd_PixFmt_RedMask, 0x00ff0000 }, /* 4 */
405 { aHidd_PixFmt_GreenMask, 0x0000ff00 }, /* 5 */
406 { aHidd_PixFmt_BlueMask, 0x000000ff }, /* 6 */
407 { aHidd_PixFmt_AlphaMask, 0x00000000 }, /* 7 */
408 { aHidd_PixFmt_ColorModel, vHidd_ColorModel_TrueColor }, /* 8 */
409 { aHidd_PixFmt_Depth, 24 }, /* 9 */
410 { aHidd_PixFmt_BytesPerPixel, 4 }, /* 10 */
411 { aHidd_PixFmt_BitsPerPixel, 24 }, /* 11 */
412 { aHidd_PixFmt_StdPixFmt, vHidd_StdPixFmt_BGR032 }, /* 12 Native */
413 { aHidd_PixFmt_BitMapType, vHidd_BitMapType_Chunky }, /* 15 */
414 { TAG_DONE, 0UL }
417 struct TagItem pftags_16bpp[] = {
418 { aHidd_PixFmt_RedShift, 16 }, /* 0 */
419 { aHidd_PixFmt_GreenShift, 21 }, /* 1 */
420 { aHidd_PixFmt_BlueShift, 27 }, /* 2 */
421 { aHidd_PixFmt_AlphaShift, 0 }, /* 3 */
422 { aHidd_PixFmt_RedMask, 0x0000f800 }, /* 4 */
423 { aHidd_PixFmt_GreenMask, 0x000007e0 }, /* 5 */
424 { aHidd_PixFmt_BlueMask, 0x0000001f }, /* 6 */
425 { aHidd_PixFmt_AlphaMask, 0x00000000 }, /* 7 */
426 { aHidd_PixFmt_ColorModel, vHidd_ColorModel_TrueColor }, /* 8 */
427 { aHidd_PixFmt_Depth, 16 }, /* 9 */
428 { aHidd_PixFmt_BytesPerPixel, 2 }, /* 10 */
429 { aHidd_PixFmt_BitsPerPixel, 16 }, /* 11 */
430 { aHidd_PixFmt_StdPixFmt, vHidd_StdPixFmt_RGB16_LE }, /* 12 */
431 { aHidd_PixFmt_BitMapType, vHidd_BitMapType_Chunky }, /* 15 */
432 { TAG_DONE, 0UL }
435 // struct TagItem pftags_15bpp[] = {
436 // { aHidd_PixFmt_RedShift, 17 }, /* 0 */
437 // { aHidd_PixFmt_GreenShift, 22 }, /* 1 */
438 // { aHidd_PixFmt_BlueShift, 27 }, /* 2 */
439 // { aHidd_PixFmt_AlphaShift, 0 }, /* 3 */
440 // { aHidd_PixFmt_RedMask, 0x00007c00 }, /* 4 */
441 // { aHidd_PixFmt_GreenMask, 0x000003e0 }, /* 5 */
442 // { aHidd_PixFmt_BlueMask, 0x0000001f }, /* 6 */
443 // { aHidd_PixFmt_AlphaMask, 0x00000000 }, /* 7 */
444 // { aHidd_PixFmt_ColorModel, vHidd_ColorModel_TrueColor }, /* 8 */
445 // { aHidd_PixFmt_Depth, 15 }, /* 9 */
446 // { aHidd_PixFmt_BytesPerPixel, 2 }, /* 10 */
447 // { aHidd_PixFmt_BitsPerPixel, 15 }, /* 11 */
448 // { aHidd_PixFmt_StdPixFmt, vHidd_StdPixFmt_RGB15_LE }, /* 12 */
449 // { aHidd_PixFmt_BitMapType, vHidd_BitMapType_Chunky }, /* 15 */
450 // { TAG_DONE, 0UL }
451 // };
453 OOP_Object *i2c;
455 modetags = tags = AllocVecPooled(sd->MemPool,
456 sizeof (struct TagItem) * (3 + SYNC_LIST_COUNT + 1));
457 poolptr = AllocVecPooled(sd->MemPool,
458 sizeof(struct TagItem) * SYNC_TAG_COUNT * SYNC_LIST_COUNT);
460 struct TagItem i2c_attrs[] = {
461 // { aHidd_I2C_HoldTime, 40 },
462 // { aHidd_I2C_RiseFallTime, 40 },
463 { TAG_DONE, 0UL }
466 tags->ti_Tag = aHidd_Gfx_PixFmtTags;
467 tags->ti_Data = (IPTR)pftags_24bpp;
468 tags++;
470 tags->ti_Tag = aHidd_Gfx_PixFmtTags;
471 tags->ti_Data = (IPTR)pftags_16bpp;
472 tags++;
474 // tags->ti_Tag = aHidd_Gfx_PixFmtTags;
475 // tags->ti_Data = (IPTR)pftags_15bpp;
476 // tags++;
478 if( sd->pipe == PIPE_B )
480 char *description = AllocVecPooled(sd->MemPool, MAX_MODE_NAME_LEN + 1);
481 snprintf(description, MAX_MODE_NAME_LEN, "GMA_LVDS:%dx%d",
482 sd->lvds_fixed.hdisp, sd->lvds_fixed.vdisp);
484 //native lcd mode
485 struct TagItem sync_native[]={
486 { aHidd_Sync_PixelClock,sd->lvds_fixed.pixelclock*1000000 },
487 { aHidd_Sync_HDisp, sd->lvds_fixed.hdisp },
488 { aHidd_Sync_HSyncStart,sd->lvds_fixed.hstart },
489 { aHidd_Sync_HSyncEnd, sd->lvds_fixed.hend },
490 { aHidd_Sync_HTotal, sd->lvds_fixed.htotal },
491 { aHidd_Sync_VDisp, sd->lvds_fixed.vdisp },
492 { aHidd_Sync_VSyncStart,sd->lvds_fixed.vstart },
493 { aHidd_Sync_VSyncEnd, sd->lvds_fixed.vend },
494 { aHidd_Sync_VTotal, sd->lvds_fixed.vtotal },
495 { aHidd_Sync_VMin, sd->lvds_fixed.vdisp},
496 { aHidd_Sync_VMax, 4096},
497 { aHidd_Sync_HMin, sd->lvds_fixed.hdisp},
498 { aHidd_Sync_HMax, 4096},
499 { aHidd_Sync_Description, (IPTR)description },
500 { TAG_DONE, 0UL }};
502 MAKE_SYNC(640x480_60, 25174,
503 640, 656, 752, 800,
504 480, 490, 492, 525,
505 "GMA_LVDS:640x480");
507 tags->ti_Tag = aHidd_Gfx_SyncTags;
508 tags->ti_Data = (IPTR)sync_640x480_60;
509 tags++;
511 tags->ti_Tag = aHidd_Gfx_SyncTags;
512 tags->ti_Data = (IPTR)sync_native;
513 tags++;
516 else
519 i2c = OOP_NewObject(sd->IntelI2C, NULL, i2c_attrs);
521 if (i2c)
523 if (HIDD_I2C_ProbeAddress(i2c, 0xa0))
525 struct TagItem attrs[] = {
526 { aHidd_I2CDevice_Driver, (IPTR)i2c },
527 { aHidd_I2CDevice_Address, 0xa0 },
528 { aHidd_I2CDevice_Name, (IPTR)"Display" },
529 { TAG_DONE, 0UL }
532 D(bug("[GMA] I2C device found\n"));
534 OOP_Object *obj = OOP_NewObject(NULL, CLID_Hidd_I2CDevice, attrs);
536 if (obj)
538 G45_parse_ddc(cl, &tags, poolptr, obj);
540 OOP_DisposeObject(obj);
543 OOP_DisposeObject(i2c);
548 tags->ti_Tag = TAG_DONE;
549 tags->ti_Data = 0;
551 struct TagItem mytags[] = {
552 { aHidd_Gfx_ModeTags, (IPTR)modetags },
553 { TAG_MORE, (IPTR)msg->attrList }
556 struct pRoot_New mymsg;
558 mymsg.mID = msg->mID;
559 mymsg.attrList = mytags;
561 msg = &mymsg;
563 o = (OOP_Object *)OOP_DoSuperMethod(cl, o, (OOP_Msg)msg);
564 if (o)
566 sd->GMAObject = o;
567 /* Create compositing object */
569 struct TagItem comptags [] =
571 { aHidd_Compositing_GfxHidd, (IPTR)o },
572 { TAG_DONE, TAG_DONE }
574 sd->compositing = OOP_NewObject(sd->compositingclass, NULL, comptags);
575 /* TODO: Check if object was created, how to handle ? */
579 FreeVecPooled(sd->MemPool, modetags);
580 FreeVecPooled(sd->MemPool, poolptr);
582 D(bug("[GMA] INTELG45::New() = %p\n", o));
584 return o;
587 void METHOD(INTELG45, Root, Get)
589 D(bug("[GMA] Root Get\n"));
591 uint32_t idx;
592 BOOL found = FALSE;
593 if (IS_GFX_ATTR(msg->attrID, idx))
595 switch (idx)
597 case aoHidd_Gfx_SupportsHWCursor:
598 *msg->storage = (IPTR)TRUE;
599 found = TRUE;
600 break;
602 case aoHidd_Gfx_NoFrameBuffer:
603 *msg->storage = (IPTR)TRUE;
604 found = TRUE;
605 break;
607 case aoHidd_Gfx_HWSpriteTypes:
608 *msg->storage = vHidd_SpriteType_DirectColor;
609 found = TRUE;
610 return;
612 case aoHidd_Gfx_DPMSLevel:
613 *msg->storage = SD(cl)->dpms;
614 found = TRUE;
615 break;
619 if (!found)
620 OOP_DoSuperMethod(cl, o, (OOP_Msg)msg);
622 return;
625 void METHOD(INTELG45, Root, Set)
627 D(bug("[GMA] Root Set\n"));
629 ULONG idx;
630 struct TagItem *tag;
631 struct TagItem *tags = msg->attrList;
633 while ((tag = NextTagItem(&tags)))
635 if (IS_GFX_ATTR(tag->ti_Tag, idx))
637 switch(idx)
639 case aoHidd_Gfx_DPMSLevel:
640 LOCK_HW
641 uint32_t adpa = readl(sd->Card.MMIO + G45_ADPA) & ~G45_ADPA_DPMS_MASK;
642 switch (tag->ti_Data)
644 case vHidd_Gfx_DPMSLevel_On:
645 adpa |= G45_ADPA_DPMS_ON;
646 break;
647 case vHidd_Gfx_DPMSLevel_Off:
648 adpa |= G45_ADPA_DPMS_OFF;
649 break;
650 case vHidd_Gfx_DPMSLevel_Standby:
651 adpa |= G45_ADPA_DPMS_STANDBY;
652 break;
653 case vHidd_Gfx_DPMSLevel_Suspend:
654 adpa |= G45_ADPA_DPMS_SUSPEND;
655 break;
657 writel(adpa, sd->Card.MMIO + G45_ADPA);
658 sd->dpms = tag->ti_Data;
660 UNLOCK_HW
661 break;
666 OOP_DoSuperMethod(cl, o, (OOP_Msg)msg);
670 OOP_Object * METHOD(INTELG45, Hidd_Gfx, CreateObject)
672 OOP_Object *object = NULL;
674 if (msg->cl == SD(cl)->basebm)
676 struct pHidd_Gfx_CreateObject mymsg;
677 HIDDT_ModeID modeid;
678 HIDDT_StdPixFmt stdpf;
680 struct TagItem mytags [] =
682 { TAG_IGNORE, TAG_IGNORE }, /* Placeholder for aHidd_BitMap_ClassPtr */
683 { TAG_IGNORE, TAG_IGNORE }, /* Placeholder for aHidd_BitMap_Align */
684 { aHidd_BitMap_IntelG45_CompositingHidd, (IPTR)sd->compositing },
685 { TAG_MORE, (IPTR)msg->attrList }
688 /* Check if user provided valid ModeID */
689 /* Check for framebuffer - not needed as IntelG45 is a NoFramebuffer driver */
690 /* Check for displayable - not needed - displayable has ModeID and we don't
691 distinguish between on-screen and off-screen bitmaps */
692 modeid = (HIDDT_ModeID)GetTagData(aHidd_BitMap_ModeID, vHidd_ModeID_Invalid, msg->attrList);
693 if (vHidd_ModeID_Invalid != modeid)
695 /* User supplied a valid modeid. We can use our bitmap class */
696 mytags[0].ti_Tag = aHidd_BitMap_ClassPtr;
697 mytags[0].ti_Data = (IPTR)SD(cl)->BMClass;
700 /* Check if bitmap is a planar bitmap */
701 stdpf = (HIDDT_StdPixFmt)GetTagData(aHidd_BitMap_StdPixFmt, vHidd_StdPixFmt_Unknown, msg->attrList);
702 if (vHidd_StdPixFmt_Plane == stdpf)
704 mytags[1].ti_Tag = aHidd_BitMap_Align;
705 mytags[1].ti_Data = 32;
708 /* We init a new message struct */
709 mymsg.mID = msg->mID;
710 mymsg.cl = msg->cl;
711 mymsg.attrList = mytags;
713 /* Pass the new message to the superclass */
714 object = (OOP_Object *)OOP_DoSuperMethod(cl, o, (OOP_Msg)&mymsg);
716 else if (SD(cl)->basegallium && (msg->cl == SD(cl)->basegallium))
718 object = OOP_NewObject(NULL, CLID_Hidd_Gallium_IntelGMA, msg->attrList);
720 else
721 object = (OOP_Object *)OOP_DoSuperMethod(cl, o, (OOP_Msg)msg);
723 return object;
727 void METHOD(INTELG45, Hidd_Gfx, SetCursorVisible)
729 sd->CursorVisible = msg->visible;
730 if (msg->visible)
732 writel( (sd->pipe == PIPE_A ? G45_CURCNTR_PIPE_A : G45_CURCNTR_PIPE_B ) | G45_CURCNTR_TYPE_ARGB ,
733 sd->Card.MMIO + (sd->pipe == PIPE_A ? G45_CURACNTR:G45_CURBCNTR));
735 else
737 writel( (sd->pipe == PIPE_A ? G45_CURCNTR_PIPE_A : G45_CURCNTR_PIPE_B ) | G45_CURCNTR_TYPE_OFF ,
738 sd->Card.MMIO + (sd->pipe == PIPE_A ? G45_CURACNTR:G45_CURBCNTR));
740 UpdateCursor(sd);
744 void METHOD(INTELG45, Hidd_Gfx, SetCursorPos)
746 SetCursorPosition(sd,msg->x,msg->y);
747 sd->pointerx = msg->x;
748 sd->pointery = msg->y;
751 BOOL METHOD(INTELG45, Hidd_Gfx, SetCursorShape)
753 if (msg->shape == NULL)
755 sd->CursorVisible = 0;
756 writel( (sd->pipe == PIPE_A ? G45_CURCNTR_PIPE_A : G45_CURCNTR_PIPE_B ) | G45_CURCNTR_TYPE_OFF ,
757 sd->Card.MMIO + (sd->pipe == PIPE_A ? G45_CURACNTR:G45_CURBCNTR));
759 else
761 IPTR width, height, x;
763 ULONG *curimg = (ULONG*)((IPTR)sd->CursorImage + (IPTR)sd->Card.Framebuffer);
765 OOP_GetAttr(msg->shape, aHidd_BitMap_Width, &width);
766 OOP_GetAttr(msg->shape, aHidd_BitMap_Height, &height);
768 if (width > 64) width = 64;
769 if (height > 64) height = 64;
771 for (x = 0; x < 64*64; x++)
772 curimg[x] = 0;
774 HIDD_BM_GetImage(msg->shape, (UBYTE *)curimg, 64*4, 0, 0, width, height, vHidd_StdPixFmt_BGRA32);
775 writel( (sd->pipe == PIPE_A ? G45_CURCNTR_PIPE_A : G45_CURCNTR_PIPE_B ) | G45_CURCNTR_TYPE_ARGB ,
776 sd->Card.MMIO + (sd->pipe == PIPE_A ? G45_CURACNTR:G45_CURBCNTR));
778 UpdateCursor(sd);
780 return TRUE;
783 void METHOD(INTELG45, Hidd_Gfx, CopyBox)
785 ULONG mode = GC_DRMD(msg->gc);
786 IPTR src=0, dst=0;
788 /* Check whether we can get Drawable attribute of our GMA class */
789 OOP_GetAttr(msg->src, aHidd_GMABitMap_Drawable, &src);
790 OOP_GetAttr(msg->dest, aHidd_GMABitMap_Drawable, &dst);
792 if (!dst || !src)
794 /* No. One of the bitmaps is not a GMA bitmap */
795 OOP_DoSuperMethod(cl, o, (OOP_Msg)msg);
797 else
799 /* Yes. Get the instance data of both bitmaps */
800 GMABitMap_t *bm_src = OOP_INST_DATA(OOP_OCLASS(msg->src), msg->src);
801 GMABitMap_t *bm_dst = OOP_INST_DATA(OOP_OCLASS(msg->dest), msg->dest);
803 // D(bug("[GMA] CopyBox(src(%p,%d:%d@%d),dst(%p,%d:%d@%d),%d:%d\n",
804 // bm_src->framebuffer,msg->srcX,msg->srcY,bm_src->depth,
805 // bm_dst->framebuffer,msg->destX,msg->destY,bm_dst->depth,
806 // msg->width, msg->height));
808 /* Case -1: (To be fixed) one of the bitmaps have chunky outside GFX mem */
809 if (!bm_src->fbgfx || !bm_dst->fbgfx)
811 D(bug("[GMA] one of bitmaps outside VRAM! CopyBox(src(%p,%d:%d@%d),dst(%p,%d:%d@%d),%d:%d\n",
812 bm_src->framebuffer,msg->srcX,msg->srcY,bm_src->depth,
813 bm_dst->framebuffer,msg->destX,msg->destY,bm_dst->depth,
814 msg->width, msg->height));
816 OOP_DoSuperMethod(cl, o, (OOP_Msg)msg);
818 /* Case 0: one of bitmaps is 8bpp, whereas the other is TrueColor one */
819 else if ((bm_src->depth <= 8 || bm_dst->depth <= 8) &&
820 (bm_src->depth != bm_dst->depth))
822 /* Unsupported case */
823 OOP_DoSuperMethod(cl, o, (OOP_Msg)msg);
824 return;
826 /* Case 1: both bitmaps have the same depth - use Blit engine */
827 else if (bm_src->depth == bm_dst->depth)
829 LOCK_MULTI_BITMAP
830 LOCK_BITMAP_BM(bm_src)
831 LOCK_BITMAP_BM(bm_dst)
832 UNLOCK_MULTI_BITMAP
834 LOCK_HW
836 uint32_t br00, br13, br22, br23, br09, br11, br26, br12;
838 br00 = (2 << 29) | (0x53 << 22) | (6);
839 if (bm_dst->bpp == 4)
840 br00 |= 3 << 20;
842 br13 = bm_dst->pitch | ROP_table[mode].rop;
843 if (bm_dst->bpp == 4)
844 br13 |= 3 << 24;
845 else if (bm_dst->bpp == 2)
846 br13 |= 1 << 24;
848 br22 = msg->destX | (msg->destY << 16);
849 br23 = (msg->destX + msg->width) | (msg->destY + msg->height) << 16;
850 br09 = bm_dst->framebuffer;
851 br11 = bm_src->pitch;
852 br26 = msg->srcX | (msg->srcY << 16);
853 br12 = bm_src->framebuffer;
855 START_RING(8);
857 OUT_RING(br00);
858 OUT_RING(br13);
859 OUT_RING(br22);
860 OUT_RING(br23);
861 OUT_RING(br09);
862 OUT_RING(br26);
863 OUT_RING(br11);
864 OUT_RING(br12);
866 ADVANCE_RING();
868 DO_FLUSH();
869 UNLOCK_HW
871 UNLOCK_BITMAP_BM(bm_src)
872 UNLOCK_BITMAP_BM(bm_dst)
874 else /* Case 2: different bitmaps.Use 3d hardware. */
876 D(bug("[GMA] Depth mismatch! CopyBox(src(%p,%d:%d@%d),dst(%p,%d:%d@%d),%d:%d\n",
877 bm_src->framebuffer,msg->srcX,msg->srcY,bm_src->depth,
878 bm_dst->framebuffer,msg->destX,msg->destY,bm_dst->depth,
879 msg->width, msg->height));
881 LOCK_MULTI_BITMAP
882 LOCK_BITMAP_BM(bm_src)
883 LOCK_BITMAP_BM(bm_dst)
884 UNLOCK_MULTI_BITMAP
886 BOOL done = copybox3d( bm_dst, bm_src,
887 msg->destX, msg->destY, msg->width, msg->height,
888 msg->srcX, msg->srcY, msg->width, msg->height );
890 UNLOCK_BITMAP_BM(bm_src)
891 UNLOCK_BITMAP_BM(bm_dst)
893 if( ! done ) OOP_DoSuperMethod(cl, o, (OOP_Msg)msg);
898 ULONG METHOD(INTELG45, Hidd_Gfx, ShowViewPorts)
900 struct pHidd_Compositing_BitMapStackChanged bscmsg =
902 mID : OOP_GetMethodID(IID_Hidd_Compositing, moHidd_Compositing_BitMapStackChanged),
903 data : msg->Data
905 D(bug("[IntelG45] ShowViewPorts enter TopLevelBM %x\n", msg->Data->Bitmap));
906 OOP_DoMethod(sd->compositing, (OOP_Msg)&bscmsg);
907 return TRUE; /* Indicate driver supports this method */
910 BOOL HIDD_INTELG45_SwitchToVideoMode(OOP_Object * bm)
912 OOP_Class * cl = OOP_OCLASS(bm);
913 GMABitMap_t * bmdata = OOP_INST_DATA(cl, bm);
914 OOP_Object * gfx = NULL;
915 HIDDT_ModeID modeid;
916 OOP_Object * sync;
917 OOP_Object * pf;
918 IPTR pixel, e;
919 IPTR hdisp, vdisp, hstart, hend, htotal, vstart, vend, vtotal;
921 OOP_GetAttr(bm, aHidd_BitMap_GfxHidd, &e);
922 gfx = (OOP_Object *)e;
924 bug("[IntelG45] HIDD_INTELG45_SwitchToVideoMode bitmap:%x\n",bmdata);
926 /* We should be able to get modeID from the bitmap */
927 OOP_GetAttr(bm, aHidd_BitMap_ModeID, &modeid);
929 if (modeid == vHidd_ModeID_Invalid)
931 D(bug("[IntelG45] Invalid ModeID\n"));
932 return FALSE;
935 /* Get Sync and PixelFormat properties */
936 struct pHidd_Gfx_GetMode __getmodemsg =
938 modeID: modeid,
939 syncPtr: &sync,
940 pixFmtPtr: &pf,
941 }, *getmodemsg = &__getmodemsg;
943 getmodemsg->mID = OOP_GetMethodID(IID_Hidd_Gfx, moHidd_Gfx_GetMode);
944 OOP_DoMethod(gfx, (OOP_Msg)getmodemsg);
946 OOP_GetAttr(sync, aHidd_Sync_PixelClock, &pixel);
947 OOP_GetAttr(sync, aHidd_Sync_HDisp, &hdisp);
948 OOP_GetAttr(sync, aHidd_Sync_VDisp, &vdisp);
949 OOP_GetAttr(sync, aHidd_Sync_HSyncStart, &hstart);
950 OOP_GetAttr(sync, aHidd_Sync_VSyncStart, &vstart);
951 OOP_GetAttr(sync, aHidd_Sync_HSyncEnd, &hend);
952 OOP_GetAttr(sync, aHidd_Sync_VSyncEnd, &vend);
953 OOP_GetAttr(sync, aHidd_Sync_HTotal, &htotal);
954 OOP_GetAttr(sync, aHidd_Sync_VTotal, &vtotal);
956 D(bug("[IntelG45] Sync: %d, %d, %d, %d, %d, %d, %d, %d, %d\n",
957 pixel, hdisp, hstart, hend, htotal, vdisp, vstart, vend, vtotal));
959 if (bmdata->state && sd->VisibleBitmap != bmdata)
961 /* Suppose bm has properly allocated state structure */
962 if (bmdata->fbgfx)
964 bmdata->usecount++;
965 SetCursorPosition(sd,0,0);
966 LOCK_HW
967 sd->VisibleBitmap = bmdata;
968 G45_LoadState(sd, bmdata->state);
969 UNLOCK_HW
970 SetCursorPosition(sd,sd->pointerx,sd->pointery);
971 return TRUE;
975 return FALSE;
979 BOOL HIDD_INTELG45_SetFramebuffer(OOP_Object * bm)
981 OOP_Class * cl = OOP_OCLASS(bm);
982 GMABitMap_t * bmdata = OOP_INST_DATA(cl, bm);
983 //bug("[IntelG45] HIDD_INTELG45_SetFramebuffer %x %d,%d\n",bmdata,bmdata->xoffset,bmdata->yoffset);
984 if (bmdata->fbgfx)
986 char *linoff_reg = sd->Card.MMIO + ((sd->pipe == PIPE_A) ? G45_DSPALINOFF : G45_DSPBLINOFF);
987 char *stride_reg = sd->Card.MMIO + ((sd->pipe == PIPE_A) ? G45_DSPASTRIDE : G45_DSPBSTRIDE);
989 // bitmap width in bytes
990 writel( bmdata->state->dspstride , stride_reg );
992 // framebuffer address + possible xy offset
993 writel( bmdata->framebuffer - ( bmdata->yoffset * bmdata->pitch +
994 bmdata->xoffset * bmdata->bpp ) ,linoff_reg );
995 readl( linoff_reg );
996 return TRUE;
998 //bug("[IntelG45] HIDD_INTELG45_SetFramebuffer: not Framebuffer Bitmap!\n");
999 return FALSE;
1003 static struct HIDD_ModeProperties modeprops =
1005 DIPF_IS_SPRITES,
1007 COMPF_ABOVE
1010 ULONG METHOD(INTELG45, Hidd_Gfx, ModeProperties)
1012 ULONG len = msg->propsLen;
1013 if (len > sizeof(modeprops))
1014 len = sizeof(modeprops);
1015 CopyMem(&modeprops, msg->props, len);
1017 return len;
1020 static const struct OOP_MethodDescr INTELG45_Root_descr[] =
1022 {(OOP_MethodFunc)INTELG45__Root__New, moRoot_New},
1023 {(OOP_MethodFunc)INTELG45__Root__Get, moRoot_Get},
1024 {(OOP_MethodFunc)INTELG45__Root__Set, moRoot_Set},
1025 {NULL, 0}
1027 #define NUM_INTELG45_Root_METHODS 3
1029 static const struct OOP_MethodDescr INTELG45_Hidd_Gfx_descr[] =
1031 {(OOP_MethodFunc)INTELG45__Hidd_Gfx__CopyBox , moHidd_Gfx_CopyBox },
1032 {(OOP_MethodFunc)INTELG45__Hidd_Gfx__CreateObject , moHidd_Gfx_CreateObject },
1033 {(OOP_MethodFunc)INTELG45__Hidd_Gfx__SetCursorVisible, moHidd_Gfx_SetCursorVisible},
1034 {(OOP_MethodFunc)INTELG45__Hidd_Gfx__SetCursorPos , moHidd_Gfx_SetCursorPos },
1035 {(OOP_MethodFunc)INTELG45__Hidd_Gfx__SetCursorShape , moHidd_Gfx_SetCursorShape },
1036 {(OOP_MethodFunc)INTELG45__Hidd_Gfx__ShowViewPorts , moHidd_Gfx_ShowViewPorts },
1037 {(OOP_MethodFunc)INTELG45__Hidd_Gfx__ModeProperties , moHidd_Gfx_ModeProperties },
1038 {NULL, 0}
1040 #define NUM_INTELG45_Hidd_Gfx_METHODS 7
1042 const struct OOP_InterfaceDescr INTELG45_ifdescr[] =
1044 {INTELG45_Root_descr , IID_Root , NUM_INTELG45_Root_METHODS },
1045 {INTELG45_Hidd_Gfx_descr, IID_Hidd_Gfx, NUM_INTELG45_Hidd_Gfx_METHODS},
1046 {NULL , NULL , 0 }