Linux kernel & device driver programming

Cross-Referenced Linux and Device Driver Code

[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ]
Version: [ 2.6.11.8 ] [ 2.6.25 ] [ 2.6.25.8 ] [ 2.6.31.13 ] Architecture: [ i386 ]
  1 /*
  2  * BRIEF MODULE DESCRIPTION
  3  *      Au1100 LCD Driver.
  4  *
  5  * Copyright 2002 MontaVista Software
  6  * Author: MontaVista Software, Inc.
  7  *              ppopov@mvista.com or source@mvista.com
  8  *
  9  * Copyright 2002 Alchemy Semiconductor
 10  * Author: Alchemy Semiconductor
 11  *
 12  * Based on:
 13  * linux/drivers/video/skeletonfb.c -- Skeleton for a frame buffer device
 14  *  Created 28 Dec 1997 by Geert Uytterhoeven
 15  *
 16  *  This program is free software; you can redistribute  it and/or modify it
 17  *  under  the terms of  the GNU General  Public License as published by the
 18  *  Free Software Foundation;  either version 2 of the  License, or (at your
 19  *  option) any later version.
 20  *
 21  *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
 22  *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
 23  *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
 24  *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
 25  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 26  *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
 27  *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
 28  *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
 29  *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 30  *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 31  *
 32  *  You should have received a copy of the  GNU General Public License along
 33  *  with this program; if not, write  to the Free Software Foundation, Inc.,
 34  *  675 Mass Ave, Cambridge, MA 02139, USA.
 35  */
 36 
 37 #include <linux/module.h>
 38 #include <linux/kernel.h>
 39 #include <linux/errno.h>
 40 #include <linux/string.h>
 41 #include <linux/mm.h>
 42 #include <linux/tty.h>
 43 #include <linux/slab.h>
 44 #include <linux/delay.h>
 45 #include <linux/fb.h>
 46 #include <linux/init.h>
 47 #include <linux/pci.h>
 48 
 49 #include <asm/au1000.h>
 50 #include <asm/pb1100.h>
 51 #include "au1100fb.h"
 52 
 53 #include <video/fbcon.h>
 54 #include <video/fbcon-mfb.h>
 55 #include <video/fbcon-cfb2.h>
 56 #include <video/fbcon-cfb4.h>
 57 #include <video/fbcon-cfb8.h>
 58 #include <video/fbcon-cfb16.h>
 59 
 60 /*
 61  * Sanity check. If this is a new Au1100 based board, search for
 62  * the PB1100 ifdefs to make sure you modify the code accordingly.
 63  */
 64 #if defined(CONFIG_MIPS_PB1100) || defined(CONFIG_MIPS_DB1100) || defined(CONFIG_MIPS_HYDROGEN3)
 65 #else
 66 error Unknown Au1100 board
 67 #endif
 68 
 69 #define CMAPSIZE 16
 70 
 71 static int my_lcd_index; /* default is zero */
 72 struct known_lcd_panels *p_lcd;
 73 AU1100_LCD *p_lcd_reg = (AU1100_LCD *)AU1100_LCD_ADDR;
 74 
 75 struct au1100fb_info {
 76         struct fb_info_gen gen;
 77         unsigned long fb_virt_start;
 78         unsigned long fb_size;
 79         unsigned long fb_phys;
 80         int mmaped;
 81         int nohwcursor;
 82 
 83         struct { unsigned red, green, blue, pad; } palette[256];
 84 
 85 #if defined(FBCON_HAS_CFB16)
 86         u16 fbcon_cmap16[16];
 87 #endif
 88 };
 89 
 90 
 91 struct au1100fb_par {
 92         struct fb_var_screeninfo var;
 93 
 94         int line_length;  // in bytes
 95         int cmap_len;     // color-map length
 96 };
 97 
 98 
 99 static struct au1100fb_info fb_info;
100 static struct au1100fb_par current_par;
101 static struct display disp;
102 
103 int au1100fb_init(void);
104 void au1100fb_setup(char *options, int *ints);
105 static int au1100fb_mmap(struct fb_info *fb, struct file *file,
106                 struct vm_area_struct *vma);
107 static int au1100_blank(int blank_mode, struct fb_info_gen *info);
108 static int au1100fb_ioctl(struct inode *inode, struct file *file, u_int cmd,
109                           u_long arg, int con, struct fb_info *info);
110 
111 void au1100_nocursor(struct display *p, int mode, int xx, int yy){};
112 
113 static struct fb_ops au1100fb_ops = {
114         owner:          THIS_MODULE,
115         fb_get_fix:     fbgen_get_fix,
116         fb_get_var:     fbgen_get_var,
117         fb_set_var:     fbgen_set_var,
118         fb_get_cmap:    fbgen_get_cmap,
119         fb_set_cmap:    fbgen_set_cmap,
120         fb_pan_display: fbgen_pan_display,
121         fb_ioctl:       au1100fb_ioctl,
122         fb_mmap:        au1100fb_mmap,
123 };
124 
125 static void au1100_detect(void)
126 {
127         /*
128          *  This function should detect the current video mode settings
129          *  and store it as the default video mode
130          */
131 
132         /*
133          * Yeh, well, we're not going to change any settings so we're
134          * always stuck with the default ...
135          */
136 
137 }
138 
139 static int au1100_encode_fix(struct fb_fix_screeninfo *fix,
140                 const void *_par, struct fb_info_gen *_info)
141 {
142         struct au1100fb_info *info = (struct au1100fb_info *) _info;
143         struct au1100fb_par *par = (struct au1100fb_par *) _par;
144         struct fb_var_screeninfo *var = &par->var;
145 
146         memset(fix, 0, sizeof(struct fb_fix_screeninfo));
147 
148         fix->smem_start = info->fb_phys;
149         fix->smem_len = info->fb_size;
150         fix->type = FB_TYPE_PACKED_PIXELS;
151         fix->type_aux = 0;
152         fix->visual = (var->bits_per_pixel == 8) ?
153                 FB_VISUAL_PSEUDOCOLOR   : FB_VISUAL_TRUECOLOR;
154         fix->ywrapstep = 0;
155         fix->xpanstep = 1;
156         fix->ypanstep = 1;
157         fix->line_length = current_par.line_length;
158         return 0;
159 }
160 
161 static void set_color_bitfields(struct fb_var_screeninfo *var)
162 {
163         switch (var->bits_per_pixel) {
164         case 8:
165                 var->red.offset = 0;
166                 var->red.length = 8;
167                 var->green.offset = 0;
168                 var->green.length = 8;
169                 var->blue.offset = 0;
170                 var->blue.length = 8;
171                 var->transp.offset = 0;
172                 var->transp.length = 0;
173                 break;
174         case 16:        /* RGB 565 */
175                 var->red.offset = 11;
176                 var->red.length = 5;
177                 var->green.offset = 5;
178                 var->green.length = 6;
179                 var->blue.offset = 0;
180                 var->blue.length = 5;
181                 var->transp.offset = 0;
182                 var->transp.length = 0;
183                 break;
184         }
185 
186         var->red.msb_right = 0;
187         var->green.msb_right = 0;
188         var->blue.msb_right = 0;
189         var->transp.msb_right = 0;
190 }
191 
192 static int au1100_decode_var(const struct fb_var_screeninfo *var,
193                 void *_par, struct fb_info_gen *_info)
194 {
195 
196         struct au1100fb_par *par = (struct au1100fb_par *)_par;
197 
198         /*
199          * Don't allow setting any of these yet: xres and yres don't
200          * make sense for LCD panels.
201          */
202         if (var->xres != p_lcd->xres ||
203             var->yres != p_lcd->yres ||
204             var->xres != p_lcd->xres ||
205             var->yres != p_lcd->yres) {
206                 return -EINVAL;
207         }
208         if(var->bits_per_pixel != p_lcd->bpp) {
209                 return -EINVAL;
210         }
211 
212         memset(par, 0, sizeof(struct au1100fb_par));
213         par->var = *var;
214 
215         /* FIXME */
216         switch (var->bits_per_pixel) {
217                 case 8:
218                         par->var.bits_per_pixel = 8;
219                         break;
220                 case 16:
221                         par->var.bits_per_pixel = 16;
222                         break;
223                 default:
224                         printk("color depth %d bpp not supported\n",
225                                         var->bits_per_pixel);
226                         return -EINVAL;
227 
228         }
229         set_color_bitfields(&par->var);
230         par->cmap_len = (par->var.bits_per_pixel == 8) ? 256 : 16;
231         return 0;
232 }
233 
234 static int au1100_encode_var(struct fb_var_screeninfo *var,
235                 const void *par, struct fb_info_gen *_info)
236 {
237 
238         *var = ((struct au1100fb_par *)par)->var;
239         return 0;
240 }
241 
242 static void
243 au1100_get_par(void *_par, struct fb_info_gen *_info)
244 {
245         *(struct au1100fb_par *)_par = current_par;
246 }
247 
248 static void au1100_set_par(const void *par, struct fb_info_gen *info)
249 {
250         /* nothing to do: we don't change any settings */
251 }
252 
253 static int au1100_getcolreg(unsigned regno, unsigned *red, unsigned *green,
254                          unsigned *blue, unsigned *transp,
255                          struct fb_info *info)
256 {
257 
258         struct au1100fb_info* i = (struct au1100fb_info*)info;
259 
260         if (regno > 255)
261                 return 1;
262 
263         *red    = i->palette[regno].red;
264         *green  = i->palette[regno].green;
265         *blue   = i->palette[regno].blue;
266         *transp = 0;
267 
268         return 0;
269 }
270 
271 static int au1100_setcolreg(unsigned regno, unsigned red, unsigned green,
272                          unsigned blue, unsigned transp,
273                          struct fb_info *info)
274 {
275         struct au1100fb_info* i = (struct au1100fb_info *)info;
276         u32 rgbcol;
277 
278         if (regno > 255)
279                 return 1;
280 
281         i->palette[regno].red    = red;
282         i->palette[regno].green  = green;
283         i->palette[regno].blue   = blue;
284 
285         switch(p_lcd->bpp) {
286 #ifdef FBCON_HAS_CFB8
287         case 8:
288                 red >>= 10;
289                 green >>= 10;
290                 blue >>= 10;
291                 p_lcd_reg->lcd_pallettebase[regno] = (blue&0x1f) |
292                         ((green&0x3f)<<5) | ((red&0x1f)<<11);
293                 break;
294 #endif
295 #ifdef FBCON_HAS_CFB16
296         case 16:
297                 i->fbcon_cmap16[regno] =
298                         ((red & 0xf800) >> 0) |
299                         ((green & 0xfc00) >> 5) |
300                         ((blue & 0xf800) >> 11);
301                 break;
302 #endif
303         default:
304                 break;
305         }
306 
307         return 0;
308 }
309 
310 
311 static int  au1100_blank(int blank_mode, struct fb_info_gen *_info)
312 {
313 
314         switch (blank_mode) {
315         case VESA_NO_BLANKING:
316                 /* turn on panel */
317                 //printk("turn on panel\n");
318 #ifdef CONFIG_MIPS_PB1100
319                 p_lcd_reg->lcd_control |= LCD_CONTROL_GO;
320                 au_writew(au_readw(PB1100_G_CONTROL) | p_lcd->mode_backlight,
321                         PB1100_G_CONTROL);
322 #endif
323 #ifdef CONFIG_MIPS_HYDROGEN3
324                 /*  Turn controller & power supply on,  GPIO213 */
325                 au_writel(0x20002000, 0xB1700008);
326                 au_writel(0x00040000, 0xB1900108);
327                 au_writel(0x01000100, 0xB1700008);
328 #endif
329                 au_sync();
330                 break;
331 
332         case VESA_VSYNC_SUSPEND:
333         case VESA_HSYNC_SUSPEND:
334         case VESA_POWERDOWN:
335                 /* turn off panel */
336                 //printk("turn off panel\n");
337 #ifdef CONFIG_MIPS_PB1100
338                 au_writew(au_readw(PB1100_G_CONTROL) & ~p_lcd->mode_backlight,
339                         PB1100_G_CONTROL);
340                 p_lcd_reg->lcd_control &= ~LCD_CONTROL_GO;
341 #endif
342                 au_sync();
343                 break;
344         default:
345                 break;
346 
347         }
348         return 0;
349 }
350 
351 static void au1100_set_disp(const void *unused, struct display *disp,
352                          struct fb_info_gen *info)
353 {
354         disp->screen_base = (char *)fb_info.fb_virt_start;
355 
356         switch (disp->var.bits_per_pixel) {
357 #ifdef FBCON_HAS_CFB8
358         case 8:
359                 disp->dispsw = &fbcon_cfb8;
360                 if (fb_info.nohwcursor)
361                         fbcon_cfb8.cursor = au1100_nocursor;
362                 break;
363 #endif
364 #ifdef FBCON_HAS_CFB16
365         case 16:
366                 disp->dispsw = &fbcon_cfb16;
367                 disp->dispsw_data = fb_info.fbcon_cmap16;
368                 if (fb_info.nohwcursor)
369                         fbcon_cfb16.cursor = au1100_nocursor;
370                 break;
371 #endif
372         default:
373                 disp->dispsw = &fbcon_dummy;
374                 disp->dispsw_data = NULL;
375                 break;
376         }
377 }
378 
379 static int
380 au1100fb_mmap(struct fb_info *_fb,
381              struct file *file,
382              struct vm_area_struct *vma)
383 {
384         unsigned int len;
385         unsigned long start=0, off;
386         struct au1100fb_info *fb = (struct au1100fb_info *)_fb;
387 
388         if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT)) {
389                 return -EINVAL;
390         }
391 
392         start = fb_info.fb_phys & PAGE_MASK;
393         len = PAGE_ALIGN((start & ~PAGE_MASK) + fb_info.fb_size);
394 
395         off = vma->vm_pgoff << PAGE_SHIFT;
396 
397         if ((vma->vm_end - vma->vm_start + off) > len) {
398                 return -EINVAL;
399         }
400 
401         off += start;
402         vma->vm_pgoff = off >> PAGE_SHIFT;
403 
404         pgprot_val(vma->vm_page_prot) &= ~_CACHE_MASK;
405         //pgprot_val(vma->vm_page_prot) |= _CACHE_CACHABLE_NONCOHERENT;
406         pgprot_val(vma->vm_page_prot) |= (6 << 9); //CCA=6
407 
408         /* This is an IO map - tell maydump to skip this VMA */
409         vma->vm_flags |= VM_IO;
410 
411         if (io_remap_page_range(vma, vma->vm_start, off,
412                                 vma->vm_end - vma->vm_start,
413                                 vma->vm_page_prot)) {
414                 return -EAGAIN;
415         }
416 
417         fb->mmaped = 1;
418         return 0;
419 }
420 
421 int au1100_pan_display(const struct fb_var_screeninfo *var,
422                        struct fb_info_gen *info)
423 {
424         return 0;
425 }
426 
427 static int au1100fb_ioctl(struct inode *inode, struct file *file, u_int cmd,
428                           u_long arg, int con, struct fb_info *info)
429 {
430         /* nothing to do yet */
431         return -EINVAL;
432 }
433 
434 static struct fbgen_hwswitch au1100_switch = {
435         au1100_detect,
436         au1100_encode_fix,
437         au1100_decode_var,
438         au1100_encode_var,
439         au1100_get_par,
440         au1100_set_par,
441         au1100_getcolreg,
442         au1100_setcolreg,
443         au1100_pan_display,
444         au1100_blank,
445         au1100_set_disp
446 };
447 
448 
449 int au1100_setmode(void)
450 {
451         int words;
452 
453         /* FIXME Need to accomodate for swivel mode and 12bpp, <8bpp*/
454         switch (p_lcd->mode_control & LCD_CONTROL_SM)
455         {
456                 case LCD_CONTROL_SM_0:
457                 case LCD_CONTROL_SM_180:
458                 words = (p_lcd->xres * p_lcd->yres * p_lcd->bpp) / 32;
459                         break;
460                 case LCD_CONTROL_SM_90:
461                 case LCD_CONTROL_SM_270:
462                         /* is this correct? */
463                 words = (p_lcd->xres * p_lcd->bpp) / 8;
464                         break;
465                 default:
466                         printk("mode_control reg not initialized\n");
467                         return -EINVAL;
468         }
469 
470         /*
471          * Setup LCD controller
472          */
473 
474         p_lcd_reg->lcd_control = p_lcd->mode_control;
475         p_lcd_reg->lcd_intstatus = 0;
476         p_lcd_reg->lcd_intenable = 0;
477         p_lcd_reg->lcd_horztiming = p_lcd->mode_horztiming;
478         p_lcd_reg->lcd_verttiming = p_lcd->mode_verttiming;
479         p_lcd_reg->lcd_clkcontrol = p_lcd->mode_clkcontrol;
480         p_lcd_reg->lcd_words = words - 1;
481         p_lcd_reg->lcd_dmaaddr0 = fb_info.fb_phys;
482 
483         /* turn on panel */
484 #ifdef CONFIG_MIPS_PB1100
485         au_writew(au_readw(PB1100_G_CONTROL) | p_lcd->mode_backlight,
486                         PB1100_G_CONTROL);
487 #endif
488 #ifdef CONFIG_MIPS_HYDROGEN3
489         /*  Turn controller & power supply on,  GPIO213 */
490         au_writel(0x20002000, 0xB1700008);
491         au_writel(0x00040000, 0xB1900108);
492         au_writel(0x01000100, 0xB1700008);
493 #endif
494 
495         p_lcd_reg->lcd_control |= LCD_CONTROL_GO;
496 
497         return 0;
498 }
499 
500 
501 int __init au1100fb_init(void)
502 {
503         uint32 sys_clksrc;
504         unsigned long page;
505 
506         /*
507         * Get the panel information/display mode and update the registry
508         */
509         p_lcd = &panels[my_lcd_index];
510 
511         switch (p_lcd->mode_control & LCD_CONTROL_SM)
512         {
513                 case LCD_CONTROL_SM_0:
514                 case LCD_CONTROL_SM_180:
515                 p_lcd->xres =
516                         (p_lcd->mode_horztiming & LCD_HORZTIMING_PPL) + 1;
517                 p_lcd->yres =
518                         (p_lcd->mode_verttiming & LCD_VERTTIMING_LPP) + 1;
519                         break;
520                 case LCD_CONTROL_SM_90:
521                 case LCD_CONTROL_SM_270:
522                 p_lcd->yres =
523                         (p_lcd->mode_horztiming & LCD_HORZTIMING_PPL) + 1;
524                 p_lcd->xres =
525                         (p_lcd->mode_verttiming & LCD_VERTTIMING_LPP) + 1;
526                         break;
527         }
528 
529         /*
530          * Panel dimensions x bpp must be divisible by 32
531          */
532         if (((p_lcd->yres * p_lcd->bpp) % 32) != 0)
533                 printk("VERT %% 32\n");
534         if (((p_lcd->xres * p_lcd->bpp) % 32) != 0)
535                 printk("HORZ %% 32\n");
536 
537         /*
538          * Allocate LCD framebuffer from system memory
539          */
540         fb_info.fb_size = (p_lcd->xres * p_lcd->yres * p_lcd->bpp) / 8;
541 
542         current_par.var.xres = p_lcd->xres;
543         current_par.var.xres_virtual = p_lcd->xres;
544         current_par.var.yres = p_lcd->yres;
545         current_par.var.yres_virtual = p_lcd->yres;
546         current_par.var.bits_per_pixel = p_lcd->bpp;
547 
548         /* FIX!!! only works for 8/16 bpp */
549         current_par.line_length = p_lcd->xres * p_lcd->bpp / 8; /* in bytes */
550         fb_info.fb_virt_start = (unsigned long )
551                 __get_free_pages(GFP_ATOMIC | GFP_DMA,
552                                 get_order(fb_info.fb_size + 0x1000));
553         if (!fb_info.fb_virt_start) {
554                 printk("Unable to allocate fb memory\n");
555                 return -ENOMEM;
556         }
557         fb_info.fb_phys = virt_to_bus((void *)fb_info.fb_virt_start);
558 
559         /*
560          * Set page reserved so that mmap will work. This is necessary
561          * since we'll be remapping normal memory.
562          */
563         for (page = fb_info.fb_virt_start;
564              page < PAGE_ALIGN(fb_info.fb_virt_start + fb_info.fb_size);
565              page += PAGE_SIZE) {
566                 SetPageReserved(virt_to_page(page));
567         }
568 
569         memset((void *)fb_info.fb_virt_start, 0, fb_info.fb_size);
570 
571         /* set freqctrl now to allow more time to stabilize */
572         /* zero-out out LCD bits */
573         sys_clksrc = au_readl(SYS_CLKSRC) & ~0x000003e0;
574         sys_clksrc |= p_lcd->mode_toyclksrc;
575         au_writel(sys_clksrc, SYS_CLKSRC);
576 
577         /* FIXME add check to make sure auxpll is what is expected! */
578         au1100_setmode();
579 
580         fb_info.gen.parsize = sizeof(struct au1100fb_par);
581         fb_info.gen.fbhw = &au1100_switch;
582 
583         strcpy(fb_info.gen.info.modename, "Au1100 LCD");
584         fb_info.gen.info.changevar = NULL;
585         fb_info.gen.info.node = -1;
586 
587         fb_info.gen.info.fbops = &au1100fb_ops;
588         fb_info.gen.info.disp = &disp;
589         fb_info.gen.info.switch_con = &fbgen_switch;
590         fb_info.gen.info.updatevar = &fbgen_update_var;
591         fb_info.gen.info.blank = &fbgen_blank;
592         fb_info.gen.info.flags = FBINFO_FLAG_DEFAULT;
593 
594         /* This should give a reasonable default video mode */
595         fbgen_get_var(&disp.var, -1, &fb_info.gen.info);
596         fbgen_do_set_var(&disp.var, 1, &fb_info.gen);
597         fbgen_set_disp(-1, &fb_info.gen);
598         fbgen_install_cmap(0, &fb_info.gen);
599         if (register_framebuffer(&fb_info.gen.info) < 0)
600                 return -EINVAL;
601         printk(KERN_INFO "fb%d: %s frame buffer device\n",
602                         GET_FB_IDX(fb_info.gen.info.node),
603                         fb_info.gen.info.modename);
604 
605         return 0;
606 }
607 
608 
609 void au1100fb_cleanup(struct fb_info *info)
610 {
611         unregister_framebuffer(info);
612 }
613 
614 
615 void au1100fb_setup(char *options, int *ints)
616 {
617         char* this_opt;
618         int i;
619         int num_panels = sizeof(panels)/sizeof(struct known_lcd_panels);
620 
621 
622         if (!options || !*options)
623                 return;
624 
625         for(this_opt=strtok(options, ","); this_opt;
626             this_opt=strtok(NULL, ",")) {
627                 if (!strncmp(this_opt, "panel:", 6)) {
628 #if defined(CONFIG_MIPS_PB1100) || defined(CONFIG_MIPS_DB1100)
629                         /* Read Pb1100 Switch S10 ? */
630                         if (!strncmp(this_opt+6, "s10", 3))
631                         {
632                                 int panel;
633                                 panel = *(volatile int *)0xAE000008; /* BCSR SWITCHES */
634                                 panel >>= 8;
635                                 panel &= 0x0F;
636                                 if (panel >= num_panels) panel = 0;
637                                 my_lcd_index = panel;
638                         }
639                         else
640 #endif
641                         /* Get the panel name, everything else if fixed */
642                         for (i=0; i<num_panels; i++) {
643                                 if (!strncmp(this_opt+6, panels[i].panel_name,
644                                                         strlen(this_opt))) {
645                                         my_lcd_index = i;
646                                         break;
647                                 }
648                         }
649                 }
650                 else if (!strncmp(this_opt, "nohwcursor", 10)) {
651                         printk("nohwcursor\n");
652                         fb_info.nohwcursor = 1;
653                 }
654         }
655 
656         printk("au1100fb: Panel %d %s\n", my_lcd_index,
657                 panels[my_lcd_index].panel_name);
658 }
659 
660 
661 
662 #ifdef MODULE
663 MODULE_LICENSE("GPL");
664 int init_module(void)
665 {
666         return au1100fb_init();
667 }
668 
669 void cleanup_module(void)
670 {
671         au1100fb_cleanup(void);
672 }
673 
674 MODULE_AUTHOR("Pete Popov <ppopov@mvista.com>");
675 MODULE_DESCRIPTION("Au1100 LCD framebuffer device driver");
676 #endif /* MODULE */
677 
  This page was automatically generated by the LXR engine.