revert between 56095 -> 55830 in arch
[AROS.git] / workbench / devs / monitors / IntelGMA / intelgma_hiddclass.c
bloba48dc5fe4ebb930b48754974c9f6178929ff580f
1 /*
2 Copyright © 1995-2019, 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 *i2cBus = NULL;
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
518 i2cBus = OOP_NewObject(sd->IntelI2C, NULL, i2c_attrs);
520 if (i2cBus)
522 if (HIDD_I2C_ProbeAddress(i2cBus, 0xa0))
524 struct TagItem attrs[] = {
525 { aHidd_I2CDevice_Driver, (IPTR)i2cBus },
526 { aHidd_I2CDevice_Address, 0xa0 },
527 { aHidd_I2CDevice_Name, (IPTR)"Display" },
528 { TAG_DONE, 0UL }
531 D(bug("[GMA] I2C display device found\n"));
533 OOP_Object *i2cDev = OOP_NewObject(NULL, CLID_Hidd_I2CDevice, attrs);
535 if (i2cDev)
537 G45_parse_ddc(cl, &tags, poolptr, i2cDev);
544 tags->ti_Tag = TAG_DONE;
545 tags->ti_Data = 0;
547 struct TagItem mytags[] = {
548 { aHidd_Gfx_ModeTags, (IPTR)modetags },
549 { aHidd_Name , (IPTR)"IntelGMA" },
550 { aHidd_HardwareName , (IPTR)"Intel GMA Display Adaptor" },
551 { aHidd_ProducerName , (IPTR)"Intel Corporation" },
552 { TAG_MORE, (IPTR)msg->attrList }
555 struct pRoot_New mymsg;
557 mymsg.mID = msg->mID;
558 mymsg.attrList = mytags;
560 msg = &mymsg;
562 o = (OOP_Object *)OOP_DoSuperMethod(cl, o, (OOP_Msg)msg);
563 if (o)
565 struct g45data * gfxdata = OOP_INST_DATA(cl, o);
566 gfxdata->i2cobj = i2cBus;
567 sd->GMAObject = o;
569 /* Create compositor object */
571 struct TagItem comptags [] =
573 { aHidd_Compositor_GfxHidd, (IPTR)o },
574 { TAG_DONE, TAG_DONE }
576 sd->compositor = OOP_NewObject(sd->compositorclass, NULL, comptags);
577 /* TODO: Check if object was created, how to handle ? */
581 FreeVecPooled(sd->MemPool, modetags);
582 FreeVecPooled(sd->MemPool, poolptr);
584 D(bug("[GMA] INTELG45::New() = %p\n", o));
586 return o;
589 void METHOD(INTELG45, Root, Get)
591 D(bug("[GMA] Root Get\n"));
593 uint32_t idx;
594 BOOL found = FALSE;
595 if (IS_GFX_ATTR(msg->attrID, idx))
597 switch (idx)
599 case aoHidd_Gfx_SupportsHWCursor:
600 *msg->storage = (IPTR)TRUE;
601 found = TRUE;
602 break;
604 case aoHidd_Gfx_NoFrameBuffer:
605 *msg->storage = (IPTR)TRUE;
606 found = TRUE;
607 break;
609 case aoHidd_Gfx_HWSpriteTypes:
610 *msg->storage = vHidd_SpriteType_DirectColor;
611 found = TRUE;
612 return;
614 case aoHidd_Gfx_DPMSLevel:
615 *msg->storage = SD(cl)->dpms;
616 found = TRUE;
617 break;
621 if (!found)
622 OOP_DoSuperMethod(cl, o, (OOP_Msg)msg);
624 return;
627 void METHOD(INTELG45, Root, Set)
629 D(bug("[GMA] Root Set\n"));
631 ULONG idx;
632 struct TagItem *tag;
633 struct TagItem *tags = msg->attrList;
635 while ((tag = NextTagItem(&tags)))
637 if (IS_GFX_ATTR(tag->ti_Tag, idx))
639 switch(idx)
641 case aoHidd_Gfx_DPMSLevel:
642 LOCK_HW
643 uint32_t adpa = readl(sd->Card.MMIO + G45_ADPA) & ~G45_ADPA_DPMS_MASK;
644 switch (tag->ti_Data)
646 case vHidd_Gfx_DPMSLevel_On:
647 adpa |= G45_ADPA_DPMS_ON;
648 break;
649 case vHidd_Gfx_DPMSLevel_Off:
650 adpa |= G45_ADPA_DPMS_OFF;
651 break;
652 case vHidd_Gfx_DPMSLevel_Standby:
653 adpa |= G45_ADPA_DPMS_STANDBY;
654 break;
655 case vHidd_Gfx_DPMSLevel_Suspend:
656 adpa |= G45_ADPA_DPMS_SUSPEND;
657 break;
659 writel(adpa, sd->Card.MMIO + G45_ADPA);
660 sd->dpms = tag->ti_Data;
662 UNLOCK_HW
663 break;
668 OOP_DoSuperMethod(cl, o, (OOP_Msg)msg);
672 OOP_Object * METHOD(INTELG45, Hidd_Gfx, CreateObject)
674 OOP_Object *object = NULL;
676 if (msg->cl == SD(cl)->basebm)
678 struct pHidd_Gfx_CreateObject mymsg;
679 HIDDT_ModeID modeid;
680 HIDDT_StdPixFmt stdpf;
682 struct TagItem mytags [] =
684 { TAG_IGNORE, TAG_IGNORE }, /* Placeholder for aHidd_BitMap_ClassPtr */
685 { TAG_IGNORE, TAG_IGNORE }, /* Placeholder for aHidd_BitMap_Align */
686 { aHidd_BitMap_IntelG45_CompositorHidd, (IPTR)sd->compositor },
687 { TAG_MORE, (IPTR)msg->attrList }
690 /* Check if user provided valid ModeID */
691 /* Check for framebuffer - not needed as IntelG45 is a NoFramebuffer driver */
692 /* Check for displayable - not needed - displayable has ModeID and we don't
693 distinguish between on-screen and off-screen bitmaps */
694 modeid = (HIDDT_ModeID)GetTagData(aHidd_BitMap_ModeID, vHidd_ModeID_Invalid, msg->attrList);
695 if (vHidd_ModeID_Invalid != modeid)
697 /* User supplied a valid modeid. We can use our bitmap class */
698 mytags[0].ti_Tag = aHidd_BitMap_ClassPtr;
699 mytags[0].ti_Data = (IPTR)SD(cl)->BMClass;
702 /* Check if bitmap is a planar bitmap */
703 stdpf = (HIDDT_StdPixFmt)GetTagData(aHidd_BitMap_StdPixFmt, vHidd_StdPixFmt_Unknown, msg->attrList);
704 if (vHidd_StdPixFmt_Plane == stdpf)
706 mytags[1].ti_Tag = aHidd_BitMap_Align;
707 mytags[1].ti_Data = 32;
710 /* We init a new message struct */
711 mymsg.mID = msg->mID;
712 mymsg.cl = msg->cl;
713 mymsg.attrList = mytags;
715 /* Pass the new message to the superclass */
716 object = (OOP_Object *)OOP_DoSuperMethod(cl, o, (OOP_Msg)&mymsg);
718 else if (SD(cl)->basegallium && (msg->cl == SD(cl)->basegallium))
720 /* Create the gallium 3d driver object .. */
721 object = OOP_NewObject(NULL, CLID_Hidd_Gallium_IntelGMA, msg->attrList);
723 else if (SD(cl)->basei2c && (msg->cl == SD(cl)->basei2c))
725 struct g45data * gfxdata = OOP_INST_DATA(cl, o);
726 /* Expose the i2c bus object .. */
727 object = gfxdata->i2cobj;
729 else
730 object = (OOP_Object *)OOP_DoSuperMethod(cl, o, (OOP_Msg)msg);
732 return object;
736 void METHOD(INTELG45, Hidd_Gfx, SetCursorVisible)
738 sd->CursorVisible = msg->visible;
739 if (msg->visible)
741 writel( (sd->pipe == PIPE_A ? G45_CURCNTR_PIPE_A : G45_CURCNTR_PIPE_B ) | G45_CURCNTR_TYPE_ARGB ,
742 sd->Card.MMIO + (sd->pipe == PIPE_A ? G45_CURACNTR:G45_CURBCNTR));
744 else
746 writel( (sd->pipe == PIPE_A ? G45_CURCNTR_PIPE_A : G45_CURCNTR_PIPE_B ) | G45_CURCNTR_TYPE_OFF ,
747 sd->Card.MMIO + (sd->pipe == PIPE_A ? G45_CURACNTR:G45_CURBCNTR));
749 UpdateCursor(sd);
753 void METHOD(INTELG45, Hidd_Gfx, SetCursorPos)
755 SetCursorPosition(sd,msg->x,msg->y);
756 sd->pointerx = msg->x;
757 sd->pointery = msg->y;
760 BOOL METHOD(INTELG45, Hidd_Gfx, SetCursorShape)
762 if (msg->shape == NULL)
764 sd->CursorVisible = 0;
765 writel( (sd->pipe == PIPE_A ? G45_CURCNTR_PIPE_A : G45_CURCNTR_PIPE_B ) | G45_CURCNTR_TYPE_OFF ,
766 sd->Card.MMIO + (sd->pipe == PIPE_A ? G45_CURACNTR:G45_CURBCNTR));
768 else
770 IPTR width, height, x;
772 ULONG *curimg = (ULONG*)((IPTR)sd->CursorImage + (IPTR)sd->Card.Framebuffer);
774 OOP_GetAttr(msg->shape, aHidd_BitMap_Width, &width);
775 OOP_GetAttr(msg->shape, aHidd_BitMap_Height, &height);
777 if (width > 64) width = 64;
778 if (height > 64) height = 64;
780 for (x = 0; x < 64*64; x++)
781 curimg[x] = 0;
783 HIDD_BM_GetImage(msg->shape, (UBYTE *)curimg, 64*4, 0, 0, width, height, vHidd_StdPixFmt_BGRA32);
784 writel( (sd->pipe == PIPE_A ? G45_CURCNTR_PIPE_A : G45_CURCNTR_PIPE_B ) | G45_CURCNTR_TYPE_ARGB ,
785 sd->Card.MMIO + (sd->pipe == PIPE_A ? G45_CURACNTR:G45_CURBCNTR));
787 UpdateCursor(sd);
789 return TRUE;
792 void METHOD(INTELG45, Hidd_Gfx, CopyBox)
794 ULONG mode = GC_DRMD(msg->gc);
795 IPTR src=0, dst=0;
797 /* Check whether we can get Drawable attribute of our GMA class */
798 OOP_GetAttr(msg->src, aHidd_GMABitMap_Drawable, &src);
799 OOP_GetAttr(msg->dest, aHidd_GMABitMap_Drawable, &dst);
801 if (!dst || !src)
803 /* No. One of the bitmaps is not a GMA bitmap */
804 OOP_DoSuperMethod(cl, o, (OOP_Msg)msg);
806 else
808 /* Yes. Get the instance data of both bitmaps */
809 GMABitMap_t *bm_src = OOP_INST_DATA(OOP_OCLASS(msg->src), msg->src);
810 GMABitMap_t *bm_dst = OOP_INST_DATA(OOP_OCLASS(msg->dest), msg->dest);
812 // D(bug("[GMA] CopyBox(src(%p,%d:%d@%d),dst(%p,%d:%d@%d),%d:%d\n",
813 // bm_src->framebuffer,msg->srcX,msg->srcY,bm_src->depth,
814 // bm_dst->framebuffer,msg->destX,msg->destY,bm_dst->depth,
815 // msg->width, msg->height));
817 /* Case -1: (To be fixed) one of the bitmaps have chunky outside GFX mem */
818 if (!bm_src->fbgfx || !bm_dst->fbgfx)
820 D(bug("[GMA] one of bitmaps outside VRAM! CopyBox(src(%p,%d:%d@%d),dst(%p,%d:%d@%d),%d:%d\n",
821 bm_src->framebuffer,msg->srcX,msg->srcY,bm_src->depth,
822 bm_dst->framebuffer,msg->destX,msg->destY,bm_dst->depth,
823 msg->width, msg->height));
825 OOP_DoSuperMethod(cl, o, (OOP_Msg)msg);
827 /* Case 0: one of bitmaps is 8bpp, whereas the other is TrueColor one */
828 else if ((bm_src->depth <= 8 || bm_dst->depth <= 8) &&
829 (bm_src->depth != bm_dst->depth))
831 /* Unsupported case */
832 OOP_DoSuperMethod(cl, o, (OOP_Msg)msg);
833 return;
835 /* Case 1: both bitmaps have the same depth - use Blit engine */
836 else if (bm_src->depth == bm_dst->depth)
838 LOCK_MULTI_BITMAP
839 LOCK_BITMAP_BM(bm_src)
840 LOCK_BITMAP_BM(bm_dst)
841 UNLOCK_MULTI_BITMAP
843 LOCK_HW
845 uint32_t br00, br13, br22, br23, br09, br11, br26, br12;
847 br00 = (2 << 29) | (0x53 << 22) | (6);
848 if (bm_dst->bpp == 4)
849 br00 |= 3 << 20;
851 br13 = bm_dst->pitch | ROP_table[mode].rop;
852 if (bm_dst->bpp == 4)
853 br13 |= 3 << 24;
854 else if (bm_dst->bpp == 2)
855 br13 |= 1 << 24;
857 br22 = msg->destX | (msg->destY << 16);
858 br23 = (msg->destX + msg->width) | (msg->destY + msg->height) << 16;
859 br09 = bm_dst->framebuffer;
860 br11 = bm_src->pitch;
861 br26 = msg->srcX | (msg->srcY << 16);
862 br12 = bm_src->framebuffer;
864 START_RING(8);
866 OUT_RING(br00);
867 OUT_RING(br13);
868 OUT_RING(br22);
869 OUT_RING(br23);
870 OUT_RING(br09);
871 OUT_RING(br26);
872 OUT_RING(br11);
873 OUT_RING(br12);
875 ADVANCE_RING();
877 DO_FLUSH();
878 UNLOCK_HW
880 UNLOCK_BITMAP_BM(bm_src)
881 UNLOCK_BITMAP_BM(bm_dst)
883 else /* Case 2: different bitmaps.Use 3d hardware. */
885 D(bug("[GMA] Depth mismatch! CopyBox(src(%p,%d:%d@%d),dst(%p,%d:%d@%d),%d:%d\n",
886 bm_src->framebuffer,msg->srcX,msg->srcY,bm_src->depth,
887 bm_dst->framebuffer,msg->destX,msg->destY,bm_dst->depth,
888 msg->width, msg->height));
890 LOCK_MULTI_BITMAP
891 LOCK_BITMAP_BM(bm_src)
892 LOCK_BITMAP_BM(bm_dst)
893 UNLOCK_MULTI_BITMAP
895 BOOL done = copybox3d( bm_dst, bm_src,
896 msg->destX, msg->destY, msg->width, msg->height,
897 msg->srcX, msg->srcY, msg->width, msg->height );
899 UNLOCK_BITMAP_BM(bm_src)
900 UNLOCK_BITMAP_BM(bm_dst)
902 if( ! done ) OOP_DoSuperMethod(cl, o, (OOP_Msg)msg);
907 ULONG METHOD(INTELG45, Hidd_Gfx, ShowViewPorts)
909 struct pHidd_Compositor_BitMapStackChanged bscmsg =
911 mID : OOP_GetMethodID(IID_Hidd_Compositor, moHidd_Compositor_BitMapStackChanged),
912 data : msg->Data
914 D(bug("[IntelG45] ShowViewPorts enter TopLevelBM %x\n", msg->Data->Bitmap));
915 OOP_DoMethod(sd->compositor, (OOP_Msg)&bscmsg);
916 return TRUE; /* Indicate driver supports this method */
919 BOOL HIDD_INTELG45_SwitchToVideoMode(OOP_Object * bm)
921 OOP_Class * cl = OOP_OCLASS(bm);
922 GMABitMap_t * bmdata = OOP_INST_DATA(cl, bm);
923 OOP_Object * gfx = NULL;
924 HIDDT_ModeID modeid;
925 OOP_Object * sync;
926 OOP_Object * pf;
927 IPTR pixel, e;
928 IPTR hdisp, vdisp, hstart, hend, htotal, vstart, vend, vtotal;
930 OOP_GetAttr(bm, aHidd_BitMap_GfxHidd, &e);
931 gfx = (OOP_Object *)e;
933 bug("[IntelG45] HIDD_INTELG45_SwitchToVideoMode bitmap:%x\n",bmdata);
935 /* We should be able to get modeID from the bitmap */
936 OOP_GetAttr(bm, aHidd_BitMap_ModeID, &modeid);
938 if (modeid == vHidd_ModeID_Invalid)
940 D(bug("[IntelG45] Invalid ModeID\n"));
941 return FALSE;
944 /* Get Sync and PixelFormat properties */
945 struct pHidd_Gfx_GetMode __getmodemsg =
947 modeID: modeid,
948 syncPtr: &sync,
949 pixFmtPtr: &pf,
950 }, *getmodemsg = &__getmodemsg;
952 getmodemsg->mID = OOP_GetMethodID(IID_Hidd_Gfx, moHidd_Gfx_GetMode);
953 OOP_DoMethod(gfx, (OOP_Msg)getmodemsg);
955 OOP_GetAttr(sync, aHidd_Sync_PixelClock, &pixel);
956 OOP_GetAttr(sync, aHidd_Sync_HDisp, &hdisp);
957 OOP_GetAttr(sync, aHidd_Sync_VDisp, &vdisp);
958 OOP_GetAttr(sync, aHidd_Sync_HSyncStart, &hstart);
959 OOP_GetAttr(sync, aHidd_Sync_VSyncStart, &vstart);
960 OOP_GetAttr(sync, aHidd_Sync_HSyncEnd, &hend);
961 OOP_GetAttr(sync, aHidd_Sync_VSyncEnd, &vend);
962 OOP_GetAttr(sync, aHidd_Sync_HTotal, &htotal);
963 OOP_GetAttr(sync, aHidd_Sync_VTotal, &vtotal);
965 D(bug("[IntelG45] Sync: %d, %d, %d, %d, %d, %d, %d, %d, %d\n",
966 pixel, hdisp, hstart, hend, htotal, vdisp, vstart, vend, vtotal));
968 if (bmdata->state && sd->VisibleBitmap != bmdata)
970 /* Suppose bm has properly allocated state structure */
971 if (bmdata->fbgfx)
973 bmdata->usecount++;
974 SetCursorPosition(sd,0,0);
975 LOCK_HW
976 sd->VisibleBitmap = bmdata;
977 G45_LoadState(sd, bmdata->state);
978 UNLOCK_HW
979 SetCursorPosition(sd,sd->pointerx,sd->pointery);
980 return TRUE;
984 return FALSE;
988 BOOL HIDD_INTELG45_SetFramebuffer(OOP_Object * bm)
990 OOP_Class * cl = OOP_OCLASS(bm);
991 GMABitMap_t * bmdata = OOP_INST_DATA(cl, bm);
992 //bug("[IntelG45] HIDD_INTELG45_SetFramebuffer %x %d,%d\n",bmdata,bmdata->xoffset,bmdata->yoffset);
993 if (bmdata->fbgfx)
995 char *linoff_reg = sd->Card.MMIO + ((sd->pipe == PIPE_A) ? G45_DSPALINOFF : G45_DSPBLINOFF);
996 char *stride_reg = sd->Card.MMIO + ((sd->pipe == PIPE_A) ? G45_DSPASTRIDE : G45_DSPBSTRIDE);
998 // bitmap width in bytes
999 writel( bmdata->state->dspstride , stride_reg );
1001 // framebuffer address + possible xy offset
1002 writel( bmdata->framebuffer - ( bmdata->yoffset * bmdata->pitch +
1003 bmdata->xoffset * bmdata->bpp ) ,linoff_reg );
1004 readl( linoff_reg );
1005 return TRUE;
1007 //bug("[IntelG45] HIDD_INTELG45_SetFramebuffer: not Framebuffer Bitmap!\n");
1008 return FALSE;
1012 static struct HIDD_ModeProperties modeprops =
1014 DIPF_IS_SPRITES,
1016 COMPF_ABOVE
1019 ULONG METHOD(INTELG45, Hidd_Gfx, ModeProperties)
1021 ULONG len = msg->propsLen;
1022 if (len > sizeof(modeprops))
1023 len = sizeof(modeprops);
1024 CopyMem(&modeprops, msg->props, len);
1026 return len;
1029 static const struct OOP_MethodDescr INTELG45_Root_descr[] =
1031 {(OOP_MethodFunc)INTELG45__Root__New, moRoot_New},
1032 {(OOP_MethodFunc)INTELG45__Root__Get, moRoot_Get},
1033 {(OOP_MethodFunc)INTELG45__Root__Set, moRoot_Set},
1034 {NULL, 0}
1036 #define NUM_INTELG45_Root_METHODS 3
1038 static const struct OOP_MethodDescr INTELG45_Hidd_Gfx_descr[] =
1040 {(OOP_MethodFunc)INTELG45__Hidd_Gfx__CopyBox , moHidd_Gfx_CopyBox },
1041 {(OOP_MethodFunc)INTELG45__Hidd_Gfx__CreateObject , moHidd_Gfx_CreateObject },
1042 {(OOP_MethodFunc)INTELG45__Hidd_Gfx__SetCursorVisible, moHidd_Gfx_SetCursorVisible},
1043 {(OOP_MethodFunc)INTELG45__Hidd_Gfx__SetCursorPos , moHidd_Gfx_SetCursorPos },
1044 {(OOP_MethodFunc)INTELG45__Hidd_Gfx__SetCursorShape , moHidd_Gfx_SetCursorShape },
1045 {(OOP_MethodFunc)INTELG45__Hidd_Gfx__ShowViewPorts , moHidd_Gfx_ShowViewPorts },
1046 {(OOP_MethodFunc)INTELG45__Hidd_Gfx__ModeProperties , moHidd_Gfx_ModeProperties },
1047 {NULL, 0}
1049 #define NUM_INTELG45_Hidd_Gfx_METHODS 7
1051 const struct OOP_InterfaceDescr INTELG45_ifdescr[] =
1053 {INTELG45_Root_descr , IID_Root , NUM_INTELG45_Root_METHODS },
1054 {INTELG45_Hidd_Gfx_descr, IID_Hidd_Gfx, NUM_INTELG45_Hidd_Gfx_METHODS},
1055 {NULL , NULL , 0 }