📄 au1100fb.c
字号:
p_lcd_reg->lcd_control &= ~LCD_CONTROL_GO;#endif au_sync(); break; default: break; } return 0;}static void au1100_set_disp(const void *unused, struct display *disp, struct fb_info_gen *info){ disp->screen_base = (char *)fb_info.fb_virt_start; switch (disp->var.bits_per_pixel) {#ifdef FBCON_HAS_CFB8 case 8: disp->dispsw = &fbcon_cfb8; if (fb_info.nohwcursor) fbcon_cfb8.cursor = au1100_nocursor; break;#endif#ifdef FBCON_HAS_CFB16 case 16: disp->dispsw = &fbcon_cfb16; disp->dispsw_data = fb_info.fbcon_cmap16; if (fb_info.nohwcursor) fbcon_cfb16.cursor = au1100_nocursor; break;#endif default: disp->dispsw = &fbcon_dummy; disp->dispsw_data = NULL; break; }}static intau1100fb_mmap(struct fb_info *_fb, struct file *file, struct vm_area_struct *vma){ unsigned int len; unsigned long start=0, off; struct au1100fb_info *fb = (struct au1100fb_info *)_fb; if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT)) { return -EINVAL; } start = fb_info.fb_phys & PAGE_MASK; len = PAGE_ALIGN((start & ~PAGE_MASK) + fb_info.fb_size); off = vma->vm_pgoff << PAGE_SHIFT; if ((vma->vm_end - vma->vm_start + off) > len) { return -EINVAL; } off += start; vma->vm_pgoff = off >> PAGE_SHIFT; pgprot_val(vma->vm_page_prot) &= ~_CACHE_MASK; //pgprot_val(vma->vm_page_prot) |= _CACHE_CACHABLE_NONCOHERENT; pgprot_val(vma->vm_page_prot) |= (6 << 9); //CCA=6 /* This is an IO map - tell maydump to skip this VMA */ vma->vm_flags |= VM_IO; if (io_remap_page_range(vma->vm_start, off, vma->vm_end - vma->vm_start, vma->vm_page_prot)) { return -EAGAIN; } fb->mmaped = 1; return 0;}int au1100_pan_display(const struct fb_var_screeninfo *var, struct fb_info_gen *info){ return 0;}static int au1100fb_ioctl(struct inode *inode, struct file *file, u_int cmd, u_long arg, int con, struct fb_info *info){ /* nothing to do yet */ return -EINVAL;}static struct fbgen_hwswitch au1100_switch = { au1100_detect, au1100_encode_fix, au1100_decode_var, au1100_encode_var, au1100_get_par, au1100_set_par, au1100_getcolreg, au1100_setcolreg, au1100_pan_display, au1100_blank, au1100_set_disp};int au1100_setmode(void) { int words; /* FIXME Need to accomodate for swivel mode and 12bpp, <8bpp*/ switch (p_lcd->mode_control & LCD_CONTROL_SM) { case LCD_CONTROL_SM_0: case LCD_CONTROL_SM_180: words = (p_lcd->xres * p_lcd->yres * p_lcd->bpp) / 32; break; case LCD_CONTROL_SM_90: case LCD_CONTROL_SM_270: /* is this correct? */ words = (p_lcd->xres * p_lcd->bpp) / 8; break; default: printk("mode_control reg not initialized\n"); return -EINVAL; } /* * Setup LCD controller */ p_lcd_reg->lcd_control = p_lcd->mode_control; p_lcd_reg->lcd_intstatus = 0; p_lcd_reg->lcd_intenable = 0; p_lcd_reg->lcd_horztiming = p_lcd->mode_horztiming; p_lcd_reg->lcd_verttiming = p_lcd->mode_verttiming; p_lcd_reg->lcd_clkcontrol = p_lcd->mode_clkcontrol; p_lcd_reg->lcd_words = words - 1; p_lcd_reg->lcd_dmaaddr0 = fb_info.fb_phys; /* turn on panel */#ifdef CONFIG_MIPS_PB1100 au_writew(au_readw(PB1100_G_CONTROL) | p_lcd->mode_backlight, PB1100_G_CONTROL);#endif p_lcd_reg->lcd_control |= LCD_CONTROL_GO; return 0;}int __init au1100fb_init(void){ uint32 sys_clksrc; unsigned long page; /* * Get the panel information/display mode and update the registry */ p_lcd = &panels[my_lcd_index]; switch (p_lcd->mode_control & LCD_CONTROL_SM) { case LCD_CONTROL_SM_0: case LCD_CONTROL_SM_180: p_lcd->xres = (p_lcd->mode_horztiming & LCD_HORZTIMING_PPL) + 1; p_lcd->yres = (p_lcd->mode_verttiming & LCD_VERTTIMING_LPP) + 1; break; case LCD_CONTROL_SM_90: case LCD_CONTROL_SM_270: p_lcd->yres = (p_lcd->mode_horztiming & LCD_HORZTIMING_PPL) + 1; p_lcd->xres = (p_lcd->mode_verttiming & LCD_VERTTIMING_LPP) + 1; break; } /* * Panel dimensions x bpp must be divisible by 32 */ if (((p_lcd->yres * p_lcd->bpp) % 32) != 0) printk("VERT %% 32\n"); if (((p_lcd->xres * p_lcd->bpp) % 32) != 0) printk("HORZ %% 32\n"); /* * Allocate LCD framebuffer from system memory */ fb_info.fb_size = (p_lcd->xres * p_lcd->yres * p_lcd->bpp) / 8; current_par.var.xres = p_lcd->xres; current_par.var.xres_virtual = p_lcd->xres; current_par.var.yres = p_lcd->yres; current_par.var.yres_virtual = p_lcd->yres; current_par.var.bits_per_pixel = p_lcd->bpp; /* FIX!!! only works for 8/16 bpp */ current_par.line_length = p_lcd->xres * p_lcd->bpp / 8; /* in bytes */ fb_info.fb_virt_start = (unsigned long ) __get_free_pages(GFP_ATOMIC | GFP_DMA, get_order(fb_info.fb_size + 0x1000)); if (!fb_info.fb_virt_start) { printk("Unable to allocate fb memory\n"); return -ENOMEM; } fb_info.fb_phys = virt_to_bus((void *)fb_info.fb_virt_start); /* * Set page reserved so that mmap will work. This is necessary * since we'll be remapping normal memory. */ for (page = fb_info.fb_virt_start; page < PAGE_ALIGN(fb_info.fb_virt_start + fb_info.fb_size); page += PAGE_SIZE) { SetPageReserved(virt_to_page(page)); } memset((void *)fb_info.fb_virt_start, 0, fb_info.fb_size); /* set freqctrl now to allow more time to stabilize */ /* zero-out out LCD bits */ sys_clksrc = au_readl(SYS_CLKSRC) & ~0x000003e0; sys_clksrc |= p_lcd->mode_toyclksrc; au_writel(sys_clksrc, SYS_CLKSRC); /* FIXME add check to make sure auxpll is what is expected! */ au1100_setmode(); fb_info.gen.parsize = sizeof(struct au1100fb_par); fb_info.gen.fbhw = &au1100_switch; strcpy(fb_info.gen.info.modename, "Au1100 LCD"); fb_info.gen.info.changevar = NULL; fb_info.gen.info.node = -1; fb_info.gen.info.fbops = &au1100fb_ops; fb_info.gen.info.disp = &disp; fb_info.gen.info.switch_con = &fbgen_switch; fb_info.gen.info.updatevar = &fbgen_update_var; fb_info.gen.info.blank = &fbgen_blank; fb_info.gen.info.flags = FBINFO_FLAG_DEFAULT; /* This should give a reasonable default video mode */ fbgen_get_var(&disp.var, -1, &fb_info.gen.info); fbgen_do_set_var(&disp.var, 1, &fb_info.gen); fbgen_set_disp(-1, &fb_info.gen); fbgen_install_cmap(0, &fb_info.gen); if (register_framebuffer(&fb_info.gen.info) < 0) return -EINVAL; printk(KERN_INFO "fb%d: %s frame buffer device\n", GET_FB_IDX(fb_info.gen.info.node), fb_info.gen.info.modename); /* uncomment this if your driver cannot be unloaded */ /* MOD_INC_USE_COUNT; */ return 0;}void au1100fb_cleanup(struct fb_info *info){ unregister_framebuffer(info);}void au1100fb_setup(char *options, int *ints){ char* this_opt; int i; int num_panels = sizeof(panels)/sizeof(struct known_lcd_panels); if (!options || !*options) return; for(this_opt=strtok(options, ","); this_opt; this_opt=strtok(NULL, ",")) { if (!strncmp(this_opt, "panel:", 6)) {#if defined(CONFIG_MIPS_PB1100) || defined(CONFIG_MIPS_DB1100) /* Read Pb1100 Switch S10 ? */ if (!strncmp(this_opt+6, "s10", 3)) { int panel; panel = *(volatile int *)0xAE000008; /* BCSR SWITCHES */ panel >>= 8; panel &= 0x0F; if (panel >= num_panels) panel = 0; my_lcd_index = panel; } else#endif /* Get the panel name, everything else if fixed */ for (i=0; i<num_panels; i++) { if (!strncmp(this_opt+6, panels[i].panel_name, strlen(this_opt))) { my_lcd_index = i; break; } } } else if (!strncmp(this_opt, "nohwcursor", 10)) { printk("nohwcursor\n"); fb_info.nohwcursor = 1; } } printk("au1100fb: Panel %d %s\n", my_lcd_index, panels[my_lcd_index].panel_name);}#ifdef MODULEMODULE_LICENSE("GPL");int init_module(void){ return au1100fb_init();}void cleanup_module(void){ au1100fb_cleanup(void);}MODULE_AUTHOR("Pete Popov <ppopov@mvista.com>");MODULE_DESCRIPTION("Au1100 LCD framebuffer device driver");#endif /* MODULE */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -