From: Steve L. <slo...@us...> - 2001-09-12 22:23:34
|
Update of /cvsroot/linux-mips/linux/drivers/video In directory usw-pr-cvs1:/tmp/cvs-serv30384/drivers/video Modified Files: epson1356fb.c epson1356fb.h Log Message: - added a boot flag "mmunalign" to enable 32-bit unaligned VA fix in mmap(). - optimized mymemset_io() and renamed to fbfill(). - clear fb memory when video mode changes (e1356fb_set_par()). - more elaborate comments. Index: epson1356fb.c =================================================================== RCS file: /cvsroot/linux-mips/linux/drivers/video/epson1356fb.c,v retrieving revision 1.4 retrieving revision 1.5 diff -C2 -d -r1.4 -r1.5 *** epson1356fb.c 2001/08/30 21:41:05 1.4 --- epson1356fb.c 2001/09/12 22:23:31 1.5 *************** *** 71,77 **** #include <linux/e1356fb.h> ! #ifdef CONFIG_MIPS_PB1000 #include <asm/au1000.h> - #define USE_MMAP 1 #endif --- 71,76 ---- #include <linux/e1356fb.h> ! #ifdef CONFIG_MIPS_AU1000 #include <asm/au1000.h> #endif *************** *** 112,120 **** int con, struct fb_info* info); - #ifdef USE_MMAP static int e1356fb_mmap(struct fb_info *info, struct file *file, struct vm_area_struct *vma); - #endif /* --- 111,117 ---- *************** *** 198,204 **** fb_pan_display: e1356fb_pan_display, fb_ioctl: e1356fb_ioctl, - #ifdef USE_MMAP fb_mmap: e1356fb_mmap, - #endif }; --- 195,199 ---- *************** *** 257,275 **** * ------------------------------------------------------------------------- */ ! #ifdef CONFIG_MIPS_PB1000 ! // MIPS memset_io does 32-bit word writes. Frame buffer ! // accesses on the Alchemy Pb1000 board can only be 8 ! // or 16 bits wide. static inline void ! mymemset_io(void* addr, u8 val, int size) { ! //u16 valw = (u16)val | ((u16)val << 8); ! //size >>= 1; ! while (size--) ! writeb(val, (u8*)addr++); } - #else - #define mymemset_io memset_io - #endif static inline int --- 252,272 ---- * ------------------------------------------------------------------------- */ ! /* ! * The SED1356 has only a 16-bit wide data bus, so some embedded ! * implementations with 32-bit CPU's (Alchemy Pb1000) may not ! * correctly emulate a 32-bit write to the framebuffer by splitting ! * the write into two seperate 16-bit writes. So it is safest to ! * only do byte or half-word writes to the fb. This routine assumes ! * fbaddr is atleast aligned on a half-word boundary. ! */ static inline void ! fbfill(u16* fbaddr, u8 val, int size) { ! u16 valw = (u16)val | ((u16)val << 8); ! for ( ; size >= 2; size -= 2) ! writew(valw, fbaddr++); ! if (size) ! writeb(val, (u8*)fbaddr); } static inline int *************** *** 1247,1251 **** u16 height, addr_offset; int disp_type = info->fix.disp_type; ! #ifdef E1356FB_VERBOSE_DEBUG dump_par(par); --- 1244,1252 ---- u16 height, addr_offset; int disp_type = info->fix.disp_type; ! int hsync = (1000 * par->ipclk.pixclk) / (par->width + par->horiz_ndp); ! ! DPRINTK("%dx%d-%dbpp @ %d Hz, %d kHz hsync\n", ! par->width, par->height, par->bpp, ! hsync / (par->height + par->vert_ndp), (((2*hsync)/1000)+1)/2); #ifdef E1356FB_VERBOSE_DEBUG dump_par(par); *************** *** 1343,1353 **** writeb(display_mode, &dispmode->disp_mode); ! #ifdef CONFIG_MIPS_PB1000 ! if (info->fix.system == SYS_PB1000 && info->mmaped) writeb(1, &dispmode->start_addr0); else - #else writeb(0, &dispmode->start_addr0); - #endif writeb(0, &dispmode->start_addr1); writeb(0, &dispmode->start_addr2); --- 1344,1351 ---- writeb(display_mode, &dispmode->disp_mode); ! if (info->fix.mmunalign && info->mmaped) writeb(1, &dispmode->start_addr0); else writeb(0, &dispmode->start_addr0); writeb(0, &dispmode->start_addr1); writeb(0, &dispmode->start_addr2); *************** *** 1362,1365 **** --- 1360,1365 ---- #endif + /* clear out framebuffer memory */ + fbfill(fb_info.membase_virt, 0, fb_info.fb_size); // finally, enable display! writeb(main_display_mode, &info->reg.misc->disp_mode); *************** *** 1677,1681 **** int activate = var->activate; int j,k; - int hsync; //DPRINTK("\n"); --- 1677,1680 ---- *************** *** 1689,1696 **** return err; - hsync = (1000 * par.ipclk.pixclk) / (par.width + par.horiz_ndp); - printk("e1356fb: mode selected: %dx%d-%d @ %d Hz, %d kHz hsync\n", - par.width, par.height, par.bpp, - hsync / (par.height + par.vert_ndp), (((2*hsync)/1000)+1)/2); if (info->fix.tv_filt & TV_FILT_FLICKER) printk("e1356fb: TV flicker filter enabled\n"); --- 1688,1691 ---- *************** *** 1884,1888 **** - #ifdef USE_MMAP static int e1356fb_mmap(struct fb_info *fb, --- 1879,1882 ---- *************** *** 1946,1968 **** pgprot_val(vma->vm_page_prot) |= (_PAGE_DIRTY | _PAGE_VALID); - #ifdef CONFIG_MIPS_PB1000 /* ! * The Pb1000 does not handle 32-bit load/stores to the ! * SED1356 display memory, only 8 or 16-bit accesses work. ! * So do this: intentionally return a non-32-bit-aligned VA. ! * This way the MIPS unaligned exception handler will emulate ! * the load/store instructions by splitting up the 32-bit ! * load/store into two 16-bit load/stores (thanks Ralf!). ! * Address error emulation is currently enabled by default, ! * but this feature 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. */ ! if (info->fix.system == SYS_PB1000) vma->vm_start += 2; ! #endif ! if (io_remap_page_range(vma->vm_start, off, vma->vm_end - vma->vm_start, --- 1940,1970 ---- 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, *************** *** 1973,1977 **** return 0; } - #endif --- 1975,1978 ---- *************** *** 2109,2117 **** */ ! #ifdef CONFIG_MIPS_PB1000 ! if (epfix->system == SYS_PB1000) { ! extern unsigned int get_au1000_lcd_clock(void); epfix->busclk = get_au1000_lcd_clock(); - } #endif --- 2110,2116 ---- */ ! #ifdef CONFIG_MIPS_AU1000 ! if (epfix->system == SYS_PB1000) epfix->busclk = get_au1000_lcd_clock(); #endif *************** *** 2264,2271 **** fb_info.fb_info.changevar = NULL; fb_info.fb_info.node = -1; ! #ifdef USE_MMAP ! if (epfix->system != SYS_PB1000) ! e1356fb_ops.fb_mmap = NULL; ! #endif fb_info.fb_info.fbops = &e1356fb_ops; fb_info.fb_info.disp = &fb_info.disp; --- 2263,2267 ---- fb_info.fb_info.changevar = NULL; fb_info.fb_info.node = -1; ! fb_info.fb_info.fbops = &e1356fb_ops; fb_info.fb_info.disp = &fb_info.disp; *************** *** 2391,2397 **** writeb(0, ®->misc->cpu2mem_watchdog); // disable watchdog timer - /* clear framebuffer memory */ - mymemset_io(fb_info.membase_virt, 0, fb_info.fb_size); - #ifdef E1356FB_VERBOSE_DEBUG dump_fb(fb_info.membase_virt + 0x100000, 512); --- 2387,2390 ---- *************** *** 2408,2413 **** fb_info.fb_info.modename); - /* FIXME: module cannot be unloaded */ - /* verify e1356fb_exit before removing this */ MOD_INC_USE_COUNT; --- 2401,2404 ---- *************** *** 2479,2482 **** --- 2470,2476 ---- } else if (!strncmp(this_opt, "nohwcursor", 10)) { boot_fix.nohwcursor = 1; + } else if (!strncmp(this_opt, "mmunalign:", 10)) { + boot_fix.mmunalign = simple_strtoul(this_opt+10, + NULL, 0); #ifdef CONFIG_MTRR } else if (!strncmp(this_opt, "nomtrr", 6)) { *************** *** 2795,2799 **** e1356fb_createcursor(struct display *p) { ! u8* memcursor; int y, w, h, u; --- 2789,2793 ---- e1356fb_createcursor(struct display *p) { ! void* memcursor; int y, w, h, u; *************** *** 2802,2815 **** h = fb_info.cursor.h; w = fb_info.cursor.w; u = fb_info.cursor.u; ! memcursor = (u8*)fb_info.membase_virt + fb_info.fb_size; // write cursor to display memory for (y=0; y<64; y++) { if (y >= h || y < u) { ! mymemset_io(memcursor, 0xaa, 16); // b/g } else { ! mymemset_io(memcursor, 0xff, w/4); // inverted b/g ! mymemset_io(memcursor + w/4, 0xaa, (64 - w)/4); // b/g } memcursor += 16; --- 2796,2810 ---- h = fb_info.cursor.h; w = fb_info.cursor.w; + DPRINTK("w=%d\n", w); u = fb_info.cursor.u; ! memcursor = fb_info.membase_virt + fb_info.fb_size; // write cursor to display memory for (y=0; y<64; y++) { if (y >= h || y < u) { ! fbfill((u16*)memcursor, 0xaa, 16); // b/g } else { ! fbfill((u16*)memcursor, 0xff, w/4); // inverted b/g ! fbfill((u16*)memcursor + w/4, 0xaa, (64 - w)/4); // b/g } memcursor += 16; Index: epson1356fb.h =================================================================== RCS file: /cvsroot/linux-mips/linux/drivers/video/epson1356fb.h,v retrieving revision 1.3 retrieving revision 1.4 diff -C2 -d -r1.3 -r1.4 *** epson1356fb.h 2001/08/30 21:41:05 1.3 --- epson1356fb.h 2001/09/12 22:23:31 1.4 *************** *** 331,334 **** --- 331,335 ---- #endif int nohwcursor; + int mmunalign; // force unaligned returned VA in mmap() char fontname[40]; *************** *** 482,485 **** --- 483,487 ---- #endif 0, + 0, {0}, "800x600@60" *************** *** 514,517 **** --- 516,520 ---- #endif 0, + 0, {0}, "800x600@60" *************** *** 543,546 **** --- 546,550 ---- 0, #endif + 0, 0, {0}, |