⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 epson1356fb.c

📁 S3C44B0X下的LCD (framebuffer)驱动资料与相关代码
💻 C
📖 第 1 页 / 共 5 页
字号:
			e1356fb_install_cmap(display, &(info->fb_info));		}	}  	return 0;}static inte1356fb_pan_display(struct fb_var_screeninfo* var, 		    int con,		    struct fb_info* fb){	struct fb_info_e1356* info = (struct fb_info_e1356*)fb;	struct e1356fb_par* par = &info->current_par;    	//DPRINTK("\n");	if (info->fix.nopan)		return -EINVAL;	if ((int)var->xoffset < 0 ||	    var->xoffset + par->width > par->width_virt ||	    (int)var->yoffset < 0 ||	    var->yoffset + par->height > par->height_virt)		return -EINVAL;    	if (con == currcon)		do_pan_var(var, info);    	fb_display[con].var.xoffset = var->xoffset;	fb_display[con].var.yoffset = var->yoffset; 	return 0;}static inte1356fb_get_cmap(struct fb_cmap *cmap, 		 int kspc, 		 int con,		 struct fb_info *fb){	struct fb_info_e1356* info = (struct fb_info_e1356*)fb;	struct display *d = (con<0) ? fb->disp : fb_display + con;   	//DPRINTK("\n");	if (con == currcon) {		/* current console? */		return fb_get_cmap(cmap, kspc, e1356fb_getcolreg, fb);	} else if (d->cmap.len) {		/* non default colormap? */		fb_copy_cmap(&d->cmap, cmap, kspc ? 0 : 2);	} else {		fb_copy_cmap(fb_default_cmap(info->current_par.cmap_len),			     cmap, kspc ? 0 : 2);	}	return 0;}static inte1356fb_set_cmap(struct fb_cmap *cmap, 		 int kspc, 		 int con,		 struct fb_info *fb){	struct display *d = (con<0) ? fb->disp : fb_display + con;	struct fb_info_e1356 *info = (struct fb_info_e1356*)fb;	int cmap_len = (info->current_par.bpp == 8) ? 256 : 16;	//DPRINTK("\n");	if (d->cmap.len!=cmap_len) {		int err;		if ((err = fb_alloc_cmap(&d->cmap, cmap_len, 0)))			return err;	}    	if (con == currcon) {		/* current console? */		return fb_set_cmap(cmap, kspc, e1356fb_setcolreg, fb);	} else {		fb_copy_cmap(cmap, &d->cmap, kspc ? 0 : 1);	}	return 0;}static inte1356fb_ioctl(struct inode *inode, 	      struct file *file, 	      u_int cmd,	      u_long arg, 	      int con, 	      struct fb_info *fb){	struct fb_info_e1356 *info = (struct fb_info_e1356*)fb;	blt_info_t blt;	u16* src = NULL;	int ret=0;    	switch (cmd) {	case FBIO_SED1356_BITBLT:		if (copy_from_user(&blt, (void *)arg, sizeof(blt_info_t)))			return -EFAULT;		if (blt.src) {			if ((ret = verify_area(VERIFY_READ,					       (void*)blt.src, blt.srcsize)))				return ret;			if ((src = (u16*)kmalloc(blt.srcsize,						 GFP_KERNEL)) == NULL)				return -ENOMEM;			if (copy_from_user(src, (void *)blt.src, blt.srcsize))				return -EFAULT;			blt.src = src;		}		ret = doBlt(&info->current_par, info, &blt);		if (src)			kfree(src);		break;	default:		return -EINVAL;	}	return ret;}static inte1356fb_mmap(struct fb_info *fb,	     struct file *file,	     struct vm_area_struct *vma){	struct fb_info_e1356 *info = (struct fb_info_e1356*)fb;	unsigned int len;	phys_t start=0, off;	if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT)) {		DPRINTK("invalid vma->vm_pgoff\n");		return -EINVAL;	}    #ifdef SHADOW_FRAME_BUFFER	if (!info->shadow.fb) {		int order = 0;		while (info->fb_size > (PAGE_SIZE * (1 << order)))			order++;		info->shadow.fb = (void*)__get_free_pages(GFP_KERNEL, order);		if (!info->shadow.fb) {			DPRINTK("shadow fb alloc failed\n");			return -ENXIO;		}		memset(info->shadow.fb, 0, info->fb_size);		init_timer(&info->shadow.timer);		info->shadow.timer.function = do_write_shadow_fb;		info->shadow.timer.data = (unsigned long)info;	}	mod_timer(&info->shadow.timer, jiffies+HZ/2);	start = virt_to_phys(info->shadow.fb) & PAGE_MASK;#else	start = info->fix.membase_phys & PAGE_MASK;#endif	len = PAGE_ALIGN((start & ~PAGE_MASK) + info->fb_size);	off = vma->vm_pgoff << PAGE_SHIFT;    	if ((vma->vm_end - vma->vm_start + off) > len) {		DPRINTK("invalid vma\n");		return -EINVAL;	}	off += start;	vma->vm_pgoff = off >> PAGE_SHIFT;	pgprot_val(vma->vm_page_prot) &= ~_CACHE_MASK;#ifdef SHADOW_FRAME_BUFFER	vma->vm_flags |= VM_RESERVED;	pgprot_val(vma->vm_page_prot) &= ~_CACHE_UNCACHED;#else	pgprot_val(vma->vm_page_prot) |= _CACHE_UNCACHED;#endif	/* This is an IO map - tell maydump to skip this VMA */	vma->vm_flags |= VM_IO;	// FIXME: shouldn't have to do this. If the pages are marked writeable,	// the TLB fault handlers should set these.	pgprot_val(vma->vm_page_prot) |= (_PAGE_DIRTY | _PAGE_VALID);    	/*	 * The SED1356 has only a 16-bit wide data bus, and some	 * embedded platforms, such as the Pb1000, do not automatically	 * split 32-bit word accesses to the framebuffer into	 * seperate half-word accesses. Hence the upper half-word	 * never gets to the framebuffer. The following solution is	 * to intentionally return a non-32-bit-aligned VA. As long	 * as the user app assumes (and doesn't check) that the returned	 * VA is 32-bit aligned, all (assumed aligned) 32-bit accesses	 * will actually be unaligned and will get trapped by the MIPS	 * unaligned exception handler. This handler will emulate the	 * load/store instructions by splitting up the load/store	 * into two 16-bit load/stores. (This emulation is currently	 * enabled by default, but may be disabled in the future, when	 * alignment problems in user-level programs get fixed. When	 * that happens, this solution won't work anymore, unless the	 * process that mmap's the fb also calls sysmips(MIPS_FIXADE, 1),	 * which turns address-error emulation back on).	 *	 * Furthermore, this solution only seems to work for TinyX	 * (Xfbdev). Others, like Qt/E, do snoop the returned VA	 * and compensate, or do originally unaligned 32-bit accesses	 * which then become aligned, hence breaking this solution.	 */	if (info->fix.mmunalign)		vma->vm_start += 2;		if (io_remap_page_range(vma->vm_start, off,				vma->vm_end - vma->vm_start,				vma->vm_page_prot))		return -EAGAIN;	info->mmaped = 1;	return 0;}int __inite1356fb_init(void){	struct fb_var_screeninfo var;	struct e1356fb_fix * epfix = &fb_info.fix;	e1356_reg_t* reg;	void* regbase;	char* name = "SED1356";	int periodMCLK, periodBCLK;	int dram_timing, rr_div, mclk_src;	u8 rev_code, btmp, mclk_cfg;	if (options) {		e1356fb_setup(options, 0);	}	// clear out fb_info	memset(&fb_info, 0, sizeof(struct fb_info_e1356));	// copy boot options	fb_info.fix = boot_fix;	fb_info.default_par = boot_par;	fb_info.regbase_size = E1356_REG_SIZE;	if (!epfix->system) {		printk(KERN_ERR "e1356/86fb: no valid system found\n");		return -ENODEV;	}	if (epfix->system == SYS_SDU1356) {		// it's the SDU1356B0C PCI eval card.		struct pci_dev *pdev = NULL;		if (!pci_present())   /* No PCI bus in this machine! */			return -ENODEV;		if (!(pdev = pci_find_device(PCI_VENDOR_ID_EPSON,					     PCI_DEVICE_ID_EPSON_SDU1356, pdev)))			return -ENODEV;		if (pci_enable_device(pdev))			return -ENODEV;		epfix->regbase_phys = pci_resource_start(pdev, 0);		epfix->membase_phys = epfix->regbase_phys + E1356_REG_SIZE;	}		fb_info.regbase_virt = ioremap_nocache(epfix->regbase_phys,					       E1356_REG_SIZE);	if (!fb_info.regbase_virt) {		printk("e1356fb: Can't remap %s register area.\n", name);		return -ENXIO;	}	regbase = fb_info.regbase_virt;	reg = &fb_info.reg;    	// Initialize the register pointers	reg->basic =         (reg_basic_t*)   (regbase + REG_BASE_BASIC);	reg->genio =         (reg_genio_t*)   (regbase + REG_BASE_GENIO);	reg->md_cfg =        (reg_mdcfg_t*)   (regbase + REG_BASE_MDCFG);	reg->clk_cfg =       (reg_clkcfg_t*)  (regbase + REG_BASE_CLKCFG);	reg->mem_cfg =       (reg_memcfg_t*)  (regbase + REG_BASE_MEMCFG);	reg->panel_cfg =     (reg_panelcfg_t*)(regbase + REG_BASE_PANELCFG);	reg->lcd_cfg =       (reg_dispcfg_t*) (regbase + REG_BASE_LCD_DISPCFG);	reg->crttv_cfg =     (reg_dispcfg_t*) (regbase + REG_BASE_CRTTV_DISPCFG);	reg->lcd_mode =      (reg_dispmode_t*)(regbase + REG_BASE_LCD_DISPMODE);	reg->crttv_mode =    (reg_dispmode_t*)(regbase + REG_BASE_CRTTV_DISPMODE);	reg->lcd_inkcurs =   (reg_inkcurs_t*) (regbase + REG_BASE_LCD_INKCURS);	reg->crttv_inkcurs = (reg_inkcurs_t*) (regbase + REG_BASE_CRTTV_INKCURS);	reg->bitblt =        (reg_bitblt_t*)  (regbase + REG_BASE_BITBLT);	reg->lut =           (reg_lut_t*)     (regbase + REG_BASE_LUT);	reg->pwr_save =      (reg_pwrsave_t*) (regbase + REG_BASE_PWRSAVE);	reg->misc =          (reg_misc_t*)    (regbase + REG_BASE_MISC);	reg->mediaplug =     (reg_mediaplug_t*)(regbase + REG_BASE_MEDIAPLUG);	reg->bitblt_data =   (u16*)           (regbase + REG_BASE_BITBLT_DATA);    	// Enable all register access	writeb(0, &reg->basic->misc);	rev_code = readb(&reg->basic->rev_code);	if ((rev_code >> 2) == 0x04) {		printk("Found EPSON1356 Display Controller\n");	}	else if ((rev_code >> 2) == 0x07) {		printk("Found EPSON13806 Display Controller\n");	}	else {		iounmap(fb_info.regbase_virt);		printk("e1356/806fb: %s not found, rev_code=0x%02x.\n",		       name, rev_code);		return -ENODEV;	}	fb_info.chip_rev = rev_code & 0x03;	// Determine frame-buffer size	switch (readb(&reg->md_cfg->md_cfg_stat0) >> 6) {	case 0:	case 2:		fb_info.fb_size = 0x80000;   /* 512K bytes */		break;	case 1:		if ((rev_code >> 2) == 7) /* 806 */			fb_info.fb_size = 0x140000;  /* 1.2M bytes */		else			fb_info.fb_size = 0x200000;  /* 2M bytes */		break;	default:		fb_info.fb_size = 0x200000;  /* 2M bytes */		break;	}	fb_info.membase_virt = ioremap_nocache(epfix->membase_phys,					       fb_info.fb_size);    	if (!fb_info.membase_virt) {		printk("e1356fb: Can't remap %s framebuffer.\n", name);		iounmap(fb_info.regbase_virt);		return -ENXIO;	}    	printk("e1356/806fb: Detected  %dKB framebuffer\n", 			(unsigned)fb_info.fb_size/1000);#ifdef CONFIG_MTRR	if (!epfix->nomtrr) {		fb_info.mtrr_idx = mtrr_add(epfix->membase_phys, fb_info.fb_size,					    MTRR_TYPE_WRCOMB, 1);		printk("e1356fb: MTRR's turned on\n");	}#endif    	if (!boot_fix.noaccel) {		/*		  Allocate a page for string BLTs. A 4K page is		  enough for a 256 character string at an 8x16 font.		*/		fb_info.putcs_buffer = (void*)__get_free_pages(GFP_KERNEL, 0);		if (fb_info.putcs_buffer == NULL) {			printk("e1356fb: Can't allocate putcs buffer\n");			goto unmap_ret_enxio;		}	}	// Begin SED1356 initialization	// disable display while initializing	writeb(0, &reg->misc->disp_mode);	// Set the GPIO1 and 2 to inputs	writeb(0, &reg->genio->gpio_cfg);	writeb(0, &reg->genio->gpio_ctrl);	if (fb_info.chip_rev == 7) /* 806 */		writeb(0, &reg->genio->gpio_ctrl2);	/*	 * Program the clocks	 */#ifdef CONFIG_SOC_AU1X00	if ((epfix->system == SYS_PB1000) || (epfix->system == SYS_PB1500))		epfix->busclk = get_au1x00_lcd_clock();#endif		if (epfix->busclk > 80000) {		printk("e1356fb: specified busclk too high\n");		goto ret_enxio;	}	epfix->mclk = mclk_cfg = 0;	if (epfix->system == SYS_PB1500) {		epfix->mclk = epfix->busclk;		mclk_cfg = 0x01;	}	else {		// Find the highest allowable MCLK		if (epfix->busclk <= MAX_PIXCLOCK && 				epfix->busclk > epfix->mclk) {			epfix->mclk = epfix->busclk;			mclk_cfg = 0x01;		}		if (epfix->clki <= MAX_PIXCLOCK && epfix->clki > epfix->mclk) {			epfix->mclk = epfix->clki;			mclk_cfg = 0x00;		}		if (epfix->busclk/2 <= MAX_PIXCLOCK && 				epfix->busclk/2 > epfix->mclk) {			epfix->mclk = epfix->busclk/2;			mclk_cfg = 0x11;		}		if (epfix->clki/2 <= MAX_PIXCLOCK && 				epfix->clki/2 > epfix->mclk) {			epfix->mclk = epfix->clki/2;			mclk_cfg = 0x10;		}	}		if (!epfix->mclk) {		printk("e1356fb: couldn't find an allowable MCLK!\n");		goto ret_enxio;	}	// When changing mclk src, you must first set bit 4 to 1.	writeb(readb(&reg->clk_cfg->mem_clk_cfg) | 0x10,	       &reg->clk_cfg->mem_clk_cfg);	writeb(mclk_cfg, &reg->clk_cfg->mem_clk_cfg);	printk("e1356fb: clocks (kHz): busclk=%d mclk=%d clki=%d clki2=%d\n",	       epfix->busclk, epfix->mclk, epfix->clki, epfix->clki2);	// Set max pixel clock	switch (epfix->disp_type) {	case DISP_TYPE_LCD:	case DISP_TYPE_TFT:	case DISP_TYPE_CRT:		fb_info.max_pixclock = epfix->mclk;		break;	case DISP_TYPE_NTSC:	case DISP_TYPE_PAL:		fb_info.max_pixclock = (epfix->disp_type == DISP_TYPE_NTSC) ?			NTSC_PIXCLOCK : PAL_PIXCLOCK;		if (epfix->tv_filt & TV_FILT_FLICKER)			fb_info.max_pixclock *= 2;		break;	default:		printk("e1356fb: invalid specified display type\n");		goto ret_enxio;	}	periodMCLK = 1000000L / epfix->mclk;   // in nano-seconds	periodBCLK = 1000000L / epfix->busclk; // in nano-seconds	if (readb(&reg->md_cfg->md_cfg_stat1) & (1<<4))		periodBCLK *= 2;    	if ((epfix->system == SYS_PB1000) || (epfix->system == SYS_PB1500))		writeb(0x00, &reg->clk_cfg->cpu2mem_wait_sel);	else if (periodMCLK - 4 > periodBCLK)		writeb(0x02, &reg->clk_cfg->cpu2mem_wait_sel);	else if (2*periodMCLK - 4 > periodBCLK)		writeb(0x01, &reg->clk_cfg->cpu2mem_wait_sel);	else		writeb(0x00, &reg->clk_cfg->cpu2mem_wait_sel);	// Program memory config	if (epfix->mem_type < MEM_TYPE_EDO_2CAS ||	    epfix->mem_type > MEM_TYPE_EMBEDDED_SDRAM) {		printk("e1356fb: bad memory type specified\n");		goto ret_enxio;	}	writeb((u8)epfix->mem_type, &reg->mem_cfg->mem_cfg);	// calc closest refresh rate	rr_div = 7;	mclk_src = (mclk_cfg & 1) ? epfix->busclk : epfix->clki;	while ((mclk_src >> (6 + rr_div)) < epfix->mem_refresh)		if (--rr_div < 0) {			printk("e1356fb: can't set specified refresh rate\n");			goto ret_enxio;		}    	DPRINTK("refresh rate = %d kHz\n", (mclk_src >> (6 + rr_div)));	// add Suspend-Mode Refresh 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -