0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036 #include <linux/module.h>
0037 #include <linux/kernel.h>
0038 #include <linux/errno.h>
0039 #include <linux/string.h>
0040 #include <linux/mm.h>
0041 #include <linux/slab.h>
0042 #include <linux/delay.h>
0043 #include <linux/fb.h>
0044 #include <linux/pci.h>
0045 #include <linux/init.h>
0046 #include <linux/io.h>
0047 #include <linux/i2c.h>
0048 #include <linux/i2c-algo-bit.h>
0049
0050
0051 #ifdef __arm__
0052 #include <asm/mach-types.h>
0053 #endif
0054
0055 #include "cyber2000fb.h"
0056
0057 struct cfb_info {
0058 struct fb_info fb;
0059 struct display_switch *dispsw;
0060 unsigned char __iomem *region;
0061 unsigned char __iomem *regs;
0062 u_int id;
0063 u_int irq;
0064 int func_use_count;
0065 u_long ref_ps;
0066
0067
0068
0069
0070 u_int divisors[4];
0071
0072 struct {
0073 u8 red, green, blue;
0074 } palette[NR_PALETTE];
0075
0076 u_char mem_ctl1;
0077 u_char mem_ctl2;
0078 u_char mclk_mult;
0079 u_char mclk_div;
0080
0081
0082
0083 u_char ramdac_ctrl;
0084 u_char ramdac_powerdown;
0085
0086 u32 pseudo_palette[16];
0087
0088 spinlock_t reg_b0_lock;
0089
0090 #ifdef CONFIG_FB_CYBER2000_DDC
0091 bool ddc_registered;
0092 struct i2c_adapter ddc_adapter;
0093 struct i2c_algo_bit_data ddc_algo;
0094 #endif
0095
0096 #ifdef CONFIG_FB_CYBER2000_I2C
0097 struct i2c_adapter i2c_adapter;
0098 struct i2c_algo_bit_data i2c_algo;
0099 #endif
0100 };
0101
0102 static char *default_font = "Acorn8x8";
0103 module_param(default_font, charp, 0);
0104 MODULE_PARM_DESC(default_font, "Default font name");
0105
0106
0107
0108
0109 #define cyber2000fb_writel(val, reg, cfb) writel(val, (cfb)->regs + (reg))
0110 #define cyber2000fb_writew(val, reg, cfb) writew(val, (cfb)->regs + (reg))
0111 #define cyber2000fb_writeb(val, reg, cfb) writeb(val, (cfb)->regs + (reg))
0112
0113 #define cyber2000fb_readb(reg, cfb) readb((cfb)->regs + (reg))
0114
0115 static inline void
0116 cyber2000_crtcw(unsigned int reg, unsigned int val, struct cfb_info *cfb)
0117 {
0118 cyber2000fb_writew((reg & 255) | val << 8, 0x3d4, cfb);
0119 }
0120
0121 static inline void
0122 cyber2000_grphw(unsigned int reg, unsigned int val, struct cfb_info *cfb)
0123 {
0124 cyber2000fb_writew((reg & 255) | val << 8, 0x3ce, cfb);
0125 }
0126
0127 static inline unsigned int
0128 cyber2000_grphr(unsigned int reg, struct cfb_info *cfb)
0129 {
0130 cyber2000fb_writeb(reg, 0x3ce, cfb);
0131 return cyber2000fb_readb(0x3cf, cfb);
0132 }
0133
0134 static inline void
0135 cyber2000_attrw(unsigned int reg, unsigned int val, struct cfb_info *cfb)
0136 {
0137 cyber2000fb_readb(0x3da, cfb);
0138 cyber2000fb_writeb(reg, 0x3c0, cfb);
0139 cyber2000fb_readb(0x3c1, cfb);
0140 cyber2000fb_writeb(val, 0x3c0, cfb);
0141 }
0142
0143 static inline void
0144 cyber2000_seqw(unsigned int reg, unsigned int val, struct cfb_info *cfb)
0145 {
0146 cyber2000fb_writew((reg & 255) | val << 8, 0x3c4, cfb);
0147 }
0148
0149
0150
0151
0152
0153
0154 static void
0155 cyber2000fb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
0156 {
0157 struct cfb_info *cfb = container_of(info, struct cfb_info, fb);
0158 unsigned long dst, col;
0159
0160 if (!(cfb->fb.var.accel_flags & FB_ACCELF_TEXT)) {
0161 cfb_fillrect(info, rect);
0162 return;
0163 }
0164
0165 cyber2000fb_writeb(0, CO_REG_CONTROL, cfb);
0166 cyber2000fb_writew(rect->width - 1, CO_REG_PIXWIDTH, cfb);
0167 cyber2000fb_writew(rect->height - 1, CO_REG_PIXHEIGHT, cfb);
0168
0169 col = rect->color;
0170 if (cfb->fb.var.bits_per_pixel > 8)
0171 col = ((u32 *)cfb->fb.pseudo_palette)[col];
0172 cyber2000fb_writel(col, CO_REG_FGCOLOUR, cfb);
0173
0174 dst = rect->dx + rect->dy * cfb->fb.var.xres_virtual;
0175 if (cfb->fb.var.bits_per_pixel == 24) {
0176 cyber2000fb_writeb(dst, CO_REG_X_PHASE, cfb);
0177 dst *= 3;
0178 }
0179
0180 cyber2000fb_writel(dst, CO_REG_DEST_PTR, cfb);
0181 cyber2000fb_writeb(CO_FG_MIX_SRC, CO_REG_FGMIX, cfb);
0182 cyber2000fb_writew(CO_CMD_L_PATTERN_FGCOL, CO_REG_CMD_L, cfb);
0183 cyber2000fb_writew(CO_CMD_H_BLITTER, CO_REG_CMD_H, cfb);
0184 }
0185
0186 static void
0187 cyber2000fb_copyarea(struct fb_info *info, const struct fb_copyarea *region)
0188 {
0189 struct cfb_info *cfb = container_of(info, struct cfb_info, fb);
0190 unsigned int cmd = CO_CMD_L_PATTERN_FGCOL;
0191 unsigned long src, dst;
0192
0193 if (!(cfb->fb.var.accel_flags & FB_ACCELF_TEXT)) {
0194 cfb_copyarea(info, region);
0195 return;
0196 }
0197
0198 cyber2000fb_writeb(0, CO_REG_CONTROL, cfb);
0199 cyber2000fb_writew(region->width - 1, CO_REG_PIXWIDTH, cfb);
0200 cyber2000fb_writew(region->height - 1, CO_REG_PIXHEIGHT, cfb);
0201
0202 src = region->sx + region->sy * cfb->fb.var.xres_virtual;
0203 dst = region->dx + region->dy * cfb->fb.var.xres_virtual;
0204
0205 if (region->sx < region->dx) {
0206 src += region->width - 1;
0207 dst += region->width - 1;
0208 cmd |= CO_CMD_L_INC_LEFT;
0209 }
0210
0211 if (region->sy < region->dy) {
0212 src += (region->height - 1) * cfb->fb.var.xres_virtual;
0213 dst += (region->height - 1) * cfb->fb.var.xres_virtual;
0214 cmd |= CO_CMD_L_INC_UP;
0215 }
0216
0217 if (cfb->fb.var.bits_per_pixel == 24) {
0218 cyber2000fb_writeb(dst, CO_REG_X_PHASE, cfb);
0219 src *= 3;
0220 dst *= 3;
0221 }
0222 cyber2000fb_writel(src, CO_REG_SRC1_PTR, cfb);
0223 cyber2000fb_writel(dst, CO_REG_DEST_PTR, cfb);
0224 cyber2000fb_writew(CO_FG_MIX_SRC, CO_REG_FGMIX, cfb);
0225 cyber2000fb_writew(cmd, CO_REG_CMD_L, cfb);
0226 cyber2000fb_writew(CO_CMD_H_FGSRCMAP | CO_CMD_H_BLITTER,
0227 CO_REG_CMD_H, cfb);
0228 }
0229
0230 static void
0231 cyber2000fb_imageblit(struct fb_info *info, const struct fb_image *image)
0232 {
0233 cfb_imageblit(info, image);
0234 return;
0235 }
0236
0237 static int cyber2000fb_sync(struct fb_info *info)
0238 {
0239 struct cfb_info *cfb = container_of(info, struct cfb_info, fb);
0240 int count = 100000;
0241
0242 if (!(cfb->fb.var.accel_flags & FB_ACCELF_TEXT))
0243 return 0;
0244
0245 while (cyber2000fb_readb(CO_REG_CONTROL, cfb) & CO_CTRL_BUSY) {
0246 if (!count--) {
0247 debug_printf("accel_wait timed out\n");
0248 cyber2000fb_writeb(0, CO_REG_CONTROL, cfb);
0249 break;
0250 }
0251 udelay(1);
0252 }
0253 return 0;
0254 }
0255
0256
0257
0258
0259
0260 static inline u32 convert_bitfield(u_int val, struct fb_bitfield *bf)
0261 {
0262 u_int mask = (1 << bf->length) - 1;
0263
0264 return (val >> (16 - bf->length) & mask) << bf->offset;
0265 }
0266
0267
0268
0269
0270 static int
0271 cyber2000fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
0272 u_int transp, struct fb_info *info)
0273 {
0274 struct cfb_info *cfb = container_of(info, struct cfb_info, fb);
0275 struct fb_var_screeninfo *var = &cfb->fb.var;
0276 u32 pseudo_val;
0277 int ret = 1;
0278
0279 switch (cfb->fb.fix.visual) {
0280 default:
0281 return 1;
0282
0283
0284
0285
0286
0287
0288
0289
0290
0291
0292 case FB_VISUAL_PSEUDOCOLOR:
0293 if (regno >= NR_PALETTE)
0294 return 1;
0295
0296 red >>= 8;
0297 green >>= 8;
0298 blue >>= 8;
0299
0300 cfb->palette[regno].red = red;
0301 cfb->palette[regno].green = green;
0302 cfb->palette[regno].blue = blue;
0303
0304 cyber2000fb_writeb(regno, 0x3c8, cfb);
0305 cyber2000fb_writeb(red, 0x3c9, cfb);
0306 cyber2000fb_writeb(green, 0x3c9, cfb);
0307 cyber2000fb_writeb(blue, 0x3c9, cfb);
0308 return 0;
0309
0310
0311
0312
0313
0314
0315
0316
0317
0318
0319
0320 case FB_VISUAL_DIRECTCOLOR:
0321 red >>= 8;
0322 green >>= 8;
0323 blue >>= 8;
0324
0325 if (var->green.length == 6 && regno < 64) {
0326 cfb->palette[regno << 2].green = green;
0327
0328
0329
0330
0331
0332 cyber2000fb_writeb(regno << 2, 0x3c8, cfb);
0333 cyber2000fb_writeb(cfb->palette[regno >> 1].red,
0334 0x3c9, cfb);
0335 cyber2000fb_writeb(green, 0x3c9, cfb);
0336 cyber2000fb_writeb(cfb->palette[regno >> 1].blue,
0337 0x3c9, cfb);
0338
0339 green = cfb->palette[regno << 3].green;
0340
0341 ret = 0;
0342 }
0343
0344 if (var->green.length >= 5 && regno < 32) {
0345 cfb->palette[regno << 3].red = red;
0346 cfb->palette[regno << 3].green = green;
0347 cfb->palette[regno << 3].blue = blue;
0348
0349
0350
0351
0352
0353 cyber2000fb_writeb(regno << 3, 0x3c8, cfb);
0354 cyber2000fb_writeb(red, 0x3c9, cfb);
0355 cyber2000fb_writeb(green, 0x3c9, cfb);
0356 cyber2000fb_writeb(blue, 0x3c9, cfb);
0357 ret = 0;
0358 }
0359
0360 if (var->green.length == 4 && regno < 16) {
0361 cfb->palette[regno << 4].red = red;
0362 cfb->palette[regno << 4].green = green;
0363 cfb->palette[regno << 4].blue = blue;
0364
0365
0366
0367
0368
0369 cyber2000fb_writeb(regno << 4, 0x3c8, cfb);
0370 cyber2000fb_writeb(red, 0x3c9, cfb);
0371 cyber2000fb_writeb(green, 0x3c9, cfb);
0372 cyber2000fb_writeb(blue, 0x3c9, cfb);
0373 ret = 0;
0374 }
0375
0376
0377
0378
0379
0380 pseudo_val = regno << var->red.offset |
0381 regno << var->green.offset |
0382 regno << var->blue.offset;
0383 break;
0384
0385
0386
0387
0388
0389
0390
0391
0392
0393
0394
0395 case FB_VISUAL_TRUECOLOR:
0396 pseudo_val = convert_bitfield(transp ^ 0xffff, &var->transp);
0397 pseudo_val |= convert_bitfield(red, &var->red);
0398 pseudo_val |= convert_bitfield(green, &var->green);
0399 pseudo_val |= convert_bitfield(blue, &var->blue);
0400 ret = 0;
0401 break;
0402 }
0403
0404
0405
0406
0407 if (regno < 16)
0408 ((u32 *)cfb->fb.pseudo_palette)[regno] = pseudo_val;
0409
0410 return ret;
0411 }
0412
0413 struct par_info {
0414
0415
0416
0417 u_char clock_mult;
0418 u_char clock_div;
0419 u_char extseqmisc;
0420 u_char co_pixfmt;
0421 u_char crtc_ofl;
0422 u_char crtc[19];
0423 u_int width;
0424 u_int pitch;
0425 u_int fetch;
0426
0427
0428
0429
0430 u_char ramdac;
0431 };
0432
0433 static const u_char crtc_idx[] = {
0434 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0435 0x08, 0x09,
0436 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18
0437 };
0438
0439 static void cyber2000fb_write_ramdac_ctrl(struct cfb_info *cfb)
0440 {
0441 unsigned int i;
0442 unsigned int val = cfb->ramdac_ctrl | cfb->ramdac_powerdown;
0443
0444 cyber2000fb_writeb(0x56, 0x3ce, cfb);
0445 i = cyber2000fb_readb(0x3cf, cfb);
0446 cyber2000fb_writeb(i | 4, 0x3cf, cfb);
0447 cyber2000fb_writeb(val, 0x3c6, cfb);
0448 cyber2000fb_writeb(i, 0x3cf, cfb);
0449
0450 cyber2000fb_readb(0x3cf, cfb);
0451 }
0452
0453 static void cyber2000fb_set_timing(struct cfb_info *cfb, struct par_info *hw)
0454 {
0455 u_int i;
0456
0457
0458
0459
0460 for (i = 0; i < NR_PALETTE; i++) {
0461 cyber2000fb_writeb(i, 0x3c8, cfb);
0462 cyber2000fb_writeb(0, 0x3c9, cfb);
0463 cyber2000fb_writeb(0, 0x3c9, cfb);
0464 cyber2000fb_writeb(0, 0x3c9, cfb);
0465 }
0466
0467 cyber2000fb_writeb(0xef, 0x3c2, cfb);
0468 cyber2000_crtcw(0x11, 0x0b, cfb);
0469 cyber2000_attrw(0x11, 0x00, cfb);
0470
0471 cyber2000_seqw(0x00, 0x01, cfb);
0472 cyber2000_seqw(0x01, 0x01, cfb);
0473 cyber2000_seqw(0x02, 0x0f, cfb);
0474 cyber2000_seqw(0x03, 0x00, cfb);
0475 cyber2000_seqw(0x04, 0x0e, cfb);
0476 cyber2000_seqw(0x00, 0x03, cfb);
0477
0478 for (i = 0; i < sizeof(crtc_idx); i++)
0479 cyber2000_crtcw(crtc_idx[i], hw->crtc[i], cfb);
0480
0481 for (i = 0x0a; i < 0x10; i++)
0482 cyber2000_crtcw(i, 0, cfb);
0483
0484 cyber2000_grphw(EXT_CRT_VRTOFL, hw->crtc_ofl, cfb);
0485 cyber2000_grphw(0x00, 0x00, cfb);
0486 cyber2000_grphw(0x01, 0x00, cfb);
0487 cyber2000_grphw(0x02, 0x00, cfb);
0488 cyber2000_grphw(0x03, 0x00, cfb);
0489 cyber2000_grphw(0x04, 0x00, cfb);
0490 cyber2000_grphw(0x05, 0x60, cfb);
0491 cyber2000_grphw(0x06, 0x05, cfb);
0492 cyber2000_grphw(0x07, 0x0f, cfb);
0493 cyber2000_grphw(0x08, 0xff, cfb);
0494
0495
0496 for (i = 0; i < 16; i++)
0497 cyber2000_attrw(i, i, cfb);
0498
0499 cyber2000_attrw(0x10, 0x01, cfb);
0500 cyber2000_attrw(0x11, 0x00, cfb);
0501 cyber2000_attrw(0x12, 0x0f, cfb);
0502 cyber2000_attrw(0x13, 0x00, cfb);
0503 cyber2000_attrw(0x14, 0x00, cfb);
0504
0505
0506 spin_lock(&cfb->reg_b0_lock);
0507 cyber2000_grphw(EXT_DCLK_MULT, hw->clock_mult, cfb);
0508 cyber2000_grphw(EXT_DCLK_DIV, hw->clock_div, cfb);
0509 cyber2000_grphw(EXT_MCLK_MULT, cfb->mclk_mult, cfb);
0510 cyber2000_grphw(EXT_MCLK_DIV, cfb->mclk_div, cfb);
0511 cyber2000_grphw(0x90, 0x01, cfb);
0512 cyber2000_grphw(0xb9, 0x80, cfb);
0513 cyber2000_grphw(0xb9, 0x00, cfb);
0514 spin_unlock(&cfb->reg_b0_lock);
0515
0516 cfb->ramdac_ctrl = hw->ramdac;
0517 cyber2000fb_write_ramdac_ctrl(cfb);
0518
0519 cyber2000fb_writeb(0x20, 0x3c0, cfb);
0520 cyber2000fb_writeb(0xff, 0x3c6, cfb);
0521
0522 cyber2000_grphw(0x14, hw->fetch, cfb);
0523 cyber2000_grphw(0x15, ((hw->fetch >> 8) & 0x03) |
0524 ((hw->pitch >> 4) & 0x30), cfb);
0525 cyber2000_grphw(EXT_SEQ_MISC, hw->extseqmisc, cfb);
0526
0527
0528
0529
0530 cyber2000fb_writew(hw->width, CO_REG_SRC_WIDTH, cfb);
0531 cyber2000fb_writew(hw->width, CO_REG_DEST_WIDTH, cfb);
0532 cyber2000fb_writeb(hw->co_pixfmt, CO_REG_PIXFMT, cfb);
0533 }
0534
0535 static inline int
0536 cyber2000fb_update_start(struct cfb_info *cfb, struct fb_var_screeninfo *var)
0537 {
0538 u_int base = var->yoffset * var->xres_virtual + var->xoffset;
0539
0540 base *= var->bits_per_pixel;
0541
0542
0543
0544
0545
0546 base >>= 5;
0547
0548 if (base >= 1 << 20)
0549 return -EINVAL;
0550
0551 cyber2000_grphw(0x10, base >> 16 | 0x10, cfb);
0552 cyber2000_crtcw(0x0c, base >> 8, cfb);
0553 cyber2000_crtcw(0x0d, base, cfb);
0554
0555 return 0;
0556 }
0557
0558 static int
0559 cyber2000fb_decode_crtc(struct par_info *hw, struct cfb_info *cfb,
0560 struct fb_var_screeninfo *var)
0561 {
0562 u_int Htotal, Hblankend, Hsyncend;
0563 u_int Vtotal, Vdispend, Vblankstart, Vblankend, Vsyncstart, Vsyncend;
0564 #define ENCODE_BIT(v, b1, m, b2) ((((v) >> (b1)) & (m)) << (b2))
0565
0566 hw->crtc[13] = hw->pitch;
0567 hw->crtc[17] = 0xe3;
0568 hw->crtc[14] = 0;
0569 hw->crtc[8] = 0;
0570
0571 Htotal = var->xres + var->right_margin +
0572 var->hsync_len + var->left_margin;
0573
0574 if (Htotal > 2080)
0575 return -EINVAL;
0576
0577 hw->crtc[0] = (Htotal >> 3) - 5;
0578 hw->crtc[1] = (var->xres >> 3) - 1;
0579 hw->crtc[2] = var->xres >> 3;
0580 hw->crtc[4] = (var->xres + var->right_margin) >> 3;
0581
0582 Hblankend = (Htotal - 4 * 8) >> 3;
0583
0584 hw->crtc[3] = ENCODE_BIT(Hblankend, 0, 0x1f, 0) |
0585 ENCODE_BIT(1, 0, 0x01, 7);
0586
0587 Hsyncend = (var->xres + var->right_margin + var->hsync_len) >> 3;
0588
0589 hw->crtc[5] = ENCODE_BIT(Hsyncend, 0, 0x1f, 0) |
0590 ENCODE_BIT(Hblankend, 5, 0x01, 7);
0591
0592 Vdispend = var->yres - 1;
0593 Vsyncstart = var->yres + var->lower_margin;
0594 Vsyncend = var->yres + var->lower_margin + var->vsync_len;
0595 Vtotal = var->yres + var->lower_margin + var->vsync_len +
0596 var->upper_margin - 2;
0597
0598 if (Vtotal > 2047)
0599 return -EINVAL;
0600
0601 Vblankstart = var->yres + 6;
0602 Vblankend = Vtotal - 10;
0603
0604 hw->crtc[6] = Vtotal;
0605 hw->crtc[7] = ENCODE_BIT(Vtotal, 8, 0x01, 0) |
0606 ENCODE_BIT(Vdispend, 8, 0x01, 1) |
0607 ENCODE_BIT(Vsyncstart, 8, 0x01, 2) |
0608 ENCODE_BIT(Vblankstart, 8, 0x01, 3) |
0609 ENCODE_BIT(1, 0, 0x01, 4) |
0610 ENCODE_BIT(Vtotal, 9, 0x01, 5) |
0611 ENCODE_BIT(Vdispend, 9, 0x01, 6) |
0612 ENCODE_BIT(Vsyncstart, 9, 0x01, 7);
0613 hw->crtc[9] = ENCODE_BIT(0, 0, 0x1f, 0) |
0614 ENCODE_BIT(Vblankstart, 9, 0x01, 5) |
0615 ENCODE_BIT(1, 0, 0x01, 6);
0616 hw->crtc[10] = Vsyncstart;
0617 hw->crtc[11] = ENCODE_BIT(Vsyncend, 0, 0x0f, 0) |
0618 ENCODE_BIT(1, 0, 0x01, 7);
0619 hw->crtc[12] = Vdispend;
0620 hw->crtc[15] = Vblankstart;
0621 hw->crtc[16] = Vblankend;
0622 hw->crtc[18] = 0xff;
0623
0624
0625
0626
0627
0628
0629 hw->crtc_ofl =
0630 ENCODE_BIT(Vtotal, 10, 0x01, 0) |
0631 ENCODE_BIT(Vdispend, 10, 0x01, 1) |
0632 ENCODE_BIT(Vsyncstart, 10, 0x01, 2) |
0633 ENCODE_BIT(Vblankstart, 10, 0x01, 3) |
0634 EXT_CRT_VRTOFL_LINECOMP10;
0635
0636
0637
0638 if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED)
0639 hw->crtc_ofl |= EXT_CRT_VRTOFL_INTERLACE;
0640
0641 return 0;
0642 }
0643
0644
0645
0646
0647
0648
0649
0650
0651
0652
0653
0654
0655
0656
0657
0658
0659 static int
0660 cyber2000fb_decode_clock(struct par_info *hw, struct cfb_info *cfb,
0661 struct fb_var_screeninfo *var)
0662 {
0663 u_long pll_ps = var->pixclock;
0664 const u_long ref_ps = cfb->ref_ps;
0665 u_int div2, t_div1, best_div1, best_mult;
0666 int best_diff;
0667 int vco;
0668
0669
0670
0671
0672
0673
0674 for (div2 = 0; div2 < 4; div2++) {
0675 u_long new_pll;
0676
0677 new_pll = pll_ps / cfb->divisors[div2];
0678 if (8696 > new_pll && new_pll > 3846) {
0679 pll_ps = new_pll;
0680 break;
0681 }
0682 }
0683
0684 if (div2 == 4)
0685 return -EINVAL;
0686
0687
0688
0689
0690
0691
0692
0693
0694 best_diff = 0x7fffffff;
0695 best_mult = 2;
0696 best_div1 = 32;
0697 for (t_div1 = 2; t_div1 < 32; t_div1 += 1) {
0698 u_int rr, t_mult, t_pll_ps;
0699 int diff;
0700
0701
0702
0703
0704 rr = ref_ps * t_div1;
0705 t_mult = (rr + pll_ps / 2) / pll_ps;
0706
0707
0708
0709
0710 if (t_mult > 256 || t_mult < 2)
0711 continue;
0712
0713
0714
0715
0716
0717 t_pll_ps = (rr + t_mult / 2) / t_mult;
0718 diff = pll_ps - t_pll_ps;
0719 if (diff < 0)
0720 diff = -diff;
0721
0722 if (diff < best_diff) {
0723 best_diff = diff;
0724 best_mult = t_mult;
0725 best_div1 = t_div1;
0726 }
0727
0728
0729
0730
0731 if (diff == 0)
0732 break;
0733 }
0734
0735
0736
0737
0738
0739 hw->clock_mult = best_mult - 1;
0740 hw->clock_div = div2 << 6 | (best_div1 - 1);
0741
0742 vco = ref_ps * best_div1 / best_mult;
0743 if ((ref_ps == 40690) && (vco < 5556))
0744
0745 hw->clock_div |= EXT_DCLK_DIV_VFSEL;
0746
0747 return 0;
0748 }
0749
0750
0751
0752
0753 static int
0754 cyber2000fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
0755 {
0756 struct cfb_info *cfb = container_of(info, struct cfb_info, fb);
0757 struct par_info hw;
0758 unsigned int mem;
0759 int err;
0760
0761 var->transp.msb_right = 0;
0762 var->red.msb_right = 0;
0763 var->green.msb_right = 0;
0764 var->blue.msb_right = 0;
0765 var->transp.offset = 0;
0766 var->transp.length = 0;
0767
0768 switch (var->bits_per_pixel) {
0769 case 8:
0770 var->red.offset = 0;
0771 var->red.length = 8;
0772 var->green.offset = 0;
0773 var->green.length = 8;
0774 var->blue.offset = 0;
0775 var->blue.length = 8;
0776 break;
0777
0778 case 16:
0779 switch (var->green.length) {
0780 case 6:
0781 var->red.offset = 11;
0782 var->red.length = 5;
0783 var->green.offset = 5;
0784 var->green.length = 6;
0785 var->blue.offset = 0;
0786 var->blue.length = 5;
0787 break;
0788
0789 default:
0790 case 5:
0791 var->red.offset = 10;
0792 var->red.length = 5;
0793 var->green.offset = 5;
0794 var->green.length = 5;
0795 var->blue.offset = 0;
0796 var->blue.length = 5;
0797 break;
0798
0799 case 4:
0800 var->transp.offset = 12;
0801 var->transp.length = 4;
0802 var->red.offset = 8;
0803 var->red.length = 4;
0804 var->green.offset = 4;
0805 var->green.length = 4;
0806 var->blue.offset = 0;
0807 var->blue.length = 4;
0808 break;
0809 }
0810 break;
0811
0812 case 24:
0813 var->red.offset = 16;
0814 var->red.length = 8;
0815 var->green.offset = 8;
0816 var->green.length = 8;
0817 var->blue.offset = 0;
0818 var->blue.length = 8;
0819 break;
0820
0821 case 32:
0822 var->transp.offset = 24;
0823 var->transp.length = 8;
0824 var->red.offset = 16;
0825 var->red.length = 8;
0826 var->green.offset = 8;
0827 var->green.length = 8;
0828 var->blue.offset = 0;
0829 var->blue.length = 8;
0830 break;
0831
0832 default:
0833 return -EINVAL;
0834 }
0835
0836 mem = var->xres_virtual * var->yres_virtual * (var->bits_per_pixel / 8);
0837 if (mem > cfb->fb.fix.smem_len)
0838 var->yres_virtual = cfb->fb.fix.smem_len * 8 /
0839 (var->bits_per_pixel * var->xres_virtual);
0840
0841 if (var->yres > var->yres_virtual)
0842 var->yres = var->yres_virtual;
0843 if (var->xres > var->xres_virtual)
0844 var->xres = var->xres_virtual;
0845
0846 err = cyber2000fb_decode_clock(&hw, cfb, var);
0847 if (err)
0848 return err;
0849
0850 err = cyber2000fb_decode_crtc(&hw, cfb, var);
0851 if (err)
0852 return err;
0853
0854 return 0;
0855 }
0856
0857 static int cyber2000fb_set_par(struct fb_info *info)
0858 {
0859 struct cfb_info *cfb = container_of(info, struct cfb_info, fb);
0860 struct fb_var_screeninfo *var = &cfb->fb.var;
0861 struct par_info hw;
0862 unsigned int mem;
0863
0864 hw.width = var->xres_virtual;
0865 hw.ramdac = RAMDAC_VREFEN | RAMDAC_DAC8BIT;
0866
0867 switch (var->bits_per_pixel) {
0868 case 8:
0869 hw.co_pixfmt = CO_PIXFMT_8BPP;
0870 hw.pitch = hw.width >> 3;
0871 hw.extseqmisc = EXT_SEQ_MISC_8;
0872 break;
0873
0874 case 16:
0875 hw.co_pixfmt = CO_PIXFMT_16BPP;
0876 hw.pitch = hw.width >> 2;
0877
0878 switch (var->green.length) {
0879 case 6:
0880 hw.extseqmisc = EXT_SEQ_MISC_16_RGB565;
0881 break;
0882 case 5:
0883 hw.extseqmisc = EXT_SEQ_MISC_16_RGB555;
0884 break;
0885 case 4:
0886 hw.extseqmisc = EXT_SEQ_MISC_16_RGB444;
0887 break;
0888 default:
0889 BUG();
0890 }
0891 break;
0892
0893 case 24:
0894 hw.co_pixfmt = CO_PIXFMT_24BPP;
0895 hw.width *= 3;
0896 hw.pitch = hw.width >> 3;
0897 hw.ramdac |= (RAMDAC_BYPASS | RAMDAC_RAMPWRDN);
0898 hw.extseqmisc = EXT_SEQ_MISC_24_RGB888;
0899 break;
0900
0901 case 32:
0902 hw.co_pixfmt = CO_PIXFMT_32BPP;
0903 hw.pitch = hw.width >> 1;
0904 hw.ramdac |= (RAMDAC_BYPASS | RAMDAC_RAMPWRDN);
0905 hw.extseqmisc = EXT_SEQ_MISC_32;
0906 break;
0907
0908 default:
0909 BUG();
0910 }
0911
0912
0913
0914
0915
0916
0917
0918
0919
0920
0921
0922
0923 BUG_ON(cyber2000fb_decode_clock(&hw, cfb, var) != 0);
0924 BUG_ON(cyber2000fb_decode_crtc(&hw, cfb, var) != 0);
0925
0926 hw.width -= 1;
0927 hw.fetch = hw.pitch;
0928 if (!(cfb->mem_ctl2 & MEM_CTL2_64BIT))
0929 hw.fetch <<= 1;
0930 hw.fetch += 1;
0931
0932 cfb->fb.fix.line_length = var->xres_virtual * var->bits_per_pixel / 8;
0933
0934
0935
0936
0937
0938
0939
0940
0941 mem = cfb->fb.fix.line_length * var->yres_virtual;
0942 BUG_ON(mem > cfb->fb.fix.smem_len);
0943
0944
0945
0946
0947
0948
0949
0950 if (var->bits_per_pixel == 8)
0951 cfb->fb.fix.visual = FB_VISUAL_PSEUDOCOLOR;
0952 else if (hw.ramdac & RAMDAC_BYPASS)
0953 cfb->fb.fix.visual = FB_VISUAL_TRUECOLOR;
0954 else
0955 cfb->fb.fix.visual = FB_VISUAL_DIRECTCOLOR;
0956
0957 cyber2000fb_set_timing(cfb, &hw);
0958 cyber2000fb_update_start(cfb, var);
0959
0960 return 0;
0961 }
0962
0963
0964
0965
0966 static int
0967 cyber2000fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
0968 {
0969 struct cfb_info *cfb = container_of(info, struct cfb_info, fb);
0970
0971 if (cyber2000fb_update_start(cfb, var))
0972 return -EINVAL;
0973
0974 cfb->fb.var.xoffset = var->xoffset;
0975 cfb->fb.var.yoffset = var->yoffset;
0976
0977 if (var->vmode & FB_VMODE_YWRAP) {
0978 cfb->fb.var.vmode |= FB_VMODE_YWRAP;
0979 } else {
0980 cfb->fb.var.vmode &= ~FB_VMODE_YWRAP;
0981 }
0982
0983 return 0;
0984 }
0985
0986
0987
0988
0989
0990
0991
0992
0993
0994
0995
0996
0997
0998
0999
1000
1001
1002
1003 static int cyber2000fb_blank(int blank, struct fb_info *info)
1004 {
1005 struct cfb_info *cfb = container_of(info, struct cfb_info, fb);
1006 unsigned int sync = 0;
1007 int i;
1008
1009 switch (blank) {
1010 case FB_BLANK_POWERDOWN:
1011 sync = EXT_SYNC_CTL_VS_0 | EXT_SYNC_CTL_HS_0;
1012 break;
1013 case FB_BLANK_HSYNC_SUSPEND:
1014 sync = EXT_SYNC_CTL_VS_NORMAL | EXT_SYNC_CTL_HS_0;
1015 break;
1016 case FB_BLANK_VSYNC_SUSPEND:
1017 sync = EXT_SYNC_CTL_VS_0 | EXT_SYNC_CTL_HS_NORMAL;
1018 break;
1019 case FB_BLANK_NORMAL:
1020 default:
1021 break;
1022 }
1023
1024 cyber2000_grphw(EXT_SYNC_CTL, sync, cfb);
1025
1026 if (blank <= 1) {
1027
1028 cfb->ramdac_powerdown &= ~(RAMDAC_DACPWRDN | RAMDAC_BYPASS |
1029 RAMDAC_RAMPWRDN);
1030 cyber2000fb_write_ramdac_ctrl(cfb);
1031 }
1032
1033
1034
1035
1036 if (blank) {
1037 for (i = 0; i < NR_PALETTE; i++) {
1038 cyber2000fb_writeb(i, 0x3c8, cfb);
1039 cyber2000fb_writeb(0, 0x3c9, cfb);
1040 cyber2000fb_writeb(0, 0x3c9, cfb);
1041 cyber2000fb_writeb(0, 0x3c9, cfb);
1042 }
1043 } else {
1044 for (i = 0; i < NR_PALETTE; i++) {
1045 cyber2000fb_writeb(i, 0x3c8, cfb);
1046 cyber2000fb_writeb(cfb->palette[i].red, 0x3c9, cfb);
1047 cyber2000fb_writeb(cfb->palette[i].green, 0x3c9, cfb);
1048 cyber2000fb_writeb(cfb->palette[i].blue, 0x3c9, cfb);
1049 }
1050 }
1051
1052 if (blank >= 2) {
1053
1054 cfb->ramdac_powerdown |= RAMDAC_DACPWRDN | RAMDAC_BYPASS |
1055 RAMDAC_RAMPWRDN;
1056 cyber2000fb_write_ramdac_ctrl(cfb);
1057 }
1058
1059 return 0;
1060 }
1061
1062 static const struct fb_ops cyber2000fb_ops = {
1063 .owner = THIS_MODULE,
1064 .fb_check_var = cyber2000fb_check_var,
1065 .fb_set_par = cyber2000fb_set_par,
1066 .fb_setcolreg = cyber2000fb_setcolreg,
1067 .fb_blank = cyber2000fb_blank,
1068 .fb_pan_display = cyber2000fb_pan_display,
1069 .fb_fillrect = cyber2000fb_fillrect,
1070 .fb_copyarea = cyber2000fb_copyarea,
1071 .fb_imageblit = cyber2000fb_imageblit,
1072 .fb_sync = cyber2000fb_sync,
1073 };
1074
1075
1076
1077
1078
1079
1080 static struct cfb_info *int_cfb_info;
1081
1082
1083
1084
1085 void cyber2000fb_enable_extregs(struct cfb_info *cfb)
1086 {
1087 cfb->func_use_count += 1;
1088
1089 if (cfb->func_use_count == 1) {
1090 int old;
1091
1092 old = cyber2000_grphr(EXT_FUNC_CTL, cfb);
1093 old |= EXT_FUNC_CTL_EXTREGENBL;
1094 cyber2000_grphw(EXT_FUNC_CTL, old, cfb);
1095 }
1096 }
1097 EXPORT_SYMBOL(cyber2000fb_enable_extregs);
1098
1099
1100
1101
1102 void cyber2000fb_disable_extregs(struct cfb_info *cfb)
1103 {
1104 if (cfb->func_use_count == 1) {
1105 int old;
1106
1107 old = cyber2000_grphr(EXT_FUNC_CTL, cfb);
1108 old &= ~EXT_FUNC_CTL_EXTREGENBL;
1109 cyber2000_grphw(EXT_FUNC_CTL, old, cfb);
1110 }
1111
1112 if (cfb->func_use_count == 0)
1113 printk(KERN_ERR "disable_extregs: count = 0\n");
1114 else
1115 cfb->func_use_count -= 1;
1116 }
1117 EXPORT_SYMBOL(cyber2000fb_disable_extregs);
1118
1119
1120
1121
1122 int cyber2000fb_attach(struct cyberpro_info *info, int idx)
1123 {
1124 if (int_cfb_info != NULL) {
1125 info->dev = int_cfb_info->fb.device;
1126 #ifdef CONFIG_FB_CYBER2000_I2C
1127 info->i2c = &int_cfb_info->i2c_adapter;
1128 #else
1129 info->i2c = NULL;
1130 #endif
1131 info->regs = int_cfb_info->regs;
1132 info->irq = int_cfb_info->irq;
1133 info->fb = int_cfb_info->fb.screen_base;
1134 info->fb_size = int_cfb_info->fb.fix.smem_len;
1135 info->info = int_cfb_info;
1136
1137 strscpy(info->dev_name, int_cfb_info->fb.fix.id,
1138 sizeof(info->dev_name));
1139 }
1140
1141 return int_cfb_info != NULL;
1142 }
1143 EXPORT_SYMBOL(cyber2000fb_attach);
1144
1145
1146
1147
1148 void cyber2000fb_detach(int idx)
1149 {
1150 }
1151 EXPORT_SYMBOL(cyber2000fb_detach);
1152
1153 #ifdef CONFIG_FB_CYBER2000_DDC
1154
1155 #define DDC_REG 0xb0
1156 #define DDC_SCL_OUT (1 << 0)
1157 #define DDC_SDA_OUT (1 << 4)
1158 #define DDC_SCL_IN (1 << 2)
1159 #define DDC_SDA_IN (1 << 6)
1160
1161 static void cyber2000fb_enable_ddc(struct cfb_info *cfb)
1162 __acquires(&cfb->reg_b0_lock)
1163 {
1164 spin_lock(&cfb->reg_b0_lock);
1165 cyber2000fb_writew(0x1bf, 0x3ce, cfb);
1166 }
1167
1168 static void cyber2000fb_disable_ddc(struct cfb_info *cfb)
1169 __releases(&cfb->reg_b0_lock)
1170 {
1171 cyber2000fb_writew(0x0bf, 0x3ce, cfb);
1172 spin_unlock(&cfb->reg_b0_lock);
1173 }
1174
1175
1176 static void cyber2000fb_ddc_setscl(void *data, int val)
1177 {
1178 struct cfb_info *cfb = data;
1179 unsigned char reg;
1180
1181 cyber2000fb_enable_ddc(cfb);
1182 reg = cyber2000_grphr(DDC_REG, cfb);
1183 if (!val)
1184 reg |= DDC_SCL_OUT;
1185 else
1186 reg &= ~DDC_SCL_OUT;
1187 cyber2000_grphw(DDC_REG, reg, cfb);
1188 cyber2000fb_disable_ddc(cfb);
1189 }
1190
1191 static void cyber2000fb_ddc_setsda(void *data, int val)
1192 {
1193 struct cfb_info *cfb = data;
1194 unsigned char reg;
1195
1196 cyber2000fb_enable_ddc(cfb);
1197 reg = cyber2000_grphr(DDC_REG, cfb);
1198 if (!val)
1199 reg |= DDC_SDA_OUT;
1200 else
1201 reg &= ~DDC_SDA_OUT;
1202 cyber2000_grphw(DDC_REG, reg, cfb);
1203 cyber2000fb_disable_ddc(cfb);
1204 }
1205
1206 static int cyber2000fb_ddc_getscl(void *data)
1207 {
1208 struct cfb_info *cfb = data;
1209 int retval;
1210
1211 cyber2000fb_enable_ddc(cfb);
1212 retval = !!(cyber2000_grphr(DDC_REG, cfb) & DDC_SCL_IN);
1213 cyber2000fb_disable_ddc(cfb);
1214
1215 return retval;
1216 }
1217
1218 static int cyber2000fb_ddc_getsda(void *data)
1219 {
1220 struct cfb_info *cfb = data;
1221 int retval;
1222
1223 cyber2000fb_enable_ddc(cfb);
1224 retval = !!(cyber2000_grphr(DDC_REG, cfb) & DDC_SDA_IN);
1225 cyber2000fb_disable_ddc(cfb);
1226
1227 return retval;
1228 }
1229
1230 static int cyber2000fb_setup_ddc_bus(struct cfb_info *cfb)
1231 {
1232 strscpy(cfb->ddc_adapter.name, cfb->fb.fix.id,
1233 sizeof(cfb->ddc_adapter.name));
1234 cfb->ddc_adapter.owner = THIS_MODULE;
1235 cfb->ddc_adapter.class = I2C_CLASS_DDC;
1236 cfb->ddc_adapter.algo_data = &cfb->ddc_algo;
1237 cfb->ddc_adapter.dev.parent = cfb->fb.device;
1238 cfb->ddc_algo.setsda = cyber2000fb_ddc_setsda;
1239 cfb->ddc_algo.setscl = cyber2000fb_ddc_setscl;
1240 cfb->ddc_algo.getsda = cyber2000fb_ddc_getsda;
1241 cfb->ddc_algo.getscl = cyber2000fb_ddc_getscl;
1242 cfb->ddc_algo.udelay = 10;
1243 cfb->ddc_algo.timeout = 20;
1244 cfb->ddc_algo.data = cfb;
1245
1246 i2c_set_adapdata(&cfb->ddc_adapter, cfb);
1247
1248 return i2c_bit_add_bus(&cfb->ddc_adapter);
1249 }
1250 #endif
1251
1252 #ifdef CONFIG_FB_CYBER2000_I2C
1253 static void cyber2000fb_i2c_setsda(void *data, int state)
1254 {
1255 struct cfb_info *cfb = data;
1256 unsigned int latch2;
1257
1258 spin_lock(&cfb->reg_b0_lock);
1259 latch2 = cyber2000_grphr(EXT_LATCH2, cfb);
1260 latch2 &= EXT_LATCH2_I2C_CLKEN;
1261 if (state)
1262 latch2 |= EXT_LATCH2_I2C_DATEN;
1263 cyber2000_grphw(EXT_LATCH2, latch2, cfb);
1264 spin_unlock(&cfb->reg_b0_lock);
1265 }
1266
1267 static void cyber2000fb_i2c_setscl(void *data, int state)
1268 {
1269 struct cfb_info *cfb = data;
1270 unsigned int latch2;
1271
1272 spin_lock(&cfb->reg_b0_lock);
1273 latch2 = cyber2000_grphr(EXT_LATCH2, cfb);
1274 latch2 &= EXT_LATCH2_I2C_DATEN;
1275 if (state)
1276 latch2 |= EXT_LATCH2_I2C_CLKEN;
1277 cyber2000_grphw(EXT_LATCH2, latch2, cfb);
1278 spin_unlock(&cfb->reg_b0_lock);
1279 }
1280
1281 static int cyber2000fb_i2c_getsda(void *data)
1282 {
1283 struct cfb_info *cfb = data;
1284 int ret;
1285
1286 spin_lock(&cfb->reg_b0_lock);
1287 ret = !!(cyber2000_grphr(EXT_LATCH2, cfb) & EXT_LATCH2_I2C_DAT);
1288 spin_unlock(&cfb->reg_b0_lock);
1289
1290 return ret;
1291 }
1292
1293 static int cyber2000fb_i2c_getscl(void *data)
1294 {
1295 struct cfb_info *cfb = data;
1296 int ret;
1297
1298 spin_lock(&cfb->reg_b0_lock);
1299 ret = !!(cyber2000_grphr(EXT_LATCH2, cfb) & EXT_LATCH2_I2C_CLK);
1300 spin_unlock(&cfb->reg_b0_lock);
1301
1302 return ret;
1303 }
1304
1305 static int cyber2000fb_i2c_register(struct cfb_info *cfb)
1306 {
1307 strscpy(cfb->i2c_adapter.name, cfb->fb.fix.id,
1308 sizeof(cfb->i2c_adapter.name));
1309 cfb->i2c_adapter.owner = THIS_MODULE;
1310 cfb->i2c_adapter.algo_data = &cfb->i2c_algo;
1311 cfb->i2c_adapter.dev.parent = cfb->fb.device;
1312 cfb->i2c_algo.setsda = cyber2000fb_i2c_setsda;
1313 cfb->i2c_algo.setscl = cyber2000fb_i2c_setscl;
1314 cfb->i2c_algo.getsda = cyber2000fb_i2c_getsda;
1315 cfb->i2c_algo.getscl = cyber2000fb_i2c_getscl;
1316 cfb->i2c_algo.udelay = 5;
1317 cfb->i2c_algo.timeout = msecs_to_jiffies(100);
1318 cfb->i2c_algo.data = cfb;
1319
1320 return i2c_bit_add_bus(&cfb->i2c_adapter);
1321 }
1322
1323 static void cyber2000fb_i2c_unregister(struct cfb_info *cfb)
1324 {
1325 i2c_del_adapter(&cfb->i2c_adapter);
1326 }
1327 #else
1328 #define cyber2000fb_i2c_register(cfb) (0)
1329 #define cyber2000fb_i2c_unregister(cfb) do { } while (0)
1330 #endif
1331
1332
1333
1334
1335
1336 static const struct fb_videomode cyber2000fb_default_mode = {
1337 .refresh = 60,
1338 .xres = 640,
1339 .yres = 480,
1340 .pixclock = 39722,
1341 .left_margin = 56,
1342 .right_margin = 16,
1343 .upper_margin = 34,
1344 .lower_margin = 9,
1345 .hsync_len = 88,
1346 .vsync_len = 2,
1347 .sync = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
1348 .vmode = FB_VMODE_NONINTERLACED
1349 };
1350
1351 static char igs_regs[] = {
1352 EXT_CRT_IRQ, 0,
1353 EXT_CRT_TEST, 0,
1354 EXT_SYNC_CTL, 0,
1355 EXT_SEG_WRITE_PTR, 0,
1356 EXT_SEG_READ_PTR, 0,
1357 EXT_BIU_MISC, EXT_BIU_MISC_LIN_ENABLE |
1358 EXT_BIU_MISC_COP_ENABLE |
1359 EXT_BIU_MISC_COP_BFC,
1360 EXT_FUNC_CTL, 0,
1361 CURS_H_START, 0,
1362 CURS_H_START + 1, 0,
1363 CURS_H_PRESET, 0,
1364 CURS_V_START, 0,
1365 CURS_V_START + 1, 0,
1366 CURS_V_PRESET, 0,
1367 CURS_CTL, 0,
1368 EXT_ATTRIB_CTL, EXT_ATTRIB_CTL_EXT,
1369 EXT_OVERSCAN_RED, 0,
1370 EXT_OVERSCAN_GREEN, 0,
1371 EXT_OVERSCAN_BLUE, 0,
1372
1373
1374 EXT_MEM_CTL0, EXT_MEM_CTL0_7CLK |
1375 EXT_MEM_CTL0_RAS_1 |
1376 EXT_MEM_CTL0_MULTCAS,
1377 EXT_HIDDEN_CTL1, 0x30,
1378 EXT_FIFO_CTL, 0x0b,
1379 EXT_FIFO_CTL + 1, 0x17,
1380 0x76, 0x00,
1381 EXT_HIDDEN_CTL4, 0xc8
1382 };
1383
1384
1385
1386
1387
1388
1389 static void cyberpro_init_hw(struct cfb_info *cfb)
1390 {
1391 int i;
1392
1393 for (i = 0; i < sizeof(igs_regs); i += 2)
1394 cyber2000_grphw(igs_regs[i], igs_regs[i + 1], cfb);
1395
1396 if (cfb->id == ID_CYBERPRO_5000) {
1397 unsigned char val;
1398 cyber2000fb_writeb(0xba, 0x3ce, cfb);
1399 val = cyber2000fb_readb(0x3cf, cfb) & 0x80;
1400 cyber2000fb_writeb(val, 0x3cf, cfb);
1401 }
1402 }
1403
1404 static struct cfb_info *cyberpro_alloc_fb_info(unsigned int id, char *name)
1405 {
1406 struct cfb_info *cfb;
1407
1408 cfb = kzalloc(sizeof(struct cfb_info), GFP_KERNEL);
1409 if (!cfb)
1410 return NULL;
1411
1412
1413 cfb->id = id;
1414
1415 if (id == ID_CYBERPRO_5000)
1416 cfb->ref_ps = 40690;
1417 else
1418 cfb->ref_ps = 69842;
1419
1420 cfb->divisors[0] = 1;
1421 cfb->divisors[1] = 2;
1422 cfb->divisors[2] = 4;
1423
1424 if (id == ID_CYBERPRO_2000)
1425 cfb->divisors[3] = 8;
1426 else
1427 cfb->divisors[3] = 6;
1428
1429 strcpy(cfb->fb.fix.id, name);
1430
1431 cfb->fb.fix.type = FB_TYPE_PACKED_PIXELS;
1432 cfb->fb.fix.type_aux = 0;
1433 cfb->fb.fix.xpanstep = 0;
1434 cfb->fb.fix.ypanstep = 1;
1435 cfb->fb.fix.ywrapstep = 0;
1436
1437 switch (id) {
1438 case ID_IGA_1682:
1439 cfb->fb.fix.accel = 0;
1440 break;
1441
1442 case ID_CYBERPRO_2000:
1443 cfb->fb.fix.accel = FB_ACCEL_IGS_CYBER2000;
1444 break;
1445
1446 case ID_CYBERPRO_2010:
1447 cfb->fb.fix.accel = FB_ACCEL_IGS_CYBER2010;
1448 break;
1449
1450 case ID_CYBERPRO_5000:
1451 cfb->fb.fix.accel = FB_ACCEL_IGS_CYBER5000;
1452 break;
1453 }
1454
1455 cfb->fb.var.nonstd = 0;
1456 cfb->fb.var.activate = FB_ACTIVATE_NOW;
1457 cfb->fb.var.height = -1;
1458 cfb->fb.var.width = -1;
1459 cfb->fb.var.accel_flags = FB_ACCELF_TEXT;
1460
1461 cfb->fb.fbops = &cyber2000fb_ops;
1462 cfb->fb.flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
1463 cfb->fb.pseudo_palette = cfb->pseudo_palette;
1464
1465 spin_lock_init(&cfb->reg_b0_lock);
1466
1467 fb_alloc_cmap(&cfb->fb.cmap, NR_PALETTE, 0);
1468
1469 return cfb;
1470 }
1471
1472 static void cyberpro_free_fb_info(struct cfb_info *cfb)
1473 {
1474 if (cfb) {
1475
1476
1477
1478 fb_alloc_cmap(&cfb->fb.cmap, 0, 0);
1479
1480 kfree(cfb);
1481 }
1482 }
1483
1484
1485
1486
1487
1488 #ifndef MODULE
1489 static int cyber2000fb_setup(char *options)
1490 {
1491 char *opt;
1492
1493 if (!options || !*options)
1494 return 0;
1495
1496 while ((opt = strsep(&options, ",")) != NULL) {
1497 if (!*opt)
1498 continue;
1499
1500 if (strncmp(opt, "font:", 5) == 0) {
1501 static char default_font_storage[40];
1502
1503 strscpy(default_font_storage, opt + 5,
1504 sizeof(default_font_storage));
1505 default_font = default_font_storage;
1506 continue;
1507 }
1508
1509 printk(KERN_ERR "CyberPro20x0: unknown parameter: %s\n", opt);
1510 }
1511 return 0;
1512 }
1513 #endif
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523 static int cyberpro_common_probe(struct cfb_info *cfb)
1524 {
1525 u_long smem_size;
1526 u_int h_sync, v_sync;
1527 int err;
1528
1529 cyberpro_init_hw(cfb);
1530
1531
1532
1533
1534
1535
1536 cfb->mem_ctl1 = cyber2000_grphr(EXT_MEM_CTL1, cfb);
1537 cfb->mem_ctl2 = cyber2000_grphr(EXT_MEM_CTL2, cfb);
1538
1539
1540
1541
1542 switch (cfb->mem_ctl2 & MEM_CTL2_SIZE_MASK) {
1543 case MEM_CTL2_SIZE_4MB:
1544 smem_size = 0x00400000;
1545 break;
1546 case MEM_CTL2_SIZE_2MB:
1547 smem_size = 0x00200000;
1548 break;
1549 case MEM_CTL2_SIZE_1MB:
1550 smem_size = 0x00100000;
1551 break;
1552 default:
1553 smem_size = 0x00100000;
1554 break;
1555 }
1556
1557 cfb->fb.fix.smem_len = smem_size;
1558 cfb->fb.fix.mmio_len = MMIO_SIZE;
1559 cfb->fb.screen_base = cfb->region;
1560
1561 #ifdef CONFIG_FB_CYBER2000_DDC
1562 if (cyber2000fb_setup_ddc_bus(cfb) == 0)
1563 cfb->ddc_registered = true;
1564 #endif
1565
1566 err = -EINVAL;
1567 if (!fb_find_mode(&cfb->fb.var, &cfb->fb, NULL, NULL, 0,
1568 &cyber2000fb_default_mode, 8)) {
1569 printk(KERN_ERR "%s: no valid mode found\n", cfb->fb.fix.id);
1570 goto failed;
1571 }
1572
1573 cfb->fb.var.yres_virtual = cfb->fb.fix.smem_len * 8 /
1574 (cfb->fb.var.bits_per_pixel * cfb->fb.var.xres_virtual);
1575
1576 if (cfb->fb.var.yres_virtual < cfb->fb.var.yres)
1577 cfb->fb.var.yres_virtual = cfb->fb.var.yres;
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587 h_sync = 1953125000 / cfb->fb.var.pixclock;
1588 h_sync = h_sync * 512 / (cfb->fb.var.xres + cfb->fb.var.left_margin +
1589 cfb->fb.var.right_margin + cfb->fb.var.hsync_len);
1590 v_sync = h_sync / (cfb->fb.var.yres + cfb->fb.var.upper_margin +
1591 cfb->fb.var.lower_margin + cfb->fb.var.vsync_len);
1592
1593 printk(KERN_INFO "%s: %dKiB VRAM, using %dx%d, %d.%03dkHz, %dHz\n",
1594 cfb->fb.fix.id, cfb->fb.fix.smem_len >> 10,
1595 cfb->fb.var.xres, cfb->fb.var.yres,
1596 h_sync / 1000, h_sync % 1000, v_sync);
1597
1598 err = cyber2000fb_i2c_register(cfb);
1599 if (err)
1600 goto failed;
1601
1602 err = register_framebuffer(&cfb->fb);
1603 if (err)
1604 cyber2000fb_i2c_unregister(cfb);
1605
1606 failed:
1607 #ifdef CONFIG_FB_CYBER2000_DDC
1608 if (err && cfb->ddc_registered)
1609 i2c_del_adapter(&cfb->ddc_adapter);
1610 #endif
1611 return err;
1612 }
1613
1614 static void cyberpro_common_remove(struct cfb_info *cfb)
1615 {
1616 unregister_framebuffer(&cfb->fb);
1617 #ifdef CONFIG_FB_CYBER2000_DDC
1618 if (cfb->ddc_registered)
1619 i2c_del_adapter(&cfb->ddc_adapter);
1620 #endif
1621 cyber2000fb_i2c_unregister(cfb);
1622 }
1623
1624 static void cyberpro_common_resume(struct cfb_info *cfb)
1625 {
1626 cyberpro_init_hw(cfb);
1627
1628
1629
1630
1631 cyber2000_grphw(EXT_MEM_CTL1, cfb->mem_ctl1, cfb);
1632 cyber2000_grphw(EXT_MEM_CTL2, cfb->mem_ctl2, cfb);
1633
1634
1635
1636
1637
1638 cyber2000fb_set_par(&cfb->fb);
1639 }
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651 static int cyberpro_pci_enable_mmio(struct cfb_info *cfb)
1652 {
1653 unsigned char val;
1654
1655 #if defined(__sparc_v9__)
1656 #error "You lose, consult DaveM."
1657 #elif defined(__sparc__)
1658
1659
1660
1661
1662
1663 unsigned char __iomem *iop;
1664
1665 iop = ioremap(0x3000000, 0x5000);
1666 if (iop == NULL) {
1667 printk(KERN_ERR "iga5000: cannot map I/O\n");
1668 return -ENOMEM;
1669 }
1670
1671 writeb(0x18, iop + 0x46e8);
1672 writeb(0x01, iop + 0x102);
1673 writeb(0x08, iop + 0x46e8);
1674 writeb(EXT_BIU_MISC, iop + 0x3ce);
1675 writeb(EXT_BIU_MISC_LIN_ENABLE, iop + 0x3cf);
1676
1677 iounmap(iop);
1678 #else
1679
1680
1681
1682
1683 outb(0x18, 0x46e8);
1684 outb(0x01, 0x102);
1685 outb(0x08, 0x46e8);
1686 outb(EXT_BIU_MISC, 0x3ce);
1687 outb(EXT_BIU_MISC_LIN_ENABLE, 0x3cf);
1688 #endif
1689
1690
1691
1692
1693 if (cfb->id == ID_CYBERPRO_2010) {
1694 printk(KERN_INFO "%s: NOT enabling PCI bursts\n",
1695 cfb->fb.fix.id);
1696 } else {
1697 val = cyber2000_grphr(EXT_BUS_CTL, cfb);
1698 if (!(val & EXT_BUS_CTL_PCIBURST_WRITE)) {
1699 printk(KERN_INFO "%s: enabling PCI bursts\n",
1700 cfb->fb.fix.id);
1701
1702 val |= EXT_BUS_CTL_PCIBURST_WRITE;
1703
1704 if (cfb->id == ID_CYBERPRO_5000)
1705 val |= EXT_BUS_CTL_PCIBURST_READ;
1706
1707 cyber2000_grphw(EXT_BUS_CTL, val, cfb);
1708 }
1709 }
1710
1711 return 0;
1712 }
1713
1714 static int cyberpro_pci_probe(struct pci_dev *dev,
1715 const struct pci_device_id *id)
1716 {
1717 struct cfb_info *cfb;
1718 char name[16];
1719 int err;
1720
1721 sprintf(name, "CyberPro%4X", id->device);
1722
1723 err = pci_enable_device(dev);
1724 if (err)
1725 return err;
1726
1727 err = -ENOMEM;
1728 cfb = cyberpro_alloc_fb_info(id->driver_data, name);
1729 if (!cfb)
1730 goto failed_release;
1731
1732 err = pci_request_regions(dev, cfb->fb.fix.id);
1733 if (err)
1734 goto failed_regions;
1735
1736 cfb->irq = dev->irq;
1737 cfb->region = pci_ioremap_bar(dev, 0);
1738 if (!cfb->region) {
1739 err = -ENOMEM;
1740 goto failed_ioremap;
1741 }
1742
1743 cfb->regs = cfb->region + MMIO_OFFSET;
1744 cfb->fb.device = &dev->dev;
1745 cfb->fb.fix.mmio_start = pci_resource_start(dev, 0) + MMIO_OFFSET;
1746 cfb->fb.fix.smem_start = pci_resource_start(dev, 0);
1747
1748
1749
1750
1751
1752
1753
1754 err = cyberpro_pci_enable_mmio(cfb);
1755 if (err)
1756 goto failed;
1757
1758
1759
1760
1761 cfb->mclk_mult = cyber2000_grphr(EXT_MCLK_MULT, cfb);
1762 cfb->mclk_div = cyber2000_grphr(EXT_MCLK_DIV, cfb);
1763
1764 #ifdef __arm__
1765
1766
1767
1768 if (machine_is_netwinder()) {
1769 cfb->mclk_mult = 0xdb;
1770 cfb->mclk_div = 0x54;
1771 }
1772 #endif
1773
1774 err = cyberpro_common_probe(cfb);
1775 if (err)
1776 goto failed;
1777
1778
1779
1780
1781 pci_set_drvdata(dev, cfb);
1782 if (int_cfb_info == NULL)
1783 int_cfb_info = cfb;
1784
1785 return 0;
1786
1787 failed:
1788 iounmap(cfb->region);
1789 failed_ioremap:
1790 pci_release_regions(dev);
1791 failed_regions:
1792 cyberpro_free_fb_info(cfb);
1793 failed_release:
1794 return err;
1795 }
1796
1797 static void cyberpro_pci_remove(struct pci_dev *dev)
1798 {
1799 struct cfb_info *cfb = pci_get_drvdata(dev);
1800
1801 if (cfb) {
1802 cyberpro_common_remove(cfb);
1803 iounmap(cfb->region);
1804 cyberpro_free_fb_info(cfb);
1805
1806 if (cfb == int_cfb_info)
1807 int_cfb_info = NULL;
1808
1809 pci_release_regions(dev);
1810 }
1811 }
1812
1813 static int __maybe_unused cyberpro_pci_suspend(struct device *dev)
1814 {
1815 return 0;
1816 }
1817
1818
1819
1820
1821 static int __maybe_unused cyberpro_pci_resume(struct device *dev)
1822 {
1823 struct cfb_info *cfb = dev_get_drvdata(dev);
1824
1825 if (cfb) {
1826 cyberpro_pci_enable_mmio(cfb);
1827 cyberpro_common_resume(cfb);
1828 }
1829
1830 return 0;
1831 }
1832
1833 static struct pci_device_id cyberpro_pci_table[] = {
1834
1835
1836
1837
1838 { PCI_VENDOR_ID_INTERG, PCI_DEVICE_ID_INTERG_2000,
1839 PCI_ANY_ID, PCI_ANY_ID, 0, 0, ID_CYBERPRO_2000 },
1840 { PCI_VENDOR_ID_INTERG, PCI_DEVICE_ID_INTERG_2010,
1841 PCI_ANY_ID, PCI_ANY_ID, 0, 0, ID_CYBERPRO_2010 },
1842 { PCI_VENDOR_ID_INTERG, PCI_DEVICE_ID_INTERG_5000,
1843 PCI_ANY_ID, PCI_ANY_ID, 0, 0, ID_CYBERPRO_5000 },
1844 { 0, }
1845 };
1846
1847 MODULE_DEVICE_TABLE(pci, cyberpro_pci_table);
1848
1849 static SIMPLE_DEV_PM_OPS(cyberpro_pci_pm_ops,
1850 cyberpro_pci_suspend,
1851 cyberpro_pci_resume);
1852
1853 static struct pci_driver cyberpro_driver = {
1854 .name = "CyberPro",
1855 .probe = cyberpro_pci_probe,
1856 .remove = cyberpro_pci_remove,
1857 .driver.pm = &cyberpro_pci_pm_ops,
1858 .id_table = cyberpro_pci_table
1859 };
1860
1861
1862
1863
1864
1865
1866
1867
1868 static int __init cyber2000fb_init(void)
1869 {
1870 int ret = -1, err;
1871
1872 #ifndef MODULE
1873 char *option = NULL;
1874
1875 if (fb_get_options("cyber2000fb", &option))
1876 return -ENODEV;
1877 cyber2000fb_setup(option);
1878 #endif
1879
1880 err = pci_register_driver(&cyberpro_driver);
1881 if (!err)
1882 ret = 0;
1883
1884 return ret ? err : 0;
1885 }
1886 module_init(cyber2000fb_init);
1887
1888 static void __exit cyberpro_exit(void)
1889 {
1890 pci_unregister_driver(&cyberpro_driver);
1891 }
1892 module_exit(cyberpro_exit);
1893
1894 MODULE_AUTHOR("Russell King");
1895 MODULE_DESCRIPTION("CyberPro 2000, 2010 and 5000 framebuffer driver");
1896 MODULE_LICENSE("GPL");