summaryrefslogtreecommitdiff
path: root/drivers/video/pm3fb.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/video/pm3fb.c')
-rw-r--r--drivers/video/pm3fb.c571
1 files changed, 376 insertions, 195 deletions
diff --git a/drivers/video/pm3fb.c b/drivers/video/pm3fb.c
index c77a1a1fd46b..5b3f54c0918e 100644
--- a/drivers/video/pm3fb.c
+++ b/drivers/video/pm3fb.c
@@ -52,11 +52,6 @@
static char *mode_option __devinitdata;
/*
- * If your driver supports multiple boards, you should make the
- * below data types arrays, or allocate them dynamically (using kmalloc()).
- */
-
-/*
* This structure defines the hardware state of the graphics card. Normally
* you place this in a header file in linux/include/video. This file usually
* also includes register information. That allows other driver subsystems
@@ -67,7 +62,7 @@ struct pm3_par {
unsigned char __iomem *v_regs;/* virtual address of p_regs */
u32 video; /* video flags before blanking */
u32 base; /* screen base (xoffset+yoffset) in 128 bits unit */
- u32 palette[16];
+ u32 palette[16];
};
/*
@@ -82,7 +77,7 @@ static struct fb_fix_screeninfo pm3fb_fix __devinitdata = {
.xpanstep = 1,
.ypanstep = 1,
.ywrapstep = 0,
- .accel = FB_ACCEL_NONE,
+ .accel = FB_ACCEL_3DLABS_PERMEDIA3,
};
/*
@@ -104,36 +99,28 @@ static inline void PM3_WAIT(struct pm3_par *par, u32 n)
while (PM3_READ_REG(par, PM3InFIFOSpace) < n);
}
-static inline void PM3_SLOW_WRITE_REG(struct pm3_par *par, s32 off, u32 v)
-{
- if (par->v_regs) {
- mb();
- PM3_WAIT(par, 1);
- wmb();
- PM3_WRITE_REG(par, off, v);
- }
-}
-
-static inline void PM3_SET_INDEX(struct pm3_par *par, unsigned index)
-{
- PM3_SLOW_WRITE_REG(par, PM3RD_IndexHigh, (index >> 8) & 0xff);
- PM3_SLOW_WRITE_REG(par, PM3RD_IndexLow, index & 0xff);
-}
-
static inline void PM3_WRITE_DAC_REG(struct pm3_par *par, unsigned r, u8 v)
{
- PM3_SET_INDEX(par, r);
+ PM3_WAIT(par, 3);
+ PM3_WRITE_REG(par, PM3RD_IndexHigh, (r >> 8) & 0xff);
+ PM3_WRITE_REG(par, PM3RD_IndexLow, r & 0xff);
wmb();
PM3_WRITE_REG(par, PM3RD_IndexedData, v);
+ wmb();
}
static inline void pm3fb_set_color(struct pm3_par *par, unsigned char regno,
unsigned char r, unsigned char g, unsigned char b)
{
- PM3_SLOW_WRITE_REG(par, PM3RD_PaletteWriteAddress, regno);
- PM3_SLOW_WRITE_REG(par, PM3RD_PaletteData, r);
- PM3_SLOW_WRITE_REG(par, PM3RD_PaletteData, g);
- PM3_SLOW_WRITE_REG(par, PM3RD_PaletteData, b);
+ PM3_WAIT(par, 4);
+ PM3_WRITE_REG(par, PM3RD_PaletteWriteAddress, regno);
+ wmb();
+ PM3_WRITE_REG(par, PM3RD_PaletteData, r);
+ wmb();
+ PM3_WRITE_REG(par, PM3RD_PaletteData, g);
+ wmb();
+ PM3_WRITE_REG(par, PM3RD_PaletteData, b);
+ wmb();
}
static void pm3fb_clear_colormap(struct pm3_par *par,
@@ -141,7 +128,7 @@ static void pm3fb_clear_colormap(struct pm3_par *par,
{
int i;
- for (i = 0; i < 256 ; i++) /* fill color map with white */
+ for (i = 0; i < 256 ; i++)
pm3fb_set_color(par, i, r, g, b);
}
@@ -175,22 +162,261 @@ static void pm3fb_calculate_clock(unsigned long reqclock,
}
}
-static inline int pm3fb_shift_bpp(unsigned long depth, int v)
+static inline int pm3fb_depth(const struct fb_var_screeninfo *var)
+{
+ if ( var->bits_per_pixel == 16 )
+ return var->red.length + var->green.length
+ + var->blue.length;
+
+ return var->bits_per_pixel;
+}
+
+static inline int pm3fb_shift_bpp(unsigned bpp, int v)
{
- switch (depth) {
+ switch (bpp) {
case 8:
return (v >> 4);
- case 12:
- case 15:
case 16:
return (v >> 3);
case 32:
return (v >> 2);
}
- DPRINTK("Unsupported depth %ld\n", depth);
+ DPRINTK("Unsupported depth %u\n", bpp);
+ return 0;
+}
+
+/* acceleration */
+static int pm3fb_sync(struct fb_info *info)
+{
+ struct pm3_par *par = info->par;
+
+ PM3_WAIT(par, 2);
+ PM3_WRITE_REG(par, PM3FilterMode, PM3FilterModeSync);
+ PM3_WRITE_REG(par, PM3Sync, 0);
+ mb();
+ do {
+ while ((PM3_READ_REG(par, PM3OutFIFOWords)) == 0);
+ rmb();
+ } while ((PM3_READ_REG(par, PM3OutputFifo)) != PM3Sync_Tag);
+
return 0;
}
+static void pm3fb_init_engine(struct fb_info *info)
+{
+ struct pm3_par *par = info->par;
+ const u32 width = (info->var.xres_virtual + 7) & ~7;
+
+ PM3_WAIT(par, 50);
+ PM3_WRITE_REG(par, PM3FilterMode, PM3FilterModeSync);
+ PM3_WRITE_REG(par, PM3StatisticMode, 0x0);
+ PM3_WRITE_REG(par, PM3DeltaMode, 0x0);
+ PM3_WRITE_REG(par, PM3RasterizerMode, 0x0);
+ PM3_WRITE_REG(par, PM3ScissorMode, 0x0);
+ PM3_WRITE_REG(par, PM3LineStippleMode, 0x0);
+ PM3_WRITE_REG(par, PM3AreaStippleMode, 0x0);
+ PM3_WRITE_REG(par, PM3GIDMode, 0x0);
+ PM3_WRITE_REG(par, PM3DepthMode, 0x0);
+ PM3_WRITE_REG(par, PM3StencilMode, 0x0);
+ PM3_WRITE_REG(par, PM3StencilData, 0x0);
+ PM3_WRITE_REG(par, PM3ColorDDAMode, 0x0);
+ PM3_WRITE_REG(par, PM3TextureCoordMode, 0x0);
+ PM3_WRITE_REG(par, PM3TextureIndexMode0, 0x0);
+ PM3_WRITE_REG(par, PM3TextureIndexMode1, 0x0);
+ PM3_WRITE_REG(par, PM3TextureReadMode, 0x0);
+ PM3_WRITE_REG(par, PM3LUTMode, 0x0);
+ PM3_WRITE_REG(par, PM3TextureFilterMode, 0x0);
+ PM3_WRITE_REG(par, PM3TextureCompositeMode, 0x0);
+ PM3_WRITE_REG(par, PM3TextureApplicationMode, 0x0);
+ PM3_WRITE_REG(par, PM3TextureCompositeColorMode1, 0x0);
+ PM3_WRITE_REG(par, PM3TextureCompositeAlphaMode1, 0x0);
+ PM3_WRITE_REG(par, PM3TextureCompositeColorMode0, 0x0);
+ PM3_WRITE_REG(par, PM3TextureCompositeAlphaMode0, 0x0);
+ PM3_WRITE_REG(par, PM3FogMode, 0x0);
+ PM3_WRITE_REG(par, PM3ChromaTestMode, 0x0);
+ PM3_WRITE_REG(par, PM3AlphaTestMode, 0x0);
+ PM3_WRITE_REG(par, PM3AntialiasMode, 0x0);
+ PM3_WRITE_REG(par, PM3YUVMode, 0x0);
+ PM3_WRITE_REG(par, PM3AlphaBlendColorMode, 0x0);
+ PM3_WRITE_REG(par, PM3AlphaBlendAlphaMode, 0x0);
+ PM3_WRITE_REG(par, PM3DitherMode, 0x0);
+ PM3_WRITE_REG(par, PM3LogicalOpMode, 0x0);
+ PM3_WRITE_REG(par, PM3RouterMode, 0x0);
+ PM3_WRITE_REG(par, PM3Window, 0x0);
+
+ PM3_WRITE_REG(par, PM3Config2D, 0x0);
+
+ PM3_WRITE_REG(par, PM3SpanColorMask, 0xffffffff);
+
+ PM3_WRITE_REG(par, PM3XBias, 0x0);
+ PM3_WRITE_REG(par, PM3YBias, 0x0);
+ PM3_WRITE_REG(par, PM3DeltaControl, 0x0);
+
+ PM3_WRITE_REG(par, PM3BitMaskPattern, 0xffffffff);
+
+ PM3_WRITE_REG(par, PM3FBDestReadEnables,
+ PM3FBDestReadEnables_E(0xff) |
+ PM3FBDestReadEnables_R(0xff) |
+ PM3FBDestReadEnables_ReferenceAlpha(0xff));
+ PM3_WRITE_REG(par, PM3FBDestReadBufferAddr0, 0x0);
+ PM3_WRITE_REG(par, PM3FBDestReadBufferOffset0, 0x0);
+ PM3_WRITE_REG(par, PM3FBDestReadBufferWidth0,
+ PM3FBDestReadBufferWidth_Width(width));
+
+ PM3_WRITE_REG(par, PM3FBDestReadMode,
+ PM3FBDestReadMode_ReadEnable |
+ PM3FBDestReadMode_Enable0);
+ PM3_WRITE_REG(par, PM3FBSourceReadBufferAddr, 0x0);
+ PM3_WRITE_REG(par, PM3FBSourceReadBufferOffset, 0x0);
+ PM3_WRITE_REG(par, PM3FBSourceReadBufferWidth,
+ PM3FBSourceReadBufferWidth_Width(width));
+ PM3_WRITE_REG(par, PM3FBSourceReadMode,
+ PM3FBSourceReadMode_Blocking |
+ PM3FBSourceReadMode_ReadEnable);
+
+ PM3_WAIT(par, 2);
+ {
+ unsigned long rm = 1;
+ switch (info->var.bits_per_pixel) {
+ case 8:
+ PM3_WRITE_REG(par, PM3PixelSize,
+ PM3PixelSize_GLOBAL_8BIT);
+ break;
+ case 16:
+ PM3_WRITE_REG(par, PM3PixelSize,
+ PM3PixelSize_GLOBAL_16BIT);
+ break;
+ case 32:
+ PM3_WRITE_REG(par, PM3PixelSize,
+ PM3PixelSize_GLOBAL_32BIT);
+ break;
+ default:
+ DPRINTK(1, "Unsupported depth %d\n",
+ info->var.bits_per_pixel);
+ break;
+ }
+ PM3_WRITE_REG(par, PM3RasterizerMode, rm);
+ }
+
+ PM3_WAIT(par, 20);
+ PM3_WRITE_REG(par, PM3FBSoftwareWriteMask, 0xffffffff);
+ PM3_WRITE_REG(par, PM3FBHardwareWriteMask, 0xffffffff);
+ PM3_WRITE_REG(par, PM3FBWriteMode,
+ PM3FBWriteMode_WriteEnable |
+ PM3FBWriteMode_OpaqueSpan |
+ PM3FBWriteMode_Enable0);
+ PM3_WRITE_REG(par, PM3FBWriteBufferAddr0, 0x0);
+ PM3_WRITE_REG(par, PM3FBWriteBufferOffset0, 0x0);
+ PM3_WRITE_REG(par, PM3FBWriteBufferWidth0,
+ PM3FBWriteBufferWidth_Width(width));
+
+ PM3_WRITE_REG(par, PM3SizeOfFramebuffer, 0x0);
+ {
+ /* size in lines of FB */
+ unsigned long sofb = info->screen_size /
+ info->fix.line_length;
+ if (sofb > 4095)
+ PM3_WRITE_REG(par, PM3SizeOfFramebuffer, 4095);
+ else
+ PM3_WRITE_REG(par, PM3SizeOfFramebuffer, sofb);
+
+ switch (info->var.bits_per_pixel) {
+ case 8:
+ PM3_WRITE_REG(par, PM3DitherMode,
+ (1 << 10) | (2 << 3));
+ break;
+ case 16:
+ PM3_WRITE_REG(par, PM3DitherMode,
+ (1 << 10) | (1 << 3));
+ break;
+ case 32:
+ PM3_WRITE_REG(par, PM3DitherMode,
+ (1 << 10) | (0 << 3));
+ break;
+ default:
+ DPRINTK(1, "Unsupported depth %d\n",
+ info->current_par->depth);
+ break;
+ }
+ }
+
+ PM3_WRITE_REG(par, PM3dXDom, 0x0);
+ PM3_WRITE_REG(par, PM3dXSub, 0x0);
+ PM3_WRITE_REG(par, PM3dY, (1 << 16));
+ PM3_WRITE_REG(par, PM3StartXDom, 0x0);
+ PM3_WRITE_REG(par, PM3StartXSub, 0x0);
+ PM3_WRITE_REG(par, PM3StartY, 0x0);
+ PM3_WRITE_REG(par, PM3Count, 0x0);
+
+/* Disable LocalBuffer. better safe than sorry */
+ PM3_WRITE_REG(par, PM3LBDestReadMode, 0x0);
+ PM3_WRITE_REG(par, PM3LBDestReadEnables, 0x0);
+ PM3_WRITE_REG(par, PM3LBSourceReadMode, 0x0);
+ PM3_WRITE_REG(par, PM3LBWriteMode, 0x0);
+
+ pm3fb_sync(info);
+}
+
+static void pm3fb_fillrect (struct fb_info *info,
+ const struct fb_fillrect *region)
+{
+ struct pm3_par *par = info->par;
+ struct fb_fillrect modded;
+ int vxres, vyres;
+ u32 color = (info->fix.visual == FB_VISUAL_TRUECOLOR) ?
+ ((u32*)info->pseudo_palette)[region->color] : region->color;
+
+ if (info->state != FBINFO_STATE_RUNNING)
+ return;
+ if ((info->flags & FBINFO_HWACCEL_DISABLED) ||
+ region->rop != ROP_COPY ) {
+ cfb_fillrect(info, region);
+ return;
+ }
+
+ vxres = info->var.xres_virtual;
+ vyres = info->var.yres_virtual;
+
+ memcpy(&modded, region, sizeof(struct fb_fillrect));
+
+ if(!modded.width || !modded.height ||
+ modded.dx >= vxres || modded.dy >= vyres)
+ return;
+
+ if(modded.dx + modded.width > vxres)
+ modded.width = vxres - modded.dx;
+ if(modded.dy + modded.height > vyres)
+ modded.height = vyres - modded.dy;
+
+ if(info->var.bits_per_pixel == 8)
+ color |= color << 8;
+ if(info->var.bits_per_pixel <= 16)
+ color |= color << 16;
+
+ PM3_WAIT(par, 4);
+
+ PM3_WRITE_REG(par, PM3Config2D,
+ PM3Config2D_UseConstantSource |
+ PM3Config2D_ForegroundROPEnable |
+ (PM3Config2D_ForegroundROP(0x3)) | /* Ox3 is GXcopy */
+ PM3Config2D_FBWriteEnable);
+
+ PM3_WRITE_REG(par, PM3ForegroundColor, color);
+
+ PM3_WRITE_REG(par, PM3RectanglePosition,
+ (PM3RectanglePosition_XOffset(modded.dx)) |
+ (PM3RectanglePosition_YOffset(modded.dy)));
+
+ PM3_WRITE_REG(par, PM3Render2D,
+ PM3Render2D_XPositive |
+ PM3Render2D_YPositive |
+ PM3Render2D_Operation_Normal |
+ PM3Render2D_SpanOperation |
+ (PM3Render2D_Width(modded.width)) |
+ (PM3Render2D_Height(modded.height)));
+}
+/* end of acceleration functions */
+
/* write the mode to registers */
static void pm3fb_write_mode(struct fb_info *info)
{
@@ -206,56 +432,50 @@ static void pm3fb_write_mode(struct fb_info *info)
const u32 vbend = vsend + info->var.upper_margin;
const u32 vtotal = info->var.yres + vbend;
const u32 width = (info->var.xres_virtual + 7) & ~7;
-
- PM3_SLOW_WRITE_REG(par, PM3MemBypassWriteMask, 0xffffffff);
- PM3_SLOW_WRITE_REG(par, PM3Aperture0, 0x00000000);
- PM3_SLOW_WRITE_REG(par, PM3Aperture1, 0x00000000);
- PM3_SLOW_WRITE_REG(par, PM3FIFODis, 0x00000007);
-
- PM3_SLOW_WRITE_REG(par, PM3HTotal,
- pm3fb_shift_bpp(info->var.bits_per_pixel,
- htotal - 1));
- PM3_SLOW_WRITE_REG(par, PM3HsEnd,
- pm3fb_shift_bpp(info->var.bits_per_pixel,
- hsend));
- PM3_SLOW_WRITE_REG(par, PM3HsStart,
- pm3fb_shift_bpp(info->var.bits_per_pixel,
- hsstart));
- PM3_SLOW_WRITE_REG(par, PM3HbEnd,
- pm3fb_shift_bpp(info->var.bits_per_pixel,
- hbend));
- PM3_SLOW_WRITE_REG(par, PM3HgEnd,
- pm3fb_shift_bpp(info->var.bits_per_pixel,
- hbend));
- PM3_SLOW_WRITE_REG(par, PM3ScreenStride,
- pm3fb_shift_bpp(info->var.bits_per_pixel,
- width));
- PM3_SLOW_WRITE_REG(par, PM3VTotal, vtotal - 1);
- PM3_SLOW_WRITE_REG(par, PM3VsEnd, vsend - 1);
- PM3_SLOW_WRITE_REG(par, PM3VsStart, vsstart - 1);
- PM3_SLOW_WRITE_REG(par, PM3VbEnd, vbend);
-
- switch (info->var.bits_per_pixel) {
+ const unsigned bpp = info->var.bits_per_pixel;
+
+ PM3_WAIT(par, 20);
+ PM3_WRITE_REG(par, PM3MemBypassWriteMask, 0xffffffff);
+ PM3_WRITE_REG(par, PM3Aperture0, 0x00000000);
+ PM3_WRITE_REG(par, PM3Aperture1, 0x00000000);
+ PM3_WRITE_REG(par, PM3FIFODis, 0x00000007);
+
+ PM3_WRITE_REG(par, PM3HTotal,
+ pm3fb_shift_bpp(bpp, htotal - 1));
+ PM3_WRITE_REG(par, PM3HsEnd,
+ pm3fb_shift_bpp(bpp, hsend));
+ PM3_WRITE_REG(par, PM3HsStart,
+ pm3fb_shift_bpp(bpp, hsstart));
+ PM3_WRITE_REG(par, PM3HbEnd,
+ pm3fb_shift_bpp(bpp, hbend));
+ PM3_WRITE_REG(par, PM3HgEnd,
+ pm3fb_shift_bpp(bpp, hbend));
+ PM3_WRITE_REG(par, PM3ScreenStride,
+ pm3fb_shift_bpp(bpp, width));
+ PM3_WRITE_REG(par, PM3VTotal, vtotal - 1);
+ PM3_WRITE_REG(par, PM3VsEnd, vsend - 1);
+ PM3_WRITE_REG(par, PM3VsStart, vsstart - 1);
+ PM3_WRITE_REG(par, PM3VbEnd, vbend);
+
+ switch (bpp) {
case 8:
- PM3_SLOW_WRITE_REG(par, PM3ByAperture1Mode,
+ PM3_WRITE_REG(par, PM3ByAperture1Mode,
PM3ByApertureMode_PIXELSIZE_8BIT);
- PM3_SLOW_WRITE_REG(par, PM3ByAperture2Mode,
+ PM3_WRITE_REG(par, PM3ByAperture2Mode,
PM3ByApertureMode_PIXELSIZE_8BIT);
break;
- case 12:
- case 15:
case 16:
#ifndef __BIG_ENDIAN
- PM3_SLOW_WRITE_REG(par, PM3ByAperture1Mode,
+ PM3_WRITE_REG(par, PM3ByAperture1Mode,
PM3ByApertureMode_PIXELSIZE_16BIT);
- PM3_SLOW_WRITE_REG(par, PM3ByAperture2Mode,
+ PM3_WRITE_REG(par, PM3ByAperture2Mode,
PM3ByApertureMode_PIXELSIZE_16BIT);
#else
- PM3_SLOW_WRITE_REG(par, PM3ByAperture1Mode,
+ PM3_WRITE_REG(par, PM3ByAperture1Mode,
PM3ByApertureMode_PIXELSIZE_16BIT |
PM3ByApertureMode_BYTESWAP_BADC);
- PM3_SLOW_WRITE_REG(par, PM3ByAperture2Mode,
+ PM3_WRITE_REG(par, PM3ByAperture2Mode,
PM3ByApertureMode_PIXELSIZE_16BIT |
PM3ByApertureMode_BYTESWAP_BADC);
#endif /* ! __BIG_ENDIAN */
@@ -263,23 +483,22 @@ static void pm3fb_write_mode(struct fb_info *info)
case 32:
#ifndef __BIG_ENDIAN
- PM3_SLOW_WRITE_REG(par, PM3ByAperture1Mode,
+ PM3_WRITE_REG(par, PM3ByAperture1Mode,
PM3ByApertureMode_PIXELSIZE_32BIT);
- PM3_SLOW_WRITE_REG(par, PM3ByAperture2Mode,
+ PM3_WRITE_REG(par, PM3ByAperture2Mode,
PM3ByApertureMode_PIXELSIZE_32BIT);
#else
- PM3_SLOW_WRITE_REG(par, PM3ByAperture1Mode,
+ PM3_WRITE_REG(par, PM3ByAperture1Mode,
PM3ByApertureMode_PIXELSIZE_32BIT |
PM3ByApertureMode_BYTESWAP_DCBA);
- PM3_SLOW_WRITE_REG(par, PM3ByAperture2Mode,
+ PM3_WRITE_REG(par, PM3ByAperture2Mode,
PM3ByApertureMode_PIXELSIZE_32BIT |
PM3ByApertureMode_BYTESWAP_DCBA);
#endif /* ! __BIG_ENDIAN */
break;
default:
- DPRINTK("Unsupported depth %d\n",
- info->var.bits_per_pixel);
+ DPRINTK("Unsupported depth %d\n", bpp);
break;
}
@@ -296,14 +515,15 @@ static void pm3fb_write_mode(struct fb_info *info)
PM3VideoControl_VSYNC_MASK);
video |= PM3VideoControl_HSYNC_ACTIVE_HIGH |
PM3VideoControl_VSYNC_ACTIVE_HIGH;
- PM3_SLOW_WRITE_REG(par, PM3VideoControl, video);
+ PM3_WRITE_REG(par, PM3VideoControl, video);
}
- PM3_SLOW_WRITE_REG(par, PM3VClkCtl,
+ PM3_WRITE_REG(par, PM3VClkCtl,
(PM3_READ_REG(par, PM3VClkCtl) & 0xFFFFFFFC));
- PM3_SLOW_WRITE_REG(par, PM3ScreenBase, par->base);
- PM3_SLOW_WRITE_REG(par, PM3ChipConfig,
+ PM3_WRITE_REG(par, PM3ScreenBase, par->base);
+ PM3_WRITE_REG(par, PM3ChipConfig,
(PM3_READ_REG(par, PM3ChipConfig) & 0xFFFFFFFD));
+ wmb();
{
unsigned char uninitialized_var(m); /* ClkPreScale */
unsigned char uninitialized_var(n); /* ClkFeedBackScale */
@@ -337,7 +557,7 @@ static void pm3fb_write_mode(struct fb_info *info)
PM3_WRITE_DAC_REG(par, PM3RD_DACControl, 0x00);
- switch (info->var.bits_per_pixel) {
+ switch (pm3fb_depth(&info->var)) {
case 8:
PM3_WRITE_DAC_REG(par, PM3RD_PixelSize,
PM3RD_PixelSize_8_BIT_PIXELS);
@@ -392,58 +612,43 @@ static void pm3fb_write_mode(struct fb_info *info)
/*
* hardware independent functions
*/
-int pm3fb_init(void);
-int pm3fb_setup(char*);
-
static int pm3fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
{
u32 lpitch;
+ unsigned bpp = var->red.length + var->green.length
+ + var->blue.length + var->transp.length;
- var->transp.offset = 0;
- var->transp.length = 0;
- switch(var->bits_per_pixel) {
- case 8:
- var->red.length = var->green.length = var->blue.length = 8;
- var->red.offset = var->green.offset = var->blue.offset = 0;
- break;
- case 12:
- var->red.offset = 8;
- var->red.length = 4;
- var->green.offset = 4;
- var->green.length = 4;
- var->blue.offset = 0;
- var->blue.length = 4;
- var->transp.offset = 12;
- var->transp.length = 4;
- case 15:
- var->red.offset = 10;
- var->red.length = 5;
- var->green.offset = 5;
- var->green.length = 5;
- var->blue.offset = 0;
- var->blue.length = 5;
- var->transp.offset = 15;
- var->transp.length = 1;
- break;
- case 16:
- var->red.offset = 11;
- var->red.length = 5;
- var->green.offset = 5;
- var->green.length = 6;
- var->blue.offset = 0;
- var->blue.length = 5;
- break;
- case 32:
- var->transp.offset = 24;
- var->transp.length = 8;
- var->red.offset = 16;
- var->green.offset = 8;
- var->blue.offset = 0;
- var->red.length = var->green.length = var->blue.length = 8;
- break;
- default:
- DPRINTK("depth not supported: %u\n", var->bits_per_pixel);
- return -EINVAL;
+ if ( bpp != var->bits_per_pixel ) {
+ /* set predefined mode for bits_per_pixel settings */
+
+ switch(var->bits_per_pixel) {
+ case 8:
+ var->red.length = var->green.length = var->blue.length = 8;
+ var->red.offset = var->green.offset = var->blue.offset = 0;
+ var->transp.offset = 0;
+ var->transp.length = 0;
+ break;
+ case 16:
+ var->red.length = var->blue.length = 5;
+ var->green.length = 6;
+ var->transp.length = 0;
+ break;
+ case 32:
+ var->red.length = var->green.length = var->blue.length = 8;
+ var->transp.length = 8;
+ break;
+ default:
+ DPRINTK("depth not supported: %u\n", var->bits_per_pixel);
+ return -EINVAL;
+ }
+ }
+ /* it is assumed BGRA order */
+ if (var->bits_per_pixel > 8 )
+ {
+ var->blue.offset = 0;
+ var->green.offset = var->blue.length;
+ var->red.offset = var->green.offset + var->green.length;
+ var->transp.offset = var->red.offset + var->red.length;
}
var->height = var->width = -1;
@@ -502,10 +707,9 @@ static int pm3fb_set_par(struct fb_info *info)
{
struct pm3_par *par = info->par;
const u32 xres = (info->var.xres + 31) & ~31;
- const int depth = (info->var.bits_per_pixel + 7) & ~7;
+ const unsigned bpp = info->var.bits_per_pixel;
- par->base = pm3fb_shift_bpp(info->var.bits_per_pixel,
- (info->var.yoffset * xres)
+ par->base = pm3fb_shift_bpp(bpp,(info->var.yoffset * xres)
+ info->var.xoffset);
par->video = 0;
@@ -524,18 +728,16 @@ static int pm3fb_set_par(struct fb_info *info)
else
par->video |= PM3VideoControl_LINE_DOUBLE_OFF;
- if (info->var.activate == FB_ACTIVATE_NOW)
+ if ((info->var.activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW)
par->video |= PM3VideoControl_ENABLE;
else {
par->video |= PM3VideoControl_DISABLE;
DPRINTK("PM3Video disabled\n");
}
- switch (depth) {
+ switch (bpp) {
case 8:
par->video |= PM3VideoControl_PIXELSIZE_8BIT;
break;
- case 12:
- case 15:
case 16:
par->video |= PM3VideoControl_PIXELSIZE_16BIT;
break;
@@ -548,14 +750,15 @@ static int pm3fb_set_par(struct fb_info *info)
}
info->fix.visual =
- (depth == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
+ (bpp == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
info->fix.line_length = ((info->var.xres_virtual + 7) & ~7)
- * depth / 8;
+ * bpp / 8;
/* pm3fb_clear_memory(info, 0);*/
pm3fb_clear_colormap(par, 0, 0, 0);
PM3_WRITE_DAC_REG(par, PM3RD_CursorMode,
PM3RD_CursorMode_CURSOR_DISABLE);
+ pm3fb_init_engine(info);
pm3fb_write_mode(info);
return 0;
}
@@ -580,8 +783,8 @@ static int pm3fb_setcolreg(unsigned regno, unsigned red, unsigned green,
* var->{color}.length contains length of bitfield
* {hardwarespecific} contains width of DAC
* pseudo_palette[X] is programmed to (X << red.offset) |
- * (X << green.offset) |
- * (X << blue.offset)
+ * (X << green.offset) |
+ * (X << blue.offset)
* RAMDAC[X] is programmed to (red, green, blue)
* color depth = SUM(var->{color}.length)
*
@@ -621,7 +824,6 @@ static int pm3fb_setcolreg(unsigned regno, unsigned red, unsigned green,
case 8:
break;
case 16:
- case 24:
case 32:
((u32*)(info->pseudo_palette))[regno] = v;
break;
@@ -643,7 +845,8 @@ static int pm3fb_pan_display(struct fb_var_screeninfo *var,
par->base = pm3fb_shift_bpp(var->bits_per_pixel,
(var->yoffset * xres)
+ var->xoffset);
- PM3_SLOW_WRITE_REG(par, PM3ScreenBase, par->base);
+ PM3_WAIT(par, 1);
+ PM3_WRITE_REG(par, PM3ScreenBase, par->base);
return 0;
}
@@ -665,31 +868,31 @@ static int pm3fb_blank(int blank_mode, struct fb_info *info)
switch (blank_mode) {
case FB_BLANK_UNBLANK:
- video = video | PM3VideoControl_ENABLE;
+ video |= PM3VideoControl_ENABLE;
break;
- case FB_BLANK_NORMAL: /* FIXME */
- video = video & ~(PM3VideoControl_ENABLE);
+ case FB_BLANK_NORMAL:
+ video &= ~(PM3VideoControl_ENABLE);
break;
case FB_BLANK_HSYNC_SUSPEND:
- video = video & ~(PM3VideoControl_HSYNC_MASK |
- PM3VideoControl_BLANK_ACTIVE_LOW);
+ video &= ~(PM3VideoControl_HSYNC_MASK |
+ PM3VideoControl_BLANK_ACTIVE_LOW);
break;
case FB_BLANK_VSYNC_SUSPEND:
- video = video & ~(PM3VideoControl_VSYNC_MASK |
- PM3VideoControl_BLANK_ACTIVE_LOW);
+ video &= ~(PM3VideoControl_VSYNC_MASK |
+ PM3VideoControl_BLANK_ACTIVE_LOW);
break;
case FB_BLANK_POWERDOWN:
- video = video & ~(PM3VideoControl_HSYNC_MASK |
- PM3VideoControl_VSYNC_MASK |
- PM3VideoControl_BLANK_ACTIVE_LOW);
+ video &= ~(PM3VideoControl_HSYNC_MASK |
+ PM3VideoControl_VSYNC_MASK |
+ PM3VideoControl_BLANK_ACTIVE_LOW);
break;
default:
DPRINTK("Unsupported blanking %d\n", blank_mode);
return 1;
}
- PM3_SLOW_WRITE_REG(par,PM3VideoControl, video);
-
+ PM3_WAIT(par, 1);
+ PM3_WRITE_REG(par,PM3VideoControl, video);
return 0;
}
@@ -703,10 +906,11 @@ static struct fb_ops pm3fb_ops = {
.fb_set_par = pm3fb_set_par,
.fb_setcolreg = pm3fb_setcolreg,
.fb_pan_display = pm3fb_pan_display,
- .fb_fillrect = cfb_fillrect, /* Needed !!! */
- .fb_copyarea = cfb_copyarea, /* Needed !!! */
- .fb_imageblit = cfb_imageblit, /* Needed !!! */
+ .fb_fillrect = pm3fb_fillrect,
+ .fb_copyarea = cfb_copyarea,
+ .fb_imageblit = cfb_imageblit,
.fb_blank = pm3fb_blank,
+ .fb_sync = pm3fb_sync,
};
/* ------------------------------------------------------------------------- */
@@ -722,7 +926,7 @@ static unsigned long pm3fb_size_memory(struct pm3_par *par)
unsigned long memsize = 0, tempBypass, i, temp1, temp2;
unsigned char __iomem *screen_mem;
- pm3fb_fix.smem_len = 64 * 1024 * 1024; /* request full aperture size */
+ pm3fb_fix.smem_len = 64 * 1024l * 1024; /* request full aperture size */
/* Linear frame buffer - request region and map it. */
if (!request_mem_region(pm3fb_fix.smem_start, pm3fb_fix.smem_len,
"pm3fb smem")) {
@@ -744,7 +948,8 @@ static unsigned long pm3fb_size_memory(struct pm3_par *par)
DPRINTK("PM3MemBypassWriteMask was: 0x%08lx\n", tempBypass);
- PM3_SLOW_WRITE_REG(par, PM3MemBypassWriteMask, 0xFFFFFFFF);
+ PM3_WAIT(par, 1);
+ PM3_WRITE_REG(par, PM3MemBypassWriteMask, 0xFFFFFFFF);
/* pm3 split up memory, replicates, and do a lot of nasty stuff IMHO ;-) */
for (i = 0; i < 32; i++) {
@@ -765,10 +970,9 @@ static unsigned long pm3fb_size_memory(struct pm3_par *par)
if (memsize + 1 == i) {
for (i = 0; i < 32; i++) {
/* Clear first 32MB ; 0 is 0, no need to byteswap */
- writel(0x0000000,
- (screen_mem + (i * 1048576)));
- mb();
+ writel(0x0000000, (screen_mem + (i * 1048576)));
}
+ wmb();
for (i = 32; i < 64; i++) {
fb_writel(i * 0x00345678,
@@ -787,7 +991,8 @@ static unsigned long pm3fb_size_memory(struct pm3_par *par)
}
DPRINTK("Second detect pass got %ld MB\n", memsize + 1);
- PM3_SLOW_WRITE_REG(par, PM3MemBypassWriteMask, tempBypass);
+ PM3_WAIT(par, 1);
+ PM3_WRITE_REG(par, PM3MemBypassWriteMask, tempBypass);
iounmap(screen_mem);
release_mem_region(pm3fb_fix.smem_start, pm3fb_fix.smem_len);
@@ -874,7 +1079,8 @@ static int __devinit pm3fb_probe(struct pci_dev *dev,
info->fix = pm3fb_fix;
info->pseudo_palette = par->palette;
- info->flags = FBINFO_DEFAULT;/* | FBINFO_HWACCEL_YPAN;*/
+ info->flags = FBINFO_DEFAULT |
+ FBINFO_HWACCEL_FILLRECT;/* | FBINFO_HWACCEL_YPAN;*/
/*
* This should give a reasonable default video mode. The following is
@@ -890,7 +1096,6 @@ static int __devinit pm3fb_probe(struct pci_dev *dev,
goto err_exit_both;
}
- /* This has to been done !!! */
if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) {
retval = -ENOMEM;
goto err_exit_both;
@@ -907,7 +1112,7 @@ static int __devinit pm3fb_probe(struct pci_dev *dev,
}
printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node,
info->fix.id);
- pci_set_drvdata(dev, info); /* or dev_set_drvdata(device, info) */
+ pci_set_drvdata(dev, info);
return 0;
err_exit_all:
@@ -949,8 +1154,7 @@ static void __devexit pm3fb_remove(struct pci_dev *dev)
static struct pci_device_id pm3fb_id_table[] = {
{ PCI_VENDOR_ID_3DLABS, 0x0a,
- PCI_ANY_ID, PCI_ANY_ID, PCI_BASE_CLASS_DISPLAY << 16,
- 0xff0000, 0 },
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
{ 0, }
};
@@ -964,19 +1168,12 @@ static struct pci_driver pm3fb_driver = {
MODULE_DEVICE_TABLE(pci, pm3fb_id_table);
-int __init pm3fb_init(void)
+static int __init pm3fb_init(void)
{
- /*
- * For kernel boot options (in 'video=pm3fb:<options>' format)
- */
#ifndef MODULE
- char *option = NULL;
-
- if (fb_get_options("pm3fb", &option))
+ if (fb_get_options("pm3fb", NULL))
return -ENODEV;
- pm3fb_setup(option);
#endif
-
return pci_register_driver(&pm3fb_driver);
}
@@ -985,22 +1182,6 @@ static void __exit pm3fb_exit(void)
pci_unregister_driver(&pm3fb_driver);
}
-#ifndef MODULE
- /*
- * Setup
- */
-
-/*
- * Only necessary if your driver takes special options,
- * otherwise we fall back on the generic fb_setup().
- */
-int __init pm3fb_setup(char *options)
-{
- /* Parse user speficied options (`video=pm3fb:') */
- return 0;
-}
-#endif /* MODULE */
-
module_init(pm3fb_init);
module_exit(pm3fb_exit);