root/drivers/video/fbdev/arcfb.c

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

DEFINITIONS

This source file includes following definitions.
  1. ks108_writeb_ctl
  2. ks108_writeb_mainctl
  3. ks108_readb_ctl2
  4. ks108_writeb_data
  5. ks108_set_start_line
  6. ks108_set_yaddr
  7. ks108_set_xaddr
  8. ks108_clear_lcd
  9. arcfb_open
  10. arcfb_release
  11. arcfb_pan_display
  12. arcfb_interrupt
  13. arcfb_lcd_update_page
  14. arcfb_lcd_update_vert
  15. arcfb_lcd_update_horiz
  16. arcfb_lcd_update
  17. arcfb_fillrect
  18. arcfb_copyarea
  19. arcfb_imageblit
  20. arcfb_ioctl
  21. arcfb_write
  22. arcfb_probe
  23. arcfb_remove
  24. arcfb_init
  25. arcfb_exit

   1 /*
   2  * linux/drivers/video/arcfb.c -- FB driver for Arc monochrome LCD board
   3  *
   4  * Copyright (C) 2005, Jaya Kumar <jayalk@intworks.biz>
   5  *
   6  * This file is subject to the terms and conditions of the GNU General Public
   7  * License. See the file COPYING in the main directory of this archive for
   8  * more details.
   9  *
  10  * Layout is based on skeletonfb.c by James Simmons and Geert Uytterhoeven.
  11  *
  12  * This driver was written to be used with the Arc LCD board. Arc uses a
  13  * set of KS108 chips that control individual 64x64 LCD matrices. The board
  14  * can be paneled in a variety of setups such as 2x1=128x64, 4x4=256x256 and
  15  * so on. The interface between the board and the host is TTL based GPIO. The
  16  * GPIO requirements are 8 writable data lines and 4+n lines for control. On a
  17  * GPIO-less system, the board can be tested by connecting the respective sigs
  18  * up to a parallel port connector. The driver requires the IO addresses for
  19  * data and control GPIO at load time. It is unable to probe for the
  20  * existence of the LCD so it must be told at load time whether it should
  21  * be enabled or not.
  22  *
  23  * Todo:
  24  * - testing with 4x4
  25  * - testing with interrupt hw
  26  *
  27  * General notes:
  28  * - User must set tuhold. It's in microseconds. According to the 108 spec,
  29  *   the hold time is supposed to be at least 1 microsecond.
  30  * - User must set num_cols=x num_rows=y, eg: x=2 means 128
  31  * - User must set arcfb_enable=1 to enable it
  32  * - User must set dio_addr=0xIOADDR cio_addr=0xIOADDR
  33  *
  34  */
  35 
  36 #include <linux/module.h>
  37 #include <linux/kernel.h>
  38 #include <linux/errno.h>
  39 #include <linux/string.h>
  40 #include <linux/mm.h>
  41 #include <linux/vmalloc.h>
  42 #include <linux/delay.h>
  43 #include <linux/interrupt.h>
  44 #include <linux/fb.h>
  45 #include <linux/init.h>
  46 #include <linux/arcfb.h>
  47 #include <linux/platform_device.h>
  48 
  49 #include <linux/uaccess.h>
  50 
  51 #define floor8(a) (a&(~0x07))
  52 #define floorXres(a,xres) (a&(~(xres - 1)))
  53 #define iceil8(a) (((int)((a+7)/8))*8)
  54 #define ceil64(a) (a|0x3F)
  55 #define ceilXres(a,xres) (a|(xres - 1))
  56 
  57 /* ks108 chipset specific defines and code */
  58 
  59 #define KS_SET_DPY_START_LINE   0xC0
  60 #define KS_SET_PAGE_NUM         0xB8
  61 #define KS_SET_X                0x40
  62 #define KS_CEHI                 0x01
  63 #define KS_CELO                 0x00
  64 #define KS_SEL_CMD              0x08
  65 #define KS_SEL_DATA             0x00
  66 #define KS_DPY_ON               0x3F
  67 #define KS_DPY_OFF              0x3E
  68 #define KS_INTACK               0x40
  69 #define KS_CLRINT               0x02
  70 
  71 struct arcfb_par {
  72         unsigned long dio_addr;
  73         unsigned long cio_addr;
  74         unsigned long c2io_addr;
  75         atomic_t ref_count;
  76         unsigned char cslut[9];
  77         struct fb_info *info;
  78         unsigned int irq;
  79         spinlock_t lock;
  80 };
  81 
  82 static const struct fb_fix_screeninfo arcfb_fix = {
  83         .id =           "arcfb",
  84         .type =         FB_TYPE_PACKED_PIXELS,
  85         .visual =       FB_VISUAL_MONO01,
  86         .xpanstep =     0,
  87         .ypanstep =     1,
  88         .ywrapstep =    0,
  89         .accel =        FB_ACCEL_NONE,
  90 };
  91 
  92 static const struct fb_var_screeninfo arcfb_var = {
  93         .xres           = 128,
  94         .yres           = 64,
  95         .xres_virtual   = 128,
  96         .yres_virtual   = 64,
  97         .bits_per_pixel = 1,
  98         .nonstd         = 1,
  99 };
 100 
 101 static unsigned long num_cols;
 102 static unsigned long num_rows;
 103 static unsigned long dio_addr;
 104 static unsigned long cio_addr;
 105 static unsigned long c2io_addr;
 106 static unsigned long splashval;
 107 static unsigned long tuhold;
 108 static unsigned int nosplash;
 109 static unsigned int arcfb_enable;
 110 static unsigned int irq;
 111 
 112 static DECLARE_WAIT_QUEUE_HEAD(arcfb_waitq);
 113 
 114 static void ks108_writeb_ctl(struct arcfb_par *par,
 115                                 unsigned int chipindex, unsigned char value)
 116 {
 117         unsigned char chipselval = par->cslut[chipindex];
 118 
 119         outb(chipselval|KS_CEHI|KS_SEL_CMD, par->cio_addr);
 120         outb(value, par->dio_addr);
 121         udelay(tuhold);
 122         outb(chipselval|KS_CELO|KS_SEL_CMD, par->cio_addr);
 123 }
 124 
 125 static void ks108_writeb_mainctl(struct arcfb_par *par, unsigned char value)
 126 {
 127 
 128         outb(value, par->cio_addr);
 129         udelay(tuhold);
 130 }
 131 
 132 static unsigned char ks108_readb_ctl2(struct arcfb_par *par)
 133 {
 134         return inb(par->c2io_addr);
 135 }
 136 
 137 static void ks108_writeb_data(struct arcfb_par *par,
 138                                 unsigned int chipindex, unsigned char value)
 139 {
 140         unsigned char chipselval = par->cslut[chipindex];
 141 
 142         outb(chipselval|KS_CEHI|KS_SEL_DATA, par->cio_addr);
 143         outb(value, par->dio_addr);
 144         udelay(tuhold);
 145         outb(chipselval|KS_CELO|KS_SEL_DATA, par->cio_addr);
 146 }
 147 
 148 static void ks108_set_start_line(struct arcfb_par *par,
 149                                 unsigned int chipindex, unsigned char y)
 150 {
 151         ks108_writeb_ctl(par, chipindex, KS_SET_DPY_START_LINE|y);
 152 }
 153 
 154 static void ks108_set_yaddr(struct arcfb_par *par,
 155                                 unsigned int chipindex, unsigned char y)
 156 {
 157         ks108_writeb_ctl(par, chipindex, KS_SET_PAGE_NUM|y);
 158 }
 159 
 160 static void ks108_set_xaddr(struct arcfb_par *par,
 161                                 unsigned int chipindex, unsigned char x)
 162 {
 163         ks108_writeb_ctl(par, chipindex, KS_SET_X|x);
 164 }
 165 
 166 static void ks108_clear_lcd(struct arcfb_par *par, unsigned int chipindex)
 167 {
 168         int i,j;
 169 
 170         for (i = 0; i <= 8; i++) {
 171                 ks108_set_yaddr(par, chipindex, i);
 172                 ks108_set_xaddr(par, chipindex, 0);
 173                 for (j = 0; j < 64; j++) {
 174                         ks108_writeb_data(par, chipindex,
 175                                 (unsigned char) splashval);
 176                 }
 177         }
 178 }
 179 
 180 /* main arcfb functions */
 181 
 182 static int arcfb_open(struct fb_info *info, int user)
 183 {
 184         struct arcfb_par *par = info->par;
 185 
 186         atomic_inc(&par->ref_count);
 187         return 0;
 188 }
 189 
 190 static int arcfb_release(struct fb_info *info, int user)
 191 {
 192         struct arcfb_par *par = info->par;
 193         int count = atomic_read(&par->ref_count);
 194 
 195         if (!count)
 196                 return -EINVAL;
 197         atomic_dec(&par->ref_count);
 198         return 0;
 199 }
 200 
 201 static int arcfb_pan_display(struct fb_var_screeninfo *var,
 202                                 struct fb_info *info)
 203 {
 204         int i;
 205         struct arcfb_par *par = info->par;
 206 
 207         if ((var->vmode & FB_VMODE_YWRAP) && (var->yoffset < 64)
 208                 && (info->var.yres <= 64)) {
 209                 for (i = 0; i < num_cols; i++) {
 210                         ks108_set_start_line(par, i, var->yoffset);
 211                 }
 212                 info->var.yoffset = var->yoffset;
 213                 return 0;
 214         }
 215 
 216         return -EINVAL;
 217 }
 218 
 219 static irqreturn_t arcfb_interrupt(int vec, void *dev_instance)
 220 {
 221         struct fb_info *info = dev_instance;
 222         unsigned char ctl2status;
 223         struct arcfb_par *par = info->par;
 224 
 225         ctl2status = ks108_readb_ctl2(par);
 226 
 227         if (!(ctl2status & KS_INTACK)) /* not arc generated interrupt */
 228                 return IRQ_NONE;
 229 
 230         ks108_writeb_mainctl(par, KS_CLRINT);
 231 
 232         spin_lock(&par->lock);
 233         if (waitqueue_active(&arcfb_waitq)) {
 234                 wake_up(&arcfb_waitq);
 235         }
 236         spin_unlock(&par->lock);
 237 
 238         return IRQ_HANDLED;
 239 }
 240 
 241 /*
 242  * here we handle a specific page on the lcd. the complexity comes from
 243  * the fact that the fb is laidout in 8xX vertical columns. we extract
 244  * each write of 8 vertical pixels. then we shift out as we move along
 245  * X. That's what rightshift does. bitmask selects the desired input bit.
 246  */
 247 static void arcfb_lcd_update_page(struct arcfb_par *par, unsigned int upper,
 248                 unsigned int left, unsigned int right, unsigned int distance)
 249 {
 250         unsigned char *src;
 251         unsigned int xindex, yindex, chipindex, linesize;
 252         int i;
 253         unsigned char val;
 254         unsigned char bitmask, rightshift;
 255 
 256         xindex = left >> 6;
 257         yindex = upper >> 6;
 258         chipindex = (xindex + (yindex*num_cols));
 259 
 260         ks108_set_yaddr(par, chipindex, upper/8);
 261 
 262         linesize = par->info->var.xres/8;
 263         src = (unsigned char __force *) par->info->screen_base + (left/8) +
 264                 (upper * linesize);
 265         ks108_set_xaddr(par, chipindex, left);
 266 
 267         bitmask=1;
 268         rightshift=0;
 269         while (left <= right) {
 270                 val = 0;
 271                 for (i = 0; i < 8; i++) {
 272                         if ( i > rightshift) {
 273                                 val |= (*(src + (i*linesize)) & bitmask)
 274                                                 << (i - rightshift);
 275                         } else {
 276                                 val |= (*(src + (i*linesize)) & bitmask)
 277                                                  >> (rightshift - i);
 278                         }
 279                 }
 280                 ks108_writeb_data(par, chipindex, val);
 281                 left++;
 282                 if (bitmask == 0x80) {
 283                         bitmask = 1;
 284                         src++;
 285                         rightshift=0;
 286                 } else {
 287                         bitmask <<= 1;
 288                         rightshift++;
 289                 }
 290         }
 291 }
 292 
 293 /*
 294  * here we handle the entire vertical page of the update. we write across
 295  * lcd chips. update_page uses the upper/left values to decide which
 296  * chip to select for the right. upper is needed for setting the page
 297  * desired for the write.
 298  */
 299 static void arcfb_lcd_update_vert(struct arcfb_par *par, unsigned int top,
 300                 unsigned int bottom, unsigned int left, unsigned int right)
 301 {
 302         unsigned int distance, upper, lower;
 303 
 304         distance = (bottom - top) + 1;
 305         upper = top;
 306         lower = top + 7;
 307 
 308         while (distance > 0) {
 309                 distance -= 8;
 310                 arcfb_lcd_update_page(par, upper, left, right, 8);
 311                 upper = lower + 1;
 312                 lower = upper + 7;
 313         }
 314 }
 315 
 316 /*
 317  * here we handle horizontal blocks for the update. update_vert will
 318  * handle spaning multiple pages. we break out each horizontal
 319  * block in to individual blocks no taller than 64 pixels.
 320  */
 321 static void arcfb_lcd_update_horiz(struct arcfb_par *par, unsigned int left,
 322                         unsigned int right, unsigned int top, unsigned int h)
 323 {
 324         unsigned int distance, upper, lower;
 325 
 326         distance = h;
 327         upper = floor8(top);
 328         lower = min(upper + distance - 1, ceil64(upper));
 329 
 330         while (distance > 0) {
 331                 distance -= ((lower - upper) + 1 );
 332                 arcfb_lcd_update_vert(par, upper, lower, left, right);
 333                 upper = lower + 1;
 334                 lower = min(upper + distance - 1, ceil64(upper));
 335         }
 336 }
 337 
 338 /*
 339  * here we start the process of splitting out the fb update into
 340  * individual blocks of pixels. we end up splitting into 64x64 blocks
 341  * and finally down to 64x8 pages.
 342  */
 343 static void arcfb_lcd_update(struct arcfb_par *par, unsigned int dx,
 344                         unsigned int dy, unsigned int w, unsigned int h)
 345 {
 346         unsigned int left, right, distance, y;
 347 
 348         /* align the request first */
 349         y = floor8(dy);
 350         h += dy - y;
 351         h = iceil8(h);
 352 
 353         distance = w;
 354         left = dx;
 355         right = min(left + w - 1, ceil64(left));
 356 
 357         while (distance > 0) {
 358                 arcfb_lcd_update_horiz(par, left, right, y, h);
 359                 distance -= ((right - left) + 1);
 360                 left = right + 1;
 361                 right = min(left + distance - 1, ceil64(left));
 362         }
 363 }
 364 
 365 static void arcfb_fillrect(struct fb_info *info,
 366                            const struct fb_fillrect *rect)
 367 {
 368         struct arcfb_par *par = info->par;
 369 
 370         sys_fillrect(info, rect);
 371 
 372         /* update the physical lcd */
 373         arcfb_lcd_update(par, rect->dx, rect->dy, rect->width, rect->height);
 374 }
 375 
 376 static void arcfb_copyarea(struct fb_info *info,
 377                            const struct fb_copyarea *area)
 378 {
 379         struct arcfb_par *par = info->par;
 380 
 381         sys_copyarea(info, area);
 382 
 383         /* update the physical lcd */
 384         arcfb_lcd_update(par, area->dx, area->dy, area->width, area->height);
 385 }
 386 
 387 static void arcfb_imageblit(struct fb_info *info, const struct fb_image *image)
 388 {
 389         struct arcfb_par *par = info->par;
 390 
 391         sys_imageblit(info, image);
 392 
 393         /* update the physical lcd */
 394         arcfb_lcd_update(par, image->dx, image->dy, image->width,
 395                                 image->height);
 396 }
 397 
 398 static int arcfb_ioctl(struct fb_info *info,
 399                           unsigned int cmd, unsigned long arg)
 400 {
 401         void __user *argp = (void __user *)arg;
 402         struct arcfb_par *par = info->par;
 403         unsigned long flags;
 404 
 405         switch (cmd) {
 406                 case FBIO_WAITEVENT:
 407                 {
 408                         DEFINE_WAIT(wait);
 409                         /* illegal to wait on arc if no irq will occur */
 410                         if (!par->irq)
 411                                 return -EINVAL;
 412 
 413                         /* wait until the Arc has generated an interrupt
 414                          * which will wake us up */
 415                         spin_lock_irqsave(&par->lock, flags);
 416                         prepare_to_wait(&arcfb_waitq, &wait,
 417                                         TASK_INTERRUPTIBLE);
 418                         spin_unlock_irqrestore(&par->lock, flags);
 419                         schedule();
 420                         finish_wait(&arcfb_waitq, &wait);
 421                 }
 422                 /* fall through */
 423 
 424                 case FBIO_GETCONTROL2:
 425                 {
 426                         unsigned char ctl2;
 427 
 428                         ctl2 = ks108_readb_ctl2(info->par);
 429                         if (copy_to_user(argp, &ctl2, sizeof(ctl2)))
 430                                 return -EFAULT;
 431                         return 0;
 432                 }
 433                 default:
 434                         return -EINVAL;
 435         }
 436 }
 437 
 438 /*
 439  * this is the access path from userspace. they can seek and write to
 440  * the fb. it's inefficient for them to do anything less than 64*8
 441  * writes since we update the lcd in each write() anyway.
 442  */
 443 static ssize_t arcfb_write(struct fb_info *info, const char __user *buf,
 444                            size_t count, loff_t *ppos)
 445 {
 446         /* modded from epson 1355 */
 447 
 448         unsigned long p;
 449         int err=-EINVAL;
 450         unsigned int fbmemlength,x,y,w,h, bitppos, startpos, endpos, bitcount;
 451         struct arcfb_par *par;
 452         unsigned int xres;
 453 
 454         p = *ppos;
 455         par = info->par;
 456         xres = info->var.xres;
 457         fbmemlength = (xres * info->var.yres)/8;
 458 
 459         if (p > fbmemlength)
 460                 return -ENOSPC;
 461 
 462         err = 0;
 463         if ((count + p) > fbmemlength) {
 464                 count = fbmemlength - p;
 465                 err = -ENOSPC;
 466         }
 467 
 468         if (count) {
 469                 char *base_addr;
 470 
 471                 base_addr = (char __force *)info->screen_base;
 472                 count -= copy_from_user(base_addr + p, buf, count);
 473                 *ppos += count;
 474                 err = -EFAULT;
 475         }
 476 
 477 
 478         bitppos = p*8;
 479         startpos = floorXres(bitppos, xres);
 480         endpos = ceilXres((bitppos + (count*8)), xres);
 481         bitcount = endpos - startpos;
 482 
 483         x = startpos % xres;
 484         y = startpos / xres;
 485         w = xres;
 486         h = bitcount / xres;
 487         arcfb_lcd_update(par, x, y, w, h);
 488 
 489         if (count)
 490                 return count;
 491         return err;
 492 }
 493 
 494 static struct fb_ops arcfb_ops = {
 495         .owner          = THIS_MODULE,
 496         .fb_open        = arcfb_open,
 497         .fb_read        = fb_sys_read,
 498         .fb_write       = arcfb_write,
 499         .fb_release     = arcfb_release,
 500         .fb_pan_display = arcfb_pan_display,
 501         .fb_fillrect    = arcfb_fillrect,
 502         .fb_copyarea    = arcfb_copyarea,
 503         .fb_imageblit   = arcfb_imageblit,
 504         .fb_ioctl       = arcfb_ioctl,
 505 };
 506 
 507 static int arcfb_probe(struct platform_device *dev)
 508 {
 509         struct fb_info *info;
 510         int retval = -ENOMEM;
 511         int videomemorysize;
 512         unsigned char *videomemory;
 513         struct arcfb_par *par;
 514         int i;
 515 
 516         videomemorysize = (((64*64)*num_cols)*num_rows)/8;
 517 
 518         /* We need a flat backing store for the Arc's
 519            less-flat actual paged framebuffer */
 520         videomemory = vzalloc(videomemorysize);
 521         if (!videomemory)
 522                 return retval;
 523 
 524         info = framebuffer_alloc(sizeof(struct arcfb_par), &dev->dev);
 525         if (!info)
 526                 goto err;
 527 
 528         info->screen_base = (char __iomem *)videomemory;
 529         info->fbops = &arcfb_ops;
 530 
 531         info->var = arcfb_var;
 532         info->fix = arcfb_fix;
 533         par = info->par;
 534         par->info = info;
 535 
 536         if (!dio_addr || !cio_addr || !c2io_addr) {
 537                 printk(KERN_WARNING "no IO addresses supplied\n");
 538                 goto err1;
 539         }
 540         par->dio_addr = dio_addr;
 541         par->cio_addr = cio_addr;
 542         par->c2io_addr = c2io_addr;
 543         par->cslut[0] = 0x00;
 544         par->cslut[1] = 0x06;
 545         info->flags = FBINFO_FLAG_DEFAULT;
 546         spin_lock_init(&par->lock);
 547         retval = register_framebuffer(info);
 548         if (retval < 0)
 549                 goto err1;
 550         platform_set_drvdata(dev, info);
 551         if (irq) {
 552                 par->irq = irq;
 553                 if (request_irq(par->irq, &arcfb_interrupt, IRQF_SHARED,
 554                                 "arcfb", info)) {
 555                         printk(KERN_INFO
 556                                 "arcfb: Failed req IRQ %d\n", par->irq);
 557                         retval = -EBUSY;
 558                         goto err1;
 559                 }
 560         }
 561         fb_info(info, "Arc frame buffer device, using %dK of video memory\n",
 562                 videomemorysize >> 10);
 563 
 564         /* this inits the lcd but doesn't clear dirty pixels */
 565         for (i = 0; i < num_cols * num_rows; i++) {
 566                 ks108_writeb_ctl(par, i, KS_DPY_OFF);
 567                 ks108_set_start_line(par, i, 0);
 568                 ks108_set_yaddr(par, i, 0);
 569                 ks108_set_xaddr(par, i, 0);
 570                 ks108_writeb_ctl(par, i, KS_DPY_ON);
 571         }
 572 
 573         /* if we were told to splash the screen, we just clear it */
 574         if (!nosplash) {
 575                 for (i = 0; i < num_cols * num_rows; i++) {
 576                         fb_info(info, "splashing lcd %d\n", i);
 577                         ks108_set_start_line(par, i, 0);
 578                         ks108_clear_lcd(par, i);
 579                 }
 580         }
 581 
 582         return 0;
 583 err1:
 584         framebuffer_release(info);
 585 err:
 586         vfree(videomemory);
 587         return retval;
 588 }
 589 
 590 static int arcfb_remove(struct platform_device *dev)
 591 {
 592         struct fb_info *info = platform_get_drvdata(dev);
 593 
 594         if (info) {
 595                 unregister_framebuffer(info);
 596                 vfree((void __force *)info->screen_base);
 597                 framebuffer_release(info);
 598         }
 599         return 0;
 600 }
 601 
 602 static struct platform_driver arcfb_driver = {
 603         .probe  = arcfb_probe,
 604         .remove = arcfb_remove,
 605         .driver = {
 606                 .name   = "arcfb",
 607         },
 608 };
 609 
 610 static struct platform_device *arcfb_device;
 611 
 612 static int __init arcfb_init(void)
 613 {
 614         int ret;
 615 
 616         if (!arcfb_enable)
 617                 return -ENXIO;
 618 
 619         ret = platform_driver_register(&arcfb_driver);
 620         if (!ret) {
 621                 arcfb_device = platform_device_alloc("arcfb", 0);
 622                 if (arcfb_device) {
 623                         ret = platform_device_add(arcfb_device);
 624                 } else {
 625                         ret = -ENOMEM;
 626                 }
 627                 if (ret) {
 628                         platform_device_put(arcfb_device);
 629                         platform_driver_unregister(&arcfb_driver);
 630                 }
 631         }
 632         return ret;
 633 
 634 }
 635 
 636 static void __exit arcfb_exit(void)
 637 {
 638         platform_device_unregister(arcfb_device);
 639         platform_driver_unregister(&arcfb_driver);
 640 }
 641 
 642 module_param(num_cols, ulong, 0);
 643 MODULE_PARM_DESC(num_cols, "Num horiz panels, eg: 2 = 128 bit wide");
 644 module_param(num_rows, ulong, 0);
 645 MODULE_PARM_DESC(num_rows, "Num vert panels, eg: 1 = 64 bit high");
 646 module_param(nosplash, uint, 0);
 647 MODULE_PARM_DESC(nosplash, "Disable doing the splash screen");
 648 module_param(arcfb_enable, uint, 0);
 649 MODULE_PARM_DESC(arcfb_enable, "Enable communication with Arc board");
 650 module_param_hw(dio_addr, ulong, ioport, 0);
 651 MODULE_PARM_DESC(dio_addr, "IO address for data, eg: 0x480");
 652 module_param_hw(cio_addr, ulong, ioport, 0);
 653 MODULE_PARM_DESC(cio_addr, "IO address for control, eg: 0x400");
 654 module_param_hw(c2io_addr, ulong, ioport, 0);
 655 MODULE_PARM_DESC(c2io_addr, "IO address for secondary control, eg: 0x408");
 656 module_param(splashval, ulong, 0);
 657 MODULE_PARM_DESC(splashval, "Splash pattern: 0xFF is black, 0x00 is green");
 658 module_param(tuhold, ulong, 0);
 659 MODULE_PARM_DESC(tuhold, "Time to hold between strobing data to Arc board");
 660 module_param_hw(irq, uint, irq, 0);
 661 MODULE_PARM_DESC(irq, "IRQ for the Arc board");
 662 
 663 module_init(arcfb_init);
 664 module_exit(arcfb_exit);
 665 
 666 MODULE_DESCRIPTION("fbdev driver for Arc monochrome LCD board");
 667 MODULE_AUTHOR("Jaya Kumar");
 668 MODULE_LICENSE("GPL");
 669 

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