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