0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015 #include <linux/bitrev.h>
0016 #include <linux/compiler.h>
0017 #include <linux/delay.h>
0018 #include <linux/device.h>
0019 #include <linux/errno.h>
0020 #include <linux/fb.h>
0021 #include <linux/init.h>
0022 #include <linux/ioport.h>
0023 #include <linux/kernel.h>
0024 #include <linux/mm.h>
0025 #include <linux/module.h>
0026 #include <linux/pci.h>
0027 #include <linux/selection.h>
0028 #include <linux/string.h>
0029 #include <linux/tc.h>
0030
0031 #include <asm/io.h>
0032
0033 #include <video/tgafb.h>
0034
0035 #ifdef CONFIG_TC
0036 #define TGA_BUS_TC(dev) (dev->bus == &tc_bus_type)
0037 #else
0038 #define TGA_BUS_TC(dev) 0
0039 #endif
0040
0041
0042
0043
0044
0045 static int tgafb_check_var(struct fb_var_screeninfo *, struct fb_info *);
0046 static int tgafb_set_par(struct fb_info *);
0047 static void tgafb_set_pll(struct tga_par *, int);
0048 static int tgafb_setcolreg(unsigned, unsigned, unsigned, unsigned,
0049 unsigned, struct fb_info *);
0050 static int tgafb_blank(int, struct fb_info *);
0051 static void tgafb_init_fix(struct fb_info *);
0052
0053 static void tgafb_imageblit(struct fb_info *, const struct fb_image *);
0054 static void tgafb_fillrect(struct fb_info *, const struct fb_fillrect *);
0055 static void tgafb_copyarea(struct fb_info *, const struct fb_copyarea *);
0056 static int tgafb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info);
0057
0058 static int tgafb_register(struct device *dev);
0059 static void tgafb_unregister(struct device *dev);
0060
0061 static const char *mode_option;
0062 static const char *mode_option_pci = "640x480@60";
0063 static const char *mode_option_tc = "1280x1024@72";
0064
0065
0066 static struct pci_driver tgafb_pci_driver;
0067 static struct tc_driver tgafb_tc_driver;
0068
0069
0070
0071
0072
0073 static const struct fb_ops tgafb_ops = {
0074 .owner = THIS_MODULE,
0075 .fb_check_var = tgafb_check_var,
0076 .fb_set_par = tgafb_set_par,
0077 .fb_setcolreg = tgafb_setcolreg,
0078 .fb_blank = tgafb_blank,
0079 .fb_pan_display = tgafb_pan_display,
0080 .fb_fillrect = tgafb_fillrect,
0081 .fb_copyarea = tgafb_copyarea,
0082 .fb_imageblit = tgafb_imageblit,
0083 };
0084
0085
0086 #ifdef CONFIG_PCI
0087
0088
0089
0090 static int tgafb_pci_register(struct pci_dev *, const struct pci_device_id *);
0091 static void tgafb_pci_unregister(struct pci_dev *);
0092
0093 static struct pci_device_id const tgafb_pci_table[] = {
0094 { PCI_DEVICE(PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_TGA) },
0095 { }
0096 };
0097 MODULE_DEVICE_TABLE(pci, tgafb_pci_table);
0098
0099 static struct pci_driver tgafb_pci_driver = {
0100 .name = "tgafb",
0101 .id_table = tgafb_pci_table,
0102 .probe = tgafb_pci_register,
0103 .remove = tgafb_pci_unregister,
0104 };
0105
0106 static int tgafb_pci_register(struct pci_dev *pdev,
0107 const struct pci_device_id *ent)
0108 {
0109 return tgafb_register(&pdev->dev);
0110 }
0111
0112 static void tgafb_pci_unregister(struct pci_dev *pdev)
0113 {
0114 tgafb_unregister(&pdev->dev);
0115 }
0116 #endif
0117
0118 #ifdef CONFIG_TC
0119
0120
0121
0122 static int tgafb_tc_register(struct device *);
0123 static int tgafb_tc_unregister(struct device *);
0124
0125 static struct tc_device_id const tgafb_tc_table[] = {
0126 { "DEC ", "PMAGD-AA" },
0127 { "DEC ", "PMAGD " },
0128 { }
0129 };
0130 MODULE_DEVICE_TABLE(tc, tgafb_tc_table);
0131
0132 static struct tc_driver tgafb_tc_driver = {
0133 .id_table = tgafb_tc_table,
0134 .driver = {
0135 .name = "tgafb",
0136 .bus = &tc_bus_type,
0137 .probe = tgafb_tc_register,
0138 .remove = tgafb_tc_unregister,
0139 },
0140 };
0141
0142 static int tgafb_tc_register(struct device *dev)
0143 {
0144 int status = tgafb_register(dev);
0145 if (!status)
0146 get_device(dev);
0147 return status;
0148 }
0149
0150 static int tgafb_tc_unregister(struct device *dev)
0151 {
0152 put_device(dev);
0153 tgafb_unregister(dev);
0154 return 0;
0155 }
0156 #endif
0157
0158
0159
0160
0161
0162
0163
0164 static int
0165 tgafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
0166 {
0167 struct tga_par *par = (struct tga_par *)info->par;
0168
0169 if (par->tga_type == TGA_TYPE_8PLANE) {
0170 if (var->bits_per_pixel != 8)
0171 return -EINVAL;
0172 } else {
0173 if (var->bits_per_pixel != 32)
0174 return -EINVAL;
0175 }
0176 var->red.length = var->green.length = var->blue.length = 8;
0177 if (var->bits_per_pixel == 32) {
0178 var->red.offset = 16;
0179 var->green.offset = 8;
0180 var->blue.offset = 0;
0181 }
0182
0183 if (var->xres_virtual != var->xres || var->yres_virtual != var->yres)
0184 return -EINVAL;
0185 if (var->xres * var->yres * (var->bits_per_pixel >> 3) > info->fix.smem_len)
0186 return -EINVAL;
0187 if (var->nonstd)
0188 return -EINVAL;
0189 if (1000000000 / var->pixclock > TGA_PLL_MAX_FREQ)
0190 return -EINVAL;
0191 if ((var->vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED)
0192 return -EINVAL;
0193
0194
0195
0196 if (var->xres * (par->tga_type == TGA_TYPE_8PLANE ? 1 : 4) % 8)
0197 return -EINVAL;
0198
0199 return 0;
0200 }
0201
0202
0203
0204
0205
0206 static int
0207 tgafb_set_par(struct fb_info *info)
0208 {
0209 static unsigned int const deep_presets[4] = {
0210 0x00004000,
0211 0x0000440d,
0212 0xffffffff,
0213 0x0000441d
0214 };
0215 static unsigned int const rasterop_presets[4] = {
0216 0x00000003,
0217 0x00000303,
0218 0xffffffff,
0219 0x00000303
0220 };
0221 static unsigned int const mode_presets[4] = {
0222 0x00000000,
0223 0x00000300,
0224 0xffffffff,
0225 0x00000300
0226 };
0227 static unsigned int const base_addr_presets[4] = {
0228 0x00000000,
0229 0x00000001,
0230 0xffffffff,
0231 0x00000001
0232 };
0233
0234 struct tga_par *par = (struct tga_par *) info->par;
0235 int tga_bus_pci = dev_is_pci(par->dev);
0236 int tga_bus_tc = TGA_BUS_TC(par->dev);
0237 u32 htimings, vtimings, pll_freq;
0238 u8 tga_type;
0239 int i;
0240
0241
0242 htimings = (((info->var.xres/4) & TGA_HORIZ_ACT_LSB)
0243 | (((info->var.xres/4) & 0x600 << 19) & TGA_HORIZ_ACT_MSB));
0244 vtimings = (info->var.yres & TGA_VERT_ACTIVE);
0245 htimings |= ((info->var.right_margin/4) << 9) & TGA_HORIZ_FP;
0246 vtimings |= (info->var.lower_margin << 11) & TGA_VERT_FP;
0247 htimings |= ((info->var.hsync_len/4) << 14) & TGA_HORIZ_SYNC;
0248 vtimings |= (info->var.vsync_len << 16) & TGA_VERT_SYNC;
0249 htimings |= ((info->var.left_margin/4) << 21) & TGA_HORIZ_BP;
0250 vtimings |= (info->var.upper_margin << 22) & TGA_VERT_BP;
0251
0252 if (info->var.sync & FB_SYNC_HOR_HIGH_ACT)
0253 htimings |= TGA_HORIZ_POLARITY;
0254 if (info->var.sync & FB_SYNC_VERT_HIGH_ACT)
0255 vtimings |= TGA_VERT_POLARITY;
0256
0257 par->htimings = htimings;
0258 par->vtimings = vtimings;
0259
0260 par->sync_on_green = !!(info->var.sync & FB_SYNC_ON_GREEN);
0261
0262
0263 par->xres = info->var.xres;
0264 par->yres = info->var.yres;
0265 par->pll_freq = pll_freq = 1000000000 / info->var.pixclock;
0266 par->bits_per_pixel = info->var.bits_per_pixel;
0267 info->fix.line_length = par->xres * (par->bits_per_pixel >> 3);
0268
0269 tga_type = par->tga_type;
0270
0271
0272 TGA_WRITE_REG(par, TGA_VALID_VIDEO | TGA_VALID_BLANK, TGA_VALID_REG);
0273
0274
0275 while (TGA_READ_REG(par, TGA_CMD_STAT_REG) & 1)
0276 continue;
0277 mb();
0278 TGA_WRITE_REG(par, deep_presets[tga_type] |
0279 (par->sync_on_green ? 0x0 : 0x00010000),
0280 TGA_DEEP_REG);
0281 while (TGA_READ_REG(par, TGA_CMD_STAT_REG) & 1)
0282 continue;
0283 mb();
0284
0285
0286 TGA_WRITE_REG(par, rasterop_presets[tga_type], TGA_RASTEROP_REG);
0287 TGA_WRITE_REG(par, mode_presets[tga_type], TGA_MODE_REG);
0288 TGA_WRITE_REG(par, base_addr_presets[tga_type], TGA_BASE_ADDR_REG);
0289
0290
0291 tgafb_set_pll(par, pll_freq);
0292
0293
0294 TGA_WRITE_REG(par, 0xffffffff, TGA_PLANEMASK_REG);
0295 TGA_WRITE_REG(par, 0xffffffff, TGA_PIXELMASK_REG);
0296
0297
0298 TGA_WRITE_REG(par, htimings, TGA_HORIZ_REG);
0299 TGA_WRITE_REG(par, vtimings, TGA_VERT_REG);
0300
0301
0302 if (tga_type == TGA_TYPE_8PLANE && tga_bus_pci) {
0303
0304
0305 BT485_WRITE(par, 0xa2 | (par->sync_on_green ? 0x8 : 0x0),
0306 BT485_CMD_0);
0307 BT485_WRITE(par, 0x01, BT485_ADDR_PAL_WRITE);
0308 BT485_WRITE(par, 0x14, BT485_CMD_3);
0309 BT485_WRITE(par, 0x40, BT485_CMD_1);
0310 BT485_WRITE(par, 0x20, BT485_CMD_2);
0311 BT485_WRITE(par, 0xff, BT485_PIXEL_MASK);
0312
0313
0314 BT485_WRITE(par, 0x00, BT485_ADDR_PAL_WRITE);
0315 TGA_WRITE_REG(par, BT485_DATA_PAL, TGA_RAMDAC_SETUP_REG);
0316
0317 for (i = 0; i < 256 * 3; i += 4) {
0318 TGA_WRITE_REG(par, 0x55 | (BT485_DATA_PAL << 8),
0319 TGA_RAMDAC_REG);
0320 TGA_WRITE_REG(par, 0x00 | (BT485_DATA_PAL << 8),
0321 TGA_RAMDAC_REG);
0322 TGA_WRITE_REG(par, 0x00 | (BT485_DATA_PAL << 8),
0323 TGA_RAMDAC_REG);
0324 TGA_WRITE_REG(par, 0x00 | (BT485_DATA_PAL << 8),
0325 TGA_RAMDAC_REG);
0326 }
0327
0328 } else if (tga_type == TGA_TYPE_8PLANE && tga_bus_tc) {
0329
0330
0331 BT459_WRITE(par, BT459_REG_ACC, BT459_CMD_REG_0, 0x40);
0332 BT459_WRITE(par, BT459_REG_ACC, BT459_CMD_REG_1, 0x00);
0333 BT459_WRITE(par, BT459_REG_ACC, BT459_CMD_REG_2,
0334 (par->sync_on_green ? 0xc0 : 0x40));
0335
0336 BT459_WRITE(par, BT459_REG_ACC, BT459_CUR_CMD_REG, 0x00);
0337
0338
0339 BT459_LOAD_ADDR(par, 0x0000);
0340 TGA_WRITE_REG(par, BT459_PALETTE << 2, TGA_RAMDAC_SETUP_REG);
0341
0342 for (i = 0; i < 256 * 3; i += 4) {
0343 TGA_WRITE_REG(par, 0x55, TGA_RAMDAC_REG);
0344 TGA_WRITE_REG(par, 0x00, TGA_RAMDAC_REG);
0345 TGA_WRITE_REG(par, 0x00, TGA_RAMDAC_REG);
0346 TGA_WRITE_REG(par, 0x00, TGA_RAMDAC_REG);
0347 }
0348
0349 } else {
0350
0351
0352 BT463_WRITE(par, BT463_REG_ACC, BT463_CMD_REG_0, 0x40);
0353 BT463_WRITE(par, BT463_REG_ACC, BT463_CMD_REG_1, 0x08);
0354 BT463_WRITE(par, BT463_REG_ACC, BT463_CMD_REG_2,
0355 (par->sync_on_green ? 0xc0 : 0x40));
0356
0357 BT463_WRITE(par, BT463_REG_ACC, BT463_READ_MASK_0, 0xff);
0358 BT463_WRITE(par, BT463_REG_ACC, BT463_READ_MASK_1, 0xff);
0359 BT463_WRITE(par, BT463_REG_ACC, BT463_READ_MASK_2, 0xff);
0360 BT463_WRITE(par, BT463_REG_ACC, BT463_READ_MASK_3, 0x0f);
0361
0362 BT463_WRITE(par, BT463_REG_ACC, BT463_BLINK_MASK_0, 0x00);
0363 BT463_WRITE(par, BT463_REG_ACC, BT463_BLINK_MASK_1, 0x00);
0364 BT463_WRITE(par, BT463_REG_ACC, BT463_BLINK_MASK_2, 0x00);
0365 BT463_WRITE(par, BT463_REG_ACC, BT463_BLINK_MASK_3, 0x00);
0366
0367
0368 BT463_LOAD_ADDR(par, 0x0000);
0369 TGA_WRITE_REG(par, BT463_PALETTE << 2, TGA_RAMDAC_SETUP_REG);
0370
0371 #ifdef CONFIG_HW_CONSOLE
0372 for (i = 0; i < 16; i++) {
0373 int j = color_table[i];
0374
0375 TGA_WRITE_REG(par, default_red[j], TGA_RAMDAC_REG);
0376 TGA_WRITE_REG(par, default_grn[j], TGA_RAMDAC_REG);
0377 TGA_WRITE_REG(par, default_blu[j], TGA_RAMDAC_REG);
0378 }
0379 for (i = 0; i < 512 * 3; i += 4) {
0380 #else
0381 for (i = 0; i < 528 * 3; i += 4) {
0382 #endif
0383 TGA_WRITE_REG(par, 0x55, TGA_RAMDAC_REG);
0384 TGA_WRITE_REG(par, 0x00, TGA_RAMDAC_REG);
0385 TGA_WRITE_REG(par, 0x00, TGA_RAMDAC_REG);
0386 TGA_WRITE_REG(par, 0x00, TGA_RAMDAC_REG);
0387 }
0388
0389
0390 while (!(TGA_READ_REG(par, TGA_INTR_STAT_REG) & 0x01))
0391 continue;
0392 TGA_WRITE_REG(par, 0x01, TGA_INTR_STAT_REG);
0393 mb();
0394 while (!(TGA_READ_REG(par, TGA_INTR_STAT_REG) & 0x01))
0395 continue;
0396 TGA_WRITE_REG(par, 0x01, TGA_INTR_STAT_REG);
0397
0398 BT463_LOAD_ADDR(par, BT463_WINDOW_TYPE_BASE);
0399 TGA_WRITE_REG(par, BT463_REG_ACC << 2, TGA_RAMDAC_SETUP_REG);
0400
0401 for (i = 0; i < 16; i++) {
0402 TGA_WRITE_REG(par, 0x00, TGA_RAMDAC_REG);
0403 TGA_WRITE_REG(par, 0x01, TGA_RAMDAC_REG);
0404 TGA_WRITE_REG(par, 0x00, TGA_RAMDAC_REG);
0405 }
0406
0407 }
0408
0409
0410 TGA_WRITE_REG(par, TGA_VALID_VIDEO, TGA_VALID_REG);
0411
0412 return 0;
0413 }
0414
0415 #define DIFFCHECK(X) \
0416 do { \
0417 if (m <= 0x3f) { \
0418 int delta = f - (TGA_PLL_BASE_FREQ * (X)) / (r << shift); \
0419 if (delta < 0) \
0420 delta = -delta; \
0421 if (delta < min_diff) \
0422 min_diff = delta, vm = m, va = a, vr = r; \
0423 } \
0424 } while (0)
0425
0426 static void
0427 tgafb_set_pll(struct tga_par *par, int f)
0428 {
0429 int n, shift, base, min_diff, target;
0430 int r,a,m,vm = 34, va = 1, vr = 30;
0431
0432 for (r = 0 ; r < 12 ; r++)
0433 TGA_WRITE_REG(par, !r, TGA_CLOCK_REG);
0434
0435 if (f > TGA_PLL_MAX_FREQ)
0436 f = TGA_PLL_MAX_FREQ;
0437
0438 if (f >= TGA_PLL_MAX_FREQ / 2)
0439 shift = 0;
0440 else if (f >= TGA_PLL_MAX_FREQ / 4)
0441 shift = 1;
0442 else
0443 shift = 2;
0444
0445 TGA_WRITE_REG(par, shift & 1, TGA_CLOCK_REG);
0446 TGA_WRITE_REG(par, shift >> 1, TGA_CLOCK_REG);
0447
0448 for (r = 0 ; r < 10 ; r++)
0449 TGA_WRITE_REG(par, 0, TGA_CLOCK_REG);
0450
0451 if (f <= 120000) {
0452 TGA_WRITE_REG(par, 0, TGA_CLOCK_REG);
0453 TGA_WRITE_REG(par, 0, TGA_CLOCK_REG);
0454 }
0455 else if (f <= 200000) {
0456 TGA_WRITE_REG(par, 1, TGA_CLOCK_REG);
0457 TGA_WRITE_REG(par, 0, TGA_CLOCK_REG);
0458 }
0459 else {
0460 TGA_WRITE_REG(par, 0, TGA_CLOCK_REG);
0461 TGA_WRITE_REG(par, 1, TGA_CLOCK_REG);
0462 }
0463
0464 TGA_WRITE_REG(par, 1, TGA_CLOCK_REG);
0465 TGA_WRITE_REG(par, 0, TGA_CLOCK_REG);
0466 TGA_WRITE_REG(par, 0, TGA_CLOCK_REG);
0467 TGA_WRITE_REG(par, 1, TGA_CLOCK_REG);
0468 TGA_WRITE_REG(par, 0, TGA_CLOCK_REG);
0469 TGA_WRITE_REG(par, 1, TGA_CLOCK_REG);
0470
0471 target = (f << shift) / TGA_PLL_BASE_FREQ;
0472 min_diff = TGA_PLL_MAX_FREQ;
0473
0474 r = 7 / target;
0475 if (!r) r = 1;
0476
0477 base = target * r;
0478 while (base < 449) {
0479 for (n = base < 7 ? 7 : base; n < base + target && n < 449; n++) {
0480 m = ((n + 3) / 7) - 1;
0481 a = 0;
0482 DIFFCHECK((m + 1) * 7);
0483 m++;
0484 DIFFCHECK((m + 1) * 7);
0485 m = (n / 6) - 1;
0486 if ((a = n % 6))
0487 DIFFCHECK(n);
0488 }
0489 r++;
0490 base += target;
0491 }
0492
0493 vr--;
0494
0495 for (r = 0; r < 8; r++)
0496 TGA_WRITE_REG(par, (vm >> r) & 1, TGA_CLOCK_REG);
0497 for (r = 0; r < 8 ; r++)
0498 TGA_WRITE_REG(par, (va >> r) & 1, TGA_CLOCK_REG);
0499 for (r = 0; r < 7 ; r++)
0500 TGA_WRITE_REG(par, (vr >> r) & 1, TGA_CLOCK_REG);
0501 TGA_WRITE_REG(par, ((vr >> 7) & 1)|2, TGA_CLOCK_REG);
0502 }
0503
0504
0505
0506
0507
0508
0509
0510
0511
0512
0513
0514 static int
0515 tgafb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue,
0516 unsigned transp, struct fb_info *info)
0517 {
0518 struct tga_par *par = (struct tga_par *) info->par;
0519 int tga_bus_pci = dev_is_pci(par->dev);
0520 int tga_bus_tc = TGA_BUS_TC(par->dev);
0521
0522 if (regno > 255)
0523 return 1;
0524 red >>= 8;
0525 green >>= 8;
0526 blue >>= 8;
0527
0528 if (par->tga_type == TGA_TYPE_8PLANE && tga_bus_pci) {
0529 BT485_WRITE(par, regno, BT485_ADDR_PAL_WRITE);
0530 TGA_WRITE_REG(par, BT485_DATA_PAL, TGA_RAMDAC_SETUP_REG);
0531 TGA_WRITE_REG(par, red|(BT485_DATA_PAL<<8),TGA_RAMDAC_REG);
0532 TGA_WRITE_REG(par, green|(BT485_DATA_PAL<<8),TGA_RAMDAC_REG);
0533 TGA_WRITE_REG(par, blue|(BT485_DATA_PAL<<8),TGA_RAMDAC_REG);
0534 } else if (par->tga_type == TGA_TYPE_8PLANE && tga_bus_tc) {
0535 BT459_LOAD_ADDR(par, regno);
0536 TGA_WRITE_REG(par, BT459_PALETTE << 2, TGA_RAMDAC_SETUP_REG);
0537 TGA_WRITE_REG(par, red, TGA_RAMDAC_REG);
0538 TGA_WRITE_REG(par, green, TGA_RAMDAC_REG);
0539 TGA_WRITE_REG(par, blue, TGA_RAMDAC_REG);
0540 } else {
0541 if (regno < 16) {
0542 u32 value = (regno << 16) | (regno << 8) | regno;
0543 ((u32 *)info->pseudo_palette)[regno] = value;
0544 }
0545 BT463_LOAD_ADDR(par, regno);
0546 TGA_WRITE_REG(par, BT463_PALETTE << 2, TGA_RAMDAC_SETUP_REG);
0547 TGA_WRITE_REG(par, red, TGA_RAMDAC_REG);
0548 TGA_WRITE_REG(par, green, TGA_RAMDAC_REG);
0549 TGA_WRITE_REG(par, blue, TGA_RAMDAC_REG);
0550 }
0551
0552 return 0;
0553 }
0554
0555
0556
0557
0558
0559
0560
0561 static int
0562 tgafb_blank(int blank, struct fb_info *info)
0563 {
0564 struct tga_par *par = (struct tga_par *) info->par;
0565 u32 vhcr, vvcr, vvvr;
0566 unsigned long flags;
0567
0568 local_irq_save(flags);
0569
0570 vhcr = TGA_READ_REG(par, TGA_HORIZ_REG);
0571 vvcr = TGA_READ_REG(par, TGA_VERT_REG);
0572 vvvr = TGA_READ_REG(par, TGA_VALID_REG);
0573 vvvr &= ~(TGA_VALID_VIDEO | TGA_VALID_BLANK);
0574
0575 switch (blank) {
0576 case FB_BLANK_UNBLANK:
0577 if (par->vesa_blanked) {
0578 TGA_WRITE_REG(par, vhcr & 0xbfffffff, TGA_HORIZ_REG);
0579 TGA_WRITE_REG(par, vvcr & 0xbfffffff, TGA_VERT_REG);
0580 par->vesa_blanked = 0;
0581 }
0582 TGA_WRITE_REG(par, vvvr | TGA_VALID_VIDEO, TGA_VALID_REG);
0583 break;
0584
0585 case FB_BLANK_NORMAL:
0586 TGA_WRITE_REG(par, vvvr | TGA_VALID_VIDEO | TGA_VALID_BLANK,
0587 TGA_VALID_REG);
0588 break;
0589
0590 case FB_BLANK_VSYNC_SUSPEND:
0591 TGA_WRITE_REG(par, vvcr | 0x40000000, TGA_VERT_REG);
0592 TGA_WRITE_REG(par, vvvr | TGA_VALID_BLANK, TGA_VALID_REG);
0593 par->vesa_blanked = 1;
0594 break;
0595
0596 case FB_BLANK_HSYNC_SUSPEND:
0597 TGA_WRITE_REG(par, vhcr | 0x40000000, TGA_HORIZ_REG);
0598 TGA_WRITE_REG(par, vvvr | TGA_VALID_BLANK, TGA_VALID_REG);
0599 par->vesa_blanked = 1;
0600 break;
0601
0602 case FB_BLANK_POWERDOWN:
0603 TGA_WRITE_REG(par, vhcr | 0x40000000, TGA_HORIZ_REG);
0604 TGA_WRITE_REG(par, vvcr | 0x40000000, TGA_VERT_REG);
0605 TGA_WRITE_REG(par, vvvr | TGA_VALID_BLANK, TGA_VALID_REG);
0606 par->vesa_blanked = 1;
0607 break;
0608 }
0609
0610 local_irq_restore(flags);
0611 return 0;
0612 }
0613
0614
0615
0616
0617
0618
0619 static void
0620 tgafb_mono_imageblit(struct fb_info *info, const struct fb_image *image)
0621 {
0622 struct tga_par *par = (struct tga_par *) info->par;
0623 u32 fgcolor, bgcolor, dx, dy, width, height, vxres, vyres, pixelmask;
0624 unsigned long rincr, line_length, shift, pos, is8bpp;
0625 unsigned long i, j;
0626 const unsigned char *data;
0627 void __iomem *regs_base;
0628 void __iomem *fb_base;
0629
0630 is8bpp = info->var.bits_per_pixel == 8;
0631
0632 dx = image->dx;
0633 dy = image->dy;
0634 width = image->width;
0635 height = image->height;
0636 vxres = info->var.xres_virtual;
0637 vyres = info->var.yres_virtual;
0638 line_length = info->fix.line_length;
0639 rincr = (width + 7) / 8;
0640
0641
0642 if (unlikely(width == 0))
0643 return;
0644
0645 if (dx > vxres || dy > vyres)
0646 return;
0647 if (dx + width > vxres)
0648 width = vxres - dx;
0649 if (dy + height > vyres)
0650 height = vyres - dy;
0651
0652 regs_base = par->tga_regs_base;
0653 fb_base = par->tga_fb_base;
0654
0655
0656
0657
0658 fgcolor = image->fg_color;
0659 bgcolor = image->bg_color;
0660 if (is8bpp) {
0661 fgcolor |= fgcolor << 8;
0662 fgcolor |= fgcolor << 16;
0663 bgcolor |= bgcolor << 8;
0664 bgcolor |= bgcolor << 16;
0665 } else {
0666 if (fgcolor < 16)
0667 fgcolor = ((u32 *)info->pseudo_palette)[fgcolor];
0668 if (bgcolor < 16)
0669 bgcolor = ((u32 *)info->pseudo_palette)[bgcolor];
0670 }
0671 __raw_writel(fgcolor, regs_base + TGA_FOREGROUND_REG);
0672 __raw_writel(bgcolor, regs_base + TGA_BACKGROUND_REG);
0673
0674
0675
0676 pos = dy * line_length;
0677 if (is8bpp) {
0678 pos += dx;
0679 shift = pos & 3;
0680 pos &= -4;
0681 } else {
0682 pos += dx * 4;
0683 shift = (pos & 7) >> 2;
0684 pos &= -8;
0685 }
0686
0687 data = (const unsigned char *) image->data;
0688
0689
0690 __raw_writel((is8bpp
0691 ? TGA_MODE_SBM_8BPP | TGA_MODE_OPAQUE_STIPPLE
0692 : TGA_MODE_SBM_24BPP | TGA_MODE_OPAQUE_STIPPLE),
0693 regs_base + TGA_MODE_REG);
0694
0695 if (width + shift <= 32) {
0696 unsigned long bwidth;
0697
0698
0699
0700
0701
0702 pixelmask = (2ul << (width - 1)) - 1;
0703 pixelmask <<= shift;
0704 __raw_writel(pixelmask, regs_base + TGA_PIXELMASK_REG);
0705 wmb();
0706
0707 bwidth = (width + 7) / 8;
0708
0709 for (i = 0; i < height; ++i) {
0710 u32 mask = 0;
0711
0712
0713
0714 for (j = 0; j < bwidth; ++j)
0715 mask |= bitrev8(data[j]) << (j * 8);
0716
0717 __raw_writel(mask << shift, fb_base + pos);
0718
0719 pos += line_length;
0720 data += rincr;
0721 }
0722 wmb();
0723 __raw_writel(0xffffffff, regs_base + TGA_PIXELMASK_REG);
0724 } else if (shift == 0) {
0725 unsigned long pos0 = pos;
0726 const unsigned char *data0 = data;
0727 unsigned long bincr = (is8bpp ? 8 : 8*4);
0728 unsigned long bwidth;
0729
0730
0731
0732
0733
0734
0735
0736 wmb();
0737
0738 bwidth = (width / 8) & -4;
0739 for (i = 0; i < height; ++i) {
0740 for (j = 0; j < bwidth; j += 4) {
0741 u32 mask = 0;
0742 mask |= bitrev8(data[j+0]) << (0 * 8);
0743 mask |= bitrev8(data[j+1]) << (1 * 8);
0744 mask |= bitrev8(data[j+2]) << (2 * 8);
0745 mask |= bitrev8(data[j+3]) << (3 * 8);
0746 __raw_writel(mask, fb_base + pos + j*bincr);
0747 }
0748 pos += line_length;
0749 data += rincr;
0750 }
0751 wmb();
0752
0753 pixelmask = (1ul << (width & 31)) - 1;
0754 if (pixelmask) {
0755 __raw_writel(pixelmask, regs_base + TGA_PIXELMASK_REG);
0756 wmb();
0757
0758 pos = pos0 + bwidth*bincr;
0759 data = data0 + bwidth;
0760 bwidth = ((width & 31) + 7) / 8;
0761
0762 for (i = 0; i < height; ++i) {
0763 u32 mask = 0;
0764 for (j = 0; j < bwidth; ++j)
0765 mask |= bitrev8(data[j]) << (j * 8);
0766 __raw_writel(mask, fb_base + pos);
0767 pos += line_length;
0768 data += rincr;
0769 }
0770 wmb();
0771 __raw_writel(0xffffffff, regs_base + TGA_PIXELMASK_REG);
0772 }
0773 } else {
0774 unsigned long pos0 = pos;
0775 const unsigned char *data0 = data;
0776 unsigned long bincr = (is8bpp ? 8 : 8*4);
0777 unsigned long bwidth;
0778
0779
0780
0781
0782
0783
0784 pixelmask = 0xffff << shift;
0785 __raw_writel(pixelmask, regs_base + TGA_PIXELMASK_REG);
0786 wmb();
0787
0788 bwidth = (width / 8) & -2;
0789 for (i = 0; i < height; ++i) {
0790 for (j = 0; j < bwidth; j += 2) {
0791 u32 mask = 0;
0792 mask |= bitrev8(data[j+0]) << (0 * 8);
0793 mask |= bitrev8(data[j+1]) << (1 * 8);
0794 mask <<= shift;
0795 __raw_writel(mask, fb_base + pos + j*bincr);
0796 }
0797 pos += line_length;
0798 data += rincr;
0799 }
0800 wmb();
0801
0802 pixelmask = ((1ul << (width & 15)) - 1) << shift;
0803 if (pixelmask) {
0804 __raw_writel(pixelmask, regs_base + TGA_PIXELMASK_REG);
0805 wmb();
0806
0807 pos = pos0 + bwidth*bincr;
0808 data = data0 + bwidth;
0809 bwidth = (width & 15) > 8;
0810
0811 for (i = 0; i < height; ++i) {
0812 u32 mask = bitrev8(data[0]);
0813 if (bwidth)
0814 mask |= bitrev8(data[1]) << 8;
0815 mask <<= shift;
0816 __raw_writel(mask, fb_base + pos);
0817 pos += line_length;
0818 data += rincr;
0819 }
0820 wmb();
0821 }
0822 __raw_writel(0xffffffff, regs_base + TGA_PIXELMASK_REG);
0823 }
0824
0825
0826 __raw_writel((is8bpp
0827 ? TGA_MODE_SBM_8BPP | TGA_MODE_SIMPLE
0828 : TGA_MODE_SBM_24BPP | TGA_MODE_SIMPLE),
0829 regs_base + TGA_MODE_REG);
0830 }
0831
0832 static void
0833 tgafb_clut_imageblit(struct fb_info *info, const struct fb_image *image)
0834 {
0835 struct tga_par *par = (struct tga_par *) info->par;
0836 u32 color, dx, dy, width, height, vxres, vyres;
0837 u32 *palette = ((u32 *)info->pseudo_palette);
0838 unsigned long pos, line_length, i, j;
0839 const unsigned char *data;
0840 void __iomem *fb_base;
0841
0842 dx = image->dx;
0843 dy = image->dy;
0844 width = image->width;
0845 height = image->height;
0846 vxres = info->var.xres_virtual;
0847 vyres = info->var.yres_virtual;
0848 line_length = info->fix.line_length;
0849
0850
0851 if (dx > vxres || dy > vyres)
0852 return;
0853 if (dx + width > vxres)
0854 width = vxres - dx;
0855 if (dy + height > vyres)
0856 height = vyres - dy;
0857
0858 fb_base = par->tga_fb_base;
0859
0860 pos = dy * line_length + (dx * 4);
0861 data = image->data;
0862
0863
0864 for (i = 0; i < height; i++) {
0865 for (j = 0; j < width; j++) {
0866 color = palette[*data++];
0867 __raw_writel(color, fb_base + pos + j*4);
0868 }
0869 pos += line_length;
0870 }
0871 }
0872
0873
0874
0875
0876
0877
0878
0879
0880
0881 static void
0882 tgafb_imageblit(struct fb_info *info, const struct fb_image *image)
0883 {
0884 unsigned int is8bpp = info->var.bits_per_pixel == 8;
0885
0886
0887 if (image->depth == 1) {
0888 tgafb_mono_imageblit(info, image);
0889 return;
0890 }
0891
0892
0893
0894
0895
0896 if (image->depth == info->var.bits_per_pixel) {
0897 cfb_imageblit(info, image);
0898 return;
0899 }
0900
0901
0902 if (!is8bpp && image->depth == 8) {
0903 tgafb_clut_imageblit(info, image);
0904 return;
0905 }
0906
0907
0908 }
0909
0910
0911
0912
0913
0914
0915
0916
0917
0918 static void
0919 tgafb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
0920 {
0921 struct tga_par *par = (struct tga_par *) info->par;
0922 int is8bpp = info->var.bits_per_pixel == 8;
0923 u32 dx, dy, width, height, vxres, vyres, color;
0924 unsigned long pos, align, line_length, i, j;
0925 void __iomem *regs_base;
0926 void __iomem *fb_base;
0927
0928 dx = rect->dx;
0929 dy = rect->dy;
0930 width = rect->width;
0931 height = rect->height;
0932 vxres = info->var.xres_virtual;
0933 vyres = info->var.yres_virtual;
0934 line_length = info->fix.line_length;
0935 regs_base = par->tga_regs_base;
0936 fb_base = par->tga_fb_base;
0937
0938
0939 if (dx > vxres || dy > vyres || !width || !height)
0940 return;
0941 if (dx + width > vxres)
0942 width = vxres - dx;
0943 if (dy + height > vyres)
0944 height = vyres - dy;
0945
0946 pos = dy * line_length + dx * (is8bpp ? 1 : 4);
0947
0948
0949
0950
0951
0952 if (rect->rop != ROP_COPY) {
0953 cfb_fillrect(info, rect);
0954 return;
0955 }
0956
0957
0958 color = rect->color;
0959 if (is8bpp) {
0960 color |= color << 8;
0961 color |= color << 16;
0962 __raw_writel(color, regs_base + TGA_BLOCK_COLOR0_REG);
0963 __raw_writel(color, regs_base + TGA_BLOCK_COLOR1_REG);
0964 } else {
0965 if (color < 16)
0966 color = ((u32 *)info->pseudo_palette)[color];
0967 __raw_writel(color, regs_base + TGA_BLOCK_COLOR0_REG);
0968 __raw_writel(color, regs_base + TGA_BLOCK_COLOR1_REG);
0969 __raw_writel(color, regs_base + TGA_BLOCK_COLOR2_REG);
0970 __raw_writel(color, regs_base + TGA_BLOCK_COLOR3_REG);
0971 __raw_writel(color, regs_base + TGA_BLOCK_COLOR4_REG);
0972 __raw_writel(color, regs_base + TGA_BLOCK_COLOR5_REG);
0973 __raw_writel(color, regs_base + TGA_BLOCK_COLOR6_REG);
0974 __raw_writel(color, regs_base + TGA_BLOCK_COLOR7_REG);
0975 }
0976
0977
0978
0979 __raw_writel(0xffffffff, regs_base + TGA_DATA_REG);
0980
0981
0982 __raw_writel((is8bpp
0983 ? TGA_MODE_SBM_8BPP | TGA_MODE_BLOCK_FILL
0984 : TGA_MODE_SBM_24BPP | TGA_MODE_BLOCK_FILL),
0985 regs_base + TGA_MODE_REG);
0986 wmb();
0987
0988
0989
0990
0991 if (width == line_length) {
0992 width *= height;
0993 height = 1;
0994 }
0995
0996
0997
0998
0999 align = (pos & 3) << 16;
1000 pos &= -4;
1001
1002 if (width <= 2048) {
1003 u32 data;
1004
1005 data = (width - 1) | align;
1006
1007 for (i = 0; i < height; ++i) {
1008 __raw_writel(data, fb_base + pos);
1009 pos += line_length;
1010 }
1011 } else {
1012 unsigned long Bpp = (is8bpp ? 1 : 4);
1013 unsigned long nwidth = width & -2048;
1014 u32 fdata, ldata;
1015
1016 fdata = (2048 - 1) | align;
1017 ldata = ((width & 2047) - 1) | align;
1018
1019 for (i = 0; i < height; ++i) {
1020 for (j = 0; j < nwidth; j += 2048)
1021 __raw_writel(fdata, fb_base + pos + j*Bpp);
1022 if (j < width)
1023 __raw_writel(ldata, fb_base + pos + j*Bpp);
1024 pos += line_length;
1025 }
1026 }
1027 wmb();
1028
1029
1030 __raw_writel((is8bpp
1031 ? TGA_MODE_SBM_8BPP | TGA_MODE_SIMPLE
1032 : TGA_MODE_SBM_24BPP | TGA_MODE_SIMPLE),
1033 regs_base + TGA_MODE_REG);
1034 }
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050 static inline void
1051 copyarea_line_8bpp(struct fb_info *info, u32 dy, u32 sy,
1052 u32 height, u32 width)
1053 {
1054 struct tga_par *par = (struct tga_par *) info->par;
1055 void __iomem *tga_regs = par->tga_regs_base;
1056 unsigned long dpos, spos, i, n64;
1057
1058
1059 __raw_writel(TGA_MODE_SBM_8BPP | TGA_MODE_COPY, tga_regs+TGA_MODE_REG);
1060 __raw_writel(0, tga_regs+TGA_PIXELSHIFT_REG);
1061 wmb();
1062
1063 n64 = (height * width) / 64;
1064
1065 if (sy < dy) {
1066 spos = (sy + height) * width;
1067 dpos = (dy + height) * width;
1068
1069 for (i = 0; i < n64; ++i) {
1070 spos -= 64;
1071 dpos -= 64;
1072 __raw_writel(spos, tga_regs+TGA_COPY64_SRC);
1073 wmb();
1074 __raw_writel(dpos, tga_regs+TGA_COPY64_DST);
1075 wmb();
1076 }
1077 } else {
1078 spos = sy * width;
1079 dpos = dy * width;
1080
1081 for (i = 0; i < n64; ++i) {
1082 __raw_writel(spos, tga_regs+TGA_COPY64_SRC);
1083 wmb();
1084 __raw_writel(dpos, tga_regs+TGA_COPY64_DST);
1085 wmb();
1086 spos += 64;
1087 dpos += 64;
1088 }
1089 }
1090
1091
1092 __raw_writel(TGA_MODE_SBM_8BPP|TGA_MODE_SIMPLE, tga_regs+TGA_MODE_REG);
1093 }
1094
1095 static inline void
1096 copyarea_line_32bpp(struct fb_info *info, u32 dy, u32 sy,
1097 u32 height, u32 width)
1098 {
1099 struct tga_par *par = (struct tga_par *) info->par;
1100 void __iomem *tga_regs = par->tga_regs_base;
1101 void __iomem *tga_fb = par->tga_fb_base;
1102 void __iomem *src;
1103 void __iomem *dst;
1104 unsigned long i, n16;
1105
1106
1107 __raw_writel(TGA_MODE_SBM_24BPP | TGA_MODE_COPY, tga_regs+TGA_MODE_REG);
1108 __raw_writel(0, tga_regs+TGA_PIXELSHIFT_REG);
1109 wmb();
1110
1111 n16 = (height * width) / 16;
1112
1113 if (sy < dy) {
1114 src = tga_fb + (sy + height) * width * 4;
1115 dst = tga_fb + (dy + height) * width * 4;
1116
1117 for (i = 0; i < n16; ++i) {
1118 src -= 64;
1119 dst -= 64;
1120 __raw_writel(0xffff, src);
1121 wmb();
1122 __raw_writel(0xffff, dst);
1123 wmb();
1124 }
1125 } else {
1126 src = tga_fb + sy * width * 4;
1127 dst = tga_fb + dy * width * 4;
1128
1129 for (i = 0; i < n16; ++i) {
1130 __raw_writel(0xffff, src);
1131 wmb();
1132 __raw_writel(0xffff, dst);
1133 wmb();
1134 src += 64;
1135 dst += 64;
1136 }
1137 }
1138
1139
1140 __raw_writel(TGA_MODE_SBM_24BPP|TGA_MODE_SIMPLE, tga_regs+TGA_MODE_REG);
1141 }
1142
1143
1144 static inline void
1145 copyarea_8bpp(struct fb_info *info, u32 dx, u32 dy, u32 sx, u32 sy,
1146 u32 height, u32 width, u32 line_length,
1147 const struct fb_copyarea *area)
1148 {
1149 struct tga_par *par = (struct tga_par *) info->par;
1150 unsigned i, yincr;
1151 int depos, sepos, backward, last_step, step;
1152 u32 mask_last;
1153 unsigned n32;
1154 void __iomem *tga_regs;
1155 void __iomem *tga_fb;
1156
1157
1158 if ((dx | sx | width) & 7) {
1159 cfb_copyarea(info, area);
1160 return;
1161 }
1162
1163 yincr = line_length;
1164 if (dy > sy) {
1165 dy += height - 1;
1166 sy += height - 1;
1167 yincr = -yincr;
1168 }
1169 backward = dy == sy && dx > sx && dx < sx + width;
1170
1171
1172
1173 depos = dy * line_length + dx;
1174 sepos = sy * line_length + sx;
1175 if (backward) {
1176 depos += width;
1177 sepos += width;
1178 }
1179
1180
1181 n32 = width / 32;
1182 last_step = width % 32;
1183
1184
1185 mask_last = (1ul << last_step) - 1;
1186
1187 if (!backward) {
1188 step = 32;
1189 last_step = 32;
1190 } else {
1191 step = -32;
1192 last_step = -last_step;
1193 sepos -= 32;
1194 depos -= 32;
1195 }
1196
1197 tga_regs = par->tga_regs_base;
1198 tga_fb = par->tga_fb_base;
1199
1200
1201 __raw_writel(TGA_MODE_SBM_8BPP|TGA_MODE_COPY, tga_regs+TGA_MODE_REG);
1202 __raw_writel(0, tga_regs+TGA_PIXELSHIFT_REG);
1203 wmb();
1204
1205 for (i = 0; i < height; ++i) {
1206 unsigned long j;
1207 void __iomem *sfb;
1208 void __iomem *dfb;
1209
1210 sfb = tga_fb + sepos;
1211 dfb = tga_fb + depos;
1212
1213 for (j = 0; j < n32; j++) {
1214 if (j < 2 && j + 1 < n32 && !backward &&
1215 !(((unsigned long)sfb | (unsigned long)dfb) & 63)) {
1216 do {
1217 __raw_writel(sfb - tga_fb, tga_regs+TGA_COPY64_SRC);
1218 wmb();
1219 __raw_writel(dfb - tga_fb, tga_regs+TGA_COPY64_DST);
1220 wmb();
1221 sfb += 64;
1222 dfb += 64;
1223 j += 2;
1224 } while (j + 1 < n32);
1225 j--;
1226 continue;
1227 }
1228 __raw_writel(0xffffffff, sfb);
1229 wmb();
1230 __raw_writel(0xffffffff, dfb);
1231 wmb();
1232 sfb += step;
1233 dfb += step;
1234 }
1235
1236 if (mask_last) {
1237 sfb += last_step - step;
1238 dfb += last_step - step;
1239 __raw_writel(mask_last, sfb);
1240 wmb();
1241 __raw_writel(mask_last, dfb);
1242 wmb();
1243 }
1244
1245 sepos += yincr;
1246 depos += yincr;
1247 }
1248
1249
1250 __raw_writel(TGA_MODE_SBM_8BPP|TGA_MODE_SIMPLE, tga_regs+TGA_MODE_REG);
1251 }
1252
1253 static void
1254 tgafb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
1255 {
1256 unsigned long dx, dy, width, height, sx, sy, vxres, vyres;
1257 unsigned long line_length, bpp;
1258
1259 dx = area->dx;
1260 dy = area->dy;
1261 width = area->width;
1262 height = area->height;
1263 sx = area->sx;
1264 sy = area->sy;
1265 vxres = info->var.xres_virtual;
1266 vyres = info->var.yres_virtual;
1267 line_length = info->fix.line_length;
1268
1269
1270 if (dx > vxres || sx > vxres || dy > vyres || sy > vyres)
1271 return;
1272
1273
1274 if (dx + width > vxres)
1275 width = vxres - dx;
1276 if (dy + height > vyres)
1277 height = vyres - dy;
1278
1279
1280 if (sx + width > vxres || sy + height > vyres)
1281 return;
1282
1283 bpp = info->var.bits_per_pixel;
1284
1285
1286 if (!(line_length & 63) && width * (bpp >> 3) == line_length) {
1287 if (bpp == 8)
1288 copyarea_line_8bpp(info, dy, sy, height, width);
1289 else
1290 copyarea_line_32bpp(info, dy, sy, height, width);
1291 }
1292
1293
1294
1295
1296 else if (bpp == 32)
1297 cfb_copyarea(info, area);
1298
1299 else
1300 copyarea_8bpp(info, dx, dy, sx, sy, height,
1301 width, line_length, area);
1302 }
1303
1304
1305
1306
1307
1308
1309 static void
1310 tgafb_init_fix(struct fb_info *info)
1311 {
1312 struct tga_par *par = (struct tga_par *)info->par;
1313 int tga_bus_pci = dev_is_pci(par->dev);
1314 int tga_bus_tc = TGA_BUS_TC(par->dev);
1315 u8 tga_type = par->tga_type;
1316 const char *tga_type_name = NULL;
1317 unsigned memory_size;
1318
1319 switch (tga_type) {
1320 case TGA_TYPE_8PLANE:
1321 if (tga_bus_pci)
1322 tga_type_name = "Digital ZLXp-E1";
1323 if (tga_bus_tc)
1324 tga_type_name = "Digital ZLX-E1";
1325 memory_size = 2097152;
1326 break;
1327 case TGA_TYPE_24PLANE:
1328 if (tga_bus_pci)
1329 tga_type_name = "Digital ZLXp-E2";
1330 if (tga_bus_tc)
1331 tga_type_name = "Digital ZLX-E2";
1332 memory_size = 8388608;
1333 break;
1334 case TGA_TYPE_24PLUSZ:
1335 if (tga_bus_pci)
1336 tga_type_name = "Digital ZLXp-E3";
1337 if (tga_bus_tc)
1338 tga_type_name = "Digital ZLX-E3";
1339 memory_size = 16777216;
1340 break;
1341 }
1342 if (!tga_type_name) {
1343 tga_type_name = "Unknown";
1344 memory_size = 16777216;
1345 }
1346
1347 strscpy(info->fix.id, tga_type_name, sizeof(info->fix.id));
1348
1349 info->fix.type = FB_TYPE_PACKED_PIXELS;
1350 info->fix.type_aux = 0;
1351 info->fix.visual = (tga_type == TGA_TYPE_8PLANE
1352 ? FB_VISUAL_PSEUDOCOLOR
1353 : FB_VISUAL_DIRECTCOLOR);
1354
1355 info->fix.smem_start = (size_t) par->tga_fb_base;
1356 info->fix.smem_len = memory_size;
1357 info->fix.mmio_start = (size_t) par->tga_regs_base;
1358 info->fix.mmio_len = 512;
1359
1360 info->fix.xpanstep = 0;
1361 info->fix.ypanstep = 0;
1362 info->fix.ywrapstep = 0;
1363
1364 info->fix.accel = FB_ACCEL_DEC_TGA;
1365
1366
1367
1368
1369
1370 if (tga_type != TGA_TYPE_8PLANE) {
1371 info->var.red.length = 8;
1372 info->var.green.length = 8;
1373 info->var.blue.length = 8;
1374 info->var.red.offset = 16;
1375 info->var.green.offset = 8;
1376 info->var.blue.offset = 0;
1377 }
1378 }
1379
1380 static int tgafb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
1381 {
1382
1383 tgafb_set_par(info);
1384 return 0;
1385 }
1386
1387 static int tgafb_register(struct device *dev)
1388 {
1389 static const struct fb_videomode modedb_tc = {
1390
1391 "1280x1024@72", 0, 1280, 1024, 7645, 224, 28, 33, 3, 160, 3,
1392 FB_SYNC_ON_GREEN, FB_VMODE_NONINTERLACED
1393 };
1394
1395 static unsigned int const fb_offset_presets[4] = {
1396 TGA_8PLANE_FB_OFFSET,
1397 TGA_24PLANE_FB_OFFSET,
1398 0xffffffff,
1399 TGA_24PLUSZ_FB_OFFSET
1400 };
1401
1402 const struct fb_videomode *modedb_tga = NULL;
1403 resource_size_t bar0_start = 0, bar0_len = 0;
1404 const char *mode_option_tga = NULL;
1405 int tga_bus_pci = dev_is_pci(dev);
1406 int tga_bus_tc = TGA_BUS_TC(dev);
1407 unsigned int modedbsize_tga = 0;
1408 void __iomem *mem_base;
1409 struct fb_info *info;
1410 struct tga_par *par;
1411 u8 tga_type;
1412 int ret = 0;
1413
1414
1415 if (tga_bus_pci && pci_enable_device(to_pci_dev(dev))) {
1416 printk(KERN_ERR "tgafb: Cannot enable PCI device\n");
1417 return -ENODEV;
1418 }
1419
1420
1421 info = framebuffer_alloc(sizeof(struct tga_par), dev);
1422 if (!info)
1423 return -ENOMEM;
1424
1425 par = info->par;
1426 dev_set_drvdata(dev, info);
1427
1428
1429 ret = -ENODEV;
1430 if (tga_bus_pci) {
1431 bar0_start = pci_resource_start(to_pci_dev(dev), 0);
1432 bar0_len = pci_resource_len(to_pci_dev(dev), 0);
1433 }
1434 if (tga_bus_tc) {
1435 bar0_start = to_tc_dev(dev)->resource.start;
1436 bar0_len = to_tc_dev(dev)->resource.end - bar0_start + 1;
1437 }
1438 if (!request_mem_region (bar0_start, bar0_len, "tgafb")) {
1439 printk(KERN_ERR "tgafb: cannot reserve FB region\n");
1440 goto err0;
1441 }
1442
1443
1444 mem_base = ioremap(bar0_start, bar0_len);
1445 if (!mem_base) {
1446 printk(KERN_ERR "tgafb: Cannot map MMIO\n");
1447 goto err1;
1448 }
1449
1450
1451 tga_type = (readl(mem_base) >> 12) & 0x0f;
1452 par->dev = dev;
1453 par->tga_mem_base = mem_base;
1454 par->tga_fb_base = mem_base + fb_offset_presets[tga_type];
1455 par->tga_regs_base = mem_base + TGA_REGS_OFFSET;
1456 par->tga_type = tga_type;
1457 if (tga_bus_pci)
1458 par->tga_chip_rev = (to_pci_dev(dev))->revision;
1459 if (tga_bus_tc)
1460 par->tga_chip_rev = TGA_READ_REG(par, TGA_START_REG) & 0xff;
1461
1462
1463 info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_COPYAREA |
1464 FBINFO_HWACCEL_IMAGEBLIT | FBINFO_HWACCEL_FILLRECT;
1465 info->fbops = &tgafb_ops;
1466 info->screen_base = par->tga_fb_base;
1467 info->pseudo_palette = par->palette;
1468
1469
1470 if (tga_bus_pci) {
1471 mode_option_tga = mode_option_pci;
1472 }
1473 if (tga_bus_tc) {
1474 mode_option_tga = mode_option_tc;
1475 modedb_tga = &modedb_tc;
1476 modedbsize_tga = 1;
1477 }
1478
1479 tgafb_init_fix(info);
1480
1481 ret = fb_find_mode(&info->var, info,
1482 mode_option ? mode_option : mode_option_tga,
1483 modedb_tga, modedbsize_tga, NULL,
1484 tga_type == TGA_TYPE_8PLANE ? 8 : 32);
1485 if (ret == 0 || ret == 4) {
1486 printk(KERN_ERR "tgafb: Could not find valid video mode\n");
1487 ret = -EINVAL;
1488 goto err1;
1489 }
1490
1491 if (fb_alloc_cmap(&info->cmap, 256, 0)) {
1492 printk(KERN_ERR "tgafb: Could not allocate color map\n");
1493 ret = -ENOMEM;
1494 goto err1;
1495 }
1496
1497 tgafb_set_par(info);
1498
1499 if (register_framebuffer(info) < 0) {
1500 printk(KERN_ERR "tgafb: Could not register framebuffer\n");
1501 ret = -EINVAL;
1502 goto err2;
1503 }
1504
1505 if (tga_bus_pci) {
1506 pr_info("tgafb: DC21030 [TGA] detected, rev=0x%02x\n",
1507 par->tga_chip_rev);
1508 pr_info("tgafb: at PCI bus %d, device %d, function %d\n",
1509 to_pci_dev(dev)->bus->number,
1510 PCI_SLOT(to_pci_dev(dev)->devfn),
1511 PCI_FUNC(to_pci_dev(dev)->devfn));
1512 }
1513 if (tga_bus_tc)
1514 pr_info("tgafb: SFB+ detected, rev=0x%02x\n",
1515 par->tga_chip_rev);
1516 fb_info(info, "%s frame buffer device at 0x%lx\n",
1517 info->fix.id, (long)bar0_start);
1518
1519 return 0;
1520
1521 err2:
1522 fb_dealloc_cmap(&info->cmap);
1523 err1:
1524 if (mem_base)
1525 iounmap(mem_base);
1526 release_mem_region(bar0_start, bar0_len);
1527 err0:
1528 framebuffer_release(info);
1529 return ret;
1530 }
1531
1532 static void tgafb_unregister(struct device *dev)
1533 {
1534 resource_size_t bar0_start = 0, bar0_len = 0;
1535 int tga_bus_pci = dev_is_pci(dev);
1536 int tga_bus_tc = TGA_BUS_TC(dev);
1537 struct fb_info *info = NULL;
1538 struct tga_par *par;
1539
1540 info = dev_get_drvdata(dev);
1541 if (!info)
1542 return;
1543
1544 par = info->par;
1545 unregister_framebuffer(info);
1546 fb_dealloc_cmap(&info->cmap);
1547 iounmap(par->tga_mem_base);
1548 if (tga_bus_pci) {
1549 bar0_start = pci_resource_start(to_pci_dev(dev), 0);
1550 bar0_len = pci_resource_len(to_pci_dev(dev), 0);
1551 }
1552 if (tga_bus_tc) {
1553 bar0_start = to_tc_dev(dev)->resource.start;
1554 bar0_len = to_tc_dev(dev)->resource.end - bar0_start + 1;
1555 }
1556 release_mem_region(bar0_start, bar0_len);
1557 framebuffer_release(info);
1558 }
1559
1560 static void tgafb_exit(void)
1561 {
1562 tc_unregister_driver(&tgafb_tc_driver);
1563 pci_unregister_driver(&tgafb_pci_driver);
1564 }
1565
1566 #ifndef MODULE
1567 static int tgafb_setup(char *arg)
1568 {
1569 char *this_opt;
1570
1571 if (arg && *arg) {
1572 while ((this_opt = strsep(&arg, ","))) {
1573 if (!*this_opt)
1574 continue;
1575 if (!strncmp(this_opt, "mode:", 5))
1576 mode_option = this_opt+5;
1577 else
1578 printk(KERN_ERR
1579 "tgafb: unknown parameter %s\n",
1580 this_opt);
1581 }
1582 }
1583
1584 return 0;
1585 }
1586 #endif
1587
1588 static int tgafb_init(void)
1589 {
1590 int status;
1591 #ifndef MODULE
1592 char *option = NULL;
1593
1594 if (fb_get_options("tgafb", &option))
1595 return -ENODEV;
1596 tgafb_setup(option);
1597 #endif
1598 status = pci_register_driver(&tgafb_pci_driver);
1599 if (!status)
1600 status = tc_register_driver(&tgafb_tc_driver);
1601 return status;
1602 }
1603
1604
1605
1606
1607
1608 module_init(tgafb_init);
1609 module_exit(tgafb_exit);
1610
1611 MODULE_DESCRIPTION("Framebuffer driver for TGA/SFB+ chipset");
1612 MODULE_LICENSE("GPL");