diff options
Diffstat (limited to 'drivers/video/macfb.c')
-rw-r--r-- | drivers/video/macfb.c | 736 |
1 files changed, 340 insertions, 396 deletions
diff --git a/drivers/video/macfb.c b/drivers/video/macfb.c index d66887e8cbb1..43207cc6cc19 100644 --- a/drivers/video/macfb.c +++ b/drivers/video/macfb.c | |||
@@ -1,29 +1,33 @@ | |||
1 | /* macfb.c: Generic framebuffer for Macs whose colourmaps/modes we | 1 | /* |
2 | don't know how to set */ | 2 | * macfb.c: Generic framebuffer for Macs whose colourmaps/modes we |
3 | 3 | * don't know how to set. | |
4 | /* (c) 1999 David Huggins-Daines <dhd@debian.org> | 4 | * |
5 | 5 | * (c) 1999 David Huggins-Daines <dhd@debian.org> | |
6 | Primarily based on vesafb.c, by Gerd Knorr | 6 | * |
7 | (c) 1998 Gerd Knorr <kraxel@cs.tu-berlin.de> | 7 | * Primarily based on vesafb.c, by Gerd Knorr |
8 | 8 | * (c) 1998 Gerd Knorr <kraxel@cs.tu-berlin.de> | |
9 | Also uses information and code from: | 9 | * |
10 | 10 | * Also uses information and code from: | |
11 | The original macfb.c from Linux/mac68k 2.0, by Alan Cox, Juergen | 11 | * |
12 | Mellinger, Mikael Forselius, Michael Schmitz, and others. | 12 | * The original macfb.c from Linux/mac68k 2.0, by Alan Cox, Juergen |
13 | 13 | * Mellinger, Mikael Forselius, Michael Schmitz, and others. | |
14 | valkyriefb.c, by Martin Costabel, Kevin Schoedel, Barry Nathan, Dan | 14 | * |
15 | Jacobowitz, Paul Mackerras, Fabio Riccardi, and Geert Uytterhoeven. | 15 | * valkyriefb.c, by Martin Costabel, Kevin Schoedel, Barry Nathan, Dan |
16 | 16 | * Jacobowitz, Paul Mackerras, Fabio Riccardi, and Geert Uytterhoeven. | |
17 | This code is free software. You may copy, modify, and distribute | 17 | * |
18 | it subject to the terms and conditions of the GNU General Public | 18 | * The VideoToolbox "Bugs" web page at |
19 | License, version 2, or any later version, at your convenience. */ | 19 | * http://rajsky.psych.nyu.edu/Tips/VideoBugs.html |
20 | * | ||
21 | * This code is free software. You may copy, modify, and distribute | ||
22 | * it subject to the terms and conditions of the GNU General Public | ||
23 | * License, version 2, or any later version, at your convenience. | ||
24 | */ | ||
20 | 25 | ||
21 | #include <linux/module.h> | 26 | #include <linux/module.h> |
22 | #include <linux/kernel.h> | 27 | #include <linux/kernel.h> |
23 | #include <linux/errno.h> | 28 | #include <linux/errno.h> |
24 | #include <linux/string.h> | 29 | #include <linux/string.h> |
25 | #include <linux/mm.h> | 30 | #include <linux/mm.h> |
26 | #include <linux/slab.h> | ||
27 | #include <linux/delay.h> | 31 | #include <linux/delay.h> |
28 | #include <linux/nubus.h> | 32 | #include <linux/nubus.h> |
29 | #include <linux/init.h> | 33 | #include <linux/init.h> |
@@ -31,9 +35,6 @@ | |||
31 | 35 | ||
32 | #include <asm/setup.h> | 36 | #include <asm/setup.h> |
33 | #include <asm/bootinfo.h> | 37 | #include <asm/bootinfo.h> |
34 | #include <asm/uaccess.h> | ||
35 | #include <asm/pgtable.h> | ||
36 | #include <asm/irq.h> | ||
37 | #include <asm/macintosh.h> | 38 | #include <asm/macintosh.h> |
38 | #include <asm/io.h> | 39 | #include <asm/io.h> |
39 | 40 | ||
@@ -44,7 +45,7 @@ | |||
44 | #define DAFB_BASE 0xf9800200 | 45 | #define DAFB_BASE 0xf9800200 |
45 | 46 | ||
46 | /* Address for the built-in Civic framebuffer in Quadra AVs */ | 47 | /* Address for the built-in Civic framebuffer in Quadra AVs */ |
47 | #define CIVIC_BASE 0x50f30800 /* Only tested on 660AV! */ | 48 | #define CIVIC_BASE 0x50f30800 |
48 | 49 | ||
49 | /* GSC (Gray Scale Controller) base address */ | 50 | /* GSC (Gray Scale Controller) base address */ |
50 | #define GSC_BASE 0x50F20000 | 51 | #define GSC_BASE 0x50F20000 |
@@ -52,37 +53,9 @@ | |||
52 | /* CSC (Color Screen Controller) base address */ | 53 | /* CSC (Color Screen Controller) base address */ |
53 | #define CSC_BASE 0x50F20000 | 54 | #define CSC_BASE 0x50F20000 |
54 | 55 | ||
55 | static int (*macfb_setpalette) (unsigned int regno, unsigned int red, | 56 | static int (*macfb_setpalette)(unsigned int regno, unsigned int red, |
56 | unsigned int green, unsigned int blue, | 57 | unsigned int green, unsigned int blue, |
57 | struct fb_info *info) = NULL; | 58 | struct fb_info *info); |
58 | static int valkyrie_setpalette (unsigned int regno, unsigned int red, | ||
59 | unsigned int green, unsigned int blue, | ||
60 | struct fb_info *info); | ||
61 | static int dafb_setpalette (unsigned int regno, unsigned int red, | ||
62 | unsigned int green, unsigned int blue, | ||
63 | struct fb_info *fb_info); | ||
64 | static int rbv_setpalette (unsigned int regno, unsigned int red, | ||
65 | unsigned int green, unsigned int blue, | ||
66 | struct fb_info *fb_info); | ||
67 | static int mdc_setpalette (unsigned int regno, unsigned int red, | ||
68 | unsigned int green, unsigned int blue, | ||
69 | struct fb_info *fb_info); | ||
70 | static int toby_setpalette (unsigned int regno, unsigned int red, | ||
71 | unsigned int green, unsigned int blue, | ||
72 | struct fb_info *fb_info); | ||
73 | static int civic_setpalette (unsigned int regno, unsigned int red, | ||
74 | unsigned int green, unsigned int blue, | ||
75 | struct fb_info *fb_info); | ||
76 | static int csc_setpalette (unsigned int regno, unsigned int red, | ||
77 | unsigned int green, unsigned int blue, | ||
78 | struct fb_info *fb_info); | ||
79 | |||
80 | static struct { | ||
81 | unsigned char addr; | ||
82 | /* Note: word-aligned */ | ||
83 | char pad[3]; | ||
84 | unsigned char lut; | ||
85 | } __iomem *valkyrie_cmap_regs; | ||
86 | 59 | ||
87 | static struct { | 60 | static struct { |
88 | unsigned char addr; | 61 | unsigned char addr; |
@@ -116,15 +89,15 @@ static struct { | |||
116 | } __iomem *civic_cmap_regs; | 89 | } __iomem *civic_cmap_regs; |
117 | 90 | ||
118 | static struct { | 91 | static struct { |
119 | char pad1[0x40]; | 92 | char pad1[0x40]; |
120 | unsigned char clut_waddr; /* 0x40 */ | 93 | unsigned char clut_waddr; /* 0x40 */ |
121 | char pad2; | 94 | char pad2; |
122 | unsigned char clut_data; /* 0x42 */ | 95 | unsigned char clut_data; /* 0x42 */ |
123 | char pad3[0x3]; | 96 | char pad3[0x3]; |
124 | unsigned char clut_raddr; /* 0x46 */ | 97 | unsigned char clut_raddr; /* 0x46 */ |
125 | } __iomem *csc_cmap_regs; | 98 | } __iomem *csc_cmap_regs; |
126 | 99 | ||
127 | /* We will leave these the way they are for the time being */ | 100 | /* The registers in these structs are in NuBus slot space */ |
128 | struct mdc_cmap_regs { | 101 | struct mdc_cmap_regs { |
129 | char pad1[0x200200]; | 102 | char pad1[0x200200]; |
130 | unsigned char addr; | 103 | unsigned char addr; |
@@ -145,13 +118,10 @@ struct jet_cmap_regs { | |||
145 | unsigned char lut; | 118 | unsigned char lut; |
146 | }; | 119 | }; |
147 | 120 | ||
148 | #define PIXEL_TO_MM(a) (((a)*10)/28) /* width in mm at 72 dpi */ | 121 | #define PIXEL_TO_MM(a) (((a)*10)/28) /* width in mm at 72 dpi */ |
149 | |||
150 | /* mode */ | ||
151 | static int video_slot = 0; | ||
152 | 122 | ||
153 | static struct fb_var_screeninfo macfb_defined = { | 123 | static struct fb_var_screeninfo macfb_defined = { |
154 | .bits_per_pixel = 8, | 124 | .bits_per_pixel = 8, |
155 | .activate = FB_ACTIVATE_NOW, | 125 | .activate = FB_ACTIVATE_NOW, |
156 | .width = -1, | 126 | .width = -1, |
157 | .height = -1, | 127 | .height = -1, |
@@ -167,181 +137,152 @@ static struct fb_fix_screeninfo macfb_fix = { | |||
167 | .accel = FB_ACCEL_NONE, | 137 | .accel = FB_ACCEL_NONE, |
168 | }; | 138 | }; |
169 | 139 | ||
140 | static void *slot_addr; | ||
170 | static struct fb_info fb_info; | 141 | static struct fb_info fb_info; |
171 | static u32 pseudo_palette[16]; | 142 | static u32 pseudo_palette[16]; |
172 | static int inverse = 0; | 143 | static int inverse; |
173 | static int vidtest = 0; | 144 | static int vidtest; |
174 | 145 | ||
175 | static int valkyrie_setpalette (unsigned int regno, unsigned int red, | 146 | /* |
176 | unsigned int green, unsigned int blue, | 147 | * Unlike the Valkyrie, the DAFB cannot set individual colormap |
177 | struct fb_info *info) | 148 | * registers. Therefore, we do what the MacOS driver does (no |
178 | { | 149 | * kidding!) and simply set them one by one until we hit the one we |
179 | unsigned long flags; | 150 | * want. |
180 | 151 | */ | |
181 | red >>= 8; | 152 | static int dafb_setpalette(unsigned int regno, unsigned int red, |
182 | green >>= 8; | 153 | unsigned int green, unsigned int blue, |
183 | blue >>= 8; | 154 | struct fb_info *info) |
184 | |||
185 | local_irq_save(flags); | ||
186 | |||
187 | /* tell clut which address to fill */ | ||
188 | nubus_writeb(regno, &valkyrie_cmap_regs->addr); | ||
189 | nop(); | ||
190 | |||
191 | /* send one color channel at a time */ | ||
192 | nubus_writeb(red, &valkyrie_cmap_regs->lut); | ||
193 | nop(); | ||
194 | nubus_writeb(green, &valkyrie_cmap_regs->lut); | ||
195 | nop(); | ||
196 | nubus_writeb(blue, &valkyrie_cmap_regs->lut); | ||
197 | |||
198 | local_irq_restore(flags); | ||
199 | return 0; | ||
200 | } | ||
201 | |||
202 | /* Unlike the Valkyrie, the DAFB cannot set individual colormap | ||
203 | registers. Therefore, we do what the MacOS driver does (no | ||
204 | kidding!) and simply set them one by one until we hit the one we | ||
205 | want. */ | ||
206 | static int dafb_setpalette (unsigned int regno, unsigned int red, | ||
207 | unsigned int green, unsigned int blue, | ||
208 | struct fb_info *info) | ||
209 | { | 155 | { |
210 | /* FIXME: really, really need to use ioremap() here, | ||
211 | phys_to_virt() doesn't work anymore */ | ||
212 | static int lastreg = -1; | 156 | static int lastreg = -1; |
213 | unsigned long flags; | 157 | unsigned long flags; |
214 | |||
215 | red >>= 8; | ||
216 | green >>= 8; | ||
217 | blue >>= 8; | ||
218 | 158 | ||
219 | local_irq_save(flags); | 159 | local_irq_save(flags); |
220 | 160 | ||
221 | /* fbdev will set an entire colourmap, but X won't. Hopefully | 161 | /* |
222 | this should accommodate both of them */ | 162 | * fbdev will set an entire colourmap, but X won't. Hopefully |
223 | if (regno != lastreg+1) { | 163 | * this should accommodate both of them |
164 | */ | ||
165 | if (regno != lastreg + 1) { | ||
224 | int i; | 166 | int i; |
225 | 167 | ||
226 | /* Stab in the dark trying to reset the CLUT pointer */ | 168 | /* Stab in the dark trying to reset the CLUT pointer */ |
227 | nubus_writel(0, &dafb_cmap_regs->reset); | 169 | nubus_writel(0, &dafb_cmap_regs->reset); |
228 | nop(); | 170 | nop(); |
229 | 171 | ||
230 | /* Loop until we get to the register we want */ | 172 | /* Loop until we get to the register we want */ |
231 | for (i = 0; i < regno; i++) { | 173 | for (i = 0; i < regno; i++) { |
232 | nubus_writeb(info->cmap.red[i] >> 8, &dafb_cmap_regs->lut); | 174 | nubus_writeb(info->cmap.red[i] >> 8, |
175 | &dafb_cmap_regs->lut); | ||
233 | nop(); | 176 | nop(); |
234 | nubus_writeb(info->cmap.green[i] >> 8, &dafb_cmap_regs->lut); | 177 | nubus_writeb(info->cmap.green[i] >> 8, |
178 | &dafb_cmap_regs->lut); | ||
235 | nop(); | 179 | nop(); |
236 | nubus_writeb(info->cmap.blue[i] >> 8, &dafb_cmap_regs->lut); | 180 | nubus_writeb(info->cmap.blue[i] >> 8, |
181 | &dafb_cmap_regs->lut); | ||
237 | nop(); | 182 | nop(); |
238 | } | 183 | } |
239 | } | 184 | } |
240 | 185 | ||
241 | nubus_writeb(red, &dafb_cmap_regs->lut); | 186 | nubus_writeb(red, &dafb_cmap_regs->lut); |
242 | nop(); | 187 | nop(); |
243 | nubus_writeb(green, &dafb_cmap_regs->lut); | 188 | nubus_writeb(green, &dafb_cmap_regs->lut); |
244 | nop(); | 189 | nop(); |
245 | nubus_writeb(blue, &dafb_cmap_regs->lut); | 190 | nubus_writeb(blue, &dafb_cmap_regs->lut); |
246 | 191 | ||
247 | local_irq_restore(flags); | 192 | local_irq_restore(flags); |
248 | lastreg = regno; | 193 | lastreg = regno; |
249 | return 0; | 194 | return 0; |
250 | } | 195 | } |
251 | 196 | ||
252 | /* V8 and Brazil seem to use the same DAC. Sonora does as well. */ | 197 | /* V8 and Brazil seem to use the same DAC. Sonora does as well. */ |
253 | static int v8_brazil_setpalette (unsigned int regno, unsigned int red, | 198 | static int v8_brazil_setpalette(unsigned int regno, unsigned int red, |
254 | unsigned int green, unsigned int blue, | 199 | unsigned int green, unsigned int blue, |
255 | struct fb_info *info) | 200 | struct fb_info *info) |
256 | { | 201 | { |
257 | unsigned int bpp = info->var.bits_per_pixel; | 202 | unsigned int bpp = info->var.bits_per_pixel; |
258 | unsigned char _red =red>>8; | ||
259 | unsigned char _green=green>>8; | ||
260 | unsigned char _blue =blue>>8; | ||
261 | unsigned char _regno; | ||
262 | unsigned long flags; | 203 | unsigned long flags; |
263 | 204 | ||
264 | if (bpp > 8) return 1; /* failsafe */ | 205 | if (bpp > 8) |
206 | return 1; /* failsafe */ | ||
265 | 207 | ||
266 | local_irq_save(flags); | 208 | local_irq_save(flags); |
267 | 209 | ||
268 | /* On these chips, the CLUT register numbers are spread out | 210 | /* On these chips, the CLUT register numbers are spread out |
269 | across the register space. Thus: | 211 | * across the register space. Thus: |
270 | 212 | * In 8bpp, all regnos are valid. | |
271 | In 8bpp, all regnos are valid. | 213 | * In 4bpp, the regnos are 0x0f, 0x1f, 0x2f, etc, etc |
272 | 214 | * In 2bpp, the regnos are 0x3f, 0x7f, 0xbf, 0xff | |
273 | In 4bpp, the regnos are 0x0f, 0x1f, 0x2f, etc, etc | 215 | */ |
274 | 216 | regno = (regno << (8 - bpp)) | (0xFF >> bpp); | |
275 | In 2bpp, the regnos are 0x3f, 0x7f, 0xbf, 0xff */ | 217 | nubus_writeb(regno, &v8_brazil_cmap_regs->addr); |
276 | _regno = (regno << (8 - bpp)) | (0xFF >> bpp); | 218 | nop(); |
277 | nubus_writeb(_regno, &v8_brazil_cmap_regs->addr); nop(); | ||
278 | 219 | ||
279 | /* send one color channel at a time */ | 220 | /* send one color channel at a time */ |
280 | nubus_writeb(_red, &v8_brazil_cmap_regs->lut); nop(); | 221 | nubus_writeb(red, &v8_brazil_cmap_regs->lut); |
281 | nubus_writeb(_green, &v8_brazil_cmap_regs->lut); nop(); | 222 | nop(); |
282 | nubus_writeb(_blue, &v8_brazil_cmap_regs->lut); | 223 | nubus_writeb(green, &v8_brazil_cmap_regs->lut); |
224 | nop(); | ||
225 | nubus_writeb(blue, &v8_brazil_cmap_regs->lut); | ||
283 | 226 | ||
284 | local_irq_restore(flags); | 227 | local_irq_restore(flags); |
285 | return 0; | 228 | return 0; |
286 | } | 229 | } |
287 | 230 | ||
288 | static int rbv_setpalette (unsigned int regno, unsigned int red, | 231 | /* RAM-Based Video */ |
289 | unsigned int green, unsigned int blue, | 232 | static int rbv_setpalette(unsigned int regno, unsigned int red, |
290 | struct fb_info *info) | 233 | unsigned int green, unsigned int blue, |
234 | struct fb_info *info) | ||
291 | { | 235 | { |
292 | /* use MSBs */ | ||
293 | unsigned char _red =red>>8; | ||
294 | unsigned char _green=green>>8; | ||
295 | unsigned char _blue =blue>>8; | ||
296 | unsigned char _regno; | ||
297 | unsigned long flags; | 236 | unsigned long flags; |
298 | 237 | ||
299 | if (info->var.bits_per_pixel > 8) return 1; /* failsafe */ | 238 | if (info->var.bits_per_pixel > 8) |
239 | return 1; /* failsafe */ | ||
300 | 240 | ||
301 | local_irq_save(flags); | 241 | local_irq_save(flags); |
302 | 242 | ||
303 | /* From the VideoToolbox driver. Seems to be saying that | 243 | /* From the VideoToolbox driver. Seems to be saying that |
304 | * regno #254 and #255 are the important ones for 1-bit color, | 244 | * regno #254 and #255 are the important ones for 1-bit color, |
305 | * regno #252-255 are the important ones for 2-bit color, etc. | 245 | * regno #252-255 are the important ones for 2-bit color, etc. |
306 | */ | 246 | */ |
307 | _regno = regno + (256-(1 << info->var.bits_per_pixel)); | 247 | regno += 256 - (1 << info->var.bits_per_pixel); |
308 | 248 | ||
309 | /* reset clut? (VideoToolbox sez "not necessary") */ | 249 | /* reset clut? (VideoToolbox sez "not necessary") */ |
310 | nubus_writeb(0xFF, &rbv_cmap_regs->cntl); nop(); | 250 | nubus_writeb(0xFF, &rbv_cmap_regs->cntl); |
311 | 251 | nop(); | |
252 | |||
312 | /* tell clut which address to use. */ | 253 | /* tell clut which address to use. */ |
313 | nubus_writeb(_regno, &rbv_cmap_regs->addr); nop(); | 254 | nubus_writeb(regno, &rbv_cmap_regs->addr); |
314 | 255 | nop(); | |
256 | |||
315 | /* send one color channel at a time. */ | 257 | /* send one color channel at a time. */ |
316 | nubus_writeb(_red, &rbv_cmap_regs->lut); nop(); | 258 | nubus_writeb(red, &rbv_cmap_regs->lut); |
317 | nubus_writeb(_green, &rbv_cmap_regs->lut); nop(); | 259 | nop(); |
318 | nubus_writeb(_blue, &rbv_cmap_regs->lut); | 260 | nubus_writeb(green, &rbv_cmap_regs->lut); |
319 | 261 | nop(); | |
320 | local_irq_restore(flags); /* done. */ | 262 | nubus_writeb(blue, &rbv_cmap_regs->lut); |
263 | |||
264 | local_irq_restore(flags); | ||
321 | return 0; | 265 | return 0; |
322 | } | 266 | } |
323 | 267 | ||
324 | /* Macintosh Display Card (8x24) */ | 268 | /* Macintosh Display Card (8*24) */ |
325 | static int mdc_setpalette(unsigned int regno, unsigned int red, | 269 | static int mdc_setpalette(unsigned int regno, unsigned int red, |
326 | unsigned int green, unsigned int blue, | 270 | unsigned int green, unsigned int blue, |
327 | struct fb_info *info) | 271 | struct fb_info *info) |
328 | { | 272 | { |
329 | volatile struct mdc_cmap_regs *cmap_regs = | 273 | struct mdc_cmap_regs *cmap_regs = slot_addr; |
330 | nubus_slot_addr(video_slot); | ||
331 | /* use MSBs */ | ||
332 | unsigned char _red =red>>8; | ||
333 | unsigned char _green=green>>8; | ||
334 | unsigned char _blue =blue>>8; | ||
335 | unsigned char _regno=regno; | ||
336 | unsigned long flags; | 274 | unsigned long flags; |
337 | 275 | ||
338 | local_irq_save(flags); | 276 | local_irq_save(flags); |
339 | 277 | ||
340 | /* the nop's are there to order writes. */ | 278 | /* the nop's are there to order writes. */ |
341 | nubus_writeb(_regno, &cmap_regs->addr); nop(); | 279 | nubus_writeb(regno, &cmap_regs->addr); |
342 | nubus_writeb(_red, &cmap_regs->lut); nop(); | 280 | nop(); |
343 | nubus_writeb(_green, &cmap_regs->lut); nop(); | 281 | nubus_writeb(red, &cmap_regs->lut); |
344 | nubus_writeb(_blue, &cmap_regs->lut); | 282 | nop(); |
283 | nubus_writeb(green, &cmap_regs->lut); | ||
284 | nop(); | ||
285 | nubus_writeb(blue, &cmap_regs->lut); | ||
345 | 286 | ||
346 | local_irq_restore(flags); | 287 | local_irq_restore(flags); |
347 | return 0; | 288 | return 0; |
@@ -350,24 +291,26 @@ static int mdc_setpalette(unsigned int regno, unsigned int red, | |||
350 | /* Toby frame buffer */ | 291 | /* Toby frame buffer */ |
351 | static int toby_setpalette(unsigned int regno, unsigned int red, | 292 | static int toby_setpalette(unsigned int regno, unsigned int red, |
352 | unsigned int green, unsigned int blue, | 293 | unsigned int green, unsigned int blue, |
353 | struct fb_info *info) | 294 | struct fb_info *info) |
354 | { | 295 | { |
355 | volatile struct toby_cmap_regs *cmap_regs = | 296 | struct toby_cmap_regs *cmap_regs = slot_addr; |
356 | nubus_slot_addr(video_slot); | ||
357 | unsigned int bpp = info->var.bits_per_pixel; | 297 | unsigned int bpp = info->var.bits_per_pixel; |
358 | /* use MSBs */ | ||
359 | unsigned char _red =~(red>>8); | ||
360 | unsigned char _green=~(green>>8); | ||
361 | unsigned char _blue =~(blue>>8); | ||
362 | unsigned char _regno = (regno << (8 - bpp)) | (0xFF >> bpp); | ||
363 | unsigned long flags; | 298 | unsigned long flags; |
364 | 299 | ||
300 | red = ~red; | ||
301 | green = ~green; | ||
302 | blue = ~blue; | ||
303 | regno = (regno << (8 - bpp)) | (0xFF >> bpp); | ||
304 | |||
365 | local_irq_save(flags); | 305 | local_irq_save(flags); |
366 | 306 | ||
367 | nubus_writeb(_regno, &cmap_regs->addr); nop(); | 307 | nubus_writeb(regno, &cmap_regs->addr); |
368 | nubus_writeb(_red, &cmap_regs->lut); nop(); | 308 | nop(); |
369 | nubus_writeb(_green, &cmap_regs->lut); nop(); | 309 | nubus_writeb(red, &cmap_regs->lut); |
370 | nubus_writeb(_blue, &cmap_regs->lut); | 310 | nop(); |
311 | nubus_writeb(green, &cmap_regs->lut); | ||
312 | nop(); | ||
313 | nubus_writeb(blue, &cmap_regs->lut); | ||
371 | 314 | ||
372 | local_irq_restore(flags); | 315 | local_irq_restore(flags); |
373 | return 0; | 316 | return 0; |
@@ -378,20 +321,18 @@ static int jet_setpalette(unsigned int regno, unsigned int red, | |||
378 | unsigned int green, unsigned int blue, | 321 | unsigned int green, unsigned int blue, |
379 | struct fb_info *info) | 322 | struct fb_info *info) |
380 | { | 323 | { |
381 | volatile struct jet_cmap_regs *cmap_regs = | 324 | struct jet_cmap_regs *cmap_regs = slot_addr; |
382 | nubus_slot_addr(video_slot); | ||
383 | /* use MSBs */ | ||
384 | unsigned char _red = (red>>8); | ||
385 | unsigned char _green = (green>>8); | ||
386 | unsigned char _blue = (blue>>8); | ||
387 | unsigned long flags; | 325 | unsigned long flags; |
388 | 326 | ||
389 | local_irq_save(flags); | 327 | local_irq_save(flags); |
390 | 328 | ||
391 | nubus_writeb(regno, &cmap_regs->addr); nop(); | 329 | nubus_writeb(regno, &cmap_regs->addr); |
392 | nubus_writeb(_red, &cmap_regs->lut); nop(); | 330 | nop(); |
393 | nubus_writeb(_green, &cmap_regs->lut); nop(); | 331 | nubus_writeb(red, &cmap_regs->lut); |
394 | nubus_writeb(_blue, &cmap_regs->lut); | 332 | nop(); |
333 | nubus_writeb(green, &cmap_regs->lut); | ||
334 | nop(); | ||
335 | nubus_writeb(blue, &cmap_regs->lut); | ||
395 | 336 | ||
396 | local_irq_restore(flags); | 337 | local_irq_restore(flags); |
397 | return 0; | 338 | return 0; |
@@ -400,53 +341,27 @@ static int jet_setpalette(unsigned int regno, unsigned int red, | |||
400 | /* | 341 | /* |
401 | * Civic framebuffer -- Quadra AV built-in video. A chip | 342 | * Civic framebuffer -- Quadra AV built-in video. A chip |
402 | * called Sebastian holds the actual color palettes, and | 343 | * called Sebastian holds the actual color palettes, and |
403 | * apparently, there are two different banks of 512K RAM | 344 | * apparently, there are two different banks of 512K RAM |
404 | * which can act as separate framebuffers for doing video | 345 | * which can act as separate framebuffers for doing video |
405 | * input and viewing the screen at the same time! The 840AV | 346 | * input and viewing the screen at the same time! The 840AV |
406 | * Can add another 1MB RAM to give the two framebuffers | 347 | * Can add another 1MB RAM to give the two framebuffers |
407 | * 1MB RAM apiece. | 348 | * 1MB RAM apiece. |
408 | * | ||
409 | * FIXME: this doesn't seem to work anymore. | ||
410 | */ | 349 | */ |
411 | static int civic_setpalette (unsigned int regno, unsigned int red, | 350 | static int civic_setpalette(unsigned int regno, unsigned int red, |
412 | unsigned int green, unsigned int blue, | 351 | unsigned int green, unsigned int blue, |
413 | struct fb_info *info) | 352 | struct fb_info *info) |
414 | { | 353 | { |
415 | static int lastreg = -1; | ||
416 | unsigned long flags; | 354 | unsigned long flags; |
417 | int clut_status; | 355 | int clut_status; |
418 | 356 | ||
419 | if (info->var.bits_per_pixel > 8) return 1; /* failsafe */ | 357 | if (info->var.bits_per_pixel > 8) |
420 | 358 | return 1; /* failsafe */ | |
421 | red >>= 8; | ||
422 | green >>= 8; | ||
423 | blue >>= 8; | ||
424 | 359 | ||
425 | local_irq_save(flags); | 360 | local_irq_save(flags); |
426 | |||
427 | /* | ||
428 | * Set the register address | ||
429 | */ | ||
430 | nubus_writeb(regno, &civic_cmap_regs->addr); nop(); | ||
431 | 361 | ||
432 | /* | 362 | /* Set the register address */ |
433 | * Wait for VBL interrupt here; | 363 | nubus_writeb(regno, &civic_cmap_regs->addr); |
434 | * They're usually not enabled from Penguin, so we won't check | 364 | nop(); |
435 | */ | ||
436 | #if 0 | ||
437 | { | ||
438 | #define CIVIC_VBL_OFFSET 0x120 | ||
439 | volatile unsigned long *vbl = nubus_readl(civic_cmap_regs->vbl_addr + CIVIC_VBL_OFFSET); | ||
440 | /* do interrupt setup stuff here? */ | ||
441 | *vbl = 0L; nop(); /* clear */ | ||
442 | *vbl = 1L; nop(); /* set */ | ||
443 | while (*vbl != 0L) /* wait for next vbl */ | ||
444 | { | ||
445 | usleep(10); /* needed? */ | ||
446 | } | ||
447 | /* do interrupt shutdown stuff here? */ | ||
448 | } | ||
449 | #endif | ||
450 | 365 | ||
451 | /* | 366 | /* |
452 | * Grab a status word and do some checking; | 367 | * Grab a status word and do some checking; |
@@ -459,39 +374,52 @@ static int civic_setpalette (unsigned int regno, unsigned int red, | |||
459 | #if 0 | 374 | #if 0 |
460 | if ((clut_status & 0x000D) != 0) | 375 | if ((clut_status & 0x000D) != 0) |
461 | { | 376 | { |
462 | nubus_writeb(0x00, &civic_cmap_regs->lut); nop(); | 377 | nubus_writeb(0x00, &civic_cmap_regs->lut); |
463 | nubus_writeb(0x00, &civic_cmap_regs->lut); nop(); | 378 | nop(); |
379 | nubus_writeb(0x00, &civic_cmap_regs->lut); | ||
380 | nop(); | ||
464 | } | 381 | } |
465 | #endif | 382 | #endif |
466 | 383 | ||
467 | nubus_writeb( red, &civic_cmap_regs->lut); nop(); | 384 | nubus_writeb(red, &civic_cmap_regs->lut); |
468 | nubus_writeb(green, &civic_cmap_regs->lut); nop(); | 385 | nop(); |
469 | nubus_writeb( blue, &civic_cmap_regs->lut); nop(); | 386 | nubus_writeb(green, &civic_cmap_regs->lut); |
470 | nubus_writeb( 0x00, &civic_cmap_regs->lut); nop(); | 387 | nop(); |
388 | nubus_writeb(blue, &civic_cmap_regs->lut); | ||
389 | nop(); | ||
390 | nubus_writeb(0x00, &civic_cmap_regs->lut); | ||
471 | } | 391 | } |
472 | else | 392 | else |
473 | { | 393 | { |
474 | unsigned char junk; | 394 | unsigned char junk; |
475 | 395 | ||
476 | junk = nubus_readb(&civic_cmap_regs->lut); nop(); | 396 | junk = nubus_readb(&civic_cmap_regs->lut); |
477 | junk = nubus_readb(&civic_cmap_regs->lut); nop(); | 397 | nop(); |
478 | junk = nubus_readb(&civic_cmap_regs->lut); nop(); | 398 | junk = nubus_readb(&civic_cmap_regs->lut); |
479 | junk = nubus_readb(&civic_cmap_regs->lut); nop(); | 399 | nop(); |
400 | junk = nubus_readb(&civic_cmap_regs->lut); | ||
401 | nop(); | ||
402 | junk = nubus_readb(&civic_cmap_regs->lut); | ||
403 | nop(); | ||
480 | 404 | ||
481 | if ((clut_status & 0x000D) != 0) | 405 | if ((clut_status & 0x000D) != 0) |
482 | { | 406 | { |
483 | nubus_writeb(0x00, &civic_cmap_regs->lut); nop(); | 407 | nubus_writeb(0x00, &civic_cmap_regs->lut); |
484 | nubus_writeb(0x00, &civic_cmap_regs->lut); nop(); | 408 | nop(); |
409 | nubus_writeb(0x00, &civic_cmap_regs->lut); | ||
410 | nop(); | ||
485 | } | 411 | } |
486 | 412 | ||
487 | nubus_writeb( red, &civic_cmap_regs->lut); nop(); | 413 | nubus_writeb(red, &civic_cmap_regs->lut); |
488 | nubus_writeb(green, &civic_cmap_regs->lut); nop(); | 414 | nop(); |
489 | nubus_writeb( blue, &civic_cmap_regs->lut); nop(); | 415 | nubus_writeb(green, &civic_cmap_regs->lut); |
490 | nubus_writeb( junk, &civic_cmap_regs->lut); nop(); | 416 | nop(); |
417 | nubus_writeb(blue, &civic_cmap_regs->lut); | ||
418 | nop(); | ||
419 | nubus_writeb(junk, &civic_cmap_regs->lut); | ||
491 | } | 420 | } |
492 | 421 | ||
493 | local_irq_restore(flags); | 422 | local_irq_restore(flags); |
494 | lastreg = regno; | ||
495 | return 0; | 423 | return 0; |
496 | } | 424 | } |
497 | 425 | ||
@@ -500,16 +428,21 @@ static int civic_setpalette (unsigned int regno, unsigned int red, | |||
500 | * (and the 5300 too, but that's a PowerMac). This function | 428 | * (and the 5300 too, but that's a PowerMac). This function |
501 | * brought to you in part by the ECSC driver for MkLinux. | 429 | * brought to you in part by the ECSC driver for MkLinux. |
502 | */ | 430 | */ |
503 | 431 | static int csc_setpalette(unsigned int regno, unsigned int red, | |
504 | static int csc_setpalette (unsigned int regno, unsigned int red, | 432 | unsigned int green, unsigned int blue, |
505 | unsigned int green, unsigned int blue, | 433 | struct fb_info *info) |
506 | struct fb_info *info) | ||
507 | { | 434 | { |
508 | mdelay(1); | 435 | unsigned long flags; |
436 | |||
437 | local_irq_save(flags); | ||
438 | |||
439 | udelay(1); /* mklinux on PB 5300 waits for 260 ns */ | ||
509 | nubus_writeb(regno, &csc_cmap_regs->clut_waddr); | 440 | nubus_writeb(regno, &csc_cmap_regs->clut_waddr); |
510 | nubus_writeb(red, &csc_cmap_regs->clut_data); | 441 | nubus_writeb(red, &csc_cmap_regs->clut_data); |
511 | nubus_writeb(green, &csc_cmap_regs->clut_data); | 442 | nubus_writeb(green, &csc_cmap_regs->clut_data); |
512 | nubus_writeb(blue, &csc_cmap_regs->clut_data); | 443 | nubus_writeb(blue, &csc_cmap_regs->clut_data); |
444 | |||
445 | local_irq_restore(flags); | ||
513 | return 0; | 446 | return 0; |
514 | } | 447 | } |
515 | 448 | ||
@@ -518,10 +451,10 @@ static int macfb_setcolreg(unsigned regno, unsigned red, unsigned green, | |||
518 | struct fb_info *fb_info) | 451 | struct fb_info *fb_info) |
519 | { | 452 | { |
520 | /* | 453 | /* |
521 | * Set a single color register. The values supplied are | 454 | * Set a single color register. The values supplied are |
522 | * already rounded down to the hardware's capabilities | 455 | * already rounded down to the hardware's capabilities |
523 | * (according to the entries in the `var' structure). Return | 456 | * (according to the entries in the `var' structure). |
524 | * != 0 for invalid regno. | 457 | * Return non-zero for invalid regno. |
525 | */ | 458 | */ |
526 | 459 | ||
527 | if (regno >= fb_info->cmap.len) | 460 | if (regno >= fb_info->cmap.len) |
@@ -536,8 +469,8 @@ static int macfb_setcolreg(unsigned regno, unsigned red, unsigned green, | |||
536 | case 4: | 469 | case 4: |
537 | case 8: | 470 | case 8: |
538 | if (macfb_setpalette) | 471 | if (macfb_setpalette) |
539 | macfb_setpalette(regno, red, green, blue, | 472 | macfb_setpalette(regno, red >> 8, green >> 8, |
540 | fb_info); | 473 | blue >> 8, fb_info); |
541 | else | 474 | else |
542 | return 1; | 475 | return 1; |
543 | break; | 476 | break; |
@@ -555,28 +488,22 @@ static int macfb_setcolreg(unsigned regno, unsigned red, unsigned green, | |||
555 | } else { | 488 | } else { |
556 | /* 0:5:6:5 */ | 489 | /* 0:5:6:5 */ |
557 | ((u32*) (fb_info->pseudo_palette))[regno] = | 490 | ((u32*) (fb_info->pseudo_palette))[regno] = |
558 | ((red & 0xf800) ) | | 491 | ((red & 0xf800) >> 0) | |
559 | ((green & 0xfc00) >> 5) | | 492 | ((green & 0xfc00) >> 5) | |
560 | ((blue & 0xf800) >> 11); | 493 | ((blue & 0xf800) >> 11); |
561 | } | 494 | } |
562 | break; | 495 | break; |
563 | /* I'm pretty sure that one or the other of these | 496 | /* |
564 | doesn't exist on 68k Macs */ | 497 | * 24-bit colour almost doesn't exist on 68k Macs -- |
498 | * http://support.apple.com/kb/TA28634 (Old Article: 10992) | ||
499 | */ | ||
565 | case 24: | 500 | case 24: |
566 | red >>= 8; | ||
567 | green >>= 8; | ||
568 | blue >>= 8; | ||
569 | ((u32 *)(fb_info->pseudo_palette))[regno] = | ||
570 | (red << fb_info->var.red.offset) | | ||
571 | (green << fb_info->var.green.offset) | | ||
572 | (blue << fb_info->var.blue.offset); | ||
573 | break; | ||
574 | case 32: | 501 | case 32: |
575 | red >>= 8; | 502 | red >>= 8; |
576 | green >>= 8; | 503 | green >>= 8; |
577 | blue >>= 8; | 504 | blue >>= 8; |
578 | ((u32 *)(fb_info->pseudo_palette))[regno] = | 505 | ((u32 *)(fb_info->pseudo_palette))[regno] = |
579 | (red << fb_info->var.red.offset) | | 506 | (red << fb_info->var.red.offset) | |
580 | (green << fb_info->var.green.offset) | | 507 | (green << fb_info->var.green.offset) | |
581 | (blue << fb_info->var.blue.offset); | 508 | (blue << fb_info->var.blue.offset); |
582 | break; | 509 | break; |
@@ -597,25 +524,24 @@ static struct fb_ops macfb_ops = { | |||
597 | static void __init macfb_setup(char *options) | 524 | static void __init macfb_setup(char *options) |
598 | { | 525 | { |
599 | char *this_opt; | 526 | char *this_opt; |
600 | 527 | ||
601 | if (!options || !*options) | 528 | if (!options || !*options) |
602 | return; | 529 | return; |
603 | 530 | ||
604 | while ((this_opt = strsep(&options, ",")) != NULL) { | 531 | while ((this_opt = strsep(&options, ",")) != NULL) { |
605 | if (!*this_opt) continue; | 532 | if (!*this_opt) |
606 | 533 | continue; | |
607 | if (! strcmp(this_opt, "inverse")) | 534 | |
608 | inverse=1; | 535 | if (!strcmp(this_opt, "inverse")) |
609 | /* This means "turn on experimental CLUT code" */ | 536 | inverse = 1; |
610 | else if (!strcmp(this_opt, "vidtest")) | 537 | else |
611 | vidtest=1; | 538 | if (!strcmp(this_opt, "vidtest")) |
539 | vidtest = 1; /* enable experimental CLUT code */ | ||
612 | } | 540 | } |
613 | } | 541 | } |
614 | 542 | ||
615 | static void __init iounmap_macfb(void) | 543 | static void __init iounmap_macfb(void) |
616 | { | 544 | { |
617 | if (valkyrie_cmap_regs) | ||
618 | iounmap(valkyrie_cmap_regs); | ||
619 | if (dafb_cmap_regs) | 545 | if (dafb_cmap_regs) |
620 | iounmap(dafb_cmap_regs); | 546 | iounmap(dafb_cmap_regs); |
621 | if (v8_brazil_cmap_regs) | 547 | if (v8_brazil_cmap_regs) |
@@ -642,48 +568,55 @@ static int __init macfb_init(void) | |||
642 | if (!MACH_IS_MAC) | 568 | if (!MACH_IS_MAC) |
643 | return -ENODEV; | 569 | return -ENODEV; |
644 | 570 | ||
645 | /* There can only be one internal video controller anyway so | 571 | if (mac_bi_data.id == MAC_MODEL_Q630 || |
646 | we're not too worried about this */ | 572 | mac_bi_data.id == MAC_MODEL_P588) |
573 | return -ENODEV; /* See valkyriefb.c */ | ||
574 | |||
647 | macfb_defined.xres = mac_bi_data.dimensions & 0xFFFF; | 575 | macfb_defined.xres = mac_bi_data.dimensions & 0xFFFF; |
648 | macfb_defined.yres = mac_bi_data.dimensions >> 16; | 576 | macfb_defined.yres = mac_bi_data.dimensions >> 16; |
649 | macfb_defined.bits_per_pixel = mac_bi_data.videodepth; | 577 | macfb_defined.bits_per_pixel = mac_bi_data.videodepth; |
578 | |||
650 | macfb_fix.line_length = mac_bi_data.videorow; | 579 | macfb_fix.line_length = mac_bi_data.videorow; |
651 | macfb_fix.smem_len = macfb_fix.line_length * macfb_defined.yres; | 580 | macfb_fix.smem_len = macfb_fix.line_length * macfb_defined.yres; |
652 | /* Note: physical address (since 2.1.127) */ | 581 | /* Note: physical address (since 2.1.127) */ |
653 | macfb_fix.smem_start = mac_bi_data.videoaddr; | 582 | macfb_fix.smem_start = mac_bi_data.videoaddr; |
654 | /* This is actually redundant with the initial mappings. | 583 | |
655 | However, there are some non-obvious aspects to the way | ||
656 | those mappings are set up, so this is in fact the safest | ||
657 | way to ensure that this driver will work on every possible | ||
658 | Mac */ | ||
659 | fb_info.screen_base = ioremap(mac_bi_data.videoaddr, macfb_fix.smem_len); | ||
660 | |||
661 | printk("macfb: framebuffer at 0x%08lx, mapped to 0x%p, size %dk\n", | ||
662 | macfb_fix.smem_start, fb_info.screen_base, macfb_fix.smem_len/1024); | ||
663 | printk("macfb: mode is %dx%dx%d, linelength=%d\n", | ||
664 | macfb_defined.xres, macfb_defined.yres, macfb_defined.bits_per_pixel, macfb_fix.line_length); | ||
665 | |||
666 | /* | 584 | /* |
667 | * Fill in the available video resolution | 585 | * This is actually redundant with the initial mappings. |
586 | * However, there are some non-obvious aspects to the way | ||
587 | * those mappings are set up, so this is in fact the safest | ||
588 | * way to ensure that this driver will work on every possible Mac | ||
668 | */ | 589 | */ |
669 | 590 | fb_info.screen_base = ioremap(mac_bi_data.videoaddr, | |
670 | macfb_defined.xres_virtual = macfb_defined.xres; | 591 | macfb_fix.smem_len); |
671 | macfb_defined.yres_virtual = macfb_defined.yres; | 592 | if (!fb_info.screen_base) |
672 | macfb_defined.height = PIXEL_TO_MM(macfb_defined.yres); | 593 | return -ENODEV; |
673 | macfb_defined.width = PIXEL_TO_MM(macfb_defined.xres); | ||
674 | 594 | ||
675 | printk("macfb: scrolling: redraw\n"); | 595 | printk("macfb: framebuffer at 0x%08lx, mapped to 0x%p, size %dk\n", |
596 | macfb_fix.smem_start, fb_info.screen_base, | ||
597 | macfb_fix.smem_len / 1024); | ||
598 | printk("macfb: mode is %dx%dx%d, linelength=%d\n", | ||
599 | macfb_defined.xres, macfb_defined.yres, | ||
600 | macfb_defined.bits_per_pixel, macfb_fix.line_length); | ||
601 | |||
602 | /* Fill in the available video resolution */ | ||
603 | macfb_defined.xres_virtual = macfb_defined.xres; | ||
676 | macfb_defined.yres_virtual = macfb_defined.yres; | 604 | macfb_defined.yres_virtual = macfb_defined.yres; |
605 | macfb_defined.height = PIXEL_TO_MM(macfb_defined.yres); | ||
606 | macfb_defined.width = PIXEL_TO_MM(macfb_defined.xres); | ||
677 | 607 | ||
678 | /* some dummy values for timing to make fbset happy */ | 608 | /* Some dummy values for timing to make fbset happy */ |
679 | macfb_defined.pixclock = 10000000 / macfb_defined.xres * 1000 / macfb_defined.yres; | 609 | macfb_defined.pixclock = 10000000 / macfb_defined.xres * |
610 | 1000 / macfb_defined.yres; | ||
680 | macfb_defined.left_margin = (macfb_defined.xres / 8) & 0xf8; | 611 | macfb_defined.left_margin = (macfb_defined.xres / 8) & 0xf8; |
681 | macfb_defined.hsync_len = (macfb_defined.xres / 8) & 0xf8; | 612 | macfb_defined.hsync_len = (macfb_defined.xres / 8) & 0xf8; |
682 | 613 | ||
683 | switch (macfb_defined.bits_per_pixel) { | 614 | switch (macfb_defined.bits_per_pixel) { |
684 | case 1: | 615 | case 1: |
685 | /* XXX: I think this will catch any program that tries | 616 | /* |
686 | to do FBIO_PUTCMAP when the visual is monochrome */ | 617 | * XXX: I think this will catch any program that tries |
618 | * to do FBIO_PUTCMAP when the visual is monochrome. | ||
619 | */ | ||
687 | macfb_defined.red.length = macfb_defined.bits_per_pixel; | 620 | macfb_defined.red.length = macfb_defined.bits_per_pixel; |
688 | macfb_defined.green.length = macfb_defined.bits_per_pixel; | 621 | macfb_defined.green.length = macfb_defined.bits_per_pixel; |
689 | macfb_defined.blue.length = macfb_defined.bits_per_pixel; | 622 | macfb_defined.blue.length = macfb_defined.bits_per_pixel; |
@@ -708,53 +641,52 @@ static int __init macfb_init(void) | |||
708 | macfb_defined.green.length = 5; | 641 | macfb_defined.green.length = 5; |
709 | macfb_defined.blue.offset = 0; | 642 | macfb_defined.blue.offset = 0; |
710 | macfb_defined.blue.length = 5; | 643 | macfb_defined.blue.length = 5; |
711 | printk("macfb: directcolor: " | ||
712 | "size=1:5:5:5, shift=15:10:5:0\n"); | ||
713 | video_cmap_len = 16; | 644 | video_cmap_len = 16; |
714 | /* Should actually be FB_VISUAL_DIRECTCOLOR, but this | 645 | /* |
715 | works too */ | 646 | * Should actually be FB_VISUAL_DIRECTCOLOR, but this |
647 | * works too | ||
648 | */ | ||
716 | macfb_fix.visual = FB_VISUAL_TRUECOLOR; | 649 | macfb_fix.visual = FB_VISUAL_TRUECOLOR; |
717 | break; | 650 | break; |
718 | case 24: | 651 | case 24: |
719 | case 32: | 652 | case 32: |
720 | /* XXX: have to test these... can any 68k Macs | ||
721 | actually do this on internal video? */ | ||
722 | macfb_defined.red.offset = 16; | 653 | macfb_defined.red.offset = 16; |
723 | macfb_defined.red.length = 8; | 654 | macfb_defined.red.length = 8; |
724 | macfb_defined.green.offset = 8; | 655 | macfb_defined.green.offset = 8; |
725 | macfb_defined.green.length = 8; | 656 | macfb_defined.green.length = 8; |
726 | macfb_defined.blue.offset = 0; | 657 | macfb_defined.blue.offset = 0; |
727 | macfb_defined.blue.length = 8; | 658 | macfb_defined.blue.length = 8; |
728 | printk("macfb: truecolor: " | ||
729 | "size=0:8:8:8, shift=0:16:8:0\n"); | ||
730 | video_cmap_len = 16; | 659 | video_cmap_len = 16; |
731 | macfb_fix.visual = FB_VISUAL_TRUECOLOR; | 660 | macfb_fix.visual = FB_VISUAL_TRUECOLOR; |
661 | break; | ||
732 | default: | 662 | default: |
733 | video_cmap_len = 0; | 663 | video_cmap_len = 0; |
734 | macfb_fix.visual = FB_VISUAL_MONO01; | 664 | macfb_fix.visual = FB_VISUAL_MONO01; |
735 | printk("macfb: unknown or unsupported bit depth: %d\n", macfb_defined.bits_per_pixel); | 665 | printk("macfb: unknown or unsupported bit depth: %d\n", |
666 | macfb_defined.bits_per_pixel); | ||
736 | break; | 667 | break; |
737 | } | 668 | } |
738 | 669 | ||
739 | /* Hardware dependent stuff */ | 670 | /* |
740 | /* We take a wild guess that if the video physical address is | 671 | * We take a wild guess that if the video physical address is |
741 | * in nubus slot space, that the nubus card is driving video. | 672 | * in nubus slot space, that the nubus card is driving video. |
742 | * Penguin really ought to tell us whether we are using internal | 673 | * Penguin really ought to tell us whether we are using internal |
743 | * video or not. | 674 | * video or not. |
675 | * Hopefully we only find one of them. Otherwise our NuBus | ||
676 | * code is really broken :-) | ||
744 | */ | 677 | */ |
745 | /* Hopefully we only find one of them. Otherwise our NuBus | ||
746 | code is really broken :-) */ | ||
747 | 678 | ||
748 | while ((ndev = nubus_find_type(NUBUS_CAT_DISPLAY, NUBUS_TYPE_VIDEO, ndev)) | 679 | while ((ndev = nubus_find_type(NUBUS_CAT_DISPLAY, |
749 | != NULL) | 680 | NUBUS_TYPE_VIDEO, ndev))) |
750 | { | 681 | { |
751 | if (!(mac_bi_data.videoaddr >= ndev->board->slot_addr | 682 | unsigned long base = ndev->board->slot_addr; |
752 | && (mac_bi_data.videoaddr < | 683 | |
753 | (unsigned long)nubus_slot_addr(ndev->board->slot+1)))) | 684 | if (mac_bi_data.videoaddr < base || |
685 | mac_bi_data.videoaddr - base > 0xFFFFFF) | ||
754 | continue; | 686 | continue; |
687 | |||
755 | video_is_nubus = 1; | 688 | video_is_nubus = 1; |
756 | /* We should probably just use the slot address... */ | 689 | slot_addr = (unsigned char *)base; |
757 | video_slot = ndev->board->slot; | ||
758 | 690 | ||
759 | switch(ndev->dr_hw) { | 691 | switch(ndev->dr_hw) { |
760 | case NUBUS_DRHW_APPLE_MDC: | 692 | case NUBUS_DRHW_APPLE_MDC: |
@@ -771,7 +703,7 @@ static int __init macfb_init(void) | |||
771 | strcpy(macfb_fix.id, "Jet"); | 703 | strcpy(macfb_fix.id, "Jet"); |
772 | macfb_setpalette = jet_setpalette; | 704 | macfb_setpalette = jet_setpalette; |
773 | macfb_defined.activate = FB_ACTIVATE_NOW; | 705 | macfb_defined.activate = FB_ACTIVATE_NOW; |
774 | break; | 706 | break; |
775 | default: | 707 | default: |
776 | strcpy(macfb_fix.id, "Generic NuBus"); | 708 | strcpy(macfb_fix.id, "Generic NuBus"); |
777 | break; | 709 | break; |
@@ -779,30 +711,19 @@ static int __init macfb_init(void) | |||
779 | } | 711 | } |
780 | 712 | ||
781 | /* If it's not a NuBus card, it must be internal video */ | 713 | /* If it's not a NuBus card, it must be internal video */ |
782 | /* FIXME: this function is getting way too big. (this driver | ||
783 | is too...) */ | ||
784 | if (!video_is_nubus) | 714 | if (!video_is_nubus) |
785 | switch( mac_bi_data.id ) | 715 | switch (mac_bi_data.id) { |
786 | { | 716 | /* |
787 | /* Valkyrie Quadras */ | 717 | * DAFB Quadras |
788 | case MAC_MODEL_Q630: | 718 | * Note: these first four have the v7 DAFB, which is |
789 | /* I'm not sure about this one */ | 719 | * known to be rather unlike the ones used in the |
790 | case MAC_MODEL_P588: | 720 | * other models |
791 | strcpy(macfb_fix.id, "Valkyrie"); | 721 | */ |
792 | macfb_setpalette = valkyrie_setpalette; | ||
793 | macfb_defined.activate = FB_ACTIVATE_NOW; | ||
794 | valkyrie_cmap_regs = ioremap(DAC_BASE, 0x1000); | ||
795 | break; | ||
796 | |||
797 | /* DAFB Quadras */ | ||
798 | /* Note: these first four have the v7 DAFB, which is | ||
799 | known to be rather unlike the ones used in the | ||
800 | other models */ | ||
801 | case MAC_MODEL_P475: | 722 | case MAC_MODEL_P475: |
802 | case MAC_MODEL_P475F: | 723 | case MAC_MODEL_P475F: |
803 | case MAC_MODEL_P575: | 724 | case MAC_MODEL_P575: |
804 | case MAC_MODEL_Q605: | 725 | case MAC_MODEL_Q605: |
805 | 726 | ||
806 | case MAC_MODEL_Q800: | 727 | case MAC_MODEL_Q800: |
807 | case MAC_MODEL_Q650: | 728 | case MAC_MODEL_Q650: |
808 | case MAC_MODEL_Q610: | 729 | case MAC_MODEL_Q610: |
@@ -817,17 +738,21 @@ static int __init macfb_init(void) | |||
817 | dafb_cmap_regs = ioremap(DAFB_BASE, 0x1000); | 738 | dafb_cmap_regs = ioremap(DAFB_BASE, 0x1000); |
818 | break; | 739 | break; |
819 | 740 | ||
820 | /* LC II uses the V8 framebuffer */ | 741 | /* |
742 | * LC II uses the V8 framebuffer | ||
743 | */ | ||
821 | case MAC_MODEL_LCII: | 744 | case MAC_MODEL_LCII: |
822 | strcpy(macfb_fix.id, "V8"); | 745 | strcpy(macfb_fix.id, "V8"); |
823 | macfb_setpalette = v8_brazil_setpalette; | 746 | macfb_setpalette = v8_brazil_setpalette; |
824 | macfb_defined.activate = FB_ACTIVATE_NOW; | 747 | macfb_defined.activate = FB_ACTIVATE_NOW; |
825 | v8_brazil_cmap_regs = ioremap(DAC_BASE, 0x1000); | 748 | v8_brazil_cmap_regs = ioremap(DAC_BASE, 0x1000); |
826 | break; | 749 | break; |
827 | 750 | ||
828 | /* IIvi, IIvx use the "Brazil" framebuffer (which is | 751 | /* |
829 | very much like the V8, it seems, and probably uses | 752 | * IIvi, IIvx use the "Brazil" framebuffer (which is |
830 | the same DAC) */ | 753 | * very much like the V8, it seems, and probably uses |
754 | * the same DAC) | ||
755 | */ | ||
831 | case MAC_MODEL_IIVI: | 756 | case MAC_MODEL_IIVI: |
832 | case MAC_MODEL_IIVX: | 757 | case MAC_MODEL_IIVX: |
833 | case MAC_MODEL_P600: | 758 | case MAC_MODEL_P600: |
@@ -836,12 +761,14 @@ static int __init macfb_init(void) | |||
836 | macfb_defined.activate = FB_ACTIVATE_NOW; | 761 | macfb_defined.activate = FB_ACTIVATE_NOW; |
837 | v8_brazil_cmap_regs = ioremap(DAC_BASE, 0x1000); | 762 | v8_brazil_cmap_regs = ioremap(DAC_BASE, 0x1000); |
838 | break; | 763 | break; |
839 | 764 | ||
840 | /* LC III (and friends) use the Sonora framebuffer */ | 765 | /* |
841 | /* Incidentally this is also used in the non-AV models | 766 | * LC III (and friends) use the Sonora framebuffer |
842 | of the x100 PowerMacs */ | 767 | * Incidentally this is also used in the non-AV models |
843 | /* These do in fact seem to use the same DAC interface | 768 | * of the x100 PowerMacs |
844 | as the LC II. */ | 769 | * These do in fact seem to use the same DAC interface |
770 | * as the LC II. | ||
771 | */ | ||
845 | case MAC_MODEL_LCIII: | 772 | case MAC_MODEL_LCIII: |
846 | case MAC_MODEL_P520: | 773 | case MAC_MODEL_P520: |
847 | case MAC_MODEL_P550: | 774 | case MAC_MODEL_P550: |
@@ -852,9 +779,11 @@ static int __init macfb_init(void) | |||
852 | v8_brazil_cmap_regs = ioremap(DAC_BASE, 0x1000); | 779 | v8_brazil_cmap_regs = ioremap(DAC_BASE, 0x1000); |
853 | break; | 780 | break; |
854 | 781 | ||
855 | /* IIci and IIsi use the infamous RBV chip | 782 | /* |
856 | (the IIsi is just a rebadged and crippled | 783 | * IIci and IIsi use the infamous RBV chip |
857 | IIci in a different case, BTW) */ | 784 | * (the IIsi is just a rebadged and crippled |
785 | * IIci in a different case, BTW) | ||
786 | */ | ||
858 | case MAC_MODEL_IICI: | 787 | case MAC_MODEL_IICI: |
859 | case MAC_MODEL_IISI: | 788 | case MAC_MODEL_IISI: |
860 | macfb_setpalette = rbv_setpalette; | 789 | macfb_setpalette = rbv_setpalette; |
@@ -863,7 +792,9 @@ static int __init macfb_init(void) | |||
863 | rbv_cmap_regs = ioremap(DAC_BASE, 0x1000); | 792 | rbv_cmap_regs = ioremap(DAC_BASE, 0x1000); |
864 | break; | 793 | break; |
865 | 794 | ||
866 | /* AVs use the Civic framebuffer */ | 795 | /* |
796 | * AVs use the Civic framebuffer | ||
797 | */ | ||
867 | case MAC_MODEL_Q840: | 798 | case MAC_MODEL_Q840: |
868 | case MAC_MODEL_C660: | 799 | case MAC_MODEL_C660: |
869 | macfb_setpalette = civic_setpalette; | 800 | macfb_setpalette = civic_setpalette; |
@@ -873,15 +804,10 @@ static int __init macfb_init(void) | |||
873 | break; | 804 | break; |
874 | 805 | ||
875 | 806 | ||
876 | /* Write a setpalette function for your machine, then | 807 | /* |
877 | you can add something similar here. These are | 808 | * Assorted weirdos |
878 | grouped by classes of video chipsets. Some of this | 809 | * We think this may be like the LC II |
879 | information is from the VideoToolbox "Bugs" web | 810 | */ |
880 | page at | ||
881 | http://rajsky.psych.nyu.edu/Tips/VideoBugs.html */ | ||
882 | |||
883 | /* Assorted weirdos */ | ||
884 | /* We think this may be like the LC II */ | ||
885 | case MAC_MODEL_LC: | 811 | case MAC_MODEL_LC: |
886 | if (vidtest) { | 812 | if (vidtest) { |
887 | macfb_setpalette = v8_brazil_setpalette; | 813 | macfb_setpalette = v8_brazil_setpalette; |
@@ -891,7 +817,10 @@ static int __init macfb_init(void) | |||
891 | } | 817 | } |
892 | strcpy(macfb_fix.id, "LC"); | 818 | strcpy(macfb_fix.id, "LC"); |
893 | break; | 819 | break; |
894 | /* We think this may be like the LC II */ | 820 | |
821 | /* | ||
822 | * We think this may be like the LC II | ||
823 | */ | ||
895 | case MAC_MODEL_CCL: | 824 | case MAC_MODEL_CCL: |
896 | if (vidtest) { | 825 | if (vidtest) { |
897 | macfb_setpalette = v8_brazil_setpalette; | 826 | macfb_setpalette = v8_brazil_setpalette; |
@@ -902,31 +831,42 @@ static int __init macfb_init(void) | |||
902 | strcpy(macfb_fix.id, "Color Classic"); | 831 | strcpy(macfb_fix.id, "Color Classic"); |
903 | break; | 832 | break; |
904 | 833 | ||
905 | /* And we *do* mean "weirdos" */ | 834 | /* |
835 | * And we *do* mean "weirdos" | ||
836 | */ | ||
906 | case MAC_MODEL_TV: | 837 | case MAC_MODEL_TV: |
907 | strcpy(macfb_fix.id, "Mac TV"); | 838 | strcpy(macfb_fix.id, "Mac TV"); |
908 | break; | 839 | break; |
909 | 840 | ||
910 | /* These don't have colour, so no need to worry */ | 841 | /* |
842 | * These don't have colour, so no need to worry | ||
843 | */ | ||
911 | case MAC_MODEL_SE30: | 844 | case MAC_MODEL_SE30: |
912 | case MAC_MODEL_CLII: | 845 | case MAC_MODEL_CLII: |
913 | strcpy(macfb_fix.id, "Monochrome"); | 846 | strcpy(macfb_fix.id, "Monochrome"); |
914 | break; | 847 | break; |
915 | 848 | ||
916 | /* Powerbooks are particularly difficult. Many of | 849 | /* |
917 | them have separate framebuffers for external and | 850 | * Powerbooks are particularly difficult. Many of |
918 | internal video, which is admittedly pretty cool, | 851 | * them have separate framebuffers for external and |
919 | but will be a bit of a headache to support here. | 852 | * internal video, which is admittedly pretty cool, |
920 | Also, many of them are grayscale, and we don't | 853 | * but will be a bit of a headache to support here. |
921 | really support that. */ | 854 | * Also, many of them are grayscale, and we don't |
922 | 855 | * really support that. | |
856 | */ | ||
857 | |||
858 | /* | ||
859 | * Slot 0 ROM says TIM. No external video. B&W. | ||
860 | */ | ||
923 | case MAC_MODEL_PB140: | 861 | case MAC_MODEL_PB140: |
924 | case MAC_MODEL_PB145: | 862 | case MAC_MODEL_PB145: |
925 | case MAC_MODEL_PB170: | 863 | case MAC_MODEL_PB170: |
926 | strcpy(macfb_fix.id, "DDC"); | 864 | strcpy(macfb_fix.id, "DDC"); |
927 | break; | 865 | break; |
928 | 866 | ||
929 | /* Internal is GSC, External (if present) is ViSC */ | 867 | /* |
868 | * Internal is GSC, External (if present) is ViSC | ||
869 | */ | ||
930 | case MAC_MODEL_PB150: /* no external video */ | 870 | case MAC_MODEL_PB150: /* no external video */ |
931 | case MAC_MODEL_PB160: | 871 | case MAC_MODEL_PB160: |
932 | case MAC_MODEL_PB165: | 872 | case MAC_MODEL_PB165: |
@@ -936,13 +876,17 @@ static int __init macfb_init(void) | |||
936 | strcpy(macfb_fix.id, "GSC"); | 876 | strcpy(macfb_fix.id, "GSC"); |
937 | break; | 877 | break; |
938 | 878 | ||
939 | /* Internal is TIM, External is ViSC */ | 879 | /* |
880 | * Internal is TIM, External is ViSC | ||
881 | */ | ||
940 | case MAC_MODEL_PB165C: | 882 | case MAC_MODEL_PB165C: |
941 | case MAC_MODEL_PB180C: | 883 | case MAC_MODEL_PB180C: |
942 | strcpy(macfb_fix.id, "TIM"); | 884 | strcpy(macfb_fix.id, "TIM"); |
943 | break; | 885 | break; |
944 | 886 | ||
945 | /* Internal is CSC, External is Keystone+Ariel. */ | 887 | /* |
888 | * Internal is CSC, External is Keystone+Ariel. | ||
889 | */ | ||
946 | case MAC_MODEL_PB190: /* external video is optional */ | 890 | case MAC_MODEL_PB190: /* external video is optional */ |
947 | case MAC_MODEL_PB520: | 891 | case MAC_MODEL_PB520: |
948 | case MAC_MODEL_PB250: | 892 | case MAC_MODEL_PB250: |
@@ -954,7 +898,7 @@ static int __init macfb_init(void) | |||
954 | strcpy(macfb_fix.id, "CSC"); | 898 | strcpy(macfb_fix.id, "CSC"); |
955 | csc_cmap_regs = ioremap(CSC_BASE, 0x1000); | 899 | csc_cmap_regs = ioremap(CSC_BASE, 0x1000); |
956 | break; | 900 | break; |
957 | 901 | ||
958 | default: | 902 | default: |
959 | strcpy(macfb_fix.id, "Unknown"); | 903 | strcpy(macfb_fix.id, "Unknown"); |
960 | break; | 904 | break; |
@@ -969,7 +913,7 @@ static int __init macfb_init(void) | |||
969 | err = fb_alloc_cmap(&fb_info.cmap, video_cmap_len, 0); | 913 | err = fb_alloc_cmap(&fb_info.cmap, video_cmap_len, 0); |
970 | if (err) | 914 | if (err) |
971 | goto fail_unmap; | 915 | goto fail_unmap; |
972 | 916 | ||
973 | err = register_framebuffer(&fb_info); | 917 | err = register_framebuffer(&fb_info); |
974 | if (err) | 918 | if (err) |
975 | goto fail_dealloc; | 919 | goto fail_dealloc; |