root/drivers/video/fbdev/cg14.c

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

DEFINITIONS

This source file includes following definitions.
  1. __cg14_reset
  2. cg14_pan_display
  3. cg14_setcolreg
  4. cg14_mmap
  5. cg14_ioctl
  6. cg14_init_fix
  7. cg14_unmap_regs
  8. cg14_probe
  9. cg14_remove
  10. cg14_init
  11. cg14_exit

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /* cg14.c: CGFOURTEEN frame buffer driver
   3  *
   4  * Copyright (C) 2003, 2006 David S. Miller (davem@davemloft.net)
   5  * Copyright (C) 1996,1998 Jakub Jelinek (jj@ultra.linux.cz)
   6  * Copyright (C) 1995 Miguel de Icaza (miguel@nuclecu.unam.mx)
   7  *
   8  * Driver layout based loosely on tgafb.c, see that file for credits.
   9  */
  10 
  11 #include <linux/module.h>
  12 #include <linux/kernel.h>
  13 #include <linux/errno.h>
  14 #include <linux/string.h>
  15 #include <linux/delay.h>
  16 #include <linux/init.h>
  17 #include <linux/fb.h>
  18 #include <linux/mm.h>
  19 #include <linux/uaccess.h>
  20 #include <linux/of_device.h>
  21 
  22 #include <asm/io.h>
  23 #include <asm/fbio.h>
  24 
  25 #include "sbuslib.h"
  26 
  27 /*
  28  * Local functions.
  29  */
  30 
  31 static int cg14_setcolreg(unsigned, unsigned, unsigned, unsigned,
  32                          unsigned, struct fb_info *);
  33 
  34 static int cg14_mmap(struct fb_info *, struct vm_area_struct *);
  35 static int cg14_ioctl(struct fb_info *, unsigned int, unsigned long);
  36 static int cg14_pan_display(struct fb_var_screeninfo *, struct fb_info *);
  37 
  38 /*
  39  *  Frame buffer operations
  40  */
  41 
  42 static struct fb_ops cg14_ops = {
  43         .owner                  = THIS_MODULE,
  44         .fb_setcolreg           = cg14_setcolreg,
  45         .fb_pan_display         = cg14_pan_display,
  46         .fb_fillrect            = cfb_fillrect,
  47         .fb_copyarea            = cfb_copyarea,
  48         .fb_imageblit           = cfb_imageblit,
  49         .fb_mmap                = cg14_mmap,
  50         .fb_ioctl               = cg14_ioctl,
  51 #ifdef CONFIG_COMPAT
  52         .fb_compat_ioctl        = sbusfb_compat_ioctl,
  53 #endif
  54 };
  55 
  56 #define CG14_MCR_INTENABLE_SHIFT        7
  57 #define CG14_MCR_INTENABLE_MASK         0x80
  58 #define CG14_MCR_VIDENABLE_SHIFT        6
  59 #define CG14_MCR_VIDENABLE_MASK         0x40
  60 #define CG14_MCR_PIXMODE_SHIFT          4
  61 #define CG14_MCR_PIXMODE_MASK           0x30
  62 #define CG14_MCR_TMR_SHIFT              2
  63 #define CG14_MCR_TMR_MASK               0x0c
  64 #define CG14_MCR_TMENABLE_SHIFT         1
  65 #define CG14_MCR_TMENABLE_MASK          0x02
  66 #define CG14_MCR_RESET_SHIFT            0
  67 #define CG14_MCR_RESET_MASK             0x01
  68 #define CG14_REV_REVISION_SHIFT         4
  69 #define CG14_REV_REVISION_MASK          0xf0
  70 #define CG14_REV_IMPL_SHIFT             0
  71 #define CG14_REV_IMPL_MASK              0x0f
  72 #define CG14_VBR_FRAMEBASE_SHIFT        12
  73 #define CG14_VBR_FRAMEBASE_MASK         0x00fff000
  74 #define CG14_VMCR1_SETUP_SHIFT          0
  75 #define CG14_VMCR1_SETUP_MASK           0x000001ff
  76 #define CG14_VMCR1_VCONFIG_SHIFT        9
  77 #define CG14_VMCR1_VCONFIG_MASK         0x00000e00
  78 #define CG14_VMCR2_REFRESH_SHIFT        0
  79 #define CG14_VMCR2_REFRESH_MASK         0x00000001
  80 #define CG14_VMCR2_TESTROWCNT_SHIFT     1
  81 #define CG14_VMCR2_TESTROWCNT_MASK      0x00000002
  82 #define CG14_VMCR2_FBCONFIG_SHIFT       2
  83 #define CG14_VMCR2_FBCONFIG_MASK        0x0000000c
  84 #define CG14_VCR_REFRESHREQ_SHIFT       0
  85 #define CG14_VCR_REFRESHREQ_MASK        0x000003ff
  86 #define CG14_VCR1_REFRESHENA_SHIFT      10
  87 #define CG14_VCR1_REFRESHENA_MASK       0x00000400
  88 #define CG14_VCA_CAD_SHIFT              0
  89 #define CG14_VCA_CAD_MASK               0x000003ff
  90 #define CG14_VCA_VERS_SHIFT             10
  91 #define CG14_VCA_VERS_MASK              0x00000c00
  92 #define CG14_VCA_RAMSPEED_SHIFT         12
  93 #define CG14_VCA_RAMSPEED_MASK          0x00001000
  94 #define CG14_VCA_8MB_SHIFT              13
  95 #define CG14_VCA_8MB_MASK               0x00002000
  96 
  97 #define CG14_MCR_PIXMODE_8              0
  98 #define CG14_MCR_PIXMODE_16             2
  99 #define CG14_MCR_PIXMODE_32             3
 100 
 101 struct cg14_regs{
 102         u8 mcr; /* Master Control Reg */
 103         u8 ppr; /* Packed Pixel Reg */
 104         u8 tms[2];      /* Test Mode Status Regs */
 105         u8 msr; /* Master Status Reg */
 106         u8 fsr; /* Fault Status Reg */
 107         u8 rev; /* Revision & Impl */
 108         u8 ccr; /* Clock Control Reg */
 109         u32 tmr;        /* Test Mode Read Back */
 110         u8 mod; /* Monitor Operation Data Reg */
 111         u8 acr; /* Aux Control */
 112         u8 xxx0[6];
 113         u16 hct;        /* Hor Counter */
 114         u16 vct;        /* Vert Counter */
 115         u16 hbs;        /* Hor Blank Start */
 116         u16 hbc;        /* Hor Blank Clear */
 117         u16 hss;        /* Hor Sync Start */
 118         u16 hsc;        /* Hor Sync Clear */
 119         u16 csc;        /* Composite Sync Clear */
 120         u16 vbs;        /* Vert Blank Start */
 121         u16 vbc;        /* Vert Blank Clear */
 122         u16 vss;        /* Vert Sync Start */
 123         u16 vsc;        /* Vert Sync Clear */
 124         u16 xcs;
 125         u16 xcc;
 126         u16 fsa;        /* Fault Status Address */
 127         u16 adr;        /* Address Registers */
 128         u8 xxx1[0xce];
 129         u8 pcg[0x100]; /* Pixel Clock Generator */
 130         u32 vbr;        /* Frame Base Row */
 131         u32 vmcr;       /* VBC Master Control */
 132         u32 vcr;        /* VBC refresh */
 133         u32 vca;        /* VBC Config */
 134 };
 135 
 136 #define CG14_CCR_ENABLE 0x04
 137 #define CG14_CCR_SELECT 0x02    /* HW/Full screen */
 138 
 139 struct cg14_cursor {
 140         u32 cpl0[32];   /* Enable plane 0 */
 141         u32 cpl1[32];  /* Color selection plane */
 142         u8 ccr; /* Cursor Control Reg */
 143         u8 xxx0[3];
 144         u16 cursx;      /* Cursor x,y position */
 145         u16 cursy;      /* Cursor x,y position */
 146         u32 color0;
 147         u32 color1;
 148         u32 xxx1[0x1bc];
 149         u32 cpl0i[32];  /* Enable plane 0 autoinc */
 150         u32 cpl1i[32]; /* Color selection autoinc */
 151 };
 152 
 153 struct cg14_dac {
 154         u8 addr;        /* Address Register */
 155         u8 xxx0[255];
 156         u8 glut;        /* Gamma table */
 157         u8 xxx1[255];
 158         u8 select;      /* Register Select */
 159         u8 xxx2[255];
 160         u8 mode;        /* Mode Register */
 161 };
 162 
 163 struct cg14_xlut{
 164         u8 x_xlut [256];
 165         u8 x_xlutd [256];
 166         u8 xxx0[0x600];
 167         u8 x_xlut_inc [256];
 168         u8 x_xlutd_inc [256];
 169 };
 170 
 171 /* Color look up table (clut) */
 172 /* Each one of these arrays hold the color lookup table (for 256
 173  * colors) for each MDI page (I assume then there should be 4 MDI
 174  * pages, I still wonder what they are.  I have seen NeXTStep split
 175  * the screen in four parts, while operating in 24 bits mode.  Each
 176  * integer holds 4 values: alpha value (transparency channel, thanks
 177  * go to John Stone (johns@umr.edu) from OpenBSD), red, green and blue
 178  *
 179  * I currently use the clut instead of the Xlut
 180  */
 181 struct cg14_clut {
 182         u32 c_clut [256];
 183         u32 c_clutd [256];    /* i wonder what the 'd' is for */
 184         u32 c_clut_inc [256];
 185         u32 c_clutd_inc [256];
 186 };
 187 
 188 #define CG14_MMAP_ENTRIES       16
 189 
 190 struct cg14_par {
 191         spinlock_t              lock;
 192         struct cg14_regs        __iomem *regs;
 193         struct cg14_clut        __iomem *clut;
 194         struct cg14_cursor      __iomem *cursor;
 195 
 196         u32                     flags;
 197 #define CG14_FLAG_BLANKED       0x00000001
 198 
 199         unsigned long           iospace;
 200 
 201         struct sbus_mmap_map    mmap_map[CG14_MMAP_ENTRIES];
 202 
 203         int                     mode;
 204         int                     ramsize;
 205 };
 206 
 207 static void __cg14_reset(struct cg14_par *par)
 208 {
 209         struct cg14_regs __iomem *regs = par->regs;
 210         u8 val;
 211 
 212         val = sbus_readb(&regs->mcr);
 213         val &= ~(CG14_MCR_PIXMODE_MASK);
 214         sbus_writeb(val, &regs->mcr);
 215 }
 216 
 217 static int cg14_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
 218 {
 219         struct cg14_par *par = (struct cg14_par *) info->par;
 220         unsigned long flags;
 221 
 222         /* We just use this to catch switches out of
 223          * graphics mode.
 224          */
 225         spin_lock_irqsave(&par->lock, flags);
 226         __cg14_reset(par);
 227         spin_unlock_irqrestore(&par->lock, flags);
 228 
 229         if (var->xoffset || var->yoffset || var->vmode)
 230                 return -EINVAL;
 231         return 0;
 232 }
 233 
 234 /**
 235  *      cg14_setcolreg - Optional function. Sets a color register.
 236  *      @regno: boolean, 0 copy local, 1 get_user() function
 237  *      @red: frame buffer colormap structure
 238  *      @green: The green value which can be up to 16 bits wide
 239  *      @blue:  The blue value which can be up to 16 bits wide.
 240  *      @transp: If supported the alpha value which can be up to 16 bits wide.
 241  *      @info: frame buffer info structure
 242  */
 243 static int cg14_setcolreg(unsigned regno,
 244                           unsigned red, unsigned green, unsigned blue,
 245                           unsigned transp, struct fb_info *info)
 246 {
 247         struct cg14_par *par = (struct cg14_par *) info->par;
 248         struct cg14_clut __iomem *clut = par->clut;
 249         unsigned long flags;
 250         u32 val;
 251 
 252         if (regno >= 256)
 253                 return 1;
 254 
 255         red >>= 8;
 256         green >>= 8;
 257         blue >>= 8;
 258         val = (red | (green << 8) | (blue << 16));
 259 
 260         spin_lock_irqsave(&par->lock, flags);
 261         sbus_writel(val, &clut->c_clut[regno]);
 262         spin_unlock_irqrestore(&par->lock, flags);
 263 
 264         return 0;
 265 }
 266 
 267 static int cg14_mmap(struct fb_info *info, struct vm_area_struct *vma)
 268 {
 269         struct cg14_par *par = (struct cg14_par *) info->par;
 270 
 271         return sbusfb_mmap_helper(par->mmap_map,
 272                                   info->fix.smem_start, info->fix.smem_len,
 273                                   par->iospace, vma);
 274 }
 275 
 276 static int cg14_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
 277 {
 278         struct cg14_par *par = (struct cg14_par *) info->par;
 279         struct cg14_regs __iomem *regs = par->regs;
 280         struct mdi_cfginfo kmdi, __user *mdii;
 281         unsigned long flags;
 282         int cur_mode, mode, ret = 0;
 283 
 284         switch (cmd) {
 285         case MDI_RESET:
 286                 spin_lock_irqsave(&par->lock, flags);
 287                 __cg14_reset(par);
 288                 spin_unlock_irqrestore(&par->lock, flags);
 289                 break;
 290 
 291         case MDI_GET_CFGINFO:
 292                 memset(&kmdi, 0, sizeof(kmdi));
 293 
 294                 spin_lock_irqsave(&par->lock, flags);
 295                 kmdi.mdi_type = FBTYPE_MDICOLOR;
 296                 kmdi.mdi_height = info->var.yres;
 297                 kmdi.mdi_width = info->var.xres;
 298                 kmdi.mdi_mode = par->mode;
 299                 kmdi.mdi_pixfreq = 72; /* FIXME */
 300                 kmdi.mdi_size = par->ramsize;
 301                 spin_unlock_irqrestore(&par->lock, flags);
 302 
 303                 mdii = (struct mdi_cfginfo __user *) arg;
 304                 if (copy_to_user(mdii, &kmdi, sizeof(kmdi)))
 305                         ret = -EFAULT;
 306                 break;
 307 
 308         case MDI_SET_PIXELMODE:
 309                 if (get_user(mode, (int __user *) arg)) {
 310                         ret = -EFAULT;
 311                         break;
 312                 }
 313 
 314                 spin_lock_irqsave(&par->lock, flags);
 315                 cur_mode = sbus_readb(&regs->mcr);
 316                 cur_mode &= ~CG14_MCR_PIXMODE_MASK;
 317                 switch(mode) {
 318                 case MDI_32_PIX:
 319                         cur_mode |= (CG14_MCR_PIXMODE_32 <<
 320                                      CG14_MCR_PIXMODE_SHIFT);
 321                         break;
 322 
 323                 case MDI_16_PIX:
 324                         cur_mode |= (CG14_MCR_PIXMODE_16 <<
 325                                      CG14_MCR_PIXMODE_SHIFT);
 326                         break;
 327 
 328                 case MDI_8_PIX:
 329                         break;
 330 
 331                 default:
 332                         ret = -ENOSYS;
 333                         break;
 334                 }
 335                 if (!ret) {
 336                         sbus_writeb(cur_mode, &regs->mcr);
 337                         par->mode = mode;
 338                 }
 339                 spin_unlock_irqrestore(&par->lock, flags);
 340                 break;
 341 
 342         default:
 343                 ret = sbusfb_ioctl_helper(cmd, arg, info,
 344                                           FBTYPE_MDICOLOR, 8,
 345                                           info->fix.smem_len);
 346                 break;
 347         }
 348 
 349         return ret;
 350 }
 351 
 352 /*
 353  *  Initialisation
 354  */
 355 
 356 static void cg14_init_fix(struct fb_info *info, int linebytes,
 357                           struct device_node *dp)
 358 {
 359         snprintf(info->fix.id, sizeof(info->fix.id), "%pOFn", dp);
 360 
 361         info->fix.type = FB_TYPE_PACKED_PIXELS;
 362         info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
 363 
 364         info->fix.line_length = linebytes;
 365 
 366         info->fix.accel = FB_ACCEL_SUN_CG14;
 367 }
 368 
 369 static struct sbus_mmap_map __cg14_mmap_map[CG14_MMAP_ENTRIES] = {
 370         {
 371                 .voff   = CG14_REGS,
 372                 .poff   = 0x80000000,
 373                 .size   = 0x1000
 374         },
 375         {
 376                 .voff   = CG14_XLUT,
 377                 .poff   = 0x80003000,
 378                 .size   = 0x1000
 379         },
 380         {
 381                 .voff   = CG14_CLUT1,
 382                 .poff   = 0x80004000,
 383                 .size   = 0x1000
 384         },
 385         {
 386                 .voff   = CG14_CLUT2,
 387                 .poff   = 0x80005000,
 388                 .size   = 0x1000
 389         },
 390         {
 391                 .voff   = CG14_CLUT3,
 392                 .poff   = 0x80006000,
 393                 .size   = 0x1000
 394         },
 395         {
 396                 .voff   = CG3_MMAP_OFFSET - 0x7000,
 397                 .poff   = 0x80000000,
 398                 .size   = 0x7000
 399         },
 400         {
 401                 .voff   = CG3_MMAP_OFFSET,
 402                 .poff   = 0x00000000,
 403                 .size   = SBUS_MMAP_FBSIZE(1)
 404         },
 405         {
 406                 .voff   = MDI_CURSOR_MAP,
 407                 .poff   = 0x80001000,
 408                 .size   = 0x1000
 409         },
 410         {
 411                 .voff   = MDI_CHUNKY_BGR_MAP,
 412                 .poff   = 0x01000000,
 413                 .size   = 0x400000
 414         },
 415         {
 416                 .voff   = MDI_PLANAR_X16_MAP,
 417                 .poff   = 0x02000000,
 418                 .size   = 0x200000
 419         },
 420         {
 421                 .voff   = MDI_PLANAR_C16_MAP,
 422                 .poff   = 0x02800000,
 423                 .size   = 0x200000
 424         },
 425         {
 426                 .voff   = MDI_PLANAR_X32_MAP,
 427                 .poff   = 0x03000000,
 428                 .size   = 0x100000
 429         },
 430         {
 431                 .voff   = MDI_PLANAR_B32_MAP,
 432                 .poff   = 0x03400000,
 433                 .size   = 0x100000
 434         },
 435         {
 436                 .voff   = MDI_PLANAR_G32_MAP,
 437                 .poff   = 0x03800000,
 438                 .size   = 0x100000
 439         },
 440         {
 441                 .voff   = MDI_PLANAR_R32_MAP,
 442                 .poff   = 0x03c00000,
 443                 .size   = 0x100000
 444         },
 445         { .size = 0 }
 446 };
 447 
 448 static void cg14_unmap_regs(struct platform_device *op, struct fb_info *info,
 449                             struct cg14_par *par)
 450 {
 451         if (par->regs)
 452                 of_iounmap(&op->resource[0],
 453                            par->regs, sizeof(struct cg14_regs));
 454         if (par->clut)
 455                 of_iounmap(&op->resource[0],
 456                            par->clut, sizeof(struct cg14_clut));
 457         if (par->cursor)
 458                 of_iounmap(&op->resource[0],
 459                            par->cursor, sizeof(struct cg14_cursor));
 460         if (info->screen_base)
 461                 of_iounmap(&op->resource[1],
 462                            info->screen_base, info->fix.smem_len);
 463 }
 464 
 465 static int cg14_probe(struct platform_device *op)
 466 {
 467         struct device_node *dp = op->dev.of_node;
 468         struct fb_info *info;
 469         struct cg14_par *par;
 470         int is_8mb, linebytes, i, err;
 471 
 472         info = framebuffer_alloc(sizeof(struct cg14_par), &op->dev);
 473 
 474         err = -ENOMEM;
 475         if (!info)
 476                 goto out_err;
 477         par = info->par;
 478 
 479         spin_lock_init(&par->lock);
 480 
 481         sbusfb_fill_var(&info->var, dp, 8);
 482         info->var.red.length = 8;
 483         info->var.green.length = 8;
 484         info->var.blue.length = 8;
 485 
 486         linebytes = of_getintprop_default(dp, "linebytes",
 487                                           info->var.xres);
 488         info->fix.smem_len = PAGE_ALIGN(linebytes * info->var.yres);
 489 
 490         if (of_node_name_eq(dp->parent, "sbus") ||
 491             of_node_name_eq(dp->parent, "sbi")) {
 492                 info->fix.smem_start = op->resource[0].start;
 493                 par->iospace = op->resource[0].flags & IORESOURCE_BITS;
 494         } else {
 495                 info->fix.smem_start = op->resource[1].start;
 496                 par->iospace = op->resource[0].flags & IORESOURCE_BITS;
 497         }
 498 
 499         par->regs = of_ioremap(&op->resource[0], 0,
 500                                sizeof(struct cg14_regs), "cg14 regs");
 501         par->clut = of_ioremap(&op->resource[0], CG14_CLUT1,
 502                                sizeof(struct cg14_clut), "cg14 clut");
 503         par->cursor = of_ioremap(&op->resource[0], CG14_CURSORREGS,
 504                                  sizeof(struct cg14_cursor), "cg14 cursor");
 505 
 506         info->screen_base = of_ioremap(&op->resource[1], 0,
 507                                        info->fix.smem_len, "cg14 ram");
 508 
 509         if (!par->regs || !par->clut || !par->cursor || !info->screen_base)
 510                 goto out_unmap_regs;
 511 
 512         is_8mb = (((op->resource[1].end - op->resource[1].start) + 1) ==
 513                   (8 * 1024 * 1024));
 514 
 515         BUILD_BUG_ON(sizeof(par->mmap_map) != sizeof(__cg14_mmap_map));
 516                 
 517         memcpy(&par->mmap_map, &__cg14_mmap_map, sizeof(par->mmap_map));
 518 
 519         for (i = 0; i < CG14_MMAP_ENTRIES; i++) {
 520                 struct sbus_mmap_map *map = &par->mmap_map[i];
 521 
 522                 if (!map->size)
 523                         break;
 524                 if (map->poff & 0x80000000)
 525                         map->poff = (map->poff & 0x7fffffff) +
 526                                 (op->resource[0].start -
 527                                  op->resource[1].start);
 528                 if (is_8mb &&
 529                     map->size >= 0x100000 &&
 530                     map->size <= 0x400000)
 531                         map->size *= 2;
 532         }
 533 
 534         par->mode = MDI_8_PIX;
 535         par->ramsize = (is_8mb ? 0x800000 : 0x400000);
 536 
 537         info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
 538         info->fbops = &cg14_ops;
 539 
 540         __cg14_reset(par);
 541 
 542         if (fb_alloc_cmap(&info->cmap, 256, 0))
 543                 goto out_unmap_regs;
 544 
 545         fb_set_cmap(&info->cmap, info);
 546 
 547         cg14_init_fix(info, linebytes, dp);
 548 
 549         err = register_framebuffer(info);
 550         if (err < 0)
 551                 goto out_dealloc_cmap;
 552 
 553         dev_set_drvdata(&op->dev, info);
 554 
 555         printk(KERN_INFO "%pOF: cgfourteen at %lx:%lx, %dMB\n",
 556                dp,
 557                par->iospace, info->fix.smem_start,
 558                par->ramsize >> 20);
 559 
 560         return 0;
 561 
 562 out_dealloc_cmap:
 563         fb_dealloc_cmap(&info->cmap);
 564 
 565 out_unmap_regs:
 566         cg14_unmap_regs(op, info, par);
 567         framebuffer_release(info);
 568 
 569 out_err:
 570         return err;
 571 }
 572 
 573 static int cg14_remove(struct platform_device *op)
 574 {
 575         struct fb_info *info = dev_get_drvdata(&op->dev);
 576         struct cg14_par *par = info->par;
 577 
 578         unregister_framebuffer(info);
 579         fb_dealloc_cmap(&info->cmap);
 580 
 581         cg14_unmap_regs(op, info, par);
 582 
 583         framebuffer_release(info);
 584 
 585         return 0;
 586 }
 587 
 588 static const struct of_device_id cg14_match[] = {
 589         {
 590                 .name = "cgfourteen",
 591         },
 592         {},
 593 };
 594 MODULE_DEVICE_TABLE(of, cg14_match);
 595 
 596 static struct platform_driver cg14_driver = {
 597         .driver = {
 598                 .name = "cg14",
 599                 .of_match_table = cg14_match,
 600         },
 601         .probe          = cg14_probe,
 602         .remove         = cg14_remove,
 603 };
 604 
 605 static int __init cg14_init(void)
 606 {
 607         if (fb_get_options("cg14fb", NULL))
 608                 return -ENODEV;
 609 
 610         return platform_driver_register(&cg14_driver);
 611 }
 612 
 613 static void __exit cg14_exit(void)
 614 {
 615         platform_driver_unregister(&cg14_driver);
 616 }
 617 
 618 module_init(cg14_init);
 619 module_exit(cg14_exit);
 620 
 621 MODULE_DESCRIPTION("framebuffer driver for CGfourteen chipsets");
 622 MODULE_AUTHOR("David S. Miller <davem@davemloft.net>");
 623 MODULE_VERSION("2.0");
 624 MODULE_LICENSE("GPL");

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