1 /* CTRC functionality */
2 /* Authors:
3 Mark Watson 2/2000,
4 Apsed,
5 Rudolf Cornelissen 11/2002-11/2005
6 */
7
8 #define MODULE_BIT 0x00040000
9
10 #include "mga_std.h"
11
12 /*Adjust passed parameters to a valid mode line*/
gx00_crtc_validate_timing(uint16 * hd_e,uint16 * hs_s,uint16 * hs_e,uint16 * ht,uint16 * vd_e,uint16 * vs_s,uint16 * vs_e,uint16 * vt)13 status_t gx00_crtc_validate_timing(
14 uint16 *hd_e,uint16 *hs_s,uint16 *hs_e,uint16 *ht,
15 uint16 *vd_e,uint16 *vs_s,uint16 *vs_e,uint16 *vt
16 )
17 {
18 /* horizontal */
19 /* make all parameters multiples of 8 */
20 *hd_e &= 0x0ff8; /* 2048 is a valid value for this item! */
21 *hs_s &= 0x0ff8;
22 *hs_e &= 0x0ff8;
23 *ht &= 0x0ff8;
24
25 /* confine to required number of bits, taking logic into account */
26 if (*hd_e > ((0x00ff + 1) << 3)) *hd_e = ((0x00ff + 1) << 3);
27 if (*hs_s > ((0x01ff - 1) << 3)) *hs_s = ((0x01ff - 1) << 3);
28 if (*hs_e > ( 0x01ff << 3)) *hs_e = ( 0x01ff << 3);
29 if (*ht > ((0x01ff + 5) << 3)) *ht = ((0x01ff + 5) << 3);
30
31 /* NOTE: keep horizontal timing at multiples of 8! */
32 /* confine to a reasonable width */
33 if (*hd_e < 640) *hd_e = 640;
34 switch (si->ps.card_type)
35 {
36 case MIL1:
37 case MYST: /* fixme MYST220 has MIL2 range.. */
38 if (*hd_e > 1600) *hd_e = 1600;
39 break;
40 case MIL2:
41 case G100:
42 case G200:
43 if (*hd_e > 1920) *hd_e = 1920;
44 break;
45 default: /* G400 and up */
46 if (*hd_e > 2048) *hd_e = 2048;
47 break;
48 }
49
50 /* if hor. total does not leave room for a sensible sync pulse, increase it! */
51 if (*ht < (*hd_e + 80)) *ht = (*hd_e + 80);
52
53 /* if hor. total does not adhere to max. blanking pulse width, decrease it! */
54 if (*ht > (*hd_e + 0x3f8)) *ht = (*hd_e + 0x3f8);
55
56 /* make sure sync pulse is not during display */
57 if (*hs_e > (*ht - 8)) *hs_e = (*ht - 8);
58 if (*hs_s < (*hd_e + 8)) *hs_s = (*hd_e + 8);
59
60 /* correct sync pulse if it is too long:
61 * there are only 5 bits available to save this in the card registers! */
62 if (*hs_e > (*hs_s + 0xf8)) *hs_e = (*hs_s + 0xf8);
63
64 /*vertical*/
65 /* confine to required number of bits, taking logic into account */
66 if (*vd_e > 0x7ff ) *vd_e = 0x7ff ; /* linecomp max value = 0x7ff! */
67 if (*vs_s > (0xfff - 1)) *vs_s = (0xfff - 1);
68 if (*vs_e > 0xfff ) *vs_e = 0xfff ;
69 if (*vt > (0xfff + 2)) *vt = (0xfff + 2);
70
71 /* confine to a reasonable height */
72 if (*vd_e < 480) *vd_e = 480;
73 switch (si->ps.card_type)
74 {
75 case MIL1:
76 case MYST: /* fixme MYST220 has MIL2 range.. */
77 if (*vd_e > 1200) *vd_e = 1200;
78 break;
79 case MIL2:
80 case G100:
81 case G200:
82 if (*vd_e > 1440) *vd_e = 1440;
83 break;
84 default: /* G400 and up */
85 if (*vd_e > 1536) *vd_e = 1536;
86 break;
87 }
88
89 /*if vertical total does not leave room for a sync pulse, increase it!*/
90 if (*vt < (*vd_e + 3)) *vt = (*vd_e + 3);
91
92 /* if vert. total does not adhere to max. blanking pulse width, decrease it! */
93 if (*vt > (*vd_e + 0xff)) *vt = (*vd_e + 0xff);
94
95 /* make sure sync pulse is not during display */
96 if (*vs_e > (*vt - 1)) *vs_e = (*vt - 1);
97 if (*vs_s < (*vd_e + 1)) *vs_s = (*vd_e + 1);
98
99 /* correct sync pulse if it is too long:
100 * there are only 4 bits available to save this in the card registers! */
101 if (*vs_e > (*vs_s + 0x0f)) *vs_e = (*vs_s + 0x0f);
102
103 return B_OK;
104 }
105
106 /* set a mode line - inputs are in pixels */
gx00_crtc_set_timing(display_mode target)107 status_t gx00_crtc_set_timing(display_mode target)
108 {
109 uint8 temp;
110
111 uint32 htotal; /*total horizontal total VCLKs*/
112 uint32 hdisp_e; /*end of horizontal display (begins at 0)*/
113 uint32 hsync_s; /*begin of horizontal sync pulse*/
114 uint32 hsync_e; /*end of horizontal sync pulse*/
115 uint32 hblnk_s; /*begin horizontal blanking*/
116 uint32 hblnk_e; /*end horizontal blanking*/
117
118 uint32 vtotal; /*total vertical total scanlines*/
119 uint32 vdisp_e; /*end of vertical display*/
120 uint32 vsync_s; /*begin of vertical sync pulse*/
121 uint32 vsync_e; /*end of vertical sync pulse*/
122 uint32 vblnk_s; /*begin vertical blanking*/
123 uint32 vblnk_e; /*end vertical blanking*/
124
125 uint32 linecomp; /*split screen and vdisp_e interrupt*/
126
127 LOG(4,("CRTC: setting timing\n"));
128
129 /* Modify parameters as required by standard VGA */
130 htotal = ((target.timing.h_total >> 3) - 5);
131 hdisp_e = ((target.timing.h_display >> 3) - 1);
132 hblnk_s = hdisp_e;
133 hblnk_e = (htotal + 4);
134 hsync_s = (target.timing.h_sync_start >> 3);
135 hsync_e = (target.timing.h_sync_end >> 3);
136
137 vtotal = target.timing.v_total - 2;
138 vdisp_e = target.timing.v_display - 1;
139 vblnk_s = vdisp_e;
140 vblnk_e = (vtotal + 1);
141 vsync_s = target.timing.v_sync_start - 1; /* Matrox */
142 vsync_e = target.timing.v_sync_end - 1; /* Matrox */
143
144 /* We use the Matrox linecomp INT function to detect the
145 * vertical retrace at the earliest possible moment.. */
146 linecomp = target.timing.v_display;
147
148 /*log the mode I am setting*/
149 LOG(2,("CRTC:\n\tHTOT:%x\n\tHDISPEND:%x\n\tHBLNKS:%x\n\tHBLNKE:%x\n\tHSYNCS:%x\n\tHSYNCE:%x\n\t",htotal,hdisp_e,hblnk_s,hblnk_e,hsync_s,hsync_e));
150 LOG(2,("VTOT:%x\n\tVDISPEND:%x\n\tVBLNKS:%x\n\tVBLNKE:%x\n\tVSYNCS:%x\n\tVSYNCE:%x\n",vtotal,vdisp_e,vblnk_s,vblnk_e,vsync_s,vsync_e));
151
152 /*actually program the card! Note linecomp is programmed to vblnk_s for VBI*/
153 /*horizontal - VGA regs*/
154
155 VGAW_I(CRTC, 0x00, (htotal & 0x0ff));
156 VGAW_I(CRTC, 0x01, (hdisp_e & 0x0ff));
157 VGAW_I(CRTC, 0x02, (hblnk_s & 0x0ff));
158 /* b7 should be set for compatibility reasons */
159 VGAW_I(CRTC, 0x03, ((hblnk_e & 0x01f) | 0x80));
160 VGAW_I(CRTC, 0x04, (hsync_s & 0x0ff));
161 VGAW_I(CRTC, 0x05, (hsync_e & 0x01f) | ((hblnk_e & 0x020) << 2));
162
163 /*vertical - VGA regs*/
164 VGAW_I(CRTC, 0x06, (vtotal & 0x0ff));
165 VGAW_I(CRTC, 0x07,
166 (
167 ((vtotal & 0x100) >> (8 - 0)) | ((vtotal & 0x200) >> (9 - 5)) |
168 ((vdisp_e & 0x100) >> (8 - 1)) | ((vdisp_e & 0x200) >> (9 - 6)) |
169 ((vsync_s & 0x100) >> (8 - 2)) | ((vsync_s & 0x200) >> (9 - 7)) |
170 ((vblnk_s & 0x100) >> (8 - 3)) | ((linecomp & 0x100) >> (8 - 4))
171 ));
172 VGAW_I(CRTC, 0x08, 0x00);
173 VGAW_I(CRTC, 0x09, ((vblnk_s & 0x200) >> (9 - 5)) | ((linecomp & 0x200) >> (9 - 6)));
174 VGAW_I(CRTC, 0x10, (vsync_s & 0x0ff));
175 VGAW_I(CRTC, 0x11, (((VGAR_I(CRTC, 0x11)) & 0xf0) | (vsync_e & 0x00f)));
176 VGAW_I(CRTC, 0x12, (vdisp_e & 0x0ff));
177 VGAW_I(CRTC, 0x15, (vblnk_s & 0x0ff));
178 VGAW_I(CRTC, 0x16, (vblnk_e & 0x0ff));
179 VGAW_I(CRTC, 0x18, (linecomp & 0x0ff));
180
181 /* horizontal - extended regs */
182 /* do not touch external sync reset inputs: used for TVout */
183 VGAW_I(CRTCEXT, 1,
184 (
185 ((htotal & 0x100) >> (8 - 0)) |
186 ((hblnk_s & 0x100) >> (8 - 1)) |
187 ((hsync_s & 0x100) >> (8 - 2)) |
188 ((hblnk_e & 0x040) >> (6 - 6)) |
189 (VGAR_I(CRTCEXT, 1) & 0xb8)
190 ));
191
192 /*vertical - extended regs*/
193 VGAW_I(CRTCEXT, 2,
194 (
195 ((vtotal & 0xc00) >> (10 - 0)) |
196 ((vdisp_e & 0x400) >> (10 - 2)) |
197 ((vblnk_s & 0xc00) >> (10 - 3)) |
198 ((vsync_s & 0xc00) >> (10 - 5)) |
199 ((linecomp & 0x400) >> (10 - 7))
200 ));
201
202 /* setup HSYNC & VSYNC polarity */
203 LOG(2,("CRTC: sync polarity: "));
204 temp = VGAR(MISCR);
205 if (target.timing.flags & B_POSITIVE_HSYNC)
206 {
207 LOG(2,("H:pos "));
208 temp &= ~0x40;
209 }
210 else
211 {
212 LOG(2,("H:neg "));
213 temp |= 0x40;
214 }
215 if (target.timing.flags & B_POSITIVE_VSYNC)
216 {
217 LOG(2,("V:pos "));
218 temp &= ~0x80;
219 }
220 else
221 {
222 LOG(2,("V:neg "));
223 temp |= 0x80;
224 }
225 VGAW(MISCW, temp);
226
227 LOG(2,(", MISC reg readback: $%02x\n", VGAR(MISCR)));
228
229 return B_OK;
230 }
231
gx00_crtc_depth(int mode)232 status_t gx00_crtc_depth(int mode)
233 {
234 uint8 viddelay = 0; // in CRTCEXT3, reserved if >= G100
235
236 if (si->ps.card_type < G100) do { // apsed TODO in caller
237 if (si->ps.memory_size <= 2) { viddelay = 1<<3; break;}
238 if (si->ps.memory_size <= 4) { viddelay = 0<<3; break;}
239 viddelay = 2<<3; // for 8 to 16Mb of memory
240 } while (0);
241
242 /* setup green_sync if requested */
243 if (si->settings.greensync)
244 {
245 /* enable sync_on_green: ctrl bit polarity was reversed for Gxxx cards! */
246 if (si->ps.card_type <= MIL2)
247 DXIW(GENCTRL, (DXIR(GENCTRL) | 0x20));
248 else
249 DXIW(GENCTRL, (DXIR(GENCTRL) & ~0x20));
250 /* select horizontal _and_ vertical sync */
251 viddelay |= 0x40;
252
253 LOG(4,("CRTC: sync_on_green enabled\n"));
254 }
255 else
256 {
257 /* disable sync_on_green: ctrl bit polarity was reversed for Gxxx cards! */
258 if (si->ps.card_type <= MIL2)
259 DXIW(GENCTRL, (DXIR(GENCTRL) & ~0x20));
260 else
261 DXIW(GENCTRL, (DXIR(GENCTRL) | 0x20));
262
263 LOG(4,("CRTC: sync_on_green disabled\n"));
264 }
265
266 /*set VCLK scaling*/
267 switch(mode)
268 {
269 case BPP8:
270 VGAW_I(CRTCEXT,3,viddelay|0x80);
271 break;
272 case BPP15:case BPP16:
273 VGAW_I(CRTCEXT,3,viddelay|0x81);
274 break;
275 case BPP24:
276 VGAW_I(CRTCEXT,3,viddelay|0x82);
277 break;
278 case BPP32:case BPP32DIR:
279 VGAW_I(CRTCEXT,3,viddelay|0x83);
280 break;
281 }
282 return B_OK;
283 }
284
gx00_crtc_dpms(bool display,bool h,bool v)285 status_t gx00_crtc_dpms(bool display, bool h, bool v) // MIL2
286 {
287 char msg[100];
288
289 strlcpy(msg, "CRTC: setting DPMS: ", sizeof(msg));
290
291 if (display)
292 {
293 VGAW_I(SEQ,1, 0x00);
294 strlcat(msg, "display on, ", sizeof(msg));
295 }
296 else
297 {
298 VGAW_I(SEQ,1, 0x20);
299 strlcat(msg, "display off, ", sizeof(msg));
300 }
301 if (h)
302 {
303 VGAW_I(CRTCEXT, 1, (VGAR_I(CRTCEXT, 1) & 0xef));
304 strlcat(msg, "hsync enabled, ", sizeof(msg));
305 }
306 else
307 {
308 VGAW_I(CRTCEXT, 1, (VGAR_I(CRTCEXT, 1) | 0x10));
309 strlcat(msg, "hsync disabled, ", sizeof(msg));
310 }
311 if (v)
312 {
313 VGAW_I(CRTCEXT, 1, (VGAR_I(CRTCEXT, 1) & 0xdf));
314 strlcat(msg, "vsync enabled\n", sizeof(msg));
315 }
316 else
317 {
318 VGAW_I(CRTCEXT, 1, (VGAR_I(CRTCEXT, 1) | 0x20));
319 strlcat(msg, "vsync disabled\n", sizeof(msg));
320 }
321
322 LOG(4, (msg));
323
324 /* set some required fixed values for proper MGA mode initialisation */
325 VGAW_I(CRTC,0x17,0xC3);
326 VGAW_I(CRTC,0x14,0x00);
327
328 /* make sure CRTC1 sync is patched through on connector on G450/G550! */
329 if (si->ps.card_type >= G450)
330 {
331 if (si->crossed_conns)
332 {
333 /* patch through HD15 hsync and vsync unmodified */
334 DXIW(SYNCCTRL, (DXIR(SYNCCTRL) & 0x0f));
335 }
336 else
337 {
338 /* patch through DVI-A hsync and vsync unmodified */
339 DXIW(SYNCCTRL, (DXIR(SYNCCTRL) & 0xf0));
340 }
341 }
342
343 return B_OK;
344 }
345
gx00_crtc_set_display_pitch()346 status_t gx00_crtc_set_display_pitch()
347 {
348 uint32 offset;
349
350 LOG(4,("CRTC: setting card pitch (offset between lines)\n"));
351
352 /* figure out offset value hardware needs:
353 * same for MIL1-G550 cards assuming MIL1/2 uses the TVP3026 64-bits DAC etc. */
354 offset = si->fbc.bytes_per_row / 16;
355
356 LOG(2,("CRTC: offset register: 0x%04x\n",offset));
357
358 /*program the card!*/
359 VGAW_I(CRTC,0x13,(offset&0xFF));
360 VGAW_I(CRTCEXT,0,(VGAR_I(CRTCEXT,0)&0xCF)|((offset&0x300)>>4));
361 return B_OK;
362 }
363
gx00_crtc_set_display_start(uint32 startadd,uint8 bpp)364 status_t gx00_crtc_set_display_start(uint32 startadd,uint8 bpp)
365 {
366 uint32 ext0;
367
368 LOG(4,("CRTC: setting card RAM to be displayed bpp %d\n", bpp));
369
370 /* Matrox docs are false/incomplete, always program qword adress. */
371 startadd >>= 3;
372
373 LOG(2,("CRTC: startadd: %x\n",startadd));
374 LOG(2,("CRTC: frameRAM: %x\n",si->framebuffer));
375 LOG(2,("CRTC: framebuffer: %x\n",si->fbc.frame_buffer));
376
377 /* make sure we are in retrace on MIL cards (if possible), because otherwise
378 * distortions might occur during our reprogramming them (no double buffering) */
379 if (si->ps.card_type < G100)
380 {
381 /* we might have no retraces during setmode! */
382 uint32 timeout = 0;
383 /* wait 25mS max. for retrace to occur (refresh > 40Hz) */
384 while ((!(ACCR(STATUS) & 0x08)) && (timeout < (25000/4)))
385 {
386 snooze(4);
387 timeout++;
388 }
389 }
390
391 /*set standard registers*/
392 VGAW_I(CRTC,0xD,startadd&0xFF);
393 VGAW_I(CRTC,0xC,(startadd&0xFF00)>>8);
394
395 //calculate extra bits that are standard over Gx00 series
396 ext0 = VGAR_I(CRTCEXT,0)&0xB0;
397 ext0|= (startadd&0xF0000)>>16;
398
399 //if card is a G200 or G400 then do first extension bit
400 if (si->ps.card_type>=G200)
401 ext0|=(startadd&0x100000)>>14;
402
403 //if card is a G400 then do write to its extension register
404 if (si->ps.card_type>=G400)
405 VGAW_I(CRTCEXT,8,((startadd&0x200000)>>21));
406
407 //write the extension bits
408 VGAW_I(CRTCEXT,0,ext0);
409
410 return B_OK;
411 }
412
gx00_crtc_mem_priority(uint8 colordepth)413 status_t gx00_crtc_mem_priority(uint8 colordepth)
414 {
415 float tpixclk, tmclk, refresh, temp;
416 uint8 mp, vc, hiprilvl, maxhipri, prioctl;
417
418 /* we can only do this if card pins is read OK *and* card is coldstarted! */
419 if (si->settings.usebios || (si->ps.pins_status != B_OK))
420 {
421 LOG(4,("CRTC: Card not coldstarted, skipping memory priority level setup\n"));
422 return B_OK;
423 }
424
425 /* only on G200 the mem_priority register should be programmed with this formula */
426 if (si->ps.card_type != G200)
427 {
428 LOG(4,("CRTC: Memory priority level setup not needed, skipping\n"));
429 return B_OK;
430 }
431
432 /* make sure the G200 is running at peak performance, so for instance high-res
433 * overlay distortions due to bandwidth limitations are minimal.
434 * Note please that later cards have plenty of bandwidth to cope by default.
435 * Note also that the formula needed is entirely cardtype-dependant! */
436 LOG(4,("CRTC: Setting G200 memory priority level\n"));
437
438 /* set memory controller pipe depth, assuming no codec or Vin operating */
439 switch ((si->ps.memrdbk_reg & 0x00c00000) >> 22)
440 {
441 case 0:
442 mp = 52;
443 break;
444 case 1:
445 mp = 41;
446 break;
447 case 2:
448 mp = 32;
449 break;
450 default:
451 mp = 52;
452 LOG(8,("CRTC: Streamer flowcontrol violation in PINS, defaulting to %%00\n"));
453 break;
454 }
455
456 /* calculate number of videoclocks needed per 8 pixels */
457 vc = (8 * colordepth) / 64;
458
459 /* calculate pixelclock period (nS) */
460 tpixclk = 1000000 / si->dm.timing.pixel_clock;
461
462 /* calculate memoryclock period (nS) */
463 if (si->ps.v3_option2_reg & 0x08)
464 {
465 tmclk = 1000.0 / si->ps.std_engine_clock;
466 }
467 else
468 {
469 if (si->ps.v3_clk_div & 0x02)
470 tmclk = 3000.0 / si->ps.std_engine_clock;
471 else
472 tmclk = 2000.0 / si->ps.std_engine_clock;
473 }
474
475 /* calculate refreshrate of current displaymode */
476 refresh = ((si->dm.timing.pixel_clock * 1000) /
477 ((uint32)si->dm.timing.h_total * (uint32)si->dm.timing.v_total));
478
479 /* calculate high priority request level, but stay on the 'crtc-safe' side:
480 * hence 'formula + 1.0' instead of 'formula + 0.5' */
481 temp = (((((mp * tmclk) + (11 * vc * tpixclk)) / tpixclk) - (vc - 1)) / (8 * vc)) + 1.0;
482 if (temp > 7.0) temp = 7.0;
483 if (temp < 0.0) temp = 0.0;
484 hiprilvl = 7 - ((uint8) temp);
485 /* limit non-crtc priority so crtc always stays 'just' OK */
486 if (hiprilvl > 4) hiprilvl = 4;
487 if ((si->dm.timing.v_display > 768) && (hiprilvl > 3)) hiprilvl = 3;
488 if ((si->dm.timing.v_display > 864) && (hiprilvl > 2) && (refresh >= 76.0)) hiprilvl = 2;
489 if ((si->dm.timing.v_display > 1024) && (hiprilvl > 2)) hiprilvl = 2;
490
491 /* calculate maximum high priority requests */
492 temp = (vc * (tmclk / tpixclk)) + 0.5;
493 if (temp > (float)hiprilvl) temp = (float)hiprilvl;
494 if (temp < 0.0) temp = 0.0;
495 maxhipri = ((uint8) temp);
496
497 /* program the card */
498 prioctl = ((hiprilvl & 0x07) | ((maxhipri & 0x07) << 4));
499 VGAW_I(CRTCEXT, 6, prioctl);
500
501 /* log results */
502 LOG(4,("CRTC: Vclks/char is %d, pixClk period %02.2fnS, memClk period %02.2fnS\n",
503 vc, tpixclk, tmclk));
504 LOG(4,("CRTC: memory priority control register is set to $%02x\n", prioctl));
505
506 return B_OK;
507 }
508
gx00_crtc_cursor_init()509 status_t gx00_crtc_cursor_init()
510 {
511 int i;
512
513 if (si->ps.card_type >= G100)
514 {
515 vuint32 * fb;
516 /* cursor bitmap will be stored at the start of the framebuffer on >= G100 */
517 const uint32 curadd = 0;
518
519 /* set cursor bitmap adress ... */
520 DXIW(CURADDL,curadd >> 10);
521 DXIW(CURADDH,curadd >> 18);
522 /* ... and repeat that: G100 requires other programming order than later cards!?! */
523 DXIW(CURADDL,curadd >> 10);
524 DXIW(CURADDH,curadd >> 18);
525
526 /*set cursor colour*/
527 DXIW(CURCOL0RED,0XFF);
528 DXIW(CURCOL0GREEN,0xFF);
529 DXIW(CURCOL0BLUE,0xFF);
530 DXIW(CURCOL1RED,0);
531 DXIW(CURCOL1GREEN,0);
532 DXIW(CURCOL1BLUE,0);
533 DXIW(CURCOL2RED,0);
534 DXIW(CURCOL2GREEN,0);
535 DXIW(CURCOL2BLUE,0);
536
537 /*clear cursor*/
538 fb = (vuint32 *) si->framebuffer + curadd;
539 for (i=0;i<(1024/4);i++)
540 {
541 fb[i]=0;
542 }
543 }
544 else
545 /* <= G100 cards have serial cursor color registers,
546 * and dedicated cursor bitmap RAM (in TVP3026 DAC)
547 */
548 {
549 /* select first colorRAM adress */
550 DACW(TVP_CUROVRWTADD,0x00);
551 /* overscan/border color is black, order of colors set is R,G,B */
552 DACW(TVP_CUROVRDATA,0xff);
553 DACW(TVP_CUROVRDATA,0xff);
554 DACW(TVP_CUROVRDATA,0xff);
555 /* set sursor color 0 */
556 DACW(TVP_CUROVRDATA,0xff);
557 DACW(TVP_CUROVRDATA,0xff);
558 DACW(TVP_CUROVRDATA,0xff);
559 /* set sursor color 1 */
560 DACW(TVP_CUROVRDATA,0x00);
561 DACW(TVP_CUROVRDATA,0x00);
562 DACW(TVP_CUROVRDATA,0x00);
563 /* set sursor color 2 */
564 DACW(TVP_CUROVRDATA,0x00);
565 DACW(TVP_CUROVRDATA,0x00);
566 DACW(TVP_CUROVRDATA,0x00);
567
568 /* select first cursor pattern DAC-internal RAM adress, and
569 * make sure indirect cursor control register is selected as active register */
570 DXIW(CURCTRL,(DXIR(CURCTRL) & 0x73));
571 DACW(PALWTADD,0x00);
572 /* now clear it, auto-incrementing the adress */
573 for(i=0;i<1024;i++)
574 {
575 DACW(TVP_CURRAMDATA,0x00);
576 }
577 }
578
579 /* activate hardware cursor */
580 gx00_crtc_cursor_show();
581
582 return B_OK;
583 }
584
gx00_crtc_cursor_show()585 status_t gx00_crtc_cursor_show()
586 {
587 if ((si->ps.card_type < G100) && (si->dm.timing.h_total > 2048))
588 {
589 /* MIL1/2 DAC needs to be told if h_total for the active mode gets above 2048 */
590 DXIW(CURCTRL, 0x11);
591 }
592 else
593 {
594 DXIW(CURCTRL, 0x01);
595 }
596
597 return B_OK;
598 }
599
gx00_crtc_cursor_hide()600 status_t gx00_crtc_cursor_hide()
601 {
602 DXIW(CURCTRL,0);
603 return B_OK;
604 }
605
606 /*set up cursor shape*/
gx00_crtc_cursor_define(uint8 * andMask,uint8 * xorMask)607 status_t gx00_crtc_cursor_define(uint8* andMask,uint8* xorMask)
608 {
609 int y;
610
611 if(si->ps.card_type >= G100)
612 {
613 vuint8 * cursor;
614
615 /*get a pointer to the cursor*/
616 cursor = (vuint8*) si->framebuffer;
617
618 /*draw the cursor*/
619 for(y=0;y<16;y++)
620 {
621 cursor[y*16+7]=~*andMask++;
622 cursor[y*16+15]=*xorMask++;
623 cursor[y*16+6]=~*andMask++;
624 cursor[y*16+14]=*xorMask++;
625 }
626 }
627 else
628 /* <= G100 cards have dedicated cursor bitmap RAM (in TVP3026 DAC) */
629 {
630 uint8 curctrl;
631
632 /* disable the cursor to prevent distortions in screen output */
633 curctrl = (DXIR(CURCTRL));
634 DXIW(CURCTRL, (curctrl & 0xfc));
635 /* select first cursor pattern DAC-internal RAM adress for plane 0 */
636 DXIW(CURCTRL, (DXIR(CURCTRL) & ~0x0c));
637 DACW(PALWTADD, 0x00);
638 /* now fill it, partly auto-incrementing the adress */
639 for(y = 0; y < 16; y++)
640 {
641 DACW(PALWTADD, (y * 8));
642 DACW(TVP_CURRAMDATA, ~*andMask++);
643 DACW(TVP_CURRAMDATA, ~*andMask++);
644 }
645 /* select first cursor pattern DAC-internal RAM adress for plane 1 */
646 DXIW(CURCTRL, (DXIR(CURCTRL) | 0x08));
647 DACW(PALWTADD, 0x00);
648 /* now fill it, partly auto-incrementing the adress */
649 for(y = 0; y < 16; y++)
650 {
651 DACW(PALWTADD, y*8);
652 DACW(TVP_CURRAMDATA, *xorMask++);
653 DACW(TVP_CURRAMDATA, *xorMask++);
654 }
655 /* delay restoring the cursor to prevent distortions in screen output */
656 snooze(5);
657 /* restore the cursor */
658 DXIW(CURCTRL, curctrl);
659 }
660
661 return B_OK;
662 }
663
664 /*position the cursor*/
gx00_crtc_cursor_position(uint16 x,uint16 y)665 status_t gx00_crtc_cursor_position(uint16 x ,uint16 y)
666 {
667 int i=64;
668
669 x+=i;
670 y+=i;
671
672 /* make sure we are not in retrace, because the register(s) might get copied
673 * during our reprogramming them (double buffering feature) */
674 while (ACCR(STATUS) & 0x08)
675 {
676 snooze(4);
677 }
678
679 DACW(CURSPOSXL,x&0xFF);
680 DACW(CURSPOSXH,x>>8);
681 DACW(CURSPOSYL,y&0xFF);
682 DACW(CURSPOSYH,y>>8);
683
684 return B_OK;
685 }
686