[PATCH] Framebuffer: Consolidated cleanup of pvr2fb.c for Sega Dreamcast

Adrian McMenamin
2007-07-29T00:40:03Z

[-- Attachment #1: Type: text/plain, Size: 798 bytes --]

Tony,

Second time attempt at this and a much better job I think.

This patch consolidates your earlier patch, some cleanup of the
documentation and, crucially, some better handling of the pvr2
registers based on more up to date information.

Testing shows that it seems to work pretty well at 16bpp, 24bpp and
32bpp - including proper rendering of the boot logo at all levels
(previously this was a bit broken even at 16bpp) and giving white
against black text. Really detailed testing (eg with X11) requires
support for the maple bus - which isn't (currently - next project
assuming this is okay) available, but I have no reason to think this
is broken.

Incidentally, substituing DIRECTCOLOR for TRUECOLOR appears to break the driver.

Signed-off by: Adrian McMenamin <adrian@mcmen.demon.co.uk>

[-- Attachment #2: DC-pvr2fb-clean.diff --]
[-- Type: text/x-patch, Size: 6132 bytes --]

diff --git a/Documentation/fb/pvr2fb.txt b/Documentation/fb/pvr2fb.txt
index 2bf6c23..3d08551 100644
--- a/Documentation/fb/pvr2fb.txt
+++ b/Documentation/fb/pvr2fb.txt
@@ -9,14 +9,14 @@ one found in the Dreamcast.
Advantages:

* It provides a nice large console (128 cols + 48 lines with 1024x768)
- without using tiny, unreadable fonts.
+ without using tiny, unreadable fonts (this size is NOT available on the
+ Dreamcast)
* You can run XF86_FBDev on top of /dev/fb0
* Most important: boot logo :-)

Disadvantages:

- * Driver is currently limited to the Dreamcast PowerVR 2 implementation
- at the time of this writing.
+ * Driver is largely untested on non-Dremcast systems.

Configuration
=============
@@ -29,11 +29,15 @@ Accepted options:
font:X - default font to use. All fonts are supported, including the
SUN12x22 font which is very nice at high resolutions.

-mode:X - default video mode. The following video modes are supported:
- 640x240-60, 640x480-60.
+mode:X - default video mode
+ The following video modes are supported:
+ 640x640-16@60, 640x480-24@60, 640x480-32@60. The Dreamcast
+ defaults to 640x480-16@60. At the time of writing the
+ 24bpp and 32bpp modes function poorly. Work to fix that is
+ ongoing

Note: the 640x240 mode is currently broken, and should not be
- used for any reason. It is only mentioned as a reference.
+ used for any reason. It is only mentioned here as a reference.

inverse - invert colors on screen (for LCD displays)

@@ -49,13 +53,20 @@ cable:X - cable type. This can be any of the following: vga, rgb, and
output:X - output type. This can be any of the following: pal, ntsc, and
vga. If none is specified, we guess.

+Video mode may also be specified in the form:
+
+ [xres]x[yres][-<bpp>][@refresh-rate]
+
+ eg 640x480-32@60
+
+
X11
===

-XF86_FBDev should work, in theory. At the time of this writing it is
-totally untested and may or may not even portray the beginnings of
-working. If you end up testing this, please let me know!
+XF86_FBDev has been shown to work on the Dremcast in the past - though not yet
+on any 2.6 series kernel.

--
Paul Mundt <lethal@linuxdc.org>
+Updated by Adrian McMenamin <adrian@mcmen.demon.co.uk>

diff --git a/drivers/video/pvr2fb.c b/drivers/video/pvr2fb.c
index 3ac32f3..264b6a6 100644
--- a/drivers/video/pvr2fb.c
+++ b/drivers/video/pvr2fb.c
@@ -94,6 +94,7 @@
#define DISP_DIWCONF (DISP_BASE + 0xe8)
#define DISP_DIWHSTRT (DISP_BASE + 0xec)
#define DISP_DIWVSTRT (DISP_BASE + 0xf0)
+#define DISP_PIXDEPTH (DISP_BASE + 0x108)

/* Pixel clocks, one for TV output, doubled for VGA output */
#define TV_CLK 74239
@@ -143,6 +144,7 @@ static struct pvr2fb_par {
unsigned char is_lowres; /* Is horizontal pixel-doubling enabled? */

unsigned long mmio_base; /* MMIO base */
+ u32 palette[16];
} *currentpar;

static struct fb_info *fb_info;
@@ -320,7 +322,7 @@ static int pvr2fb_setcolreg(unsigned int regno, unsigned int red,

if (regno > info->cmap.len)
return 1;
-
+
/*
* We only support the hardware palette for 16 and 32bpp. It's also
* expected that the palette format has been set by the time we get
@@ -333,24 +335,25 @@ static int pvr2fb_setcolreg(unsigned int regno, unsigned int red,
((blue & 0xf800) >> 11);

pvr2fb_set_pal_entry(par, regno, tmp);
- ((u16*)(info->pseudo_palette))[regno] = tmp;
break;
case 24: /* RGB 888 */
red >>= 8; green >>= 8; blue >>= 8;
- ((u32*)(info->pseudo_palette))[regno] = (red << 16) | (green << 8) | blue;
+ tmp = (red << 16) | (green << 8) | blue;
break;
case 32: /* ARGB 8888 */
red >>= 8; green >>= 8; blue >>= 8;
tmp = (transp << 24) | (red << 16) | (green << 8) | blue;

pvr2fb_set_pal_entry(par, regno, tmp);
- ((u32*)(info->pseudo_palette))[regno] = tmp;
break;
default:
pr_debug("Invalid bit depth %d?!?\n", info->var.bits_per_pixel);
return 1;
}

+ if (regno < 16)
+ ((u32*)(info->pseudo_palette))[regno] = tmp;
+
return 0;
}

@@ -598,6 +601,7 @@ static void pvr2_init_display(struct fb_info *info)

/* bits per pixel */
fb_writel(fb_readl(DISP_DIWMODE) | (--bytesperpixel << 2), DISP_DIWMODE);
+ fb_writel(bytesperpixel << 2, DISP_PIXDEPTH);

/* video enable, color sync, interlace,
* hsync and vsync polarity (currently unused) */
@@ -789,7 +793,7 @@ static int __devinit pvr2fb_common_init(void)
fb_info->fbops = &pvr2fb_ops;
fb_info->fix = pvr2_fix;
fb_info->par = currentpar;
- fb_info->pseudo_palette = (void *)(fb_info->par + 1);
+ fb_info->pseudo_palette = currentpar->palette;
fb_info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;

if (video_output == VO_VGA)
@@ -806,6 +810,8 @@ static int __devinit pvr2fb_common_init(void)

if (register_framebuffer(fb_info) < 0)
goto out_err;
+ /*Must write PIXDEPTH to register before anything is displayed - so force init */
+ pvr2_init_display(fb_info);

modememused = get_line_length(fb_info->var.xres_virtual,
fb_info->var.bits_per_pixel);
@@ -1081,14 +1087,15 @@ static int __init pvr2fb_init(void)
#endif
size = sizeof(struct fb_info) + sizeof(struct pvr2fb_par) + 16 * sizeof(u32);

- fb_info = kzalloc(size, GFP_KERNEL);
+ fb_info = framebuffer_alloc(sizeof(struct pvr2fb_par), NULL);
+
if (!fb_info) {
printk(KERN_ERR "Failed to allocate memory for fb_info\n");
return -ENOMEM;
}

- currentpar = (struct pvr2fb_par *)(fb_info + 1);
+ currentpar = fb_info->par;

for (i = 0; i < ARRAY_SIZE(board_driver); i++) {
struct pvr2_board *pvr_board = board_driver + i;
@@ -1101,7 +1108,7 @@ static int __init pvr2fb_init(void)
if (ret != 0) {
printk(KERN_ERR "pvr2fb: Failed init of %s device\n",
pvr_board->name);
- kfree(fb_info);
+ framebuffer_release(fb_info);
break;
}
}
@@ -1125,7 +1132,7 @@ static void __exit pvr2fb_exit(void)
#endif

unregister_framebuffer(fb_info);
- kfree(fb_info);
+ framebuffer_release(fb_info);
}

module_init(pvr2fb_init);