13 #include <linux/module.h>
14 #include <linux/kernel.h>
15 #include <linux/errno.h>
22 #include <asm/sizes.h>
23 #include <mach/hardware.h>
26 #define UNIFB_REGS_NUM 10
28 #define UNIFB_MEMSIZE (SZ_4M)
36 {
"640x480@60", 60, 640, 480, 25175000, 48, 16, 34, 10, 96, 1,
39 {
"640x480@75", 75, 640, 480, 31500000, 120, 16, 18, 1, 64, 1,
42 {
"800x600@60", 60, 800, 600, 40000000, 88, 40, 26, 1, 128, 1,
45 {
"800x600@75", 75, 800, 600, 49500000, 160, 16, 23, 1, 80, 1,
48 {
"1024x768@60", 60, 1024, 768, 65000000, 160, 24, 34, 3, 136, 1,
51 {
"1024x768@75", 75, 1024, 768, 78750000, 176, 16, 30, 1, 96, 1,
54 {
"1280x960@60", 60, 1280, 960, 108000000, 312, 96, 38, 1, 112, 1,
57 {
"1440x900@60", 60, 1440, 900, 106500000, 232, 80, 30, 3, 152, 1,
60 {
"1024x600@60", 60, 1024, 600, 50650000, 160, 24, 26, 1, 136, 1,
63 {
"1024x600@75", 75, 1024, 600, 61500000, 176, 16, 23, 1, 96, 1,
66 {
"1366x768@60", 60, 1366, 768, 85500000, 256, 58, 18, 1, 112, 3,
107 for (cnt = 0; cnt < 0x10000000; cnt++) {
116 static void unifb_prim_fillrect(
struct fb_info *info,
119 int awidth = region->
width;
120 int aheight = region->
height;
121 int m_iBpp = info->
var.bits_per_pixel;
122 int screen_width = info->
var.xres;
126 int dst_x0 = region->
dx;
128 int dst_y0 = region->
dy;
129 int rop_alpha_sel = 0;
130 int rop_alpha_code = 0xCC;
135 int dst_pitch = screen_width * (m_iBpp / 8);
136 int dst_offset = dst_y0 * dst_pitch + dst_x0 * (m_iBpp / 8);
137 int src_pitch = screen_width * (m_iBpp / 8);
138 int src_offset = src_y0 * src_pitch + src_x0 * (m_iBpp / 8);
148 bottom = (bottom << 16) | right;
149 command = (rop_alpha_sel << 26) | (pat_sel << 18) | (src_sel << 16)
150 | (x_dir << 20) | (y_dir << 21) | (command << 24)
151 | (clip_region << 23) | (clip_en << 22) | (tp_en << 27);
152 src_pitch = (dst_pitch << 16) | src_pitch;
153 awidth = awidth | (aheight << 16);
154 alpha_r = ((rop_alpha_code & 0xff) << 8) | (alpha_r & 0xff)
156 src_x0 = (src_x0 & 0x1fff) | ((src_y0 & 0x1fff) << 16);
157 dst_x0 = (dst_x0 & 0x1fff) | ((dst_y0 & 0x1fff) << 16);
158 fg_color = region->
color;
176 static void unifb_fillrect(
struct fb_info *info,
187 vxres = info->
var.xres_virtual;
188 vyres = info->
var.yres_virtual;
192 if (!modded.width || !modded.height ||
193 modded.dx >= vxres || modded.dy >= vyres)
196 if (modded.dx + modded.width > vxres)
197 modded.width = vxres - modded.dx;
198 if (modded.dy + modded.height > vyres)
199 modded.height = vyres - modded.dy;
201 unifb_prim_fillrect(info, &modded);
204 static void unifb_prim_copyarea(
struct fb_info *info,
207 int awidth = area->
width;
208 int aheight = area->
height;
209 int m_iBpp = info->
var.bits_per_pixel;
210 int screen_width = info->
var.xres;
213 int src_x0 = area->
sx;
214 int dst_x0 = area->
dx;
215 int src_y0 = area->
sy;
216 int dst_y0 = area->
dy;
218 int rop_alpha_sel = 0;
219 int rop_alpha_code = 0xCC;
225 int dst_pitch = screen_width * (m_iBpp / 8);
226 int dst_offset = dst_y0 * dst_pitch + dst_x0 * (m_iBpp / 8);
227 int src_pitch = screen_width * (m_iBpp / 8);
228 int src_offset = src_y0 * src_pitch + src_x0 * (m_iBpp / 8);
229 unsigned int command = 0;
234 int bottom = info->
var.yres;
235 int right = info->
var.xres;
244 if (src_y0 - dst_y0 > 0) {
248 src_offset = (src_y0 + aheight) * src_pitch +
249 src_x0 * (m_iBpp / 8);
250 dst_offset = (dst_y0 + aheight) * dst_pitch +
251 dst_x0 * (m_iBpp / 8);
256 command = (rop_alpha_sel << 26) | (pat_sel << 18) | (src_sel << 16) |
257 (x_dir << 20) | (y_dir << 21) | (command << 24) |
258 (clip_region << 23) | (clip_en << 22) | (tp_en << 27);
259 src_pitch = (dst_pitch << 16) | src_pitch;
260 awidth = awidth | (aheight << 16);
261 alpha_r = ((rop_alpha_code & 0xff) << 8) | (alpha_r & 0xff) |
263 src_x0 = (src_x0 & 0x1fff) | ((src_y0 & 0x1fff) << 16);
264 dst_x0 = (dst_x0 & 0x1fff) | ((dst_y0 & 0x1fff) << 16);
265 bottom = (bottom << 16) | right;
287 modded.
sx = area->
sx;
288 modded.sy = area->
sy;
289 modded.dx = area->
dx;
290 modded.dy = area->
dy;
291 modded.width = area->
width;
292 modded.height = area->
height;
299 vxres = info->
var.xres_virtual;
300 vyres = info->
var.yres_virtual;
302 if (!modded.width || !modded.height ||
303 modded.sx >= vxres || modded.sy >= vyres ||
304 modded.dx >= vxres || modded.dy >= vyres)
307 if (modded.sx + modded.width > vxres)
308 modded.width = vxres - modded.sx;
309 if (modded.dx + modded.width > vxres)
310 modded.width = vxres - modded.dx;
311 if (modded.sy + modded.height > vyres)
312 modded.height = vyres - modded.sy;
313 if (modded.dy + modded.height > vyres)
314 modded.height = vyres - modded.dy;
316 unifb_prim_copyarea(info, &modded);
324 static u_long get_line_length(
int xres_virtual,
int bpp)
328 length = xres_virtual *
bpp;
329 length = (length + 31) & ~31;
404 var->
green.offset = 0;
405 var->
green.length = 8;
406 var->
blue.offset = 0;
407 var->
blue.length = 8;
415 var->
green.offset = 5;
416 var->
green.length = 5;
417 var->
blue.offset = 10;
418 var->
blue.length = 5;
422 var->
red.offset = 11;
424 var->
green.offset = 5;
425 var->
green.length = 6;
426 var->
blue.offset = 0;
427 var->
blue.length = 5;
435 var->
green.offset = 8;
436 var->
green.length = 8;
437 var->
blue.offset = 16;
438 var->
blue.length = 8;
443 var->
red.offset = 16;
445 var->
green.offset = 8;
446 var->
green.length = 8;
447 var->
blue.offset = 0;
448 var->
blue.length = 8;
453 var->
red.msb_right = 0;
454 var->
green.msb_right = 0;
455 var->
blue.msb_right = 0;
456 var->
transp.msb_right = 0;
466 static int unifb_set_par(
struct fb_info *info)
468 int hTotal, vTotal, hSyncStart, hSyncEnd, vSyncStart, vSyncEnd;
471 #ifdef CONFIG_PUV3_PM
476 for (i = 0; i <= 10; i++) {
477 if (info->
var.xres == unifb_modes[i].
xres
478 && info->
var.yres == unifb_modes[i].
yres
492 if (clk_vga == ERR_PTR(-
ENOENT))
497 info->
fix = unifb_fix;
498 info->
var = unifb_default;
505 info->
fix.line_length = get_line_length(info->
var.xres_virtual,
506 info->
var.bits_per_pixel);
508 hSyncStart = info->
var.xres + info->
var.right_margin;
509 hSyncEnd = hSyncStart + info->
var.hsync_len;
510 hTotal = hSyncEnd + info->
var.left_margin;
512 vSyncStart = info->
var.yres + info->
var.lower_margin;
513 vSyncEnd = vSyncStart + info->
var.vsync_len;
514 vTotal = vSyncEnd + info->
var.upper_margin;
516 switch (info->
var.bits_per_pixel) {
545 | format | 0xC0000001,
UDE_CFG);
562 if (info->
var.grayscale) {
565 (red * 77 + green * 151 + blue * 28) >> 8;
568 #define CNVT_TOHW(val, width) ((((val)<<(width))+0x7FFF-(val))>>16)
569 switch (info->
fix.visual) {
593 v = (red << info->
var.red.offset) |
594 (green << info->
var.green.offset) |
595 (blue << info->
var.blue.offset) |
596 (transp << info->
var.transp.offset);
597 switch (info->
var.bits_per_pixel) {
627 if (var->
xoffset + info->
var.xres > info->
var.xres_virtual ||
647 if (offset + size > info->
fix.smem_len)
660 static struct fb_ops unifb_ops = {
663 .fb_check_var = unifb_check_var,
664 .fb_set_par = unifb_set_par,
665 .fb_setcolreg = unifb_setcolreg,
666 .fb_pan_display = unifb_pan_display,
667 .fb_fillrect = unifb_fillrect,
668 .fb_copyarea = unifb_copyarea,
669 .fb_imageblit = unifb_imageblit,
702 info->
fbops = &unifb_ops;
705 unifb_modes, 10, &unifb_modes[0], 16);
707 if (!retval || (retval == 4))
708 info->
var = unifb_default;
710 info->
fix = unifb_fix;
714 #ifdef FB_ACCEL_PUV3_UNIGFX
725 platform_set_drvdata(dev, info);
729 "fb%d: Virtual frame buffer device, using %dM of video memory\n",
742 struct fb_info *info = platform_get_drvdata(dev);
756 u32 *unifb_regs = dev->
dev.platform_data;
784 u32 *unifb_regs = dev->
dev.platform_data;
797 if (mesg.
event == dev->
dev.power.power_state.event)
800 switch (mesg.
event) {
813 dev->
dev.power.power_state = mesg;
818 #define unifb_resume NULL
819 #define unifb_suspend NULL
823 .probe = unifb_probe,
824 .remove = unifb_remove,
828 .name =
"PKUnity-v3-UNIGFX",
832 static int __init unifb_init(
void)
844 static void __exit unifb_exit(
void)