root/drivers/video/fbdev/chipsfb.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. chipsfb_check_var
  2. chipsfb_set_par
  3. chipsfb_blank
  4. chipsfb_setcolreg
  5. chips_hw_init
  6. init_chips
  7. chipsfb_pci_init
  8. chipsfb_remove
  9. chipsfb_pci_suspend
  10. chipsfb_pci_resume
  11. chips_init
  12. chipsfb_exit

   1 /*
   2  *  drivers/video/chipsfb.c -- frame buffer device for
   3  *  Chips & Technologies 65550 chip.
   4  *
   5  *  Copyright (C) 1998-2002 Paul Mackerras
   6  *
   7  *  This file is derived from the Powermac "chips" driver:
   8  *  Copyright (C) 1997 Fabio Riccardi.
   9  *  And from the frame buffer device for Open Firmware-initialized devices:
  10  *  Copyright (C) 1997 Geert Uytterhoeven.
  11  *
  12  *  This file is subject to the terms and conditions of the GNU General Public
  13  *  License. See the file COPYING in the main directory of this archive for
  14  *  more details.
  15  */
  16 
  17 #include <linux/module.h>
  18 #include <linux/kernel.h>
  19 #include <linux/errno.h>
  20 #include <linux/string.h>
  21 #include <linux/mm.h>
  22 #include <linux/vmalloc.h>
  23 #include <linux/delay.h>
  24 #include <linux/interrupt.h>
  25 #include <linux/fb.h>
  26 #include <linux/pm.h>
  27 #include <linux/init.h>
  28 #include <linux/pci.h>
  29 #include <linux/console.h>
  30 
  31 #ifdef CONFIG_PMAC_BACKLIGHT
  32 #include <asm/backlight.h>
  33 #endif
  34 
  35 /*
  36  * Since we access the display with inb/outb to fixed port numbers,
  37  * we can only handle one 6555x chip.  -- paulus
  38  */
  39 #define write_ind(num, val, ap, dp)     do { \
  40         outb((num), (ap)); outb((val), (dp)); \
  41 } while (0)
  42 #define read_ind(num, var, ap, dp)      do { \
  43         outb((num), (ap)); var = inb((dp)); \
  44 } while (0)
  45 
  46 /* extension registers */
  47 #define write_xr(num, val)      write_ind(num, val, 0x3d6, 0x3d7)
  48 #define read_xr(num, var)       read_ind(num, var, 0x3d6, 0x3d7)
  49 /* flat panel registers */
  50 #define write_fr(num, val)      write_ind(num, val, 0x3d0, 0x3d1)
  51 #define read_fr(num, var)       read_ind(num, var, 0x3d0, 0x3d1)
  52 /* CRTC registers */
  53 #define write_cr(num, val)      write_ind(num, val, 0x3d4, 0x3d5)
  54 #define read_cr(num, var)       read_ind(num, var, 0x3d4, 0x3d5)
  55 /* graphics registers */
  56 #define write_gr(num, val)      write_ind(num, val, 0x3ce, 0x3cf)
  57 #define read_gr(num, var)       read_ind(num, var, 0x3ce, 0x3cf)
  58 /* sequencer registers */
  59 #define write_sr(num, val)      write_ind(num, val, 0x3c4, 0x3c5)
  60 #define read_sr(num, var)       read_ind(num, var, 0x3c4, 0x3c5)
  61 /* attribute registers - slightly strange */
  62 #define write_ar(num, val)      do { \
  63         inb(0x3da); write_ind(num, val, 0x3c0, 0x3c0); \
  64 } while (0)
  65 #define read_ar(num, var)       do { \
  66         inb(0x3da); read_ind(num, var, 0x3c0, 0x3c1); \
  67 } while (0)
  68 
  69 /*
  70  * Exported functions
  71  */
  72 int chips_init(void);
  73 
  74 static int chipsfb_pci_init(struct pci_dev *dp, const struct pci_device_id *);
  75 static int chipsfb_check_var(struct fb_var_screeninfo *var,
  76                              struct fb_info *info);
  77 static int chipsfb_set_par(struct fb_info *info);
  78 static int chipsfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
  79                              u_int transp, struct fb_info *info);
  80 static int chipsfb_blank(int blank, struct fb_info *info);
  81 
  82 static struct fb_ops chipsfb_ops = {
  83         .owner          = THIS_MODULE,
  84         .fb_check_var   = chipsfb_check_var,
  85         .fb_set_par     = chipsfb_set_par,
  86         .fb_setcolreg   = chipsfb_setcolreg,
  87         .fb_blank       = chipsfb_blank,
  88         .fb_fillrect    = cfb_fillrect,
  89         .fb_copyarea    = cfb_copyarea,
  90         .fb_imageblit   = cfb_imageblit,
  91 };
  92 
  93 static int chipsfb_check_var(struct fb_var_screeninfo *var,
  94                              struct fb_info *info)
  95 {
  96         if (var->xres > 800 || var->yres > 600
  97             || var->xres_virtual > 800 || var->yres_virtual > 600
  98             || (var->bits_per_pixel != 8 && var->bits_per_pixel != 16)
  99             || var->nonstd
 100             || (var->vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED)
 101                 return -EINVAL;
 102 
 103         var->xres = var->xres_virtual = 800;
 104         var->yres = var->yres_virtual = 600;
 105 
 106         return 0;
 107 }
 108 
 109 static int chipsfb_set_par(struct fb_info *info)
 110 {
 111         if (info->var.bits_per_pixel == 16) {
 112                 write_cr(0x13, 200);            // Set line length (doublewords)
 113                 write_xr(0x81, 0x14);           // 15 bit (555) color mode
 114                 write_xr(0x82, 0x00);           // Disable palettes
 115                 write_xr(0x20, 0x10);           // 16 bit blitter mode
 116 
 117                 info->fix.line_length = 800*2;
 118                 info->fix.visual = FB_VISUAL_TRUECOLOR;
 119 
 120                 info->var.red.offset = 10;
 121                 info->var.green.offset = 5;
 122                 info->var.blue.offset = 0;
 123                 info->var.red.length = info->var.green.length =
 124                         info->var.blue.length = 5;
 125                 
 126         } else {
 127                 /* p->var.bits_per_pixel == 8 */
 128                 write_cr(0x13, 100);            // Set line length (doublewords)
 129                 write_xr(0x81, 0x12);           // 8 bit color mode
 130                 write_xr(0x82, 0x08);           // Graphics gamma enable
 131                 write_xr(0x20, 0x00);           // 8 bit blitter mode
 132 
 133                 info->fix.line_length = 800;
 134                 info->fix.visual = FB_VISUAL_PSEUDOCOLOR;               
 135 
 136                 info->var.red.offset = info->var.green.offset =
 137                         info->var.blue.offset = 0;
 138                 info->var.red.length = info->var.green.length =
 139                         info->var.blue.length = 8;
 140                 
 141         }
 142         return 0;
 143 }
 144 
 145 static int chipsfb_blank(int blank, struct fb_info *info)
 146 {
 147         return 1;       /* get fb_blank to set the colormap to all black */
 148 }
 149 
 150 static int chipsfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
 151                              u_int transp, struct fb_info *info)
 152 {
 153         if (regno > 255)
 154                 return 1;
 155         red >>= 8;
 156         green >>= 8;
 157         blue >>= 8;
 158         outb(regno, 0x3c8);
 159         udelay(1);
 160         outb(red, 0x3c9);
 161         outb(green, 0x3c9);
 162         outb(blue, 0x3c9);
 163 
 164         return 0;
 165 }
 166 
 167 struct chips_init_reg {
 168         unsigned char addr;
 169         unsigned char data;
 170 };
 171 
 172 static struct chips_init_reg chips_init_sr[] = {
 173         { 0x00, 0x03 },
 174         { 0x01, 0x01 },
 175         { 0x02, 0x0f },
 176         { 0x04, 0x0e }
 177 };
 178 
 179 static struct chips_init_reg chips_init_gr[] = {
 180         { 0x05, 0x00 },
 181         { 0x06, 0x0d },
 182         { 0x08, 0xff }
 183 };
 184 
 185 static struct chips_init_reg chips_init_ar[] = {
 186         { 0x10, 0x01 },
 187         { 0x12, 0x0f },
 188         { 0x13, 0x00 }
 189 };
 190 
 191 static struct chips_init_reg chips_init_cr[] = {
 192         { 0x00, 0x7f },
 193         { 0x01, 0x63 },
 194         { 0x02, 0x63 },
 195         { 0x03, 0x83 },
 196         { 0x04, 0x66 },
 197         { 0x05, 0x10 },
 198         { 0x06, 0x72 },
 199         { 0x07, 0x3e },
 200         { 0x08, 0x00 },
 201         { 0x09, 0x40 },
 202         { 0x0c, 0x00 },
 203         { 0x0d, 0x00 },
 204         { 0x10, 0x59 },
 205         { 0x11, 0x0d },
 206         { 0x12, 0x57 },
 207         { 0x13, 0x64 },
 208         { 0x14, 0x00 },
 209         { 0x15, 0x57 },
 210         { 0x16, 0x73 },
 211         { 0x17, 0xe3 },
 212         { 0x18, 0xff },
 213         { 0x30, 0x02 },
 214         { 0x31, 0x02 },
 215         { 0x32, 0x02 },
 216         { 0x33, 0x02 },
 217         { 0x40, 0x00 },
 218         { 0x41, 0x00 },
 219         { 0x40, 0x80 }
 220 };
 221 
 222 static struct chips_init_reg chips_init_fr[] = {
 223         { 0x01, 0x02 },
 224         { 0x03, 0x08 },
 225         { 0x04, 0x81 },
 226         { 0x05, 0x21 },
 227         { 0x08, 0x0c },
 228         { 0x0a, 0x74 },
 229         { 0x0b, 0x11 },
 230         { 0x10, 0x0c },
 231         { 0x11, 0xe0 },
 232         /* { 0x12, 0x40 }, -- 3400 needs 40, 2400 needs 48, no way to tell */
 233         { 0x20, 0x63 },
 234         { 0x21, 0x68 },
 235         { 0x22, 0x19 },
 236         { 0x23, 0x7f },
 237         { 0x24, 0x68 },
 238         { 0x26, 0x00 },
 239         { 0x27, 0x0f },
 240         { 0x30, 0x57 },
 241         { 0x31, 0x58 },
 242         { 0x32, 0x0d },
 243         { 0x33, 0x72 },
 244         { 0x34, 0x02 },
 245         { 0x35, 0x22 },
 246         { 0x36, 0x02 },
 247         { 0x37, 0x00 }
 248 };
 249 
 250 static struct chips_init_reg chips_init_xr[] = {
 251         { 0xce, 0x00 },         /* set default memory clock */
 252         { 0xcc, 0x43 },         /* memory clock ratio */
 253         { 0xcd, 0x18 },
 254         { 0xce, 0xa1 },
 255         { 0xc8, 0x84 },
 256         { 0xc9, 0x0a },
 257         { 0xca, 0x00 },
 258         { 0xcb, 0x20 },
 259         { 0xcf, 0x06 },
 260         { 0xd0, 0x0e },
 261         { 0x09, 0x01 },
 262         { 0x0a, 0x02 },
 263         { 0x0b, 0x01 },
 264         { 0x20, 0x00 },
 265         { 0x40, 0x03 },
 266         { 0x41, 0x01 },
 267         { 0x42, 0x00 },
 268         { 0x80, 0x82 },
 269         { 0x81, 0x12 },
 270         { 0x82, 0x08 },
 271         { 0xa0, 0x00 },
 272         { 0xa8, 0x00 }
 273 };
 274 
 275 static void chips_hw_init(void)
 276 {
 277         int i;
 278 
 279         for (i = 0; i < ARRAY_SIZE(chips_init_xr); ++i)
 280                 write_xr(chips_init_xr[i].addr, chips_init_xr[i].data);
 281         outb(0x29, 0x3c2); /* set misc output reg */
 282         for (i = 0; i < ARRAY_SIZE(chips_init_sr); ++i)
 283                 write_sr(chips_init_sr[i].addr, chips_init_sr[i].data);
 284         for (i = 0; i < ARRAY_SIZE(chips_init_gr); ++i)
 285                 write_gr(chips_init_gr[i].addr, chips_init_gr[i].data);
 286         for (i = 0; i < ARRAY_SIZE(chips_init_ar); ++i)
 287                 write_ar(chips_init_ar[i].addr, chips_init_ar[i].data);
 288         for (i = 0; i < ARRAY_SIZE(chips_init_cr); ++i)
 289                 write_cr(chips_init_cr[i].addr, chips_init_cr[i].data);
 290         for (i = 0; i < ARRAY_SIZE(chips_init_fr); ++i)
 291                 write_fr(chips_init_fr[i].addr, chips_init_fr[i].data);
 292 }
 293 
 294 static const struct fb_fix_screeninfo chipsfb_fix = {
 295         .id =           "C&T 65550",
 296         .type =         FB_TYPE_PACKED_PIXELS,
 297         .visual =       FB_VISUAL_PSEUDOCOLOR,
 298         .accel =        FB_ACCEL_NONE,
 299         .line_length =  800,
 300 
 301 // FIXME: Assumes 1MB frame buffer, but 65550 supports 1MB or 2MB.
 302 // * "3500" PowerBook G3 (the original PB G3) has 2MB.
 303 // * 2400 has 1MB composed of 2 Mitsubishi M5M4V4265CTP DRAM chips.
 304 //   Motherboard actually supports 2MB -- there are two blank locations
 305 //   for a second pair of DRAMs.  (Thanks, Apple!)
 306 // * 3400 has 1MB (I think).  Don't know if it's expandable.
 307 // -- Tim Seufert
 308         .smem_len =     0x100000,       /* 1MB */
 309 };
 310 
 311 static const struct fb_var_screeninfo chipsfb_var = {
 312         .xres = 800,
 313         .yres = 600,
 314         .xres_virtual = 800,
 315         .yres_virtual = 600,
 316         .bits_per_pixel = 8,
 317         .red = { .length = 8 },
 318         .green = { .length = 8 },
 319         .blue = { .length = 8 },
 320         .height = -1,
 321         .width = -1,
 322         .vmode = FB_VMODE_NONINTERLACED,
 323         .pixclock = 10000,
 324         .left_margin = 16,
 325         .right_margin = 16,
 326         .upper_margin = 16,
 327         .lower_margin = 16,
 328         .hsync_len = 8,
 329         .vsync_len = 8,
 330 };
 331 
 332 static void init_chips(struct fb_info *p, unsigned long addr)
 333 {
 334         memset(p->screen_base, 0, 0x100000);
 335 
 336         p->fix = chipsfb_fix;
 337         p->fix.smem_start = addr;
 338 
 339         p->var = chipsfb_var;
 340 
 341         p->fbops = &chipsfb_ops;
 342         p->flags = FBINFO_DEFAULT;
 343 
 344         fb_alloc_cmap(&p->cmap, 256, 0);
 345 
 346         chips_hw_init();
 347 }
 348 
 349 static int chipsfb_pci_init(struct pci_dev *dp, const struct pci_device_id *ent)
 350 {
 351         struct fb_info *p;
 352         unsigned long addr;
 353         unsigned short cmd;
 354         int rc = -ENODEV;
 355 
 356         if (pci_enable_device(dp) < 0) {
 357                 dev_err(&dp->dev, "Cannot enable PCI device\n");
 358                 goto err_out;
 359         }
 360 
 361         if ((dp->resource[0].flags & IORESOURCE_MEM) == 0)
 362                 goto err_disable;
 363         addr = pci_resource_start(dp, 0);
 364         if (addr == 0)
 365                 goto err_disable;
 366 
 367         p = framebuffer_alloc(0, &dp->dev);
 368         if (p == NULL) {
 369                 rc = -ENOMEM;
 370                 goto err_disable;
 371         }
 372 
 373         if (pci_request_region(dp, 0, "chipsfb") != 0) {
 374                 dev_err(&dp->dev, "Cannot request framebuffer\n");
 375                 rc = -EBUSY;
 376                 goto err_release_fb;
 377         }
 378 
 379 #ifdef __BIG_ENDIAN
 380         addr += 0x800000;       // Use big-endian aperture
 381 #endif
 382 
 383         /* we should use pci_enable_device here, but,
 384            the device doesn't declare its I/O ports in its BARs
 385            so pci_enable_device won't turn on I/O responses */
 386         pci_read_config_word(dp, PCI_COMMAND, &cmd);
 387         cmd |= 3;       /* enable memory and IO space */
 388         pci_write_config_word(dp, PCI_COMMAND, cmd);
 389 
 390 #ifdef CONFIG_PMAC_BACKLIGHT
 391         /* turn on the backlight */
 392         mutex_lock(&pmac_backlight_mutex);
 393         if (pmac_backlight) {
 394                 pmac_backlight->props.power = FB_BLANK_UNBLANK;
 395                 backlight_update_status(pmac_backlight);
 396         }
 397         mutex_unlock(&pmac_backlight_mutex);
 398 #endif /* CONFIG_PMAC_BACKLIGHT */
 399 
 400 #ifdef CONFIG_PPC
 401         p->screen_base = ioremap_wc(addr, 0x200000);
 402 #else
 403         p->screen_base = ioremap(addr, 0x200000);
 404 #endif
 405         if (p->screen_base == NULL) {
 406                 dev_err(&dp->dev, "Cannot map framebuffer\n");
 407                 rc = -ENOMEM;
 408                 goto err_release_pci;
 409         }
 410 
 411         pci_set_drvdata(dp, p);
 412 
 413         init_chips(p, addr);
 414 
 415         if (register_framebuffer(p) < 0) {
 416                 dev_err(&dp->dev,"C&T 65550 framebuffer failed to register\n");
 417                 goto err_unmap;
 418         }
 419 
 420         dev_info(&dp->dev,"fb%d: Chips 65550 frame buffer"
 421                  " (%dK RAM detected)\n",
 422                  p->node, p->fix.smem_len / 1024);
 423 
 424         return 0;
 425 
 426  err_unmap:
 427         iounmap(p->screen_base);
 428  err_release_pci:
 429         pci_release_region(dp, 0);
 430  err_release_fb:
 431         framebuffer_release(p);
 432  err_disable:
 433  err_out:
 434         return rc;
 435 }
 436 
 437 static void chipsfb_remove(struct pci_dev *dp)
 438 {
 439         struct fb_info *p = pci_get_drvdata(dp);
 440 
 441         if (p->screen_base == NULL)
 442                 return;
 443         unregister_framebuffer(p);
 444         iounmap(p->screen_base);
 445         p->screen_base = NULL;
 446         pci_release_region(dp, 0);
 447 }
 448 
 449 #ifdef CONFIG_PM
 450 static int chipsfb_pci_suspend(struct pci_dev *pdev, pm_message_t state)
 451 {
 452         struct fb_info *p = pci_get_drvdata(pdev);
 453 
 454         if (state.event == pdev->dev.power.power_state.event)
 455                 return 0;
 456         if (!(state.event & PM_EVENT_SLEEP))
 457                 goto done;
 458 
 459         console_lock();
 460         chipsfb_blank(1, p);
 461         fb_set_suspend(p, 1);
 462         console_unlock();
 463  done:
 464         pdev->dev.power.power_state = state;
 465         return 0;
 466 }
 467 
 468 static int chipsfb_pci_resume(struct pci_dev *pdev)
 469 {
 470         struct fb_info *p = pci_get_drvdata(pdev);
 471 
 472         console_lock();
 473         fb_set_suspend(p, 0);
 474         chipsfb_blank(0, p);
 475         console_unlock();
 476 
 477         pdev->dev.power.power_state = PMSG_ON;
 478         return 0;
 479 }
 480 #endif /* CONFIG_PM */
 481 
 482 
 483 static struct pci_device_id chipsfb_pci_tbl[] = {
 484         { PCI_VENDOR_ID_CT, PCI_DEVICE_ID_CT_65550, PCI_ANY_ID, PCI_ANY_ID },
 485         { 0 }
 486 };
 487 
 488 MODULE_DEVICE_TABLE(pci, chipsfb_pci_tbl);
 489 
 490 static struct pci_driver chipsfb_driver = {
 491         .name =         "chipsfb",
 492         .id_table =     chipsfb_pci_tbl,
 493         .probe =        chipsfb_pci_init,
 494         .remove =       chipsfb_remove,
 495 #ifdef CONFIG_PM
 496         .suspend =      chipsfb_pci_suspend,
 497         .resume =       chipsfb_pci_resume,
 498 #endif
 499 };
 500 
 501 int __init chips_init(void)
 502 {
 503         if (fb_get_options("chipsfb", NULL))
 504                 return -ENODEV;
 505 
 506         return pci_register_driver(&chipsfb_driver);
 507 }
 508 
 509 module_init(chips_init);
 510 
 511 static void __exit chipsfb_exit(void)
 512 {
 513         pci_unregister_driver(&chipsfb_driver);
 514 }
 515 
 516 MODULE_LICENSE("GPL");

/* [<][>][^][v][top][bottom][index][help] */