This source file includes following definitions.
- valkyriefb_set_par
- valkyrie_par_to_var
- valkyriefb_check_var
- valkyriefb_blank
- valkyriefb_setcolreg
- valkyrie_vram_reqd
- set_valkyrie_clock
- valkyrie_choose_mode
- valkyriefb_init
- read_valkyrie_sense
- valkyrie_var_to_par
- valkyrie_init_fix
- valkyrie_par_to_fix
- valkyrie_init_info
- valkyriefb_setup
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42 #include <linux/module.h>
43 #include <linux/kernel.h>
44 #include <linux/errno.h>
45 #include <linux/string.h>
46 #include <linux/mm.h>
47 #include <linux/slab.h>
48 #include <linux/vmalloc.h>
49 #include <linux/delay.h>
50 #include <linux/interrupt.h>
51 #include <linux/fb.h>
52 #include <linux/selection.h>
53 #include <linux/init.h>
54 #include <linux/nvram.h>
55 #include <linux/adb.h>
56 #include <linux/cuda.h>
57 #ifdef CONFIG_MAC
58 #include <asm/macintosh.h>
59 #else
60 #include <asm/prom.h>
61 #endif
62
63 #include "macmodes.h"
64 #include "valkyriefb.h"
65
66 static int default_vmode = VMODE_NVRAM;
67 static int default_cmode = CMODE_NVRAM;
68
69 struct fb_par_valkyrie {
70 int vmode, cmode;
71 int xres, yres;
72 int vxres, vyres;
73 struct valkyrie_regvals *init;
74 };
75
76 struct fb_info_valkyrie {
77 struct fb_info info;
78 struct fb_par_valkyrie par;
79 struct cmap_regs __iomem *cmap_regs;
80 unsigned long cmap_regs_phys;
81
82 struct valkyrie_regs __iomem *valkyrie_regs;
83 unsigned long valkyrie_regs_phys;
84
85 __u8 __iomem *frame_buffer;
86 unsigned long frame_buffer_phys;
87
88 int sense;
89 unsigned long total_vram;
90
91 u32 pseudo_palette[16];
92 };
93
94
95
96
97 int valkyriefb_init(void);
98 int valkyriefb_setup(char*);
99
100 static int valkyriefb_check_var(struct fb_var_screeninfo *var,
101 struct fb_info *info);
102 static int valkyriefb_set_par(struct fb_info *info);
103 static int valkyriefb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
104 u_int transp, struct fb_info *info);
105 static int valkyriefb_blank(int blank_mode, struct fb_info *info);
106
107 static int read_valkyrie_sense(struct fb_info_valkyrie *p);
108 static void set_valkyrie_clock(unsigned char *params);
109 static int valkyrie_var_to_par(struct fb_var_screeninfo *var,
110 struct fb_par_valkyrie *par, const struct fb_info *fb_info);
111
112 static int valkyrie_init_info(struct fb_info *info, struct fb_info_valkyrie *p);
113 static void valkyrie_par_to_fix(struct fb_par_valkyrie *par, struct fb_fix_screeninfo *fix);
114 static void valkyrie_init_fix(struct fb_fix_screeninfo *fix, struct fb_info_valkyrie *p);
115
116 static struct fb_ops valkyriefb_ops = {
117 .owner = THIS_MODULE,
118 .fb_check_var = valkyriefb_check_var,
119 .fb_set_par = valkyriefb_set_par,
120 .fb_setcolreg = valkyriefb_setcolreg,
121 .fb_blank = valkyriefb_blank,
122 .fb_fillrect = cfb_fillrect,
123 .fb_copyarea = cfb_copyarea,
124 .fb_imageblit = cfb_imageblit,
125 };
126
127
128 static int valkyriefb_set_par(struct fb_info *info)
129 {
130 struct fb_info_valkyrie *p =
131 container_of(info, struct fb_info_valkyrie, info);
132 volatile struct valkyrie_regs __iomem *valkyrie_regs = p->valkyrie_regs;
133 struct fb_par_valkyrie *par = info->par;
134 struct valkyrie_regvals *init;
135 int err;
136
137 if ((err = valkyrie_var_to_par(&info->var, par, info)))
138 return err;
139
140 valkyrie_par_to_fix(par, &info->fix);
141
142
143 out_8(&valkyrie_regs->status.r, 0);
144 udelay(100);
145
146
147 init = par->init;
148 out_8(&valkyrie_regs->mode.r, init->mode | 0x80);
149 out_8(&valkyrie_regs->depth.r, par->cmode + 3);
150 set_valkyrie_clock(init->clock_params);
151 udelay(100);
152
153
154 out_8(&valkyrie_regs->mode.r, init->mode);
155
156 return 0;
157 }
158
159 static inline int valkyrie_par_to_var(struct fb_par_valkyrie *par,
160 struct fb_var_screeninfo *var)
161 {
162 return mac_vmode_to_var(par->vmode, par->cmode, var);
163 }
164
165 static int
166 valkyriefb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
167 {
168 int err;
169 struct fb_par_valkyrie par;
170
171 if ((err = valkyrie_var_to_par(var, &par, info)))
172 return err;
173 valkyrie_par_to_var(&par, var);
174 return 0;
175 }
176
177
178
179
180
181
182
183
184
185
186
187 static int valkyriefb_blank(int blank_mode, struct fb_info *info)
188 {
189 struct fb_info_valkyrie *p =
190 container_of(info, struct fb_info_valkyrie, info);
191 struct fb_par_valkyrie *par = info->par;
192 struct valkyrie_regvals *init = par->init;
193
194 if (init == NULL)
195 return 1;
196
197 switch (blank_mode) {
198 case FB_BLANK_UNBLANK:
199 out_8(&p->valkyrie_regs->mode.r, init->mode);
200 break;
201 case FB_BLANK_NORMAL:
202 return 1;
203 case FB_BLANK_VSYNC_SUSPEND:
204 case FB_BLANK_HSYNC_SUSPEND:
205
206
207
208
209
210 out_8(&p->valkyrie_regs->mode.r, init->mode | 0x40);
211 break;
212 case FB_BLANK_POWERDOWN:
213 out_8(&p->valkyrie_regs->mode.r, 0x66);
214 break;
215 }
216 return 0;
217 }
218
219 static int valkyriefb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
220 u_int transp, struct fb_info *info)
221 {
222 struct fb_info_valkyrie *p =
223 container_of(info, struct fb_info_valkyrie, info);
224 volatile struct cmap_regs __iomem *cmap_regs = p->cmap_regs;
225 struct fb_par_valkyrie *par = info->par;
226
227 if (regno > 255)
228 return 1;
229 red >>= 8;
230 green >>= 8;
231 blue >>= 8;
232
233
234 out_8(&p->cmap_regs->addr, regno);
235 udelay(1);
236
237 out_8(&cmap_regs->lut, red);
238 out_8(&cmap_regs->lut, green);
239 out_8(&cmap_regs->lut, blue);
240
241 if (regno < 16 && par->cmode == CMODE_16)
242 ((u32 *)info->pseudo_palette)[regno] =
243 (regno << 10) | (regno << 5) | regno;
244
245 return 0;
246 }
247
248 static inline int valkyrie_vram_reqd(int video_mode, int color_mode)
249 {
250 int pitch;
251 struct valkyrie_regvals *init = valkyrie_reg_init[video_mode-1];
252
253 if ((pitch = init->pitch[color_mode]) == 0)
254 pitch = 2 * init->pitch[0];
255 return init->vres * pitch;
256 }
257
258 static void set_valkyrie_clock(unsigned char *params)
259 {
260 #ifdef CONFIG_ADB_CUDA
261 struct adb_request req;
262 int i;
263
264 for (i = 0; i < 3; ++i) {
265 cuda_request(&req, NULL, 5, CUDA_PACKET, CUDA_GET_SET_IIC,
266 0x50, i + 1, params[i]);
267 while (!req.complete)
268 cuda_poll();
269 }
270 #endif
271 }
272
273 static void __init valkyrie_choose_mode(struct fb_info_valkyrie *p)
274 {
275 p->sense = read_valkyrie_sense(p);
276 printk(KERN_INFO "Monitor sense value = 0x%x\n", p->sense);
277
278
279 #ifdef CONFIG_PPC_PMAC
280 if (IS_REACHABLE(CONFIG_NVRAM) && default_vmode == VMODE_NVRAM)
281 default_vmode = nvram_read_byte(NV_VMODE);
282 #endif
283 if (default_vmode <= 0 || default_vmode > VMODE_MAX ||
284 !valkyrie_reg_init[default_vmode - 1]) {
285 default_vmode = mac_map_monitor_sense(p->sense);
286 if (!valkyrie_reg_init[default_vmode - 1])
287 default_vmode = VMODE_640_480_67;
288 }
289
290 #ifdef CONFIG_PPC_PMAC
291 if (IS_REACHABLE(CONFIG_NVRAM) && default_cmode == CMODE_NVRAM)
292 default_cmode = nvram_read_byte(NV_CMODE);
293 #endif
294
295
296
297 if (default_cmode < CMODE_8 || default_cmode > CMODE_16
298 || valkyrie_reg_init[default_vmode-1]->pitch[default_cmode] == 0
299 || valkyrie_vram_reqd(default_vmode, default_cmode) > p->total_vram)
300 default_cmode = CMODE_8;
301
302 printk(KERN_INFO "using video mode %d and color mode %d.\n",
303 default_vmode, default_cmode);
304 }
305
306 int __init valkyriefb_init(void)
307 {
308 struct fb_info_valkyrie *p;
309 unsigned long frame_buffer_phys, cmap_regs_phys;
310 int err;
311 char *option = NULL;
312
313 if (fb_get_options("valkyriefb", &option))
314 return -ENODEV;
315 valkyriefb_setup(option);
316
317 #ifdef CONFIG_MAC
318 if (!MACH_IS_MAC)
319 return -ENODEV;
320 if (!(mac_bi_data.id == MAC_MODEL_Q630
321
322 || mac_bi_data.id == MAC_MODEL_P588))
323 return -ENODEV;
324
325
326 frame_buffer_phys = 0xf9000000;
327 cmap_regs_phys = 0x50f24000;
328 #else
329 {
330 struct device_node *dp;
331 struct resource r;
332
333 dp = of_find_node_by_name(NULL, "valkyrie");
334 if (dp == 0)
335 return 0;
336
337 if (of_address_to_resource(dp, 0, &r)) {
338 printk(KERN_ERR "can't find address for valkyrie\n");
339 return 0;
340 }
341
342 frame_buffer_phys = r.start;
343 cmap_regs_phys = r.start + 0x304000;
344 }
345 #endif
346
347 p = kzalloc(sizeof(*p), GFP_ATOMIC);
348 if (p == 0)
349 return -ENOMEM;
350
351
352 if (!request_mem_region(frame_buffer_phys, 0x100000, "valkyriefb")) {
353 kfree(p);
354 return 0;
355 }
356 p->total_vram = 0x100000;
357 p->frame_buffer_phys = frame_buffer_phys;
358 #ifdef CONFIG_MAC
359 p->frame_buffer = ioremap_nocache(frame_buffer_phys, p->total_vram);
360 #else
361 p->frame_buffer = ioremap_wt(frame_buffer_phys, p->total_vram);
362 #endif
363 p->cmap_regs_phys = cmap_regs_phys;
364 p->cmap_regs = ioremap(p->cmap_regs_phys, 0x1000);
365 p->valkyrie_regs_phys = cmap_regs_phys+0x6000;
366 p->valkyrie_regs = ioremap(p->valkyrie_regs_phys, 0x1000);
367 err = -ENOMEM;
368 if (p->frame_buffer == NULL || p->cmap_regs == NULL
369 || p->valkyrie_regs == NULL) {
370 printk(KERN_ERR "valkyriefb: couldn't map resources\n");
371 goto out_free;
372 }
373
374 valkyrie_choose_mode(p);
375 mac_vmode_to_var(default_vmode, default_cmode, &p->info.var);
376 err = valkyrie_init_info(&p->info, p);
377 if (err < 0)
378 goto out_free;
379 valkyrie_init_fix(&p->info.fix, p);
380 if (valkyriefb_set_par(&p->info))
381
382 printk(KERN_ERR "valkyriefb: can't set default video mode\n");
383
384 if ((err = register_framebuffer(&p->info)) != 0)
385 goto out_cmap_free;
386
387 fb_info(&p->info, "valkyrie frame buffer device\n");
388 return 0;
389
390 out_cmap_free:
391 fb_dealloc_cmap(&p->info.cmap);
392 out_free:
393 if (p->frame_buffer)
394 iounmap(p->frame_buffer);
395 if (p->cmap_regs)
396 iounmap(p->cmap_regs);
397 if (p->valkyrie_regs)
398 iounmap(p->valkyrie_regs);
399 kfree(p);
400 return err;
401 }
402
403
404
405
406 static int read_valkyrie_sense(struct fb_info_valkyrie *p)
407 {
408 int sense, in;
409
410 out_8(&p->valkyrie_regs->msense.r, 0);
411 __delay(20000);
412 sense = ((in = in_8(&p->valkyrie_regs->msense.r)) & 0x70) << 4;
413
414 out_8(&p->valkyrie_regs->msense.r, 4);
415 __delay(20000);
416 sense |= ((in = in_8(&p->valkyrie_regs->msense.r)) & 0x30);
417 out_8(&p->valkyrie_regs->msense.r, 2);
418 __delay(20000);
419 sense |= ((in = in_8(&p->valkyrie_regs->msense.r)) & 0x40) >> 3;
420 sense |= (in & 0x10) >> 2;
421 out_8(&p->valkyrie_regs->msense.r, 1);
422 __delay(20000);
423 sense |= ((in = in_8(&p->valkyrie_regs->msense.r)) & 0x60) >> 5;
424
425 out_8(&p->valkyrie_regs->msense.r, 7);
426
427 return sense;
428 }
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456 static int valkyrie_var_to_par(struct fb_var_screeninfo *var,
457 struct fb_par_valkyrie *par, const struct fb_info *fb_info)
458 {
459 int vmode, cmode;
460 struct valkyrie_regvals *init;
461 struct fb_info_valkyrie *p =
462 container_of(fb_info, struct fb_info_valkyrie, info);
463
464 if (mac_var_to_vmode(var, &vmode, &cmode) != 0) {
465 printk(KERN_ERR "valkyriefb: can't do %dx%dx%d.\n",
466 var->xres, var->yres, var->bits_per_pixel);
467 return -EINVAL;
468 }
469
470
471 if (vmode < 1 || vmode > VMODE_MAX || !valkyrie_reg_init[vmode-1]) {
472 printk(KERN_ERR "valkyriefb: vmode %d not valid.\n", vmode);
473 return -EINVAL;
474 }
475
476 if (cmode != CMODE_8 && cmode != CMODE_16) {
477 printk(KERN_ERR "valkyriefb: cmode %d not valid.\n", cmode);
478 return -EINVAL;
479 }
480
481 if (var->xres_virtual > var->xres || var->yres_virtual > var->yres
482 || var->xoffset != 0 || var->yoffset != 0) {
483 return -EINVAL;
484 }
485
486 init = valkyrie_reg_init[vmode-1];
487 if (init->pitch[cmode] == 0) {
488 printk(KERN_ERR "valkyriefb: vmode %d does not support "
489 "cmode %d.\n", vmode, cmode);
490 return -EINVAL;
491 }
492
493 if (valkyrie_vram_reqd(vmode, cmode) > p->total_vram) {
494 printk(KERN_ERR "valkyriefb: not enough ram for vmode %d, "
495 "cmode %d.\n", vmode, cmode);
496 return -EINVAL;
497 }
498
499 par->vmode = vmode;
500 par->cmode = cmode;
501 par->init = init;
502 par->xres = var->xres;
503 par->yres = var->yres;
504 par->vxres = par->xres;
505 par->vyres = par->yres;
506
507 return 0;
508 }
509
510 static void valkyrie_init_fix(struct fb_fix_screeninfo *fix, struct fb_info_valkyrie *p)
511 {
512 memset(fix, 0, sizeof(*fix));
513 strcpy(fix->id, "valkyrie");
514 fix->mmio_start = p->valkyrie_regs_phys;
515 fix->mmio_len = sizeof(struct valkyrie_regs);
516 fix->type = FB_TYPE_PACKED_PIXELS;
517 fix->smem_start = p->frame_buffer_phys + 0x1000;
518 fix->smem_len = p->total_vram;
519
520 fix->type_aux = 0;
521 fix->ywrapstep = 0;
522 fix->ypanstep = 0;
523 fix->xpanstep = 0;
524
525 }
526
527
528 static void valkyrie_par_to_fix(struct fb_par_valkyrie *par,
529 struct fb_fix_screeninfo *fix)
530 {
531 fix->smem_len = valkyrie_vram_reqd(par->vmode, par->cmode);
532 fix->visual = (par->cmode == CMODE_8) ?
533 FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR;
534 fix->line_length = par->vxres << par->cmode;
535
536 }
537
538 static int __init valkyrie_init_info(struct fb_info *info,
539 struct fb_info_valkyrie *p)
540 {
541 info->fbops = &valkyriefb_ops;
542 info->screen_base = p->frame_buffer + 0x1000;
543 info->flags = FBINFO_DEFAULT;
544 info->pseudo_palette = p->pseudo_palette;
545 info->par = &p->par;
546 return fb_alloc_cmap(&info->cmap, 256, 0);
547 }
548
549
550
551
552
553 int __init valkyriefb_setup(char *options)
554 {
555 char *this_opt;
556
557 if (!options || !*options)
558 return 0;
559
560 while ((this_opt = strsep(&options, ",")) != NULL) {
561 if (!strncmp(this_opt, "vmode:", 6)) {
562 int vmode = simple_strtoul(this_opt+6, NULL, 0);
563 if (vmode > 0 && vmode <= VMODE_MAX)
564 default_vmode = vmode;
565 }
566 else if (!strncmp(this_opt, "cmode:", 6)) {
567 int depth = simple_strtoul(this_opt+6, NULL, 0);
568 switch (depth) {
569 case 8:
570 default_cmode = CMODE_8;
571 break;
572 case 15:
573 case 16:
574 default_cmode = CMODE_16;
575 break;
576 }
577 }
578 }
579 return 0;
580 }
581
582 module_init(valkyriefb_init);
583 MODULE_LICENSE("GPL");