--- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -255,6 +255,25 @@ config FB_CIRRUS Say N unless you have such a graphics board or plan to get one before you next recompile the kernel. +config FB_EP93XX + tristate "EP93xx frame buffer support" + depends on FB + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + help + This is the frame buffer device driver for the internal raster engine + on certain members of the EP93xx family. For VGA and LCD output. + +config FB_EP93XX_MONO + tristate "EP93xx Mono frame buffer support" + depends on FB + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + help + This is the frame buffer device driver for the internal raster engine + on certain members of the EP93xx family. For LCD output. + config FB_PM2 tristate "Permedia2 support" depends on FB && ((AMIGA && BROKEN) || PCI) --- a/drivers/video/Makefile +++ b/drivers/video/Makefile @@ -95,6 +95,8 @@ obj-$(CONFIG_FB_ARMCLCD) += amba-clcd. obj-$(CONFIG_FB_68328) += 68328fb.o obj-$(CONFIG_FB_GBE) += gbefb.o obj-$(CONFIG_FB_CIRRUS) += cirrusfb.o +obj-$(CONFIG_FB_EP93XX) += ep93xxfb.o +obj-$(CONFIG_FB_EP93XX_MONO) += ep93xxfb_mono.o obj-$(CONFIG_FB_ASILIANT) += asiliantfb.o obj-$(CONFIG_FB_PXA) += pxafb.o obj-$(CONFIG_FB_W100) += w100fb.o --- /dev/null +++ b/drivers/video/ep93xxfb.c @@ -0,0 +1,1628 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "ep93xxfb.h" +#include +#include + +#include "console/fbcon.h" + + +#if defined(CONFIG_MACH_EDB9312) || defined(CONFIG_MACH_EDB9315) || defined(CONFIG_MACH_EDB9307) || defined(CONFIG_MACH_EDB9301) || defined(CONFIG_MACH_EDB9302) +#define CONFIG_EP93XX_SDCS3 +#else +#define CONFIG_EP93XX_SDCS0 +#endif + +//#define DEBUG 1 +#ifdef DEBUG +#define DPRINTK( fmt, arg... ) printk( fmt, ##arg ) +#else +#define DPRINTK( fmt, arg... ) +#endif + +#define FBDEV_NAME "ep93xxfb" + +#define ep93xxfb_outl(value, reg) \ +{ \ + outl(RASTER_SWLOCK_VALUE, RASTER_SWLOCK); \ + outl(value, reg); \ +} + +#define DEFAULT_OUT CRT_OUT +#define DEFAULT_MODE 7 +#define DEFAULT_BPP 24 + +static DECLARE_WAIT_QUEUE_HEAD(ep93xxfb_wait_in); + +static unsigned int pseudo_palette[256]; +static unsigned long *cursor_data = NULL; +static struct ep93xxfb_info epinfo; + +static int vout = DEFAULT_OUT; +static int vmode = DEFAULT_MODE; +static int depth = DEFAULT_BPP; + + +static int ep93xxfb_setcol(struct fb_info *info, int bpp); + + +static struct ep93xxfb_videomodes ep93xxfb_vmods[] = { + { + "Philips-LB064V02-640x480x60", + 640, 24, 96, 40, 480, 10, 2, 33, 60, + CLK_INTERNAL, EDGE_FALLING, POL_LOW, POL_LOW, POL_LOW, + }, + { // 1 + "CRT-640x480-60", + 640, 24, 96, 40, 480, 11, 2, 32, 60, + CLK_INTERNAL, EDGE_RISING, POL_LOW, POL_LOW, POL_LOW, + }, + { // 2 + "CRT-640x480-72", + 640, 40, 40, 144, 480, 8, 3, 30, 72, + CLK_INTERNAL, EDGE_RISING, POL_LOW, POL_LOW, POL_LOW, + }, + { // 3 + "CRT-640x480-75", + 640, 16, 76, 120, 480, 1, 3, 16, 75, + CLK_INTERNAL, EDGE_RISING, POL_LOW, POL_LOW, POL_LOW, + }, + { // 4 + "CRT-640x480-85", + 640, 56, 56, 80, 480, 1, 3, 25, 85, + CLK_INTERNAL, EDGE_RISING, POL_LOW, POL_LOW, POL_LOW, + }, + { // 5 + "CTR-640x480-100", + 640, 32, 96, 96, 480, 8, 6, 36, 100, + CLK_INTERNAL, EDGE_RISING, POL_LOW, POL_LOW, POL_LOW, + }, + { // 6 + "CRT-800x600-56", + 800, 24, 72, 128, 600, 1, 2, 22, 56, + CLK_INTERNAL, EDGE_RISING, POL_LOW, POL_LOW, POL_LOW, + }, + { // 7 + "CRT-800x600-60", + 800, 40, 128, 88, 600, 1, 4, 23, 60, + CLK_INTERNAL, EDGE_RISING, POL_LOW, POL_HIGH, POL_HIGH, + }, + { // 8 + "CRT-800x600-72", + 800, 56, 120, 64, 600, 37, 6, 23, 72, + CLK_INTERNAL, EDGE_RISING, POL_LOW, POL_LOW, POL_LOW, + }, + { // 9 + "CRT-800x600-85", + 800, 64, 64, 160, 600, 16, 5, 36, 85, + CLK_INTERNAL, EDGE_RISING, POL_LOW, POL_LOW, POL_LOW, + }, + { // 10 + "CRT-800x600-100", + 800, 64, 64, 160, 600, 4, 6, 30, 100, + CLK_INTERNAL, EDGE_RISING, POL_LOW, POL_LOW, POL_LOW, + }, + { // 11 + "CRT-1024x768-60", + 1024, 8, 144, 168, 768, 3, 6, 29, 60, + CLK_INTERNAL, EDGE_RISING, POL_LOW, POL_LOW, POL_LOW, + }, + { // 12 + "CRT-1024x768-70", + 1024, 24, 136, 144, 768, 3, 6, 29, 70, + CLK_INTERNAL, EDGE_RISING, POL_LOW, POL_LOW, POL_LOW, + }, + { // 13 + "CRT-1024x768-75", + 1024, 16, 96, 176, 768, 1, 3, 28, 75, + CLK_INTERNAL, EDGE_RISING, POL_LOW, POL_HIGH, POL_HIGH, + }, + { // 14 + "CRT-1024x768-85", + 1024, 48, 96, 208, 768, 1, 3, 36, 85, + CLK_INTERNAL, EDGE_RISING, POL_LOW, POL_HIGH, POL_HIGH, + }, + { // 15 + "CRT-1280x720-60", + 1280, 48, 112, 248, 720, 1, 3, 38, 60, + CLK_INTERNAL, EDGE_RISING, POL_LOW, POL_HIGH, POL_HIGH, + } +}; + +static void philips_lb064v02_on(unsigned char value) +{ + DPRINTK("philips_lb064v02_on \n"); + outl(inl(GPIO_PADDR) | 2, GPIO_PADDR); + outl(inl(GPIO_PADR) | 2, GPIO_PADR); +} + +static void philips_lb064v02_off(unsigned char value) +{ + DPRINTK("philips_lb064v02_off \n"); + outl(inl(GPIO_PADR) & ~2, GPIO_PADR); +} + +static irqreturn_t ep93xxfb_irq_handler(int i, void *blah) +{ + outl(0x00000000, BLOCKCTRL); + wake_up(&ep93xxfb_wait_in); + return IRQ_HANDLED; +} + +static void ep93xxfb_wait(void) +{ + DECLARE_WAITQUEUE(wait, current); + add_wait_queue(&ep93xxfb_wait_in, &wait); + set_current_state(TASK_UNINTERRUPTIBLE); + + while (inl(BLOCKCTRL) & 0x00000001){ + if(/*(pls_proba==1)&&*/(!in_atomic())) + schedule(); + } + + remove_wait_queue(&ep93xxfb_wait_in, &wait); + set_current_state(TASK_RUNNING); + +} + +void ep93xxfb_fillrect(struct fb_info *p, const struct fb_fillrect *fill) +{ + unsigned long blkdestwidth,tmp; + + if (!fill->width || !fill->height || + (fill->dx >= p->var.xres) || + (fill->dy >= p->var.yres) || + ((fill->dx + fill->width - 1) >= p->var.xres) || + ((fill->dy + fill->height - 1) >= p->var.yres)) + return; + + tmp = (( fill->dx + fill->width ) * epinfo.bpp ); + blkdestwidth = tmp / 32; + if(blkdestwidth > 0 && (tmp % 32 == 0)) + blkdestwidth--; + blkdestwidth = blkdestwidth - (fill->dx * epinfo.bpp) / 32; + + outl(fill->color, BLOCKMASK); + outl( ((fill->dx * epinfo.bpp) & 0x1F) | + ((((fill->dx + fill->width - 1) * epinfo.bpp ) & 0x1F) << 16), + DESTPIXELSTRT); + outl( ((epinfo.xres * epinfo.bpp) / 32), DESTLINELENGTH); + outl( blkdestwidth, BLKDESTWIDTH ); + outl(fill->height - 1, BLKDESTHEIGHT); + outl((epinfo.fb_phys + (fill->dy * epinfo.xres * epinfo.bpp ) / 8 + + (fill->dx * epinfo.bpp ) / 8 ) + , BLKDSTSTRT); + outl( epinfo.pixformat | 0x0000000B, BLOCKCTRL); + ep93xxfb_wait(); + +} + +void ep93xxfb_copyarea(struct fb_info *p, const struct fb_copyarea *area) +{ + unsigned long startsx,stopsx,startdx,stopdx,startsy,startdy; + unsigned long blksrcwidth,blkdestwidth,tmp; + unsigned long val = 0; + + if( !area->width || !area->width || + (area->sx >= p->var.xres) || (area->sy >= p->var.yres) || + (area->dx >= p->var.xres) || (area->dy >= p->var.yres) || + ((area->dx + area->width - 1) >= p->var.xres) || + ((area->dy + area->height - 1) >= p->var.yres)) + return; + + if(area->sx == area->dx && area->sy == area->dy) + return; + + if ((area->dy == area->sy) && (area->dx > area->sx) && + (area->dx < (area->sx + area->width - 1))) { + startdx = area->dx + area->width - 1; + stopdx = area->dx; + startsx = area->sx + area->width - 1; + stopsx = area->sx; + val |= 0x000000A0; + } + else { + startdx = area->dx; + stopdx = area->dx + area->width - 1; + startsx = area->sx; + stopsx = area->sx + area->width - 1; + } + + if (area->dy <= area->sy) { + startdy = area->dy; + startsy = area->sy; + } + else { + startdy = area->dy + area->height -1; + startsy = area->sy + area->height -1; + val |= 0x00000140; + } + + tmp = (( area->sx + area->width ) * epinfo.bpp ); + blksrcwidth = tmp / 32; + if(blksrcwidth > 0 && (tmp % 32 == 0)) + blksrcwidth--; + blksrcwidth = blksrcwidth - (area->sx * epinfo.bpp) / 32; + + tmp = (( area->dx + area->width ) * epinfo.bpp ); + blkdestwidth = tmp / 32; + if(blkdestwidth > 0 && (tmp % 32 == 0)) + blkdestwidth--; + blkdestwidth = blkdestwidth - (area->dx * epinfo.bpp) / 32; + + outl( 0x00000000 , BLOCKCTRL); + + /*** src ***/ + outl((((startsx * epinfo.bpp) & 0x1F) | + (((stopsx * epinfo.bpp ) & 0x1F) << 16)) + , SRCPIXELSTRT); + outl((epinfo.fb_phys + (startsy * epinfo.xres * epinfo.bpp ) / 8 + + (startsx * epinfo.bpp ) / 8 ) + , BLKSRCSTRT); + outl(((epinfo.xres * epinfo.bpp) / 32), SRCLINELENGTH); + outl( blksrcwidth, BLKSRCWIDTH ); + + /*** dest ***/ + outl((((startdx * epinfo.bpp) & 0x1F) | + (((stopdx * epinfo.bpp ) & 0x1F) << 16)) + , DESTPIXELSTRT); + outl((epinfo.fb_phys + (startdy * epinfo.xres * epinfo.bpp ) / 8 + + (startdx * epinfo.bpp ) / 8 ) + , BLKDSTSTRT); + outl( ((epinfo.xres * epinfo.bpp) / 32), DESTLINELENGTH); + outl( blkdestwidth, BLKDESTWIDTH); + outl( area->height - 1 , BLKDESTHEIGHT); + outl( epinfo.pixformat | val | 0x00000003, BLOCKCTRL); + ep93xxfb_wait(); +} + +void ep93xxfb_imageblit(struct fb_info *p, const struct fb_image *image) +{ +// unsigned long blkdestwidth,tmp; +// void * pucBlitBuf; + cfb_imageblit( p , image ); + return; +/* + if ((image->dx >= p->var.xres) || + (image->dy >= p->var.yres) || + ((image->dx + image->width - 1) >= p->var.xres) || + ((image->dy + image->height - 1) >= p->var.yres)) + return; + if (epinfo.bpp != image->depth ) + return; + + tmp = (( image->dx + image->width ) * epinfo.bpp ); + blkdestwidth = tmp / 32; + if(blkdestwidth > 0 && (tmp % 32 == 0)) + blkdestwidth--; + blkdestwidth = blkdestwidth - (image->dx * epinfo.bpp) / 32; + + pucBlitBuf = kmalloc(1024*8,GFP_KERNEL); + copy_from_user(pucBlitBuf, image->data, 5000); + + outl( 0x00000000 , BLOCKCTRL); + + outl( 0x00000000, SRCPIXELSTRT); + outl( virt_to_phys(pucBlitBuf), BLKSRCSTRT); + outl( (image->width * epinfo.bpp) / 32 , SRCLINELENGTH); + outl(((image->width - 1) * epinfo.bpp) / 32, BLKSRCWIDTH ); + + outl(((image->dx * epinfo.bpp) & 0x1F) | + ((((image->dx + image->width - 1) * epinfo.bpp ) & 0x1F) << 16) + , DESTPIXELSTRT); + outl((epinfo.fb_phys + (image->dy * epinfo.xres * epinfo.bpp ) / 8 + + (image->dx * epinfo.bpp ) / 8 ) + , BLKDSTSTRT); + outl( ((epinfo.xres * epinfo.bpp) / 32), DESTLINELENGTH ); + outl( blkdestwidth, BLKDESTWIDTH ); + outl( image->height - 1 , BLKDESTHEIGHT); + outl(image->fg_color, BLOCKMASK); + outl(image->bg_color, BACKGROUND); + outl( epinfo.pixformat | 0x00000003, BLOCKCTRL ); + ep93xxfb_wait(); +*/ +} + + +static unsigned long isqrt(unsigned long a) +{ + unsigned long rem = 0; + unsigned long root = 0; + int i; + + for (i = 0; i < 16; i++) { + root <<= 1; + rem = ((rem << 2) + (a >> 30)); + a <<= 2; + root++; + if (root <= rem) { + rem -= root; + root++; + } + else + root--; + } + return root >> 1; +} + +int ep93xxfb_line(struct fb_info *info, struct ep93xx_line *line) +{ + unsigned long value = 0; + long x, y, dx, dy, count, xinc, yinc, xval, yval, incr; + + if ((line->x1 > info->var.xres) || + (line->x2 > info->var.xres) || + (line->y1 > info->var.yres) || + (line->y2 > info->var.yres)) + return -EFAULT; + x = line->x1; + y = line->y1; + dx = line->x2 - line->x1; + dy = line->y2 - line->y1; + + if ( !dx || !dy ) + return -EFAULT; + + if ( dx < 0 && dy < 0 ) { + x = line->x2; + y = line->y2; + dx *= -1; + dy *= -1; + } + else if ( dx < 0 && dy > 0 ){ + dx *= -1; + value = 0x000000A0; + } + else if( dy < 0 && dx > 0 ){ + dy *= -1; + value = 0x00000140; + } + + if (line->flags & LINE_PRECISE) { + count = isqrt(((dy * dy) + (dx * dx)) * 4096); + xinc = (4095 * 64 * dx) / count; + yinc = (4095 * 64 * dy) / count; + xval = 2048; + yval = 2048; + count = 0; + while (dx || dy) { + incr = 0; + xval -= xinc; + if (xval <= 0) { + xval += 4096; + dx--; + incr = 1; + } + yval -= yinc; + if (yval <= 0) { + yval += 4096; + dy--; + incr = 1; + } + count += incr; + } + } + else { + if ( dx == dy ) { + xinc = 4095; + yinc = 4095; + count = dx; + + } + else if ( dx < dy ) { + xinc = ( dx * 4095 ) / dy; + yinc = 4095; + count = dy; + + } + else { + xinc = 4095; + yinc = ( dy * 4095 ) / dx; + count = dx; + } + } + + outl(0x08000800, LINEINIT); + if (line->flags & LINE_PATTERN) + outl(line->pattern, LINEPATTRN); + else + outl(0x000fffff, LINEPATTRN); + outl(epinfo.fb_phys + ((y * epinfo.xres * epinfo.bpp) / 8) + + ((x * epinfo.bpp ) / 8 ), BLKDSTSTRT); + + outl(((x * epinfo.bpp) & 0x1F) | + ((((x + dx - 1) * epinfo.bpp) & 0x1F ) << 16), + DESTPIXELSTRT); + outl((epinfo.xres * epinfo.bpp) / 32, DESTLINELENGTH); + outl(line->fgcolor, BLOCKMASK); + outl(line->bgcolor, BACKGROUND); + outl((yinc << 16) | xinc, LINEINC); + outl( count & 0xFFF, BLKDESTWIDTH); + outl( 0 , BLKDESTHEIGHT); + value |= (line->flags & LINE_BACKGROUND) ? 0x00004000 : 0; + outl(epinfo.pixformat | value | 0x00000013, BLOCKCTRL); + ep93xxfb_wait(); + return 0; +} + +int ioctl_cursor=0; + +int ep93xxfb_cursor(struct fb_info *info, struct ep93xx_cursor *cursor) +{ + unsigned long x,y,save; + + if((cursor->width ==0) || (cursor->height ==0) ) + { + struct fb_cursor *fbcon_cursor =(struct fb_cursor *)cursor; + struct fbcon_ops *ops = (struct fbcon_ops *)info->fbcon_par; + unsigned int scan_align = info->pixmap.scan_align - 1; + unsigned int buf_align = info->pixmap.buf_align - 1; + unsigned int i, size, dsize, s_pitch, d_pitch; + struct fb_image *image; + u8 *src, *dst; + + if(ioctl_cursor==1 ){ + DPRINTK("softcursor error return\n"); + return 0; + } + + + if (info->state != FBINFO_STATE_RUNNING) + return 0; + + s_pitch = (fbcon_cursor->image.width + 7) >> 3; + dsize = s_pitch * fbcon_cursor->image.height; + + if (dsize + sizeof(struct fb_image) != ops->cursor_size) { + if (ops->cursor_src != NULL) + kfree(ops->cursor_src); + ops->cursor_size = dsize + sizeof(struct fb_image); + + ops->cursor_src = kmalloc(ops->cursor_size, GFP_ATOMIC); + if (!ops->cursor_src) { + ops->cursor_size = 0; + return -ENOMEM; + } + } + src = ops->cursor_src + sizeof(struct fb_image); + image = (struct fb_image *)ops->cursor_src; + *image = fbcon_cursor->image; + d_pitch = (s_pitch + scan_align) & ~scan_align; + + size = d_pitch * image->height + buf_align; + size &= ~buf_align; + dst = fb_get_buffer_offset(info, &info->pixmap, size); + + if (fbcon_cursor->enable) { + switch (fbcon_cursor->rop) { + case ROP_XOR: + for (i = 0; i < dsize; i++) + src[i] = image->data[i] ^ fbcon_cursor->mask[i]; + break; + case ROP_COPY: + default: + for (i = 0; i < dsize; i++) + src[i] = image->data[i] & fbcon_cursor->mask[i]; + break; + } + } else + memcpy(src, image->data, dsize); + + fb_pad_aligned_buffer(dst, d_pitch, src, s_pitch, image->height); + image->data = dst; + info->fbops->fb_imageblit(info, image); + return 0; + + } + else{ + ioctl_cursor = 1; + + /*if (cursor->width > 16 || cursor->height > 16){ + DPRINTK("%s width %d or heright %d error\n",__FUNCTION__,cursor->width,cursor->height); + return -ENXIO; + }*/ + + if (cursor->flags & CURSOR_OFF) + outl(inl(CURSORXYLOC) & ~0x00008000, CURSORXYLOC); + + if (cursor->flags & CURSOR_SETSHAPE) { + copy_from_user(cursor_data, cursor->data, + cursor->width * cursor->height / 4); + save = inl(CURSORXYLOC); + outl(save & ~0x00008000, CURSORXYLOC); + + outl(virt_to_phys(cursor_data), CURSOR_ADR_START); + outl(virt_to_phys(cursor_data), CURSOR_ADR_RESET); + outl(((cursor->width - 1) & 0x30) << 4 | ((cursor->height - 1) << 2) | + ((cursor->width - 1) >> 4), CURSORSIZE); + outl(save, CURSORXYLOC); + + } + + if (cursor->flags & CURSOR_SETCOLOR) { + outl(cursor->color1, CURSORCOLOR1); + outl(cursor->color2, CURSORCOLOR2); + outl(cursor->blinkcolor1, CURSORBLINK1); + outl(cursor->blinkcolor2, CURSORBLINK2); + } + + if (cursor->flags & CURSOR_BLINK) { + if (cursor->blinkrate) + outl(0x00000100 | cursor->blinkrate, CURSORBLINK); + else + outl(0x0000000FF, CURSORBLINK); + } + + if (cursor->flags & CURSOR_MOVE) { + x = (inl(HACTIVESTRTSTOP) & 0x000007ff) - cursor->dx - 2; + y = (inl(VACTIVESTRTSTOP) & 0x000007ff) - cursor->dy; + outl((inl(CURSORXYLOC) & 0x8000) | (y << 16) | x, CURSORXYLOC); + } + + if(cursor->flags & CURSOR_ON) + outl(inl(CURSORXYLOC) | 0x00008000, CURSORXYLOC); + + return 0; + } +} + + + +static inline void +ep93xxfb_palette_write(u_int regno, u_int red, u_int green, + u_int blue, u_int trans) +{ + unsigned int cont, i, pal; + DPRINTK("ep93xxfb_palette_write - enter\n"); + pal = ((red & 0xFF00) << 8) | (green & 0xFF00) | ((blue & 0xFF00) >> 8); + pseudo_palette[regno] = pal; + outl( pal, ( COLOR_LUT + ( regno << 2 ))); + cont = inl( LUTCONT ); + + if (( cont & LUTCONT_STAT && cont & LUTCONT_RAM1 ) || + ( !( cont & LUTCONT_STAT ) && !( cont&LUTCONT_RAM1 ))) { + for ( i = 0; i < 256; i++ ) { + outl( pseudo_palette[i], ( COLOR_LUT + ( i << 2 )) ); + } + outl( cont ^ LUTCONT_RAM1, LUTCONT ); + } +} + +int ep93xxfb_setcolreg(unsigned regno, unsigned red, unsigned green, + unsigned blue, unsigned transp, + struct fb_info *info) +{ + +#define CNVT_TOHW(val,width) ((((val)<<(width))+0x7FFF-(val))>>16) + + switch ( info->fix.visual ) + { + case FB_VISUAL_PSEUDOCOLOR: + ep93xxfb_palette_write(regno, red, green, blue, transp); + break; + case FB_VISUAL_TRUECOLOR: + if (regno >= 16) + return 1; + red = CNVT_TOHW(red, info->var.red.length); + green = CNVT_TOHW(green, info->var.green.length); + blue = CNVT_TOHW(blue, info->var.blue.length); + transp = CNVT_TOHW(transp, info->var.transp.length); + ((u32 *)(info->pseudo_palette))[regno] = + (red << info->var.red.offset) | + (green << info->var.green.offset) | + (blue << info->var.blue.offset) | + (transp << info->var.transp.offset); + break; + case FB_VISUAL_DIRECTCOLOR: + red = CNVT_TOHW(red, 8); + green = CNVT_TOHW(green, 8); + blue = CNVT_TOHW(blue, 8); + transp = CNVT_TOHW(transp, 8); + break; + } +#undef CNVT_TOHW + return 0; +} + +static int ep93xx_pan_display(struct fb_var_screeninfo *var, + struct fb_info *info) +{ + DPRINTK("ep93xx_pan_display - enter\n"); + + if (var->yoffset < 0 + || var->yoffset + var->yres > info->var.yres_virtual + || var->xoffset) + return -EINVAL; + + outl(epinfo.fb_phys + info->fix.line_length * var->yoffset + , VIDSCRNPAGE); + + info->var.xoffset = var->xoffset; + info->var.yoffset = var->yoffset; + + DPRINTK("ep93xx_pan_display - exit\n"); + return 0; +} + + +static int +ep93xxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) +{ + struct fb_var_screeninfo tmp_var; + unsigned long pclk; + DPRINTK("ep93xxfb_check_var - enter\n"); + + if( vout != 0) { + printk(" ep93xxfb_check_var - vout != 0\n"); + return -EINVAL; + } + + memcpy (&tmp_var, var, sizeof (tmp_var)); + + if( (tmp_var.vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED ) { + printk(" ep93xxfb_check_var - unsupported video mode\n"); + return -EINVAL; + } + + if( ((tmp_var.xres * tmp_var.yres * tmp_var.bits_per_pixel) / 8) > + MAX_FBMEM_SIZE ) { + printk(" ep93xxfb_check_var - memory error \n"); + return -ENOMEM; + } + + if( ((tmp_var.xres_virtual * tmp_var.yres_virtual * tmp_var.bits_per_pixel) / 8) > + MAX_FBMEM_SIZE ) { + printk(" ep93xxfb_check_var - memory error \n"); + return -ENOMEM; + } + + pclk = 1000 * (1000000000 / tmp_var.pixclock); + + if( pclk > ep93xx_get_max_video_clk() ) { + printk(" ep93xxfb_check_var - pixel clock error %lu\n",pclk); + return -EINVAL; + } + + if (var->xres_virtual != var->xres) + var->xres_virtual = var->xres; + if (var->yres_virtual < var->yres) + var->yres_virtual = var->yres; + + if (var->xoffset < 0) + var->xoffset = 0; + if (var->yoffset < 0) + var->yoffset = 0; + + switch (tmp_var.bits_per_pixel) { + case 8: + break; + case 16: + break; + case 24: + break; + case 32: + break; + default: + return -EINVAL; + } + + DPRINTK("ep93xxfb_check_var - exit\n"); + return 0; +} + + +static int ep93xxfb_set_par(struct fb_info *info) +{ + struct fb_var_screeninfo tmp_var; + unsigned long attribs; + + DPRINTK("ep93xxfb_set_par - enter\n"); + + if( ep93xxfb_check_var(&info->var,info) < 0 ) + return -EINVAL; + + if( !ep93xxfb_setcol(info,info->var.bits_per_pixel) ) + return -EINVAL; + + + info->fix.line_length = (info->var.xres * info->var.bits_per_pixel) / 8; + + ep93xxfb_blank( 1 , info ); + + memcpy(&tmp_var,&info->var,sizeof(tmp_var)); + + epinfo.xres = tmp_var.xres; + epinfo.xsync = tmp_var.hsync_len; + epinfo.xfp = tmp_var.right_margin; + epinfo.xbp = tmp_var.left_margin; + epinfo.xtotal = epinfo.xres + epinfo.xsync + + epinfo.xfp + epinfo.xbp; + + epinfo.yres = tmp_var.yres; + epinfo.ysync = tmp_var.vsync_len; + epinfo.yfp = tmp_var.lower_margin; + epinfo.ybp = tmp_var.upper_margin; + epinfo.ytotal = epinfo.yres + epinfo.ysync + + epinfo.yfp + epinfo.ybp; + + epinfo.pixclock = tmp_var.pixclock ; + epinfo.refresh = 1000 * (1000000000 / tmp_var.pixclock) ; + + if( epinfo.refresh > ep93xx_get_max_video_clk()) + epinfo.refresh = ep93xx_get_max_video_clk(); + epinfo.bpp = tmp_var.bits_per_pixel; + + ep93xxfb_setclk(); + ep93xxfb_timing_signal_generation(); + + // set video memory parameters + outl(epinfo.fb_phys, VIDSCRNPAGE); + outl(epinfo.yres , SCRNLINES); + outl(((epinfo.xres * epinfo.bpp) / 32) - 1, LINELENGTH); + outl((epinfo.xres * epinfo.bpp) / 32, VLINESTEP); + + // set pixel mode + ep93xxfb_pixelmod(epinfo.bpp); + + attribs = 0; +#ifdef CONFIG_EP93XX_SDCS0 + attribs |= 0 << VIDEOATTRIBS_SDSEL_SHIFT; +#endif +#ifdef CONFIG_EP93XX_SDCS1 + attribs |= 1 << VIDEOATTRIBS_SDSEL_SHIFT; +#endif +#ifdef CONFIG_EP93XX_SDCS2 + attribs |= 2 << VIDEOATTRIBS_SDSEL_SHIFT; +#endif +#ifdef CONFIG_EP93XX_SDCS3 + attribs |= 3 << VIDEOATTRIBS_SDSEL_SHIFT; +#endif + + attribs |= VIDEOATTRIBS_INVCLK; + if( tmp_var.sync & FB_SYNC_HOR_HIGH_ACT ) + attribs |= VIDEOATTRIBS_HSPOL; + if( tmp_var.sync & FB_SYNC_VERT_HIGH_ACT ) + attribs |= VIDEOATTRIBS_VCPOL; + + ep93xxfb_outl(attribs, VIDEOATTRIBS); + ep93xxfb_blank( 0 , info ); + + DPRINTK("ep93xxfb_set_par - exit\n"); + + return 0; +} + + +static int ep93xxfb_blank(int blank_mode,struct fb_info *info) +{ + unsigned long attribs; + DPRINTK("ep93xxfb_blank - enter\n"); + attribs = inl(VIDEOATTRIBS); + +#ifdef CONFIG_EP93XX_SDCS0 + attribs |= 0 << VIDEOATTRIBS_SDSEL_SHIFT; +#endif +#ifdef CONFIG_EP93XX_SDCS1 + attribs |= 1 << VIDEOATTRIBS_SDSEL_SHIFT; +#endif +#ifdef CONFIG_EP93XX_SDCS2 + attribs |= 2 << VIDEOATTRIBS_SDSEL_SHIFT; +#endif +#ifdef CONFIG_EP93XX_SDCS3 + attribs |= 3 << VIDEOATTRIBS_SDSEL_SHIFT; +#endif + + if (blank_mode) { + if (epinfo.off) + (epinfo.off)( 0 ); + + ep93xxfb_outl(attribs & ~(VIDEOATTRIBS_DATAEN | + VIDEOATTRIBS_SYNCEN | VIDEOATTRIBS_PCLKEN | + VIDEOATTRIBS_EN), VIDEOATTRIBS); + } + else { + if (epinfo.clk_src == CLK_INTERNAL) + attribs |= VIDEOATTRIBS_PCLKEN; + else + attribs &= ~VIDEOATTRIBS_PCLKEN; + + ep93xxfb_outl(attribs | VIDEOATTRIBS_DATAEN | + VIDEOATTRIBS_SYNCEN | VIDEOATTRIBS_EN, + VIDEOATTRIBS); + + if (epinfo.configure) + (epinfo.configure)( epinfo.automods ); + if (epinfo.on) + (epinfo.on)( 0 ); + } + return 0; +} + +static int ep93xxfb_mmap(struct fb_info *info,struct vm_area_struct *vma) +{ + unsigned long off, start, len; + + DPRINTK("ep93xxfb_mmap - enter\n"); + + off = vma->vm_pgoff << PAGE_SHIFT; + start = info->fix.smem_start; + len = PAGE_ALIGN(start & ~PAGE_MASK) + info->fix.smem_len; + start &= PAGE_MASK; + if ((vma->vm_end - vma->vm_start + off) > len) + return -EINVAL; + + off += start; + vma->vm_pgoff = off >> PAGE_SHIFT; + + vma->vm_flags |= VM_IO; + vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); + + if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT, + vma->vm_end - vma->vm_start, vma->vm_page_prot)) { + DPRINTK("ep93xxfb_mmap error\n"); + return -EAGAIN; + } + + DPRINTK("ep93xxfb_mmap - exit\n"); + return 0; +} + +static unsigned long ep93xx_get_pll_frequency(unsigned long pll) +{ + unsigned long fb1, fb2, ipd, ps, freq; + + if (pll == 1) + pll = inl(EP93XX_SYSCON_CLOCK_SET1); + else if (pll == 2) + pll = inl(EP93XX_SYSCON_CLOCK_SET2); + else + return 0; + + ps = (pll & SYSCON_CLKSET1_PLL1_PS_MASK) >> SYSCON_CLKSET1_PLL1_PS_SHIFT; + fb1 = ((pll & SYSCON_CLKSET1_PLL1_X1FBD1_MASK) >> SYSCON_CLKSET1_PLL1_X1FBD1_SHIFT); + fb2 = ((pll & SYSCON_CLKSET1_PLL1_X2FBD2_MASK) >> SYSCON_CLKSET1_PLL1_X2FBD2_SHIFT); + ipd = ((pll & SYSCON_CLKSET1_PLL1_X2IPD_MASK) >> SYSCON_CLKSET1_PLL1_X2IPD_SHIFT); + + freq = (((0x00e10000 * (fb1+1)) / (ipd+1)) * (fb2+1)) >> ps; + return freq; +} + +static int ep93xx_get_max_video_clk() +{ + unsigned long f,freq = 0; + + freq = 14745600 / 4; + f = ep93xx_get_pll_frequency(1) / 4; + if ( f > freq ) + freq = f; + f = ep93xx_get_pll_frequency(2) / 4; + if ( f > freq ) + freq = f; + + return freq; +} + +static int ep93xx_set_video_div(unsigned long freq) +{ + unsigned long pdiv = 0, div = 0, psel = 0, esel = 0; + unsigned long err, f, i, j, k; + + err = -1; + + for (i = 0; i < 3; i++) { + if (i == 0) + f = 14745600 * 2; + else if (i == 1) + f = ep93xx_get_pll_frequency(1) * 2; + else + f = ep93xx_get_pll_frequency(2) * 2; + + for (j = 4; j <= 6; j++) { + k = f / (freq * j); + if (k < 2) + continue; + + if (abs(((f / (j * k))) - freq ) < err ) { + pdiv = j - 3; + div = k; + psel = (i == 2) ? 1 : 0; + esel = (i == 0) ? 0 : 1; + err = (f / (j * k)) - freq; + } + } + } + + if (err == -1) + return -1; + + SysconSetLocked(SYSCON_VIDDIV,SYSCON_VIDDIV_VENA | (esel ? SYSCON_VIDDIV_ESEL : 0) | + (psel ? SYSCON_VIDDIV_PSEL : 0) | + (pdiv << SYSCON_VIDDIV_PDIV_SHIFT) | + (div << SYSCON_VIDDIV_VDIV_SHIFT) + ); + + return freq + err; +} + +static void ep93xxfb_pixelmod(int bpp) +{ + unsigned long tmpdata = 0; + + DPRINTK("ep93xxfb_pixelmod %dbpp -enter\n",bpp); + switch(bpp) { + case 8: + tmpdata = PIXELMODE_P_8BPP | + PIXELMODE_S_1PPCMAPPED | + PIXELMODE_C_LUT; + epinfo.pixformat = PIXEL_FORMAT_8; + break; + case 16: + tmpdata = PIXELMODE_P_16BPP | + PIXELMODE_S_1PPCMAPPED | + PIXELMODE_C_565; + epinfo.pixformat = PIXEL_FORMAT_16; + break; + case 24: + tmpdata = PIXELMODE_P_24BPP | + PIXELMODE_S_1PPC | + PIXELMODE_C_888; + epinfo.pixformat = PIXEL_FORMAT_24; + break; + case 32: + tmpdata = PIXELMODE_P_32BPP | + PIXELMODE_S_1PPC | + PIXELMODE_C_888; + epinfo.pixformat = PIXEL_FORMAT_32; + break; + default: + break; + } + outl(tmpdata,PIXELMODE); +} + +static void ep93xxfb_timing_signal_generation(void) +{ + unsigned long vlinestotal,vsyncstart,vsyncstop, + vactivestart,vactivestop, + vblankstart,vblankstop, + vclkstart,vclkstop; + + unsigned long hclkstotal,hsyncstart,hsyncstop, + hactivestart,hactivestop, + hblankstart,hblankstop, + hclkstart,hclkstop; + + DPRINTK("ep93xxfb_timing_signal_generation - enter\n"); + + vlinestotal = epinfo.ytotal - 1; + vsyncstart = vlinestotal; + vsyncstop = vlinestotal - epinfo.ysync; + vblankstart = vlinestotal - epinfo.ysync - epinfo.ybp; + vblankstop = epinfo.yfp - 1; + vactivestart = vblankstart; + vactivestop = vblankstop; + vclkstart = vlinestotal; + vclkstop = vlinestotal + 1; + + hclkstotal = epinfo.xtotal - 1; + hsyncstart = hclkstotal; + hsyncstop = hclkstotal - epinfo.xsync; + hblankstart = hclkstotal - epinfo.xsync - epinfo.xbp; + hblankstop = epinfo.xfp - 1; + hactivestart = hblankstart; + hactivestop = hblankstop; + hclkstart = hclkstotal ; + hclkstop = hclkstotal ; + + ep93xxfb_outl(0, VIDEOATTRIBS); + + ep93xxfb_outl( vlinestotal , VLINESTOTAL ); + ep93xxfb_outl( vsyncstart + (vsyncstop << 16), VSYNCSTRTSTOP ); + ep93xxfb_outl( vactivestart + (vactivestop << 16), VACTIVESTRTSTOP ); + ep93xxfb_outl( vblankstart + (vblankstop << 16), VBLANKSTRTSTOP ); + ep93xxfb_outl( vclkstart + (vclkstop << 16), VCLKSTRTSTOP ); + + ep93xxfb_outl( hclkstotal , HCLKSTOTAL ); + ep93xxfb_outl( hsyncstart + (hsyncstop << 16), HSYNCSTRTSTOP ); + ep93xxfb_outl( hactivestart + (hactivestop << 16) , HACTIVESTRTSTOP ); + ep93xxfb_outl( hblankstart + (hblankstop << 16) , HBLANKSTRTSTOP ); + ep93xxfb_outl( hclkstart + (hclkstop << 16) , HCLKSTRTSTOP ); + + ep93xxfb_outl(0, LINECARRY); + +} + +static int ep93xxfb_setcol(struct fb_info *info, int bpp) +{ + + DPRINTK("ep93xxfb_setcol %dbpp\n",bpp); + switch(bpp) { + case 8: + info->var.bits_per_pixel = 8; + info->var.red.length = 8; + info->var.green.length = 8; + info->var.blue.length = 8; + info->fix.visual = FB_VISUAL_PSEUDOCOLOR; + break; + case 16: + info->var.bits_per_pixel = 16; + info->var.red.offset = 11; + info->var.red.length = 5; + info->var.green.offset = 5; + info->var.green.length = 6; + info->var.blue.offset = 0; + info->var.blue.length = 5; + info->fix.visual = FB_VISUAL_TRUECOLOR; + break; + case 24: + info->var.bits_per_pixel = 24; + info->var.red.length = 8; + info->var.blue.length = 8; + info->var.green.length = 8; + info->var.red.offset = 16; + info->var.green.offset = 8; + info->var.blue.offset = 0; + info->fix.visual = FB_VISUAL_TRUECOLOR; + break; + case 32: + info->var.bits_per_pixel = 32; + info->var.red.length = 8; + info->var.blue.length = 8; + info->var.green.length = 8; + info->var.transp.length = 0; + info->var.red.offset = 16; + info->var.green.offset = 8; + info->var.blue.offset = 0; + info->var.transp.offset = 0; + info->fix.visual = FB_VISUAL_TRUECOLOR; + break; + default: + return 0; + } + return 1; +} + +static int ep93xxfb_setclk() +{ + unsigned long calc_clk,act_clk; + + if ( epinfo.clk_src == CLK_INTERNAL ) { + SysconSetLocked(EP93XX_SYSCON_DEVICE_CONFIG,inl(EP93XX_SYSCON_DEVICE_CONFIG) & ~EP93XX_SYSCON_DEVICE_CONFIG_CRUNCH_ENABLE); + calc_clk = epinfo.refresh; + act_clk = ep93xx_set_video_div( calc_clk ); + if ( act_clk == -1 ) + return -ENODEV; + + epinfo.refresh = act_clk; + epinfo.pixclock = 1000000000 / (act_clk / 1000); + } + else { + SysconSetLocked(SYSCON_VIDDIV,0); + SysconSetLocked(EP93XX_SYSCON_DEVICE_CONFIG,inl(EP93XX_SYSCON_DEVICE_CONFIG) | EP93XX_SYSCON_DEVICE_CONFIG_CRUNCH_ENABLE); + + } + + return 0; +} + + +static void ep93xxfb_get_par(struct fb_info *info) +{ + + DPRINTK("ep93xxfb_get_par - enter\n"); + epinfo.configure = NULL; + epinfo.on = NULL; + epinfo.off = NULL; + + switch( vout ) { + case LCD_OUT: + epinfo.on = philips_lb064v02_on; + epinfo.off = philips_lb064v02_off; + + case CRT_OUT: + epinfo.xres = ep93xxfb_vmods[vmode].hres; + epinfo.xsync = ep93xxfb_vmods[vmode].hsync; + epinfo.xfp = ep93xxfb_vmods[vmode].hfp; + epinfo.xbp = ep93xxfb_vmods[vmode].hbp; + epinfo.xtotal = epinfo.xres + epinfo.xsync + + epinfo.xfp + epinfo.xbp; + + epinfo.yres = ep93xxfb_vmods[vmode].vres; + epinfo.ysync = ep93xxfb_vmods[vmode].vsync; + epinfo.yfp = ep93xxfb_vmods[vmode].vfp; + epinfo.ybp = ep93xxfb_vmods[vmode].vbp; + epinfo.ytotal = epinfo.yres + epinfo.ysync + + epinfo.yfp + epinfo.ybp; + + epinfo.refresh = ep93xxfb_vmods[vmode].refresh; + epinfo.refresh = epinfo.xtotal * epinfo.ytotal * epinfo.refresh; + epinfo.pixclock = 1000000000 / ( epinfo.refresh / 1000); + epinfo.bpp = depth; + + epinfo.clk_src = ep93xxfb_vmods[vmode].clk_src; + epinfo.clk_edge = ep93xxfb_vmods[vmode].clk_edge; + epinfo.pol_blank = ep93xxfb_vmods[vmode].pol_blank; + epinfo.pol_xsync = ep93xxfb_vmods[vmode].pol_hsync; + epinfo.pol_ysync = ep93xxfb_vmods[vmode].pol_vsync; + break; + + } +} + +static int ep93xxfb_alloc_videomem(void) +{ + unsigned long adr,size,pgsize; + int order; + + DPRINTK("ep93xxfb_alloc_videomem - enter \n"); + + epinfo.fb_log = NULL; + epinfo.fb_size = PAGE_ALIGN( MAX_FBMEM_SIZE/*ep93xxfb_vmods[vmode].hres * ep93xxfb_vmods[vmode].vres * (depth / 8)*/ ); + order = get_order( epinfo.fb_size ); + epinfo.fb_log = (void*) __get_free_pages( GFP_KERNEL, order ); + + if (epinfo.fb_log) { + epinfo.fb_phys = __virt_to_phys((int) epinfo.fb_log ); + adr = (unsigned long)epinfo.fb_log; + size = epinfo.fb_size; + pgsize = 1 << order; + do { + adr += pgsize; + SetPageReserved(virt_to_page(adr)); + } while(size -= pgsize); + } + else{ + printk("%s memory fail \n",__FUNCTION__); + return -ENOMEM; + } + + memset(epinfo.fb_log,0x00,epinfo.fb_size); + DPRINTK(" fb_log_addres = 0x%x\n",epinfo.fb_log); + DPRINTK(" fb_phys_address = 0x%x\n",epinfo.fb_phys); + DPRINTK(" fb_size = %lu\n",epinfo.fb_size); + DPRINTK(" fb_page_order = %d\n",order); + DPRINTK("ep93xxfb_alloc_videomem - exit \n"); + return 0; +} + +static void ep93xxfb_release_videomem(void) +{ + unsigned long adr,size,psize; + int order; + + DPRINTK("ep93xxfb_release_videomem - enter \n"); + + if (epinfo.fb_log) { + order = get_order(epinfo.fb_size); + adr = (unsigned long)epinfo.fb_log; + size = epinfo.fb_size; + psize = 1 << order ; + do { + adr += psize; + ClearPageReserved(virt_to_page(adr)); + } while(size -= psize); + free_pages((unsigned long)epinfo.fb_log, order ); + } + + + DPRINTK("ep93xxfb_release_videomem - exit \n"); +} + +static void ep93xxfb_setinfo(struct fb_info *info) +{ + + info->pseudo_palette = pseudo_palette; + info->var.xres = epinfo.xres; + info->var.yres = epinfo.yres; + info->var.xres_virtual = epinfo.xres; + info->var.yres_virtual = epinfo.yres; + + ep93xxfb_setcol( info, depth ); + + info->var.activate = FB_ACTIVATE_NOW; + info->var.left_margin = epinfo.xbp; + info->var.right_margin = epinfo.xfp; + info->var.upper_margin = epinfo.ybp; + info->var.lower_margin = epinfo.yfp; + info->var.hsync_len = epinfo.xsync; + info->var.vsync_len = epinfo.ysync; + + if( epinfo.pol_xsync == POL_HIGH ) + info->var.sync |= FB_SYNC_HOR_HIGH_ACT; + if( epinfo.pol_ysync == POL_HIGH ) + info->var.sync |= FB_SYNC_VERT_HIGH_ACT; + + info->var.vmode = FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP; + info->fix.smem_start = epinfo.fb_phys; + info->fix.smem_len = epinfo.fb_size; + info->fix.type = FB_TYPE_PACKED_PIXELS; + info->fix.line_length = epinfo.xres * (epinfo.bpp / 8); + info->screen_base = epinfo.fb_log; + info->var.pixclock = epinfo.pixclock; + info->fix.ypanstep = 1; + info->fix.ywrapstep = 1; + +} + +static int ep93xxfb_config(struct fb_info *info) +{ + unsigned long attribs; + + DPRINTK("ep93xxfb_config - enter\n"); + + ep93xxfb_get_par( info ); + if( ep93xxfb_alloc_videomem() != 0 ) { + printk("Unable to allocate video memory\n"); + return -ENOMEM; + } + + if( ep93xxfb_setclk() != 0 ) { + printk("Unable to set pixel clock\n"); + ep93xxfb_release_videomem(); + return -ENODEV; + } + + SysconSetLocked(EP93XX_SYSCON_DEVICE_CONFIG, inl(EP93XX_SYSCON_DEVICE_CONFIG) |EP93XX_SYSCON_DEVCFG_RasOnP3); + ep93xxfb_timing_signal_generation(); + + /* set video memory parameters */ + outl(epinfo.fb_phys, VIDSCRNPAGE); + outl(epinfo.yres , SCRNLINES); + outl(((epinfo.xres * epinfo.bpp) / 32) - 1, LINELENGTH); + outl((epinfo.xres * epinfo.bpp) / 32, VLINESTEP); + + + /* set pixel mode */ + ep93xxfb_pixelmod(depth); + + attribs = 0; + +#ifdef CONFIG_EP93XX_SDCS0 + attribs |= 0 << VIDEOATTRIBS_SDSEL_SHIFT; +#endif +#ifdef CONFIG_EP93XX_SDCS1 + attribs |= 1 << VIDEOATTRIBS_SDSEL_SHIFT; +#endif +#ifdef CONFIG_EP93XX_SDCS2 + attribs |= 2 << VIDEOATTRIBS_SDSEL_SHIFT; +#endif +#ifdef CONFIG_EP93XX_SDCS3 + attribs |= 3 << VIDEOATTRIBS_SDSEL_SHIFT; +#endif + + if(epinfo.clk_edge == EDGE_RISING) + attribs |= VIDEOATTRIBS_INVCLK; + if(epinfo.pol_blank == POL_HIGH) + attribs |= VIDEOATTRIBS_BLKPOL; + if(epinfo.pol_xsync == POL_HIGH) + attribs |= VIDEOATTRIBS_HSPOL; + if(epinfo.pol_ysync == POL_HIGH) + attribs |= VIDEOATTRIBS_VCPOL; + + ep93xxfb_outl(attribs, VIDEOATTRIBS); + ep93xxfb_setinfo( info ); + + if(epinfo.configure) + (epinfo.configure)( epinfo.automods ); + + ep93xxfb_blank( 0 , info ); + + DPRINTK("ep93xxfb_config - exit\n"); + return 0; +} + +int ep93xxfb_ioctl(struct fb_info *info,unsigned int cmd, unsigned long arg) +{ + struct fb_fillrect fill; + struct fb_copyarea cparea; + struct fb_image img; + struct ep93xx_line line; + struct ep93xx_cursor cursor; + + switch (cmd) { + case FBIO_EP93XX_CURSOR: + copy_from_user(&cursor, (void *)arg, sizeof(struct ep93xx_cursor)); + ep93xxfb_cursor(info,&cursor); + break; + case FBIO_EP93XX_LINE: + copy_from_user(&line, (void *)arg, sizeof(struct ep93xx_line)); + ep93xxfb_line(info,&line); + break; + case FBIO_EP93XX_FILL: + copy_from_user(&fill, (void *)arg, sizeof(struct fb_fillrect)); + ep93xxfb_fillrect(info,&fill); + break; + case FBIO_EP93XX_BLIT: + copy_from_user(&img, (void *)arg, sizeof(struct fb_image)); + ep93xxfb_imageblit(info, &img); + break; + case FBIO_EP93XX_COPY: + copy_from_user(&cparea, (void *)arg, sizeof(struct fb_copyarea)); + ep93xxfb_copyarea(info,&cparea); + break; + default: + return -EFAULT; + } + return 0; +} + + +static struct fb_ops ep93xxfb_ops = { + .owner = THIS_MODULE, + .fb_setcolreg = ep93xxfb_setcolreg, + .fb_check_var = ep93xxfb_check_var, + .fb_set_par = ep93xxfb_set_par, + .fb_blank = ep93xxfb_blank, + .fb_pan_display = ep93xx_pan_display, + .fb_fillrect = ep93xxfb_fillrect, + .fb_copyarea = ep93xxfb_copyarea, + .fb_imageblit = cfb_imageblit, + .fb_cursor = ep93xxfb_cursor, + .fb_ioctl = ep93xxfb_ioctl, + .fb_mmap = ep93xxfb_mmap, +}; + + +static struct resource ep93xxfb_raster_resources = { + .start = EP93XX_RASTER_PHYS_BASE, + .end = EP93XX_RASTER_PHYS_BASE + 0x1ffff, + .flags = IORESOURCE_MEM, +}; + + +static int __init ep93xxfb_probe(struct platform_device *device) +{ + struct fb_info *info = NULL; + struct resource *res = NULL; + int ret = 0; + int arb = 0; + + DPRINTK("ep93xxfb_probe - enter \n"); + + + if(!device) { + printk("error : to_platform_device\n"); + return -ENODEV; + } + res = platform_get_resource( device, IORESOURCE_MEM, 0); + if(!res) { + printk("error : platform_get_resource \n"); + return -ENODEV; + } + cursor_data = kmalloc( 64 * 64 * 2, GFP_KERNEL ); + memset( cursor_data, 0x00, 64 * 64 * 2 ); + if(!cursor_data) { + printk("Unable to allocate memory for hw_cursor\n"); + return -ENOMEM; + } + if (!request_mem_region(res->start,res->end - res->start + 1, FBDEV_NAME )) + return -EBUSY; + + info = framebuffer_alloc(sizeof(u32) * 256, &device->dev); + + if(!info) { + printk("Unable to allocate memory for frame buffer\n"); + return -ENOMEM; + } + + info->flags = FBINFO_DEFAULT; + strncpy(info->fix.id, FBDEV_NAME, sizeof(info->fix.id)); + info->fix.mmio_start = res->start; + info->fix.mmio_len = res->end - res->start + 1; + info->fbops = &ep93xxfb_ops; + info->pseudo_palette = info->par; + info->state = FBINFO_STATE_RUNNING; + + if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) { + ret = -ENOMEM; + goto fbuff; + } + + if ((ret = ep93xxfb_config(info)) < 0) + goto clmap; + + if (register_framebuffer(info) < 0) { + printk(KERN_ERR "Unable to register ep93xxfb frame buffer\n"); + ret = -EINVAL; + goto clmap; + } + platform_set_drvdata(device, info); + printk(KERN_INFO "fb%d: EP93xx frame buffer at %dx%dx%dbpp\n", info->node, + info->var.xres, info->var.yres, info->var.bits_per_pixel); + + /*change the raster arb to the highest one--Bo*/ + arb = inl(EP93XX_SYSCON_BMAR); + arb = (arb & 0x3f8) | 0x01; + outl(arb,EP93XX_SYSCON_BMAR); + + DPRINTK("ep93xxfb_probe - exit \n"); + return 0; + +clmap: + fb_dealloc_cmap(&info->cmap); + +fbuff: + framebuffer_release(info); + return ret; +} + +static int ep93xxfb_remove(struct platform_device *device) +{ + struct resource *res; + struct fb_info *info; + struct ep93xx_cursor cursor; + + DPRINTK("ep93xxfb_remove - enter \n"); + + info = platform_get_drvdata(device); + + ep93xxfb_release_videomem(); + + res = platform_get_resource( device, IORESOURCE_MEM, 0); + release_mem_region(res->start, res->end - res->start + 1); + + platform_set_drvdata(device, NULL); + unregister_framebuffer(info); + + fb_dealloc_cmap(&info->cmap); + framebuffer_release(info); + + cursor.flags = CURSOR_OFF; + ep93xxfb_cursor(info,&cursor); + if(cursor_data!=NULL) + kfree(cursor_data); + + ep93xxfb_blank( 1, info ); + + DPRINTK("ep93xxfb_remove - exit \n"); + return 0; +} + +static void ep93xxfb_platform_release(struct device *device) +{ + DPRINTK("ep93xxfb_platform_release - enter\n"); +} + +static int ep93xxfb_check_param(void) +{ + + switch(vout) { + case CRT_OUT: + if( vmode >=(sizeof(ep93xxfb_vmods)/sizeof(ep93xxfb_vmods[0]))){ + vmode = 1; + depth = DEFAULT_BPP; + return 0; + } + break; + case LCD_OUT: + if( vmode != 0 || depth != 16 ) { + vmode = 0; + depth = DEFAULT_BPP; + return 0; + } + break; + default: + vmode = DEFAULT_MODE; + depth = DEFAULT_BPP; + vout = DEFAULT_OUT; + return 0; + break; + } + + if(!((depth == 8) || (depth == 16) || (depth == 24) || (depth == 32))) + depth = DEFAULT_BPP; + + return 1; +} + +int __init ep93xxfb_setup(char *options) +{ + char *opt; + + DPRINTK("ep93xxfb_setup - %s\n",options); + + if (!options || !*options) + return 0; + + while ((opt = strsep(&options, ",")) != NULL) { + if (!strncmp(opt, "vout=", 5)) + vout = simple_strtoul(opt + 5, NULL, 0); + else if (!strncmp(opt, "vmode=", 6)) + vmode = simple_strtoul(opt + 6, NULL, 0); + else if (!strncmp(opt, "depth=", 6)) + depth = simple_strtoul(opt + 6, NULL, 0); + } + ep93xxfb_check_param(); + return 0; +} + + +static struct platform_driver ep93xxfb_driver = { + .probe = ep93xxfb_probe, + .remove = ep93xxfb_remove, + .driver = { + .name = FBDEV_NAME, + }, +}; + +static struct platform_device ep93xxfb_device = { + .name = FBDEV_NAME, + .id = -1, + .dev = { + .release = ep93xxfb_platform_release, + }, + .num_resources = 1, + .resource = &ep93xxfb_raster_resources, +}; + +int __init ep93xxfb_init(void) +{ + int ret = 0; + char *option = NULL; + + DPRINTK("ep93xxfb_init - enter\n"); + + if (fb_get_options("ep93xxfb", &option)) + return -ENODEV; + ep93xxfb_setup(option); + + + if( !ep93xxfb_check_param() ) { + printk("Unsupported format \n"); + return -1; + } + /*Add the Hardware accel irq */ + outl(0x00000000, BLOCKCTRL); + ret = request_irq(IRQ_EP93XX_GRAPHICS, ep93xxfb_irq_handler, IRQF_DISABLED,"graphics",NULL); + + if (ret != 0) { + printk("%s: can't get irq %i, err %d\n",__FUNCTION__, IRQ_EP93XX_GRAPHICS, ret); + return -EBUSY; + } + + /*-------------------------------*/ + ret = platform_driver_register(&ep93xxfb_driver); + + if (!ret) { + ret = platform_device_register(&ep93xxfb_device); + if (ret) + platform_driver_unregister(&ep93xxfb_driver); + } + + DPRINTK("ep93xxfb_init - exit\n"); + return ret; +} + + + +static void __exit ep93xxfb_exit(void) +{ + DPRINTK("ep93xxfb_exit - enter\n"); + platform_driver_unregister(&ep93xxfb_driver); + platform_device_unregister(&ep93xxfb_device); + DPRINTK("ep93xxfb_exit - exit\n"); +} + +module_init(ep93xxfb_init); +module_exit(ep93xxfb_exit); + + +module_param( vmode, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); +MODULE_PARM_DESC(vmode, "Specify the video mode number that should be used"); +module_param( vout , int , S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP ); +MODULE_PARM_DESC(vout ,"Specify video output (0 = CRT ,1 = LCD )"); +module_param( depth , int, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); +MODULE_PARM_DESC(depth ,"Color depth (8,16,24,32)"); +MODULE_LICENSE("GPL"); --- /dev/null +++ b/drivers/video/ep93xxfb.h @@ -0,0 +1,236 @@ +#ifndef __EP93XXFB_H__ +#define __EP93XXFB_H__ + + +#define POL_HIGH 1 +#define POL_LOW 0 +#define EDGE_RISING 1 +#define EDGE_FALLING 0 +#define CLK_INTERNAL 1 +#define CLK_EXTERNAL 0 + +#define CRT_OUT 0 +#define LCD_OUT 1 +#define TV_OUT 2 + +#define MAX_XRES 1280 +#define MAX_YRES 1024 +#define MAX_BPP 16 +#define MAX_FBMEM_SIZE 3686400/*1920000*/ + +#define MAX_XRES_CRT MAX_XRES +#define MAX_YRES_CRT MAX_YRES +#define MAX_XRES_SVIDEO 1024 +#define MAX_YRES_SVIDEO 768 + +#define PIXEL_FORMAT_SHIFT 17 +#define PIXEL_FORMAT_4 ( 1 << PIXEL_FORMAT_SHIFT ) +#define PIXEL_FORMAT_8 ( 2 << PIXEL_FORMAT_SHIFT ) +#define PIXEL_FORMAT_16 ( 4 << PIXEL_FORMAT_SHIFT ) +#define PIXEL_FORMAT_24 ( 6 << PIXEL_FORMAT_SHIFT ) +#define PIXEL_FORMAT_32 ( 7 << PIXEL_FORMAT_SHIFT ) + + +struct ep93xxfb_videomodes +{ + const char *name; + + unsigned long hres; // Horizontal Valid + unsigned long hfp; // Horizontal Front Porch + unsigned long hsync; // Horizontal Sync Width + unsigned long hbp; // Horizontal Back Porch + + unsigned long vres; // Vertical Valid + unsigned long vfp; // Vertical Front Porch + unsigned long vsync; // Vertical Sync Width + unsigned long vbp; // Vertical Back Porch + + unsigned long refresh; // Vertical Sync Frequency + + unsigned long clk_src; + unsigned long clk_edge; + unsigned long pol_blank; + unsigned long pol_hsync; + unsigned long pol_vsync; +}; + + +struct ep93xxfb_info +{ + + + dma_addr_t fb_phys; + void *fb_log; + unsigned long fb_size; + unsigned long fb_actsize; + + unsigned long xtotal; + unsigned long ytotal; + + unsigned int xres; + unsigned int xfp; + unsigned int xsync; + unsigned int xbp; + + unsigned int yres; + unsigned int yfp; + unsigned int ysync; + unsigned int ybp; + unsigned int bpp; + + unsigned long refresh; + unsigned long pixclock; + unsigned long pixformat; + + unsigned int clk_src; + unsigned int clk_edge; + unsigned int pol_blank; + unsigned int pol_xsync; + unsigned int pol_ysync; + + unsigned char automods; + + void (*configure)(unsigned char value); + void (*on)(unsigned char value); + void (*off)(unsigned char value); +}; + +static int ep93xxfb_setclk(void); +static int ep93xx_get_max_video_clk(void); +static void ep93xxfb_pixelmod(int bpp); +static void ep93xxfb_timing_signal_generation(void); +static int ep93xxfb_blank(int blank_mode,struct fb_info *info); + +#define EE_DELAY_USEC 2 +#define EE_READ_TIMEOUT 100 +#define CX25871_DEV_ADDRESS 0x88 +#define GPIOG_EEDAT 2 +#define GPIOG_EECLK 1 +#define CXMODES_COUNT 24 + +struct cx25871_vmodes +{ + + const char *name; + unsigned char automode; + unsigned int hres; + unsigned int vres; + unsigned int hclktotal; + unsigned int vclktotal; + unsigned int hblank; + unsigned int vblank; + unsigned long clkfrequency; + +}; + + +int write_reg(unsigned char ucRegAddr, unsigned char ucRegValue); +void cx25871_on(unsigned char value); +void cx25871_off(unsigned char value); +void cx25871_config(unsigned char value); + +static void philips_lb064v02_on(unsigned char value); +static void philips_lb064v02_off(unsigned char value); + + +#define FBIO_EP93XX_CURSOR 0x000046c1 +#define FBIO_EP93XX_LINE 0x000046c2 +#define FBIO_EP93XX_FILL 0x000046c3 +#define FBIO_EP93XX_BLIT 0x000046c4 +#define FBIO_EP93XX_COPY 0x000046c5 + + +#define CURSOR_BLINK 0x00000001 +#define CURSOR_MOVE 0x00000002 +#define CURSOR_SETSHAPE 0x00000004 +#define CURSOR_SETCOLOR 0x00000008 +#define CURSOR_ON 0x00000010 +#define CURSOR_OFF 0x00000020 + + +/* +* ioctl(fd, FBIO_EP93XX_CURSOR, ep93xx_cursor *) +* +* "data" points to an array of pixels that define the cursor; each row should +* be a multiple of 32-bit values (i.e. 16 pixels). Each pixel is two bits, +* where the values are: +* +* 00 => transparent 01 => invert 10 => color1 11 => color2 +* +* The data is arranged as follows (per word): +* +* bits: |31-30|29-28|27-26|25-24|23-22|21-20|19-18|17-16| +* pixel: | 12 | 13 | 14 | 15 | 8 | 9 | 10 | 11 | +* bits: |15-14|13-12|11-10| 9-8 | 7-6 | 5-4 | 3-2 | 1-0 | +* pixel: | 4 | 5 | 6 | 7 | 0 | 1 | 2 | 3 | +* +* Regardless of the frame buffer color depth, "color1", "color2", +* "blinkcolor1", and "blinkcolor2" are 24-bit colors since the cursor is +* injected into the data stream right before the video DAC. +* +* When "blinkrate" is not zero, pixel value 10 will alternate between "color1" +* and "blinkcolor1" (similar for pixel value 11 and "color2"/"blinkcolor2"). +* +* "blinkrate" ranges between 0 and 255. When 0, blinking is disabled. 255 is +* the fastest blink rate and 1 is the slowest. +* +* Both "width" and "height" must be between 1 and 64; it is preferable to have +* "width" a multiple of 16. +*/ +struct ep93xx_cursor { + unsigned long flags; + unsigned long dx; // Only used if CURSOR_MOVE is set + unsigned long dy; // Only used if CURSOR_MOVE is set + unsigned long width; // Only used if CURSOR_SETSHAPE is set + unsigned long height; // Only used if CURSOR_SETSHAPE is set + const char *data; // Only used if CURSOR_SETSHAPE is set + unsigned long blinkrate; // Only used if CURSOR_BLINK is set + unsigned long color1; // Only used if CURSOR_SETCOLOR is set + unsigned long color2; // Only used if CURSOR_SETCOLOR is set + unsigned long blinkcolor1; // Only used if CURSOR_SETCOLOR is set + unsigned long blinkcolor2; // Only used if CURSOR_SETCOLOR is set +}; + + +/* + * The bits in the flags field of ep93xx_line. +*/ +/* +* ioctl(fd, FBIO_EP93XX_LINE, ep93xx_line *) +* +* The line starts at ("x1","y1") and ends at ("x2","y2"). This means that +* when using a pattern, the two coordinates are not transitive (i.e. swapping +* ("x1","y1") with ("x2","y2") will not necessarily draw the exact same line, +* pattern-wise). +* +* "pattern" is a 2 to 16 bit pattern (since a 1 bit pattern isn't much of a +* pattern). The lower 16 bits define the pattern (1 being foreground, 0 being +* background or transparent), and bits 19-16 define the length of the pattern +* (as pattern length - 1). So, for example, "0xf00ff" defines a 16 bit +* with the first 8 pixels in the foreground color and the next 8 pixels in the +* background color or transparent. +* +* LINE_PRECISE is used to apply angularly corrected patterns to line. It +* should only be used when LINE_PATTERN is also set. The pattern will be +* applied along the length of the line, instead of along the length of the +* major axis. This may result in the loss of fine details in the pattern, and +* will take more time to draw the line in most cases. +*/ + +#define LINE_PATTERN 0x00000001 +#define LINE_PRECISE 0x00000002 +#define LINE_BACKGROUND 0x00000004 + +struct ep93xx_line { + unsigned long flags; + unsigned long x1; + unsigned long y1; + unsigned long x2; + unsigned long y2; + unsigned long fgcolor; + unsigned long bgcolor; // Only used if LINE_BACKGROUND is set + unsigned long pattern; // Only used if LINE_PATTERN is set +}; + +#endif /* __EP93XXFB_H__ */ + --- /dev/null +++ b/drivers/video/ep93xxfb_mono.c @@ -0,0 +1,1281 @@ +/* + * drivers/video/ep93xxfb_mono.c -- grayscale on mono LCD driver for + * Cirrus Logic EP93xx. + * + * Copyright (C) 2007 Cirrus Logic + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive for + * more details. + * + * This driver works for the following two LCD: + * SHARP LM121VB1T01 - A dual scan 640x480 monochrome LCD. + * HOSIDEN HLM6323 - A single scan 320x240 monochrome LCD. + * + * And support two gray modes: + * 8 levels of gray - Actually is 7 levels of gray. Two of the levels + * have the same gray. + * 16 levels of gray - Extending the gray levels by switching the LUT + * for each frame. + * + * HW connection for SHARP LM121VB1T01: + * P12 <------> LCD_U0 + * P8 <------> LCD_U1 + * P4 <------> LCD_U2 + * P0 <------> LCD_U3 + * P14 <------> LCD_L0 + * P10 <------> LCD_L1 + * P6 <------> LCD_L2 + * P2 <------> LCD_L3 + * HW connection for HOSIDEN HLM6323: + * P12 <------> LCD_0 + * P8 <------> LCD_1 + * P4 <------> LCD_2 + * P0 <------> LCD_3 + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#include + +#define CONFIG_EP93XX_SDCS0 + +#undef DEBUG +#ifdef DEBUG +#define DPRINTK( fmt, arg... ) printk( fmt, ##arg ) +#else +#define DPRINTK( fmt, arg... ) +#endif + +#define FBDEV_NAME "ep93xxfb" + +#define ep93xxfb_lock_outl(value, reg) \ +{ \ + outl(RASTER_SWLOCK_VALUE, RASTER_SWLOCK); \ + outl(value, reg); \ + DPRINTK(#reg"=0x%08x\n", (unsigned int)(value)); \ +} + +#define ep93xxfb_outl(value, reg) \ +{ \ + outl(value, reg); \ + DPRINTK(#reg"=0x%08x\n", (unsigned int)(value)); \ +} + +static unsigned int pseudo_palette[256]; + +struct ep93xxfb_mono_videomodes +{ + const char *name; + + unsigned long hres; // Horizontal Valid + unsigned long vres; // Vertical Valid + unsigned int freq; + unsigned int dualscan; + unsigned int bpp; + unsigned int graylevel; + + void (*configure)(unsigned char value); + void (*on)(unsigned char value); + void (*off)(unsigned char value); +}; + +struct ep93xxfb_mono_info +{ + dma_addr_t fb_phys; + void *fb_log; + unsigned long fb_size; + unsigned long fb_actsize; + + unsigned int xres; + unsigned int yres; + + unsigned int freq; + unsigned int dualscan; + unsigned int bpp; + unsigned int graylevel; + + void (*configure)(unsigned char value); + void (*on)(unsigned char value); + void (*off)(unsigned char value); +}; + + +void LM121VB1T01_configure(unsigned char value); +void HOSIDEN_HLM6323_configure(unsigned char value); + +static int vmode = 1; + +static struct ep93xxfb_mono_info epinfo; +static struct ep93xxfb_mono_videomodes ep93xxfb_vmods[] = +{ + { + "SHARP-LM121VB1T01-8GRAY", + 640, 480, 100, + 1, //dual scan + 4, //4bpp + 8, //8-level grayscale + LM121VB1T01_configure, + NULL, + NULL, + }, + { + "SHARP-LM121VB1T01-16GRAY", + 640, 480, 120, + 1, //dual scan + 4, //4bpp + 16, //16-level grayscale + LM121VB1T01_configure, + NULL, + NULL, + }, + { + "HOSIDEN HLM6323", + 320, 240, 115, + 0, //single scan + 4, //4bpp + 8, //8-level grayscale + HOSIDEN_HLM6323_configure, + NULL, + NULL, + }, + { + "HOSIDEN HLM6323", + 320, 240, 115, + 0, //single scan + 4, //4bpp + 16, //16-level grayscale + HOSIDEN_HLM6323_configure, + NULL, + NULL, + }, +}; + + +#define EP93XX_GS_OFFSET(lut, frame, pixel) ( (lut) + ( (pixel) << 2) + ((frame) << 5 )) + +static unsigned long DY_LUT[2][16]; + +static unsigned long GSLUT[32] = +{ + 0x00070000, 0x00070000, 0x00070000, 0x00070000, /*0%*/ + 0x00078241, 0x00074182, 0x00071428, 0x00072814, /*25%*/ + 0x00000412, 0x00000241, 0x00000124, 0x00000000, /*33%*/ + 0x0007aa55, 0x000755aa, 0x000755aa, 0x0007aa55, /*50%*/ + 0x00000bed, 0x00000dbe, 0x00000edb, 0x00000000, /*66%*/ + 0x00077dbe, 0x0007be7d, 0x0007ebd7, 0x0007d7eb, /*75%*/ + 0x0007ffff, 0x0007ffff, 0x0007ffff, 0x0007ffff, /*100%*/ + 0x0007ffff, 0x0007ffff, 0x0007ffff, 0x0007ffff, +}; + +static void ep93xxfb_8gray_palette_init(void) +{ + unsigned int cont, i, n; + unsigned int frame, pixval, gslut; + cont = inl(LUTCONT); + for (i=0; i< 16; i++) + { + n = (i & 0xe) << 4; + outl( n, (COLOR_LUT+(i<<2)) ); + } + for (pixval=0; pixval < 8; pixval++) + { + for (frame=0; frame < 4; frame++) + { + gslut = GSLUT[pixval*4 + frame]; + outl(gslut,EP93XX_GS_OFFSET(GS_LUT, frame, pixval)); + } + } + outl( cont ^ LUTCONT_RAM1, LUTCONT ); +} + +static void ep93xxfb_16gray_palette_switch(int index) +{ + unsigned int cont, i, n; + cont = inl(LUTCONT); + n = index & 0x1; + for (i=0; i< 16; i++) + { + outl( DY_LUT[n][i], (COLOR_LUT+(i<<2)) ); + } + outl( cont ^ LUTCONT_RAM1, LUTCONT ); +} + +static void ep93xxfb_16gray_palette_init(void) +{ + int i; + unsigned int cont; + unsigned int frame, pixval, gslut; + int split_table[16][2] = + { + {0, 0 }, + {0, 2 }, + {1, 1 }, + {3, 0 }, + + {2, 2 }, + {4, 0 }, + {3, 2 }, + {4, 2 }, + + {3, 3 }, // {6, 0 }, + {3, 4 }, + {4, 4 }, + {6, 2 }, + + {5, 5 }, + {3, 6 }, + {4, 6 }, + {6, 6 }, + }; + + cont = inl(LUTCONT); + for (i=0; i< 16; i++) + { + DY_LUT[0][i]=split_table[i][0] << 5; + DY_LUT[1][i]=split_table[i][1] << 5; + + outl( DY_LUT[0][i], (COLOR_LUT+(i<<2)) ); + } + + for (pixval=0; pixval < 8; pixval++) + { + for (frame=0; frame < 4; frame++) + { + gslut = GSLUT[pixval*4 + frame]; + outl(gslut,EP93XX_GS_OFFSET(GS_LUT, frame, pixval)); + outl(gslut,EP93XX_GS_OFFSET(GS_LUT2, frame, pixval)); + outl(gslut,EP93XX_GS_OFFSET(GS_LUT3, frame, pixval)); + } + } + outl( cont ^ LUTCONT_RAM1, LUTCONT ); +} + +static int ep93xxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) +{ + struct fb_var_screeninfo tmp_var; + DPRINTK("ep93xxfb_check_var - enter\n"); + + memcpy (&tmp_var, var, sizeof (tmp_var)); + + if (var->xres_virtual != var->xres) + var->xres_virtual = var->xres; + if (var->yres_virtual < var->yres) + var->yres_virtual = var->yres; + + if (var->xoffset < 0) + var->xoffset = 0; + if (var->yoffset < 0) + var->yoffset = 0; + + switch (tmp_var.bits_per_pixel) + { + case 4: + break; + default: + return -EINVAL; + } + + DPRINTK("ep93xxfb_check_var - exit\n"); + return 0; +} + +static int ep93xxfb_set_par(struct fb_info *info) +{ + DPRINTK("ep93xxfb_set_par\n"); + switch (info->var.bits_per_pixel) { + case 4: + info->fix.visual = FB_VISUAL_PSEUDOCOLOR; + break; + + default: + return -EINVAL; + } + + return 0; +} + + +static int ep93xxfb_blank(int blank_mode,struct fb_info *info) +{ + unsigned long attribs; + DPRINTK("ep93xxfb_blank - enter\n"); + attribs = inl(VIDEOATTRIBS); + + if (blank_mode) { + if (epinfo.off) + (epinfo.off)( 0 ); + + ep93xxfb_lock_outl(attribs & ~(VIDEOATTRIBS_DATAEN | + VIDEOATTRIBS_SYNCEN | VIDEOATTRIBS_PCLKEN | + VIDEOATTRIBS_EN), VIDEOATTRIBS); + } + else { + + if (epinfo.configure) + (epinfo.configure)( (unsigned char) epinfo.graylevel ); + if (epinfo.on) + (epinfo.on)( 0 ); + } + return 0; +} + +static void ep93xxfb_get_par(struct fb_info *info) +{ + + DPRINTK("ep93xxfb_get_par - enter\n"); + + epinfo.configure = ep93xxfb_vmods[vmode].configure; + epinfo.on = ep93xxfb_vmods[vmode].on; + epinfo.off = ep93xxfb_vmods[vmode].off; + + epinfo.freq = ep93xxfb_vmods[vmode].freq; + epinfo.dualscan = ep93xxfb_vmods[vmode].dualscan; + epinfo.bpp = ep93xxfb_vmods[vmode].bpp; + epinfo.graylevel = ep93xxfb_vmods[vmode].graylevel; + + epinfo.xres = ep93xxfb_vmods[vmode].hres; + epinfo.yres = ep93xxfb_vmods[vmode].vres; + +} + +static int ep93xxfb_alloc_videomem(void) +{ + unsigned long adr,size,pgsize; + int order; + + DPRINTK("ep93xxfb_alloc_videomem - enter \n"); + + epinfo.fb_log = NULL; + epinfo.fb_size = epinfo.xres*epinfo.yres*epinfo.bpp/8; + order = get_order( epinfo.fb_size ); + epinfo.fb_log = (void*) __get_free_pages( GFP_KERNEL, order ); + + if (epinfo.fb_log) { + epinfo.fb_phys = __virt_to_phys((int) epinfo.fb_log ); + adr = (unsigned long)epinfo.fb_log; + size = epinfo.fb_size; + pgsize = 1 << order; + do { + adr += pgsize; + SetPageReserved(virt_to_page(adr)); + } while(size -= pgsize); + } + else + return -ENOMEM; + + memset(epinfo.fb_log,0x00,epinfo.fb_size); + + DPRINTK(" fb_log_addres = 0x%x\n", (unsigned int)epinfo.fb_log); + DPRINTK(" fb_phys_address = 0x%x\n", (unsigned int)epinfo.fb_phys); + DPRINTK(" fb_size = %lu\n", (unsigned long)epinfo.fb_size); + DPRINTK(" fb_page_order = %d\n", (unsigned int)order); + DPRINTK("ep93xxfb_alloc_videomem - exit \n"); + return 0; +} + +static void ep93xxfb_release_videomem(void) +{ + unsigned long adr,size,psize; + int order; + + DPRINTK("ep93xxfb_release_videomem - enter \n"); + if (epinfo.fb_log) { + order = get_order(epinfo.fb_size); + adr = (unsigned long)epinfo.fb_log; + size = epinfo.fb_size; + psize = 1 << order ; + do { + adr += psize; + ClearPageReserved(virt_to_page(adr)); + } while(size -= psize); + free_pages((unsigned long)epinfo.fb_log, order ); + } + DPRINTK("ep93xxfb_release_videomem - exit \n"); +} + +static void ep93xxfb_setinfo(struct fb_info *info) +{ + + DPRINTK("ep93xxfb_setinfo - enter \n"); + info->pseudo_palette = pseudo_palette; + info->var.xres = epinfo.xres; + info->var.yres = epinfo.yres; + info->var.xres_virtual = epinfo.xres; + info->var.yres_virtual = epinfo.yres; + + info->var.bits_per_pixel = epinfo.bpp; + info->var.red.length = epinfo.bpp; + info->var.green.length = epinfo.bpp; + info->var.blue.length = epinfo.bpp; + info->fix.visual = FB_VISUAL_PSEUDOCOLOR; + info->var.red.offset = 0; + info->var.green.offset =0; + info->var.blue.offset = 0; + + info->fix.smem_start = epinfo.fb_phys; + info->fix.smem_len = epinfo.fb_size; + info->fix.type = FB_TYPE_PACKED_PIXELS; + info->fix.line_length = (epinfo.xres * epinfo.bpp) / 8; + info->fix.accel = FB_ACCEL_NONE; + info->screen_base = epinfo.fb_log; + info->fix.ypanstep = 1; + info->fix.ywrapstep = 1; + + DPRINTK("ep93xxfb_setinfo - exit \n"); +} + +static int ep93xxfb_config(struct fb_info *info) +{ + DPRINTK("ep93xxfb_config - enter\n"); + + ep93xxfb_get_par( info ); + if( ep93xxfb_alloc_videomem() != 0 ) { + printk("Unable to allocate video memory\n"); + return -ENOMEM; + } + + /* set video memory parameters */ + ep93xxfb_outl(epinfo.fb_phys, VIDSCRNPAGE); + if(epinfo.dualscan) + { + ep93xxfb_outl(epinfo.fb_phys + (epinfo.bpp*epinfo.xres*epinfo.yres/16) + , VIDSCRNHPG); + } + + DPRINTK(" fb_phys = 0x%x\n", inl(VIDSCRNPAGE) ); + DPRINTK(" fb_phys_hpg = 0x%x\n", inl(VIDSCRNHPG)); + + ep93xxfb_outl(epinfo.yres , SCRNLINES); + ep93xxfb_outl(((epinfo.xres * epinfo.bpp) / 32) - 1, LINELENGTH); + ep93xxfb_outl((epinfo.xres * epinfo.bpp) / 32, VLINESTEP); + + if(epinfo.configure) + (epinfo.configure)( (unsigned char) epinfo.graylevel ); + + ep93xxfb_setinfo( info ); + + + DPRINTK("ep93xxfb_config - exit\n"); + return 0; +} + +static unsigned long ep93xx_get_pll_frequency(unsigned long pll) +{ + unsigned long fb1, fb2, ipd, ps, freq; + + if (pll == 1) + pll = inl(EP93XX_SYSCON_CLOCK_SET1); + else if (pll == 2) + pll = inl(EP93XX_SYSCON_CLOCK_SET2); + else + return 0; + + ps = (pll & SYSCON_CLKSET1_PLL1_PS_MASK) >> SYSCON_CLKSET1_PLL1_PS_SHIFT; + fb1 = ((pll & SYSCON_CLKSET1_PLL1_X1FBD1_MASK) >> SYSCON_CLKSET1_PLL1_X1FBD1_SHIFT); + fb2 = ((pll & SYSCON_CLKSET1_PLL1_X2FBD2_MASK) >> SYSCON_CLKSET1_PLL1_X2FBD2_SHIFT); + ipd = ((pll & SYSCON_CLKSET1_PLL1_X2IPD_MASK) >> SYSCON_CLKSET1_PLL1_X2IPD_SHIFT); + + freq = (((0x00e10000 * (fb1+1)) / (ipd+1)) * (fb2+1)) >> ps; + return freq; +} + +static int ep93xx_set_video_div(unsigned long freq) +{ + unsigned long pdiv = 0, div = 0, psel = 0, esel = 0; + unsigned long err, f, i, j, k; + + err = -1; + + for (i = 0; i < 3; i++) { + if (i == 0) + f = 14745600 * 2; + else if (i == 1) + f = ep93xx_get_pll_frequency(1) * 2; + else + f = ep93xx_get_pll_frequency(2) * 2; + + for (j = 4; j <= 6; j++) { + k = f / (freq * j); + if (k < 2) + continue; + + if (abs(((f / (j * k))) - freq ) < err ) { + pdiv = j - 3; + div = k; + psel = (i == 2) ? 1 : 0; + esel = (i == 0) ? 0 : 1; + err = (f / (j * k)) - freq; + } + } + } + + if (err == -1) + return -1; + + f = SYSCON_VIDDIV_VENA | (esel ? SYSCON_VIDDIV_ESEL : 0) | + (psel ? SYSCON_VIDDIV_PSEL : 0) | + (pdiv << SYSCON_VIDDIV_PDIV_SHIFT) | + (div << SYSCON_VIDDIV_VDIV_SHIFT); + outl(0xaa, EP93XX_SYSCON_SWLOCK); + outl(f, SYSCON_VIDDIV); + + return freq + err; +} + +static int interrupt_hooked = 0; +static int vs_counter = 0; + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17) +static irqreturn_t ep93xxfb_irq_handler(int i, void *blah) +#else +static irqreturn_t ep93xxfb_irq_handler(int i, void *blah, struct pt_regs *regs) +#endif +{ + + outl(RASTER_SWLOCK_VALUE, RASTER_SWLOCK); + outl( +#ifdef CONFIG_EP93XX_SDCS0 + (0 << VIDEOATTRIBS_SDSEL_SHIFT) | +#endif +#ifdef CONFIG_EP93XX_SDCS1 + (1 << VIDEOATTRIBS_SDSEL_SHIFT) | +#endif +#ifdef CONFIG_EP93XX_SDCS2 + (2 << VIDEOATTRIBS_SDSEL_SHIFT) | +#endif +#ifdef CONFIG_EP93XX_SDCS3 + (3 << VIDEOATTRIBS_SDSEL_SHIFT) | +#endif + VIDEOATTRIBS_VCPOL | VIDEOATTRIBS_HSPOL | + VIDEOATTRIBS_DATAEN | VIDEOATTRIBS_SYNCEN | VIDEOATTRIBS_INVCLK | + VIDEOATTRIBS_PCLKEN | VIDEOATTRIBS_EN | VIDEOATTRIBS_INTEN , + VIDEOATTRIBS ); + + ep93xxfb_16gray_palette_switch(vs_counter++); + + return IRQ_HANDLED; +} + +void LM121VB1T01_configure(unsigned char value) +{ + + int n; + unsigned long attribs; + printk("LM121VB1T01_configure\n"); + + switch(value) + { + case 8: + ep93xxfb_8gray_palette_init(); + break; + case 16: + ep93xxfb_16gray_palette_init(); + break; + default: + return; + } + + SysconSetLocked(EP93XX_SYSCON_DEVICE_CONFIG, (inl(EP93XX_SYSCON_DEVICE_CONFIG) & ~EP93XX_SYSCON_DEVICE_CONFIG_CRUNCH_ENABLE) | EP93XX_SYSCON_DEVCFG_RasOnP3); + + ep93xx_set_video_div(epinfo.freq*240*1280); + + ep93xxfb_lock_outl( 0x00000000 , VIDEOATTRIBS ); + + n = 240; + ep93xxfb_lock_outl( n + 3 , VLINESTOTAL ); + ep93xxfb_lock_outl( ((n)<<16) + n+1 , VSYNCSTRTSTOP ); + ep93xxfb_lock_outl( ((2)<<16) + n+2 , VACTIVESTRTSTOP ); + ep93xxfb_lock_outl( ((3)<<16) + n+3 , VBLANKSTRTSTOP ); + ep93xxfb_lock_outl( ((n+3)<<16) + n+3 , VCLKSTRTSTOP ); + + n = 1280; + ep93xxfb_lock_outl( n + 15 , HCLKSTOTAL ); + ep93xxfb_lock_outl( ((n+5)<<16) + n+ 14 , HSYNCSTRTSTOP ); + ep93xxfb_lock_outl( ((15)<<16) + n + 15 , HACTIVESTRTSTOP ); + ep93xxfb_lock_outl( ((n+15)<<16) + 15 , HBLANKSTRTSTOP ); + ep93xxfb_lock_outl( ((n)<<16) + n , HCLKSTRTSTOP ); + + ep93xxfb_lock_outl( 14 , LINECARRY ); + + attribs = 0; + +#ifdef CONFIG_EP93XX_SDCS0 + attribs |= 0 << VIDEOATTRIBS_SDSEL_SHIFT; +#endif +#ifdef CONFIG_EP93XX_SDCS1 + attribs |= 1 << VIDEOATTRIBS_SDSEL_SHIFT; +#endif +#ifdef CONFIG_EP93XX_SDCS2 + attribs |= 2 << VIDEOATTRIBS_SDSEL_SHIFT; +#endif +#ifdef CONFIG_EP93XX_SDCS3 + attribs |= 3 << VIDEOATTRIBS_SDSEL_SHIFT; +#endif + + switch(value) + { + case 8: + ep93xxfb_lock_outl( PIXELMODE_DSCAN | + PIXELMODE_S_8PPC | PIXELMODE_P_4BPP | + PIXELMODE_C_GSLUT , PIXELMODE ); + + ep93xxfb_lock_outl( + attribs | VIDEOATTRIBS_VCPOL | VIDEOATTRIBS_HSPOL | + VIDEOATTRIBS_DATAEN | VIDEOATTRIBS_SYNCEN | VIDEOATTRIBS_INVCLK | + VIDEOATTRIBS_PCLKEN | VIDEOATTRIBS_EN , + VIDEOATTRIBS ); + break; + case 16: + if(!interrupt_hooked) + { + request_irq(IRQ_EP93XX_VSYNC, ep93xxfb_irq_handler, IRQF_DISABLED, "lut switch interrupt", NULL); + interrupt_hooked = 1; + } + ep93xxfb_lock_outl( PIXELMODE_DSCAN | + PIXELMODE_S_8PPC | PIXELMODE_P_4BPP | PIXELMODE_C_GSLUT, PIXELMODE ); + + ep93xxfb_lock_outl( + attribs | VIDEOATTRIBS_VCPOL | VIDEOATTRIBS_HSPOL | + VIDEOATTRIBS_DATAEN | VIDEOATTRIBS_SYNCEN | VIDEOATTRIBS_INVCLK | + VIDEOATTRIBS_PCLKEN | VIDEOATTRIBS_EN | VIDEOATTRIBS_INTEN, + VIDEOATTRIBS ); + break; + default: + return; + } + +} + +void HOSIDEN_HLM6323_configure(unsigned char value) +{ + int n; + unsigned long attribs; + + printk("HOSIDEN_HLM6323_configure\n"); + + switch(value) + { + case 8: + ep93xxfb_8gray_palette_init(); + break; + case 16: + ep93xxfb_16gray_palette_init(); + break; + default: + return; + } + + SysconSetLocked(EP93XX_SYSCON_DEVICE_CONFIG, inl(EP93XX_SYSCON_DEVICE_CONFIG) |EP93XX_SYSCON_DEVCFG_RasOnP3); + + ep93xxfb_lock_outl( 0x00000000 , VIDEOATTRIBS ); + + ep93xx_set_video_div(epinfo.freq*320*240); + mdelay(10); + + n = 240; + ep93xxfb_lock_outl( n + 3 , VLINESTOTAL ); + ep93xxfb_lock_outl( ((n+1)<<16) + n +2 , VSYNCSTRTSTOP ); + ep93xxfb_lock_outl( ((3)<<16) + n +3 , VACTIVESTRTSTOP ); + ep93xxfb_lock_outl( ((3)<<16) + n +3 , VBLANKSTRTSTOP ); + ep93xxfb_lock_outl( ((n+3)<<16) + n +3, VCLKSTRTSTOP ); + + n = 320; + ep93xxfb_lock_outl( n + 3, HCLKSTOTAL ); + ep93xxfb_lock_outl( ((n+1)<<16) + n+2 , HSYNCSTRTSTOP ); + ep93xxfb_lock_outl( ((3)<<16) + n+3 , HACTIVESTRTSTOP ); + ep93xxfb_lock_outl( ((3)<<16) + n+3 , HBLANKSTRTSTOP ); + ep93xxfb_lock_outl( ((n+3)<<16) + n+3 , HCLKSTRTSTOP ); + + ep93xxfb_lock_outl( 3 , LINECARRY ); + + attribs = 0; + +#ifdef CONFIG_EP93XX_SDCS0 + attribs |= 0 << VIDEOATTRIBS_SDSEL_SHIFT; +#endif +#ifdef CONFIG_EP93XX_SDCS1 + attribs |= 1 << VIDEOATTRIBS_SDSEL_SHIFT; +#endif +#ifdef CONFIG_EP93XX_SDCS2 + attribs |= 2 << VIDEOATTRIBS_SDSEL_SHIFT; +#endif +#ifdef CONFIG_EP93XX_SDCS3 + attribs |= 3 << VIDEOATTRIBS_SDSEL_SHIFT; +#endif + + switch(value) + { + case 8: + ep93xxfb_lock_outl( + PIXELMODE_S_4PPC | PIXELMODE_P_4BPP | PIXELMODE_C_GSLUT, PIXELMODE ); + ep93xxfb_lock_outl( + attribs | VIDEOATTRIBS_VCPOL | VIDEOATTRIBS_HSPOL | + VIDEOATTRIBS_DATAEN | VIDEOATTRIBS_SYNCEN | VIDEOATTRIBS_INVCLK | + VIDEOATTRIBS_PCLKEN | VIDEOATTRIBS_EN , + VIDEOATTRIBS ); + break; + case 16: + ep93xxfb_lock_outl( + PIXELMODE_S_4PPC | PIXELMODE_P_4BPP | PIXELMODE_C_GSLUT, PIXELMODE ); + if(!interrupt_hooked) + { + request_irq(IRQ_EP93XX_VSYNC, ep93xxfb_irq_handler, IRQF_DISABLED, "lut switch interrupt", NULL); + interrupt_hooked = 1; + } + ep93xxfb_lock_outl( + attribs | VIDEOATTRIBS_VCPOL | VIDEOATTRIBS_HSPOL | + VIDEOATTRIBS_DATAEN | VIDEOATTRIBS_SYNCEN | VIDEOATTRIBS_INVCLK | + VIDEOATTRIBS_PCLKEN | VIDEOATTRIBS_EN | VIDEOATTRIBS_INTEN, + VIDEOATTRIBS ); + break; + default: + return; + } +} + +#define FB_WRITEL fb_writel +#define FB_READL fb_readl +#define LEFT_POS(bpp) (0) +#define SHIFT_HIGH(val, bits) ((val) << (bits)) +#define SHIFT_LOW(val, bits) ((val) >> (bits)) +static inline void color_imageblit(const struct fb_image *image, + struct fb_info *p, u8 *dst1, + u32 start_index, + u32 pitch_index) +{ + /* Draw the penguin */ + u32 *dst, *dst2; + u32 color = 0, val, shift; + int i, n, bpp = p->var.bits_per_pixel; + u32 null_bits = 32 - bpp; + u32 *palette = (u32 *) p->pseudo_palette; + const u8 *src = image->data; + + dst2 = (u32 *) dst1; + for (i = image->height; i--; ) { + n = image->width; + dst = (u32 *) dst1; + shift = 0; + val = 0; + + if (start_index) { + u32 start_mask = ~(SHIFT_HIGH(~(u32)0, start_index)); + val = FB_READL(dst) & start_mask; + shift = start_index; + } + while (n--) { + if (p->fix.visual == FB_VISUAL_TRUECOLOR || + p->fix.visual == FB_VISUAL_DIRECTCOLOR ) + color = palette[*src]; + else + color = *src; + color <<= LEFT_POS(bpp); + val |= SHIFT_HIGH(color, shift); + if (shift >= null_bits) { + FB_WRITEL(val, dst++); + + val = (shift == null_bits) ? 0 : + SHIFT_LOW(color, 32 - shift); + } + shift += bpp; + shift &= (32 - 1); + src++; + } + if (shift) { + u32 end_mask = SHIFT_HIGH(~(u32)0, shift); + + FB_WRITEL((FB_READL(dst) & end_mask) | val, dst); + } + dst1 += p->fix.line_length; + if (pitch_index) { + dst2 += p->fix.line_length; + dst1 = (u8 *)((long __force)dst2 & ~(sizeof(u32) - 1)); + + start_index += pitch_index; + start_index &= 32 - 1; + } + } +} + +static const int reversebit[]= +{ + 7, 6, 5, 4, 3, 2, 1, 0, + 15,14,13,12,11,10, 9, 8, + 23,22,21,20,19,18,17,16, + 31,30,29,28,27,26,25,24, +}; +static inline void slow_imageblit(const struct fb_image *image, struct fb_info *p, + u8 *dst1, u32 fgcolor, + u32 bgcolor, + u32 start_index, + u32 pitch_index) +{ + u32 shift, color = 0, bpp = p->var.bits_per_pixel; + u32 *dst, *dst2; + u32 val, pitch = p->fix.line_length; + u32 null_bits = 32 - bpp; + u32 spitch = (image->width+7)/8; + const u8 *src = image->data, *s; + u32 i, j, l; + + dst2 = (u32 *) dst1; + fgcolor <<= LEFT_POS(bpp); + bgcolor <<= LEFT_POS(bpp); + for (i = image->height; i--; ) { + shift = val = 0; + l = 8; + j = image->width; + dst = (u32 *) dst1; + s = src; + + /* write leading bits */ + if (start_index) { + u32 start_mask = ~(SHIFT_HIGH(~(u32)0,start_index)); + val = FB_READL(dst) & start_mask; + shift = start_index; + } + + while (j--) { + l--; + color = (*s & (1 << l)) ? fgcolor : bgcolor; + val |= SHIFT_HIGH(color, reversebit[shift]); + /* Did the bitshift spill bits to the next long? */ + if (shift >= null_bits) { + FB_WRITEL(val, dst++); + val = (shift == null_bits) ? 0 : + SHIFT_LOW(color, 32 - reversebit[shift]); + } + shift += bpp; + shift &= (32 - 1); + if (!l) { l = 8; s++; }; + } + + /* write trailing bits */ + if (shift) { + u32 end_mask = SHIFT_HIGH(~(u32)0, shift); + + FB_WRITEL((FB_READL(dst) & end_mask) | val, dst); + } + + dst1 += pitch; + src += spitch; + if (pitch_index) { + dst2 += pitch; + dst1 = (u8 *)((long __force)dst2 & ~(sizeof(u32) - 1)); + start_index += pitch_index; + start_index &= 32 - 1; + } + + } +} + +static void ep93xx_imageblit(struct fb_info *p, const struct fb_image *image) +{ + u32 fgcolor, bgcolor, start_index, bitstart, pitch_index = 0; + u32 bpl = sizeof(u32), bpp = p->var.bits_per_pixel; + u32 dx = image->dx, dy = image->dy; + u8 *dst1; + + if (p->state != FBINFO_STATE_RUNNING) + return; + + bitstart = (dy * p->fix.line_length * 8) + (dx * bpp); + start_index = bitstart & (32 - 1); + pitch_index = (p->fix.line_length & (bpl - 1)) * 8; + + bitstart /= 8; + bitstart &= ~(bpl - 1); + dst1 = p->screen_base + bitstart; + + if (p->fbops->fb_sync) + p->fbops->fb_sync(p); + + if (image->depth == 1) { + if (p->fix.visual == FB_VISUAL_TRUECOLOR || + p->fix.visual == FB_VISUAL_DIRECTCOLOR) { + fgcolor = ((u32*)(p->pseudo_palette))[image->fg_color]; + bgcolor = ((u32*)(p->pseudo_palette))[image->bg_color]; + } else { + fgcolor = image->fg_color; + bgcolor = image->bg_color; + } + slow_imageblit(image, p, dst1, fgcolor, bgcolor, + start_index, pitch_index); + } else + color_imageblit(image, p, dst1, start_index, pitch_index); +} + + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,8) + +int ep93xxfb_ioctl(struct fb_info *info,unsigned int cmd, unsigned long arg) +{ + return 0; +} + +static int ep93xxfb_mmap(struct fb_info *info,struct vm_area_struct *vma) +{ + unsigned long off, start, len; + + DPRINTK("ep93xxfb_mmap - enter\n"); + + off = vma->vm_pgoff << PAGE_SHIFT; + start = info->fix.smem_start; + len = PAGE_ALIGN(start & ~PAGE_MASK) + info->fix.smem_len; + start &= PAGE_MASK; + if ((vma->vm_end - vma->vm_start + off) > len) + return -EINVAL; + + off += start; + vma->vm_pgoff = off >> PAGE_SHIFT; + + vma->vm_flags |= VM_IO; + vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); + + if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT, + vma->vm_end - vma->vm_start, vma->vm_page_prot)) { + DPRINTK("ep93xxfb_mmap error\n"); + return -EAGAIN; + } + + DPRINTK("ep93xxfb_mmap - exit\n"); + return 0; +} + + +static struct fb_ops ep93xxfb_ops = { + .owner = THIS_MODULE, + .fb_check_var = ep93xxfb_check_var, + .fb_set_par = ep93xxfb_set_par, + .fb_blank = ep93xxfb_blank, + .fb_fillrect = cfb_fillrect, + .fb_copyarea = cfb_copyarea, + // .fb_imageblit = cfb_imageblit, + .fb_imageblit = ep93xx_imageblit, + .fb_ioctl = ep93xxfb_ioctl, + .fb_mmap = ep93xxfb_mmap, +}; + + +static struct resource ep93xxfb_raster_resources = { + .start = EP93XX_RASTER_PHYS_BASE, + .end = EP93XX_RASTER_PHYS_BASE + 0x1ffff, + .flags = IORESOURCE_MEM, +}; + + +static int __init ep93xxfb_probe(struct platform_device *device) +{ + struct fb_info *info = NULL; + struct resource *res = NULL; + int ret = 0; + int arb = 0; + + DPRINTK("ep93xxfb_probe - enter \n"); + + if(!device) { + printk("error : to_platform_device\n"); + return -ENODEV; + } + res = platform_get_resource( device, IORESOURCE_MEM, 0); + if(!res) { + printk("error : platform_get_resource \n"); + return -ENODEV; + } + if (!request_mem_region(res->start,res->end - res->start + 1, FBDEV_NAME )) + return -EBUSY; + + info = framebuffer_alloc(sizeof(u32) * 256, &device->dev); + + if(!info) { + printk("Unable to allocate memory for frame buffer\n"); + return -ENOMEM; + } + + info->flags = FBINFO_DEFAULT; + strncpy(info->fix.id, FBDEV_NAME, sizeof(info->fix.id)); + info->fix.mmio_start = res->start; + info->fix.mmio_len = res->end - res->start + 1; + info->fbops = &ep93xxfb_ops; + info->pseudo_palette = info->par; + info->state = FBINFO_STATE_RUNNING; + + printk("mmio_start = 0x%08x\n", res->start); + printk("mmio_len = 0x%08x\n", res->end - res->start + 1); + + if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) { + ret = -ENOMEM; + goto fbuff; + } + + if ((ret = ep93xxfb_config(info)) < 0) + goto clmap; + + if (register_framebuffer(info) < 0) { + printk(KERN_ERR "Unable to register ep93xxfb frame buffer\n"); + ret = -EINVAL; + goto clmap; + } + platform_set_drvdata(device, info); + printk(KERN_INFO "fb%d: EP93xx frame buffer at %dx%dx%dbpp\n", info->node, + info->var.xres, info->var.yres, info->var.bits_per_pixel); + + /*change the raster arb to the highest one--Bo*/ + arb = inl(EP93XX_SYSCON_BMAR); + arb = (arb & 0x3f8) | 0x01; + ep93xxfb_outl(arb,EP93XX_SYSCON_BMAR); + + DPRINTK("ep93xxfb_probe - exit \n"); + return 0; + +clmap: + fb_dealloc_cmap(&info->cmap); + +fbuff: + framebuffer_release(info); + return ret; +} + +static int ep93xxfb_remove(struct platform_device *device) +{ + struct resource *res; + struct fb_info *info; + + DPRINTK("ep93xxfb_remove - enter \n"); + + info = platform_get_drvdata(device); + + ep93xxfb_release_videomem(); + + res = platform_get_resource( device, IORESOURCE_MEM, 0); + release_mem_region(res->start, res->end - res->start + 1); + + platform_set_drvdata(device, NULL); + unregister_framebuffer(info); + + fb_dealloc_cmap(&info->cmap); + framebuffer_release(info); + + ep93xxfb_blank( 1, info ); + + DPRINTK("ep93xxfb_remove - exit \n"); + return 0; +} + +static void ep93xxfb_platform_release(struct device *device) +{ + DPRINTK("ep93xxfb_platform_release - enter\n"); +} + + +static struct platform_driver ep93xxfb_driver = { + .probe = ep93xxfb_probe, + .remove = ep93xxfb_remove, + .driver = { + .name = FBDEV_NAME, + }, +}; + +static struct platform_device ep93xxfb_device = { + .name = FBDEV_NAME, + .id = -1, + .dev = { + .release = ep93xxfb_platform_release, + }, + .num_resources = 1, + .resource = &ep93xxfb_raster_resources, +}; + +int __init ep93xxfb_init(void) +{ + int ret = 0; + + DPRINTK("ep93xxfb_init - enter\n"); + + ret = platform_driver_register(&ep93xxfb_driver); + + if (!ret) { + ret = platform_device_register(&ep93xxfb_device); + if (ret) + platform_driver_unregister(&ep93xxfb_driver); + } + DPRINTK("ep93xxfb_init - exit\n"); + return ret; +} + +static void __exit ep93xxfb_exit(void) +{ + DPRINTK("ep93xxfb_exit - enter\n"); + platform_driver_unregister(&ep93xxfb_driver); + platform_device_unregister(&ep93xxfb_device); + DPRINTK("ep93xxfb_exit - exit\n"); +} + +#else // LINUX_VERSION_CODE + + +int ep93xxfb_setcolreg(unsigned regno, unsigned red, unsigned green, + unsigned blue, unsigned transp, + struct fb_info *info) +{ + return 0; +} +static struct fb_ops ep93xxfb_ops = { + .owner = THIS_MODULE, + .fb_setcolreg = ep93xxfb_setcolreg, + .fb_check_var = ep93xxfb_check_var, + .fb_set_par = ep93xxfb_set_par, + .fb_blank = ep93xxfb_blank, + .fb_fillrect = cfb_fillrect, + .fb_copyarea = cfb_copyarea, + .fb_imageblit = ep93xx_imageblit, + .fb_cursor = soft_cursor, +}; + +static int __init ep93xxfb_probe(struct device *device) +{ + struct platform_device *pdev = to_platform_device(device); + struct fb_info *info = NULL; + struct resource *res = NULL; + int ret = 0; + int arb = 0; + + DPRINTK("ep93xxfb_probe - enter \n"); + + + if(!device) { + printk("error : to_platform_device\n"); + return -ENODEV; + } + res = platform_get_resource( pdev, IORESOURCE_MEM, 0); + if(!res) { + printk("error : platform_get_resource \n"); + return -ENODEV; + } + if (!request_mem_region(res->start,res->end - res->start + 1, FBDEV_NAME )) + return -EBUSY; + + info = framebuffer_alloc(sizeof(u32) * 256, &pdev->dev); + + if(!info) { + printk("Unable to allocate memory for frame buffer\n"); + return -ENOMEM; + } + + info->flags = FBINFO_DEFAULT; + strncpy(info->fix.id, FBDEV_NAME, sizeof(info->fix.id)); + info->fix.mmio_start = res->start; + info->fix.mmio_len = res->end - res->start + 1; + info->fbops = &ep93xxfb_ops; + info->pseudo_palette = info->par; + info->state = FBINFO_STATE_RUNNING; + + if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) { + ret = -ENOMEM; + goto fbuff; + } + + if ((ret = ep93xxfb_config(info)) < 0) + goto clmap; + + if (register_framebuffer(info) < 0) { + printk(KERN_ERR "Unable to register ep93xxfb frame buffer\n"); + ret = -EINVAL; + goto clmap; + } + dev_set_drvdata(device, info); + printk(KERN_INFO "fb%d: EP93xx frame buffer at %dx%dx%dbpp\n", info->node, + info->var.xres, info->var.yres, info->var.bits_per_pixel); + + /*change the raster arb to the highest one--Bo*/ + arb = inl(EP93XX_SYSCON_BMAR); + arb = (arb & 0x3f8) | 0x01; + ep93xxfb_outl(arb,EP93XX_SYSCON_BMAR); + + DPRINTK("ep93xxfb_probe - exit \n"); + return 0; + +clmap: + fb_dealloc_cmap(&info->cmap); + +fbuff: + framebuffer_release(info); + return ret; +} + +static int ep93xxfb_remove(struct device *device) +{ + struct platform_device *pdev = to_platform_device(device); + struct resource *res; + struct fb_info *info; + + DPRINTK("ep93xxfb_remove - enter \n"); + + info = dev_get_drvdata(device); + + ep93xxfb_release_videomem(); + + res = platform_get_resource( pdev, IORESOURCE_MEM, 0); + release_mem_region(res->start, res->end - res->start + 1); + + dev_set_drvdata(device, NULL); + unregister_framebuffer(info); + + fb_dealloc_cmap(&info->cmap); + framebuffer_release(info); + + ep93xxfb_blank( 1, info ); + + DPRINTK("ep93xxfb_remove - exit \n"); + return 0; +} +static struct device_driver ep93xxfb_driver = { + .name = FBDEV_NAME, + .bus = &platform_bus_type, + .probe = ep93xxfb_probe, + .remove = ep93xxfb_remove, +}; +int __init ep93xxfb_init(void) +{ + DPRINTK("ep93xxfb_init\n"); + return driver_register(&ep93xxfb_driver); +} + +static void __exit ep93xxfb_exit(void) +{ + DPRINTK("ep93xxfb_exit\n"); + return driver_unregister(&ep93xxfb_driver); +} + +int __init ep93xxfb_setup(char *options) +{ + DPRINTK("ep93xxfb_setup\n"); + return 0; +} + +#endif // LINUX_VERSION_CODE + + +module_init(ep93xxfb_init); +module_exit(ep93xxfb_exit); +MODULE_AUTHOR("John Zheng "); +MODULE_LICENSE("GPL"); + --- a/arch/arm/mach-ep93xx/include/mach/hardware.h +++ b/arch/arm/mach-ep93xx/include/mach/hardware.h @@ -7,6 +7,7 @@ #include "ep93xx-regs.h" #define pcibios_assign_all_busses() 0 +#include "regs_raster.h" #include "regs_touch.h" #include "platform.h" --- a/arch/arm/mach-ep93xx/include/mach/irqs.h +++ b/arch/arm/mach-ep93xx/include/mach/irqs.h @@ -34,7 +34,8 @@ #define IRQ_EP93XX_UART3TX 28 #define IRQ_EP93XX_KEY 29 #define IRQ_EP93XX_TOUCH 30 -#define EP93XX_VIC1_VALID_IRQ_MASK 0x7ffffffc +#define IRQ_EP93XX_GRAPHICS 31 +#define EP93XX_VIC1_VALID_IRQ_MASK 0xfffffffc #define IRQ_EP93XX_EXT0 32 #define IRQ_EP93XX_EXT1 33 --- /dev/null +++ b/arch/arm/mach-ep93xx/include/mach/regs_raster.h @@ -0,0 +1,347 @@ +/*============================================================================= + * + * FILE: regs_raster.h + * + * DESCRIPTION: ep93xx Raster Engine Register Definition + * + * Copyright Cirrus Logic, 2001-2003 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + *============================================================================= + */ +#ifndef _REGS_RASTER_H_ +#define _REGS_RASTER_H_ + +//----------------------------------------------------------------------------- +// VLINESTOTAL Register Definitions +//----------------------------------------------------------------------------- +#define VLINESTOTAL_MASK 0x000007ff + +//----------------------------------------------------------------------------- +// VSYNCSTRTSTOP Register Definitions +//----------------------------------------------------------------------------- +#define VSYNCSTRTSTOP_STRT_MASK 0x07ff0000 +#define VSYNCSTRTSTOP_STRT_SHIFT 0 +#define VSYNCSTRTSTOP_STOP_MASK 0x000007ff +#define VSYNCSTRTSTOP_STOP_SHIFT 16 + +//----------------------------------------------------------------------------- +// VACTIVESTRTSTOP Register Definitions +//----------------------------------------------------------------------------- +#define VACTIVESTRTSTOP_STRT_MASK 0x07ff0000 +#define VACTIVESTRTSTOP_STRT_SHIFT 0 +#define VACTIVESTRTSTOP_STOP_MASK 0x000007ff +#define VACTIVESTRTSTOP_STOP_SHIFT 16 + +//----------------------------------------------------------------------------- +// VCLKSTRTSTOP Register Definitions +//----------------------------------------------------------------------------- +#define VCLKSTRTSTOP_STRT_MASK 0x07ff0000 +#define VCLKSTRTSTOP_STRT_SHIFT 0 +#define VCLKSTRTSTOP_STOP_MASK 0x000007ff +#define VCLKSTRTSTOP_STOP_SHIFT 16 + +//----------------------------------------------------------------------------- +// VBLANKSTRTSTOP Register Definitions +//----------------------------------------------------------------------------- +#define VBLANKSTRTSTOP_STRT_MASK 0x07ff0000 +#define VBLANKSTRTSTOP_STRT_SHIFT 0 +#define VBLANKSTRTSTOP_STOP_MASK 0x000007ff +#define VBLANKSTRTSTOP_STOP_SHIFT 16 + +//----------------------------------------------------------------------------- +// HSYNCSTRTSTOP Register Definitions +//----------------------------------------------------------------------------- +#define HSYNCSTRTSTOP_STRT_MASK 0x07ff0000 +#define HSYNCSTRTSTOP_STRT_SHIFT 0 +#define HSYNCSTRTSTOP_STOP_MASK 0x000007ff +#define HSYNCSTRTSTOP_STOP_SHIFT 16 + +//----------------------------------------------------------------------------- +// HACTIVESTRTSTOP Register Definitions +//----------------------------------------------------------------------------- +#define HACTIVESTRTSTOP_STRT_MASK 0x07ff0000 +#define HACTIVESTRTSTOP_STRT_SHIFT 0 +#define HACTIVESTRTSTOP_STOP_MASK 0x000007ff +#define HACTIVESTRTSTOP_STOP_SHIFT 16 + +//----------------------------------------------------------------------------- +// HCLKSTRTSTOP Register Definitions +//----------------------------------------------------------------------------- +#define HCLKSTRTSTOP_STRT_MASK 0x07ff0000 +#define HCLKSTRTSTOP_STRT_SHIFT 0 +#define HCLKSTRTSTOP_STOP_MASK 0x000007ff +#define HCLKSTRTSTOP_STOP_SHIFT 16 + +//----------------------------------------------------------------------------- +// BRIGHTNESS Register Definitions +//----------------------------------------------------------------------------- +#define BRIGHTNESS_MASK 0x0000ffff +#define BRIGHTNESS_CNT_MASK 0x000000ff +#define BRIGHTNESS_CNT_SHIFT 0 +#define BRIGHTNESS_CMP_MASK 0x0000ff00 +#define BRIGHTNESS_CMP_SHIFT 8 + +//----------------------------------------------------------------------------- +// VIDEOATTRIBS Register Definitions +//----------------------------------------------------------------------------- +#define VIDEOATTRIBS_MASK 0x001fffff +#define VIDEOATTRIBS_EN 0x00000001 +#define VIDEOATTRIBS_PCLKEN 0x00000002 +#define VIDEOATTRIBS_SYNCEN 0x00000004 +#define VIDEOATTRIBS_DATAEN 0x00000008 +#define VIDEOATTRIBS_CSYNC 0x00000010 +#define VIDEOATTRIBS_VCPOL 0x00000020 +#define VIDEOATTRIBS_HSPOL 0x00000040 +#define VIDEOATTRIBS_BLKPOL 0x00000080 +#define VIDEOATTRIBS_INVCLK 0x00000100 +#define VIDEOATTRIBS_ACEN 0x00000200 +#define VIDEOATTRIBS_LCDEN 0x00000400 +#define VIDEOATTRIBS_CCIREN 0x00001000 +#define VIDEOATTRIBS_PIFEN 0x00002000 +#define VIDEOATTRIBS_INTEN 0x00004000 +#define VIDEOATTRIBS_INT 0x00008000 +#define VIDEOATTRIBS_INTRLC 0x00010000 +#define VIDEOATTRIBS_EQUSER 0x00020000 +#define VIDEOATTRIBS_DHORZ 0x00040000 +#define VIDEOATTRIBS_DVERT 0x00080000 +#define VIDEOATTRIBS_BKPXD 0x00100000 + +#define VIDEOATTRIBS_SDSEL_MASK 0x00600000 +#define VIDEOATTRIBS_SDSEL_SHIFT 21 + +//----------------------------------------------------------------------------- +// HBLANKSTRTSTOP Register Definitions +//----------------------------------------------------------------------------- +#define HBLANKSTRTSTOP_STRT_MASK 0x07ff0000 +#define HBLANKSTRTSTOP_STRT_SHIFT 0 +#define HBLANKSTRTSTOP_STOP_MASK 0x000007ff +#define HBLANKSTRTSTOP_STOP_SHIFT 16 + +//----------------------------------------------------------------------------- +// LINECARRY Register Definitions +//----------------------------------------------------------------------------- +#define LINECARRY_LCARY_MASK 0x000007ff +#define LINECARRY_LCARY_SHIFT 0 + +//----------------------------------------------------------------------------- +// BLINKRATE Register Definitons +//----------------------------------------------------------------------------- +#define BLINKRATE_MASK 0x000000ff + +//----------------------------------------------------------------------------- +// BLINKMASK Register Definitons +//----------------------------------------------------------------------------- +#define BLINKMASK_MASK 0x00ffffff + +//----------------------------------------------------------------------------- +// VIDSCRNPAGE Register Definitons +//----------------------------------------------------------------------------- +#define VIDSCRNPAGE_PAGE_MASK 0x0ffffffc + +//----------------------------------------------------------------------------- +// VIDSCRNHPG Register Definitons +//----------------------------------------------------------------------------- +#define VIDSCRNHPG_MASK 0x0ffffffc + +//----------------------------------------------------------------------------- +// SCRNLINES Register Definitons +//----------------------------------------------------------------------------- +#define SCRNLINES_MASK 0x000007ff + +//----------------------------------------------------------------------------- +// LINELENGTH Register Definitons +//----------------------------------------------------------------------------- +#define LINELENGTH_MASK 0x000007ff + +//----------------------------------------------------------------------------- +// VLINESTEP Register Definitons +//----------------------------------------------------------------------------- +#define VLINESTEP_MASK 0x00000fff + +//----------------------------------------------------------------------------- +// RASTER_SWLOCK Register Definitons +//----------------------------------------------------------------------------- +#define RASTER_SWLOCK_MASK_WR 0xff +#define RASTER_SWLOCK_MASK_R 0x1 +#define RASTER_SWLOCK_VALUE 0xaa + +//----------------------------------------------------------------------------- +// LUTCONT Register Definitions +//----------------------------------------------------------------------------- +#define LUTCONT_MASK 0x00000003 +#define LUTCONT_SWTCH 0x00000001 +#define LUTCONT_STAT 0x00000002 +#define LUTCONT_RAM0 0 +#define LUTCONT_RAM1 1 + +//----------------------------------------------------------------------------- +// CURSORBLINK1 Register Definitions +//----------------------------------------------------------------------------- +#define CURSORBLINK1_MASK 0x00ffffff +//----------------------------------------------------------------------------- +// CURSORBLINK2 Register Definitions +//----------------------------------------------------------------------------- +#define CURSORBLINK2_MASK 0x00ffffff + +//----------------------------------------------------------------------------- +// CURSORBLINK Register Definitions +//----------------------------------------------------------------------------- +#define CURSORBLINK_MASK 0x000001ff +#define CURSORBLINK_RATE_MASK 0x000000ff +#define CURSORBLINK_RATE_SHIFT 0 +#define CURSORBLINK_EN 0x00000100 + +//----------------------------------------------------------------------------- +// BLINKPATRN Register Definitions +//----------------------------------------------------------------------------- +#define BLINKPATRN_MASK 0x00ffffff + +//----------------------------------------------------------------------------- +// PATRNMASK Register Definitions +//----------------------------------------------------------------------------- +#define PATRNMASK_MASK 0x00ffffff + +//----------------------------------------------------------------------------- +// BG_OFFSET Register Definitions +//----------------------------------------------------------------------------- +#define BG_OFFSET_MASK 0x00ffffff + +//----------------------------------------------------------------------------- +// PIXELMODE Register Definitions +//----------------------------------------------------------------------------- +#define PIXELMODE_P_MASK 0x00000007 +#define PIXELMODE_P_MUX_DISABLE 0x00000000 +#define PIXELMODE_P_4BPP 0x00000001 +#define PIXELMODE_P_8BPP 0x00000002 +#define PIXELMODE_P_16BPP 0x00000004 +#define PIXELMODE_P_24BPP 0x00000006 +#define PIXELMODE_P_32BPP 0x00000007 + +#define PIXELMODE_S_MASK 0x00000038 +#define PIXELMODE_S_1PPC 0x00000000 +#define PIXELMODE_S_1PPCMAPPED 0x00000008 +#define PIXELMODE_S_2PPC 0x00000010 +#define PIXELMODE_S_4PPC 0x00000018 +#define PIXELMODE_S_8PPC 0x00000020 +#define PIXELMODE_S_223PPC 0x00000028 +#define PIXELMODE_S_DS223PPC 0x00000030 +#define PIXELMODE_S_UNDEF 0x00000038 + +#define PIXELMODE_M_MASK 0x000003c0 +#define PIXELMODE_M_NOBLINK 0x00000000 +#define PIXELMODE_M_ANDBLINK 0x00000040 +#define PIXELMODE_M_ORBLINK 0x00000080 +#define PIXELMODE_M_XORBLINK 0x000000c0 +#define PIXELMODE_M_BGBLINK 0x00000100 +#define PIXELMODE_M_OFFSINGBLINK 0x00000140 +#define PIXELMODE_M_OFF888BLINK 0x00000180 +#define PIXELMODE_M_DIMBLINK 0x00000300 +#define PIXELMODE_M_BRTBLINK 0x00000340 +#define PIXELMODE_M_DIM888BLINK 0x00000380 +#define PIXELMODE_M_BRT888BLINK 0x000003c0 + +#define PIXELMODE_C_MASK 0x00003c00 +#define PIXELMODE_C_LUT 0x00000000 +#define PIXELMODE_C_888 0x00001000 +#define PIXELMODE_C_565 0x00001400 +#define PIXELMODE_C_555 0x00001800 +#define PIXELMODE_C_GSLUT 0x00002000 + +#define PIXELMODE_DSCAN 0x00004000 +#define PIXELMODE_TRBSW 0x00008000 + +//----------------------------------------------------------------------------- +//PARLLIFOUT Register Defintions +//----------------------------------------------------------------------------- +#define PARLLIFOUT_DAT_MASK 0x0000000f +#define PARLLIFOUT_DAT_SHIFT 0 +#define PARLLIFOUT_RD 0x00000010 + +//----------------------------------------------------------------------------- +//PARLLIFIN Register Defintions +//----------------------------------------------------------------------------- +#define PARLLIFIN_DAT_MASK 0x0000000f +#define PARLLIFIN_DAT_SHIFT 0 +#define PARLLIFIN_CNT_MASK 0x000f0000 +#define PARLLIFIN_CNT_SHIFT 16 +#define PARLLIFIN_ESTRT_MASK 0x00f00000 +#define PARLLIFIN_ESTRT_SHIFT 20 + +//----------------------------------------------------------------------------- +// CURSORADRSTART Register Defintions +//----------------------------------------------------------------------------- +#define CURSOR_ADR_START_MASK 0xfffffffc + +//----------------------------------------------------------------------------- +// CURSORADRSTART Register Defintions +//----------------------------------------------------------------------------- +#define CURSOR_ADR_RESET_MASK 0xfffffffc + +//----------------------------------------------------------------------------- +// CURSORCOLOR1 Register Definitions +//----------------------------------------------------------------------------- +#define CURSORCOLOR1_MASK 0x00ffffff +//----------------------------------------------------------------------------- +// CURSORCOLOR2 Register Definitions +//----------------------------------------------------------------------------- +#define CURSORCOLOR2_MASK 0x00ffffff + +//----------------------------------------------------------------------------- +// CURSORXYLOC Register Definitions +//----------------------------------------------------------------------------- +#define CURSORXYLOC_MASK 0x07ff87ff +#define CURSORXYLOC_XLOC_MASK 0x000007ff +#define CURSORXYLOC_XLOC_SHIFT 0 +#define CURSORXYLOC_CEN 0x00008000 +#define CURSORXYLOC_YLOC_MASK 0x07ff0000 +#define CURSORXYLOC_YLOC_SHIFT 16 + +//----------------------------------------------------------------------------- +// CURSOR_DSCAN_LH_YLOC Register Definitions +//----------------------------------------------------------------------------- +#define CURSOR_DSCAN_LH_YLOC_MASK 0x000087ff + +#define CURSOR_DSCAN_LH_YLOC_YLOC_MASK 0x000007ff +#define CURSOR_DSCAN_LH_YLOC_YLOC_SHIFT 0 +#define CURSOR_DSCAN_LH_YLOC_CLHEN 0x00008000 + +//----------------------------------------------------------------------------- +// CURSORSIZE Register Definitions +//----------------------------------------------------------------------------- +#define CURSORSIZE_MASK 0x0000ffff + +#define CURSORSIZE_CWID_MASK 0x00000003 +#define CURSORSIZE_CWID_SHIFT 0 +#define CURSORSIZE_CWID_1_WORD 0 +#define CURSORSIZE_CWID_2_WORD 1 +#define CURSORSIZE_CWID_3_WORD 2 +#define CURSORSIZE_CWID_4_WORD 3 + +#define CURSORSIZE_CLINS_MASK 0x000000fc +#define CURSORSIZE_CLINS_SHIFT 2 + +#define CURSORSIZE_CSTEP_MASK 0x00000300 +#define CURSORSIZE_CSTEP_SHIFT 8 +#define CURSORSIZE_CSTEP_1_WORD 0 +#define CURSORSIZE_CSTEP_2_WORD 1 +#define CURSORSIZE_CSTEP_3_WORD 2 +#define CURSORSIZE_CSTEP_4_WORD 3 + +#define CURSORSIZE_DLNS_MASK 0x0000fc00 +#define CURSORSIZE_DLNS_SHIFT 10 + +#endif /* _REGS_RASTER_H_ */