/*
* Frame Buffer Driver for PKUnity-v3 Unigfx
* Code specific to PKUnity SoC and UniCore ISA
*
* Maintained by GUAN Xue-tao <gxt@mprc.pku.edu.cn>
* Copyright (C) 2001-2010 Guan Xuetao
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/platform_device.h>
#include <linux/clk.h>
#include <linux/fb.h>
#include <linux/init.h>
#include <linux/console.h>
#include <linux/mm.h>
#include <asm/sizes.h>
#include <asm/pgtable.h>
#include <mach/hardware.h>
/* Platform_data reserved for unifb registers. */
#define UNIFB_REGS_NUM 10
/* RAM reserved for the frame buffer. */
#define UNIFB_MEMSIZE (SZ_4M) /* 4 MB for 1024*768*32b */
/*
* cause UNIGFX don not have EDID
* all the modes are organized as follow
*/
static const struct fb_videomode unifb_modes[] = {
/* 0 640x480-60 VESA */
{ "640x480@60", 60, 640, 480, 25175000, 48, 16, 34, 10, 96, 1,
0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
/* 1 640x480-75 VESA */
{ "640x480@75", 75, 640, 480, 31500000, 120, 16, 18, 1, 64, 1,
0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
/* 2 800x600-60 VESA */
{ "800x600@60", 60, 800, 600, 40000000, 88, 40, 26, 1, 128, 1,
0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
/* 3 800x600-75 VESA */
{ "800x600@75", 75, 800, 600, 49500000, 160, 16, 23, 1, 80, 1,
0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
/* 4 1024x768-60 VESA */
{ "1024x768@60", 60, 1024, 768, 65000000, 160, 24, 34, 3, 136, 1,
0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
/* 5 1024x768-75 VESA */
{ "1024x768@75", 75, 1024, 768, 78750000, 176, 16, 30, 1, 96, 1,
0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
/* 6 1280x960-60 VESA */
{ "1280x960@60", 60, 1280, 960, 108000000, 312, 96, 38, 1, 112, 1,
0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
/* 7 1440x900-60 VESA */
{ "1440x900@60", 60, 1440, 900, 106500000, 232, 80, 30, 3, 152, 1,
0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
/* 8 FIXME 9 1024x600-60 VESA UNTESTED */
{ "1024x600@60", 60, 1024, 600, 50650000, 160, 24, 26, 1, 136, 1,
0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
/* 9 FIXME 10 1024x600-75 VESA UNTESTED */
{ "1024x600@75", 75, 1024, 600, 61500000, 176, 16, 23, 1, 96, 1,
0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
/* 10 FIXME 11 1366x768-60 VESA UNTESTED */
{ "1366x768@60", 60, 1366, 768, 85500000, 256, 58, 18, 1, 112, 3,
0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
};
static struct fb_var_screeninfo unifb_default = {
.xres = 640,
.yres = 480,
.xres_virtual = 640,
.yres_virtual = 480,
.bits_per_pixel = 16,
.red = { 11, 5, 0 },
.green = { 5, 6, 0 },
.blue = { 0, 5, 0 },
.activate = FB_ACTIVATE_NOW,
.height = -1,
.width = -1,
.pixclock = 25175000,
.left_margin = 48,
.right_margin = 16,
.upper_margin = 33,
.lower_margin = 10,
.hsync_len = 96,
.vsync_len = 2,
.vmode = FB_VMODE_NONINTERLACED,
};
static struct fb_fix_screeninfo unifb_fix = {
.id = "UNIGFX FB",
.type = FB_TYPE_PACKED_PIXELS,
.visual = FB_VISUAL_TRUECOLOR,
.xpanstep = 1,
.ypanstep = 1,
.ywrapstep = 1,
.accel = FB_ACCEL_NONE,
};
static void unifb_sync(struct fb_info *info)
{
/* TODO: may, this can be replaced by interrupt */
int cnt;
for (cnt = 0; cnt < 0x10000000; cnt++) {
if (readl(UGE_COMMAND) & 0x1000000)
return;
}
if (cnt > 0x8000000)
dev_warn(info->device, "Warning: UniGFX GE time out ...\n");
}
static void unifb_prim_fillrect(struct fb_info *info,
const struct fb_fillrect *region)
{
int awidth = region->width;
int aheight = region->height;
int m_iBpp = info->var.bits_per_pixel;
int screen_width = info->var.xres;
int src_sel = 1; /* from fg_color */
int pat_sel = 1;
int src_x0 = 0;
int dst_x0 = region