- Fixed potential memory leaks and use of freed memory.
[AROS.git] / workbench / devs / monitors / IntelGMA / intelG45_lowlevel.c
blob4818c4cdb3af7d7a463cf3292397b46fbca0d2fd
1 /*
2 Copyright © 2010-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 <proto/oop.h>
16 #include <proto/exec.h>
17 #include <proto/utility.h>
19 #include <stdint.h>
20 #include <stdlib.h>
22 #include "intelG45_intern.h"
23 #include "intelG45_regs.h"
25 typedef struct {
26 uint8_t N;
27 uint8_t M1;
28 uint8_t M2;
29 uint8_t P1;
30 uint8_t P2;
31 uint32_t VCO;
32 uint32_t PixelClock;
33 } GMA_PLL_t;
35 VOID delay_ms(struct g45staticdata *sd, uint32_t msec)
37 /* Take MsgPort over by current task */
38 sd->tr->tr_node.io_Message.mn_ReplyPort->mp_SigBit = SIGB_SINGLE;
39 sd->tr->tr_node.io_Message.mn_ReplyPort->mp_SigTask = FindTask(NULL);
41 /* Specify the request */
42 sd->tr->tr_node.io_Command = TR_ADDREQUEST;
43 sd->tr->tr_time.tv_secs = msec / 1000;
44 sd->tr->tr_time.tv_micro = 1000 * (msec % 1000);
46 /* Wait */
47 DoIO(&sd->tr->tr_node);
49 sd->tr->tr_node.io_Message.mn_ReplyPort->mp_SigTask = NULL;
52 VOID delay_us(struct g45staticdata *sd, uint32_t usec)
54 /* Take MsgPort over by current task */
55 sd->tr->tr_node.io_Message.mn_ReplyPort->mp_SigBit = SIGB_SINGLE;
56 sd->tr->tr_node.io_Message.mn_ReplyPort->mp_SigTask = FindTask(NULL);
58 /* Specify the request */
59 sd->tr->tr_node.io_Command = TR_ADDREQUEST;
60 sd->tr->tr_time.tv_secs = usec / 1000000;
61 sd->tr->tr_time.tv_micro = (usec % 1000000);
63 /* Wait */
64 DoIO(&sd->tr->tr_node);
66 sd->tr->tr_node.io_Message.mn_ReplyPort->mp_SigTask = NULL;
69 static BOOL calc_pll_and_validate(GMA_PLL_t *pll)
71 uint32_t m, p;
73 /* requirement: M1 > M2 */
74 if (pll->M1 <= pll->M2)
75 return FALSE;
77 /* M1 range: 10 .. 20 */
78 if (pll->M1 < 10 || pll->M1 > 20)
79 return FALSE;
81 /* M2 range: 5 .. 9 */
82 if (pll->M2 < 5 || pll->M2 > 9)
83 return FALSE;
85 m = 5 * ((uint32_t)pll->M1 + 2) + (pll->M2 + 2);
87 /* m range: 70 .. 120 */
88 if (m < 70 || m > 120)
89 return FALSE;
91 /* N range: 3 .. 8 */
92 if (pll->N < 3 || pll->N > 8)
93 return FALSE;
95 pll->VCO = (96000 * m) / (pll->N + 2);
97 if (pll->VCO < 1400000 || pll->VCO > 2800000)
98 return FALSE;
100 if (pll->P1 < 1 || pll->P1 > 8)
101 return FALSE;
103 p = (uint32_t)pll->P1 * (uint32_t)pll->P2;
105 /* p range: 5 .. 80 for sDVO/DAC mode */
106 if (p < 5 || p > 80)
107 return FALSE;
109 pll->PixelClock = pll->VCO / p;
111 if (pll->PixelClock < 20000 || pll->PixelClock > 400000)
112 return FALSE;
114 return TRUE;
117 void EnablePipe(struct g45staticdata *sd,LONG pipe){
118 char *pipeconf_reg = sd->Card.MMIO + ((pipe == PIPE_A) ? G45_PIPEACONF : G45_PIPEBCONF);
119 writel( readl( pipeconf_reg ) | G45_PIPECONF_ENABLE ,pipeconf_reg );
122 void DisablePipe(struct g45staticdata *sd,LONG pipe){
123 char *pipeconf_reg = sd->Card.MMIO + ((pipe == PIPE_A) ? G45_PIPEACONF : G45_PIPEBCONF);
125 writel(readl( pipeconf_reg ) & ~G45_PIPECONF_ENABLE, pipeconf_reg );
126 readl( pipeconf_reg );
127 delay_ms(sd, 20);
130 void EnablePlane(struct g45staticdata *sd,LONG plane){
131 char *dspbase_reg = sd->Card.MMIO + ((plane == PIPE_A) ? G45_DSPABASE : G45_DSPBBASE);
132 char *dspcntr_reg = sd->Card.MMIO + ((plane == PIPE_A) ? G45_DSPACNTR : G45_DSPBCNTR);
134 writel( readl( dspcntr_reg ) | G45_DSPCNTR_PLANE_ENABLE ,dspcntr_reg);
135 writel( readl( dspbase_reg ), dspbase_reg);
136 delay_ms(sd, 20);
139 void DisablePlane(struct g45staticdata *sd,LONG plane){
140 char *dspbase_reg = sd->Card.MMIO + ((plane == PIPE_A) ? G45_DSPABASE : G45_DSPBBASE);
141 char *dspcntr_reg = sd->Card.MMIO + ((plane == PIPE_A) ? G45_DSPACNTR : G45_DSPBCNTR);
143 writel( readl( dspcntr_reg ) & ~G45_DSPCNTR_PLANE_ENABLE ,dspcntr_reg);
144 writel( readl( dspbase_reg ), dspbase_reg);
145 readl( dspbase_reg );
146 delay_ms(sd, 20);
149 void UpdateCursor(struct g45staticdata *sd)
151 writel(sd->CursorBase, sd->Card.MMIO + (sd->pipe == PIPE_A ? G45_CURABASE : G45_CURBBASE));
154 void SetCursorPosition(struct g45staticdata *sd,LONG x,LONG y)
156 LONG width = (sd->VisibleBitmap->state->htotal & 0x0000ffff);
157 LONG height = (sd->VisibleBitmap->state->vtotal & 0x0000ffff);
159 if(x<0)x=0;
160 if(y<0)y=0;
161 if(x>width)x = width; // Grue eats you,if pointer is outside of the screen.
162 if(y>height)y = height;
164 writel(((ULONG)x << G45_CURPOS_XSHIFT) | ((ULONG)y << G45_CURPOS_YSHIFT),
165 sd->Card.MMIO + (sd->pipe == PIPE_A ?G45_CURAPOS:G45_CURBPOS));
166 UpdateCursor(sd);
169 void G45_InitMode(struct g45staticdata *sd, GMAState_t *state,
170 uint16_t width, uint16_t height, uint8_t depth, uint32_t pixelclock, intptr_t framebuffer,
171 uint16_t hdisp, uint16_t vdisp, uint16_t hstart, uint16_t hend, uint16_t htotal,
172 uint16_t vstart, uint16_t vend, uint16_t vtotal, uint32_t flags)
174 bug("[GMA] InitMode %dx%dx%d @ %dHz\n", hdisp, vdisp, depth, ((pixelclock / (uint32_t)htotal) * 1000) / ((uint32_t)vtotal));
175 GMA_PLL_t clock = { 0 }, t = { 0 };
176 uint32_t err = pixelclock;
178 clock.PixelClock = 0;
181 * Brute force determination of PLL settings. Iterate through all available configurations and select the most
182 * suitable one. I know, nested loops, but there is really no better way to do it
184 if (pixelclock <= 270000)
185 t.P2 = 10;
186 else
187 t.P2 = 5;
189 for (t.M1 = 10; t.M1 <= 20; t.M1++)
191 for (t.M2 = 5; t.M2 <= 9; t.M2++)
193 for (t.N = 3; t.N <= 8; t.N++)
195 for (t.P1=1; t.P1 <= 8; t.P1++)
197 if (calc_pll_and_validate(&t) == TRUE)
199 int this_err = abs(pixelclock - t.PixelClock);
200 if (this_err < err)
202 clock = t;
203 err = this_err;
211 if (clock.PixelClock)
213 D(bug("[GMA] PixelClock: Found: %d kHz, Requested: %d kHz\n", clock.PixelClock, pixelclock));
214 D(bug("[GMA] VCO: %d MHz\n", clock.VCO / 1000));
215 state->fp = clock.N << 16 | clock.M1 << 8 | clock.M2;
217 if (clock.VCO >= 1900000 && clock.VCO < 2400000)
218 state->fp |= 1 << 24;
219 else if (clock.VCO >= 2500000 && clock.VCO < 3000000)
220 state->fp |= 2 << 24;
221 else if (clock.VCO > 3100000)
222 state->fp |= 3 << 24;
224 state->dpll = (10 << G45_DPLL_PHASE_SHIFT) | G45_DPLL_VGA_MODE_DISABLE | G45_DPLL_MODE_DAC_SERIAL;
225 if (clock.P2 >= 10)
226 state->dpll |= G45_DPLL_DAC_SERIAL_P2_DIV_10;
227 else
228 state->dpll |= G45_DPLL_DAC_SERIAL_P2_DIV_5;
229 state->dpll |= (1 << (clock.P1 - 1)) << G45_DPLL_P1_SHIFT;
231 state->dspcntr = readl(sd->Card.MMIO + G45_DSPACNTR ) & 0x000f0000;
233 if (depth <= 8)
235 state->dspcntr |= G45_DSPCNTR_8BPP;
236 state->dspstride = width;
238 else if (depth == 15)
240 state->dspcntr |= G45_DSPCNTR_15BPP;
241 state->dspstride = width * 2;
243 else if (depth == 16)
245 state->dspcntr |= G45_DSPCNTR_16BPP;
246 state->dspstride = width * 2;
248 else
250 state->dspcntr |= G45_DSPCNTR_32BPP;
251 state->dspstride = width * 4;
254 state->pipeconf = G45_PIPECONF_ENABLE;
255 state->dpll |= G45_DPLL_VCO_ENABLE;
256 state->dspcntr |= G45_DSPCNTR_PLANE_ENABLE;
258 state->htotal = (hdisp - 1) | ((htotal - 1) << 16);
259 state->hblank = (hdisp - 1) | ((htotal - 1) << 16);
260 state->hsync = (hstart - 1) | ((hend - 1) << 16);
262 state->vtotal = (vdisp - 1) | ((vtotal - 1) << 16);
263 state->vblank = (vdisp - 1) | ((vtotal - 1) << 16);
264 state->vsync = (vstart - 1) | ((vend - 1) << 16);
266 state->pipesrc = (vdisp - 1) | ((hdisp - 1) << 16);
267 state->dspsurf = 0;
268 state->dsplinoff = framebuffer;
269 state->dspstride = (state->dspstride + 63) & ~63;
271 state->adpa = 0;
273 if (flags & vHidd_Sync_HSyncPlus)
274 state->adpa |= G45_ADPA_HSYNC_PLUS;
275 if (flags & vHidd_Sync_VSyncPlus)
276 state->adpa |= G45_ADPA_VSYNC_PLUS;
278 D(bug("[GMA] dpll=%08x\n", state->dpll));
282 void G45_LoadState(struct g45staticdata *sd, GMAState_t *state)
284 int i;
285 uint32_t tmp;
286 BOOL panelfitter;
288 bug("[GMA] LoadState %dx%dx%d\n",
289 (state->htotal & 0x0000ffff) + 1,
290 (state->vtotal & 0x0000ffff) + 1,
291 (state->dspcntr & G45_DSPCNTR_PIXEL_MASK)==G45_DSPCNTR_8BPP ? 8:
292 (state->dspcntr & G45_DSPCNTR_PIXEL_MASK)==G45_DSPCNTR_15BPP ? 15:
293 (state->dspcntr & G45_DSPCNTR_PIXEL_MASK)==G45_DSPCNTR_16BPP ? 16:
294 (state->dspcntr & G45_DSPCNTR_PIXEL_MASK)==G45_DSPCNTR_32BPP ? 32:666
297 LOCK_HW
298 DO_FLUSH();
300 if( sd->pipe == PIPE_B )
302 /* G45: Volume 3: Display Register
303 • DPLL must be enabled and warmed up before pipe or ports are enabled.
304 • DPLL must be kept enabled until ports are disabled and pipe is completely off.
305 • DPLL frequency must not be changed until ports are disabled and pipe is completely off, except
306 when in native VGA where SR01 25/28 MHz select can be changed.
307 • Planes must be disabled before pipe is disabled or pipe timings changed.
308 • Panelfitter must be enabled or disabled only when pipe is completely off.
309 • On Gen3 set port multiply when enabling a SDVO port.
310 • On Gen3.5 and GenX set port multiply when programming the DPLL.
311 • The internal TV and CRT ports can be left on during a mode switch if DPLL is not touched.
312 • Ports can be freely enabled or disabled on a running pipe, except when port multiply needs to
313 be changed.
316 // DPLL or FP is not touched here ,register value is same in BIOS vesa modes 640x420 and 1024x600
318 // disable vga
319 writel(readl(sd->Card.MMIO + G45_VGACNTRL) | G45_VGACNTRL_VGA_DISABLE, sd->Card.MMIO + G45_VGACNTRL);
321 ULONG hdisp = (state->htotal & 0x0000ffff) + 1;
322 ULONG vdisp = (state->vtotal & 0x0000ffff) + 1;
324 if( hdisp == sd->lvds_fixed.hdisp && vdisp == sd->lvds_fixed.vdisp)
325 panelfitter = FALSE;
326 else
327 panelfitter = TRUE;
329 bug("[GMA] panelfitter %s\n",panelfitter ? "ON":"OFF");
331 DisablePlane(sd,PIPE_B);
332 DisablePipe(sd,PIPE_B);
334 bug("G45_PFIT_CONTROL=%x\n",readl(sd->Card.MMIO + G45_PFIT_CONTROL));
335 bug("G45_PFIT_PGM_RATIOS=%x\n",readl(sd->Card.MMIO + G45_PFIT_PGM_RATIOS));
337 writel(((hdisp - 1) << 16) | (vdisp - 1), sd->Card.MMIO + G45_PIPEBSRC);
338 writel(((vdisp - 1) << 16) | (hdisp - 1), sd->Card.MMIO + G45_DSPBSIZE);
340 // pixel format , use pipe B
341 tmp = readl( sd->Card.MMIO + G45_DSPBCNTR );
342 tmp = ( tmp & ~G45_DSPCNTR_PIXEL_MASK ) | ( state->dspcntr & G45_DSPCNTR_PIXEL_MASK );
343 tmp |= G45_DSPCNTR_SEL_PIPE_B;
344 writel( tmp , sd->Card.MMIO + G45_DSPBCNTR );
345 delay_ms(sd, 20);
347 // bitmap width in bytes
348 writel( state->dspstride , sd->Card.MMIO + G45_DSPBSTRIDE );
350 // framebuffer address
351 writel( state->dsplinoff , sd->Card.MMIO + G45_DSPBLINOFF );
352 readl( sd->Card.MMIO + G45_DSPBLINOFF );
354 delay_ms(sd, 20);
356 // without this pointer color is corrupted
357 ULONG i;
358 for (i = 0; i < 256; i++) {
359 writel( (i << 16) |(i << 8) | i , sd->Card.MMIO + 0x0a800 + 4 * i);//PALETTE_B
362 // enable/disable panelfitter
363 if( panelfitter ){
364 writel( 0 , sd->Card.MMIO + G45_PFIT_PGM_RATIOS );
365 writel( readl(sd->Card.MMIO + G45_PFIT_CONTROL) | G45_PFIT_ENABLE , sd->Card.MMIO + G45_PFIT_CONTROL );
367 else
369 writel( 0 , sd->Card.MMIO + G45_PFIT_PGM_RATIOS );
370 writel( readl(sd->Card.MMIO + G45_PFIT_CONTROL) & ~G45_PFIT_ENABLE , sd->Card.MMIO + G45_PFIT_CONTROL );
372 writel(state->dspsurf, sd->Card.MMIO + G45_DSPBSURF);
373 delay_ms(sd, 1);
375 EnablePipe(sd,PIPE_B);
376 EnablePlane(sd,PIPE_B);
379 else
382 uint32_t tmp;
384 writel(readl(sd->Card.MMIO + 0x61140) & ~(1 << 29), sd->Card.MMIO + 0x61140);
385 writel(readl(sd->Card.MMIO + 0x61160) & ~(1 << 29), sd->Card.MMIO + 0x61160);
387 writel(readl(sd->Card.MMIO + 0x61140) & ~(1 << 31), sd->Card.MMIO + 0x61140);
388 writel(readl(sd->Card.MMIO + 0x61160) & ~(1 << 31), sd->Card.MMIO + 0x61160);
390 // /* Stop cursor */
391 // writel(0, sd->Card.MMIO + 0x70080);
392 // delay_ms(sd, 20);
394 /* Disable pipe */
395 writel(readl(sd->Card.MMIO + G45_PIPEACONF) & ~G45_PIPECONF_ENABLE, sd->Card.MMIO + G45_PIPEACONF);
397 for (i=0; i < 100; i++)
399 if ((readl(sd->Card.MMIO + G45_PIPEACONF) & G45_PIPECONF_ENABLED) == 0)
400 break;
402 /* Disable pipe again and again*/
403 writel(readl(sd->Card.MMIO + G45_PIPEACONF) & ~G45_PIPECONF_ENABLE, sd->Card.MMIO + G45_PIPEACONF);
404 delay_ms(sd, 10);
407 /* Disable DAC */
408 writel(readl(sd->Card.MMIO + G45_ADPA) & ~G45_ADPA_ENABLE, sd->Card.MMIO + G45_ADPA);
410 /* Disable planes */
411 writel(readl(sd->Card.MMIO + G45_DSPACNTR) & ~G45_DSPCNTR_PLANE_ENABLE, sd->Card.MMIO + G45_DSPACNTR);
412 writel(readl(sd->Card.MMIO + G45_DSPBCNTR) & ~G45_DSPCNTR_PLANE_ENABLE, sd->Card.MMIO + G45_DSPBCNTR);
414 /* "VBLANK" delay */
415 delay_ms(sd, 20);
417 /* Stop sync */
418 writel((readl(sd->Card.MMIO + G45_ADPA) & G45_ADPA_MASK) | G45_ADPA_DPMS_OFF, sd->Card.MMIO + G45_ADPA);
420 /* Disable VGA */
421 writel(readl(sd->Card.MMIO + G45_VGACNTRL) | G45_VGACNTRL_VGA_DISABLE, sd->Card.MMIO + G45_VGACNTRL);
423 /* Clear PIPE status */
424 D(bug("[GMA] Old PIPEA Status = %08x\n", readl(sd->Card.MMIO + 0x70024)));
425 writel(0xffff, sd->Card.MMIO + 0x70024);
427 /* Use all 96 fifo entries for PIPE A */
428 writel(95 | (95 << 7), sd->Card.MMIO + 0x70030);
430 /* unprotect some fields */
431 writel(0xabcd0000, sd->Card.MMIO + 0x61204);
433 // tmp = readl(sd->Card.MMIO + G45_DPLLA_CTRL);
434 // D(bug("[GMA] dpll before=%08x\n", tmp));
435 // tmp &= ~G45_DPLL_VCO_ENABLE;
436 // D(bug("[GMA] writing dpll=%08x\n", tmp));
437 // writel(tmp, sd->Card.MMIO + G45_DPLLA_CTRL);
438 // D(bug("[GMA] dpll after=%08x\n", readl(sd->Card.MMIO + G45_DPLLA_CTRL)));
440 delay_us(sd, 150);
442 // writel(state->dspsurf, sd->Card.MMIO + G45_DSPASURF);
444 tmp = readl(sd->Card.MMIO + G45_PIPEACONF);
445 writel(tmp & ~(3 << 18), sd->Card.MMIO + G45_PIPEACONF);
446 writel(readl(sd->Card.MMIO + G45_DSPACNTR) | 0x80000000, sd->Card.MMIO + G45_DSPACNTR);
447 writel(0, sd->Card.MMIO + G45_DSPASURF);
448 writel(readl(sd->Card.MMIO + G45_DSPACNTR) & 0x7fffffff, sd->Card.MMIO + G45_DSPACNTR);
449 writel(0, sd->Card.MMIO + G45_DSPASURF);
450 writel(tmp, sd->Card.MMIO + G45_PIPEACONF);
452 if (state->dpll & G45_DPLL_VCO_ENABLE)
454 writel(state->fp, sd->Card.MMIO + G45_FPA0);
455 writel(state->fp, sd->Card.MMIO + G45_FPA1);
456 writel(state->dpll & ~G45_DPLL_VCO_ENABLE, sd->Card.MMIO + G45_DPLLA_CTRL);
457 (void)readl(sd->Card.MMIO + G45_DPLLA_CTRL);
458 delay_ms(sd, 1);
459 writel(state->dpll & ~G45_DPLL_VCO_ENABLE, sd->Card.MMIO + G45_DPLLA_CTRL);
460 (void)readl(sd->Card.MMIO + G45_DPLLA_CTRL);
461 delay_ms(sd, 1);
462 // writel(state->dpll & ~G45_DPLL_VCO_ENABLE, sd->Card.MMIO + G45_DPLLA_CTRL);
463 // (void)readl(sd->Card.MMIO + G45_DPLLA_CTRL);
464 // delay_ms(sd, 1);
465 // writel(state->dpll & ~G45_DPLL_VCO_ENABLE, sd->Card.MMIO + G45_DPLLA_CTRL);
466 // (void)readl(sd->Card.MMIO + G45_DPLLA_CTRL);
467 // delay_ms(sd, 1);
468 // writel(state->dpll & ~G45_DPLL_VCO_ENABLE, sd->Card.MMIO + G45_DPLLA_CTRL);
469 // (void)readl(sd->Card.MMIO + G45_DPLLA_CTRL);
470 // delay_ms(sd, 1);
471 // writel(state->dpll & ~G45_DPLL_VCO_ENABLE, sd->Card.MMIO + G45_DPLLA_CTRL);
472 // (void)readl(sd->Card.MMIO + G45_DPLLA_CTRL);
473 // delay_ms(sd, 1);
476 writel(state->fp, sd->Card.MMIO + G45_FPA0);
477 writel(state->fp, sd->Card.MMIO + G45_FPA1);
478 writel(state->dpll, sd->Card.MMIO + G45_DPLLA_CTRL);
479 (void)readl(sd->Card.MMIO + G45_DPLLA_CTRL);
480 delay_us(sd, 150);
481 writel(state->dpll, sd->Card.MMIO + G45_DPLLA_CTRL);
482 D(bug("[GMA] writing dpll=%08x, got %08x\n", state->dpll, readl(sd->Card.MMIO + G45_DPLLA_CTRL)));
483 delay_us(sd, 150);
485 /* protect on again */
486 writel(0x00000000, sd->Card.MMIO + 0x61204);
488 /* Enable DAC*/
489 writel((readl(sd->Card.MMIO + G45_ADPA) & G45_ADPA_MASK) | G45_ADPA_DPMS_OFF | G45_ADPA_ENABLE, sd->Card.MMIO + G45_ADPA);
491 writel(state->htotal, sd->Card.MMIO + G45_HTOTAL_A);
492 writel(state->hblank, sd->Card.MMIO + G45_HBLANK_A);
493 writel(state->hsync, sd->Card.MMIO + G45_HSYNC_A);
494 writel(state->vtotal, sd->Card.MMIO + G45_VTOTAL_A);
495 writel(state->vblank, sd->Card.MMIO + G45_VBLANK_A);
496 writel(state->vsync, sd->Card.MMIO + G45_VSYNC_A);
498 writel(state->pipesrc, sd->Card.MMIO + G45_PIPEASRC);
499 writel(state->pipesrc, sd->Card.MMIO + 0x70190);
500 writel(state->pipeconf, sd->Card.MMIO + G45_PIPEACONF);
501 (void)readl(sd->Card.MMIO + G45_PIPEACONF);
503 writel(state->dspsurf, sd->Card.MMIO + G45_DSPASURF);
504 writel(state->dspstride, sd->Card.MMIO + G45_DSPASTRIDE);
505 writel(state->dsplinoff , sd->Card.MMIO + G45_DSPALINOFF);
507 /* Enable DAC */
508 writel((readl(sd->Card.MMIO + G45_ADPA) & ~G45_ADPA_DPMS_MASK) | G45_ADPA_DPMS_ON, sd->Card.MMIO + G45_ADPA);
510 /* Adjust Sync pulse polarity */
511 writel((readl(sd->Card.MMIO + G45_ADPA) & ~(G45_ADPA_VSYNC_PLUS | G45_ADPA_HSYNC_PLUS)) | state->adpa, sd->Card.MMIO + G45_ADPA);
513 D(bug("[GMA] Loaded state. dpll=%08x %08x %08x %08x %08x %08x %08x\n", state->dpll,
514 readl(sd->Card.MMIO + G45_HTOTAL_A),
515 readl(sd->Card.MMIO + G45_HBLANK_A),
516 readl(sd->Card.MMIO + G45_HSYNC_A),
517 readl(sd->Card.MMIO + G45_VTOTAL_A),
518 readl(sd->Card.MMIO + G45_VBLANK_A),
519 readl(sd->Card.MMIO + G45_VSYNC_A)));
521 if (state->dpll != readl(sd->Card.MMIO + G45_DPLLA_CTRL))
523 D(bug("[GMA] DPLL mismatch!\n"));
524 writel(state->dpll, sd->Card.MMIO + G45_DPLLA_CTRL);
525 (void)readl(sd->Card.MMIO + G45_DPLLA_CTRL);
528 delay_ms(sd, 20);
530 writel(state->dspcntr, sd->Card.MMIO + G45_DSPACNTR);
533 UNLOCK_HW
536 void G45_SaveState(struct g45staticdata *sd, GMAState_t *state)
541 IPTR AllocBitmapArea(struct g45staticdata *sd, ULONG width, ULONG height,
542 ULONG bpp)
544 IPTR result;
546 LOCK_HW
548 result = (IPTR)AllocGfxMem(sd, 1024 + ((width * bpp + 63) & ~63) * height);
550 if (result)
551 result +=512;
553 D(bug("[GMA] AllocBitmapArea(%dx%d@%d) = %p\n",
554 width, height, bpp, result));
555 D(bug("[GMA] Available graphics memory is now %ldMB\n", sd->CardMem.mh_Free >> 20));
557 If allocation failed, use -1 as return value. If it succeeded,
558 make the memory pointer relative to the beginning of GFX memory
560 if (result == 0) result--;
561 else result -= (IPTR)sd->Card.Framebuffer;
563 UNLOCK_HW
565 /* Generic thing. Will be extended later */
566 return result;
569 VOID FreeBitmapArea(struct g45staticdata *sd, IPTR bmp, ULONG width, ULONG height,
570 ULONG bpp)
572 APTR ptr = (APTR)(bmp + sd->Card.Framebuffer-512);
574 LOCK_HW
576 D(bug("[GMA] FreeBitmapArea(%p,%dx%d@%d)\n",
577 ptr, width, height, bpp));
579 FreeGfxMem(sd, ptr, 1024 + ((width * bpp + 63) & ~63) * height);
580 D(bug("[GMA] Available graphics memory is now %ldMB\n", sd->CardMem.mh_Free >> 20));
582 UNLOCK_HW
585 BOOL adpa_Enabled(struct g45staticdata *sd)
587 return ( readl( sd->Card.MMIO + G45_ADPA ) & G45_ADPA_ENABLE) ? TRUE : FALSE;
590 BOOL lvds_Enabled(struct g45staticdata *sd)
592 return ( readl( sd->Card.MMIO + G45_LVDS ) & G45_LVDS_PORT_EN) ? TRUE : FALSE;
595 void GetSync(struct g45staticdata *sd,struct Sync *sync,ULONG pipe)
597 ULONG htot = readl(sd->Card.MMIO + (pipe == PIPE_A ? G45_HTOTAL_A : G45_HTOTAL_B));
598 ULONG hsync = readl(sd->Card.MMIO + (pipe == PIPE_A ? G45_HSYNC_A : G45_HSYNC_B));
599 ULONG vtot = readl(sd->Card.MMIO + (pipe == PIPE_A ? G45_VTOTAL_A : G45_VTOTAL_B));
600 ULONG vsync = readl(sd->Card.MMIO + (pipe == PIPE_A ? G45_VSYNC_A : G45_VSYNC_B));
602 sync->pixelclock = 48; // dummy value
603 sync->flags =0;
605 sync->hdisp = (htot & 0xffff) + 1;
606 sync->htotal = ((htot & 0xffff0000) >> 16) + 1;
607 sync->hstart = (hsync & 0xffff) + 1;
608 sync->hend = ((hsync & 0xffff0000) >> 16) + 1;
609 sync->vdisp = (vtot & 0xffff) + 1;
610 sync->vtotal = ((vtot & 0xffff0000) >> 16) + 1;
611 sync->vstart = (vsync & 0xffff) + 1;
612 sync->vend = ((vsync & 0xffff0000) >> 16) + 1;
614 sync->width = sync->hdisp;
615 sync->height = sync->vdisp;
617 ULONG dsp_cntr = readl(sd->Card.MMIO + (sd->pipe == 0 ? G45_DSPACNTR : G45_DSPBCNTR));
619 switch (dsp_cntr & G45_DSPCNTR_PIXEL_MASK) {
620 case G45_DSPCNTR_8BPP:
621 sync->depth = 8;
622 break;
623 case G45_DSPCNTR_16BPP:
624 sync->depth = 16;
625 break;
626 case G45_DSPCNTR_32BPP:
627 sync->depth = 32;
628 break;
629 default:
630 bug("[GMA] GetSync: Unknown pixel format.\n");
632 bug("[GMA] GetSync: %d %d %d %d\n",
633 sync->hdisp,
634 sync->hstart,
635 sync->hend,
636 sync->htotal);
638 bug(" %d %d %d %d\n",
639 sync->vdisp,
640 sync->vstart,
641 sync->vend,
642 sync->vtotal);