Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Permedia2 framebuffer driver.
0003  *
0004  * 2.5/2.6 driver:
0005  * Copyright (c) 2003 Jim Hague (jim.hague@acm.org)
0006  *
0007  * based on 2.4 driver:
0008  * Copyright (c) 1998-2000 Ilario Nardinocchi (nardinoc@CS.UniBO.IT)
0009  * Copyright (c) 1999 Jakub Jelinek (jakub@redhat.com)
0010  *
0011  * and additional input from James Simmon's port of Hannu Mallat's tdfx
0012  * driver.
0013  *
0014  * I have a Creative Graphics Blaster Exxtreme card - pm2fb on x86. I
0015  * have no access to other pm2fb implementations. Sparc (and thus
0016  * hopefully other big-endian) devices now work, thanks to a lot of
0017  * testing work by Ron Murray. I have no access to CVision hardware,
0018  * and therefore for now I am omitting the CVision code.
0019  *
0020  * Multiple boards support has been on the TODO list for ages.
0021  * Don't expect this to change.
0022  *
0023  * This file is subject to the terms and conditions of the GNU General Public
0024  * License. See the file COPYING in the main directory of this archive for
0025  * more details.
0026  *
0027  *
0028  */
0029 
0030 #include <linux/module.h>
0031 #include <linux/moduleparam.h>
0032 #include <linux/kernel.h>
0033 #include <linux/errno.h>
0034 #include <linux/string.h>
0035 #include <linux/mm.h>
0036 #include <linux/slab.h>
0037 #include <linux/delay.h>
0038 #include <linux/fb.h>
0039 #include <linux/init.h>
0040 #include <linux/pci.h>
0041 #include <video/permedia2.h>
0042 #include <video/cvisionppc.h>
0043 
0044 #if !defined(__LITTLE_ENDIAN) && !defined(__BIG_ENDIAN)
0045 #error  "The endianness of the target host has not been defined."
0046 #endif
0047 
0048 #if !defined(CONFIG_PCI)
0049 #error "Only generic PCI cards supported."
0050 #endif
0051 
0052 #undef PM2FB_MASTER_DEBUG
0053 #ifdef PM2FB_MASTER_DEBUG
0054 #define DPRINTK(a, b...)    \
0055     printk(KERN_DEBUG "pm2fb: %s: " a, __func__ , ## b)
0056 #else
0057 #define DPRINTK(a, b...)    no_printk(a, ##b)
0058 #endif
0059 
0060 #define PM2_PIXMAP_SIZE (1600 * 4)
0061 
0062 /*
0063  * Driver data
0064  */
0065 static int hwcursor = 1;
0066 static char *mode_option;
0067 
0068 /*
0069  * The XFree GLINT driver will (I think to implement hardware cursor
0070  * support on TVP4010 and similar where there is no RAMDAC - see
0071  * comment in set_video) always request +ve sync regardless of what
0072  * the mode requires. This screws me because I have a Sun
0073  * fixed-frequency monitor which absolutely has to have -ve sync. So
0074  * these flags allow the user to specify that requests for +ve sync
0075  * should be silently turned in -ve sync.
0076  */
0077 static bool lowhsync;
0078 static bool lowvsync;
0079 static bool noaccel;
0080 static bool nomtrr;
0081 
0082 /*
0083  * The hardware state of the graphics card that isn't part of the
0084  * screeninfo.
0085  */
0086 struct pm2fb_par
0087 {
0088     pm2type_t   type;       /* Board type */
0089     unsigned char   __iomem *v_regs;/* virtual address of p_regs */
0090     u32     memclock;   /* memclock */
0091     u32     video;      /* video flags before blanking */
0092     u32     mem_config; /* MemConfig reg at probe */
0093     u32     mem_control;    /* MemControl reg at probe */
0094     u32     boot_address;   /* BootAddress reg at probe */
0095     u32     palette[16];
0096     int     wc_cookie;
0097 };
0098 
0099 /*
0100  * Here we define the default structs fb_fix_screeninfo and fb_var_screeninfo
0101  * if we don't use modedb.
0102  */
0103 static struct fb_fix_screeninfo pm2fb_fix = {
0104     .id =       "",
0105     .type =     FB_TYPE_PACKED_PIXELS,
0106     .visual =   FB_VISUAL_PSEUDOCOLOR,
0107     .xpanstep = 1,
0108     .ypanstep = 1,
0109     .ywrapstep =    0,
0110     .accel =    FB_ACCEL_3DLABS_PERMEDIA2,
0111 };
0112 
0113 /*
0114  * Default video mode. In case the modedb doesn't work.
0115  */
0116 static const struct fb_var_screeninfo pm2fb_var = {
0117     /* "640x480, 8 bpp @ 60 Hz */
0118     .xres =         640,
0119     .yres =         480,
0120     .xres_virtual =     640,
0121     .yres_virtual =     480,
0122     .bits_per_pixel =   8,
0123     .red =          {0, 8, 0},
0124     .blue =         {0, 8, 0},
0125     .green =        {0, 8, 0},
0126     .activate =     FB_ACTIVATE_NOW,
0127     .height =       -1,
0128     .width =        -1,
0129     .accel_flags =      0,
0130     .pixclock =     39721,
0131     .left_margin =      40,
0132     .right_margin =     24,
0133     .upper_margin =     32,
0134     .lower_margin =     11,
0135     .hsync_len =        96,
0136     .vsync_len =        2,
0137     .vmode =        FB_VMODE_NONINTERLACED
0138 };
0139 
0140 /*
0141  * Utility functions
0142  */
0143 
0144 static inline u32 pm2_RD(struct pm2fb_par *p, s32 off)
0145 {
0146     return fb_readl(p->v_regs + off);
0147 }
0148 
0149 static inline void pm2_WR(struct pm2fb_par *p, s32 off, u32 v)
0150 {
0151     fb_writel(v, p->v_regs + off);
0152 }
0153 
0154 static inline u32 pm2_RDAC_RD(struct pm2fb_par *p, s32 idx)
0155 {
0156     pm2_WR(p, PM2R_RD_PALETTE_WRITE_ADDRESS, idx);
0157     mb();
0158     return pm2_RD(p, PM2R_RD_INDEXED_DATA);
0159 }
0160 
0161 static inline u32 pm2v_RDAC_RD(struct pm2fb_par *p, s32 idx)
0162 {
0163     pm2_WR(p, PM2VR_RD_INDEX_LOW, idx & 0xff);
0164     mb();
0165     return pm2_RD(p,  PM2VR_RD_INDEXED_DATA);
0166 }
0167 
0168 static inline void pm2_RDAC_WR(struct pm2fb_par *p, s32 idx, u32 v)
0169 {
0170     pm2_WR(p, PM2R_RD_PALETTE_WRITE_ADDRESS, idx);
0171     wmb();
0172     pm2_WR(p, PM2R_RD_INDEXED_DATA, v);
0173     wmb();
0174 }
0175 
0176 static inline void pm2v_RDAC_WR(struct pm2fb_par *p, s32 idx, u32 v)
0177 {
0178     pm2_WR(p, PM2VR_RD_INDEX_LOW, idx & 0xff);
0179     wmb();
0180     pm2_WR(p, PM2VR_RD_INDEXED_DATA, v);
0181     wmb();
0182 }
0183 
0184 #ifdef CONFIG_FB_PM2_FIFO_DISCONNECT
0185 #define WAIT_FIFO(p, a)
0186 #else
0187 static inline void WAIT_FIFO(struct pm2fb_par *p, u32 a)
0188 {
0189     while (pm2_RD(p, PM2R_IN_FIFO_SPACE) < a)
0190         cpu_relax();
0191 }
0192 #endif
0193 
0194 /*
0195  * partial products for the supported horizontal resolutions.
0196  */
0197 #define PACKPP(p0, p1, p2)  (((p2) << 6) | ((p1) << 3) | (p0))
0198 static const struct {
0199     u16 width;
0200     u16 pp;
0201 } pp_table[] = {
0202     { 32,   PACKPP(1, 0, 0) }, { 64,    PACKPP(1, 1, 0) },
0203     { 96,   PACKPP(1, 1, 1) }, { 128,   PACKPP(2, 1, 1) },
0204     { 160,  PACKPP(2, 2, 1) }, { 192,   PACKPP(2, 2, 2) },
0205     { 224,  PACKPP(3, 2, 1) }, { 256,   PACKPP(3, 2, 2) },
0206     { 288,  PACKPP(3, 3, 1) }, { 320,   PACKPP(3, 3, 2) },
0207     { 384,  PACKPP(3, 3, 3) }, { 416,   PACKPP(4, 3, 1) },
0208     { 448,  PACKPP(4, 3, 2) }, { 512,   PACKPP(4, 3, 3) },
0209     { 544,  PACKPP(4, 4, 1) }, { 576,   PACKPP(4, 4, 2) },
0210     { 640,  PACKPP(4, 4, 3) }, { 768,   PACKPP(4, 4, 4) },
0211     { 800,  PACKPP(5, 4, 1) }, { 832,   PACKPP(5, 4, 2) },
0212     { 896,  PACKPP(5, 4, 3) }, { 1024,  PACKPP(5, 4, 4) },
0213     { 1056, PACKPP(5, 5, 1) }, { 1088,  PACKPP(5, 5, 2) },
0214     { 1152, PACKPP(5, 5, 3) }, { 1280,  PACKPP(5, 5, 4) },
0215     { 1536, PACKPP(5, 5, 5) }, { 1568,  PACKPP(6, 5, 1) },
0216     { 1600, PACKPP(6, 5, 2) }, { 1664,  PACKPP(6, 5, 3) },
0217     { 1792, PACKPP(6, 5, 4) }, { 2048,  PACKPP(6, 5, 5) },
0218     { 0,    0 } };
0219 
0220 static u32 partprod(u32 xres)
0221 {
0222     int i;
0223 
0224     for (i = 0; pp_table[i].width && pp_table[i].width != xres; i++)
0225         ;
0226     if (pp_table[i].width == 0)
0227         DPRINTK("invalid width %u\n", xres);
0228     return pp_table[i].pp;
0229 }
0230 
0231 static u32 to3264(u32 timing, int bpp, int is64)
0232 {
0233     switch (bpp) {
0234     case 24:
0235         timing *= 3;
0236         fallthrough;
0237     case 8:
0238         timing >>= 1;
0239         fallthrough;
0240     case 16:
0241         timing >>= 1;
0242         fallthrough;
0243     case 32:
0244         break;
0245     }
0246     if (is64)
0247         timing >>= 1;
0248     return timing;
0249 }
0250 
0251 static void pm2_mnp(u32 clk, unsigned char *mm, unsigned char *nn,
0252             unsigned char *pp)
0253 {
0254     unsigned char m;
0255     unsigned char n;
0256     unsigned char p;
0257     u32 f;
0258     s32 curr;
0259     s32 delta = 100000;
0260 
0261     *mm = *nn = *pp = 0;
0262     for (n = 2; n < 15; n++) {
0263         for (m = 2; m; m++) {
0264             f = PM2_REFERENCE_CLOCK * m / n;
0265             if (f >= 150000 && f <= 300000) {
0266                 for (p = 0; p < 5; p++, f >>= 1) {
0267                     curr = (clk > f) ? clk - f : f - clk;
0268                     if (curr < delta) {
0269                         delta = curr;
0270                         *mm = m;
0271                         *nn = n;
0272                         *pp = p;
0273                     }
0274                 }
0275             }
0276         }
0277     }
0278 }
0279 
0280 static void pm2v_mnp(u32 clk, unsigned char *mm, unsigned char *nn,
0281              unsigned char *pp)
0282 {
0283     unsigned char m;
0284     unsigned char n;
0285     unsigned char p;
0286     u32 f;
0287     s32 delta = 1000;
0288 
0289     *mm = *nn = *pp = 0;
0290     for (m = 1; m < 128; m++) {
0291         for (n = 2 * m + 1; n; n++) {
0292             for (p = 0; p < 2; p++) {
0293                 f = (PM2_REFERENCE_CLOCK >> (p + 1)) * n / m;
0294                 if (clk > f - delta && clk < f + delta) {
0295                     delta = (clk > f) ? clk - f : f - clk;
0296                     *mm = m;
0297                     *nn = n;
0298                     *pp = p;
0299                 }
0300             }
0301         }
0302     }
0303 }
0304 
0305 static void clear_palette(struct pm2fb_par *p)
0306 {
0307     int i = 256;
0308 
0309     WAIT_FIFO(p, 1);
0310     pm2_WR(p, PM2R_RD_PALETTE_WRITE_ADDRESS, 0);
0311     wmb();
0312     while (i--) {
0313         WAIT_FIFO(p, 3);
0314         pm2_WR(p, PM2R_RD_PALETTE_DATA, 0);
0315         pm2_WR(p, PM2R_RD_PALETTE_DATA, 0);
0316         pm2_WR(p, PM2R_RD_PALETTE_DATA, 0);
0317     }
0318 }
0319 
0320 static void reset_card(struct pm2fb_par *p)
0321 {
0322     if (p->type == PM2_TYPE_PERMEDIA2V)
0323         pm2_WR(p, PM2VR_RD_INDEX_HIGH, 0);
0324     pm2_WR(p, PM2R_RESET_STATUS, 0);
0325     mb();
0326     while (pm2_RD(p, PM2R_RESET_STATUS) & PM2F_BEING_RESET)
0327         cpu_relax();
0328     mb();
0329 #ifdef CONFIG_FB_PM2_FIFO_DISCONNECT
0330     DPRINTK("FIFO disconnect enabled\n");
0331     pm2_WR(p, PM2R_FIFO_DISCON, 1);
0332     mb();
0333 #endif
0334 
0335     /* Restore stashed memory config information from probe */
0336     WAIT_FIFO(p, 3);
0337     pm2_WR(p, PM2R_MEM_CONTROL, p->mem_control);
0338     pm2_WR(p, PM2R_BOOT_ADDRESS, p->boot_address);
0339     wmb();
0340     pm2_WR(p, PM2R_MEM_CONFIG, p->mem_config);
0341 }
0342 
0343 static void reset_config(struct pm2fb_par *p)
0344 {
0345     WAIT_FIFO(p, 53);
0346     pm2_WR(p, PM2R_CHIP_CONFIG, pm2_RD(p, PM2R_CHIP_CONFIG) &
0347             ~(PM2F_VGA_ENABLE | PM2F_VGA_FIXED));
0348     pm2_WR(p, PM2R_BYPASS_WRITE_MASK, ~(0L));
0349     pm2_WR(p, PM2R_FRAMEBUFFER_WRITE_MASK, ~(0L));
0350     pm2_WR(p, PM2R_FIFO_CONTROL, 0);
0351     pm2_WR(p, PM2R_APERTURE_ONE, 0);
0352     pm2_WR(p, PM2R_APERTURE_TWO, 0);
0353     pm2_WR(p, PM2R_RASTERIZER_MODE, 0);
0354     pm2_WR(p, PM2R_DELTA_MODE, PM2F_DELTA_ORDER_RGB);
0355     pm2_WR(p, PM2R_LB_READ_FORMAT, 0);
0356     pm2_WR(p, PM2R_LB_WRITE_FORMAT, 0);
0357     pm2_WR(p, PM2R_LB_READ_MODE, 0);
0358     pm2_WR(p, PM2R_LB_SOURCE_OFFSET, 0);
0359     pm2_WR(p, PM2R_FB_SOURCE_OFFSET, 0);
0360     pm2_WR(p, PM2R_FB_PIXEL_OFFSET, 0);
0361     pm2_WR(p, PM2R_FB_WINDOW_BASE, 0);
0362     pm2_WR(p, PM2R_LB_WINDOW_BASE, 0);
0363     pm2_WR(p, PM2R_FB_SOFT_WRITE_MASK, ~(0L));
0364     pm2_WR(p, PM2R_FB_HARD_WRITE_MASK, ~(0L));
0365     pm2_WR(p, PM2R_FB_READ_PIXEL, 0);
0366     pm2_WR(p, PM2R_DITHER_MODE, 0);
0367     pm2_WR(p, PM2R_AREA_STIPPLE_MODE, 0);
0368     pm2_WR(p, PM2R_DEPTH_MODE, 0);
0369     pm2_WR(p, PM2R_STENCIL_MODE, 0);
0370     pm2_WR(p, PM2R_TEXTURE_ADDRESS_MODE, 0);
0371     pm2_WR(p, PM2R_TEXTURE_READ_MODE, 0);
0372     pm2_WR(p, PM2R_TEXEL_LUT_MODE, 0);
0373     pm2_WR(p, PM2R_YUV_MODE, 0);
0374     pm2_WR(p, PM2R_COLOR_DDA_MODE, 0);
0375     pm2_WR(p, PM2R_TEXTURE_COLOR_MODE, 0);
0376     pm2_WR(p, PM2R_FOG_MODE, 0);
0377     pm2_WR(p, PM2R_ALPHA_BLEND_MODE, 0);
0378     pm2_WR(p, PM2R_LOGICAL_OP_MODE, 0);
0379     pm2_WR(p, PM2R_STATISTICS_MODE, 0);
0380     pm2_WR(p, PM2R_SCISSOR_MODE, 0);
0381     pm2_WR(p, PM2R_FILTER_MODE, PM2F_SYNCHRONIZATION);
0382     pm2_WR(p, PM2R_RD_PIXEL_MASK, 0xff);
0383     switch (p->type) {
0384     case PM2_TYPE_PERMEDIA2:
0385         pm2_RDAC_WR(p, PM2I_RD_MODE_CONTROL, 0); /* no overlay */
0386         pm2_RDAC_WR(p, PM2I_RD_CURSOR_CONTROL, 0);
0387         pm2_RDAC_WR(p, PM2I_RD_MISC_CONTROL, PM2F_RD_PALETTE_WIDTH_8);
0388         pm2_RDAC_WR(p, PM2I_RD_COLOR_KEY_CONTROL, 0);
0389         pm2_RDAC_WR(p, PM2I_RD_OVERLAY_KEY, 0);
0390         pm2_RDAC_WR(p, PM2I_RD_RED_KEY, 0);
0391         pm2_RDAC_WR(p, PM2I_RD_GREEN_KEY, 0);
0392         pm2_RDAC_WR(p, PM2I_RD_BLUE_KEY, 0);
0393         break;
0394     case PM2_TYPE_PERMEDIA2V:
0395         pm2v_RDAC_WR(p, PM2VI_RD_MISC_CONTROL, 1); /* 8bit */
0396         break;
0397     }
0398 }
0399 
0400 static void set_aperture(struct pm2fb_par *p, u32 depth)
0401 {
0402     /*
0403      * The hardware is little-endian. When used in big-endian
0404      * hosts, the on-chip aperture settings are used where
0405      * possible to translate from host to card byte order.
0406      */
0407     WAIT_FIFO(p, 2);
0408 #ifdef __LITTLE_ENDIAN
0409     pm2_WR(p, PM2R_APERTURE_ONE, PM2F_APERTURE_STANDARD);
0410 #else
0411     switch (depth) {
0412     case 24:    /* RGB->BGR */
0413         /*
0414          * We can't use the aperture to translate host to
0415          * card byte order here, so we switch to BGR mode
0416          * in pm2fb_set_par().
0417          */
0418     case 8:     /* B->B */
0419         pm2_WR(p, PM2R_APERTURE_ONE, PM2F_APERTURE_STANDARD);
0420         break;
0421     case 16:    /* HL->LH */
0422         pm2_WR(p, PM2R_APERTURE_ONE, PM2F_APERTURE_HALFWORDSWAP);
0423         break;
0424     case 32:    /* RGBA->ABGR */
0425         pm2_WR(p, PM2R_APERTURE_ONE, PM2F_APERTURE_BYTESWAP);
0426         break;
0427     }
0428 #endif
0429 
0430     /* We don't use aperture two, so this may be superflous */
0431     pm2_WR(p, PM2R_APERTURE_TWO, PM2F_APERTURE_STANDARD);
0432 }
0433 
0434 static void set_color(struct pm2fb_par *p, unsigned char regno,
0435               unsigned char r, unsigned char g, unsigned char b)
0436 {
0437     WAIT_FIFO(p, 4);
0438     pm2_WR(p, PM2R_RD_PALETTE_WRITE_ADDRESS, regno);
0439     wmb();
0440     pm2_WR(p, PM2R_RD_PALETTE_DATA, r);
0441     wmb();
0442     pm2_WR(p, PM2R_RD_PALETTE_DATA, g);
0443     wmb();
0444     pm2_WR(p, PM2R_RD_PALETTE_DATA, b);
0445 }
0446 
0447 static void set_memclock(struct pm2fb_par *par, u32 clk)
0448 {
0449     int i;
0450     unsigned char m, n, p;
0451 
0452     switch (par->type) {
0453     case PM2_TYPE_PERMEDIA2V:
0454         pm2v_mnp(clk/2, &m, &n, &p);
0455         WAIT_FIFO(par, 12);
0456         pm2_WR(par, PM2VR_RD_INDEX_HIGH, PM2VI_RD_MCLK_CONTROL >> 8);
0457         pm2v_RDAC_WR(par, PM2VI_RD_MCLK_CONTROL, 0);
0458         pm2v_RDAC_WR(par, PM2VI_RD_MCLK_PRESCALE, m);
0459         pm2v_RDAC_WR(par, PM2VI_RD_MCLK_FEEDBACK, n);
0460         pm2v_RDAC_WR(par, PM2VI_RD_MCLK_POSTSCALE, p);
0461         pm2v_RDAC_WR(par, PM2VI_RD_MCLK_CONTROL, 1);
0462         rmb();
0463         for (i = 256; i; i--)
0464             if (pm2v_RDAC_RD(par, PM2VI_RD_MCLK_CONTROL) & 2)
0465                 break;
0466         pm2_WR(par, PM2VR_RD_INDEX_HIGH, 0);
0467         break;
0468     case PM2_TYPE_PERMEDIA2:
0469         pm2_mnp(clk, &m, &n, &p);
0470         WAIT_FIFO(par, 10);
0471         pm2_RDAC_WR(par, PM2I_RD_MEMORY_CLOCK_3, 6);
0472         pm2_RDAC_WR(par, PM2I_RD_MEMORY_CLOCK_1, m);
0473         pm2_RDAC_WR(par, PM2I_RD_MEMORY_CLOCK_2, n);
0474         pm2_RDAC_WR(par, PM2I_RD_MEMORY_CLOCK_3, 8|p);
0475         pm2_RDAC_RD(par, PM2I_RD_MEMORY_CLOCK_STATUS);
0476         rmb();
0477         for (i = 256; i; i--)
0478             if (pm2_RD(par, PM2R_RD_INDEXED_DATA) & PM2F_PLL_LOCKED)
0479                 break;
0480         break;
0481     }
0482 }
0483 
0484 static void set_pixclock(struct pm2fb_par *par, u32 clk)
0485 {
0486     int i;
0487     unsigned char m, n, p;
0488 
0489     switch (par->type) {
0490     case PM2_TYPE_PERMEDIA2:
0491         pm2_mnp(clk, &m, &n, &p);
0492         WAIT_FIFO(par, 10);
0493         pm2_RDAC_WR(par, PM2I_RD_PIXEL_CLOCK_A3, 0);
0494         pm2_RDAC_WR(par, PM2I_RD_PIXEL_CLOCK_A1, m);
0495         pm2_RDAC_WR(par, PM2I_RD_PIXEL_CLOCK_A2, n);
0496         pm2_RDAC_WR(par, PM2I_RD_PIXEL_CLOCK_A3, 8|p);
0497         pm2_RDAC_RD(par, PM2I_RD_PIXEL_CLOCK_STATUS);
0498         rmb();
0499         for (i = 256; i; i--)
0500             if (pm2_RD(par, PM2R_RD_INDEXED_DATA) & PM2F_PLL_LOCKED)
0501                 break;
0502         break;
0503     case PM2_TYPE_PERMEDIA2V:
0504         pm2v_mnp(clk/2, &m, &n, &p);
0505         WAIT_FIFO(par, 8);
0506         pm2_WR(par, PM2VR_RD_INDEX_HIGH, PM2VI_RD_CLK0_PRESCALE >> 8);
0507         pm2v_RDAC_WR(par, PM2VI_RD_CLK0_PRESCALE, m);
0508         pm2v_RDAC_WR(par, PM2VI_RD_CLK0_FEEDBACK, n);
0509         pm2v_RDAC_WR(par, PM2VI_RD_CLK0_POSTSCALE, p);
0510         pm2_WR(par, PM2VR_RD_INDEX_HIGH, 0);
0511         break;
0512     }
0513 }
0514 
0515 static void set_video(struct pm2fb_par *p, u32 video)
0516 {
0517     u32 tmp;
0518     u32 vsync = video;
0519 
0520     DPRINTK("video = 0x%x\n", video);
0521 
0522     /*
0523      * The hardware cursor needs +vsync to recognise vert retrace.
0524      * We may not be using the hardware cursor, but the X Glint
0525      * driver may well. So always set +hsync/+vsync and then set
0526      * the RAMDAC to invert the sync if necessary.
0527      */
0528     vsync &= ~(PM2F_HSYNC_MASK | PM2F_VSYNC_MASK);
0529     vsync |= PM2F_HSYNC_ACT_HIGH | PM2F_VSYNC_ACT_HIGH;
0530 
0531     WAIT_FIFO(p, 3);
0532     pm2_WR(p, PM2R_VIDEO_CONTROL, vsync);
0533 
0534     switch (p->type) {
0535     case PM2_TYPE_PERMEDIA2:
0536         tmp = PM2F_RD_PALETTE_WIDTH_8;
0537         if ((video & PM2F_HSYNC_MASK) == PM2F_HSYNC_ACT_LOW)
0538             tmp |= 4; /* invert hsync */
0539         if ((video & PM2F_VSYNC_MASK) == PM2F_VSYNC_ACT_LOW)
0540             tmp |= 8; /* invert vsync */
0541         pm2_RDAC_WR(p, PM2I_RD_MISC_CONTROL, tmp);
0542         break;
0543     case PM2_TYPE_PERMEDIA2V:
0544         tmp = 0;
0545         if ((video & PM2F_HSYNC_MASK) == PM2F_HSYNC_ACT_LOW)
0546             tmp |= 1; /* invert hsync */
0547         if ((video & PM2F_VSYNC_MASK) == PM2F_VSYNC_ACT_LOW)
0548             tmp |= 4; /* invert vsync */
0549         pm2v_RDAC_WR(p, PM2VI_RD_SYNC_CONTROL, tmp);
0550         break;
0551     }
0552 }
0553 
0554 /*
0555  *  pm2fb_check_var - Optional function. Validates a var passed in.
0556  *  @var: frame buffer variable screen structure
0557  *  @info: frame buffer structure that represents a single frame buffer
0558  *
0559  *  Checks to see if the hardware supports the state requested by
0560  *  var passed in.
0561  *
0562  *  Returns negative errno on error, or zero on success.
0563  */
0564 static int pm2fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
0565 {
0566     u32 lpitch;
0567 
0568     if (var->bits_per_pixel != 8  && var->bits_per_pixel != 16 &&
0569         var->bits_per_pixel != 24 && var->bits_per_pixel != 32) {
0570         DPRINTK("depth not supported: %u\n", var->bits_per_pixel);
0571         return -EINVAL;
0572     }
0573 
0574     if (var->xres != var->xres_virtual) {
0575         DPRINTK("virtual x resolution != "
0576             "physical x resolution not supported\n");
0577         return -EINVAL;
0578     }
0579 
0580     if (var->yres > var->yres_virtual) {
0581         DPRINTK("virtual y resolution < "
0582             "physical y resolution not possible\n");
0583         return -EINVAL;
0584     }
0585 
0586     /* permedia cannot blit over 2048 */
0587     if (var->yres_virtual > 2047) {
0588         var->yres_virtual = 2047;
0589     }
0590 
0591     if (var->xoffset) {
0592         DPRINTK("xoffset not supported\n");
0593         return -EINVAL;
0594     }
0595 
0596     if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
0597         DPRINTK("interlace not supported\n");
0598         return -EINVAL;
0599     }
0600 
0601     var->xres = (var->xres + 15) & ~15; /* could sometimes be 8 */
0602     lpitch = var->xres * ((var->bits_per_pixel + 7) >> 3);
0603 
0604     if (var->xres < 320 || var->xres > 1600) {
0605         DPRINTK("width not supported: %u\n", var->xres);
0606         return -EINVAL;
0607     }
0608 
0609     if (var->yres < 200 || var->yres > 1200) {
0610         DPRINTK("height not supported: %u\n", var->yres);
0611         return -EINVAL;
0612     }
0613 
0614     if (lpitch * var->yres_virtual > info->fix.smem_len) {
0615         DPRINTK("no memory for screen (%ux%ux%u)\n",
0616             var->xres, var->yres_virtual, var->bits_per_pixel);
0617         return -EINVAL;
0618     }
0619 
0620     if (!var->pixclock) {
0621         DPRINTK("pixclock is zero\n");
0622         return -EINVAL;
0623     }
0624 
0625     if (PICOS2KHZ(var->pixclock) > PM2_MAX_PIXCLOCK) {
0626         DPRINTK("pixclock too high (%ldKHz)\n",
0627             PICOS2KHZ(var->pixclock));
0628         return -EINVAL;
0629     }
0630 
0631     var->transp.offset = 0;
0632     var->transp.length = 0;
0633     switch (var->bits_per_pixel) {
0634     case 8:
0635         var->red.length = 8;
0636         var->green.length = 8;
0637         var->blue.length = 8;
0638         break;
0639     case 16:
0640         var->red.offset   = 11;
0641         var->red.length   = 5;
0642         var->green.offset = 5;
0643         var->green.length = 6;
0644         var->blue.offset  = 0;
0645         var->blue.length  = 5;
0646         break;
0647     case 32:
0648         var->transp.offset = 24;
0649         var->transp.length = 8;
0650         var->red.offset   = 16;
0651         var->green.offset = 8;
0652         var->blue.offset  = 0;
0653         var->red.length = 8;
0654         var->green.length = 8;
0655         var->blue.length = 8;
0656         break;
0657     case 24:
0658 #ifdef __BIG_ENDIAN
0659         var->red.offset   = 0;
0660         var->blue.offset  = 16;
0661 #else
0662         var->red.offset   = 16;
0663         var->blue.offset  = 0;
0664 #endif
0665         var->green.offset = 8;
0666         var->red.length = 8;
0667         var->green.length = 8;
0668         var->blue.length = 8;
0669         break;
0670     }
0671     var->height = -1;
0672     var->width = -1;
0673 
0674     var->accel_flags = 0;   /* Can't mmap if this is on */
0675 
0676     DPRINTK("Checking graphics mode at %dx%d depth %d\n",
0677         var->xres, var->yres, var->bits_per_pixel);
0678     return 0;
0679 }
0680 
0681 /**
0682  *  pm2fb_set_par - Alters the hardware state.
0683  *  @info: frame buffer structure that represents a single frame buffer
0684  *
0685  *  Using the fb_var_screeninfo in fb_info we set the resolution of the
0686  *  this particular framebuffer.
0687  */
0688 static int pm2fb_set_par(struct fb_info *info)
0689 {
0690     struct pm2fb_par *par = info->par;
0691     u32 pixclock;
0692     u32 width = (info->var.xres_virtual + 7) & ~7;
0693     u32 height = info->var.yres_virtual;
0694     u32 depth = (info->var.bits_per_pixel + 7) & ~7;
0695     u32 hsstart, hsend, hbend, htotal;
0696     u32 vsstart, vsend, vbend, vtotal;
0697     u32 stride;
0698     u32 base;
0699     u32 video = 0;
0700     u32 clrmode = PM2F_RD_COLOR_MODE_RGB | PM2F_RD_GUI_ACTIVE;
0701     u32 txtmap = 0;
0702     u32 pixsize = 0;
0703     u32 clrformat = 0;
0704     u32 misc = 1; /* 8-bit DAC */
0705     u32 xres = (info->var.xres + 31) & ~31;
0706     int data64;
0707 
0708     reset_card(par);
0709     reset_config(par);
0710     clear_palette(par);
0711     if (par->memclock)
0712         set_memclock(par, par->memclock);
0713 
0714     depth = (depth > 32) ? 32 : depth;
0715     data64 = depth > 8 || par->type == PM2_TYPE_PERMEDIA2V;
0716 
0717     pixclock = PICOS2KHZ(info->var.pixclock);
0718     if (pixclock > PM2_MAX_PIXCLOCK) {
0719         DPRINTK("pixclock too high (%uKHz)\n", pixclock);
0720         return -EINVAL;
0721     }
0722 
0723     hsstart = to3264(info->var.right_margin, depth, data64);
0724     hsend = hsstart + to3264(info->var.hsync_len, depth, data64);
0725     hbend = hsend + to3264(info->var.left_margin, depth, data64);
0726     htotal = to3264(xres, depth, data64) + hbend - 1;
0727     vsstart = (info->var.lower_margin)
0728         ? info->var.lower_margin - 1
0729         : 0;    /* FIXME! */
0730     vsend = info->var.lower_margin + info->var.vsync_len - 1;
0731     vbend = info->var.lower_margin + info->var.vsync_len +
0732         info->var.upper_margin;
0733     vtotal = info->var.yres + vbend - 1;
0734     stride = to3264(width, depth, 1);
0735     base = to3264(info->var.yoffset * xres + info->var.xoffset, depth, 1);
0736     if (data64)
0737         video |= PM2F_DATA_64_ENABLE;
0738 
0739     if (info->var.sync & FB_SYNC_HOR_HIGH_ACT) {
0740         if (lowhsync) {
0741             DPRINTK("ignoring +hsync, using -hsync.\n");
0742             video |= PM2F_HSYNC_ACT_LOW;
0743         } else
0744             video |= PM2F_HSYNC_ACT_HIGH;
0745     } else
0746         video |= PM2F_HSYNC_ACT_LOW;
0747 
0748     if (info->var.sync & FB_SYNC_VERT_HIGH_ACT) {
0749         if (lowvsync) {
0750             DPRINTK("ignoring +vsync, using -vsync.\n");
0751             video |= PM2F_VSYNC_ACT_LOW;
0752         } else
0753             video |= PM2F_VSYNC_ACT_HIGH;
0754     } else
0755         video |= PM2F_VSYNC_ACT_LOW;
0756 
0757     if ((info->var.vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
0758         DPRINTK("interlaced not supported\n");
0759         return -EINVAL;
0760     }
0761     if ((info->var.vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE)
0762         video |= PM2F_LINE_DOUBLE;
0763     if ((info->var.activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW)
0764         video |= PM2F_VIDEO_ENABLE;
0765     par->video = video;
0766 
0767     info->fix.visual =
0768         (depth == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
0769     info->fix.line_length = info->var.xres * depth / 8;
0770     info->cmap.len = 256;
0771 
0772     /*
0773      * Settings calculated. Now write them out.
0774      */
0775     if (par->type == PM2_TYPE_PERMEDIA2V) {
0776         WAIT_FIFO(par, 1);
0777         pm2_WR(par, PM2VR_RD_INDEX_HIGH, 0);
0778     }
0779 
0780     set_aperture(par, depth);
0781 
0782     mb();
0783     WAIT_FIFO(par, 19);
0784     switch (depth) {
0785     case 8:
0786         pm2_WR(par, PM2R_FB_READ_PIXEL, 0);
0787         clrformat = 0x2e;
0788         break;
0789     case 16:
0790         pm2_WR(par, PM2R_FB_READ_PIXEL, 1);
0791         clrmode |= PM2F_RD_TRUECOLOR | PM2F_RD_PIXELFORMAT_RGB565;
0792         txtmap = PM2F_TEXTEL_SIZE_16;
0793         pixsize = 1;
0794         clrformat = 0x70;
0795         misc |= 8;
0796         break;
0797     case 32:
0798         pm2_WR(par, PM2R_FB_READ_PIXEL, 2);
0799         clrmode |= PM2F_RD_TRUECOLOR | PM2F_RD_PIXELFORMAT_RGBA8888;
0800         txtmap = PM2F_TEXTEL_SIZE_32;
0801         pixsize = 2;
0802         clrformat = 0x20;
0803         misc |= 8;
0804         break;
0805     case 24:
0806         pm2_WR(par, PM2R_FB_READ_PIXEL, 4);
0807         clrmode |= PM2F_RD_TRUECOLOR | PM2F_RD_PIXELFORMAT_RGB888;
0808         txtmap = PM2F_TEXTEL_SIZE_24;
0809         pixsize = 4;
0810         clrformat = 0x20;
0811         misc |= 8;
0812         break;
0813     }
0814     pm2_WR(par, PM2R_FB_WRITE_MODE, PM2F_FB_WRITE_ENABLE);
0815     pm2_WR(par, PM2R_FB_READ_MODE, partprod(xres));
0816     pm2_WR(par, PM2R_LB_READ_MODE, partprod(xres));
0817     pm2_WR(par, PM2R_TEXTURE_MAP_FORMAT, txtmap | partprod(xres));
0818     pm2_WR(par, PM2R_H_TOTAL, htotal);
0819     pm2_WR(par, PM2R_HS_START, hsstart);
0820     pm2_WR(par, PM2R_HS_END, hsend);
0821     pm2_WR(par, PM2R_HG_END, hbend);
0822     pm2_WR(par, PM2R_HB_END, hbend);
0823     pm2_WR(par, PM2R_V_TOTAL, vtotal);
0824     pm2_WR(par, PM2R_VS_START, vsstart);
0825     pm2_WR(par, PM2R_VS_END, vsend);
0826     pm2_WR(par, PM2R_VB_END, vbend);
0827     pm2_WR(par, PM2R_SCREEN_STRIDE, stride);
0828     wmb();
0829     pm2_WR(par, PM2R_WINDOW_ORIGIN, 0);
0830     pm2_WR(par, PM2R_SCREEN_SIZE, (height << 16) | width);
0831     pm2_WR(par, PM2R_SCISSOR_MODE, PM2F_SCREEN_SCISSOR_ENABLE);
0832     wmb();
0833     pm2_WR(par, PM2R_SCREEN_BASE, base);
0834     wmb();
0835     set_video(par, video);
0836     WAIT_FIFO(par, 10);
0837     switch (par->type) {
0838     case PM2_TYPE_PERMEDIA2:
0839         pm2_RDAC_WR(par, PM2I_RD_COLOR_MODE, clrmode);
0840         pm2_RDAC_WR(par, PM2I_RD_COLOR_KEY_CONTROL,
0841                 (depth == 8) ? 0 : PM2F_COLOR_KEY_TEST_OFF);
0842         break;
0843     case PM2_TYPE_PERMEDIA2V:
0844         pm2v_RDAC_WR(par, PM2VI_RD_DAC_CONTROL, 0);
0845         pm2v_RDAC_WR(par, PM2VI_RD_PIXEL_SIZE, pixsize);
0846         pm2v_RDAC_WR(par, PM2VI_RD_COLOR_FORMAT, clrformat);
0847         pm2v_RDAC_WR(par, PM2VI_RD_MISC_CONTROL, misc);
0848         pm2v_RDAC_WR(par, PM2VI_RD_OVERLAY_KEY, 0);
0849         break;
0850     }
0851     set_pixclock(par, pixclock);
0852     DPRINTK("Setting graphics mode at %dx%d depth %d\n",
0853         info->var.xres, info->var.yres, info->var.bits_per_pixel);
0854     return 0;
0855 }
0856 
0857 /**
0858  *  pm2fb_setcolreg - Sets a color register.
0859  *  @regno: boolean, 0 copy local, 1 get_user() function
0860  *  @red: frame buffer colormap structure
0861  *  @green: The green value which can be up to 16 bits wide
0862  *  @blue:  The blue value which can be up to 16 bits wide.
0863  *  @transp: If supported the alpha value which can be up to 16 bits wide.
0864  *  @info: frame buffer info structure
0865  *
0866  *  Set a single color register. The values supplied have a 16 bit
0867  *  magnitude which needs to be scaled in this function for the hardware.
0868  *  Pretty much a direct lift from tdfxfb.c.
0869  *
0870  *  Returns negative errno on error, or zero on success.
0871  */
0872 static int pm2fb_setcolreg(unsigned regno, unsigned red, unsigned green,
0873                unsigned blue, unsigned transp,
0874                struct fb_info *info)
0875 {
0876     struct pm2fb_par *par = info->par;
0877 
0878     if (regno >= info->cmap.len)  /* no. of hw registers */
0879         return -EINVAL;
0880     /*
0881      * Program hardware... do anything you want with transp
0882      */
0883 
0884     /* grayscale works only partially under directcolor */
0885     /* grayscale = 0.30*R + 0.59*G + 0.11*B */
0886     if (info->var.grayscale)
0887         red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8;
0888 
0889     /* Directcolor:
0890      *   var->{color}.offset contains start of bitfield
0891      *   var->{color}.length contains length of bitfield
0892      *   {hardwarespecific} contains width of DAC
0893      *   cmap[X] is programmed to
0894      *   (X << red.offset) | (X << green.offset) | (X << blue.offset)
0895      *   RAMDAC[X] is programmed to (red, green, blue)
0896      *
0897      * Pseudocolor:
0898      *    uses offset = 0 && length = DAC register width.
0899      *    var->{color}.offset is 0
0900      *    var->{color}.length contains width of DAC
0901      *    cmap is not used
0902      *    DAC[X] is programmed to (red, green, blue)
0903      * Truecolor:
0904      *    does not use RAMDAC (usually has 3 of them).
0905      *    var->{color}.offset contains start of bitfield
0906      *    var->{color}.length contains length of bitfield
0907      *    cmap is programmed to
0908      *    (red << red.offset) | (green << green.offset) |
0909      *    (blue << blue.offset) | (transp << transp.offset)
0910      *    RAMDAC does not exist
0911      */
0912 #define CNVT_TOHW(val, width) ((((val) << (width)) + 0x7FFF -(val)) >> 16)
0913     switch (info->fix.visual) {
0914     case FB_VISUAL_TRUECOLOR:
0915     case FB_VISUAL_PSEUDOCOLOR:
0916         red = CNVT_TOHW(red, info->var.red.length);
0917         green = CNVT_TOHW(green, info->var.green.length);
0918         blue = CNVT_TOHW(blue, info->var.blue.length);
0919         transp = CNVT_TOHW(transp, info->var.transp.length);
0920         break;
0921     case FB_VISUAL_DIRECTCOLOR:
0922         /* example here assumes 8 bit DAC. Might be different
0923          * for your hardware */
0924         red = CNVT_TOHW(red, 8);
0925         green = CNVT_TOHW(green, 8);
0926         blue = CNVT_TOHW(blue, 8);
0927         /* hey, there is bug in transp handling... */
0928         transp = CNVT_TOHW(transp, 8);
0929         break;
0930     }
0931 #undef CNVT_TOHW
0932     /* Truecolor has hardware independent palette */
0933     if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
0934         u32 v;
0935 
0936         if (regno >= 16)
0937             return -EINVAL;
0938 
0939         v = (red << info->var.red.offset) |
0940             (green << info->var.green.offset) |
0941             (blue << info->var.blue.offset) |
0942             (transp << info->var.transp.offset);
0943 
0944         switch (info->var.bits_per_pixel) {
0945         case 8:
0946             break;
0947         case 16:
0948         case 24:
0949         case 32:
0950             par->palette[regno] = v;
0951             break;
0952         }
0953         return 0;
0954     } else if (info->fix.visual == FB_VISUAL_PSEUDOCOLOR)
0955         set_color(par, regno, red, green, blue);
0956 
0957     return 0;
0958 }
0959 
0960 /**
0961  *  pm2fb_pan_display - Pans the display.
0962  *  @var: frame buffer variable screen structure
0963  *  @info: frame buffer structure that represents a single frame buffer
0964  *
0965  *  Pan (or wrap, depending on the `vmode' field) the display using the
0966  *  `xoffset' and `yoffset' fields of the `var' structure.
0967  *  If the values don't fit, return -EINVAL.
0968  *
0969  *  Returns negative errno on error, or zero on success.
0970  *
0971  */
0972 static int pm2fb_pan_display(struct fb_var_screeninfo *var,
0973                  struct fb_info *info)
0974 {
0975     struct pm2fb_par *p = info->par;
0976     u32 base;
0977     u32 depth = (info->var.bits_per_pixel + 7) & ~7;
0978     u32 xres = (info->var.xres + 31) & ~31;
0979 
0980     depth = (depth > 32) ? 32 : depth;
0981     base = to3264(var->yoffset * xres + var->xoffset, depth, 1);
0982     WAIT_FIFO(p, 1);
0983     pm2_WR(p, PM2R_SCREEN_BASE, base);
0984     return 0;
0985 }
0986 
0987 /**
0988  *  pm2fb_blank - Blanks the display.
0989  *  @blank_mode: the blank mode we want.
0990  *  @info: frame buffer structure that represents a single frame buffer
0991  *
0992  *  Blank the screen if blank_mode != 0, else unblank. Return 0 if
0993  *  blanking succeeded, != 0 if un-/blanking failed due to e.g. a
0994  *  video mode which doesn't support it. Implements VESA suspend
0995  *  and powerdown modes on hardware that supports disabling hsync/vsync:
0996  *  blank_mode == 2: suspend vsync
0997  *  blank_mode == 3: suspend hsync
0998  *  blank_mode == 4: powerdown
0999  *
1000  *  Returns negative errno on error, or zero on success.
1001  *
1002  */
1003 static int pm2fb_blank(int blank_mode, struct fb_info *info)
1004 {
1005     struct pm2fb_par *par = info->par;
1006     u32 video = par->video;
1007 
1008     DPRINTK("blank_mode %d\n", blank_mode);
1009 
1010     switch (blank_mode) {
1011     case FB_BLANK_UNBLANK:
1012         /* Screen: On */
1013         video |= PM2F_VIDEO_ENABLE;
1014         break;
1015     case FB_BLANK_NORMAL:
1016         /* Screen: Off */
1017         video &= ~PM2F_VIDEO_ENABLE;
1018         break;
1019     case FB_BLANK_VSYNC_SUSPEND:
1020         /* VSync: Off */
1021         video &= ~(PM2F_VSYNC_MASK | PM2F_BLANK_LOW);
1022         break;
1023     case FB_BLANK_HSYNC_SUSPEND:
1024         /* HSync: Off */
1025         video &= ~(PM2F_HSYNC_MASK | PM2F_BLANK_LOW);
1026         break;
1027     case FB_BLANK_POWERDOWN:
1028         /* HSync: Off, VSync: Off */
1029         video &= ~(PM2F_VSYNC_MASK | PM2F_HSYNC_MASK | PM2F_BLANK_LOW);
1030         break;
1031     }
1032     set_video(par, video);
1033     return 0;
1034 }
1035 
1036 static int pm2fb_sync(struct fb_info *info)
1037 {
1038     struct pm2fb_par *par = info->par;
1039 
1040     WAIT_FIFO(par, 1);
1041     pm2_WR(par, PM2R_SYNC, 0);
1042     mb();
1043     do {
1044         while (pm2_RD(par, PM2R_OUT_FIFO_WORDS) == 0)
1045             cpu_relax();
1046     } while (pm2_RD(par, PM2R_OUT_FIFO) != PM2TAG(PM2R_SYNC));
1047 
1048     return 0;
1049 }
1050 
1051 static void pm2fb_fillrect(struct fb_info *info,
1052                 const struct fb_fillrect *region)
1053 {
1054     struct pm2fb_par *par = info->par;
1055     struct fb_fillrect modded;
1056     int vxres, vyres;
1057     u32 color = (info->fix.visual == FB_VISUAL_TRUECOLOR) ?
1058         ((u32 *)info->pseudo_palette)[region->color] : region->color;
1059 
1060     if (info->state != FBINFO_STATE_RUNNING)
1061         return;
1062     if ((info->flags & FBINFO_HWACCEL_DISABLED) ||
1063         region->rop != ROP_COPY ) {
1064         cfb_fillrect(info, region);
1065         return;
1066     }
1067 
1068     vxres = info->var.xres_virtual;
1069     vyres = info->var.yres_virtual;
1070 
1071     memcpy(&modded, region, sizeof(struct fb_fillrect));
1072 
1073     if (!modded.width || !modded.height ||
1074         modded.dx >= vxres || modded.dy >= vyres)
1075         return;
1076 
1077     if (modded.dx + modded.width  > vxres)
1078         modded.width  = vxres - modded.dx;
1079     if (modded.dy + modded.height > vyres)
1080         modded.height = vyres - modded.dy;
1081 
1082     if (info->var.bits_per_pixel == 8)
1083         color |= color << 8;
1084     if (info->var.bits_per_pixel <= 16)
1085         color |= color << 16;
1086 
1087     WAIT_FIFO(par, 3);
1088     pm2_WR(par, PM2R_CONFIG, PM2F_CONFIG_FB_WRITE_ENABLE);
1089     pm2_WR(par, PM2R_RECTANGLE_ORIGIN, (modded.dy << 16) | modded.dx);
1090     pm2_WR(par, PM2R_RECTANGLE_SIZE, (modded.height << 16) | modded.width);
1091     if (info->var.bits_per_pixel != 24) {
1092         WAIT_FIFO(par, 2);
1093         pm2_WR(par, PM2R_FB_BLOCK_COLOR, color);
1094         wmb();
1095         pm2_WR(par, PM2R_RENDER,
1096                 PM2F_RENDER_RECTANGLE | PM2F_RENDER_FASTFILL);
1097     } else {
1098         WAIT_FIFO(par, 4);
1099         pm2_WR(par, PM2R_COLOR_DDA_MODE, 1);
1100         pm2_WR(par, PM2R_CONSTANT_COLOR, color);
1101         wmb();
1102         pm2_WR(par, PM2R_RENDER,
1103                 PM2F_RENDER_RECTANGLE |
1104                 PM2F_INCREASE_X | PM2F_INCREASE_Y );
1105         pm2_WR(par, PM2R_COLOR_DDA_MODE, 0);
1106     }
1107 }
1108 
1109 static void pm2fb_copyarea(struct fb_info *info,
1110                 const struct fb_copyarea *area)
1111 {
1112     struct pm2fb_par *par = info->par;
1113     struct fb_copyarea modded;
1114     u32 vxres, vyres;
1115 
1116     if (info->state != FBINFO_STATE_RUNNING)
1117         return;
1118     if (info->flags & FBINFO_HWACCEL_DISABLED) {
1119         cfb_copyarea(info, area);
1120         return;
1121     }
1122 
1123     memcpy(&modded, area, sizeof(struct fb_copyarea));
1124 
1125     vxres = info->var.xres_virtual;
1126     vyres = info->var.yres_virtual;
1127 
1128     if (!modded.width || !modded.height ||
1129         modded.sx >= vxres || modded.sy >= vyres ||
1130         modded.dx >= vxres || modded.dy >= vyres)
1131         return;
1132 
1133     if (modded.sx + modded.width > vxres)
1134         modded.width = vxres - modded.sx;
1135     if (modded.dx + modded.width > vxres)
1136         modded.width = vxres - modded.dx;
1137     if (modded.sy + modded.height > vyres)
1138         modded.height = vyres - modded.sy;
1139     if (modded.dy + modded.height > vyres)
1140         modded.height = vyres - modded.dy;
1141 
1142     WAIT_FIFO(par, 5);
1143     pm2_WR(par, PM2R_CONFIG, PM2F_CONFIG_FB_WRITE_ENABLE |
1144         PM2F_CONFIG_FB_READ_SOURCE_ENABLE);
1145     pm2_WR(par, PM2R_FB_SOURCE_DELTA,
1146             ((modded.sy - modded.dy) & 0xfff) << 16 |
1147             ((modded.sx - modded.dx) & 0xfff));
1148     pm2_WR(par, PM2R_RECTANGLE_ORIGIN, (modded.dy << 16) | modded.dx);
1149     pm2_WR(par, PM2R_RECTANGLE_SIZE, (modded.height << 16) | modded.width);
1150     wmb();
1151     pm2_WR(par, PM2R_RENDER, PM2F_RENDER_RECTANGLE |
1152                 (modded.dx < modded.sx ? PM2F_INCREASE_X : 0) |
1153                 (modded.dy < modded.sy ? PM2F_INCREASE_Y : 0));
1154 }
1155 
1156 static void pm2fb_imageblit(struct fb_info *info, const struct fb_image *image)
1157 {
1158     struct pm2fb_par *par = info->par;
1159     u32 height = image->height;
1160     u32 fgx, bgx;
1161     const u32 *src = (const u32 *)image->data;
1162     u32 xres = (info->var.xres + 31) & ~31;
1163     int raster_mode = 1; /* invert bits */
1164 
1165 #ifdef __LITTLE_ENDIAN
1166     raster_mode |= 3 << 7; /* reverse byte order */
1167 #endif
1168 
1169     if (info->state != FBINFO_STATE_RUNNING)
1170         return;
1171     if (info->flags & FBINFO_HWACCEL_DISABLED || image->depth != 1) {
1172         cfb_imageblit(info, image);
1173         return;
1174     }
1175     switch (info->fix.visual) {
1176     case FB_VISUAL_PSEUDOCOLOR:
1177         fgx = image->fg_color;
1178         bgx = image->bg_color;
1179         break;
1180     case FB_VISUAL_TRUECOLOR:
1181     default:
1182         fgx = par->palette[image->fg_color];
1183         bgx = par->palette[image->bg_color];
1184         break;
1185     }
1186     if (info->var.bits_per_pixel == 8) {
1187         fgx |= fgx << 8;
1188         bgx |= bgx << 8;
1189     }
1190     if (info->var.bits_per_pixel <= 16) {
1191         fgx |= fgx << 16;
1192         bgx |= bgx << 16;
1193     }
1194 
1195     WAIT_FIFO(par, 13);
1196     pm2_WR(par, PM2R_FB_READ_MODE, partprod(xres));
1197     pm2_WR(par, PM2R_SCISSOR_MIN_XY,
1198             ((image->dy & 0xfff) << 16) | (image->dx & 0x0fff));
1199     pm2_WR(par, PM2R_SCISSOR_MAX_XY,
1200             (((image->dy + image->height) & 0x0fff) << 16) |
1201             ((image->dx + image->width) & 0x0fff));
1202     pm2_WR(par, PM2R_SCISSOR_MODE, 1);
1203     /* GXcopy & UNIT_ENABLE */
1204     pm2_WR(par, PM2R_LOGICAL_OP_MODE, (0x3 << 1) | 1);
1205     pm2_WR(par, PM2R_RECTANGLE_ORIGIN,
1206             ((image->dy & 0xfff) << 16) | (image->dx & 0x0fff));
1207     pm2_WR(par, PM2R_RECTANGLE_SIZE,
1208             ((image->height & 0x0fff) << 16) |
1209             ((image->width) & 0x0fff));
1210     if (info->var.bits_per_pixel == 24) {
1211         pm2_WR(par, PM2R_COLOR_DDA_MODE, 1);
1212         /* clear area */
1213         pm2_WR(par, PM2R_CONSTANT_COLOR, bgx);
1214         pm2_WR(par, PM2R_RENDER,
1215             PM2F_RENDER_RECTANGLE |
1216             PM2F_INCREASE_X | PM2F_INCREASE_Y);
1217         /* BitMapPackEachScanline */
1218         pm2_WR(par, PM2R_RASTERIZER_MODE, raster_mode | (1 << 9));
1219         pm2_WR(par, PM2R_CONSTANT_COLOR, fgx);
1220         pm2_WR(par, PM2R_RENDER,
1221             PM2F_RENDER_RECTANGLE |
1222             PM2F_INCREASE_X | PM2F_INCREASE_Y |
1223             PM2F_RENDER_SYNC_ON_BIT_MASK);
1224     } else {
1225         pm2_WR(par, PM2R_COLOR_DDA_MODE, 0);
1226         /* clear area */
1227         pm2_WR(par, PM2R_FB_BLOCK_COLOR, bgx);
1228         pm2_WR(par, PM2R_RENDER,
1229             PM2F_RENDER_RECTANGLE |
1230             PM2F_RENDER_FASTFILL |
1231             PM2F_INCREASE_X | PM2F_INCREASE_Y);
1232         pm2_WR(par, PM2R_RASTERIZER_MODE, raster_mode);
1233         pm2_WR(par, PM2R_FB_BLOCK_COLOR, fgx);
1234         pm2_WR(par, PM2R_RENDER,
1235             PM2F_RENDER_RECTANGLE |
1236             PM2F_INCREASE_X | PM2F_INCREASE_Y |
1237             PM2F_RENDER_FASTFILL |
1238             PM2F_RENDER_SYNC_ON_BIT_MASK);
1239     }
1240 
1241     while (height--) {
1242         int width = ((image->width + 7) >> 3)
1243                 + info->pixmap.scan_align - 1;
1244         width >>= 2;
1245         WAIT_FIFO(par, width);
1246         while (width--) {
1247             pm2_WR(par, PM2R_BIT_MASK_PATTERN, *src);
1248             src++;
1249         }
1250     }
1251     WAIT_FIFO(par, 3);
1252     pm2_WR(par, PM2R_RASTERIZER_MODE, 0);
1253     pm2_WR(par, PM2R_COLOR_DDA_MODE, 0);
1254     pm2_WR(par, PM2R_SCISSOR_MODE, 0);
1255 }
1256 
1257 /*
1258  *  Hardware cursor support.
1259  */
1260 static const u8 cursor_bits_lookup[16] = {
1261     0x00, 0x40, 0x10, 0x50, 0x04, 0x44, 0x14, 0x54,
1262     0x01, 0x41, 0x11, 0x51, 0x05, 0x45, 0x15, 0x55
1263 };
1264 
1265 static int pm2vfb_cursor(struct fb_info *info, struct fb_cursor *cursor)
1266 {
1267     struct pm2fb_par *par = info->par;
1268     u8 mode = PM2F_CURSORMODE_TYPE_X;
1269     int x = cursor->image.dx - info->var.xoffset;
1270     int y = cursor->image.dy - info->var.yoffset;
1271 
1272     if (cursor->enable)
1273         mode |= PM2F_CURSORMODE_CURSOR_ENABLE;
1274 
1275     pm2v_RDAC_WR(par, PM2VI_RD_CURSOR_MODE, mode);
1276 
1277     if (!cursor->enable)
1278         x = 2047;   /* push it outside display */
1279     pm2v_RDAC_WR(par, PM2VI_RD_CURSOR_X_LOW, x & 0xff);
1280     pm2v_RDAC_WR(par, PM2VI_RD_CURSOR_X_HIGH, (x >> 8) & 0xf);
1281     pm2v_RDAC_WR(par, PM2VI_RD_CURSOR_Y_LOW, y & 0xff);
1282     pm2v_RDAC_WR(par, PM2VI_RD_CURSOR_Y_HIGH, (y >> 8) & 0xf);
1283 
1284     /*
1285      * If the cursor is not be changed this means either we want the
1286      * current cursor state (if enable is set) or we want to query what
1287      * we can do with the cursor (if enable is not set)
1288      */
1289     if (!cursor->set)
1290         return 0;
1291 
1292     if (cursor->set & FB_CUR_SETHOT) {
1293         pm2v_RDAC_WR(par, PM2VI_RD_CURSOR_X_HOT,
1294                  cursor->hot.x & 0x3f);
1295         pm2v_RDAC_WR(par, PM2VI_RD_CURSOR_Y_HOT,
1296                  cursor->hot.y & 0x3f);
1297     }
1298 
1299     if (cursor->set & FB_CUR_SETCMAP) {
1300         u32 fg_idx = cursor->image.fg_color;
1301         u32 bg_idx = cursor->image.bg_color;
1302         struct fb_cmap cmap = info->cmap;
1303 
1304         /* the X11 driver says one should use these color registers */
1305         pm2_WR(par, PM2VR_RD_INDEX_HIGH, PM2VI_RD_CURSOR_PALETTE >> 8);
1306         pm2v_RDAC_WR(par, PM2VI_RD_CURSOR_PALETTE + 0,
1307                  cmap.red[bg_idx] >> 8 );
1308         pm2v_RDAC_WR(par, PM2VI_RD_CURSOR_PALETTE + 1,
1309                  cmap.green[bg_idx] >> 8 );
1310         pm2v_RDAC_WR(par, PM2VI_RD_CURSOR_PALETTE + 2,
1311                  cmap.blue[bg_idx] >> 8 );
1312 
1313         pm2v_RDAC_WR(par, PM2VI_RD_CURSOR_PALETTE + 3,
1314                  cmap.red[fg_idx] >> 8 );
1315         pm2v_RDAC_WR(par, PM2VI_RD_CURSOR_PALETTE + 4,
1316                  cmap.green[fg_idx] >> 8 );
1317         pm2v_RDAC_WR(par, PM2VI_RD_CURSOR_PALETTE + 5,
1318                  cmap.blue[fg_idx] >> 8 );
1319         pm2_WR(par, PM2VR_RD_INDEX_HIGH, 0);
1320     }
1321 
1322     if (cursor->set & (FB_CUR_SETSHAPE | FB_CUR_SETIMAGE)) {
1323         u8 *bitmap = (u8 *)cursor->image.data;
1324         u8 *mask = (u8 *)cursor->mask;
1325         int i;
1326         int pos = PM2VI_RD_CURSOR_PATTERN;
1327 
1328         for (i = 0; i < cursor->image.height; i++) {
1329             int j = (cursor->image.width + 7) >> 3;
1330             int k = 8 - j;
1331 
1332             pm2_WR(par, PM2VR_RD_INDEX_HIGH, pos >> 8);
1333 
1334             for (; j > 0; j--) {
1335                 u8 data = *bitmap ^ *mask;
1336 
1337                 if (cursor->rop == ROP_COPY)
1338                     data = *mask & *bitmap;
1339                 /* Upper 4 bits of bitmap data */
1340                 pm2v_RDAC_WR(par, pos++,
1341                     cursor_bits_lookup[data >> 4] |
1342                     (cursor_bits_lookup[*mask >> 4] << 1));
1343                 /* Lower 4 bits of bitmap */
1344                 pm2v_RDAC_WR(par, pos++,
1345                     cursor_bits_lookup[data & 0xf] |
1346                     (cursor_bits_lookup[*mask & 0xf] << 1));
1347                 bitmap++;
1348                 mask++;
1349             }
1350             for (; k > 0; k--) {
1351                 pm2v_RDAC_WR(par, pos++, 0);
1352                 pm2v_RDAC_WR(par, pos++, 0);
1353             }
1354         }
1355 
1356         while (pos < (1024 + PM2VI_RD_CURSOR_PATTERN)) {
1357             pm2_WR(par, PM2VR_RD_INDEX_HIGH, pos >> 8);
1358             pm2v_RDAC_WR(par, pos++, 0);
1359         }
1360 
1361         pm2_WR(par, PM2VR_RD_INDEX_HIGH, 0);
1362     }
1363     return 0;
1364 }
1365 
1366 static int pm2fb_cursor(struct fb_info *info, struct fb_cursor *cursor)
1367 {
1368     struct pm2fb_par *par = info->par;
1369     u8 mode;
1370 
1371     if (!hwcursor)
1372         return -EINVAL; /* just to force soft_cursor() call */
1373 
1374     /* Too large of a cursor or wrong bpp :-( */
1375     if (cursor->image.width > 64 ||
1376         cursor->image.height > 64 ||
1377         cursor->image.depth > 1)
1378         return -EINVAL;
1379 
1380     if (par->type == PM2_TYPE_PERMEDIA2V)
1381         return pm2vfb_cursor(info, cursor);
1382 
1383     mode = 0x40;
1384     if (cursor->enable)
1385          mode = 0x43;
1386 
1387     pm2_RDAC_WR(par, PM2I_RD_CURSOR_CONTROL, mode);
1388 
1389     /*
1390      * If the cursor is not be changed this means either we want the
1391      * current cursor state (if enable is set) or we want to query what
1392      * we can do with the cursor (if enable is not set)
1393      */
1394     if (!cursor->set)
1395         return 0;
1396 
1397     if (cursor->set & FB_CUR_SETPOS) {
1398         int x = cursor->image.dx - info->var.xoffset + 63;
1399         int y = cursor->image.dy - info->var.yoffset + 63;
1400 
1401         WAIT_FIFO(par, 4);
1402         pm2_WR(par, PM2R_RD_CURSOR_X_LSB, x & 0xff);
1403         pm2_WR(par, PM2R_RD_CURSOR_X_MSB, (x >> 8) & 0x7);
1404         pm2_WR(par, PM2R_RD_CURSOR_Y_LSB, y & 0xff);
1405         pm2_WR(par, PM2R_RD_CURSOR_Y_MSB, (y >> 8) & 0x7);
1406     }
1407 
1408     if (cursor->set & FB_CUR_SETCMAP) {
1409         u32 fg_idx = cursor->image.fg_color;
1410         u32 bg_idx = cursor->image.bg_color;
1411 
1412         WAIT_FIFO(par, 7);
1413         pm2_WR(par, PM2R_RD_CURSOR_COLOR_ADDRESS, 1);
1414         pm2_WR(par, PM2R_RD_CURSOR_COLOR_DATA,
1415             info->cmap.red[bg_idx] >> 8);
1416         pm2_WR(par, PM2R_RD_CURSOR_COLOR_DATA,
1417             info->cmap.green[bg_idx] >> 8);
1418         pm2_WR(par, PM2R_RD_CURSOR_COLOR_DATA,
1419             info->cmap.blue[bg_idx] >> 8);
1420 
1421         pm2_WR(par, PM2R_RD_CURSOR_COLOR_DATA,
1422             info->cmap.red[fg_idx] >> 8);
1423         pm2_WR(par, PM2R_RD_CURSOR_COLOR_DATA,
1424             info->cmap.green[fg_idx] >> 8);
1425         pm2_WR(par, PM2R_RD_CURSOR_COLOR_DATA,
1426             info->cmap.blue[fg_idx] >> 8);
1427     }
1428 
1429     if (cursor->set & (FB_CUR_SETSHAPE | FB_CUR_SETIMAGE)) {
1430         u8 *bitmap = (u8 *)cursor->image.data;
1431         u8 *mask = (u8 *)cursor->mask;
1432         int i;
1433 
1434         WAIT_FIFO(par, 1);
1435         pm2_WR(par, PM2R_RD_PALETTE_WRITE_ADDRESS, 0);
1436 
1437         for (i = 0; i < cursor->image.height; i++) {
1438             int j = (cursor->image.width + 7) >> 3;
1439             int k = 8 - j;
1440 
1441             WAIT_FIFO(par, 8);
1442             for (; j > 0; j--) {
1443                 u8 data = *bitmap ^ *mask;
1444 
1445                 if (cursor->rop == ROP_COPY)
1446                     data = *mask & *bitmap;
1447                 /* bitmap data */
1448                 pm2_WR(par, PM2R_RD_CURSOR_DATA, data);
1449                 bitmap++;
1450                 mask++;
1451             }
1452             for (; k > 0; k--)
1453                 pm2_WR(par, PM2R_RD_CURSOR_DATA, 0);
1454         }
1455         for (; i < 64; i++) {
1456             int j = 8;
1457             WAIT_FIFO(par, 8);
1458             while (j-- > 0)
1459                 pm2_WR(par, PM2R_RD_CURSOR_DATA, 0);
1460         }
1461 
1462         mask = (u8 *)cursor->mask;
1463         for (i = 0; i < cursor->image.height; i++) {
1464             int j = (cursor->image.width + 7) >> 3;
1465             int k = 8 - j;
1466 
1467             WAIT_FIFO(par, 8);
1468             for (; j > 0; j--) {
1469                 /* mask */
1470                 pm2_WR(par, PM2R_RD_CURSOR_DATA, *mask);
1471                 mask++;
1472             }
1473             for (; k > 0; k--)
1474                 pm2_WR(par, PM2R_RD_CURSOR_DATA, 0);
1475         }
1476         for (; i < 64; i++) {
1477             int j = 8;
1478             WAIT_FIFO(par, 8);
1479             while (j-- > 0)
1480                 pm2_WR(par, PM2R_RD_CURSOR_DATA, 0);
1481         }
1482     }
1483     return 0;
1484 }
1485 
1486 /* ------------ Hardware Independent Functions ------------ */
1487 
1488 /*
1489  *  Frame buffer operations
1490  */
1491 
1492 static const struct fb_ops pm2fb_ops = {
1493     .owner      = THIS_MODULE,
1494     .fb_check_var   = pm2fb_check_var,
1495     .fb_set_par = pm2fb_set_par,
1496     .fb_setcolreg   = pm2fb_setcolreg,
1497     .fb_blank   = pm2fb_blank,
1498     .fb_pan_display = pm2fb_pan_display,
1499     .fb_fillrect    = pm2fb_fillrect,
1500     .fb_copyarea    = pm2fb_copyarea,
1501     .fb_imageblit   = pm2fb_imageblit,
1502     .fb_sync    = pm2fb_sync,
1503     .fb_cursor  = pm2fb_cursor,
1504 };
1505 
1506 /*
1507  * PCI stuff
1508  */
1509 
1510 
1511 /**
1512  * pm2fb_probe - Initialise and allocate resource for PCI device.
1513  *
1514  * @pdev:   PCI device.
1515  * @id:     PCI device ID.
1516  */
1517 static int pm2fb_probe(struct pci_dev *pdev, const struct pci_device_id *id)
1518 {
1519     struct pm2fb_par *default_par;
1520     struct fb_info *info;
1521     int err;
1522     int retval = -ENXIO;
1523 
1524     err = pci_enable_device(pdev);
1525     if (err) {
1526         printk(KERN_WARNING "pm2fb: Can't enable pdev: %d\n", err);
1527         return err;
1528     }
1529 
1530     info = framebuffer_alloc(sizeof(struct pm2fb_par), &pdev->dev);
1531     if (!info)
1532         return -ENOMEM;
1533     default_par = info->par;
1534 
1535     switch (pdev->device) {
1536     case  PCI_DEVICE_ID_TI_TVP4020:
1537         strcpy(pm2fb_fix.id, "TVP4020");
1538         default_par->type = PM2_TYPE_PERMEDIA2;
1539         break;
1540     case  PCI_DEVICE_ID_3DLABS_PERMEDIA2:
1541         strcpy(pm2fb_fix.id, "Permedia2");
1542         default_par->type = PM2_TYPE_PERMEDIA2;
1543         break;
1544     case  PCI_DEVICE_ID_3DLABS_PERMEDIA2V:
1545         strcpy(pm2fb_fix.id, "Permedia2v");
1546         default_par->type = PM2_TYPE_PERMEDIA2V;
1547         break;
1548     }
1549 
1550     pm2fb_fix.mmio_start = pci_resource_start(pdev, 0);
1551     pm2fb_fix.mmio_len = PM2_REGS_SIZE;
1552 
1553 #if defined(__BIG_ENDIAN)
1554     /*
1555      * PM2 has a 64k register file, mapped twice in 128k. Lower
1556      * map is little-endian, upper map is big-endian.
1557      */
1558     pm2fb_fix.mmio_start += PM2_REGS_SIZE;
1559     DPRINTK("Adjusting register base for big-endian.\n");
1560 #endif
1561     DPRINTK("Register base at 0x%lx\n", pm2fb_fix.mmio_start);
1562 
1563     /* Registers - request region and map it. */
1564     if (!request_mem_region(pm2fb_fix.mmio_start, pm2fb_fix.mmio_len,
1565                 "pm2fb regbase")) {
1566         printk(KERN_WARNING "pm2fb: Can't reserve regbase.\n");
1567         goto err_exit_neither;
1568     }
1569     default_par->v_regs =
1570         ioremap(pm2fb_fix.mmio_start, pm2fb_fix.mmio_len);
1571     if (!default_par->v_regs) {
1572         printk(KERN_WARNING "pm2fb: Can't remap %s register area.\n",
1573                pm2fb_fix.id);
1574         release_mem_region(pm2fb_fix.mmio_start, pm2fb_fix.mmio_len);
1575         goto err_exit_neither;
1576     }
1577 
1578     /* Stash away memory register info for use when we reset the board */
1579     default_par->mem_control = pm2_RD(default_par, PM2R_MEM_CONTROL);
1580     default_par->boot_address = pm2_RD(default_par, PM2R_BOOT_ADDRESS);
1581     default_par->mem_config = pm2_RD(default_par, PM2R_MEM_CONFIG);
1582     DPRINTK("MemControl 0x%x BootAddress 0x%x MemConfig 0x%x\n",
1583         default_par->mem_control, default_par->boot_address,
1584         default_par->mem_config);
1585 
1586     if (default_par->mem_control == 0 &&
1587         default_par->boot_address == 0x31 &&
1588         default_par->mem_config == 0x259fffff) {
1589         default_par->memclock = CVPPC_MEMCLOCK;
1590         default_par->mem_control = 0;
1591         default_par->boot_address = 0x20;
1592         default_par->mem_config = 0xe6002021;
1593         if (pdev->subsystem_vendor == 0x1048 &&
1594             pdev->subsystem_device == 0x0a31) {
1595             DPRINTK("subsystem_vendor: %04x, "
1596                 "subsystem_device: %04x\n",
1597                 pdev->subsystem_vendor, pdev->subsystem_device);
1598             DPRINTK("We have not been initialized by VGA BIOS and "
1599                 "are running on an Elsa Winner 2000 Office\n");
1600             DPRINTK("Initializing card timings manually...\n");
1601             default_par->memclock = 100000;
1602         }
1603         if (pdev->subsystem_vendor == 0x3d3d &&
1604             pdev->subsystem_device == 0x0100) {
1605             DPRINTK("subsystem_vendor: %04x, "
1606                 "subsystem_device: %04x\n",
1607                 pdev->subsystem_vendor, pdev->subsystem_device);
1608             DPRINTK("We have not been initialized by VGA BIOS and "
1609                 "are running on an 3dlabs reference board\n");
1610             DPRINTK("Initializing card timings manually...\n");
1611             default_par->memclock = 74894;
1612         }
1613     }
1614 
1615     /* Now work out how big lfb is going to be. */
1616     switch (default_par->mem_config & PM2F_MEM_CONFIG_RAM_MASK) {
1617     case PM2F_MEM_BANKS_1:
1618         pm2fb_fix.smem_len = 0x200000;
1619         break;
1620     case PM2F_MEM_BANKS_2:
1621         pm2fb_fix.smem_len = 0x400000;
1622         break;
1623     case PM2F_MEM_BANKS_3:
1624         pm2fb_fix.smem_len = 0x600000;
1625         break;
1626     case PM2F_MEM_BANKS_4:
1627         pm2fb_fix.smem_len = 0x800000;
1628         break;
1629     }
1630     pm2fb_fix.smem_start = pci_resource_start(pdev, 1);
1631 
1632     /* Linear frame buffer - request region and map it. */
1633     if (!request_mem_region(pm2fb_fix.smem_start, pm2fb_fix.smem_len,
1634                 "pm2fb smem")) {
1635         printk(KERN_WARNING "pm2fb: Can't reserve smem.\n");
1636         goto err_exit_mmio;
1637     }
1638     info->screen_base =
1639         ioremap_wc(pm2fb_fix.smem_start, pm2fb_fix.smem_len);
1640     if (!info->screen_base) {
1641         printk(KERN_WARNING "pm2fb: Can't ioremap smem area.\n");
1642         release_mem_region(pm2fb_fix.smem_start, pm2fb_fix.smem_len);
1643         goto err_exit_mmio;
1644     }
1645 
1646     if (!nomtrr)
1647         default_par->wc_cookie = arch_phys_wc_add(pm2fb_fix.smem_start,
1648                               pm2fb_fix.smem_len);
1649 
1650     info->fbops     = &pm2fb_ops;
1651     info->fix       = pm2fb_fix;
1652     info->pseudo_palette    = default_par->palette;
1653     info->flags     = FBINFO_DEFAULT |
1654                   FBINFO_HWACCEL_YPAN |
1655                   FBINFO_HWACCEL_COPYAREA |
1656                   FBINFO_HWACCEL_IMAGEBLIT |
1657                   FBINFO_HWACCEL_FILLRECT;
1658 
1659     info->pixmap.addr = kmalloc(PM2_PIXMAP_SIZE, GFP_KERNEL);
1660     if (!info->pixmap.addr) {
1661         retval = -ENOMEM;
1662         goto err_exit_pixmap;
1663     }
1664     info->pixmap.size = PM2_PIXMAP_SIZE;
1665     info->pixmap.buf_align = 4;
1666     info->pixmap.scan_align = 4;
1667     info->pixmap.access_align = 32;
1668     info->pixmap.flags = FB_PIXMAP_SYSTEM;
1669 
1670     if (noaccel) {
1671         printk(KERN_DEBUG "disabling acceleration\n");
1672         info->flags |= FBINFO_HWACCEL_DISABLED;
1673         info->pixmap.scan_align = 1;
1674     }
1675 
1676     if (!mode_option)
1677         mode_option = "640x480@60";
1678 
1679     err = fb_find_mode(&info->var, info, mode_option, NULL, 0, NULL, 8);
1680     if (!err || err == 4)
1681         info->var = pm2fb_var;
1682 
1683     retval = fb_alloc_cmap(&info->cmap, 256, 0);
1684     if (retval < 0)
1685         goto err_exit_both;
1686 
1687     retval = register_framebuffer(info);
1688     if (retval < 0)
1689         goto err_exit_all;
1690 
1691     fb_info(info, "%s frame buffer device, memory = %dK\n",
1692         info->fix.id, pm2fb_fix.smem_len / 1024);
1693 
1694     /*
1695      * Our driver data
1696      */
1697     pci_set_drvdata(pdev, info);
1698 
1699     return 0;
1700 
1701  err_exit_all:
1702     fb_dealloc_cmap(&info->cmap);
1703  err_exit_both:
1704     kfree(info->pixmap.addr);
1705  err_exit_pixmap:
1706     iounmap(info->screen_base);
1707     release_mem_region(pm2fb_fix.smem_start, pm2fb_fix.smem_len);
1708  err_exit_mmio:
1709     iounmap(default_par->v_regs);
1710     release_mem_region(pm2fb_fix.mmio_start, pm2fb_fix.mmio_len);
1711  err_exit_neither:
1712     framebuffer_release(info);
1713     return retval;
1714 }
1715 
1716 /**
1717  * pm2fb_remove - Release all device resources.
1718  *
1719  * @pdev:   PCI device to clean up.
1720  */
1721 static void pm2fb_remove(struct pci_dev *pdev)
1722 {
1723     struct fb_info *info = pci_get_drvdata(pdev);
1724     struct fb_fix_screeninfo *fix = &info->fix;
1725     struct pm2fb_par *par = info->par;
1726 
1727     unregister_framebuffer(info);
1728     arch_phys_wc_del(par->wc_cookie);
1729     iounmap(info->screen_base);
1730     release_mem_region(fix->smem_start, fix->smem_len);
1731     iounmap(par->v_regs);
1732     release_mem_region(fix->mmio_start, fix->mmio_len);
1733 
1734     fb_dealloc_cmap(&info->cmap);
1735     kfree(info->pixmap.addr);
1736     framebuffer_release(info);
1737 }
1738 
1739 static const struct pci_device_id pm2fb_id_table[] = {
1740     { PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_TVP4020,
1741       PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
1742     { PCI_VENDOR_ID_3DLABS, PCI_DEVICE_ID_3DLABS_PERMEDIA2,
1743       PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
1744     { PCI_VENDOR_ID_3DLABS, PCI_DEVICE_ID_3DLABS_PERMEDIA2V,
1745       PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
1746     { 0, }
1747 };
1748 
1749 static struct pci_driver pm2fb_driver = {
1750     .name       = "pm2fb",
1751     .id_table   = pm2fb_id_table,
1752     .probe      = pm2fb_probe,
1753     .remove     = pm2fb_remove,
1754 };
1755 
1756 MODULE_DEVICE_TABLE(pci, pm2fb_id_table);
1757 
1758 
1759 #ifndef MODULE
1760 /*
1761  * Parse user specified options.
1762  *
1763  * This is, comma-separated options following `video=pm2fb:'.
1764  */
1765 static int __init pm2fb_setup(char *options)
1766 {
1767     char *this_opt;
1768 
1769     if (!options || !*options)
1770         return 0;
1771 
1772     while ((this_opt = strsep(&options, ",")) != NULL) {
1773         if (!*this_opt)
1774             continue;
1775         if (!strcmp(this_opt, "lowhsync"))
1776             lowhsync = 1;
1777         else if (!strcmp(this_opt, "lowvsync"))
1778             lowvsync = 1;
1779         else if (!strncmp(this_opt, "hwcursor=", 9))
1780             hwcursor = simple_strtoul(this_opt + 9, NULL, 0);
1781         else if (!strncmp(this_opt, "nomtrr", 6))
1782             nomtrr = 1;
1783         else if (!strncmp(this_opt, "noaccel", 7))
1784             noaccel = 1;
1785         else
1786             mode_option = this_opt;
1787     }
1788     return 0;
1789 }
1790 #endif
1791 
1792 
1793 static int __init pm2fb_init(void)
1794 {
1795 #ifndef MODULE
1796     char *option = NULL;
1797 
1798     if (fb_get_options("pm2fb", &option))
1799         return -ENODEV;
1800     pm2fb_setup(option);
1801 #endif
1802 
1803     return pci_register_driver(&pm2fb_driver);
1804 }
1805 
1806 module_init(pm2fb_init);
1807 
1808 #ifdef MODULE
1809 /*
1810  *  Cleanup
1811  */
1812 
1813 static void __exit pm2fb_exit(void)
1814 {
1815     pci_unregister_driver(&pm2fb_driver);
1816 }
1817 #endif
1818 
1819 #ifdef MODULE
1820 module_exit(pm2fb_exit);
1821 
1822 module_param(mode_option, charp, 0);
1823 MODULE_PARM_DESC(mode_option, "Initial video mode e.g. '648x480-8@60'");
1824 module_param_named(mode, mode_option, charp, 0);
1825 MODULE_PARM_DESC(mode, "Initial video mode e.g. '648x480-8@60' (deprecated)");
1826 module_param(lowhsync, bool, 0);
1827 MODULE_PARM_DESC(lowhsync, "Force horizontal sync low regardless of mode");
1828 module_param(lowvsync, bool, 0);
1829 MODULE_PARM_DESC(lowvsync, "Force vertical sync low regardless of mode");
1830 module_param(noaccel, bool, 0);
1831 MODULE_PARM_DESC(noaccel, "Disable acceleration");
1832 module_param(hwcursor, int, 0644);
1833 MODULE_PARM_DESC(hwcursor, "Enable hardware cursor "
1834             "(1=enable, 0=disable, default=1)");
1835 module_param(nomtrr, bool, 0);
1836 MODULE_PARM_DESC(nomtrr, "Disable MTRR support (0 or 1=disabled) (default=0)");
1837 
1838 MODULE_AUTHOR("Jim Hague <jim.hague@acm.org>");
1839 MODULE_DESCRIPTION("Permedia2 framebuffer device driver");
1840 MODULE_LICENSE("GPL");
1841 #endif