1 /*
2 (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org)
3 (c) Copyright 2000-2004 Convergence (integrated media) GmbH
4
5 All rights reserved.
6
7 Written by Denis Oliver Kropp <dok@directfb.org>,
8 Andreas Hundt <andi@fischlustig.de>,
9 Sven Neumann <neo@directfb.org>,
10 Ville Syrjälä <syrjala@sci.fi> and
11 Claudio Ciccani <klan@users.sf.net>.
12
13 This library is free software; you can redistribute it and/or
14 modify it under the terms of the GNU Lesser General Public
15 License as published by the Free Software Foundation; either
16 version 2 of the License, or (at your option) any later version.
17
18 This library is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 Lesser General Public License for more details.
22
23 You should have received a copy of the GNU Lesser General Public
24 License along with this library; if not, write to the
25 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
26 Boston, MA 02111-1307, USA.
27 */
28
29 #include <config.h>
30
31 #include <stdio.h>
32
33 #include <directfb.h>
34
35 #include <direct/messages.h>
36
37 #include <core/coredefs.h>
38 #include <core/coretypes.h>
39 #include <core/layers.h>
40 #include <core/screen.h>
41 #include <core/surface.h>
42
43 #include <misc/conf.h>
44
45 #include "regs.h"
46 #include "mmio.h"
47 #include "matrox.h"
48 #include "matrox_maven.h"
49
50 typedef struct {
51 CoreLayerRegionConfig config;
52 DFBColorAdjustment adj;
53 int field;
54
55 /* Stored registers */
56 struct {
57 /* CRTC2 */
58 u32 c2CTL;
59 u32 c2DATACTL;
60 u32 c2MISC;
61 u32 c2OFFSET;
62
63 u32 c2HPARAM;
64 u32 c2VPARAM;
65
66 u32 c2STARTADD0;
67 u32 c2STARTADD1;
68 u32 c2PL2STARTADD0;
69 u32 c2PL2STARTADD1;
70 u32 c2PL3STARTADD0;
71 u32 c2PL3STARTADD1;
72 } regs;
73
74 MatroxMavenData mav;
75 } MatroxCrtc2LayerData;
76
77 static void crtc2_set_regs ( MatroxDriverData *mdrv,
78 MatroxCrtc2LayerData *mcrtc2 );
79
80 static void crtc2_calc_regs ( MatroxDriverData *mdrv,
81 MatroxCrtc2LayerData *mcrtc2,
82 CoreLayerRegionConfig *config,
83 CoreSurface *surface,
84 CoreSurfaceBufferLock *lock );
85
86 static void crtc2_calc_buffer ( MatroxDriverData *mdrv,
87 MatroxCrtc2LayerData *mcrtc2,
88 CoreSurface *surface,
89 CoreSurfaceBufferLock *lock );
90
91 static void crtc2_set_buffer ( MatroxDriverData *mdrv,
92 MatroxCrtc2LayerData *mcrtc2 );
93
94 static DFBResult crtc2_disable_output( MatroxDriverData *mdrv,
95 MatroxCrtc2LayerData *mcrtc2 );
96
97 static DFBResult crtc2_enable_output ( MatroxDriverData *mdrv,
98 MatroxCrtc2LayerData *mcrtc2 );
99
100 #define CRTC2_SUPPORTED_OPTIONS (DLOP_FIELD_PARITY)
101
102 /**********************/
103
104 static int
crtc2LayerDataSize(void)105 crtc2LayerDataSize( void )
106 {
107 return sizeof(MatroxCrtc2LayerData);
108 }
109
110 static const DFBColorAdjustment adjustments[2][2] = {
111 /* G400 */
112 {
113 /* PAL / PAL-60 */
114 {
115 .flags = DCAF_BRIGHTNESS | DCAF_CONTRAST | DCAF_HUE | DCAF_SATURATION,
116 .brightness = 0xA800,
117 .saturation = 0x9500,
118 .contrast = 0xFF00,
119 .hue = 0x0000,
120 },
121 /* NTSC */
122 {
123 .flags = DCAF_BRIGHTNESS | DCAF_CONTRAST | DCAF_HUE | DCAF_SATURATION,
124 .brightness = 0xB500,
125 .saturation = 0x8E00,
126 .contrast = 0xEA00,
127 .hue = 0x0000,
128 }
129 },
130 /* G450 / G550 */
131 {
132 /* PAL / PAL-60 */
133 {
134 .flags = DCAF_BRIGHTNESS | DCAF_CONTRAST | DCAF_HUE | DCAF_SATURATION,
135 .brightness = 0x9E00,
136 .saturation = 0xBB00,
137 .contrast = 0xFF00,
138 .hue = 0x0000,
139 },
140 /* NTSC */
141 {
142 .flags = DCAF_BRIGHTNESS | DCAF_CONTRAST | DCAF_HUE | DCAF_SATURATION,
143 .brightness = 0xAA00,
144 .saturation = 0xAE00,
145 .contrast = 0xEA00,
146 .hue = 0x0000,
147 }
148 }
149 };
150
151 static DFBResult
crtc2InitLayer(CoreLayer * layer,void * driver_data,void * layer_data,DFBDisplayLayerDescription * description,DFBDisplayLayerConfig * config,DFBColorAdjustment * adjustment)152 crtc2InitLayer( CoreLayer *layer,
153 void *driver_data,
154 void *layer_data,
155 DFBDisplayLayerDescription *description,
156 DFBDisplayLayerConfig *config,
157 DFBColorAdjustment *adjustment )
158 {
159 MatroxDriverData *mdrv = (MatroxDriverData*) driver_data;
160 MatroxCrtc2LayerData *mcrtc2 = (MatroxCrtc2LayerData*) layer_data;
161 MatroxDeviceData *mdev = mdrv->device_data;
162 MatroxMavenData *mav = &mcrtc2->mav;
163 DFBResult res;
164
165 if ((res = maven_init( mav, mdrv )) != DFB_OK)
166 return res;
167
168 /* set capabilities and type */
169 description->caps = DLCAPS_SURFACE | DLCAPS_FIELD_PARITY |
170 DLCAPS_BRIGHTNESS | DLCAPS_CONTRAST |
171 DLCAPS_HUE | DLCAPS_SATURATION | DLCAPS_ALPHA_RAMP;
172 description->type = DLTF_GRAPHICS | DLTF_VIDEO | DLTF_STILL_PICTURE;
173
174 /* set name */
175 snprintf( description->name,
176 DFB_DISPLAY_LAYER_DESC_NAME_LENGTH, "Matrox CRTC2 Layer" );
177
178 /* fill out the default configuration */
179 config->flags = DLCONF_WIDTH | DLCONF_HEIGHT |
180 DLCONF_PIXELFORMAT | DLCONF_BUFFERMODE |
181 DLCONF_OPTIONS | DLCONF_SURFACE_CAPS;
182 config->width = 720;
183 config->height = (dfb_config->matrox_tv_std != DSETV_PAL) ? 480 : 576;
184 config->pixelformat = DSPF_YUY2;
185 config->buffermode = DLBM_FRONTONLY;
186 config->options = DLOP_NONE;
187 config->surface_caps = DSCAPS_INTERLACED;
188
189 /* fill out default color adjustment,
190 only fields set in flags will be accepted from applications */
191 *adjustment = adjustments[mdev->g450_matrox][dfb_config->matrox_tv_std == DSETV_NTSC];
192
193 /* remember color adjustment */
194 mcrtc2->adj = *adjustment;
195
196 return DFB_OK;
197 }
198
199 static DFBResult
crtc2TestRegion(CoreLayer * layer,void * driver_data,void * layer_data,CoreLayerRegionConfig * config,CoreLayerRegionConfigFlags * failed)200 crtc2TestRegion( CoreLayer *layer,
201 void *driver_data,
202 void *layer_data,
203 CoreLayerRegionConfig *config,
204 CoreLayerRegionConfigFlags *failed )
205 {
206 CoreLayerRegionConfigFlags fail = 0;
207
208 if (config->options & ~CRTC2_SUPPORTED_OPTIONS)
209 fail |= CLRCF_OPTIONS;
210
211 if (config->surface_caps & ~(DSCAPS_INTERLACED | DSCAPS_SEPARATED))
212 fail |= CLRCF_SURFACE_CAPS;
213
214 switch (config->format) {
215 case DSPF_ARGB:
216 case DSPF_RGB32:
217 case DSPF_RGB555:
218 case DSPF_ARGB1555:
219 case DSPF_RGB16:
220 case DSPF_YUY2:
221 case DSPF_UYVY:
222 case DSPF_I420:
223 case DSPF_YV12:
224 break;
225 default:
226 fail |= CLRCF_FORMAT;
227 }
228
229 if (config->width != 720)
230 fail |= CLRCF_WIDTH;
231
232 if (config->height != ((dfb_config->matrox_tv_std != DSETV_PAL) ? 480 : 576))
233 fail |= CLRCF_HEIGHT;
234
235 if (failed)
236 *failed = fail;
237
238 if (fail)
239 return DFB_UNSUPPORTED;
240
241 return DFB_OK;
242 }
243
244 static DFBResult
crtc2AddRegion(CoreLayer * layer,void * driver_data,void * layer_data,void * region_data,CoreLayerRegionConfig * config)245 crtc2AddRegion( CoreLayer *layer,
246 void *driver_data,
247 void *layer_data,
248 void *region_data,
249 CoreLayerRegionConfig *config )
250 {
251 return DFB_OK;
252 }
253
254 static DFBResult
crtc2SetRegion(CoreLayer * layer,void * driver_data,void * layer_data,void * region_data,CoreLayerRegionConfig * config,CoreLayerRegionConfigFlags updated,CoreSurface * surface,CorePalette * palette,CoreSurfaceBufferLock * lock)255 crtc2SetRegion( CoreLayer *layer,
256 void *driver_data,
257 void *layer_data,
258 void *region_data,
259 CoreLayerRegionConfig *config,
260 CoreLayerRegionConfigFlags updated,
261 CoreSurface *surface,
262 CorePalette *palette,
263 CoreSurfaceBufferLock *lock )
264 {
265 DFBResult ret;
266 MatroxDriverData *mdrv = (MatroxDriverData*) driver_data;
267 MatroxCrtc2LayerData *mcrtc2 = (MatroxCrtc2LayerData*) layer_data;
268 MatroxDeviceData *mdev = mdrv->device_data;
269
270 /* remember configuration */
271 mcrtc2->config = *config;
272
273 if (updated & CLRCF_PARITY)
274 mcrtc2->field = !config->parity;
275
276 if (updated & (CLRCF_WIDTH | CLRCF_HEIGHT | CLRCF_FORMAT |
277 CLRCF_SURFACE_CAPS | CLRCF_ALPHA_RAMP | CLRCF_SURFACE)) {
278 crtc2_calc_regs( mdrv, mcrtc2, config, surface, lock );
279 crtc2_calc_buffer( mdrv, mcrtc2, surface, lock );
280
281 ret = crtc2_enable_output( mdrv, mcrtc2 );
282 if (ret)
283 return ret;
284
285 mdev->crtc2_separated = !!(surface->config.caps & DSCAPS_SEPARATED);
286 }
287
288 return DFB_OK;
289 }
290
291 static DFBResult
crtc2RemoveRegion(CoreLayer * layer,void * driver_data,void * layer_data,void * region_data)292 crtc2RemoveRegion( CoreLayer *layer,
293 void *driver_data,
294 void *layer_data,
295 void *region_data )
296 {
297 MatroxDriverData *mdrv = (MatroxDriverData*) driver_data;
298 MatroxCrtc2LayerData *mcrtc2 = (MatroxCrtc2LayerData*) layer_data;
299
300 crtc2_disable_output( mdrv, mcrtc2 );
301
302 return DFB_OK;
303 }
304
305 static DFBResult
crtc2FlipRegion(CoreLayer * layer,void * driver_data,void * layer_data,void * region_data,CoreSurface * surface,DFBSurfaceFlipFlags flags,CoreSurfaceBufferLock * lock)306 crtc2FlipRegion( CoreLayer *layer,
307 void *driver_data,
308 void *layer_data,
309 void *region_data,
310 CoreSurface *surface,
311 DFBSurfaceFlipFlags flags,
312 CoreSurfaceBufferLock *lock )
313 {
314 MatroxDriverData *mdrv = (MatroxDriverData*) driver_data;
315 MatroxCrtc2LayerData *mcrtc2 = (MatroxCrtc2LayerData*) layer_data;
316 volatile u8 *mmio = mdrv->mmio_base;
317
318 crtc2_calc_buffer( mdrv, mcrtc2, surface, lock );
319
320 if (mcrtc2->config.options & DLOP_FIELD_PARITY) {
321 int field = (mga_in32( mmio, C2VCOUNT ) & C2FIELD) ? 1 : 0;
322
323 while (field == mcrtc2->field) {
324 dfb_screen_wait_vsync( mdrv->secondary );
325
326 field = (mga_in32( mmio, C2VCOUNT ) & C2FIELD) ? 1 : 0;
327 }
328 }
329 crtc2_set_buffer( mdrv, mcrtc2 );
330
331 dfb_surface_flip( surface, false );
332
333 if (flags & DSFLIP_WAIT)
334 dfb_screen_wait_vsync( mdrv->secondary );
335
336 return DFB_OK;
337 }
338
339 static DFBResult
crtc2SetColorAdjustment(CoreLayer * layer,void * driver_data,void * layer_data,DFBColorAdjustment * adj)340 crtc2SetColorAdjustment( CoreLayer *layer,
341 void *driver_data,
342 void *layer_data,
343 DFBColorAdjustment *adj )
344 {
345 MatroxDriverData *mdrv = (MatroxDriverData*) driver_data;
346 MatroxCrtc2LayerData *mcrtc2 = (MatroxCrtc2LayerData*) layer_data;
347 MatroxMavenData *mav = &mcrtc2->mav;
348 DFBResult res;
349
350 if ((res = maven_open( mav, mdrv )) != DFB_OK)
351 return res;
352
353 if (adj->flags & DCAF_HUE)
354 maven_set_hue( mav, mdrv,
355 adj->hue >> 8 );
356 if (adj->flags & DCAF_SATURATION)
357 maven_set_saturation( mav, mdrv,
358 adj->saturation >> 8 );
359 if (adj->flags & DCAF_BRIGHTNESS ||
360 adj->flags & DCAF_CONTRAST)
361 maven_set_bwlevel( mav, mdrv,
362 adj->brightness >> 8,
363 adj->contrast >> 8 );
364
365 maven_close( mav, mdrv );
366
367 /* remember color adjustment */
368 mcrtc2->adj = *adj;
369
370 return DFB_OK;
371 }
372
373 static DFBResult
crtc2GetCurrentOutputField(CoreLayer * layer,void * driver_data,void * layer_data,int * field)374 crtc2GetCurrentOutputField( CoreLayer *layer,
375 void *driver_data,
376 void *layer_data,
377 int *field )
378 {
379 MatroxDriverData *mdrv = (MatroxDriverData*) driver_data;
380
381 if (!field)
382 return DFB_INVARG;
383
384 *field = (mga_in32( mdrv->mmio_base, C2VCOUNT ) & C2FIELD) ? 1 : 0;
385
386 return DFB_OK;
387 }
388
389 DisplayLayerFuncs matroxCrtc2Funcs = {
390 .LayerDataSize = crtc2LayerDataSize,
391 .InitLayer = crtc2InitLayer,
392
393 .TestRegion = crtc2TestRegion,
394 .AddRegion = crtc2AddRegion,
395 .SetRegion = crtc2SetRegion,
396 .RemoveRegion = crtc2RemoveRegion,
397 .FlipRegion = crtc2FlipRegion,
398
399 .SetColorAdjustment = crtc2SetColorAdjustment,
400 .GetCurrentOutputField = crtc2GetCurrentOutputField,
401 };
402
403 /* internal */
404
crtc2_set_regs(MatroxDriverData * mdrv,MatroxCrtc2LayerData * mcrtc2)405 static void crtc2_set_regs( MatroxDriverData *mdrv,
406 MatroxCrtc2LayerData *mcrtc2 )
407 {
408 volatile u8 *mmio = mdrv->mmio_base;
409
410 mga_out32( mmio, mcrtc2->regs.c2CTL, C2CTL );
411 mga_out32( mmio, mcrtc2->regs.c2DATACTL, C2DATACTL );
412 mga_out32( mmio, mcrtc2->regs.c2HPARAM, C2HPARAM );
413 mga_out32( mmio, 0, C2HSYNC );
414 mga_out32( mmio, mcrtc2->regs.c2VPARAM, C2VPARAM );
415 mga_out32( mmio, 0, C2VSYNC );
416 mga_out32( mmio, mcrtc2->regs.c2OFFSET, C2OFFSET );
417 mga_out32( mmio, mcrtc2->regs.c2MISC, C2MISC );
418 mga_out32( mmio, 0, C2PRELOAD );
419 }
420
crtc2_calc_regs(MatroxDriverData * mdrv,MatroxCrtc2LayerData * mcrtc2,CoreLayerRegionConfig * config,CoreSurface * surface,CoreSurfaceBufferLock * lock)421 static void crtc2_calc_regs( MatroxDriverData *mdrv,
422 MatroxCrtc2LayerData *mcrtc2,
423 CoreLayerRegionConfig *config,
424 CoreSurface *surface,
425 CoreSurfaceBufferLock *lock )
426 {
427 MatroxDeviceData *mdev = mdrv->device_data;
428
429 mcrtc2->regs.c2CTL = 0;
430
431 /* Don't touch sub-picture bits. */
432 mcrtc2->regs.c2DATACTL = mga_in32( mdrv->mmio_base, C2DATACTL );
433 mcrtc2->regs.c2DATACTL &= C2STATICKEY | C2OFFSETDIVEN | C2STATICKEYEN | C2SUBPICEN;
434
435 if (mdev->g450_matrox)
436 mcrtc2->regs.c2CTL |= C2PIXCLKSEL_CRISTAL;
437 else
438 mcrtc2->regs.c2CTL |= C2PIXCLKSEL_VDOCLK;
439
440 /*
441 * High priority request level.
442 * According to G400 specs these values should
443 * be fixed when CRTC2 is in YUV mode.
444 */
445 /* c2hiprilvl */
446 mcrtc2->regs.c2CTL |= 2 << 4;
447 /* c2maxhipri */
448 mcrtc2->regs.c2CTL |= 1 << 8;
449
450 switch (surface->config.format) {
451 case DSPF_RGB555:
452 case DSPF_ARGB1555:
453 case DSPF_RGB16:
454 case DSPF_RGB32:
455 case DSPF_ARGB:
456 mcrtc2->regs.c2DATACTL |= C2DITHEN | C2YFILTEN | C2CBCRFILTEN;
457 break;
458 default:
459 break;
460 }
461
462 if (dfb_config->matrox_tv_std != DSETV_PAL)
463 mcrtc2->regs.c2DATACTL |= C2NTSCEN;
464
465 /* pixel format settings */
466 switch (surface->config.format) {
467 case DSPF_I420:
468 case DSPF_YV12:
469 mcrtc2->regs.c2CTL |= C2DEPTH_YCBCR420;
470 break;
471
472 case DSPF_UYVY:
473 mcrtc2->regs.c2DATACTL |= C2UYVYFMT;
474 /* fall through */
475
476 case DSPF_YUY2:
477 mcrtc2->regs.c2CTL |= C2DEPTH_YCBCR422;
478 break;
479
480 case DSPF_RGB555:
481 case DSPF_ARGB1555:
482 mcrtc2->regs.c2CTL |= C2DEPTH_15BPP;
483 break;
484
485 case DSPF_RGB16:
486 mcrtc2->regs.c2CTL |= C2DEPTH_16BPP;
487 break;
488
489 case DSPF_RGB32:
490 case DSPF_ARGB:
491 mcrtc2->regs.c2CTL |= C2DEPTH_32BPP;
492 break;
493
494 default:
495 D_BUG( "unexpected pixelformat" );
496 return;
497 }
498
499 if (!(surface->config.caps & DSCAPS_INTERLACED))
500 mcrtc2->regs.c2CTL |= C2VCBCRSINGLE;
501
502 mcrtc2->regs.c2OFFSET = lock->pitch;
503 if (!(surface->config.caps & DSCAPS_SEPARATED))
504 mcrtc2->regs.c2OFFSET *= 2;
505
506 {
507 int hdisplay, htotal, vdisplay, vtotal;
508
509 if (dfb_config->matrox_tv_std != DSETV_PAL) {
510 hdisplay = 720;
511 htotal = 858;
512 vdisplay = 480 / 2;
513 vtotal = 525 / 2;
514 } else {
515 hdisplay = 720;
516 htotal = 864;
517 vdisplay = 576 / 2;
518 vtotal = 625 / 2;
519 }
520
521 mcrtc2->regs.c2HPARAM = ((hdisplay - 8) << 16) | (htotal - 8);
522 mcrtc2->regs.c2VPARAM = ((vdisplay - 1) << 16) | (vtotal - 1);
523
524 mcrtc2->regs.c2MISC = 0;
525 /* c2vlinecomp */
526 mcrtc2->regs.c2MISC |= (vdisplay + 1) << 16;
527 }
528
529 /* c2bpp15halpha */
530 mcrtc2->regs.c2DATACTL |= config->alpha_ramp[3] << 8;
531
532 /* c2bpp15lalpha */
533 mcrtc2->regs.c2DATACTL |= config->alpha_ramp[0] << 16;
534 }
535
crtc2_calc_buffer(MatroxDriverData * mdrv,MatroxCrtc2LayerData * mcrtc2,CoreSurface * surface,CoreSurfaceBufferLock * lock)536 static void crtc2_calc_buffer( MatroxDriverData *mdrv,
537 MatroxCrtc2LayerData *mcrtc2,
538 CoreSurface *surface,
539 CoreSurfaceBufferLock *lock )
540 {
541 unsigned int field_offset = lock->pitch;
542
543 if (surface->config.caps & DSCAPS_SEPARATED)
544 field_offset *= surface->config.size.h / 2;
545
546 mcrtc2->regs.c2STARTADD1 = lock->offset;
547 mcrtc2->regs.c2STARTADD0 = mcrtc2->regs.c2STARTADD1 + field_offset;
548
549 if (surface->config.caps & DSCAPS_INTERLACED)
550 field_offset = lock->pitch / 2;
551 else
552 field_offset = 0;
553
554 if (surface->config.caps & DSCAPS_SEPARATED)
555 field_offset *= surface->config.size.h / 4;
556
557 switch (surface->config.format) {
558 case DSPF_I420:
559 mcrtc2->regs.c2PL2STARTADD1 = mcrtc2->regs.c2STARTADD1 + surface->config.size.h * lock->pitch;
560 mcrtc2->regs.c2PL2STARTADD0 = mcrtc2->regs.c2PL2STARTADD1 + field_offset;
561
562 mcrtc2->regs.c2PL3STARTADD1 = mcrtc2->regs.c2PL2STARTADD1 + surface->config.size.h/2 * lock->pitch/2;
563 mcrtc2->regs.c2PL3STARTADD0 = mcrtc2->regs.c2PL3STARTADD1 + field_offset;
564 break;
565 case DSPF_YV12:
566 mcrtc2->regs.c2PL3STARTADD1 = mcrtc2->regs.c2STARTADD1 + surface->config.size.h * lock->pitch;
567 mcrtc2->regs.c2PL3STARTADD0 = mcrtc2->regs.c2PL3STARTADD1 + field_offset;
568
569 mcrtc2->regs.c2PL2STARTADD1 = mcrtc2->regs.c2PL3STARTADD1 + surface->config.size.h/2 * lock->pitch/2;
570 mcrtc2->regs.c2PL2STARTADD0 = mcrtc2->regs.c2PL2STARTADD1 + field_offset;
571 break;
572 default:
573 break;
574 }
575 }
576
crtc2_set_buffer(MatroxDriverData * mdrv,MatroxCrtc2LayerData * mcrtc2)577 static void crtc2_set_buffer( MatroxDriverData *mdrv,
578 MatroxCrtc2LayerData *mcrtc2 )
579 {
580 volatile u8 *mmio = mdrv->mmio_base;
581
582 mga_out32( mmio, mcrtc2->regs.c2STARTADD0, C2STARTADD0 );
583 mga_out32( mmio, mcrtc2->regs.c2STARTADD1, C2STARTADD1 );
584 mga_out32( mmio, mcrtc2->regs.c2PL2STARTADD0, C2PL2STARTADD0 );
585 mga_out32( mmio, mcrtc2->regs.c2PL2STARTADD1, C2PL2STARTADD1 );
586 mga_out32( mmio, mcrtc2->regs.c2PL3STARTADD0, C2PL3STARTADD0 );
587 mga_out32( mmio, mcrtc2->regs.c2PL3STARTADD1, C2PL3STARTADD1 );
588 }
589
590 static void
crtc2OnOff(MatroxDriverData * mdrv,MatroxCrtc2LayerData * mcrtc2,int on)591 crtc2OnOff( MatroxDriverData *mdrv,
592 MatroxCrtc2LayerData *mcrtc2,
593 int on )
594 {
595 volatile u8 *mmio = mdrv->mmio_base;
596
597 if (on)
598 mcrtc2->regs.c2CTL |= C2EN;
599 else
600 mcrtc2->regs.c2CTL &= ~C2EN;
601 mga_out32( mmio, mcrtc2->regs.c2CTL, C2CTL );
602
603 if (on)
604 mcrtc2->regs.c2CTL &= ~C2PIXCLKDIS;
605 else
606 mcrtc2->regs.c2CTL |= C2PIXCLKDIS;
607 mga_out32( mmio, mcrtc2->regs.c2CTL, C2CTL );
608
609 if (!on) {
610 mcrtc2->regs.c2CTL &= ~C2INTERLACE;
611 mga_out32( mmio, mcrtc2->regs.c2CTL, C2CTL );
612 }
613 }
614
crtc2_set_mafc(MatroxDriverData * mdrv,int on)615 static void crtc2_set_mafc( MatroxDriverData *mdrv,
616 int on )
617 {
618 volatile u8 *mmio = mdrv->mmio_base;
619 u8 val;
620
621 val = mga_in_dac( mmio, XMISCCTRL );
622 if (on) {
623 val &= ~(MFCSEL_MASK | VDOUTSEL_MASK);
624 val |= MFCSEL_MAFC | VDOUTSEL_CRTC2656;
625 } else {
626 val &= ~MFCSEL_MASK;
627 val |= MFCSEL_DIS;
628 }
629 mga_out_dac( mmio, XMISCCTRL, val );
630 }
631
632 static DFBResult
crtc2_disable_output(MatroxDriverData * mdrv,MatroxCrtc2LayerData * mcrtc2)633 crtc2_disable_output( MatroxDriverData *mdrv,
634 MatroxCrtc2LayerData *mcrtc2 )
635 {
636 MatroxDeviceData *mdev = mdrv->device_data;
637 MatroxMavenData *mav = &mcrtc2->mav;
638 DFBResult res;
639
640 if ((res = maven_open( mav, mdrv )) != DFB_OK)
641 return res;
642
643 maven_disable( mav, mdrv );
644 if (!mdev->g450_matrox)
645 crtc2_set_mafc( mdrv, 0 );
646 crtc2OnOff( mdrv, mcrtc2, 0 );
647
648 maven_close( mav, mdrv );
649
650 if (mdev->g450_matrox) {
651 volatile u8 *mmio = mdrv->mmio_base;
652 u8 val;
653
654 /* Set Rset to 0.7 V */
655 val = mga_in_dac( mmio, XGENIOCTRL );
656 val &= ~0x40;
657 mga_out_dac( mmio, XGENIOCTRL, val );
658 val = mga_in_dac( mmio, XGENIODATA );
659 val &= ~0x40;
660 mga_out_dac( mmio, XGENIODATA, val );
661
662 val = mga_in_dac( mmio, XPWRCTRL );
663 val &= ~(DAC2PDN | CFIFOPDN);
664 mga_out_dac( mmio, XPWRCTRL, val );
665
666 val = mga_in_dac( mmio, XDISPCTRL );
667 val &= ~DAC2OUTSEL_MASK;
668 val |= DAC2OUTSEL_DIS;
669 mga_out_dac( mmio, XDISPCTRL, val );
670 }
671
672 return DFB_OK;
673 }
674
675 static DFBResult
crtc2_enable_output(MatroxDriverData * mdrv,MatroxCrtc2LayerData * mcrtc2)676 crtc2_enable_output( MatroxDriverData *mdrv,
677 MatroxCrtc2LayerData *mcrtc2 )
678 {
679 MatroxDeviceData *mdev = mdrv->device_data;
680 MatroxMavenData *mav = &mcrtc2->mav;
681 volatile u8 *mmio = mdrv->mmio_base;
682 DFBResult res;
683
684 if ((res = maven_open( mav, mdrv )) != DFB_OK)
685 return res;
686
687 if (mdev->g450_matrox) {
688 volatile u8 *mmio = mdrv->mmio_base;
689 u8 val;
690
691 /* Set Rset to 1.0 V */
692 val = mga_in_dac( mmio, XGENIOCTRL );
693 val |= 0x40;
694 mga_out_dac( mmio, XGENIOCTRL, val );
695 val = mga_in_dac( mmio, XGENIODATA );
696 val &= ~0x40;
697 mga_out_dac( mmio, XGENIODATA, val );
698
699 val = mga_in_dac( mmio, XPWRCTRL );
700 val |= DAC2PDN | CFIFOPDN;
701 mga_out_dac( mmio, XPWRCTRL, val );
702
703 val = mga_in_dac( mmio, XDISPCTRL );
704 val &= ~DAC2OUTSEL_MASK;
705 val |= DAC2OUTSEL_TVE;
706 mga_out_dac( mmio, XDISPCTRL, val );
707
708 if (dfb_config->matrox_cable == 1) {
709 val = mga_in_dac( mmio, XSYNCCTRL );
710 val &= ~(DAC2HSOFF | DAC2VSOFF | DAC2HSPOL | DAC2VSPOL);
711 mga_out_dac( mmio, XSYNCCTRL, val );
712 }
713 }
714
715 maven_disable( mav, mdrv );
716 if (!mdev->g450_matrox)
717 crtc2_set_mafc( mdrv, 0 );
718 crtc2OnOff( mdrv, mcrtc2, 0 );
719
720 crtc2_set_regs( mdrv, mcrtc2 );
721 crtc2_set_buffer( mdrv, mcrtc2 );
722
723 if (!mdev->g450_matrox)
724 crtc2_set_mafc( mdrv, 1 );
725 crtc2OnOff( mdrv, mcrtc2, 1 );
726
727 maven_set_regs( mav, mdrv, &mcrtc2->config, &mcrtc2->adj );
728
729 mcrtc2->regs.c2CTL |= C2INTERLACE;
730 if (mdev->g450_matrox)
731 mcrtc2->regs.c2CTL |= 0x1000; /* Undocumented bit */
732 while ((mga_in32( mmio, C2VCOUNT ) & 0x00000FFF) != 1)
733 ;
734 while ((mga_in32( mmio, C2VCOUNT ) & 0x00000FFF) != 0)
735 ;
736 mga_out32( mmio, mcrtc2->regs.c2CTL, C2CTL );
737
738 maven_enable( mav, mdrv );
739
740 if (!mdev->g450_matrox) {
741 while ((mga_in32( mmio, C2VCOUNT ) & 0x00000FFF) != 1)
742 ;
743 while ((mga_in32( mmio, C2VCOUNT ) & 0x00000FFF) != 0)
744 ;
745 maven_sync( mav, mdrv );
746 }
747
748 maven_close( mav, mdrv );
749
750 return DFB_OK;
751 }
752