Commit 7654532dbeb6cc3fb35b12449f71f1d97e26fa9a

Authored by Hannes Eder
Committed by Linus Torvalds
1 parent 2899bb0941

pm3fb: fix sparse warning

Fix this sparse warning:

  drivers/video/pm3fb.c:543:3: warning: returning void-valued expression

Signed-off-by: Hannes Eder <hannes@hanneseder.net>
Cc: Krzysztof Helt <krzysztof.h1@poczta.fm>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

Showing 1 changed file with 4 additions and 2 deletions Inline Diff

drivers/video/pm3fb.c
1 /* 1 /*
2 * linux/drivers/video/pm3fb.c -- 3DLabs Permedia3 frame buffer device 2 * linux/drivers/video/pm3fb.c -- 3DLabs Permedia3 frame buffer device
3 * 3 *
4 * Copyright (C) 2001 Romain Dolbeau <romain@dolbeau.org>. 4 * Copyright (C) 2001 Romain Dolbeau <romain@dolbeau.org>.
5 * 5 *
6 * Ported to 2.6 kernel on 1 May 2007 by Krzysztof Helt <krzysztof.h1@wp.pl> 6 * Ported to 2.6 kernel on 1 May 2007 by Krzysztof Helt <krzysztof.h1@wp.pl>
7 * based on pm2fb.c 7 * based on pm2fb.c
8 * 8 *
9 * Based on code written by: 9 * Based on code written by:
10 * Sven Luther, <luther@dpt-info.u-strasbg.fr> 10 * Sven Luther, <luther@dpt-info.u-strasbg.fr>
11 * Alan Hourihane, <alanh@fairlite.demon.co.uk> 11 * Alan Hourihane, <alanh@fairlite.demon.co.uk>
12 * Russell King, <rmk@arm.linux.org.uk> 12 * Russell King, <rmk@arm.linux.org.uk>
13 * Based on linux/drivers/video/skeletonfb.c: 13 * Based on linux/drivers/video/skeletonfb.c:
14 * Copyright (C) 1997 Geert Uytterhoeven 14 * Copyright (C) 1997 Geert Uytterhoeven
15 * Based on linux/driver/video/pm2fb.c: 15 * Based on linux/driver/video/pm2fb.c:
16 * Copyright (C) 1998-1999 Ilario Nardinocchi (nardinoc@CS.UniBO.IT) 16 * Copyright (C) 1998-1999 Ilario Nardinocchi (nardinoc@CS.UniBO.IT)
17 * Copyright (C) 1999 Jakub Jelinek (jakub@redhat.com) 17 * Copyright (C) 1999 Jakub Jelinek (jakub@redhat.com)
18 * 18 *
19 * This file is subject to the terms and conditions of the GNU General Public 19 * This file is subject to the terms and conditions of the GNU General Public
20 * License. See the file COPYING in the main directory of this archive for 20 * License. See the file COPYING in the main directory of this archive for
21 * more details. 21 * more details.
22 * 22 *
23 */ 23 */
24 24
25 #include <linux/module.h> 25 #include <linux/module.h>
26 #include <linux/kernel.h> 26 #include <linux/kernel.h>
27 #include <linux/errno.h> 27 #include <linux/errno.h>
28 #include <linux/string.h> 28 #include <linux/string.h>
29 #include <linux/mm.h> 29 #include <linux/mm.h>
30 #include <linux/slab.h> 30 #include <linux/slab.h>
31 #include <linux/delay.h> 31 #include <linux/delay.h>
32 #include <linux/fb.h> 32 #include <linux/fb.h>
33 #include <linux/init.h> 33 #include <linux/init.h>
34 #include <linux/pci.h> 34 #include <linux/pci.h>
35 #ifdef CONFIG_MTRR 35 #ifdef CONFIG_MTRR
36 #include <asm/mtrr.h> 36 #include <asm/mtrr.h>
37 #endif 37 #endif
38 38
39 #include <video/pm3fb.h> 39 #include <video/pm3fb.h>
40 40
41 #if !defined(CONFIG_PCI) 41 #if !defined(CONFIG_PCI)
42 #error "Only generic PCI cards supported." 42 #error "Only generic PCI cards supported."
43 #endif 43 #endif
44 44
45 #undef PM3FB_MASTER_DEBUG 45 #undef PM3FB_MASTER_DEBUG
46 #ifdef PM3FB_MASTER_DEBUG 46 #ifdef PM3FB_MASTER_DEBUG
47 #define DPRINTK(a, b...) \ 47 #define DPRINTK(a, b...) \
48 printk(KERN_DEBUG "pm3fb: %s: " a, __func__ , ## b) 48 printk(KERN_DEBUG "pm3fb: %s: " a, __func__ , ## b)
49 #else 49 #else
50 #define DPRINTK(a, b...) 50 #define DPRINTK(a, b...)
51 #endif 51 #endif
52 52
53 #define PM3_PIXMAP_SIZE (2048 * 4) 53 #define PM3_PIXMAP_SIZE (2048 * 4)
54 54
55 /* 55 /*
56 * Driver data 56 * Driver data
57 */ 57 */
58 static int hwcursor = 1; 58 static int hwcursor = 1;
59 static char *mode_option __devinitdata; 59 static char *mode_option __devinitdata;
60 static int noaccel __devinitdata; 60 static int noaccel __devinitdata;
61 61
62 /* mtrr option */ 62 /* mtrr option */
63 #ifdef CONFIG_MTRR 63 #ifdef CONFIG_MTRR
64 static int nomtrr __devinitdata; 64 static int nomtrr __devinitdata;
65 #endif 65 #endif
66 66
67 /* 67 /*
68 * This structure defines the hardware state of the graphics card. Normally 68 * This structure defines the hardware state of the graphics card. Normally
69 * you place this in a header file in linux/include/video. This file usually 69 * you place this in a header file in linux/include/video. This file usually
70 * also includes register information. That allows other driver subsystems 70 * also includes register information. That allows other driver subsystems
71 * and userland applications the ability to use the same header file to 71 * and userland applications the ability to use the same header file to
72 * avoid duplicate work and easy porting of software. 72 * avoid duplicate work and easy porting of software.
73 */ 73 */
74 struct pm3_par { 74 struct pm3_par {
75 unsigned char __iomem *v_regs;/* virtual address of p_regs */ 75 unsigned char __iomem *v_regs;/* virtual address of p_regs */
76 u32 video; /* video flags before blanking */ 76 u32 video; /* video flags before blanking */
77 u32 base; /* screen base in 128 bits unit */ 77 u32 base; /* screen base in 128 bits unit */
78 u32 palette[16]; 78 u32 palette[16];
79 int mtrr_handle; 79 int mtrr_handle;
80 }; 80 };
81 81
82 /* 82 /*
83 * Here we define the default structs fb_fix_screeninfo and fb_var_screeninfo 83 * Here we define the default structs fb_fix_screeninfo and fb_var_screeninfo
84 * if we don't use modedb. If we do use modedb see pm3fb_init how to use it 84 * if we don't use modedb. If we do use modedb see pm3fb_init how to use it
85 * to get a fb_var_screeninfo. Otherwise define a default var as well. 85 * to get a fb_var_screeninfo. Otherwise define a default var as well.
86 */ 86 */
87 static struct fb_fix_screeninfo pm3fb_fix __devinitdata = { 87 static struct fb_fix_screeninfo pm3fb_fix __devinitdata = {
88 .id = "Permedia3", 88 .id = "Permedia3",
89 .type = FB_TYPE_PACKED_PIXELS, 89 .type = FB_TYPE_PACKED_PIXELS,
90 .visual = FB_VISUAL_PSEUDOCOLOR, 90 .visual = FB_VISUAL_PSEUDOCOLOR,
91 .xpanstep = 1, 91 .xpanstep = 1,
92 .ypanstep = 1, 92 .ypanstep = 1,
93 .ywrapstep = 0, 93 .ywrapstep = 0,
94 .accel = FB_ACCEL_3DLABS_PERMEDIA3, 94 .accel = FB_ACCEL_3DLABS_PERMEDIA3,
95 }; 95 };
96 96
97 /* 97 /*
98 * Utility functions 98 * Utility functions
99 */ 99 */
100 100
101 static inline u32 PM3_READ_REG(struct pm3_par *par, s32 off) 101 static inline u32 PM3_READ_REG(struct pm3_par *par, s32 off)
102 { 102 {
103 return fb_readl(par->v_regs + off); 103 return fb_readl(par->v_regs + off);
104 } 104 }
105 105
106 static inline void PM3_WRITE_REG(struct pm3_par *par, s32 off, u32 v) 106 static inline void PM3_WRITE_REG(struct pm3_par *par, s32 off, u32 v)
107 { 107 {
108 fb_writel(v, par->v_regs + off); 108 fb_writel(v, par->v_regs + off);
109 } 109 }
110 110
111 static inline void PM3_WAIT(struct pm3_par *par, u32 n) 111 static inline void PM3_WAIT(struct pm3_par *par, u32 n)
112 { 112 {
113 while (PM3_READ_REG(par, PM3InFIFOSpace) < n) 113 while (PM3_READ_REG(par, PM3InFIFOSpace) < n)
114 cpu_relax(); 114 cpu_relax();
115 } 115 }
116 116
117 static inline void PM3_WRITE_DAC_REG(struct pm3_par *par, unsigned r, u8 v) 117 static inline void PM3_WRITE_DAC_REG(struct pm3_par *par, unsigned r, u8 v)
118 { 118 {
119 PM3_WAIT(par, 3); 119 PM3_WAIT(par, 3);
120 PM3_WRITE_REG(par, PM3RD_IndexHigh, (r >> 8) & 0xff); 120 PM3_WRITE_REG(par, PM3RD_IndexHigh, (r >> 8) & 0xff);
121 PM3_WRITE_REG(par, PM3RD_IndexLow, r & 0xff); 121 PM3_WRITE_REG(par, PM3RD_IndexLow, r & 0xff);
122 wmb(); 122 wmb();
123 PM3_WRITE_REG(par, PM3RD_IndexedData, v); 123 PM3_WRITE_REG(par, PM3RD_IndexedData, v);
124 wmb(); 124 wmb();
125 } 125 }
126 126
127 static inline void pm3fb_set_color(struct pm3_par *par, unsigned char regno, 127 static inline void pm3fb_set_color(struct pm3_par *par, unsigned char regno,
128 unsigned char r, unsigned char g, unsigned char b) 128 unsigned char r, unsigned char g, unsigned char b)
129 { 129 {
130 PM3_WAIT(par, 4); 130 PM3_WAIT(par, 4);
131 PM3_WRITE_REG(par, PM3RD_PaletteWriteAddress, regno); 131 PM3_WRITE_REG(par, PM3RD_PaletteWriteAddress, regno);
132 wmb(); 132 wmb();
133 PM3_WRITE_REG(par, PM3RD_PaletteData, r); 133 PM3_WRITE_REG(par, PM3RD_PaletteData, r);
134 wmb(); 134 wmb();
135 PM3_WRITE_REG(par, PM3RD_PaletteData, g); 135 PM3_WRITE_REG(par, PM3RD_PaletteData, g);
136 wmb(); 136 wmb();
137 PM3_WRITE_REG(par, PM3RD_PaletteData, b); 137 PM3_WRITE_REG(par, PM3RD_PaletteData, b);
138 wmb(); 138 wmb();
139 } 139 }
140 140
141 static void pm3fb_clear_colormap(struct pm3_par *par, 141 static void pm3fb_clear_colormap(struct pm3_par *par,
142 unsigned char r, unsigned char g, unsigned char b) 142 unsigned char r, unsigned char g, unsigned char b)
143 { 143 {
144 int i; 144 int i;
145 145
146 for (i = 0; i < 256 ; i++) 146 for (i = 0; i < 256 ; i++)
147 pm3fb_set_color(par, i, r, g, b); 147 pm3fb_set_color(par, i, r, g, b);
148 148
149 } 149 }
150 150
151 /* Calculating various clock parameters */ 151 /* Calculating various clock parameters */
152 static void pm3fb_calculate_clock(unsigned long reqclock, 152 static void pm3fb_calculate_clock(unsigned long reqclock,
153 unsigned char *prescale, 153 unsigned char *prescale,
154 unsigned char *feedback, 154 unsigned char *feedback,
155 unsigned char *postscale) 155 unsigned char *postscale)
156 { 156 {
157 int f, pre, post; 157 int f, pre, post;
158 unsigned long freq; 158 unsigned long freq;
159 long freqerr = 1000; 159 long freqerr = 1000;
160 long currerr; 160 long currerr;
161 161
162 for (f = 1; f < 256; f++) { 162 for (f = 1; f < 256; f++) {
163 for (pre = 1; pre < 256; pre++) { 163 for (pre = 1; pre < 256; pre++) {
164 for (post = 0; post < 5; post++) { 164 for (post = 0; post < 5; post++) {
165 freq = ((2*PM3_REF_CLOCK * f) >> post) / pre; 165 freq = ((2*PM3_REF_CLOCK * f) >> post) / pre;
166 currerr = (reqclock > freq) 166 currerr = (reqclock > freq)
167 ? reqclock - freq 167 ? reqclock - freq
168 : freq - reqclock; 168 : freq - reqclock;
169 if (currerr < freqerr) { 169 if (currerr < freqerr) {
170 freqerr = currerr; 170 freqerr = currerr;
171 *feedback = f; 171 *feedback = f;
172 *prescale = pre; 172 *prescale = pre;
173 *postscale = post; 173 *postscale = post;
174 } 174 }
175 } 175 }
176 } 176 }
177 } 177 }
178 } 178 }
179 179
180 static inline int pm3fb_depth(const struct fb_var_screeninfo *var) 180 static inline int pm3fb_depth(const struct fb_var_screeninfo *var)
181 { 181 {
182 if (var->bits_per_pixel == 16) 182 if (var->bits_per_pixel == 16)
183 return var->red.length + var->green.length 183 return var->red.length + var->green.length
184 + var->blue.length; 184 + var->blue.length;
185 185
186 return var->bits_per_pixel; 186 return var->bits_per_pixel;
187 } 187 }
188 188
189 static inline int pm3fb_shift_bpp(unsigned bpp, int v) 189 static inline int pm3fb_shift_bpp(unsigned bpp, int v)
190 { 190 {
191 switch (bpp) { 191 switch (bpp) {
192 case 8: 192 case 8:
193 return (v >> 4); 193 return (v >> 4);
194 case 16: 194 case 16:
195 return (v >> 3); 195 return (v >> 3);
196 case 32: 196 case 32:
197 return (v >> 2); 197 return (v >> 2);
198 } 198 }
199 DPRINTK("Unsupported depth %u\n", bpp); 199 DPRINTK("Unsupported depth %u\n", bpp);
200 return 0; 200 return 0;
201 } 201 }
202 202
203 /* acceleration */ 203 /* acceleration */
204 static int pm3fb_sync(struct fb_info *info) 204 static int pm3fb_sync(struct fb_info *info)
205 { 205 {
206 struct pm3_par *par = info->par; 206 struct pm3_par *par = info->par;
207 207
208 PM3_WAIT(par, 2); 208 PM3_WAIT(par, 2);
209 PM3_WRITE_REG(par, PM3FilterMode, PM3FilterModeSync); 209 PM3_WRITE_REG(par, PM3FilterMode, PM3FilterModeSync);
210 PM3_WRITE_REG(par, PM3Sync, 0); 210 PM3_WRITE_REG(par, PM3Sync, 0);
211 mb(); 211 mb();
212 do { 212 do {
213 while ((PM3_READ_REG(par, PM3OutFIFOWords)) == 0) 213 while ((PM3_READ_REG(par, PM3OutFIFOWords)) == 0)
214 cpu_relax(); 214 cpu_relax();
215 } while ((PM3_READ_REG(par, PM3OutputFifo)) != PM3Sync_Tag); 215 } while ((PM3_READ_REG(par, PM3OutputFifo)) != PM3Sync_Tag);
216 216
217 return 0; 217 return 0;
218 } 218 }
219 219
220 static void pm3fb_init_engine(struct fb_info *info) 220 static void pm3fb_init_engine(struct fb_info *info)
221 { 221 {
222 struct pm3_par *par = info->par; 222 struct pm3_par *par = info->par;
223 const u32 width = (info->var.xres_virtual + 7) & ~7; 223 const u32 width = (info->var.xres_virtual + 7) & ~7;
224 224
225 PM3_WAIT(par, 50); 225 PM3_WAIT(par, 50);
226 PM3_WRITE_REG(par, PM3FilterMode, PM3FilterModeSync); 226 PM3_WRITE_REG(par, PM3FilterMode, PM3FilterModeSync);
227 PM3_WRITE_REG(par, PM3StatisticMode, 0x0); 227 PM3_WRITE_REG(par, PM3StatisticMode, 0x0);
228 PM3_WRITE_REG(par, PM3DeltaMode, 0x0); 228 PM3_WRITE_REG(par, PM3DeltaMode, 0x0);
229 PM3_WRITE_REG(par, PM3RasterizerMode, 0x0); 229 PM3_WRITE_REG(par, PM3RasterizerMode, 0x0);
230 PM3_WRITE_REG(par, PM3ScissorMode, 0x0); 230 PM3_WRITE_REG(par, PM3ScissorMode, 0x0);
231 PM3_WRITE_REG(par, PM3LineStippleMode, 0x0); 231 PM3_WRITE_REG(par, PM3LineStippleMode, 0x0);
232 PM3_WRITE_REG(par, PM3AreaStippleMode, 0x0); 232 PM3_WRITE_REG(par, PM3AreaStippleMode, 0x0);
233 PM3_WRITE_REG(par, PM3GIDMode, 0x0); 233 PM3_WRITE_REG(par, PM3GIDMode, 0x0);
234 PM3_WRITE_REG(par, PM3DepthMode, 0x0); 234 PM3_WRITE_REG(par, PM3DepthMode, 0x0);
235 PM3_WRITE_REG(par, PM3StencilMode, 0x0); 235 PM3_WRITE_REG(par, PM3StencilMode, 0x0);
236 PM3_WRITE_REG(par, PM3StencilData, 0x0); 236 PM3_WRITE_REG(par, PM3StencilData, 0x0);
237 PM3_WRITE_REG(par, PM3ColorDDAMode, 0x0); 237 PM3_WRITE_REG(par, PM3ColorDDAMode, 0x0);
238 PM3_WRITE_REG(par, PM3TextureCoordMode, 0x0); 238 PM3_WRITE_REG(par, PM3TextureCoordMode, 0x0);
239 PM3_WRITE_REG(par, PM3TextureIndexMode0, 0x0); 239 PM3_WRITE_REG(par, PM3TextureIndexMode0, 0x0);
240 PM3_WRITE_REG(par, PM3TextureIndexMode1, 0x0); 240 PM3_WRITE_REG(par, PM3TextureIndexMode1, 0x0);
241 PM3_WRITE_REG(par, PM3TextureReadMode, 0x0); 241 PM3_WRITE_REG(par, PM3TextureReadMode, 0x0);
242 PM3_WRITE_REG(par, PM3LUTMode, 0x0); 242 PM3_WRITE_REG(par, PM3LUTMode, 0x0);
243 PM3_WRITE_REG(par, PM3TextureFilterMode, 0x0); 243 PM3_WRITE_REG(par, PM3TextureFilterMode, 0x0);
244 PM3_WRITE_REG(par, PM3TextureCompositeMode, 0x0); 244 PM3_WRITE_REG(par, PM3TextureCompositeMode, 0x0);
245 PM3_WRITE_REG(par, PM3TextureApplicationMode, 0x0); 245 PM3_WRITE_REG(par, PM3TextureApplicationMode, 0x0);
246 PM3_WRITE_REG(par, PM3TextureCompositeColorMode1, 0x0); 246 PM3_WRITE_REG(par, PM3TextureCompositeColorMode1, 0x0);
247 PM3_WRITE_REG(par, PM3TextureCompositeAlphaMode1, 0x0); 247 PM3_WRITE_REG(par, PM3TextureCompositeAlphaMode1, 0x0);
248 PM3_WRITE_REG(par, PM3TextureCompositeColorMode0, 0x0); 248 PM3_WRITE_REG(par, PM3TextureCompositeColorMode0, 0x0);
249 PM3_WRITE_REG(par, PM3TextureCompositeAlphaMode0, 0x0); 249 PM3_WRITE_REG(par, PM3TextureCompositeAlphaMode0, 0x0);
250 PM3_WRITE_REG(par, PM3FogMode, 0x0); 250 PM3_WRITE_REG(par, PM3FogMode, 0x0);
251 PM3_WRITE_REG(par, PM3ChromaTestMode, 0x0); 251 PM3_WRITE_REG(par, PM3ChromaTestMode, 0x0);
252 PM3_WRITE_REG(par, PM3AlphaTestMode, 0x0); 252 PM3_WRITE_REG(par, PM3AlphaTestMode, 0x0);
253 PM3_WRITE_REG(par, PM3AntialiasMode, 0x0); 253 PM3_WRITE_REG(par, PM3AntialiasMode, 0x0);
254 PM3_WRITE_REG(par, PM3YUVMode, 0x0); 254 PM3_WRITE_REG(par, PM3YUVMode, 0x0);
255 PM3_WRITE_REG(par, PM3AlphaBlendColorMode, 0x0); 255 PM3_WRITE_REG(par, PM3AlphaBlendColorMode, 0x0);
256 PM3_WRITE_REG(par, PM3AlphaBlendAlphaMode, 0x0); 256 PM3_WRITE_REG(par, PM3AlphaBlendAlphaMode, 0x0);
257 PM3_WRITE_REG(par, PM3DitherMode, 0x0); 257 PM3_WRITE_REG(par, PM3DitherMode, 0x0);
258 PM3_WRITE_REG(par, PM3LogicalOpMode, 0x0); 258 PM3_WRITE_REG(par, PM3LogicalOpMode, 0x0);
259 PM3_WRITE_REG(par, PM3RouterMode, 0x0); 259 PM3_WRITE_REG(par, PM3RouterMode, 0x0);
260 PM3_WRITE_REG(par, PM3Window, 0x0); 260 PM3_WRITE_REG(par, PM3Window, 0x0);
261 261
262 PM3_WRITE_REG(par, PM3Config2D, 0x0); 262 PM3_WRITE_REG(par, PM3Config2D, 0x0);
263 263
264 PM3_WRITE_REG(par, PM3SpanColorMask, 0xffffffff); 264 PM3_WRITE_REG(par, PM3SpanColorMask, 0xffffffff);
265 265
266 PM3_WRITE_REG(par, PM3XBias, 0x0); 266 PM3_WRITE_REG(par, PM3XBias, 0x0);
267 PM3_WRITE_REG(par, PM3YBias, 0x0); 267 PM3_WRITE_REG(par, PM3YBias, 0x0);
268 PM3_WRITE_REG(par, PM3DeltaControl, 0x0); 268 PM3_WRITE_REG(par, PM3DeltaControl, 0x0);
269 269
270 PM3_WRITE_REG(par, PM3BitMaskPattern, 0xffffffff); 270 PM3_WRITE_REG(par, PM3BitMaskPattern, 0xffffffff);
271 271
272 PM3_WRITE_REG(par, PM3FBDestReadEnables, 272 PM3_WRITE_REG(par, PM3FBDestReadEnables,
273 PM3FBDestReadEnables_E(0xff) | 273 PM3FBDestReadEnables_E(0xff) |
274 PM3FBDestReadEnables_R(0xff) | 274 PM3FBDestReadEnables_R(0xff) |
275 PM3FBDestReadEnables_ReferenceAlpha(0xff)); 275 PM3FBDestReadEnables_ReferenceAlpha(0xff));
276 PM3_WRITE_REG(par, PM3FBDestReadBufferAddr0, 0x0); 276 PM3_WRITE_REG(par, PM3FBDestReadBufferAddr0, 0x0);
277 PM3_WRITE_REG(par, PM3FBDestReadBufferOffset0, 0x0); 277 PM3_WRITE_REG(par, PM3FBDestReadBufferOffset0, 0x0);
278 PM3_WRITE_REG(par, PM3FBDestReadBufferWidth0, 278 PM3_WRITE_REG(par, PM3FBDestReadBufferWidth0,
279 PM3FBDestReadBufferWidth_Width(width)); 279 PM3FBDestReadBufferWidth_Width(width));
280 280
281 PM3_WRITE_REG(par, PM3FBDestReadMode, 281 PM3_WRITE_REG(par, PM3FBDestReadMode,
282 PM3FBDestReadMode_ReadEnable | 282 PM3FBDestReadMode_ReadEnable |
283 PM3FBDestReadMode_Enable0); 283 PM3FBDestReadMode_Enable0);
284 PM3_WRITE_REG(par, PM3FBSourceReadBufferAddr, 0x0); 284 PM3_WRITE_REG(par, PM3FBSourceReadBufferAddr, 0x0);
285 PM3_WRITE_REG(par, PM3FBSourceReadBufferOffset, 0x0); 285 PM3_WRITE_REG(par, PM3FBSourceReadBufferOffset, 0x0);
286 PM3_WRITE_REG(par, PM3FBSourceReadBufferWidth, 286 PM3_WRITE_REG(par, PM3FBSourceReadBufferWidth,
287 PM3FBSourceReadBufferWidth_Width(width)); 287 PM3FBSourceReadBufferWidth_Width(width));
288 PM3_WRITE_REG(par, PM3FBSourceReadMode, 288 PM3_WRITE_REG(par, PM3FBSourceReadMode,
289 PM3FBSourceReadMode_Blocking | 289 PM3FBSourceReadMode_Blocking |
290 PM3FBSourceReadMode_ReadEnable); 290 PM3FBSourceReadMode_ReadEnable);
291 291
292 PM3_WAIT(par, 2); 292 PM3_WAIT(par, 2);
293 { 293 {
294 /* invert bits in bitmask */ 294 /* invert bits in bitmask */
295 unsigned long rm = 1 | (3 << 7); 295 unsigned long rm = 1 | (3 << 7);
296 switch (info->var.bits_per_pixel) { 296 switch (info->var.bits_per_pixel) {
297 case 8: 297 case 8:
298 PM3_WRITE_REG(par, PM3PixelSize, 298 PM3_WRITE_REG(par, PM3PixelSize,
299 PM3PixelSize_GLOBAL_8BIT); 299 PM3PixelSize_GLOBAL_8BIT);
300 #ifdef __BIG_ENDIAN 300 #ifdef __BIG_ENDIAN
301 rm |= 3 << 15; 301 rm |= 3 << 15;
302 #endif 302 #endif
303 break; 303 break;
304 case 16: 304 case 16:
305 PM3_WRITE_REG(par, PM3PixelSize, 305 PM3_WRITE_REG(par, PM3PixelSize,
306 PM3PixelSize_GLOBAL_16BIT); 306 PM3PixelSize_GLOBAL_16BIT);
307 #ifdef __BIG_ENDIAN 307 #ifdef __BIG_ENDIAN
308 rm |= 2 << 15; 308 rm |= 2 << 15;
309 #endif 309 #endif
310 break; 310 break;
311 case 32: 311 case 32:
312 PM3_WRITE_REG(par, PM3PixelSize, 312 PM3_WRITE_REG(par, PM3PixelSize,
313 PM3PixelSize_GLOBAL_32BIT); 313 PM3PixelSize_GLOBAL_32BIT);
314 break; 314 break;
315 default: 315 default:
316 DPRINTK(1, "Unsupported depth %d\n", 316 DPRINTK(1, "Unsupported depth %d\n",
317 info->var.bits_per_pixel); 317 info->var.bits_per_pixel);
318 break; 318 break;
319 } 319 }
320 PM3_WRITE_REG(par, PM3RasterizerMode, rm); 320 PM3_WRITE_REG(par, PM3RasterizerMode, rm);
321 } 321 }
322 322
323 PM3_WAIT(par, 20); 323 PM3_WAIT(par, 20);
324 PM3_WRITE_REG(par, PM3FBSoftwareWriteMask, 0xffffffff); 324 PM3_WRITE_REG(par, PM3FBSoftwareWriteMask, 0xffffffff);
325 PM3_WRITE_REG(par, PM3FBHardwareWriteMask, 0xffffffff); 325 PM3_WRITE_REG(par, PM3FBHardwareWriteMask, 0xffffffff);
326 PM3_WRITE_REG(par, PM3FBWriteMode, 326 PM3_WRITE_REG(par, PM3FBWriteMode,
327 PM3FBWriteMode_WriteEnable | 327 PM3FBWriteMode_WriteEnable |
328 PM3FBWriteMode_OpaqueSpan | 328 PM3FBWriteMode_OpaqueSpan |
329 PM3FBWriteMode_Enable0); 329 PM3FBWriteMode_Enable0);
330 PM3_WRITE_REG(par, PM3FBWriteBufferAddr0, 0x0); 330 PM3_WRITE_REG(par, PM3FBWriteBufferAddr0, 0x0);
331 PM3_WRITE_REG(par, PM3FBWriteBufferOffset0, 0x0); 331 PM3_WRITE_REG(par, PM3FBWriteBufferOffset0, 0x0);
332 PM3_WRITE_REG(par, PM3FBWriteBufferWidth0, 332 PM3_WRITE_REG(par, PM3FBWriteBufferWidth0,
333 PM3FBWriteBufferWidth_Width(width)); 333 PM3FBWriteBufferWidth_Width(width));
334 334
335 PM3_WRITE_REG(par, PM3SizeOfFramebuffer, 0x0); 335 PM3_WRITE_REG(par, PM3SizeOfFramebuffer, 0x0);
336 { 336 {
337 /* size in lines of FB */ 337 /* size in lines of FB */
338 unsigned long sofb = info->screen_size / 338 unsigned long sofb = info->screen_size /
339 info->fix.line_length; 339 info->fix.line_length;
340 if (sofb > 4095) 340 if (sofb > 4095)
341 PM3_WRITE_REG(par, PM3SizeOfFramebuffer, 4095); 341 PM3_WRITE_REG(par, PM3SizeOfFramebuffer, 4095);
342 else 342 else
343 PM3_WRITE_REG(par, PM3SizeOfFramebuffer, sofb); 343 PM3_WRITE_REG(par, PM3SizeOfFramebuffer, sofb);
344 344
345 switch (info->var.bits_per_pixel) { 345 switch (info->var.bits_per_pixel) {
346 case 8: 346 case 8:
347 PM3_WRITE_REG(par, PM3DitherMode, 347 PM3_WRITE_REG(par, PM3DitherMode,
348 (1 << 10) | (2 << 3)); 348 (1 << 10) | (2 << 3));
349 break; 349 break;
350 case 16: 350 case 16:
351 PM3_WRITE_REG(par, PM3DitherMode, 351 PM3_WRITE_REG(par, PM3DitherMode,
352 (1 << 10) | (1 << 3)); 352 (1 << 10) | (1 << 3));
353 break; 353 break;
354 case 32: 354 case 32:
355 PM3_WRITE_REG(par, PM3DitherMode, 355 PM3_WRITE_REG(par, PM3DitherMode,
356 (1 << 10) | (0 << 3)); 356 (1 << 10) | (0 << 3));
357 break; 357 break;
358 default: 358 default:
359 DPRINTK(1, "Unsupported depth %d\n", 359 DPRINTK(1, "Unsupported depth %d\n",
360 info->current_par->depth); 360 info->current_par->depth);
361 break; 361 break;
362 } 362 }
363 } 363 }
364 364
365 PM3_WRITE_REG(par, PM3dXDom, 0x0); 365 PM3_WRITE_REG(par, PM3dXDom, 0x0);
366 PM3_WRITE_REG(par, PM3dXSub, 0x0); 366 PM3_WRITE_REG(par, PM3dXSub, 0x0);
367 PM3_WRITE_REG(par, PM3dY, 1 << 16); 367 PM3_WRITE_REG(par, PM3dY, 1 << 16);
368 PM3_WRITE_REG(par, PM3StartXDom, 0x0); 368 PM3_WRITE_REG(par, PM3StartXDom, 0x0);
369 PM3_WRITE_REG(par, PM3StartXSub, 0x0); 369 PM3_WRITE_REG(par, PM3StartXSub, 0x0);
370 PM3_WRITE_REG(par, PM3StartY, 0x0); 370 PM3_WRITE_REG(par, PM3StartY, 0x0);
371 PM3_WRITE_REG(par, PM3Count, 0x0); 371 PM3_WRITE_REG(par, PM3Count, 0x0);
372 372
373 /* Disable LocalBuffer. better safe than sorry */ 373 /* Disable LocalBuffer. better safe than sorry */
374 PM3_WRITE_REG(par, PM3LBDestReadMode, 0x0); 374 PM3_WRITE_REG(par, PM3LBDestReadMode, 0x0);
375 PM3_WRITE_REG(par, PM3LBDestReadEnables, 0x0); 375 PM3_WRITE_REG(par, PM3LBDestReadEnables, 0x0);
376 PM3_WRITE_REG(par, PM3LBSourceReadMode, 0x0); 376 PM3_WRITE_REG(par, PM3LBSourceReadMode, 0x0);
377 PM3_WRITE_REG(par, PM3LBWriteMode, 0x0); 377 PM3_WRITE_REG(par, PM3LBWriteMode, 0x0);
378 378
379 pm3fb_sync(info); 379 pm3fb_sync(info);
380 } 380 }
381 381
382 static void pm3fb_fillrect(struct fb_info *info, 382 static void pm3fb_fillrect(struct fb_info *info,
383 const struct fb_fillrect *region) 383 const struct fb_fillrect *region)
384 { 384 {
385 struct pm3_par *par = info->par; 385 struct pm3_par *par = info->par;
386 struct fb_fillrect modded; 386 struct fb_fillrect modded;
387 int vxres, vyres; 387 int vxres, vyres;
388 int rop; 388 int rop;
389 u32 color = (info->fix.visual == FB_VISUAL_TRUECOLOR) ? 389 u32 color = (info->fix.visual == FB_VISUAL_TRUECOLOR) ?
390 ((u32 *)info->pseudo_palette)[region->color] : region->color; 390 ((u32 *)info->pseudo_palette)[region->color] : region->color;
391 391
392 if (info->state != FBINFO_STATE_RUNNING) 392 if (info->state != FBINFO_STATE_RUNNING)
393 return; 393 return;
394 if (info->flags & FBINFO_HWACCEL_DISABLED) { 394 if (info->flags & FBINFO_HWACCEL_DISABLED) {
395 cfb_fillrect(info, region); 395 cfb_fillrect(info, region);
396 return; 396 return;
397 } 397 }
398 if (region->rop == ROP_COPY ) 398 if (region->rop == ROP_COPY )
399 rop = PM3Config2D_ForegroundROP(0x3); /* GXcopy */ 399 rop = PM3Config2D_ForegroundROP(0x3); /* GXcopy */
400 else 400 else
401 rop = PM3Config2D_ForegroundROP(0x6) | /* GXxor */ 401 rop = PM3Config2D_ForegroundROP(0x6) | /* GXxor */
402 PM3Config2D_FBDestReadEnable; 402 PM3Config2D_FBDestReadEnable;
403 403
404 vxres = info->var.xres_virtual; 404 vxres = info->var.xres_virtual;
405 vyres = info->var.yres_virtual; 405 vyres = info->var.yres_virtual;
406 406
407 memcpy(&modded, region, sizeof(struct fb_fillrect)); 407 memcpy(&modded, region, sizeof(struct fb_fillrect));
408 408
409 if (!modded.width || !modded.height || 409 if (!modded.width || !modded.height ||
410 modded.dx >= vxres || modded.dy >= vyres) 410 modded.dx >= vxres || modded.dy >= vyres)
411 return; 411 return;
412 412
413 if (modded.dx + modded.width > vxres) 413 if (modded.dx + modded.width > vxres)
414 modded.width = vxres - modded.dx; 414 modded.width = vxres - modded.dx;
415 if (modded.dy + modded.height > vyres) 415 if (modded.dy + modded.height > vyres)
416 modded.height = vyres - modded.dy; 416 modded.height = vyres - modded.dy;
417 417
418 if (info->var.bits_per_pixel == 8) 418 if (info->var.bits_per_pixel == 8)
419 color |= color << 8; 419 color |= color << 8;
420 if (info->var.bits_per_pixel <= 16) 420 if (info->var.bits_per_pixel <= 16)
421 color |= color << 16; 421 color |= color << 16;
422 422
423 PM3_WAIT(par, 4); 423 PM3_WAIT(par, 4);
424 /* ROP Ox3 is GXcopy */ 424 /* ROP Ox3 is GXcopy */
425 PM3_WRITE_REG(par, PM3Config2D, 425 PM3_WRITE_REG(par, PM3Config2D,
426 PM3Config2D_UseConstantSource | 426 PM3Config2D_UseConstantSource |
427 PM3Config2D_ForegroundROPEnable | 427 PM3Config2D_ForegroundROPEnable |
428 rop | 428 rop |
429 PM3Config2D_FBWriteEnable); 429 PM3Config2D_FBWriteEnable);
430 430
431 PM3_WRITE_REG(par, PM3ForegroundColor, color); 431 PM3_WRITE_REG(par, PM3ForegroundColor, color);
432 432
433 PM3_WRITE_REG(par, PM3RectanglePosition, 433 PM3_WRITE_REG(par, PM3RectanglePosition,
434 PM3RectanglePosition_XOffset(modded.dx) | 434 PM3RectanglePosition_XOffset(modded.dx) |
435 PM3RectanglePosition_YOffset(modded.dy)); 435 PM3RectanglePosition_YOffset(modded.dy));
436 436
437 PM3_WRITE_REG(par, PM3Render2D, 437 PM3_WRITE_REG(par, PM3Render2D,
438 PM3Render2D_XPositive | 438 PM3Render2D_XPositive |
439 PM3Render2D_YPositive | 439 PM3Render2D_YPositive |
440 PM3Render2D_Operation_Normal | 440 PM3Render2D_Operation_Normal |
441 PM3Render2D_SpanOperation | 441 PM3Render2D_SpanOperation |
442 PM3Render2D_Width(modded.width) | 442 PM3Render2D_Width(modded.width) |
443 PM3Render2D_Height(modded.height)); 443 PM3Render2D_Height(modded.height));
444 } 444 }
445 445
446 static void pm3fb_copyarea(struct fb_info *info, 446 static void pm3fb_copyarea(struct fb_info *info,
447 const struct fb_copyarea *area) 447 const struct fb_copyarea *area)
448 { 448 {
449 struct pm3_par *par = info->par; 449 struct pm3_par *par = info->par;
450 struct fb_copyarea modded; 450 struct fb_copyarea modded;
451 u32 vxres, vyres; 451 u32 vxres, vyres;
452 int x_align, o_x, o_y; 452 int x_align, o_x, o_y;
453 453
454 if (info->state != FBINFO_STATE_RUNNING) 454 if (info->state != FBINFO_STATE_RUNNING)
455 return; 455 return;
456 if (info->flags & FBINFO_HWACCEL_DISABLED) { 456 if (info->flags & FBINFO_HWACCEL_DISABLED) {
457 cfb_copyarea(info, area); 457 cfb_copyarea(info, area);
458 return; 458 return;
459 } 459 }
460 460
461 memcpy(&modded, area, sizeof(struct fb_copyarea)); 461 memcpy(&modded, area, sizeof(struct fb_copyarea));
462 462
463 vxres = info->var.xres_virtual; 463 vxres = info->var.xres_virtual;
464 vyres = info->var.yres_virtual; 464 vyres = info->var.yres_virtual;
465 465
466 if (!modded.width || !modded.height || 466 if (!modded.width || !modded.height ||
467 modded.sx >= vxres || modded.sy >= vyres || 467 modded.sx >= vxres || modded.sy >= vyres ||
468 modded.dx >= vxres || modded.dy >= vyres) 468 modded.dx >= vxres || modded.dy >= vyres)
469 return; 469 return;
470 470
471 if (modded.sx + modded.width > vxres) 471 if (modded.sx + modded.width > vxres)
472 modded.width = vxres - modded.sx; 472 modded.width = vxres - modded.sx;
473 if (modded.dx + modded.width > vxres) 473 if (modded.dx + modded.width > vxres)
474 modded.width = vxres - modded.dx; 474 modded.width = vxres - modded.dx;
475 if (modded.sy + modded.height > vyres) 475 if (modded.sy + modded.height > vyres)
476 modded.height = vyres - modded.sy; 476 modded.height = vyres - modded.sy;
477 if (modded.dy + modded.height > vyres) 477 if (modded.dy + modded.height > vyres)
478 modded.height = vyres - modded.dy; 478 modded.height = vyres - modded.dy;
479 479
480 o_x = modded.sx - modded.dx; /*(sx > dx ) ? (sx - dx) : (dx - sx); */ 480 o_x = modded.sx - modded.dx; /*(sx > dx ) ? (sx - dx) : (dx - sx); */
481 o_y = modded.sy - modded.dy; /*(sy > dy ) ? (sy - dy) : (dy - sy); */ 481 o_y = modded.sy - modded.dy; /*(sy > dy ) ? (sy - dy) : (dy - sy); */
482 482
483 x_align = (modded.sx & 0x1f); 483 x_align = (modded.sx & 0x1f);
484 484
485 PM3_WAIT(par, 6); 485 PM3_WAIT(par, 6);
486 486
487 PM3_WRITE_REG(par, PM3Config2D, 487 PM3_WRITE_REG(par, PM3Config2D,
488 PM3Config2D_UserScissorEnable | 488 PM3Config2D_UserScissorEnable |
489 PM3Config2D_ForegroundROPEnable | 489 PM3Config2D_ForegroundROPEnable |
490 PM3Config2D_Blocking | 490 PM3Config2D_Blocking |
491 PM3Config2D_ForegroundROP(0x3) | /* Ox3 is GXcopy */ 491 PM3Config2D_ForegroundROP(0x3) | /* Ox3 is GXcopy */
492 PM3Config2D_FBWriteEnable); 492 PM3Config2D_FBWriteEnable);
493 493
494 PM3_WRITE_REG(par, PM3ScissorMinXY, 494 PM3_WRITE_REG(par, PM3ScissorMinXY,
495 ((modded.dy & 0x0fff) << 16) | (modded.dx & 0x0fff)); 495 ((modded.dy & 0x0fff) << 16) | (modded.dx & 0x0fff));
496 PM3_WRITE_REG(par, PM3ScissorMaxXY, 496 PM3_WRITE_REG(par, PM3ScissorMaxXY,
497 (((modded.dy + modded.height) & 0x0fff) << 16) | 497 (((modded.dy + modded.height) & 0x0fff) << 16) |
498 ((modded.dx + modded.width) & 0x0fff)); 498 ((modded.dx + modded.width) & 0x0fff));
499 499
500 PM3_WRITE_REG(par, PM3FBSourceReadBufferOffset, 500 PM3_WRITE_REG(par, PM3FBSourceReadBufferOffset,
501 PM3FBSourceReadBufferOffset_XOffset(o_x) | 501 PM3FBSourceReadBufferOffset_XOffset(o_x) |
502 PM3FBSourceReadBufferOffset_YOffset(o_y)); 502 PM3FBSourceReadBufferOffset_YOffset(o_y));
503 503
504 PM3_WRITE_REG(par, PM3RectanglePosition, 504 PM3_WRITE_REG(par, PM3RectanglePosition,
505 PM3RectanglePosition_XOffset(modded.dx - x_align) | 505 PM3RectanglePosition_XOffset(modded.dx - x_align) |
506 PM3RectanglePosition_YOffset(modded.dy)); 506 PM3RectanglePosition_YOffset(modded.dy));
507 507
508 PM3_WRITE_REG(par, PM3Render2D, 508 PM3_WRITE_REG(par, PM3Render2D,
509 ((modded.sx > modded.dx) ? PM3Render2D_XPositive : 0) | 509 ((modded.sx > modded.dx) ? PM3Render2D_XPositive : 0) |
510 ((modded.sy > modded.dy) ? PM3Render2D_YPositive : 0) | 510 ((modded.sy > modded.dy) ? PM3Render2D_YPositive : 0) |
511 PM3Render2D_Operation_Normal | 511 PM3Render2D_Operation_Normal |
512 PM3Render2D_SpanOperation | 512 PM3Render2D_SpanOperation |
513 PM3Render2D_FBSourceReadEnable | 513 PM3Render2D_FBSourceReadEnable |
514 PM3Render2D_Width(modded.width + x_align) | 514 PM3Render2D_Width(modded.width + x_align) |
515 PM3Render2D_Height(modded.height)); 515 PM3Render2D_Height(modded.height));
516 } 516 }
517 517
518 static void pm3fb_imageblit(struct fb_info *info, const struct fb_image *image) 518 static void pm3fb_imageblit(struct fb_info *info, const struct fb_image *image)
519 { 519 {
520 struct pm3_par *par = info->par; 520 struct pm3_par *par = info->par;
521 u32 height = image->height; 521 u32 height = image->height;
522 u32 fgx, bgx; 522 u32 fgx, bgx;
523 const u32 *src = (const u32 *)image->data; 523 const u32 *src = (const u32 *)image->data;
524 524
525 if (info->state != FBINFO_STATE_RUNNING) 525 if (info->state != FBINFO_STATE_RUNNING)
526 return; 526 return;
527 if (info->flags & FBINFO_HWACCEL_DISABLED) { 527 if (info->flags & FBINFO_HWACCEL_DISABLED) {
528 cfb_imageblit(info, image); 528 cfb_imageblit(info, image);
529 return; 529 return;
530 } 530 }
531 switch (info->fix.visual) { 531 switch (info->fix.visual) {
532 case FB_VISUAL_PSEUDOCOLOR: 532 case FB_VISUAL_PSEUDOCOLOR:
533 fgx = image->fg_color; 533 fgx = image->fg_color;
534 bgx = image->bg_color; 534 bgx = image->bg_color;
535 break; 535 break;
536 case FB_VISUAL_TRUECOLOR: 536 case FB_VISUAL_TRUECOLOR:
537 default: 537 default:
538 fgx = par->palette[image->fg_color]; 538 fgx = par->palette[image->fg_color];
539 bgx = par->palette[image->bg_color]; 539 bgx = par->palette[image->bg_color];
540 break; 540 break;
541 } 541 }
542 if (image->depth != 1) 542 if (image->depth != 1) {
543 return cfb_imageblit(info, image); 543 cfb_imageblit(info, image);
544 return;
545 }
544 546
545 if (info->var.bits_per_pixel == 8) { 547 if (info->var.bits_per_pixel == 8) {
546 fgx |= fgx << 8; 548 fgx |= fgx << 8;
547 bgx |= bgx << 8; 549 bgx |= bgx << 8;
548 } 550 }
549 if (info->var.bits_per_pixel <= 16) { 551 if (info->var.bits_per_pixel <= 16) {
550 fgx |= fgx << 16; 552 fgx |= fgx << 16;
551 bgx |= bgx << 16; 553 bgx |= bgx << 16;
552 } 554 }
553 555
554 PM3_WAIT(par, 7); 556 PM3_WAIT(par, 7);
555 557
556 PM3_WRITE_REG(par, PM3ForegroundColor, fgx); 558 PM3_WRITE_REG(par, PM3ForegroundColor, fgx);
557 PM3_WRITE_REG(par, PM3BackgroundColor, bgx); 559 PM3_WRITE_REG(par, PM3BackgroundColor, bgx);
558 560
559 /* ROP Ox3 is GXcopy */ 561 /* ROP Ox3 is GXcopy */
560 PM3_WRITE_REG(par, PM3Config2D, 562 PM3_WRITE_REG(par, PM3Config2D,
561 PM3Config2D_UserScissorEnable | 563 PM3Config2D_UserScissorEnable |
562 PM3Config2D_UseConstantSource | 564 PM3Config2D_UseConstantSource |
563 PM3Config2D_ForegroundROPEnable | 565 PM3Config2D_ForegroundROPEnable |
564 PM3Config2D_ForegroundROP(0x3) | 566 PM3Config2D_ForegroundROP(0x3) |
565 PM3Config2D_OpaqueSpan | 567 PM3Config2D_OpaqueSpan |
566 PM3Config2D_FBWriteEnable); 568 PM3Config2D_FBWriteEnable);
567 PM3_WRITE_REG(par, PM3ScissorMinXY, 569 PM3_WRITE_REG(par, PM3ScissorMinXY,
568 ((image->dy & 0x0fff) << 16) | (image->dx & 0x0fff)); 570 ((image->dy & 0x0fff) << 16) | (image->dx & 0x0fff));
569 PM3_WRITE_REG(par, PM3ScissorMaxXY, 571 PM3_WRITE_REG(par, PM3ScissorMaxXY,
570 (((image->dy + image->height) & 0x0fff) << 16) | 572 (((image->dy + image->height) & 0x0fff) << 16) |
571 ((image->dx + image->width) & 0x0fff)); 573 ((image->dx + image->width) & 0x0fff));
572 PM3_WRITE_REG(par, PM3RectanglePosition, 574 PM3_WRITE_REG(par, PM3RectanglePosition,
573 PM3RectanglePosition_XOffset(image->dx) | 575 PM3RectanglePosition_XOffset(image->dx) |
574 PM3RectanglePosition_YOffset(image->dy)); 576 PM3RectanglePosition_YOffset(image->dy));
575 PM3_WRITE_REG(par, PM3Render2D, 577 PM3_WRITE_REG(par, PM3Render2D,
576 PM3Render2D_XPositive | 578 PM3Render2D_XPositive |
577 PM3Render2D_YPositive | 579 PM3Render2D_YPositive |
578 PM3Render2D_Operation_SyncOnBitMask | 580 PM3Render2D_Operation_SyncOnBitMask |
579 PM3Render2D_SpanOperation | 581 PM3Render2D_SpanOperation |
580 PM3Render2D_Width(image->width) | 582 PM3Render2D_Width(image->width) |
581 PM3Render2D_Height(image->height)); 583 PM3Render2D_Height(image->height));
582 584
583 585
584 while (height--) { 586 while (height--) {
585 int width = ((image->width + 7) >> 3) 587 int width = ((image->width + 7) >> 3)
586 + info->pixmap.scan_align - 1; 588 + info->pixmap.scan_align - 1;
587 width >>= 2; 589 width >>= 2;
588 590
589 while (width >= PM3_FIFO_SIZE) { 591 while (width >= PM3_FIFO_SIZE) {
590 int i = PM3_FIFO_SIZE - 1; 592 int i = PM3_FIFO_SIZE - 1;
591 593
592 PM3_WAIT(par, PM3_FIFO_SIZE); 594 PM3_WAIT(par, PM3_FIFO_SIZE);
593 while (i--) { 595 while (i--) {
594 PM3_WRITE_REG(par, PM3BitMaskPattern, *src); 596 PM3_WRITE_REG(par, PM3BitMaskPattern, *src);
595 src++; 597 src++;
596 } 598 }
597 width -= PM3_FIFO_SIZE - 1; 599 width -= PM3_FIFO_SIZE - 1;
598 } 600 }
599 601
600 PM3_WAIT(par, width + 1); 602 PM3_WAIT(par, width + 1);
601 while (width--) { 603 while (width--) {
602 PM3_WRITE_REG(par, PM3BitMaskPattern, *src); 604 PM3_WRITE_REG(par, PM3BitMaskPattern, *src);
603 src++; 605 src++;
604 } 606 }
605 } 607 }
606 } 608 }
607 /* end of acceleration functions */ 609 /* end of acceleration functions */
608 610
609 /* 611 /*
610 * Hardware Cursor support. 612 * Hardware Cursor support.
611 */ 613 */
612 static const u8 cursor_bits_lookup[16] = { 614 static const u8 cursor_bits_lookup[16] = {
613 0x00, 0x40, 0x10, 0x50, 0x04, 0x44, 0x14, 0x54, 615 0x00, 0x40, 0x10, 0x50, 0x04, 0x44, 0x14, 0x54,
614 0x01, 0x41, 0x11, 0x51, 0x05, 0x45, 0x15, 0x55 616 0x01, 0x41, 0x11, 0x51, 0x05, 0x45, 0x15, 0x55
615 }; 617 };
616 618
617 static int pm3fb_cursor(struct fb_info *info, struct fb_cursor *cursor) 619 static int pm3fb_cursor(struct fb_info *info, struct fb_cursor *cursor)
618 { 620 {
619 struct pm3_par *par = info->par; 621 struct pm3_par *par = info->par;
620 u8 mode; 622 u8 mode;
621 623
622 if (!hwcursor) 624 if (!hwcursor)
623 return -EINVAL; /* just to force soft_cursor() call */ 625 return -EINVAL; /* just to force soft_cursor() call */
624 626
625 /* Too large of a cursor or wrong bpp :-( */ 627 /* Too large of a cursor or wrong bpp :-( */
626 if (cursor->image.width > 64 || 628 if (cursor->image.width > 64 ||
627 cursor->image.height > 64 || 629 cursor->image.height > 64 ||
628 cursor->image.depth > 1) 630 cursor->image.depth > 1)
629 return -EINVAL; 631 return -EINVAL;
630 632
631 mode = PM3RD_CursorMode_TYPE_X; 633 mode = PM3RD_CursorMode_TYPE_X;
632 if (cursor->enable) 634 if (cursor->enable)
633 mode |= PM3RD_CursorMode_CURSOR_ENABLE; 635 mode |= PM3RD_CursorMode_CURSOR_ENABLE;
634 636
635 PM3_WRITE_DAC_REG(par, PM3RD_CursorMode, mode); 637 PM3_WRITE_DAC_REG(par, PM3RD_CursorMode, mode);
636 638
637 /* 639 /*
638 * If the cursor is not be changed this means either we want the 640 * If the cursor is not be changed this means either we want the
639 * current cursor state (if enable is set) or we want to query what 641 * current cursor state (if enable is set) or we want to query what
640 * we can do with the cursor (if enable is not set) 642 * we can do with the cursor (if enable is not set)
641 */ 643 */
642 if (!cursor->set) 644 if (!cursor->set)
643 return 0; 645 return 0;
644 646
645 if (cursor->set & FB_CUR_SETPOS) { 647 if (cursor->set & FB_CUR_SETPOS) {
646 int x = cursor->image.dx - info->var.xoffset; 648 int x = cursor->image.dx - info->var.xoffset;
647 int y = cursor->image.dy - info->var.yoffset; 649 int y = cursor->image.dy - info->var.yoffset;
648 650
649 PM3_WRITE_DAC_REG(par, PM3RD_CursorXLow, x & 0xff); 651 PM3_WRITE_DAC_REG(par, PM3RD_CursorXLow, x & 0xff);
650 PM3_WRITE_DAC_REG(par, PM3RD_CursorXHigh, (x >> 8) & 0xf); 652 PM3_WRITE_DAC_REG(par, PM3RD_CursorXHigh, (x >> 8) & 0xf);
651 PM3_WRITE_DAC_REG(par, PM3RD_CursorYLow, y & 0xff); 653 PM3_WRITE_DAC_REG(par, PM3RD_CursorYLow, y & 0xff);
652 PM3_WRITE_DAC_REG(par, PM3RD_CursorYHigh, (y >> 8) & 0xf); 654 PM3_WRITE_DAC_REG(par, PM3RD_CursorYHigh, (y >> 8) & 0xf);
653 } 655 }
654 656
655 if (cursor->set & FB_CUR_SETHOT) { 657 if (cursor->set & FB_CUR_SETHOT) {
656 PM3_WRITE_DAC_REG(par, PM3RD_CursorHotSpotX, 658 PM3_WRITE_DAC_REG(par, PM3RD_CursorHotSpotX,
657 cursor->hot.x & 0x3f); 659 cursor->hot.x & 0x3f);
658 PM3_WRITE_DAC_REG(par, PM3RD_CursorHotSpotY, 660 PM3_WRITE_DAC_REG(par, PM3RD_CursorHotSpotY,
659 cursor->hot.y & 0x3f); 661 cursor->hot.y & 0x3f);
660 } 662 }
661 663
662 if (cursor->set & FB_CUR_SETCMAP) { 664 if (cursor->set & FB_CUR_SETCMAP) {
663 u32 fg_idx = cursor->image.fg_color; 665 u32 fg_idx = cursor->image.fg_color;
664 u32 bg_idx = cursor->image.bg_color; 666 u32 bg_idx = cursor->image.bg_color;
665 struct fb_cmap cmap = info->cmap; 667 struct fb_cmap cmap = info->cmap;
666 668
667 /* the X11 driver says one should use these color registers */ 669 /* the X11 driver says one should use these color registers */
668 PM3_WRITE_DAC_REG(par, PM3RD_CursorPalette(39), 670 PM3_WRITE_DAC_REG(par, PM3RD_CursorPalette(39),
669 cmap.red[fg_idx] >> 8 ); 671 cmap.red[fg_idx] >> 8 );
670 PM3_WRITE_DAC_REG(par, PM3RD_CursorPalette(40), 672 PM3_WRITE_DAC_REG(par, PM3RD_CursorPalette(40),
671 cmap.green[fg_idx] >> 8 ); 673 cmap.green[fg_idx] >> 8 );
672 PM3_WRITE_DAC_REG(par, PM3RD_CursorPalette(41), 674 PM3_WRITE_DAC_REG(par, PM3RD_CursorPalette(41),
673 cmap.blue[fg_idx] >> 8 ); 675 cmap.blue[fg_idx] >> 8 );
674 676
675 PM3_WRITE_DAC_REG(par, PM3RD_CursorPalette(42), 677 PM3_WRITE_DAC_REG(par, PM3RD_CursorPalette(42),
676 cmap.red[bg_idx] >> 8 ); 678 cmap.red[bg_idx] >> 8 );
677 PM3_WRITE_DAC_REG(par, PM3RD_CursorPalette(43), 679 PM3_WRITE_DAC_REG(par, PM3RD_CursorPalette(43),
678 cmap.green[bg_idx] >> 8 ); 680 cmap.green[bg_idx] >> 8 );
679 PM3_WRITE_DAC_REG(par, PM3RD_CursorPalette(44), 681 PM3_WRITE_DAC_REG(par, PM3RD_CursorPalette(44),
680 cmap.blue[bg_idx] >> 8 ); 682 cmap.blue[bg_idx] >> 8 );
681 } 683 }
682 684
683 if (cursor->set & (FB_CUR_SETSHAPE | FB_CUR_SETIMAGE)) { 685 if (cursor->set & (FB_CUR_SETSHAPE | FB_CUR_SETIMAGE)) {
684 u8 *bitmap = (u8 *)cursor->image.data; 686 u8 *bitmap = (u8 *)cursor->image.data;
685 u8 *mask = (u8 *)cursor->mask; 687 u8 *mask = (u8 *)cursor->mask;
686 int i; 688 int i;
687 int pos = PM3RD_CursorPattern(0); 689 int pos = PM3RD_CursorPattern(0);
688 690
689 for (i = 0; i < cursor->image.height; i++) { 691 for (i = 0; i < cursor->image.height; i++) {
690 int j = (cursor->image.width + 7) >> 3; 692 int j = (cursor->image.width + 7) >> 3;
691 int k = 8 - j; 693 int k = 8 - j;
692 694
693 for (; j > 0; j--) { 695 for (; j > 0; j--) {
694 u8 data = *bitmap ^ *mask; 696 u8 data = *bitmap ^ *mask;
695 697
696 if (cursor->rop == ROP_COPY) 698 if (cursor->rop == ROP_COPY)
697 data = *mask & *bitmap; 699 data = *mask & *bitmap;
698 /* Upper 4 bits of bitmap data */ 700 /* Upper 4 bits of bitmap data */
699 PM3_WRITE_DAC_REG(par, pos++, 701 PM3_WRITE_DAC_REG(par, pos++,
700 cursor_bits_lookup[data >> 4] | 702 cursor_bits_lookup[data >> 4] |
701 (cursor_bits_lookup[*mask >> 4] << 1)); 703 (cursor_bits_lookup[*mask >> 4] << 1));
702 /* Lower 4 bits of bitmap */ 704 /* Lower 4 bits of bitmap */
703 PM3_WRITE_DAC_REG(par, pos++, 705 PM3_WRITE_DAC_REG(par, pos++,
704 cursor_bits_lookup[data & 0xf] | 706 cursor_bits_lookup[data & 0xf] |
705 (cursor_bits_lookup[*mask & 0xf] << 1)); 707 (cursor_bits_lookup[*mask & 0xf] << 1));
706 bitmap++; 708 bitmap++;
707 mask++; 709 mask++;
708 } 710 }
709 for (; k > 0; k--) { 711 for (; k > 0; k--) {
710 PM3_WRITE_DAC_REG(par, pos++, 0); 712 PM3_WRITE_DAC_REG(par, pos++, 0);
711 PM3_WRITE_DAC_REG(par, pos++, 0); 713 PM3_WRITE_DAC_REG(par, pos++, 0);
712 } 714 }
713 } 715 }
714 while (pos < PM3RD_CursorPattern(1024)) 716 while (pos < PM3RD_CursorPattern(1024))
715 PM3_WRITE_DAC_REG(par, pos++, 0); 717 PM3_WRITE_DAC_REG(par, pos++, 0);
716 } 718 }
717 return 0; 719 return 0;
718 } 720 }
719 721
720 /* write the mode to registers */ 722 /* write the mode to registers */
721 static void pm3fb_write_mode(struct fb_info *info) 723 static void pm3fb_write_mode(struct fb_info *info)
722 { 724 {
723 struct pm3_par *par = info->par; 725 struct pm3_par *par = info->par;
724 char tempsync = 0x00; 726 char tempsync = 0x00;
725 char tempmisc = 0x00; 727 char tempmisc = 0x00;
726 const u32 hsstart = info->var.right_margin; 728 const u32 hsstart = info->var.right_margin;
727 const u32 hsend = hsstart + info->var.hsync_len; 729 const u32 hsend = hsstart + info->var.hsync_len;
728 const u32 hbend = hsend + info->var.left_margin; 730 const u32 hbend = hsend + info->var.left_margin;
729 const u32 xres = (info->var.xres + 31) & ~31; 731 const u32 xres = (info->var.xres + 31) & ~31;
730 const u32 htotal = xres + hbend; 732 const u32 htotal = xres + hbend;
731 const u32 vsstart = info->var.lower_margin; 733 const u32 vsstart = info->var.lower_margin;
732 const u32 vsend = vsstart + info->var.vsync_len; 734 const u32 vsend = vsstart + info->var.vsync_len;
733 const u32 vbend = vsend + info->var.upper_margin; 735 const u32 vbend = vsend + info->var.upper_margin;
734 const u32 vtotal = info->var.yres + vbend; 736 const u32 vtotal = info->var.yres + vbend;
735 const u32 width = (info->var.xres_virtual + 7) & ~7; 737 const u32 width = (info->var.xres_virtual + 7) & ~7;
736 const unsigned bpp = info->var.bits_per_pixel; 738 const unsigned bpp = info->var.bits_per_pixel;
737 739
738 PM3_WAIT(par, 20); 740 PM3_WAIT(par, 20);
739 PM3_WRITE_REG(par, PM3MemBypassWriteMask, 0xffffffff); 741 PM3_WRITE_REG(par, PM3MemBypassWriteMask, 0xffffffff);
740 PM3_WRITE_REG(par, PM3Aperture0, 0x00000000); 742 PM3_WRITE_REG(par, PM3Aperture0, 0x00000000);
741 PM3_WRITE_REG(par, PM3Aperture1, 0x00000000); 743 PM3_WRITE_REG(par, PM3Aperture1, 0x00000000);
742 PM3_WRITE_REG(par, PM3FIFODis, 0x00000007); 744 PM3_WRITE_REG(par, PM3FIFODis, 0x00000007);
743 745
744 PM3_WRITE_REG(par, PM3HTotal, 746 PM3_WRITE_REG(par, PM3HTotal,
745 pm3fb_shift_bpp(bpp, htotal - 1)); 747 pm3fb_shift_bpp(bpp, htotal - 1));
746 PM3_WRITE_REG(par, PM3HsEnd, 748 PM3_WRITE_REG(par, PM3HsEnd,
747 pm3fb_shift_bpp(bpp, hsend)); 749 pm3fb_shift_bpp(bpp, hsend));
748 PM3_WRITE_REG(par, PM3HsStart, 750 PM3_WRITE_REG(par, PM3HsStart,
749 pm3fb_shift_bpp(bpp, hsstart)); 751 pm3fb_shift_bpp(bpp, hsstart));
750 PM3_WRITE_REG(par, PM3HbEnd, 752 PM3_WRITE_REG(par, PM3HbEnd,
751 pm3fb_shift_bpp(bpp, hbend)); 753 pm3fb_shift_bpp(bpp, hbend));
752 PM3_WRITE_REG(par, PM3HgEnd, 754 PM3_WRITE_REG(par, PM3HgEnd,
753 pm3fb_shift_bpp(bpp, hbend)); 755 pm3fb_shift_bpp(bpp, hbend));
754 PM3_WRITE_REG(par, PM3ScreenStride, 756 PM3_WRITE_REG(par, PM3ScreenStride,
755 pm3fb_shift_bpp(bpp, width)); 757 pm3fb_shift_bpp(bpp, width));
756 PM3_WRITE_REG(par, PM3VTotal, vtotal - 1); 758 PM3_WRITE_REG(par, PM3VTotal, vtotal - 1);
757 PM3_WRITE_REG(par, PM3VsEnd, vsend - 1); 759 PM3_WRITE_REG(par, PM3VsEnd, vsend - 1);
758 PM3_WRITE_REG(par, PM3VsStart, vsstart - 1); 760 PM3_WRITE_REG(par, PM3VsStart, vsstart - 1);
759 PM3_WRITE_REG(par, PM3VbEnd, vbend); 761 PM3_WRITE_REG(par, PM3VbEnd, vbend);
760 762
761 switch (bpp) { 763 switch (bpp) {
762 case 8: 764 case 8:
763 PM3_WRITE_REG(par, PM3ByAperture1Mode, 765 PM3_WRITE_REG(par, PM3ByAperture1Mode,
764 PM3ByApertureMode_PIXELSIZE_8BIT); 766 PM3ByApertureMode_PIXELSIZE_8BIT);
765 PM3_WRITE_REG(par, PM3ByAperture2Mode, 767 PM3_WRITE_REG(par, PM3ByAperture2Mode,
766 PM3ByApertureMode_PIXELSIZE_8BIT); 768 PM3ByApertureMode_PIXELSIZE_8BIT);
767 break; 769 break;
768 770
769 case 16: 771 case 16:
770 #ifndef __BIG_ENDIAN 772 #ifndef __BIG_ENDIAN
771 PM3_WRITE_REG(par, PM3ByAperture1Mode, 773 PM3_WRITE_REG(par, PM3ByAperture1Mode,
772 PM3ByApertureMode_PIXELSIZE_16BIT); 774 PM3ByApertureMode_PIXELSIZE_16BIT);
773 PM3_WRITE_REG(par, PM3ByAperture2Mode, 775 PM3_WRITE_REG(par, PM3ByAperture2Mode,
774 PM3ByApertureMode_PIXELSIZE_16BIT); 776 PM3ByApertureMode_PIXELSIZE_16BIT);
775 #else 777 #else
776 PM3_WRITE_REG(par, PM3ByAperture1Mode, 778 PM3_WRITE_REG(par, PM3ByAperture1Mode,
777 PM3ByApertureMode_PIXELSIZE_16BIT | 779 PM3ByApertureMode_PIXELSIZE_16BIT |
778 PM3ByApertureMode_BYTESWAP_BADC); 780 PM3ByApertureMode_BYTESWAP_BADC);
779 PM3_WRITE_REG(par, PM3ByAperture2Mode, 781 PM3_WRITE_REG(par, PM3ByAperture2Mode,
780 PM3ByApertureMode_PIXELSIZE_16BIT | 782 PM3ByApertureMode_PIXELSIZE_16BIT |
781 PM3ByApertureMode_BYTESWAP_BADC); 783 PM3ByApertureMode_BYTESWAP_BADC);
782 #endif /* ! __BIG_ENDIAN */ 784 #endif /* ! __BIG_ENDIAN */
783 break; 785 break;
784 786
785 case 32: 787 case 32:
786 #ifndef __BIG_ENDIAN 788 #ifndef __BIG_ENDIAN
787 PM3_WRITE_REG(par, PM3ByAperture1Mode, 789 PM3_WRITE_REG(par, PM3ByAperture1Mode,
788 PM3ByApertureMode_PIXELSIZE_32BIT); 790 PM3ByApertureMode_PIXELSIZE_32BIT);
789 PM3_WRITE_REG(par, PM3ByAperture2Mode, 791 PM3_WRITE_REG(par, PM3ByAperture2Mode,
790 PM3ByApertureMode_PIXELSIZE_32BIT); 792 PM3ByApertureMode_PIXELSIZE_32BIT);
791 #else 793 #else
792 PM3_WRITE_REG(par, PM3ByAperture1Mode, 794 PM3_WRITE_REG(par, PM3ByAperture1Mode,
793 PM3ByApertureMode_PIXELSIZE_32BIT | 795 PM3ByApertureMode_PIXELSIZE_32BIT |
794 PM3ByApertureMode_BYTESWAP_DCBA); 796 PM3ByApertureMode_BYTESWAP_DCBA);
795 PM3_WRITE_REG(par, PM3ByAperture2Mode, 797 PM3_WRITE_REG(par, PM3ByAperture2Mode,
796 PM3ByApertureMode_PIXELSIZE_32BIT | 798 PM3ByApertureMode_PIXELSIZE_32BIT |
797 PM3ByApertureMode_BYTESWAP_DCBA); 799 PM3ByApertureMode_BYTESWAP_DCBA);
798 #endif /* ! __BIG_ENDIAN */ 800 #endif /* ! __BIG_ENDIAN */
799 break; 801 break;
800 802
801 default: 803 default:
802 DPRINTK("Unsupported depth %d\n", bpp); 804 DPRINTK("Unsupported depth %d\n", bpp);
803 break; 805 break;
804 } 806 }
805 807
806 /* 808 /*
807 * Oxygen VX1 - it appears that setting PM3VideoControl and 809 * Oxygen VX1 - it appears that setting PM3VideoControl and
808 * then PM3RD_SyncControl to the same SYNC settings undoes 810 * then PM3RD_SyncControl to the same SYNC settings undoes
809 * any net change - they seem to xor together. Only set the 811 * any net change - they seem to xor together. Only set the
810 * sync options in PM3RD_SyncControl. --rmk 812 * sync options in PM3RD_SyncControl. --rmk
811 */ 813 */
812 { 814 {
813 unsigned int video = par->video; 815 unsigned int video = par->video;
814 816
815 video &= ~(PM3VideoControl_HSYNC_MASK | 817 video &= ~(PM3VideoControl_HSYNC_MASK |
816 PM3VideoControl_VSYNC_MASK); 818 PM3VideoControl_VSYNC_MASK);
817 video |= PM3VideoControl_HSYNC_ACTIVE_HIGH | 819 video |= PM3VideoControl_HSYNC_ACTIVE_HIGH |
818 PM3VideoControl_VSYNC_ACTIVE_HIGH; 820 PM3VideoControl_VSYNC_ACTIVE_HIGH;
819 PM3_WRITE_REG(par, PM3VideoControl, video); 821 PM3_WRITE_REG(par, PM3VideoControl, video);
820 } 822 }
821 PM3_WRITE_REG(par, PM3VClkCtl, 823 PM3_WRITE_REG(par, PM3VClkCtl,
822 (PM3_READ_REG(par, PM3VClkCtl) & 0xFFFFFFFC)); 824 (PM3_READ_REG(par, PM3VClkCtl) & 0xFFFFFFFC));
823 PM3_WRITE_REG(par, PM3ScreenBase, par->base); 825 PM3_WRITE_REG(par, PM3ScreenBase, par->base);
824 PM3_WRITE_REG(par, PM3ChipConfig, 826 PM3_WRITE_REG(par, PM3ChipConfig,
825 (PM3_READ_REG(par, PM3ChipConfig) & 0xFFFFFFFD)); 827 (PM3_READ_REG(par, PM3ChipConfig) & 0xFFFFFFFD));
826 828
827 wmb(); 829 wmb();
828 { 830 {
829 unsigned char uninitialized_var(m); /* ClkPreScale */ 831 unsigned char uninitialized_var(m); /* ClkPreScale */
830 unsigned char uninitialized_var(n); /* ClkFeedBackScale */ 832 unsigned char uninitialized_var(n); /* ClkFeedBackScale */
831 unsigned char uninitialized_var(p); /* ClkPostScale */ 833 unsigned char uninitialized_var(p); /* ClkPostScale */
832 unsigned long pixclock = PICOS2KHZ(info->var.pixclock); 834 unsigned long pixclock = PICOS2KHZ(info->var.pixclock);
833 835
834 (void)pm3fb_calculate_clock(pixclock, &m, &n, &p); 836 (void)pm3fb_calculate_clock(pixclock, &m, &n, &p);
835 837
836 DPRINTK("Pixclock: %ld, Pre: %d, Feedback: %d, Post: %d\n", 838 DPRINTK("Pixclock: %ld, Pre: %d, Feedback: %d, Post: %d\n",
837 pixclock, (int) m, (int) n, (int) p); 839 pixclock, (int) m, (int) n, (int) p);
838 840
839 PM3_WRITE_DAC_REG(par, PM3RD_DClk0PreScale, m); 841 PM3_WRITE_DAC_REG(par, PM3RD_DClk0PreScale, m);
840 PM3_WRITE_DAC_REG(par, PM3RD_DClk0FeedbackScale, n); 842 PM3_WRITE_DAC_REG(par, PM3RD_DClk0FeedbackScale, n);
841 PM3_WRITE_DAC_REG(par, PM3RD_DClk0PostScale, p); 843 PM3_WRITE_DAC_REG(par, PM3RD_DClk0PostScale, p);
842 } 844 }
843 /* 845 /*
844 PM3_WRITE_DAC_REG(par, PM3RD_IndexControl, 0x00); 846 PM3_WRITE_DAC_REG(par, PM3RD_IndexControl, 0x00);
845 */ 847 */
846 /* 848 /*
847 PM3_SLOW_WRITE_REG(par, PM3RD_IndexControl, 0x00); 849 PM3_SLOW_WRITE_REG(par, PM3RD_IndexControl, 0x00);
848 */ 850 */
849 if ((par->video & PM3VideoControl_HSYNC_MASK) == 851 if ((par->video & PM3VideoControl_HSYNC_MASK) ==
850 PM3VideoControl_HSYNC_ACTIVE_HIGH) 852 PM3VideoControl_HSYNC_ACTIVE_HIGH)
851 tempsync |= PM3RD_SyncControl_HSYNC_ACTIVE_HIGH; 853 tempsync |= PM3RD_SyncControl_HSYNC_ACTIVE_HIGH;
852 if ((par->video & PM3VideoControl_VSYNC_MASK) == 854 if ((par->video & PM3VideoControl_VSYNC_MASK) ==
853 PM3VideoControl_VSYNC_ACTIVE_HIGH) 855 PM3VideoControl_VSYNC_ACTIVE_HIGH)
854 tempsync |= PM3RD_SyncControl_VSYNC_ACTIVE_HIGH; 856 tempsync |= PM3RD_SyncControl_VSYNC_ACTIVE_HIGH;
855 857
856 PM3_WRITE_DAC_REG(par, PM3RD_SyncControl, tempsync); 858 PM3_WRITE_DAC_REG(par, PM3RD_SyncControl, tempsync);
857 DPRINTK("PM3RD_SyncControl: %d\n", tempsync); 859 DPRINTK("PM3RD_SyncControl: %d\n", tempsync);
858 860
859 PM3_WRITE_DAC_REG(par, PM3RD_DACControl, 0x00); 861 PM3_WRITE_DAC_REG(par, PM3RD_DACControl, 0x00);
860 862
861 switch (pm3fb_depth(&info->var)) { 863 switch (pm3fb_depth(&info->var)) {
862 case 8: 864 case 8:
863 PM3_WRITE_DAC_REG(par, PM3RD_PixelSize, 865 PM3_WRITE_DAC_REG(par, PM3RD_PixelSize,
864 PM3RD_PixelSize_8_BIT_PIXELS); 866 PM3RD_PixelSize_8_BIT_PIXELS);
865 PM3_WRITE_DAC_REG(par, PM3RD_ColorFormat, 867 PM3_WRITE_DAC_REG(par, PM3RD_ColorFormat,
866 PM3RD_ColorFormat_CI8_COLOR | 868 PM3RD_ColorFormat_CI8_COLOR |
867 PM3RD_ColorFormat_COLOR_ORDER_BLUE_LOW); 869 PM3RD_ColorFormat_COLOR_ORDER_BLUE_LOW);
868 tempmisc |= PM3RD_MiscControl_HIGHCOLOR_RES_ENABLE; 870 tempmisc |= PM3RD_MiscControl_HIGHCOLOR_RES_ENABLE;
869 break; 871 break;
870 case 12: 872 case 12:
871 PM3_WRITE_DAC_REG(par, PM3RD_PixelSize, 873 PM3_WRITE_DAC_REG(par, PM3RD_PixelSize,
872 PM3RD_PixelSize_16_BIT_PIXELS); 874 PM3RD_PixelSize_16_BIT_PIXELS);
873 PM3_WRITE_DAC_REG(par, PM3RD_ColorFormat, 875 PM3_WRITE_DAC_REG(par, PM3RD_ColorFormat,
874 PM3RD_ColorFormat_4444_COLOR | 876 PM3RD_ColorFormat_4444_COLOR |
875 PM3RD_ColorFormat_COLOR_ORDER_BLUE_LOW | 877 PM3RD_ColorFormat_COLOR_ORDER_BLUE_LOW |
876 PM3RD_ColorFormat_LINEAR_COLOR_EXT_ENABLE); 878 PM3RD_ColorFormat_LINEAR_COLOR_EXT_ENABLE);
877 tempmisc |= PM3RD_MiscControl_DIRECTCOLOR_ENABLE | 879 tempmisc |= PM3RD_MiscControl_DIRECTCOLOR_ENABLE |
878 PM3RD_MiscControl_HIGHCOLOR_RES_ENABLE; 880 PM3RD_MiscControl_HIGHCOLOR_RES_ENABLE;
879 break; 881 break;
880 case 15: 882 case 15:
881 PM3_WRITE_DAC_REG(par, PM3RD_PixelSize, 883 PM3_WRITE_DAC_REG(par, PM3RD_PixelSize,
882 PM3RD_PixelSize_16_BIT_PIXELS); 884 PM3RD_PixelSize_16_BIT_PIXELS);
883 PM3_WRITE_DAC_REG(par, PM3RD_ColorFormat, 885 PM3_WRITE_DAC_REG(par, PM3RD_ColorFormat,
884 PM3RD_ColorFormat_5551_FRONT_COLOR | 886 PM3RD_ColorFormat_5551_FRONT_COLOR |
885 PM3RD_ColorFormat_COLOR_ORDER_BLUE_LOW | 887 PM3RD_ColorFormat_COLOR_ORDER_BLUE_LOW |
886 PM3RD_ColorFormat_LINEAR_COLOR_EXT_ENABLE); 888 PM3RD_ColorFormat_LINEAR_COLOR_EXT_ENABLE);
887 tempmisc |= PM3RD_MiscControl_DIRECTCOLOR_ENABLE | 889 tempmisc |= PM3RD_MiscControl_DIRECTCOLOR_ENABLE |
888 PM3RD_MiscControl_HIGHCOLOR_RES_ENABLE; 890 PM3RD_MiscControl_HIGHCOLOR_RES_ENABLE;
889 break; 891 break;
890 case 16: 892 case 16:
891 PM3_WRITE_DAC_REG(par, PM3RD_PixelSize, 893 PM3_WRITE_DAC_REG(par, PM3RD_PixelSize,
892 PM3RD_PixelSize_16_BIT_PIXELS); 894 PM3RD_PixelSize_16_BIT_PIXELS);
893 PM3_WRITE_DAC_REG(par, PM3RD_ColorFormat, 895 PM3_WRITE_DAC_REG(par, PM3RD_ColorFormat,
894 PM3RD_ColorFormat_565_FRONT_COLOR | 896 PM3RD_ColorFormat_565_FRONT_COLOR |
895 PM3RD_ColorFormat_COLOR_ORDER_BLUE_LOW | 897 PM3RD_ColorFormat_COLOR_ORDER_BLUE_LOW |
896 PM3RD_ColorFormat_LINEAR_COLOR_EXT_ENABLE); 898 PM3RD_ColorFormat_LINEAR_COLOR_EXT_ENABLE);
897 tempmisc |= PM3RD_MiscControl_DIRECTCOLOR_ENABLE | 899 tempmisc |= PM3RD_MiscControl_DIRECTCOLOR_ENABLE |
898 PM3RD_MiscControl_HIGHCOLOR_RES_ENABLE; 900 PM3RD_MiscControl_HIGHCOLOR_RES_ENABLE;
899 break; 901 break;
900 case 32: 902 case 32:
901 PM3_WRITE_DAC_REG(par, PM3RD_PixelSize, 903 PM3_WRITE_DAC_REG(par, PM3RD_PixelSize,
902 PM3RD_PixelSize_32_BIT_PIXELS); 904 PM3RD_PixelSize_32_BIT_PIXELS);
903 PM3_WRITE_DAC_REG(par, PM3RD_ColorFormat, 905 PM3_WRITE_DAC_REG(par, PM3RD_ColorFormat,
904 PM3RD_ColorFormat_8888_COLOR | 906 PM3RD_ColorFormat_8888_COLOR |
905 PM3RD_ColorFormat_COLOR_ORDER_BLUE_LOW); 907 PM3RD_ColorFormat_COLOR_ORDER_BLUE_LOW);
906 tempmisc |= PM3RD_MiscControl_DIRECTCOLOR_ENABLE | 908 tempmisc |= PM3RD_MiscControl_DIRECTCOLOR_ENABLE |
907 PM3RD_MiscControl_HIGHCOLOR_RES_ENABLE; 909 PM3RD_MiscControl_HIGHCOLOR_RES_ENABLE;
908 break; 910 break;
909 } 911 }
910 PM3_WRITE_DAC_REG(par, PM3RD_MiscControl, tempmisc); 912 PM3_WRITE_DAC_REG(par, PM3RD_MiscControl, tempmisc);
911 } 913 }
912 914
913 /* 915 /*
914 * hardware independent functions 916 * hardware independent functions
915 */ 917 */
916 static int pm3fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) 918 static int pm3fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
917 { 919 {
918 u32 lpitch; 920 u32 lpitch;
919 unsigned bpp = var->red.length + var->green.length 921 unsigned bpp = var->red.length + var->green.length
920 + var->blue.length + var->transp.length; 922 + var->blue.length + var->transp.length;
921 923
922 if (bpp != var->bits_per_pixel) { 924 if (bpp != var->bits_per_pixel) {
923 /* set predefined mode for bits_per_pixel settings */ 925 /* set predefined mode for bits_per_pixel settings */
924 926
925 switch (var->bits_per_pixel) { 927 switch (var->bits_per_pixel) {
926 case 8: 928 case 8:
927 var->red.length = 8; 929 var->red.length = 8;
928 var->green.length = 8; 930 var->green.length = 8;
929 var->blue.length = 8; 931 var->blue.length = 8;
930 var->red.offset = 0; 932 var->red.offset = 0;
931 var->green.offset = 0; 933 var->green.offset = 0;
932 var->blue.offset = 0; 934 var->blue.offset = 0;
933 var->transp.offset = 0; 935 var->transp.offset = 0;
934 var->transp.length = 0; 936 var->transp.length = 0;
935 break; 937 break;
936 case 16: 938 case 16:
937 var->red.length = 5; 939 var->red.length = 5;
938 var->blue.length = 5; 940 var->blue.length = 5;
939 var->green.length = 6; 941 var->green.length = 6;
940 var->transp.length = 0; 942 var->transp.length = 0;
941 break; 943 break;
942 case 32: 944 case 32:
943 var->red.length = 8; 945 var->red.length = 8;
944 var->green.length = 8; 946 var->green.length = 8;
945 var->blue.length = 8; 947 var->blue.length = 8;
946 var->transp.length = 8; 948 var->transp.length = 8;
947 break; 949 break;
948 default: 950 default:
949 DPRINTK("depth not supported: %u\n", 951 DPRINTK("depth not supported: %u\n",
950 var->bits_per_pixel); 952 var->bits_per_pixel);
951 return -EINVAL; 953 return -EINVAL;
952 } 954 }
953 } 955 }
954 /* it is assumed BGRA order */ 956 /* it is assumed BGRA order */
955 if (var->bits_per_pixel > 8 ) { 957 if (var->bits_per_pixel > 8 ) {
956 var->blue.offset = 0; 958 var->blue.offset = 0;
957 var->green.offset = var->blue.length; 959 var->green.offset = var->blue.length;
958 var->red.offset = var->green.offset + var->green.length; 960 var->red.offset = var->green.offset + var->green.length;
959 var->transp.offset = var->red.offset + var->red.length; 961 var->transp.offset = var->red.offset + var->red.length;
960 } 962 }
961 var->height = -1; 963 var->height = -1;
962 var->width = -1; 964 var->width = -1;
963 965
964 if (var->xres != var->xres_virtual) { 966 if (var->xres != var->xres_virtual) {
965 DPRINTK("virtual x resolution != " 967 DPRINTK("virtual x resolution != "
966 "physical x resolution not supported\n"); 968 "physical x resolution not supported\n");
967 return -EINVAL; 969 return -EINVAL;
968 } 970 }
969 971
970 if (var->yres > var->yres_virtual) { 972 if (var->yres > var->yres_virtual) {
971 DPRINTK("virtual y resolution < " 973 DPRINTK("virtual y resolution < "
972 "physical y resolution not possible\n"); 974 "physical y resolution not possible\n");
973 return -EINVAL; 975 return -EINVAL;
974 } 976 }
975 977
976 if (var->xoffset) { 978 if (var->xoffset) {
977 DPRINTK("xoffset not supported\n"); 979 DPRINTK("xoffset not supported\n");
978 return -EINVAL; 980 return -EINVAL;
979 } 981 }
980 982
981 if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) { 983 if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
982 DPRINTK("interlace not supported\n"); 984 DPRINTK("interlace not supported\n");
983 return -EINVAL; 985 return -EINVAL;
984 } 986 }
985 987
986 var->xres = (var->xres + 31) & ~31; /* could sometimes be 8 */ 988 var->xres = (var->xres + 31) & ~31; /* could sometimes be 8 */
987 lpitch = var->xres * ((var->bits_per_pixel + 7) >> 3); 989 lpitch = var->xres * ((var->bits_per_pixel + 7) >> 3);
988 990
989 if (var->xres < 200 || var->xres > 2048) { 991 if (var->xres < 200 || var->xres > 2048) {
990 DPRINTK("width not supported: %u\n", var->xres); 992 DPRINTK("width not supported: %u\n", var->xres);
991 return -EINVAL; 993 return -EINVAL;
992 } 994 }
993 995
994 if (var->yres < 200 || var->yres > 4095) { 996 if (var->yres < 200 || var->yres > 4095) {
995 DPRINTK("height not supported: %u\n", var->yres); 997 DPRINTK("height not supported: %u\n", var->yres);
996 return -EINVAL; 998 return -EINVAL;
997 } 999 }
998 1000
999 if (lpitch * var->yres_virtual > info->fix.smem_len) { 1001 if (lpitch * var->yres_virtual > info->fix.smem_len) {
1000 DPRINTK("no memory for screen (%ux%ux%u)\n", 1002 DPRINTK("no memory for screen (%ux%ux%u)\n",
1001 var->xres, var->yres_virtual, var->bits_per_pixel); 1003 var->xres, var->yres_virtual, var->bits_per_pixel);
1002 return -EINVAL; 1004 return -EINVAL;
1003 } 1005 }
1004 1006
1005 if (PICOS2KHZ(var->pixclock) > PM3_MAX_PIXCLOCK) { 1007 if (PICOS2KHZ(var->pixclock) > PM3_MAX_PIXCLOCK) {
1006 DPRINTK("pixclock too high (%ldKHz)\n", 1008 DPRINTK("pixclock too high (%ldKHz)\n",
1007 PICOS2KHZ(var->pixclock)); 1009 PICOS2KHZ(var->pixclock));
1008 return -EINVAL; 1010 return -EINVAL;
1009 } 1011 }
1010 1012
1011 var->accel_flags = 0; /* Can't mmap if this is on */ 1013 var->accel_flags = 0; /* Can't mmap if this is on */
1012 1014
1013 DPRINTK("Checking graphics mode at %dx%d depth %d\n", 1015 DPRINTK("Checking graphics mode at %dx%d depth %d\n",
1014 var->xres, var->yres, var->bits_per_pixel); 1016 var->xres, var->yres, var->bits_per_pixel);
1015 return 0; 1017 return 0;
1016 } 1018 }
1017 1019
1018 static int pm3fb_set_par(struct fb_info *info) 1020 static int pm3fb_set_par(struct fb_info *info)
1019 { 1021 {
1020 struct pm3_par *par = info->par; 1022 struct pm3_par *par = info->par;
1021 const u32 xres = (info->var.xres + 31) & ~31; 1023 const u32 xres = (info->var.xres + 31) & ~31;
1022 const unsigned bpp = info->var.bits_per_pixel; 1024 const unsigned bpp = info->var.bits_per_pixel;
1023 1025
1024 par->base = pm3fb_shift_bpp(bpp, (info->var.yoffset * xres) 1026 par->base = pm3fb_shift_bpp(bpp, (info->var.yoffset * xres)
1025 + info->var.xoffset); 1027 + info->var.xoffset);
1026 par->video = 0; 1028 par->video = 0;
1027 1029
1028 if (info->var.sync & FB_SYNC_HOR_HIGH_ACT) 1030 if (info->var.sync & FB_SYNC_HOR_HIGH_ACT)
1029 par->video |= PM3VideoControl_HSYNC_ACTIVE_HIGH; 1031 par->video |= PM3VideoControl_HSYNC_ACTIVE_HIGH;
1030 else 1032 else
1031 par->video |= PM3VideoControl_HSYNC_ACTIVE_LOW; 1033 par->video |= PM3VideoControl_HSYNC_ACTIVE_LOW;
1032 1034
1033 if (info->var.sync & FB_SYNC_VERT_HIGH_ACT) 1035 if (info->var.sync & FB_SYNC_VERT_HIGH_ACT)
1034 par->video |= PM3VideoControl_VSYNC_ACTIVE_HIGH; 1036 par->video |= PM3VideoControl_VSYNC_ACTIVE_HIGH;
1035 else 1037 else
1036 par->video |= PM3VideoControl_VSYNC_ACTIVE_LOW; 1038 par->video |= PM3VideoControl_VSYNC_ACTIVE_LOW;
1037 1039
1038 if ((info->var.vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) 1040 if ((info->var.vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE)
1039 par->video |= PM3VideoControl_LINE_DOUBLE_ON; 1041 par->video |= PM3VideoControl_LINE_DOUBLE_ON;
1040 1042
1041 if ((info->var.activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) 1043 if ((info->var.activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW)
1042 par->video |= PM3VideoControl_ENABLE; 1044 par->video |= PM3VideoControl_ENABLE;
1043 else 1045 else
1044 DPRINTK("PM3Video disabled\n"); 1046 DPRINTK("PM3Video disabled\n");
1045 1047
1046 switch (bpp) { 1048 switch (bpp) {
1047 case 8: 1049 case 8:
1048 par->video |= PM3VideoControl_PIXELSIZE_8BIT; 1050 par->video |= PM3VideoControl_PIXELSIZE_8BIT;
1049 break; 1051 break;
1050 case 16: 1052 case 16:
1051 par->video |= PM3VideoControl_PIXELSIZE_16BIT; 1053 par->video |= PM3VideoControl_PIXELSIZE_16BIT;
1052 break; 1054 break;
1053 case 32: 1055 case 32:
1054 par->video |= PM3VideoControl_PIXELSIZE_32BIT; 1056 par->video |= PM3VideoControl_PIXELSIZE_32BIT;
1055 break; 1057 break;
1056 default: 1058 default:
1057 DPRINTK("Unsupported depth\n"); 1059 DPRINTK("Unsupported depth\n");
1058 break; 1060 break;
1059 } 1061 }
1060 1062
1061 info->fix.visual = 1063 info->fix.visual =
1062 (bpp == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR; 1064 (bpp == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
1063 info->fix.line_length = ((info->var.xres_virtual + 7) >> 3) * bpp; 1065 info->fix.line_length = ((info->var.xres_virtual + 7) >> 3) * bpp;
1064 1066
1065 /* pm3fb_clear_memory(info, 0);*/ 1067 /* pm3fb_clear_memory(info, 0);*/
1066 pm3fb_clear_colormap(par, 0, 0, 0); 1068 pm3fb_clear_colormap(par, 0, 0, 0);
1067 PM3_WRITE_DAC_REG(par, PM3RD_CursorMode, 0); 1069 PM3_WRITE_DAC_REG(par, PM3RD_CursorMode, 0);
1068 pm3fb_init_engine(info); 1070 pm3fb_init_engine(info);
1069 pm3fb_write_mode(info); 1071 pm3fb_write_mode(info);
1070 return 0; 1072 return 0;
1071 } 1073 }
1072 1074
1073 static int pm3fb_setcolreg(unsigned regno, unsigned red, unsigned green, 1075 static int pm3fb_setcolreg(unsigned regno, unsigned red, unsigned green,
1074 unsigned blue, unsigned transp, 1076 unsigned blue, unsigned transp,
1075 struct fb_info *info) 1077 struct fb_info *info)
1076 { 1078 {
1077 struct pm3_par *par = info->par; 1079 struct pm3_par *par = info->par;
1078 1080
1079 if (regno >= 256) /* no. of hw registers */ 1081 if (regno >= 256) /* no. of hw registers */
1080 return -EINVAL; 1082 return -EINVAL;
1081 1083
1082 /* grayscale works only partially under directcolor */ 1084 /* grayscale works only partially under directcolor */
1083 /* grayscale = 0.30*R + 0.59*G + 0.11*B */ 1085 /* grayscale = 0.30*R + 0.59*G + 0.11*B */
1084 if (info->var.grayscale) 1086 if (info->var.grayscale)
1085 red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8; 1087 red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8;
1086 1088
1087 /* Directcolor: 1089 /* Directcolor:
1088 * var->{color}.offset contains start of bitfield 1090 * var->{color}.offset contains start of bitfield
1089 * var->{color}.length contains length of bitfield 1091 * var->{color}.length contains length of bitfield
1090 * {hardwarespecific} contains width of DAC 1092 * {hardwarespecific} contains width of DAC
1091 * pseudo_palette[X] is programmed to (X << red.offset) | 1093 * pseudo_palette[X] is programmed to (X << red.offset) |
1092 * (X << green.offset) | 1094 * (X << green.offset) |
1093 * (X << blue.offset) 1095 * (X << blue.offset)
1094 * RAMDAC[X] is programmed to (red, green, blue) 1096 * RAMDAC[X] is programmed to (red, green, blue)
1095 * color depth = SUM(var->{color}.length) 1097 * color depth = SUM(var->{color}.length)
1096 * 1098 *
1097 * Pseudocolor: 1099 * Pseudocolor:
1098 * var->{color}.offset is 0 1100 * var->{color}.offset is 0
1099 * var->{color}.length contains width of DAC or the number 1101 * var->{color}.length contains width of DAC or the number
1100 * of unique colors available (color depth) 1102 * of unique colors available (color depth)
1101 * pseudo_palette is not used 1103 * pseudo_palette is not used
1102 * RAMDAC[X] is programmed to (red, green, blue) 1104 * RAMDAC[X] is programmed to (red, green, blue)
1103 * color depth = var->{color}.length 1105 * color depth = var->{color}.length
1104 */ 1106 */
1105 1107
1106 /* 1108 /*
1107 * This is the point where the color is converted to something that 1109 * This is the point where the color is converted to something that
1108 * is acceptable by the hardware. 1110 * is acceptable by the hardware.
1109 */ 1111 */
1110 #define CNVT_TOHW(val, width) ((((val) << (width)) + 0x7FFF - (val)) >> 16) 1112 #define CNVT_TOHW(val, width) ((((val) << (width)) + 0x7FFF - (val)) >> 16)
1111 red = CNVT_TOHW(red, info->var.red.length); 1113 red = CNVT_TOHW(red, info->var.red.length);
1112 green = CNVT_TOHW(green, info->var.green.length); 1114 green = CNVT_TOHW(green, info->var.green.length);
1113 blue = CNVT_TOHW(blue, info->var.blue.length); 1115 blue = CNVT_TOHW(blue, info->var.blue.length);
1114 transp = CNVT_TOHW(transp, info->var.transp.length); 1116 transp = CNVT_TOHW(transp, info->var.transp.length);
1115 #undef CNVT_TOHW 1117 #undef CNVT_TOHW
1116 1118
1117 if (info->fix.visual == FB_VISUAL_TRUECOLOR || 1119 if (info->fix.visual == FB_VISUAL_TRUECOLOR ||
1118 info->fix.visual == FB_VISUAL_DIRECTCOLOR) { 1120 info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
1119 u32 v; 1121 u32 v;
1120 1122
1121 if (regno >= 16) 1123 if (regno >= 16)
1122 return -EINVAL; 1124 return -EINVAL;
1123 1125
1124 v = (red << info->var.red.offset) | 1126 v = (red << info->var.red.offset) |
1125 (green << info->var.green.offset) | 1127 (green << info->var.green.offset) |
1126 (blue << info->var.blue.offset) | 1128 (blue << info->var.blue.offset) |
1127 (transp << info->var.transp.offset); 1129 (transp << info->var.transp.offset);
1128 1130
1129 switch (info->var.bits_per_pixel) { 1131 switch (info->var.bits_per_pixel) {
1130 case 8: 1132 case 8:
1131 break; 1133 break;
1132 case 16: 1134 case 16:
1133 case 32: 1135 case 32:
1134 ((u32 *)(info->pseudo_palette))[regno] = v; 1136 ((u32 *)(info->pseudo_palette))[regno] = v;
1135 break; 1137 break;
1136 } 1138 }
1137 return 0; 1139 return 0;
1138 } else if (info->fix.visual == FB_VISUAL_PSEUDOCOLOR) 1140 } else if (info->fix.visual == FB_VISUAL_PSEUDOCOLOR)
1139 pm3fb_set_color(par, regno, red, green, blue); 1141 pm3fb_set_color(par, regno, red, green, blue);
1140 1142
1141 return 0; 1143 return 0;
1142 } 1144 }
1143 1145
1144 static int pm3fb_pan_display(struct fb_var_screeninfo *var, 1146 static int pm3fb_pan_display(struct fb_var_screeninfo *var,
1145 struct fb_info *info) 1147 struct fb_info *info)
1146 { 1148 {
1147 struct pm3_par *par = info->par; 1149 struct pm3_par *par = info->par;
1148 const u32 xres = (var->xres + 31) & ~31; 1150 const u32 xres = (var->xres + 31) & ~31;
1149 1151
1150 par->base = pm3fb_shift_bpp(var->bits_per_pixel, 1152 par->base = pm3fb_shift_bpp(var->bits_per_pixel,
1151 (var->yoffset * xres) 1153 (var->yoffset * xres)
1152 + var->xoffset); 1154 + var->xoffset);
1153 PM3_WAIT(par, 1); 1155 PM3_WAIT(par, 1);
1154 PM3_WRITE_REG(par, PM3ScreenBase, par->base); 1156 PM3_WRITE_REG(par, PM3ScreenBase, par->base);
1155 return 0; 1157 return 0;
1156 } 1158 }
1157 1159
1158 static int pm3fb_blank(int blank_mode, struct fb_info *info) 1160 static int pm3fb_blank(int blank_mode, struct fb_info *info)
1159 { 1161 {
1160 struct pm3_par *par = info->par; 1162 struct pm3_par *par = info->par;
1161 u32 video = par->video; 1163 u32 video = par->video;
1162 1164
1163 /* 1165 /*
1164 * Oxygen VX1 - it appears that setting PM3VideoControl and 1166 * Oxygen VX1 - it appears that setting PM3VideoControl and
1165 * then PM3RD_SyncControl to the same SYNC settings undoes 1167 * then PM3RD_SyncControl to the same SYNC settings undoes
1166 * any net change - they seem to xor together. Only set the 1168 * any net change - they seem to xor together. Only set the
1167 * sync options in PM3RD_SyncControl. --rmk 1169 * sync options in PM3RD_SyncControl. --rmk
1168 */ 1170 */
1169 video &= ~(PM3VideoControl_HSYNC_MASK | 1171 video &= ~(PM3VideoControl_HSYNC_MASK |
1170 PM3VideoControl_VSYNC_MASK); 1172 PM3VideoControl_VSYNC_MASK);
1171 video |= PM3VideoControl_HSYNC_ACTIVE_HIGH | 1173 video |= PM3VideoControl_HSYNC_ACTIVE_HIGH |
1172 PM3VideoControl_VSYNC_ACTIVE_HIGH; 1174 PM3VideoControl_VSYNC_ACTIVE_HIGH;
1173 1175
1174 switch (blank_mode) { 1176 switch (blank_mode) {
1175 case FB_BLANK_UNBLANK: 1177 case FB_BLANK_UNBLANK:
1176 video |= PM3VideoControl_ENABLE; 1178 video |= PM3VideoControl_ENABLE;
1177 break; 1179 break;
1178 case FB_BLANK_NORMAL: 1180 case FB_BLANK_NORMAL:
1179 video &= ~PM3VideoControl_ENABLE; 1181 video &= ~PM3VideoControl_ENABLE;
1180 break; 1182 break;
1181 case FB_BLANK_HSYNC_SUSPEND: 1183 case FB_BLANK_HSYNC_SUSPEND:
1182 video &= ~(PM3VideoControl_HSYNC_MASK | 1184 video &= ~(PM3VideoControl_HSYNC_MASK |
1183 PM3VideoControl_BLANK_ACTIVE_LOW); 1185 PM3VideoControl_BLANK_ACTIVE_LOW);
1184 break; 1186 break;
1185 case FB_BLANK_VSYNC_SUSPEND: 1187 case FB_BLANK_VSYNC_SUSPEND:
1186 video &= ~(PM3VideoControl_VSYNC_MASK | 1188 video &= ~(PM3VideoControl_VSYNC_MASK |
1187 PM3VideoControl_BLANK_ACTIVE_LOW); 1189 PM3VideoControl_BLANK_ACTIVE_LOW);
1188 break; 1190 break;
1189 case FB_BLANK_POWERDOWN: 1191 case FB_BLANK_POWERDOWN:
1190 video &= ~(PM3VideoControl_HSYNC_MASK | 1192 video &= ~(PM3VideoControl_HSYNC_MASK |
1191 PM3VideoControl_VSYNC_MASK | 1193 PM3VideoControl_VSYNC_MASK |
1192 PM3VideoControl_BLANK_ACTIVE_LOW); 1194 PM3VideoControl_BLANK_ACTIVE_LOW);
1193 break; 1195 break;
1194 default: 1196 default:
1195 DPRINTK("Unsupported blanking %d\n", blank_mode); 1197 DPRINTK("Unsupported blanking %d\n", blank_mode);
1196 return 1; 1198 return 1;
1197 } 1199 }
1198 1200
1199 PM3_WAIT(par, 1); 1201 PM3_WAIT(par, 1);
1200 PM3_WRITE_REG(par, PM3VideoControl, video); 1202 PM3_WRITE_REG(par, PM3VideoControl, video);
1201 return 0; 1203 return 0;
1202 } 1204 }
1203 1205
1204 /* 1206 /*
1205 * Frame buffer operations 1207 * Frame buffer operations
1206 */ 1208 */
1207 1209
1208 static struct fb_ops pm3fb_ops = { 1210 static struct fb_ops pm3fb_ops = {
1209 .owner = THIS_MODULE, 1211 .owner = THIS_MODULE,
1210 .fb_check_var = pm3fb_check_var, 1212 .fb_check_var = pm3fb_check_var,
1211 .fb_set_par = pm3fb_set_par, 1213 .fb_set_par = pm3fb_set_par,
1212 .fb_setcolreg = pm3fb_setcolreg, 1214 .fb_setcolreg = pm3fb_setcolreg,
1213 .fb_pan_display = pm3fb_pan_display, 1215 .fb_pan_display = pm3fb_pan_display,
1214 .fb_fillrect = pm3fb_fillrect, 1216 .fb_fillrect = pm3fb_fillrect,
1215 .fb_copyarea = pm3fb_copyarea, 1217 .fb_copyarea = pm3fb_copyarea,
1216 .fb_imageblit = pm3fb_imageblit, 1218 .fb_imageblit = pm3fb_imageblit,
1217 .fb_blank = pm3fb_blank, 1219 .fb_blank = pm3fb_blank,
1218 .fb_sync = pm3fb_sync, 1220 .fb_sync = pm3fb_sync,
1219 .fb_cursor = pm3fb_cursor, 1221 .fb_cursor = pm3fb_cursor,
1220 }; 1222 };
1221 1223
1222 /* ------------------------------------------------------------------------- */ 1224 /* ------------------------------------------------------------------------- */
1223 1225
1224 /* 1226 /*
1225 * Initialization 1227 * Initialization
1226 */ 1228 */
1227 1229
1228 /* mmio register are already mapped when this function is called */ 1230 /* mmio register are already mapped when this function is called */
1229 /* the pm3fb_fix.smem_start is also set */ 1231 /* the pm3fb_fix.smem_start is also set */
1230 static unsigned long __devinit pm3fb_size_memory(struct pm3_par *par) 1232 static unsigned long __devinit pm3fb_size_memory(struct pm3_par *par)
1231 { 1233 {
1232 unsigned long memsize = 0; 1234 unsigned long memsize = 0;
1233 unsigned long tempBypass, i, temp1, temp2; 1235 unsigned long tempBypass, i, temp1, temp2;
1234 unsigned char __iomem *screen_mem; 1236 unsigned char __iomem *screen_mem;
1235 1237
1236 pm3fb_fix.smem_len = 64 * 1024l * 1024; /* request full aperture size */ 1238 pm3fb_fix.smem_len = 64 * 1024l * 1024; /* request full aperture size */
1237 /* Linear frame buffer - request region and map it. */ 1239 /* Linear frame buffer - request region and map it. */
1238 if (!request_mem_region(pm3fb_fix.smem_start, pm3fb_fix.smem_len, 1240 if (!request_mem_region(pm3fb_fix.smem_start, pm3fb_fix.smem_len,
1239 "pm3fb smem")) { 1241 "pm3fb smem")) {
1240 printk(KERN_WARNING "pm3fb: Can't reserve smem.\n"); 1242 printk(KERN_WARNING "pm3fb: Can't reserve smem.\n");
1241 return 0; 1243 return 0;
1242 } 1244 }
1243 screen_mem = 1245 screen_mem =
1244 ioremap_nocache(pm3fb_fix.smem_start, pm3fb_fix.smem_len); 1246 ioremap_nocache(pm3fb_fix.smem_start, pm3fb_fix.smem_len);
1245 if (!screen_mem) { 1247 if (!screen_mem) {
1246 printk(KERN_WARNING "pm3fb: Can't ioremap smem area.\n"); 1248 printk(KERN_WARNING "pm3fb: Can't ioremap smem area.\n");
1247 release_mem_region(pm3fb_fix.smem_start, pm3fb_fix.smem_len); 1249 release_mem_region(pm3fb_fix.smem_start, pm3fb_fix.smem_len);
1248 return 0; 1250 return 0;
1249 } 1251 }
1250 1252
1251 /* TODO: card-specific stuff, *before* accessing *any* FB memory */ 1253 /* TODO: card-specific stuff, *before* accessing *any* FB memory */
1252 /* For Appian Jeronimo 2000 board second head */ 1254 /* For Appian Jeronimo 2000 board second head */
1253 1255
1254 tempBypass = PM3_READ_REG(par, PM3MemBypassWriteMask); 1256 tempBypass = PM3_READ_REG(par, PM3MemBypassWriteMask);
1255 1257
1256 DPRINTK("PM3MemBypassWriteMask was: 0x%08lx\n", tempBypass); 1258 DPRINTK("PM3MemBypassWriteMask was: 0x%08lx\n", tempBypass);
1257 1259
1258 PM3_WAIT(par, 1); 1260 PM3_WAIT(par, 1);
1259 PM3_WRITE_REG(par, PM3MemBypassWriteMask, 0xFFFFFFFF); 1261 PM3_WRITE_REG(par, PM3MemBypassWriteMask, 0xFFFFFFFF);
1260 1262
1261 /* pm3 split up memory, replicates, and do a lot of 1263 /* pm3 split up memory, replicates, and do a lot of
1262 * nasty stuff IMHO ;-) 1264 * nasty stuff IMHO ;-)
1263 */ 1265 */
1264 for (i = 0; i < 32; i++) { 1266 for (i = 0; i < 32; i++) {
1265 fb_writel(i * 0x00345678, 1267 fb_writel(i * 0x00345678,
1266 (screen_mem + (i * 1048576))); 1268 (screen_mem + (i * 1048576)));
1267 mb(); 1269 mb();
1268 temp1 = fb_readl((screen_mem + (i * 1048576))); 1270 temp1 = fb_readl((screen_mem + (i * 1048576)));
1269 1271
1270 /* Let's check for wrapover, write will fail at 16MB boundary */ 1272 /* Let's check for wrapover, write will fail at 16MB boundary */
1271 if (temp1 == (i * 0x00345678)) 1273 if (temp1 == (i * 0x00345678))
1272 memsize = i; 1274 memsize = i;
1273 else 1275 else
1274 break; 1276 break;
1275 } 1277 }
1276 1278
1277 DPRINTK("First detect pass already got %ld MB\n", memsize + 1); 1279 DPRINTK("First detect pass already got %ld MB\n", memsize + 1);
1278 1280
1279 if (memsize + 1 == i) { 1281 if (memsize + 1 == i) {
1280 for (i = 0; i < 32; i++) { 1282 for (i = 0; i < 32; i++) {
1281 /* Clear first 32MB ; 0 is 0, no need to byteswap */ 1283 /* Clear first 32MB ; 0 is 0, no need to byteswap */
1282 writel(0x0000000, (screen_mem + (i * 1048576))); 1284 writel(0x0000000, (screen_mem + (i * 1048576)));
1283 } 1285 }
1284 wmb(); 1286 wmb();
1285 1287
1286 for (i = 32; i < 64; i++) { 1288 for (i = 32; i < 64; i++) {
1287 fb_writel(i * 0x00345678, 1289 fb_writel(i * 0x00345678,
1288 (screen_mem + (i * 1048576))); 1290 (screen_mem + (i * 1048576)));
1289 mb(); 1291 mb();
1290 temp1 = 1292 temp1 =
1291 fb_readl((screen_mem + (i * 1048576))); 1293 fb_readl((screen_mem + (i * 1048576)));
1292 temp2 = 1294 temp2 =
1293 fb_readl((screen_mem + ((i - 32) * 1048576))); 1295 fb_readl((screen_mem + ((i - 32) * 1048576)));
1294 /* different value, different RAM... */ 1296 /* different value, different RAM... */
1295 if ((temp1 == (i * 0x00345678)) && (temp2 == 0)) 1297 if ((temp1 == (i * 0x00345678)) && (temp2 == 0))
1296 memsize = i; 1298 memsize = i;
1297 else 1299 else
1298 break; 1300 break;
1299 } 1301 }
1300 } 1302 }
1301 DPRINTK("Second detect pass got %ld MB\n", memsize + 1); 1303 DPRINTK("Second detect pass got %ld MB\n", memsize + 1);
1302 1304
1303 PM3_WAIT(par, 1); 1305 PM3_WAIT(par, 1);
1304 PM3_WRITE_REG(par, PM3MemBypassWriteMask, tempBypass); 1306 PM3_WRITE_REG(par, PM3MemBypassWriteMask, tempBypass);
1305 1307
1306 iounmap(screen_mem); 1308 iounmap(screen_mem);
1307 release_mem_region(pm3fb_fix.smem_start, pm3fb_fix.smem_len); 1309 release_mem_region(pm3fb_fix.smem_start, pm3fb_fix.smem_len);
1308 memsize = 1048576 * (memsize + 1); 1310 memsize = 1048576 * (memsize + 1);
1309 1311
1310 DPRINTK("Returning 0x%08lx bytes\n", memsize); 1312 DPRINTK("Returning 0x%08lx bytes\n", memsize);
1311 1313
1312 return memsize; 1314 return memsize;
1313 } 1315 }
1314 1316
1315 static int __devinit pm3fb_probe(struct pci_dev *dev, 1317 static int __devinit pm3fb_probe(struct pci_dev *dev,
1316 const struct pci_device_id *ent) 1318 const struct pci_device_id *ent)
1317 { 1319 {
1318 struct fb_info *info; 1320 struct fb_info *info;
1319 struct pm3_par *par; 1321 struct pm3_par *par;
1320 struct device *device = &dev->dev; /* for pci drivers */ 1322 struct device *device = &dev->dev; /* for pci drivers */
1321 int err; 1323 int err;
1322 int retval = -ENXIO; 1324 int retval = -ENXIO;
1323 1325
1324 err = pci_enable_device(dev); 1326 err = pci_enable_device(dev);
1325 if (err) { 1327 if (err) {
1326 printk(KERN_WARNING "pm3fb: Can't enable PCI dev: %d\n", err); 1328 printk(KERN_WARNING "pm3fb: Can't enable PCI dev: %d\n", err);
1327 return err; 1329 return err;
1328 } 1330 }
1329 /* 1331 /*
1330 * Dynamically allocate info and par 1332 * Dynamically allocate info and par
1331 */ 1333 */
1332 info = framebuffer_alloc(sizeof(struct pm3_par), device); 1334 info = framebuffer_alloc(sizeof(struct pm3_par), device);
1333 1335
1334 if (!info) 1336 if (!info)
1335 return -ENOMEM; 1337 return -ENOMEM;
1336 par = info->par; 1338 par = info->par;
1337 1339
1338 /* 1340 /*
1339 * Here we set the screen_base to the virtual memory address 1341 * Here we set the screen_base to the virtual memory address
1340 * for the framebuffer. 1342 * for the framebuffer.
1341 */ 1343 */
1342 pm3fb_fix.mmio_start = pci_resource_start(dev, 0); 1344 pm3fb_fix.mmio_start = pci_resource_start(dev, 0);
1343 pm3fb_fix.mmio_len = PM3_REGS_SIZE; 1345 pm3fb_fix.mmio_len = PM3_REGS_SIZE;
1344 #if defined(__BIG_ENDIAN) 1346 #if defined(__BIG_ENDIAN)
1345 pm3fb_fix.mmio_start += PM3_REGS_SIZE; 1347 pm3fb_fix.mmio_start += PM3_REGS_SIZE;
1346 DPRINTK("Adjusting register base for big-endian.\n"); 1348 DPRINTK("Adjusting register base for big-endian.\n");
1347 #endif 1349 #endif
1348 1350
1349 /* Registers - request region and map it. */ 1351 /* Registers - request region and map it. */
1350 if (!request_mem_region(pm3fb_fix.mmio_start, pm3fb_fix.mmio_len, 1352 if (!request_mem_region(pm3fb_fix.mmio_start, pm3fb_fix.mmio_len,
1351 "pm3fb regbase")) { 1353 "pm3fb regbase")) {
1352 printk(KERN_WARNING "pm3fb: Can't reserve regbase.\n"); 1354 printk(KERN_WARNING "pm3fb: Can't reserve regbase.\n");
1353 goto err_exit_neither; 1355 goto err_exit_neither;
1354 } 1356 }
1355 par->v_regs = 1357 par->v_regs =
1356 ioremap_nocache(pm3fb_fix.mmio_start, pm3fb_fix.mmio_len); 1358 ioremap_nocache(pm3fb_fix.mmio_start, pm3fb_fix.mmio_len);
1357 if (!par->v_regs) { 1359 if (!par->v_regs) {
1358 printk(KERN_WARNING "pm3fb: Can't remap %s register area.\n", 1360 printk(KERN_WARNING "pm3fb: Can't remap %s register area.\n",
1359 pm3fb_fix.id); 1361 pm3fb_fix.id);
1360 release_mem_region(pm3fb_fix.mmio_start, pm3fb_fix.mmio_len); 1362 release_mem_region(pm3fb_fix.mmio_start, pm3fb_fix.mmio_len);
1361 goto err_exit_neither; 1363 goto err_exit_neither;
1362 } 1364 }
1363 1365
1364 /* Linear frame buffer - request region and map it. */ 1366 /* Linear frame buffer - request region and map it. */
1365 pm3fb_fix.smem_start = pci_resource_start(dev, 1); 1367 pm3fb_fix.smem_start = pci_resource_start(dev, 1);
1366 pm3fb_fix.smem_len = pm3fb_size_memory(par); 1368 pm3fb_fix.smem_len = pm3fb_size_memory(par);
1367 if (!pm3fb_fix.smem_len) { 1369 if (!pm3fb_fix.smem_len) {
1368 printk(KERN_WARNING "pm3fb: Can't find memory on board.\n"); 1370 printk(KERN_WARNING "pm3fb: Can't find memory on board.\n");
1369 goto err_exit_mmio; 1371 goto err_exit_mmio;
1370 } 1372 }
1371 if (!request_mem_region(pm3fb_fix.smem_start, pm3fb_fix.smem_len, 1373 if (!request_mem_region(pm3fb_fix.smem_start, pm3fb_fix.smem_len,
1372 "pm3fb smem")) { 1374 "pm3fb smem")) {
1373 printk(KERN_WARNING "pm3fb: Can't reserve smem.\n"); 1375 printk(KERN_WARNING "pm3fb: Can't reserve smem.\n");
1374 goto err_exit_mmio; 1376 goto err_exit_mmio;
1375 } 1377 }
1376 info->screen_base = 1378 info->screen_base =
1377 ioremap_nocache(pm3fb_fix.smem_start, pm3fb_fix.smem_len); 1379 ioremap_nocache(pm3fb_fix.smem_start, pm3fb_fix.smem_len);
1378 if (!info->screen_base) { 1380 if (!info->screen_base) {
1379 printk(KERN_WARNING "pm3fb: Can't ioremap smem area.\n"); 1381 printk(KERN_WARNING "pm3fb: Can't ioremap smem area.\n");
1380 release_mem_region(pm3fb_fix.smem_start, pm3fb_fix.smem_len); 1382 release_mem_region(pm3fb_fix.smem_start, pm3fb_fix.smem_len);
1381 goto err_exit_mmio; 1383 goto err_exit_mmio;
1382 } 1384 }
1383 info->screen_size = pm3fb_fix.smem_len; 1385 info->screen_size = pm3fb_fix.smem_len;
1384 1386
1385 #ifdef CONFIG_MTRR 1387 #ifdef CONFIG_MTRR
1386 if (!nomtrr) 1388 if (!nomtrr)
1387 par->mtrr_handle = mtrr_add(pm3fb_fix.smem_start, 1389 par->mtrr_handle = mtrr_add(pm3fb_fix.smem_start,
1388 pm3fb_fix.smem_len, 1390 pm3fb_fix.smem_len,
1389 MTRR_TYPE_WRCOMB, 1); 1391 MTRR_TYPE_WRCOMB, 1);
1390 #endif 1392 #endif
1391 info->fbops = &pm3fb_ops; 1393 info->fbops = &pm3fb_ops;
1392 1394
1393 par->video = PM3_READ_REG(par, PM3VideoControl); 1395 par->video = PM3_READ_REG(par, PM3VideoControl);
1394 1396
1395 info->fix = pm3fb_fix; 1397 info->fix = pm3fb_fix;
1396 info->pseudo_palette = par->palette; 1398 info->pseudo_palette = par->palette;
1397 info->flags = FBINFO_DEFAULT | 1399 info->flags = FBINFO_DEFAULT |
1398 FBINFO_HWACCEL_XPAN | 1400 FBINFO_HWACCEL_XPAN |
1399 FBINFO_HWACCEL_YPAN | 1401 FBINFO_HWACCEL_YPAN |
1400 FBINFO_HWACCEL_COPYAREA | 1402 FBINFO_HWACCEL_COPYAREA |
1401 FBINFO_HWACCEL_IMAGEBLIT | 1403 FBINFO_HWACCEL_IMAGEBLIT |
1402 FBINFO_HWACCEL_FILLRECT; 1404 FBINFO_HWACCEL_FILLRECT;
1403 1405
1404 if (noaccel) { 1406 if (noaccel) {
1405 printk(KERN_DEBUG "disabling acceleration\n"); 1407 printk(KERN_DEBUG "disabling acceleration\n");
1406 info->flags |= FBINFO_HWACCEL_DISABLED; 1408 info->flags |= FBINFO_HWACCEL_DISABLED;
1407 } 1409 }
1408 info->pixmap.addr = kmalloc(PM3_PIXMAP_SIZE, GFP_KERNEL); 1410 info->pixmap.addr = kmalloc(PM3_PIXMAP_SIZE, GFP_KERNEL);
1409 if (!info->pixmap.addr) { 1411 if (!info->pixmap.addr) {
1410 retval = -ENOMEM; 1412 retval = -ENOMEM;
1411 goto err_exit_pixmap; 1413 goto err_exit_pixmap;
1412 } 1414 }
1413 info->pixmap.size = PM3_PIXMAP_SIZE; 1415 info->pixmap.size = PM3_PIXMAP_SIZE;
1414 info->pixmap.buf_align = 4; 1416 info->pixmap.buf_align = 4;
1415 info->pixmap.scan_align = 4; 1417 info->pixmap.scan_align = 4;
1416 info->pixmap.access_align = 32; 1418 info->pixmap.access_align = 32;
1417 info->pixmap.flags = FB_PIXMAP_SYSTEM; 1419 info->pixmap.flags = FB_PIXMAP_SYSTEM;
1418 1420
1419 /* 1421 /*
1420 * This should give a reasonable default video mode. The following is 1422 * This should give a reasonable default video mode. The following is
1421 * done when we can set a video mode. 1423 * done when we can set a video mode.
1422 */ 1424 */
1423 if (!mode_option) 1425 if (!mode_option)
1424 mode_option = "640x480@60"; 1426 mode_option = "640x480@60";
1425 1427
1426 retval = fb_find_mode(&info->var, info, mode_option, NULL, 0, NULL, 8); 1428 retval = fb_find_mode(&info->var, info, mode_option, NULL, 0, NULL, 8);
1427 1429
1428 if (!retval || retval == 4) { 1430 if (!retval || retval == 4) {
1429 retval = -EINVAL; 1431 retval = -EINVAL;
1430 goto err_exit_both; 1432 goto err_exit_both;
1431 } 1433 }
1432 1434
1433 if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) { 1435 if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) {
1434 retval = -ENOMEM; 1436 retval = -ENOMEM;
1435 goto err_exit_both; 1437 goto err_exit_both;
1436 } 1438 }
1437 1439
1438 /* 1440 /*
1439 * For drivers that can... 1441 * For drivers that can...
1440 */ 1442 */
1441 pm3fb_check_var(&info->var, info); 1443 pm3fb_check_var(&info->var, info);
1442 1444
1443 if (register_framebuffer(info) < 0) { 1445 if (register_framebuffer(info) < 0) {
1444 retval = -EINVAL; 1446 retval = -EINVAL;
1445 goto err_exit_all; 1447 goto err_exit_all;
1446 } 1448 }
1447 printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node, 1449 printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node,
1448 info->fix.id); 1450 info->fix.id);
1449 pci_set_drvdata(dev, info); 1451 pci_set_drvdata(dev, info);
1450 return 0; 1452 return 0;
1451 1453
1452 err_exit_all: 1454 err_exit_all:
1453 fb_dealloc_cmap(&info->cmap); 1455 fb_dealloc_cmap(&info->cmap);
1454 err_exit_both: 1456 err_exit_both:
1455 kfree(info->pixmap.addr); 1457 kfree(info->pixmap.addr);
1456 err_exit_pixmap: 1458 err_exit_pixmap:
1457 iounmap(info->screen_base); 1459 iounmap(info->screen_base);
1458 release_mem_region(pm3fb_fix.smem_start, pm3fb_fix.smem_len); 1460 release_mem_region(pm3fb_fix.smem_start, pm3fb_fix.smem_len);
1459 err_exit_mmio: 1461 err_exit_mmio:
1460 iounmap(par->v_regs); 1462 iounmap(par->v_regs);
1461 release_mem_region(pm3fb_fix.mmio_start, pm3fb_fix.mmio_len); 1463 release_mem_region(pm3fb_fix.mmio_start, pm3fb_fix.mmio_len);
1462 err_exit_neither: 1464 err_exit_neither:
1463 framebuffer_release(info); 1465 framebuffer_release(info);
1464 return retval; 1466 return retval;
1465 } 1467 }
1466 1468
1467 /* 1469 /*
1468 * Cleanup 1470 * Cleanup
1469 */ 1471 */
1470 static void __devexit pm3fb_remove(struct pci_dev *dev) 1472 static void __devexit pm3fb_remove(struct pci_dev *dev)
1471 { 1473 {
1472 struct fb_info *info = pci_get_drvdata(dev); 1474 struct fb_info *info = pci_get_drvdata(dev);
1473 1475
1474 if (info) { 1476 if (info) {
1475 struct fb_fix_screeninfo *fix = &info->fix; 1477 struct fb_fix_screeninfo *fix = &info->fix;
1476 struct pm3_par *par = info->par; 1478 struct pm3_par *par = info->par;
1477 1479
1478 unregister_framebuffer(info); 1480 unregister_framebuffer(info);
1479 fb_dealloc_cmap(&info->cmap); 1481 fb_dealloc_cmap(&info->cmap);
1480 1482
1481 #ifdef CONFIG_MTRR 1483 #ifdef CONFIG_MTRR
1482 if (par->mtrr_handle >= 0) 1484 if (par->mtrr_handle >= 0)
1483 mtrr_del(par->mtrr_handle, info->fix.smem_start, 1485 mtrr_del(par->mtrr_handle, info->fix.smem_start,
1484 info->fix.smem_len); 1486 info->fix.smem_len);
1485 #endif /* CONFIG_MTRR */ 1487 #endif /* CONFIG_MTRR */
1486 iounmap(info->screen_base); 1488 iounmap(info->screen_base);
1487 release_mem_region(fix->smem_start, fix->smem_len); 1489 release_mem_region(fix->smem_start, fix->smem_len);
1488 iounmap(par->v_regs); 1490 iounmap(par->v_regs);
1489 release_mem_region(fix->mmio_start, fix->mmio_len); 1491 release_mem_region(fix->mmio_start, fix->mmio_len);
1490 1492
1491 pci_set_drvdata(dev, NULL); 1493 pci_set_drvdata(dev, NULL);
1492 kfree(info->pixmap.addr); 1494 kfree(info->pixmap.addr);
1493 framebuffer_release(info); 1495 framebuffer_release(info);
1494 } 1496 }
1495 } 1497 }
1496 1498
1497 static struct pci_device_id pm3fb_id_table[] = { 1499 static struct pci_device_id pm3fb_id_table[] = {
1498 { PCI_VENDOR_ID_3DLABS, 0x0a, 1500 { PCI_VENDOR_ID_3DLABS, 0x0a,
1499 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, 1501 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
1500 { 0, } 1502 { 0, }
1501 }; 1503 };
1502 1504
1503 /* For PCI drivers */ 1505 /* For PCI drivers */
1504 static struct pci_driver pm3fb_driver = { 1506 static struct pci_driver pm3fb_driver = {
1505 .name = "pm3fb", 1507 .name = "pm3fb",
1506 .id_table = pm3fb_id_table, 1508 .id_table = pm3fb_id_table,
1507 .probe = pm3fb_probe, 1509 .probe = pm3fb_probe,
1508 .remove = __devexit_p(pm3fb_remove), 1510 .remove = __devexit_p(pm3fb_remove),
1509 }; 1511 };
1510 1512
1511 MODULE_DEVICE_TABLE(pci, pm3fb_id_table); 1513 MODULE_DEVICE_TABLE(pci, pm3fb_id_table);
1512 1514
1513 #ifndef MODULE 1515 #ifndef MODULE
1514 /* 1516 /*
1515 * Setup 1517 * Setup
1516 */ 1518 */
1517 1519
1518 /* 1520 /*
1519 * Only necessary if your driver takes special options, 1521 * Only necessary if your driver takes special options,
1520 * otherwise we fall back on the generic fb_setup(). 1522 * otherwise we fall back on the generic fb_setup().
1521 */ 1523 */
1522 static int __init pm3fb_setup(char *options) 1524 static int __init pm3fb_setup(char *options)
1523 { 1525 {
1524 char *this_opt; 1526 char *this_opt;
1525 1527
1526 /* Parse user speficied options (`video=pm3fb:') */ 1528 /* Parse user speficied options (`video=pm3fb:') */
1527 if (!options || !*options) 1529 if (!options || !*options)
1528 return 0; 1530 return 0;
1529 1531
1530 while ((this_opt = strsep(&options, ",")) != NULL) { 1532 while ((this_opt = strsep(&options, ",")) != NULL) {
1531 if (!*this_opt) 1533 if (!*this_opt)
1532 continue; 1534 continue;
1533 else if (!strncmp(this_opt, "noaccel", 7)) 1535 else if (!strncmp(this_opt, "noaccel", 7))
1534 noaccel = 1; 1536 noaccel = 1;
1535 else if (!strncmp(this_opt, "hwcursor=", 9)) 1537 else if (!strncmp(this_opt, "hwcursor=", 9))
1536 hwcursor = simple_strtoul(this_opt + 9, NULL, 0); 1538 hwcursor = simple_strtoul(this_opt + 9, NULL, 0);
1537 #ifdef CONFIG_MTRR 1539 #ifdef CONFIG_MTRR
1538 else if (!strncmp(this_opt, "nomtrr", 6)) 1540 else if (!strncmp(this_opt, "nomtrr", 6))
1539 nomtrr = 1; 1541 nomtrr = 1;
1540 #endif 1542 #endif
1541 else 1543 else
1542 mode_option = this_opt; 1544 mode_option = this_opt;
1543 } 1545 }
1544 return 0; 1546 return 0;
1545 } 1547 }
1546 #endif /* MODULE */ 1548 #endif /* MODULE */
1547 1549
1548 static int __init pm3fb_init(void) 1550 static int __init pm3fb_init(void)
1549 { 1551 {
1550 /* 1552 /*
1551 * For kernel boot options (in 'video=pm3fb:<options>' format) 1553 * For kernel boot options (in 'video=pm3fb:<options>' format)
1552 */ 1554 */
1553 #ifndef MODULE 1555 #ifndef MODULE
1554 char *option = NULL; 1556 char *option = NULL;
1555 1557
1556 if (fb_get_options("pm3fb", &option)) 1558 if (fb_get_options("pm3fb", &option))
1557 return -ENODEV; 1559 return -ENODEV;
1558 pm3fb_setup(option); 1560 pm3fb_setup(option);
1559 #endif 1561 #endif
1560 1562
1561 return pci_register_driver(&pm3fb_driver); 1563 return pci_register_driver(&pm3fb_driver);
1562 } 1564 }
1563 1565
1564 #ifdef MODULE 1566 #ifdef MODULE
1565 static void __exit pm3fb_exit(void) 1567 static void __exit pm3fb_exit(void)
1566 { 1568 {
1567 pci_unregister_driver(&pm3fb_driver); 1569 pci_unregister_driver(&pm3fb_driver);
1568 } 1570 }
1569 1571
1570 module_exit(pm3fb_exit); 1572 module_exit(pm3fb_exit);
1571 #endif 1573 #endif
1572 module_init(pm3fb_init); 1574 module_init(pm3fb_init);
1573 1575
1574 module_param(mode_option, charp, 0); 1576 module_param(mode_option, charp, 0);
1575 MODULE_PARM_DESC(mode_option, "Initial video mode e.g. '648x480-8@60'"); 1577 MODULE_PARM_DESC(mode_option, "Initial video mode e.g. '648x480-8@60'");
1576 module_param(noaccel, bool, 0); 1578 module_param(noaccel, bool, 0);
1577 MODULE_PARM_DESC(noaccel, "Disable acceleration"); 1579 MODULE_PARM_DESC(noaccel, "Disable acceleration");
1578 module_param(hwcursor, int, 0644); 1580 module_param(hwcursor, int, 0644);
1579 MODULE_PARM_DESC(hwcursor, "Enable hardware cursor " 1581 MODULE_PARM_DESC(hwcursor, "Enable hardware cursor "
1580 "(1=enable, 0=disable, default=1)"); 1582 "(1=enable, 0=disable, default=1)");
1581 #ifdef CONFIG_MTRR 1583 #ifdef CONFIG_MTRR
1582 module_param(nomtrr, bool, 0); 1584 module_param(nomtrr, bool, 0);
1583 MODULE_PARM_DESC(nomtrr, "Disable MTRR support (0 or 1=disabled) (default=0)"); 1585 MODULE_PARM_DESC(nomtrr, "Disable MTRR support (0 or 1=disabled) (default=0)");
1584 #endif 1586 #endif
1585 1587
1586 MODULE_DESCRIPTION("Permedia3 framebuffer device driver"); 1588 MODULE_DESCRIPTION("Permedia3 framebuffer device driver");
1587 MODULE_LICENSE("GPL"); 1589 MODULE_LICENSE("GPL");
1588 1590