home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-385-Vol-1of3.iso / d / ddx-mips.zip / MIPS4000.C < prev    next >
C/C++ Source or Header  |  1992-06-10  |  22KB  |  1,043 lines

  1. /*
  2.  * $XConsortium$
  3.  *
  4.  * Copyright 1991 MIPS Computer Systems, Inc.
  5.  *
  6.  * Permission to use, copy, modify, distribute, and sell this software and its
  7.  * documentation for any purpose is hereby granted without fee, provided that
  8.  * the above copyright notice appear in all copies and that both that
  9.  * copyright notice and this permission notice appear in supporting
  10.  * documentation, and that the name of MIPS not be used in advertising or
  11.  * publicity pertaining to distribution of the software without specific,
  12.  * written prior permission.  MIPS makes no representations about the
  13.  * suitability of this software for any purpose.  It is provided "as is"
  14.  * without express or implied warranty.
  15.  *
  16.  * MIPS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
  17.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL MIPS
  18.  * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  19.  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
  20.  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 
  21.  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  22.  */
  23. #ident    "$Header: mips4000.c,v 1.11 92/06/10 15:21:05 dd Exp $"
  24.  
  25. /*
  26.  * Device support for the RC4030 VDRxx frame buffers
  27.  *
  28.  * Note: This code is used only when the RISC/os frame buffer device
  29.  * driver is not available (cf. mipsGenFb.c).
  30.  */
  31.  
  32. #include <sys/types.h>
  33.  
  34. #include <X.h>
  35. #include <Xproto.h>
  36. #include <misc.h>
  37. #include <cursorstr.h>
  38. #include <input.h>
  39. #include <scrnintstr.h>
  40. #include <servermd.h>
  41.  
  42. #include "mipsFb.h"
  43. #include "mips4000.h"
  44. #include "fb_vdr1.h"
  45. #include "fb_vdr2.h"
  46.  
  47. #ifdef _MIPSEL
  48. #define    VDR2_SUPPORT
  49. #endif
  50.  
  51. #ifndef _MIPSEL
  52. #define    VDR_CURSOR_SUPPORT
  53. #endif
  54.  
  55. #ifndef _KERNEL
  56. #undef DELAY
  57. #define DELAY(usec) mipsUsleep(usec)
  58. #endif
  59.  
  60. #define    ITEMSIN(a)    (sizeof (a) / sizeof (a)[0])
  61. #define    ENDOF(a)    (&(a)[ITEMSIN(a)])
  62.  
  63. #ifdef FBDEBUG
  64. int fb_debug = FBDEBUG;
  65. #define    DEBUGF(level, args) if (fb_debug >= (level)) printf args; else
  66. #else
  67. #define    DEBUGF(level, args) /* nothing */
  68. #endif
  69.  
  70. #ifdef VDREXPORT
  71. #define    STATIC /* nothing */
  72. #else
  73. #define STATIC static
  74. #endif
  75.  
  76. static int vdr1_set_video(), vdr1_get_video(),
  77.     vdr1_set_colormap(), vdr1_get_colormap();
  78.  
  79. #ifdef VDR2_SUPPORT
  80. static int vdr2_set_video(), vdr2_get_video(),
  81.     vdr2_set_colormap(), vdr2_get_colormap();
  82. #endif /* VDR2_SUPPORT */
  83.  
  84. static struct fb_ops {
  85.     int (*set_video)();
  86.     int (*get_video)();
  87.     int (*set_colormap)();
  88.     int (*get_colormap)();
  89. } fb_ops[] = {
  90.     {
  91.         vdr1_set_video,
  92.         vdr1_get_video,
  93.         vdr1_set_colormap,
  94.         vdr1_get_colormap,
  95.     },
  96. #ifdef VDR2_SUPPORT
  97.     {
  98.         vdr2_set_video,
  99.         vdr2_get_video,
  100.         vdr2_set_colormap,
  101.         vdr2_get_colormap,
  102.     },
  103. #endif /* VDR2_SUPPORT */
  104. };
  105.  
  106. /*
  107.  * RISCwindows ddx interface
  108.  */
  109.  
  110. /* borrow unused entries in pm structure */
  111. #define    FBTYPE(pm)    ((pm)->fd)
  112. #define    FBREG(pm)    ((pm)->fbcache)
  113. #define    FBOPS(pm)    ((pm)->fbspec)
  114. #define    FBOP(pm, func)    (*((struct fb_ops *) (pm)->fbspec)->func)
  115.  
  116. extern char *mipsMapit();
  117.  
  118. static void Blank4000();
  119. static void WriteCMap4000();
  120. static void Close4000();
  121.  
  122. #ifdef VDR_CURSOR_SUPPORT
  123. static Bool RealizeCursor4000();
  124. static void SetCursor4000();
  125. static void MoveCursor4000();
  126. static void RecolorCursor4000();
  127. #endif /* VDR_CURSOR_SUPPORT */
  128.  
  129. Bool
  130. mipsMap4000(pm)
  131.     MipsScreenPtr pm;
  132. {
  133.     if (!pm->fbreg && (
  134.         !(pm->fbnocache = (unsigned char *) mipsMapit((char *) 0,
  135.             RS4000_FBKEY, RS4000_FBSIZE)) ||
  136.         !(pm->fbreg = (unsigned char *) mipsMapit((char *) 0,
  137.             RS4000_REGKEY, RS4000_REGSIZE))))
  138.         return FALSE;
  139.  
  140.     pm->fbnorm = pm->fbnocache;
  141.  
  142.     mipsInitColor(pm);
  143.  
  144.     if (Init4000(pm) < 0)
  145.         return FALSE;
  146.  
  147.     pm->Blank = Blank4000;
  148.     pm->WriteCMap = WriteCMap4000;
  149.     pm->Close = Close4000;
  150.  
  151. #ifdef VDR_CURSOR_SUPPORT
  152.     if (!(pm->option & MIPS_SCR_NOHW) &&
  153.         FBTYPE(pm) > 0) {
  154.         pm->cap |= MIPS_SCR_CURSOR;
  155.  
  156.         pm->RealizeCursor = RealizeCursor4000;
  157.         pm->SetCursor = SetCursor4000;
  158.         pm->MoveCursor = MoveCursor4000;
  159.         pm->RecolorCursor = RecolorCursor4000;
  160.     }
  161. #endif /* VDR_CURSOR_SUPPORT */
  162.  
  163.     return TRUE;
  164. }
  165.  
  166. static void
  167. Blank4000(pm, on)
  168.     MipsScreenPtr pm;
  169.     Bool on;
  170. {
  171.     FBOP(pm, set_video)(FBREG(pm), on != SCREEN_SAVER_ON);
  172. }
  173.  
  174. static void
  175. WriteCMap4000(pm, index, count, rgb)
  176.     MipsScreenPtr pm;
  177.     int index;
  178.     int count;
  179.     unsigned char *rgb;
  180. {
  181.     FBOP(pm, set_colormap)(FBREG(pm), index, count, rgb);
  182. }
  183.  
  184. /* ARGSUSED */
  185. static void
  186. Close4000(pm)
  187.     MipsScreenPtr pm;
  188. {
  189. #ifdef VDR_CURSOR_SUPPORT
  190.     /* disable HW cursor */
  191.     SetCursor4000(pm, (CursorPtr) 0, (pointer) 0, 0, 0);
  192. #endif /* VDR_CURSOR_SUPPORT */
  193. }
  194.  
  195. /*
  196.  * Device support code
  197.  */
  198.  
  199. union vdr_reg {
  200.     struct vdr1_reg vdr1;
  201.     struct vdr1f_reg vdr1f;
  202.     struct vdr2_reg vdr2;
  203. };
  204.  
  205. /*
  206.  * Video timing parameters
  207.  */
  208. struct vdr_vtgval {
  209.     short w, h, vrate;    /* width, height, vertical rate */
  210.     short type;        /* parameter format (== 1 for now) */
  211.     short pixel;        /* pixel rate, MHz */
  212.     short hfp, hs, hbp;    /* horiz. parameters, pixels */
  213.     short vfp, vs, vbp;    /* vert. parameters, pixels */
  214.     short opt;        /* misc. video options */
  215. #define    VDR_VTGOPT_PLAINSYNC    1
  216. #define    VDR_VTGOPT_PEDESTAL    2
  217. };
  218. #define    VDR_VTGVAL_FIELDS    12
  219. STATIC struct vdr_vtgval *vdr_getvtg();
  220.  
  221. /*
  222.  * board characteristics
  223.  */
  224. struct vdr_opt {
  225.     char type;        /* board ID */
  226.     char flags;
  227. #define    VDRT_X8        1    /* 8.125 MHz crystal (otherwise 5 MHz) */
  228. #define VDRT_G365    2    /* has G365 RAMDAC */
  229. #define    VDRT_2M        4    /* has 2MB RAM, VRAM SAM len = 1024 */
  230. #define    VDRT_1M        8    /* has 1MB RAM, w = 1024 only */
  231. #define    VDRT_G364    16    /* has G364 RAMDAC (for 1M board) */
  232.     short pixel;        /* max. pixel rate, MHz */
  233.     int memsize;        /* VRAM size, bytes */
  234. };
  235. STATIC struct vdr_opt *vdr_getopt();
  236.  
  237.  
  238. /* ARGSUSED */
  239. Init4000(pm)
  240.     MipsScreenPtr pm;
  241. {
  242.     int type;
  243.     struct vdr_vtgval vtg[1];
  244.     struct vdr_opt *opt;
  245.     struct vdr_vtgval *newvtg;
  246.  
  247.     DEBUGF(3, ("Init4000()\n"));
  248.  
  249.     bzero((char *) vtg, sizeof vtg);
  250.     vdr_getconf(vtg);
  251.  
  252.     FBREG(pm) = pm->fbreg;
  253.     if ((type =
  254.         vdr_init((union vdr_reg **) &FBREG(pm), vtg)) < 0)
  255.         return -1;
  256.  
  257.     DEBUGF(2, ("vdr_init returned type 0x%0x, %d x %d, %dK\n",
  258.         type, vtg->w, vtg->h, vdr_getopt(type)->memsize >> 10));
  259.  
  260.     FBTYPE(pm) = type;
  261.     pm->scr_width = vtg->w;
  262.     pm->scr_height = vtg->h;
  263.     pm->fb_width =
  264.         vdr_getopt(type)->flags & VDRT_1M ? 2048 : pm->scr_width;
  265.  
  266.     FBOPS(pm) = (unsigned char *) &fb_ops[type < 1];
  267.  
  268.     return 0;
  269. }
  270.  
  271. #define    ISNUM(c) ((c) >= '0' && (c) <= '9')
  272.  
  273. /*
  274.  * vdr_getconf: extract video parameters from environment string
  275.  */
  276. STATIC
  277. vdr_getconf(vtg)
  278.     struct vdr_vtgval *vtg;
  279. {
  280.     char *cp;
  281.     int i, v;
  282.     extern char *getenv();
  283.  
  284. #ifdef FBDEBUG
  285.     if ((cp = getenv("fbdebug")))
  286.         fb_debug = atoi(cp);
  287. #endif /* FBDEBUG */
  288.  
  289.     if (!(cp = getenv("screensize")))
  290.         return;
  291.  
  292.     for (i = 0; i < VDR_VTGVAL_FIELDS; i++) {
  293.         v = atoi(cp);
  294.         if (v <= 0 && i > 3)
  295.             break;
  296.         (&vtg->w)[i] = v;
  297.         do {
  298.             v = *cp++;
  299.         } while (ISNUM(v));
  300.     }
  301.  
  302.     switch (vtg->type) {
  303.     case 0:
  304.     case 1:
  305.         /* options field is optional */
  306.         if (i == VDR_VTGVAL_FIELDS - 1 ||
  307.             i == VDR_VTGVAL_FIELDS) {
  308.             vtg->type = 1;
  309.             break;
  310.         }
  311.         /* fall through */
  312.     default:
  313.         vtg->type = 0;
  314.     }
  315.  
  316.     DEBUGF(3, ("vdr_getconf: screensize = \"%s\", vtg->type = %d\n",
  317.         getenv("screensize"), vtg->type));
  318. }
  319.  
  320.  
  321. /*
  322.  * vdr_init: board identification
  323.  */
  324. static int
  325. vdr_init(regarg, vtg)
  326.     union vdr_reg **regarg;
  327.     struct vdr_vtgval *vtg;
  328. {
  329.     union vdr_reg *reg = *regarg;
  330.     int type;
  331.  
  332.     /* start VDR2 (G300) PLL */
  333.     (void) vdr_vtginit(reg, vtg, 0, 1);
  334.  
  335.     /*
  336.      * Try to write to VDR1 ID register address:
  337.      *    VDR2: wraps to colormap
  338.      *    VDR1: ID register
  339.      *    Fission: ROM location
  340.      */
  341.     reg->vdr1.id.r = 0;
  342.     type = reg->vdr1.id.r;
  343.  
  344.     switch (type) {
  345.     case 0:
  346.         DEBUGF(3, ("vdr_init: possible type 0\n"));
  347.         /* confirm type 0 */
  348.         reg->vdr1.id.r = 0x5a;
  349.         if (reg->vdr1.id.r != 0)
  350.             return vdr_vtginit(reg, vtg, type, 0);
  351.         break;
  352.  
  353.     case 1:
  354.         DEBUGF(3, ("vdr_init: possible type 1\n"));
  355.         /* start VDR1 (G364) PLL */
  356.         (void) vdr_vtginit(reg, vtg, type, 1);
  357.         reg->vdr1.ramdac.cmap[128].r = 0x5a3ca5;
  358.         /* try to write to VDR1 colormap (Fission ROM) */
  359.         if ((reg->vdr1.ramdac.cmap[128].r & 0xffffff) == 0x5a3ca5)
  360.             return vdr_vtginit(reg, vtg, type, 0);
  361.         break;
  362.     }
  363.  
  364.     /* new style video board w/ROM */
  365.     type = reg->vdr1f.rom[0].r;
  366.     DEBUGF(3, ("vdr_init: ROM type 0x%0x\n", type));
  367.     if ((type = vdr_vtginit(reg, vtg, type, 0)) >= 0) {
  368.         DEBUGF(4, ("vdr_init: fixing register pointer\n"));
  369.         *regarg = (union vdr_reg *) ®->vdr1f.ramdac;
  370.     }
  371.     return type;
  372. }
  373.  
  374. static struct vdr_vtgval
  375. vdr_vtgval[] = {
  376. /*   w     h  hz typ pix hfp   hs  hbp vfp  vs vbp opt */
  377. { 1280, 1024, 60, 1, 110, 40, 184, 224,  1,  3, 32, 0 },
  378. { 1280, 1024, 70, 1, 130, 40, 184, 224,  1,  3, 46, 0 },
  379. { 1280, 1024, 72, 1, 135, 40, 192, 228,  1,  3, 48, 0 },
  380. { 1024,  768, 60, 1,  65, 24, 136, 160,  1,  2, 35, 0 },
  381. { 1024,  768, 70, 1,  75, 24, 136, 144,  1,  2, 35, 0 },
  382. { 1024,  768, 72, 1,  80, 24, 136, 200,  1,  2, 36, 0 },
  383. { 1152,  900, 66, 1,  95, 32, 112, 208,  1,  3, 36, 0 },
  384. { 1152,  900, 76, 1, 110, 32, 128, 224,  1,  3, 40, 0 },
  385. };
  386. #define    VTGVAL_BOOT    (&vdr_vtgval[3])
  387.  
  388. static struct vdr_opt
  389. vdr_opt[] = {
  390.     /* note: G364 is only spec-ed to 110 MHz,
  391.        usually works at 130 */
  392.     { 0x10, VDRT_2M,        130, 2048 * 1024 },
  393.     { 0x11, VDRT_2M | VDRT_G365,    135, 2048 * 1024 },
  394.     { 0x12, VDRT_1M,         85, 1024 * 1024 },
  395.     { 0x13, VDRT_1M | VDRT_G364,    110, 1024 * 1024 },
  396.     { 0x01, VDRT_X8 | VDRT_2M,    110, 2048 * 1024 },
  397. #ifdef VDR2_SUPPORT
  398.     { 0x00, VDRT_X8 | VDRT_2M,    110, 2048 * 1024 },
  399. #endif /* VDR2_SUPPORT */
  400. };
  401.  
  402. /*
  403.  * vdr_getopt: look up characteristics of video board with given type
  404.  */
  405. STATIC struct vdr_opt *
  406. vdr_getopt(type)
  407.     int type;
  408. {
  409.     struct vdr_opt *p;
  410.  
  411.     for (p = vdr_opt; p < ENDOF(vdr_opt); p++)
  412.         if (p->type == type)
  413.             return p;
  414.  
  415.     return 0;
  416. }
  417.  
  418. /*
  419.  * vdr_vtginit: locate video parameters, start VTG
  420.  */
  421. static int
  422. vdr_vtginit(reg, vtg, type, boot)
  423.     union vdr_reg *reg;
  424.     struct vdr_vtgval *vtg;
  425.     int type, boot;
  426. {
  427.     struct vdr_opt *opt;
  428.     struct vdr_vtgval *newvtg;
  429.  
  430.     DEBUGF(3, ("vdr_vtginit()\n"));
  431.  
  432.     if ((opt = vdr_getopt(type)) == 0)
  433.         return -1;
  434.  
  435.     /* incorrect resolution reverts to default */
  436.     if (vtg->type == 0 || vdr_vtgck(vtg, opt)) {
  437.         if ((newvtg = vdr_getvtg(vtg, type, boot)) == 0) {
  438.             DEBUGF(2, ("vdr_vtginit: using default resolution\n"));
  439.             bzero((char *) vtg, sizeof *vtg);
  440.             if ((newvtg = vdr_getvtg(vtg, type, boot)) == 0)
  441.                 return -1;
  442.         }
  443.         vtg = newvtg;
  444.     }
  445.  
  446.     return vdr_vtgload(reg, vtg, type, boot);
  447. }
  448.  
  449. /*
  450.  * vdr_getvtg: find video parameters to match specified screen size
  451.  */
  452. STATIC struct vdr_vtgval *
  453. vdr_getvtg(vtgconf, type, boot)
  454.     struct vdr_vtgval *vtgconf;
  455.     int type, boot;
  456. {
  457.     int w, h, vrate;
  458.     struct vdr_opt *opt;
  459.     struct vdr_vtgval *vtg;
  460.  
  461.     DEBUGF(3, ("vdr_getvtg()\n"));
  462.  
  463.     w = vtgconf->w;
  464.     h = vtgconf->h;
  465.     vrate = vtgconf->vrate;
  466.  
  467.     DEBUGF(4, ("vdr_getvtg: %d x %d @ %d Hz, type = %d%s\n",
  468.         w, h, vrate, type, boot ? " (boot)" : ""));
  469.  
  470.     if ((opt = vdr_getopt(type)) == 0)
  471.         return 0;
  472.  
  473.     /* pick video parameters */
  474.     for (vtg = vdr_vtgval; vtg < ENDOF(vdr_vtgval); vtg++) {
  475.         DEBUGF(5, ("vtg w, h, vrate = %d, %d, %d\n",
  476.             vtg->w, vtg->h, vtg->vrate));
  477.  
  478.         if (w != 0 && !(w == vtg->w && h == vtg->h))
  479.             continue;
  480.  
  481.         if (vrate != 0 && vrate != vtg->vrate)
  482.             continue;
  483.  
  484.         if (vdr_vtgck(vtg, opt))
  485.             continue;
  486.  
  487.         if (!boot) {
  488.             vtgconf->w = vtg->w;
  489.             vtgconf->h = vtg->h;
  490.             vtgconf->vrate = vtg->vrate;
  491.         }
  492.  
  493.         DEBUGF(3, ("vdr_getvtg: returning %d x %d @ %d Hz\n",
  494.             vtg->w, vtg->h, vtg->vrate));
  495.  
  496.         return vtg;
  497.     }
  498.  
  499.     return boot ? VTGVAL_BOOT : 0;
  500. }
  501.  
  502. static int
  503. vdr_vtgck(vtg, opt)
  504.     struct vdr_vtgval *vtg;
  505.     struct vdr_opt *opt;
  506. {
  507.     DEBUGF(3, ("vdr_vtgck: %d x %d, flags = 0x%x\n",
  508.         vtg->w, vtg->h, opt->flags));
  509.  
  510.     if (opt->flags & VDRT_1M && vtg->w != 1024 ||
  511.         vtg->pixel > opt->pixel ||
  512.         vtg->w * vtg->h > opt->memsize)
  513.         return -1;
  514.  
  515.     return 0;
  516. }
  517.  
  518. STATIC int
  519. vdr_vtgload(reg, vtg, type, boot)
  520.     union vdr_reg *reg;
  521.     struct vdr_vtgval *vtg;
  522.     int type, boot;
  523. {
  524.     DEBUGF(3, ("vdr_vtgload: type %d, boot %d\n", type, boot));
  525.  
  526. #ifdef VDR2_SUPPORT
  527.     if (type == 0)
  528.         return vdr2_init(®->vdr2, vtg, type, boot);
  529. #endif /* VDR2_SUPPORT */
  530.  
  531.     return vdr1_init(reg, vtg, type, boot);
  532. }
  533.  
  534.  
  535. /*
  536.  * VDR1 device dependent code
  537.  */
  538.  
  539. static int
  540. vdr1_init(reg, vtg, type, boot)
  541.     union vdr_reg *reg;
  542.     struct vdr_vtgval *vtg;
  543.     int type, boot;
  544. {
  545.     struct g364 *ramdac;
  546.     int vdrflags = vdr_getopt(type)->flags;
  547.     int control, xferdelay, samlen;
  548.  
  549.     DEBUGF(3, ("vdr1_init: type %d, boot %d\n", type, boot));
  550.  
  551.     /* reset board, load boot register */
  552.     reg->vdr1.reset.r = 0;
  553.     ramdac = ®->vdr1.ramdac;
  554.     if (type > 1) {
  555.         reg->vdr1f.reset.r = 0;
  556. #ifdef _MIPSEL
  557.         DEBUGF(3, ("vdr1_init: writing little endian register\n"));
  558.         reg->vdr1f.little_end.r = 0;
  559. #else /* _MIPSEL */
  560.         DEBUGF(3, ("vdr1_init: writing big endian register\n"));
  561.         reg->vdr1f.big_end.r = 0;
  562. #endif /* _MIPSEL */
  563.         ramdac = ®->vdr1f.ramdac;
  564.     }
  565.     DELAY(1);
  566.     ramdac->boot.r =
  567.         G364_BOOTVAL(vtg->pixel / (vdrflags & VDRT_X8 ? 8 : 5));
  568.  
  569.     /* wait for PLL to stabilize */
  570.     DELAY(200);
  571.  
  572.     /* just starting PLL for probe */
  573.     if (boot)
  574.         return type;
  575.  
  576.     /* disable VTG (if running) */
  577.     ramdac->control.r = 0;
  578.     ramdac->controlb.r = 0;
  579.  
  580.     control = G364_CONTROL_2M;
  581.     samlen = 1024;
  582.     if (vdrflags & VDRT_1M) {
  583.         control = G332_CONTROL_1M;
  584.         if (vdrflags & VDRT_G364)
  585.             control = G364_CONTROL_1M;
  586.         samlen = 512;
  587.     }
  588.  
  589.     /*
  590.      * G364 C04 bug #4:
  591.      * "The second and subsequent serration pulses
  592.      * during PreEqualization are one screen unit in duration."
  593.      * We have to turn off serration if more vfp is needed.
  594.      */
  595.     if (!(vdrflags & VDRT_G365) && vtg->vfp > 1)
  596.         control |= G364_CONTROL_PLAINSYNC;
  597.  
  598.     /*
  599.      * Set misc. control register bits according to options...
  600.      */
  601.     if (vtg->opt & VDR_VTGOPT_PLAINSYNC)
  602.         control |= G364_CONTROL_PLAINSYNC;
  603.  
  604.     if (vtg->opt & VDR_VTGOPT_PEDESTAL)
  605.         control |= G364_CONTROL_PEDESTAL;
  606.  
  607.     ramdac->control.r = control;
  608.  
  609.     if (vdrflags & VDRT_G365)
  610.         ramdac->controlb.r =
  611.             G364_CONTROLB_EXTSAMP |
  612.             G364_CONTROLB_HSYNC_FLYBACK;
  613.  
  614.     /* load datapath registers */
  615.     {
  616.         int w, hfp, hs, hbp, linetime;
  617.  
  618.         xferdelay = G364_XFER_DELAY(vtg->pixel);
  619.  
  620.         hfp = vtg->hfp >> 2;
  621.         hs = vtg->hs >> 2;
  622.         hbp = vtg->hbp >> 2;
  623.         if (hbp <= xferdelay)
  624.             hbp = xferdelay + 1;
  625.         w = vtg->w >> 2;
  626.  
  627.         ramdac->halfsync.r = hs >> 1;
  628.         ramdac->backporch.r = hbp;
  629.         ramdac->display.r = w;
  630.         linetime = w + hfp + hs + hbp;
  631.         ramdac->linetime.r = linetime;
  632.         ramdac->broadpulse.r = (linetime / 2) - hfp;
  633.         ramdac->shortdisplay.r = (linetime / 2) - hfp - hs - hbp;
  634.     }
  635.  
  636.     ramdac->vsync.r = vtg->vs << 1;
  637.  
  638.     ramdac->vpreeq.r = vtg->vfp << 1;
  639.     ramdac->vposteq.r = 2;
  640.     ramdac->vblank.r = (vtg->vbp - 1) << 1;
  641.     ramdac->vdisplay.r = vtg->h << 1;
  642.  
  643.     ramdac->linestart.r = 0;
  644.     ramdac->meminit.r = samlen - xferdelay;
  645.     ramdac->xferdelay.r = xferdelay;
  646.  
  647.     /* set read mask */
  648.     ramdac->mask.r = ~0;
  649.  
  650.     /* start VTG */
  651.     ramdac->control.r = control | G364_CONTROL_VTGON;
  652.  
  653.     /*
  654.      * G364 C04 bug #6:
  655.      * "The action of starting the VTG may cause the TopOfScreen
  656.      * register to become corrupted."
  657.      */
  658.     ramdac->top.r = 0;
  659.  
  660.     return type;
  661. }
  662.  
  663. static int
  664. vdr1_set_video(reg, video)
  665.     unsigned char *reg;
  666.     int video;
  667. {
  668.     g364_reg *control = &((struct vdr1_reg *) reg)->ramdac.control;
  669.  
  670.     if (video)
  671.         control->r &= ~G364_CONTROL_BLANK;
  672.     else
  673.         control->r |= G364_CONTROL_BLANK;
  674.  
  675.     return 0;
  676. }
  677.  
  678. static int
  679. vdr1_get_video(reg, video)
  680.     unsigned char *reg;
  681.     int *video;
  682. {
  683.     g364_reg *control = &((struct vdr1_reg *) reg)->ramdac.control;
  684.  
  685.     *video = (control->r & G364_CONTROL_BLANK) ? 0 : 1;
  686.     return 0;
  687. }
  688.  
  689. static int
  690. vdr1_set_colormap(reg, index, count, rgb)
  691.     unsigned char *reg;
  692.     int index, count;
  693.     unsigned char *rgb;
  694. {
  695.     g364_reg *cmap = &((struct vdr1_reg *) reg)->ramdac.cmap[index];
  696.     u_int val;
  697.  
  698.     while (--count >= 0) {
  699.         val = (rgb[0] << 16) | (rgb[1] << 8) | rgb[2];
  700.         rgb += 3;
  701.         cmap->r = val;
  702.         cmap++;
  703.     }
  704.  
  705.     return 0;
  706. }
  707.  
  708. static int
  709. vdr1_get_colormap(reg, index, count, rgb)
  710.     unsigned char *reg;
  711.     int index, count;
  712.     unsigned char *rgb;
  713. {
  714.     g364_reg *cmap = &((struct vdr1_reg *) reg)->ramdac.cmap[index];
  715.     u_int val;
  716.  
  717.     while (--count >= 0) {
  718.         val = cmap->r;
  719.         cmap++;
  720.         rgb[0] = val >> 16;
  721.         rgb[1] = val >> 8;
  722.         rgb[2] = val;
  723.         rgb += 3;
  724.     }
  725.  
  726.     return 0;
  727. }
  728.  
  729. #ifdef VDR_CURSOR_SUPPORT
  730.  
  731. /* XXX little-endian support */
  732. /* ARGSUSED */
  733. static Bool
  734. RealizeCursor4000(pm, pCurs, pPriv)
  735.     MipsScreenPtr pm;
  736.     CursorPtr pCurs;
  737.     pointer *pPriv;
  738. {
  739.     CursorBitsPtr bits = pCurs->bits;
  740.     int w, h;
  741.     int x, y;
  742.     int bytes;
  743.     int soffset;
  744.     short *ram, rmask;
  745.     unsigned char *source, *mask;
  746.     int ramt, st, mt;
  747.     int bit;
  748.  
  749.     ram = (short *) xalloc(G364_CURSBYTES);
  750.     *pPriv = (pointer) ram;
  751.     if (!ram)
  752.         return FALSE;
  753.  
  754.     h = bits->height;
  755.     if (h > G364_CURSMAX)
  756.         h = G364_CURSMAX;
  757.  
  758.     w = bits->width;
  759.  
  760.     /* line to line offset in source and mask bitmaps */
  761.     soffset = ((w + BITMAP_SCANLINE_PAD - 1) &
  762.         ~(BITMAP_SCANLINE_PAD - 1)) >> 3;
  763.  
  764.     if (w > G364_CURSMAX)
  765.         w = G364_CURSMAX;
  766.  
  767.     /* right edge mask for cursor RAM */
  768.     rmask = 0xffff0000 >> ((w & 7) << 1);
  769.  
  770.     /* bytes per line actually used in source and mask bitmaps */
  771.     bytes = (w + 7) >> 3;
  772.  
  773.     source = bits->source;
  774.     mask = bits->mask;
  775.  
  776.     /*
  777.      * M7 I7 .. M0 I0
  778.      */
  779.  
  780.     for (y = 0; y < h; y++) {
  781.         for (x = 0; x < bytes; x++) {
  782.             /*
  783.              * Repack 1 mask byte and 1 source byte into
  784.              * 1 G364 cursor RAM word.
  785.              */
  786.             mt = mask[x];
  787.             st = source[x];
  788.             ramt = 0;
  789.             for (bit = 0; bit < 8; bit++)
  790.                 if (mt & (0x80 >> bit)) {
  791.                     ramt |= (1 << (bit * 2 + 1));
  792.                     if (st & (0x80 >> bit))
  793.                         ramt |= (1 << (bit * 2));
  794.                 }
  795.             *ram++ = ramt;
  796.         }
  797.  
  798.         /*
  799.          * Mask off garbage bits of partial word on right edge of
  800.          * cursor (if any).
  801.          */
  802.         if (rmask)
  803.             ram[-1] &= rmask;
  804.  
  805.         /* zero out blank space to right of cursor */
  806.         for (; x < G364_CURSMAX / 8; x++)
  807.             *ram++ = 0;
  808.  
  809.         source += soffset;
  810.         mask += soffset;
  811.     }
  812.     /* zero out blank space below cursor */
  813.     for (; y < G364_CURSMAX; y++) {
  814.         for (x = 0; x < G364_CURSMAX / 8; x++)
  815.             ram[x] = 0;
  816.         ram += G364_CURSMAX / 8;
  817.     }
  818.  
  819.     return TRUE;
  820. }
  821.  
  822. static void
  823. SetCursor4000(pm, pCurs, priv, x, y)
  824.     MipsScreenPtr pm;
  825.     CursorPtr pCurs;
  826.     pointer priv;
  827.     int x, y;
  828. {
  829.     struct g364 *ramdac = &((struct vdr1_reg *) FBREG(pm))->ramdac;
  830.     unsigned short *ram;
  831.     int i;
  832.  
  833.     /* turn cursor off */
  834.     ramdac->control.r |= G364_CONTROL_CURSDIS;
  835.  
  836.     if (!pCurs)
  837.         return;
  838.  
  839.     /* save hot spot */
  840.     pm->xhot = pCurs->bits->xhot;
  841.     pm->yhot = pCurs->bits->yhot;
  842.  
  843.     /* position cursor */
  844.     MoveCursor4000(pm, x, y);
  845.  
  846.     /* load colormap */
  847.     RecolorCursor4000(pm, pCurs);
  848.  
  849.     ram = (unsigned short *) priv;
  850.  
  851.     /*
  852.      * Load cursor RAM from preformatted buffer
  853.      */
  854.     for (i = 0; i < G364_CURSBYTES / 2; i++) {
  855.         /* G364 C04 bug workaround */
  856.         (void) ramdac->curpat[i].r;
  857.     
  858.         ramdac->curpat[i].r = ram[i];
  859.     }
  860.  
  861.     /* turn cursor on */
  862.     ramdac->control.r &= ~G364_CONTROL_CURSDIS;
  863. }
  864.  
  865. static void
  866. MoveCursor4000(pm, x, y)
  867.     MipsScreenPtr pm;
  868.     int x, y;
  869. {
  870.     struct g364 *ramdac = &((struct vdr1_reg *) FBREG(pm))->ramdac;
  871.  
  872.     x -= pm->xhot;
  873.     y -= pm->yhot;
  874.  
  875.     if (x < -G364_CURSMAX)
  876.         x = -G364_CURSMAX;
  877.     if (x > (pm->scr_width + 1))
  878.         x = pm->scr_width + 1;
  879.  
  880.     if (y < -G364_CURSMAX)
  881.         y = -G364_CURSMAX;
  882.     if (x > 2047)
  883.         y = 2047;
  884.  
  885.     ramdac->curpos.r = (x << 12) | y;
  886. }
  887.  
  888. static void
  889. RecolorCursor4000(pm, pCurs)
  890.     MipsScreenPtr pm;
  891.     CursorPtr pCurs;
  892. {
  893.     struct g364 *ramdac = &((struct vdr1_reg *) FBREG(pm))->ramdac;
  894.  
  895.     ramdac->curcmap[1].r =
  896.         (pCurs->backRed >> 8) << 16 |
  897.         (pCurs->backGreen >> 8) << 8 |
  898.         (pCurs->backBlue >> 8);
  899.     ramdac->curcmap[2].r =
  900.         (pCurs->foreRed >> 8) << 16 |
  901.         (pCurs->foreGreen >> 8) << 8 |
  902.         (pCurs->foreBlue >> 8);
  903. }
  904.  
  905. #endif /* VDR_CURSOR_SUPPORT */
  906.  
  907.  
  908. #ifdef VDR2_SUPPORT
  909. /*
  910.  * VDR2 device dependent code
  911.  */
  912.  
  913. /* ARGSUSED */
  914. static int
  915. vdr2_init(reg, vtg, type, boot)
  916.     struct vdr2_reg *reg;
  917.     struct vdr_vtgval *vtg;
  918.     int type, boot;
  919. {
  920.     struct g300 *ramdac = ®->ramdac;
  921.     struct bt431 *curs = ®->cursor;
  922.     int i;
  923.  
  924.     DEBUGF(3, ("vdr2_init: type %d, boot %d\n", type, boot));
  925.  
  926.     /* start PLL */
  927.     if (ramdac->boot.r != (i = G300_BOOTVAL(vtg->pixel / 8))) {
  928.         ramdac->boot.r = i;
  929.         DELAY(200);
  930.     }
  931.  
  932.     if (boot)
  933.         return 0;
  934.  
  935.     /* initialize cursor chips */
  936.     BT431_SETADDR(curs, 0);
  937.     for (i = 0; i < 13; i++)
  938.         curs->ctrl.r = 0;
  939.     BT431_SETADDR(curs, 0);
  940.     for (i = 0; i < 512; i++)
  941.         curs->ram.r = 0;
  942.  
  943.     /* turn off HW cursor */
  944.     BT431_SETADDR(curs, BT431_COMMAND);
  945.     curs->ctrl.r = BT431_COMMAND_CURSOFF;
  946.  
  947.     /* disable G300 VTG (if running) */
  948.     ramdac->control.r = G300_CONTROL_OFF;
  949.  
  950.     /* load datapath registers */
  951.     {
  952.         int w, hfp, hs, hbp, linetime;
  953.  
  954.         hfp = vtg->hfp >> 2;
  955.         hs = vtg->hs >> 2;
  956.         hbp = vtg->hbp >> 2;
  957.         w = vtg->w >> 2;
  958.  
  959.         ramdac->halfsync.r = hs >> 1;
  960.         ramdac->backporch.r = hbp;
  961.         ramdac->display.r = w;
  962.         linetime = w + hfp + hs + hbp;
  963.         ramdac->linetime.r = linetime;
  964.         ramdac->broadpulse.r = (linetime / 2) - hfp;
  965.         ramdac->shortdisplay.r = (linetime / 2) - hfp - hs - hbp;
  966.     }
  967.  
  968.     ramdac->vsync.r = vtg->vs << 1;
  969.     ramdac->vblank.r = (vtg->vfp + vtg->vbp) << 1;
  970.     ramdac->vdisplay.r = vtg->h << 1;
  971.  
  972.     ramdac->linestart.r = 0;
  973.     ramdac->meminit.r = 1024 - G300_XFER_DELAY;
  974.     ramdac->xferdelay.r = G300_XFER_DELAY;
  975.  
  976.     /* set read mask */
  977.     reg->ramdac.mask.r = ~0;
  978.  
  979.     /* start VTG */
  980.     ramdac->control.r = G300_CONTROL_ON;
  981.  
  982.     return 0;
  983. }
  984.  
  985. /*ARGSUSED*/
  986. static int
  987. vdr2_set_video(reg, video)
  988.     unsigned char *reg;
  989.     int video;
  990. {
  991.     return -1;
  992. }
  993.  
  994. /*ARGSUSED*/
  995. static int
  996. vdr2_get_video(reg, video)
  997.     unsigned char *reg;
  998.     int *video;
  999. {
  1000.     return -1;
  1001. }
  1002.  
  1003. static int
  1004. vdr2_set_colormap(reg, index, count, rgb)
  1005.     char * reg;
  1006.     int index, count;
  1007.     unsigned char *rgb;
  1008. {
  1009.     g300_reg *cmap = &((struct vdr2_reg *) reg)->ramdac.cmap[index];
  1010.     u_int val;
  1011.  
  1012.     while (--count >= 0) {
  1013.         val = (rgb[2] << 16) | (rgb[1] << 8) | rgb[0];
  1014.         rgb += 3;
  1015.         cmap->r = val;
  1016.         cmap++;
  1017.     }
  1018.  
  1019.     return 0;
  1020. }
  1021.  
  1022. static int
  1023. vdr2_get_colormap(reg, index, count, rgb)
  1024.     char * reg;
  1025.     int index, count;
  1026.     unsigned char *rgb;
  1027. {
  1028.     g300_reg *cmap = &((struct vdr2_reg *) reg)->ramdac.cmap[index];
  1029.     u_int val;
  1030.  
  1031.     while (--count >= 0) {
  1032.         val = cmap->r;
  1033.         cmap++;
  1034.         rgb[0] = val;
  1035.         rgb[1] = val >> 8;
  1036.         rgb[2] = val >> 16;
  1037.         rgb += 3;
  1038.     }
  1039.  
  1040.     return 0;
  1041. }
  1042. #endif /* VDR2_SUPPORT */
  1043.