corrections/consistency
[AROS.git] / workbench / devs / monitors / IntelGMA / intelgma_hiddclass.c
blob46845cdc7dd235d66ac195e980d72c9d7ec7fcab
1 /*
2 Copyright © 1995-2017, 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/gfx.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 "intelgma_hidd.h"
24 #include "intelG45_regs.h"
25 #include "intelgma_gallium.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 { aHidd_Name , (IPTR)"IntelGMA" },
554 { aHidd_HardwareName , (IPTR)"Intel GMA Display Adaptor" },
555 { aHidd_ProducerName , (IPTR)"Intel Corporation" },
556 { TAG_MORE, (IPTR)msg->attrList }
559 struct pRoot_New mymsg;
561 mymsg.mID = msg->mID;
562 mymsg.attrList = mytags;
564 msg = &mymsg;
566 o = (OOP_Object *)OOP_DoSuperMethod(cl, o, (OOP_Msg)msg);
567 if (o)
569 sd->GMAObject = o;
570 /* Create compositing object */
572 struct TagItem comptags [] =
574 { aHidd_Compositor_GfxHidd, (IPTR)o },
575 { TAG_DONE, TAG_DONE }
577 sd->compositing = OOP_NewObject(sd->compositingclass, NULL, comptags);
578 /* TODO: Check if object was created, how to handle ? */
582 FreeVecPooled(sd->MemPool, modetags);
583 FreeVecPooled(sd->MemPool, poolptr);
585 D(bug("[GMA] INTELG45::New() = %p\n", o));
587 return o;
590 void METHOD(INTELG45, Root, Get)
592 D(bug("[GMA] Root Get\n"));
594 uint32_t idx;
595 BOOL found = FALSE;
596 if (IS_GFX_ATTR(msg->attrID, idx))
598 switch (idx)
600 case aoHidd_Gfx_SupportsHWCursor:
601 *msg->storage = (IPTR)TRUE;
602 found = TRUE;
603 break;
605 case aoHidd_Gfx_NoFrameBuffer:
606 *msg->storage = (IPTR)TRUE;
607 found = TRUE;
608 break;
610 case aoHidd_Gfx_HWSpriteTypes:
611 *msg->storage = vHidd_SpriteType_DirectColor;
612 found = TRUE;
613 return;
615 case aoHidd_Gfx_DPMSLevel:
616 *msg->storage = SD(cl)->dpms;
617 found = TRUE;
618 break;
622 if (!found)
623 OOP_DoSuperMethod(cl, o, (OOP_Msg)msg);
625 return;
628 void METHOD(INTELG45, Root, Set)
630 D(bug("[GMA] Root Set\n"));
632 ULONG idx;
633 struct TagItem *tag;
634 struct TagItem *tags = msg->attrList;
636 while ((tag = NextTagItem(&tags)))
638 if (IS_GFX_ATTR(tag->ti_Tag, idx))
640 switch(idx)
642 case aoHidd_Gfx_DPMSLevel:
643 LOCK_HW
644 uint32_t adpa = readl(sd->Card.MMIO + G45_ADPA) & ~G45_ADPA_DPMS_MASK;
645 switch (tag->ti_Data)
647 case vHidd_Gfx_DPMSLevel_On:
648 adpa |= G45_ADPA_DPMS_ON;
649 break;
650 case vHidd_Gfx_DPMSLevel_Off:
651 adpa |= G45_ADPA_DPMS_OFF;
652 break;
653 case vHidd_Gfx_DPMSLevel_Standby:
654 adpa |= G45_ADPA_DPMS_STANDBY;
655 break;
656 case vHidd_Gfx_DPMSLevel_Suspend:
657 adpa |= G45_ADPA_DPMS_SUSPEND;
658 break;
660 writel(adpa, sd->Card.MMIO + G45_ADPA);
661 sd->dpms = tag->ti_Data;
663 UNLOCK_HW
664 break;
669 OOP_DoSuperMethod(cl, o, (OOP_Msg)msg);
673 OOP_Object * METHOD(INTELG45, Hidd_Gfx, CreateObject)
675 OOP_Object *object = NULL;
677 if (msg->cl == SD(cl)->basebm)
679 struct pHidd_Gfx_CreateObject mymsg;
680 HIDDT_ModeID modeid;
681 HIDDT_StdPixFmt stdpf;
683 struct TagItem mytags [] =
685 { TAG_IGNORE, TAG_IGNORE }, /* Placeholder for aHidd_BitMap_ClassPtr */
686 { TAG_IGNORE, TAG_IGNORE }, /* Placeholder for aHidd_BitMap_Align */
687 { aHidd_BitMap_IntelG45_CompositorHidd, (IPTR)sd->compositing },
688 { TAG_MORE, (IPTR)msg->attrList }
691 /* Check if user provided valid ModeID */
692 /* Check for framebuffer - not needed as IntelG45 is a NoFramebuffer driver */
693 /* Check for displayable - not needed - displayable has ModeID and we don't
694 distinguish between on-screen and off-screen bitmaps */
695 modeid = (HIDDT_ModeID)GetTagData(aHidd_BitMap_ModeID, vHidd_ModeID_Invalid, msg->attrList);
696 if (vHidd_ModeID_Invalid != modeid)
698 /* User supplied a valid modeid. We can use our bitmap class */
699 mytags[0].ti_Tag = aHidd_BitMap_ClassPtr;
700 mytags[0].ti_Data = (IPTR)SD(cl)->BMClass;
703 /* Check if bitmap is a planar bitmap */
704 stdpf = (HIDDT_StdPixFmt)GetTagData(aHidd_BitMap_StdPixFmt, vHidd_StdPixFmt_Unknown, msg->attrList);
705 if (vHidd_StdPixFmt_Plane == stdpf)
707 mytags[1].ti_Tag = aHidd_BitMap_Align;
708 mytags[1].ti_Data = 32;
711 /* We init a new message struct */
712 mymsg.mID = msg->mID;
713 mymsg.cl = msg->cl;
714 mymsg.attrList = mytags;
716 /* Pass the new message to the superclass */
717 object = (OOP_Object *)OOP_DoSuperMethod(cl, o, (OOP_Msg)&mymsg);
719 else if (SD(cl)->basegallium && (msg->cl == SD(cl)->basegallium))
721 object = OOP_NewObject(NULL, CLID_Hidd_Gallium_IntelGMA, msg->attrList);
723 else
724 object = (OOP_Object *)OOP_DoSuperMethod(cl, o, (OOP_Msg)msg);
726 return object;
730 void METHOD(INTELG45, Hidd_Gfx, SetCursorVisible)
732 sd->CursorVisible = msg->visible;
733 if (msg->visible)
735 writel( (sd->pipe == PIPE_A ? G45_CURCNTR_PIPE_A : G45_CURCNTR_PIPE_B ) | G45_CURCNTR_TYPE_ARGB ,
736 sd->Card.MMIO + (sd->pipe == PIPE_A ? G45_CURACNTR:G45_CURBCNTR));
738 else
740 writel( (sd->pipe == PIPE_A ? G45_CURCNTR_PIPE_A : G45_CURCNTR_PIPE_B ) | G45_CURCNTR_TYPE_OFF ,
741 sd->Card.MMIO + (sd->pipe == PIPE_A ? G45_CURACNTR:G45_CURBCNTR));
743 UpdateCursor(sd);
747 void METHOD(INTELG45, Hidd_Gfx, SetCursorPos)
749 SetCursorPosition(sd,msg->x,msg->y);
750 sd->pointerx = msg->x;
751 sd->pointery = msg->y;
754 BOOL METHOD(INTELG45, Hidd_Gfx, SetCursorShape)
756 if (msg->shape == NULL)
758 sd->CursorVisible = 0;
759 writel( (sd->pipe == PIPE_A ? G45_CURCNTR_PIPE_A : G45_CURCNTR_PIPE_B ) | G45_CURCNTR_TYPE_OFF ,
760 sd->Card.MMIO + (sd->pipe == PIPE_A ? G45_CURACNTR:G45_CURBCNTR));
762 else
764 IPTR width, height, x;
766 ULONG *curimg = (ULONG*)((IPTR)sd->CursorImage + (IPTR)sd->Card.Framebuffer);
768 OOP_GetAttr(msg->shape, aHidd_BitMap_Width, &width);
769 OOP_GetAttr(msg->shape, aHidd_BitMap_Height, &height);
771 if (width > 64) width = 64;
772 if (height > 64) height = 64;
774 for (x = 0; x < 64*64; x++)
775 curimg[x] = 0;
777 HIDD_BM_GetImage(msg->shape, (UBYTE *)curimg, 64*4, 0, 0, width, height, vHidd_StdPixFmt_BGRA32);
778 writel( (sd->pipe == PIPE_A ? G45_CURCNTR_PIPE_A : G45_CURCNTR_PIPE_B ) | G45_CURCNTR_TYPE_ARGB ,
779 sd->Card.MMIO + (sd->pipe == PIPE_A ? G45_CURACNTR:G45_CURBCNTR));
781 UpdateCursor(sd);
783 return TRUE;
786 void METHOD(INTELG45, Hidd_Gfx, CopyBox)
788 ULONG mode = GC_DRMD(msg->gc);
789 IPTR src=0, dst=0;
791 /* Check whether we can get Drawable attribute of our GMA class */
792 OOP_GetAttr(msg->src, aHidd_GMABitMap_Drawable, &src);
793 OOP_GetAttr(msg->dest, aHidd_GMABitMap_Drawable, &dst);
795 if (!dst || !src)
797 /* No. One of the bitmaps is not a GMA bitmap */
798 OOP_DoSuperMethod(cl, o, (OOP_Msg)msg);
800 else
802 /* Yes. Get the instance data of both bitmaps */
803 GMABitMap_t *bm_src = OOP_INST_DATA(OOP_OCLASS(msg->src), msg->src);
804 GMABitMap_t *bm_dst = OOP_INST_DATA(OOP_OCLASS(msg->dest), msg->dest);
806 // D(bug("[GMA] CopyBox(src(%p,%d:%d@%d),dst(%p,%d:%d@%d),%d:%d\n",
807 // bm_src->framebuffer,msg->srcX,msg->srcY,bm_src->depth,
808 // bm_dst->framebuffer,msg->destX,msg->destY,bm_dst->depth,
809 // msg->width, msg->height));
811 /* Case -1: (To be fixed) one of the bitmaps have chunky outside GFX mem */
812 if (!bm_src->fbgfx || !bm_dst->fbgfx)
814 D(bug("[GMA] one of bitmaps outside VRAM! CopyBox(src(%p,%d:%d@%d),dst(%p,%d:%d@%d),%d:%d\n",
815 bm_src->framebuffer,msg->srcX,msg->srcY,bm_src->depth,
816 bm_dst->framebuffer,msg->destX,msg->destY,bm_dst->depth,
817 msg->width, msg->height));
819 OOP_DoSuperMethod(cl, o, (OOP_Msg)msg);
821 /* Case 0: one of bitmaps is 8bpp, whereas the other is TrueColor one */
822 else if ((bm_src->depth <= 8 || bm_dst->depth <= 8) &&
823 (bm_src->depth != bm_dst->depth))
825 /* Unsupported case */
826 OOP_DoSuperMethod(cl, o, (OOP_Msg)msg);
827 return;
829 /* Case 1: both bitmaps have the same depth - use Blit engine */
830 else if (bm_src->depth == bm_dst->depth)
832 LOCK_MULTI_BITMAP
833 LOCK_BITMAP_BM(bm_src)
834 LOCK_BITMAP_BM(bm_dst)
835 UNLOCK_MULTI_BITMAP
837 LOCK_HW
839 uint32_t br00, br13, br22, br23, br09, br11, br26, br12;
841 br00 = (2 << 29) | (0x53 << 22) | (6);
842 if (bm_dst->bpp == 4)
843 br00 |= 3 << 20;
845 br13 = bm_dst->pitch | ROP_table[mode].rop;
846 if (bm_dst->bpp == 4)
847 br13 |= 3 << 24;
848 else if (bm_dst->bpp == 2)
849 br13 |= 1 << 24;
851 br22 = msg->destX | (msg->destY << 16);
852 br23 = (msg->destX + msg->width) | (msg->destY + msg->height) << 16;
853 br09 = bm_dst->framebuffer;
854 br11 = bm_src->pitch;
855 br26 = msg->srcX | (msg->srcY << 16);
856 br12 = bm_src->framebuffer;
858 START_RING(8);
860 OUT_RING(br00);
861 OUT_RING(br13);
862 OUT_RING(br22);
863 OUT_RING(br23);
864 OUT_RING(br09);
865 OUT_RING(br26);
866 OUT_RING(br11);
867 OUT_RING(br12);
869 ADVANCE_RING();
871 DO_FLUSH();
872 UNLOCK_HW
874 UNLOCK_BITMAP_BM(bm_src)
875 UNLOCK_BITMAP_BM(bm_dst)
877 else /* Case 2: different bitmaps.Use 3d hardware. */
879 D(bug("[GMA] Depth mismatch! CopyBox(src(%p,%d:%d@%d),dst(%p,%d:%d@%d),%d:%d\n",
880 bm_src->framebuffer,msg->srcX,msg->srcY,bm_src->depth,
881 bm_dst->framebuffer,msg->destX,msg->destY,bm_dst->depth,
882 msg->width, msg->height));
884 LOCK_MULTI_BITMAP
885 LOCK_BITMAP_BM(bm_src)
886 LOCK_BITMAP_BM(bm_dst)
887 UNLOCK_MULTI_BITMAP
889 BOOL done = copybox3d( bm_dst, bm_src,
890 msg->destX, msg->destY, msg->width, msg->height,
891 msg->srcX, msg->srcY, msg->width, msg->height );
893 UNLOCK_BITMAP_BM(bm_src)
894 UNLOCK_BITMAP_BM(bm_dst)
896 if( ! done ) OOP_DoSuperMethod(cl, o, (OOP_Msg)msg);
901 ULONG METHOD(INTELG45, Hidd_Gfx, ShowViewPorts)
903 struct pHidd_Compositor_BitMapStackChanged bscmsg =
905 mID : OOP_GetMethodID(IID_Hidd_Compositor, moHidd_Compositor_BitMapStackChanged),
906 data : msg->Data
908 D(bug("[IntelG45] ShowViewPorts enter TopLevelBM %x\n", msg->Data->Bitmap));
909 OOP_DoMethod(sd->compositor, (OOP_Msg)&bscmsg);
910 return TRUE; /* Indicate driver supports this method */
913 BOOL HIDD_INTELG45_SwitchToVideoMode(OOP_Object * bm)
915 OOP_Class * cl = OOP_OCLASS(bm);
916 GMABitMap_t * bmdata = OOP_INST_DATA(cl, bm);
917 OOP_Object * gfx = NULL;
918 HIDDT_ModeID modeid;
919 OOP_Object * sync;
920 OOP_Object * pf;
921 IPTR pixel, e;
922 IPTR hdisp, vdisp, hstart, hend, htotal, vstart, vend, vtotal;
924 OOP_GetAttr(bm, aHidd_BitMap_GfxHidd, &e);
925 gfx = (OOP_Object *)e;
927 bug("[IntelG45] HIDD_INTELG45_SwitchToVideoMode bitmap:%x\n",bmdata);
929 /* We should be able to get modeID from the bitmap */
930 OOP_GetAttr(bm, aHidd_BitMap_ModeID, &modeid);
932 if (modeid == vHidd_ModeID_Invalid)
934 D(bug("[IntelG45] Invalid ModeID\n"));
935 return FALSE;
938 /* Get Sync and PixelFormat properties */
939 struct pHidd_Gfx_GetMode __getmodemsg =
941 modeID: modeid,
942 syncPtr: &sync,
943 pixFmtPtr: &pf,
944 }, *getmodemsg = &__getmodemsg;
946 getmodemsg->mID = OOP_GetMethodID(IID_Hidd_Gfx, moHidd_Gfx_GetMode);
947 OOP_DoMethod(gfx, (OOP_Msg)getmodemsg);
949 OOP_GetAttr(sync, aHidd_Sync_PixelClock, &pixel);
950 OOP_GetAttr(sync, aHidd_Sync_HDisp, &hdisp);
951 OOP_GetAttr(sync, aHidd_Sync_VDisp, &vdisp);
952 OOP_GetAttr(sync, aHidd_Sync_HSyncStart, &hstart);
953 OOP_GetAttr(sync, aHidd_Sync_VSyncStart, &vstart);
954 OOP_GetAttr(sync, aHidd_Sync_HSyncEnd, &hend);
955 OOP_GetAttr(sync, aHidd_Sync_VSyncEnd, &vend);
956 OOP_GetAttr(sync, aHidd_Sync_HTotal, &htotal);
957 OOP_GetAttr(sync, aHidd_Sync_VTotal, &vtotal);
959 D(bug("[IntelG45] Sync: %d, %d, %d, %d, %d, %d, %d, %d, %d\n",
960 pixel, hdisp, hstart, hend, htotal, vdisp, vstart, vend, vtotal));
962 if (bmdata->state && sd->VisibleBitmap != bmdata)
964 /* Suppose bm has properly allocated state structure */
965 if (bmdata->fbgfx)
967 bmdata->usecount++;
968 SetCursorPosition(sd,0,0);
969 LOCK_HW
970 sd->VisibleBitmap = bmdata;
971 G45_LoadState(sd, bmdata->state);
972 UNLOCK_HW
973 SetCursorPosition(sd,sd->pointerx,sd->pointery);
974 return TRUE;
978 return FALSE;
982 BOOL HIDD_INTELG45_SetFramebuffer(OOP_Object * bm)
984 OOP_Class * cl = OOP_OCLASS(bm);
985 GMABitMap_t * bmdata = OOP_INST_DATA(cl, bm);
986 //bug("[IntelG45] HIDD_INTELG45_SetFramebuffer %x %d,%d\n",bmdata,bmdata->xoffset,bmdata->yoffset);
987 if (bmdata->fbgfx)
989 char *linoff_reg = sd->Card.MMIO + ((sd->pipe == PIPE_A) ? G45_DSPALINOFF : G45_DSPBLINOFF);
990 char *stride_reg = sd->Card.MMIO + ((sd->pipe == PIPE_A) ? G45_DSPASTRIDE : G45_DSPBSTRIDE);
992 // bitmap width in bytes
993 writel( bmdata->state->dspstride , stride_reg );
995 // framebuffer address + possible xy offset
996 writel( bmdata->framebuffer - ( bmdata->yoffset * bmdata->pitch +
997 bmdata->xoffset * bmdata->bpp ) ,linoff_reg );
998 readl( linoff_reg );
999 return TRUE;
1001 //bug("[IntelG45] HIDD_INTELG45_SetFramebuffer: not Framebuffer Bitmap!\n");
1002 return FALSE;
1006 static struct HIDD_ModeProperties modeprops =
1008 DIPF_IS_SPRITES,
1010 COMPF_ABOVE
1013 ULONG METHOD(INTELG45, Hidd_Gfx, ModeProperties)
1015 ULONG len = msg->propsLen;
1016 if (len > sizeof(modeprops))
1017 len = sizeof(modeprops);
1018 CopyMem(&modeprops, msg->props, len);
1020 return len;
1023 static const struct OOP_MethodDescr INTELG45_Root_descr[] =
1025 {(OOP_MethodFunc)INTELG45__Root__New, moRoot_New},
1026 {(OOP_MethodFunc)INTELG45__Root__Get, moRoot_Get},
1027 {(OOP_MethodFunc)INTELG45__Root__Set, moRoot_Set},
1028 {NULL, 0}
1030 #define NUM_INTELG45_Root_METHODS 3
1032 static const struct OOP_MethodDescr INTELG45_Hidd_Gfx_descr[] =
1034 {(OOP_MethodFunc)INTELG45__Hidd_Gfx__CopyBox , moHidd_Gfx_CopyBox },
1035 {(OOP_MethodFunc)INTELG45__Hidd_Gfx__CreateObject , moHidd_Gfx_CreateObject },
1036 {(OOP_MethodFunc)INTELG45__Hidd_Gfx__SetCursorVisible, moHidd_Gfx_SetCursorVisible},
1037 {(OOP_MethodFunc)INTELG45__Hidd_Gfx__SetCursorPos , moHidd_Gfx_SetCursorPos },
1038 {(OOP_MethodFunc)INTELG45__Hidd_Gfx__SetCursorShape , moHidd_Gfx_SetCursorShape },
1039 {(OOP_MethodFunc)INTELG45__Hidd_Gfx__ShowViewPorts , moHidd_Gfx_ShowViewPorts },
1040 {(OOP_MethodFunc)INTELG45__Hidd_Gfx__ModeProperties , moHidd_Gfx_ModeProperties },
1041 {NULL, 0}
1043 #define NUM_INTELG45_Hidd_Gfx_METHODS 7
1045 const struct OOP_InterfaceDescr INTELG45_ifdescr[] =
1047 {INTELG45_Root_descr , IID_Root , NUM_INTELG45_Root_METHODS },
1048 {INTELG45_Hidd_Gfx_descr, IID_Hidd_Gfx, NUM_INTELG45_Hidd_Gfx_METHODS},
1049 {NULL , NULL , 0 }