This adds support for a framebuffer on the "Xenos" graphics chip used in the Xbox 360 machine. It requires a pre-initialized framebuffer. The major problem is that the graphics chip only supports a 'tiled' mode, thus this patch also uses some serious ugly patches to allow the framebuffer console to handle this. So this patch is given just for completeness, to have a working console output, and of course not meant for inclusion into the kernel. This patch can probably be rewritten using the deferred io support in a much nicer way. Signed-off-by: Felix Domke --- drivers/video/Kconfig | 9 + drivers/video/Makefile | 1 drivers/video/cfbimgblt.c | 23 +-- drivers/video/xenonfb.c | 337 ++++++++++++++++++++++++++++++++++++++++++++++ include/linux/fb.h | 12 + 5 files changed, 373 insertions(+), 9 deletions(-) Index: linux-2.6.20/drivers/video/Kconfig =================================================================== --- linux-2.6.20.orig/drivers/video/Kconfig 2007-03-07 19:01:12.000000000 +0100 +++ linux-2.6.20/drivers/video/Kconfig 2007-03-07 19:01:23.000000000 +0100 @@ -568,6 +568,15 @@ help This is the frame buffer device driver for the Intel-based Macintosh +config FB_XENON + bool "Xbox 360 Framebuffer Support" + depends on (FB = y) && PPC + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + help + This is the frame buffer device driver for the Microsoft Xbox 360. + config FB_HGA tristate "Hercules mono graphics support" depends on FB && X86 Index: linux-2.6.20/drivers/video/Makefile =================================================================== --- linux-2.6.20.orig/drivers/video/Makefile 2007-03-07 19:01:12.000000000 +0100 +++ linux-2.6.20/drivers/video/Makefile 2007-03-07 19:01:23.000000000 +0100 @@ -104,6 +104,7 @@ # Platform or fallback drivers go here obj-$(CONFIG_FB_VESA) += vesafb.o obj-$(CONFIG_FB_IMAC) += imacfb.o +obj-$(CONFIG_FB_XENON) += xenonfb.o obj-$(CONFIG_FB_VGA16) += vga16fb.o vgastate.o obj-$(CONFIG_FB_OF) += offb.o Index: linux-2.6.20/drivers/video/cfbimgblt.c =================================================================== --- linux-2.6.20.orig/drivers/video/cfbimgblt.c 2007-03-07 19:01:12.000000000 +0100 +++ linux-2.6.20/drivers/video/cfbimgblt.c 2007-03-07 19:01:23.000000000 +0100 @@ -72,8 +72,13 @@ 0x00000000, 0xffffffff }; -#define FB_WRITEL fb_writel -#define FB_READL fb_readl +#if 0 +#define FB_WRITEL(p,b,addr) fb_writel(b,addr) +#define FB_READL(p,addr) fb_readl(addr) +#else +#define FB_READL(p,addr) fb_readl(xenon_convert(p, addr)) +#define FB_WRITEL(p,b,addr) fb_writel(b, xenon_convert(p, addr)) +#endif static inline void color_imageblit(const struct fb_image *image, struct fb_info *p, u8 __iomem *dst1, @@ -97,7 +102,7 @@ if (start_index) { u32 start_mask = ~(FB_SHIFT_HIGH(~(u32)0, start_index)); - val = FB_READL(dst) & start_mask; + val = FB_READL(p, dst) & start_mask; shift = start_index; } while (n--) { @@ -109,7 +114,7 @@ color <<= FB_LEFT_POS(bpp); val |= FB_SHIFT_HIGH(color, shift); if (shift >= null_bits) { - FB_WRITEL(val, dst++); + FB_WRITEL(p, val, dst++); val = (shift == null_bits) ? 0 : FB_SHIFT_LOW(color, 32 - shift); @@ -121,7 +126,7 @@ if (shift) { u32 end_mask = FB_SHIFT_HIGH(~(u32)0, shift); - FB_WRITEL((FB_READL(dst) & end_mask) | val, dst); + FB_WRITEL(p, (FB_READL(p, dst) & end_mask) | val, dst); } dst1 += p->fix.line_length; if (pitch_index) { @@ -162,7 +167,7 @@ /* write leading bits */ if (start_index) { u32 start_mask = ~(FB_SHIFT_HIGH(~(u32)0,start_index)); - val = FB_READL(dst) & start_mask; + val = FB_READL(p, dst) & start_mask; shift = start_index; } @@ -173,7 +178,7 @@ /* Did the bitshift spill bits to the next long? */ if (shift >= null_bits) { - FB_WRITEL(val, dst++); + FB_WRITEL(p, val, dst++); val = (shift == null_bits) ? 0 : FB_SHIFT_LOW(color,32 - shift); } @@ -186,7 +191,7 @@ if (shift) { u32 end_mask = FB_SHIFT_HIGH(~(u32)0, shift); - FB_WRITEL((FB_READL(dst) & end_mask) | val, dst); + FB_WRITEL(p, (FB_READL(p, dst) & end_mask) | val, dst); } dst1 += pitch; @@ -251,7 +256,7 @@ for (j = k; j--; ) { shift -= ppw; end_mask = tab[(*src >> shift) & bit_mask]; - FB_WRITEL((end_mask & eorx)^bgx, dst++); + FB_WRITEL(p, (end_mask & eorx)^bgx, dst++); if (!shift) { shift = 8; src++; } } dst1 += p->fix.line_length; Index: linux-2.6.20/include/linux/fb.h =================================================================== --- linux-2.6.20.orig/include/linux/fb.h 2007-03-07 19:01:12.000000000 +0100 +++ linux-2.6.20/include/linux/fb.h 2007-03-07 19:01:23.000000000 +0100 @@ -907,6 +907,18 @@ } } +static inline int *xenon_convert(struct fb_info *p, int *addr) +{ + int index = ((char*)addr) - ((char*)p->screen_base); + int y = index / (p->fix.line_length); + int x = index % (p->fix.line_length)/4; + unsigned int base = ((((y & ~31)*p->var.xres) + (x & ~31)*32 ) + + (((x&3) + ((y&1)<<2) + ((x&28)<<1) + ((y&30)<<5)) ^ ((y&8)<<2))) * 4; + + return (int*)(((char*)p->screen_base)+base); +} + + /* drivers/video/fbsysfs.c */ extern struct fb_info *framebuffer_alloc(size_t size, struct device *dev); extern void framebuffer_release(struct fb_info *info); Index: linux-2.6.20/drivers/video/xenonfb.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.6.20/drivers/video/xenonfb.c 2007-03-07 19:01:23.000000000 +0100 @@ -0,0 +1,337 @@ +/* + * framebuffer driver for Microsoft Xbox 360 + * + * (c) 2006 ... + * Original vesafb driver written by Gerd Knorr + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include