ata_piix: SATA 2port controller port map fix
[linux-2.6.git] / drivers / video / controlfb.c
1 /*
2  *  controlfb.c -- frame buffer device for the PowerMac 'control' display
3  *
4  *  Created 12 July 1998 by Dan Jacobowitz <dan@debian.org>
5  *  Copyright (C) 1998 Dan Jacobowitz
6  *  Copyright (C) 2001 Takashi Oe
7  *
8  *  Mmap code by Michel Lanners <mlan@cpu.lu>
9  *
10  *  Frame buffer structure from:
11  *    drivers/video/chipsfb.c -- frame buffer device for
12  *    Chips & Technologies 65550 chip.
13  *
14  *    Copyright (C) 1998 Paul Mackerras
15  *
16  *    This file is derived from the Powermac "chips" driver:
17  *    Copyright (C) 1997 Fabio Riccardi.
18  *    And from the frame buffer device for Open Firmware-initialized devices:
19  *    Copyright (C) 1997 Geert Uytterhoeven.
20  *
21  *  Hardware information from:
22  *    control.c: Console support for PowerMac "control" display adaptor.
23  *    Copyright (C) 1996 Paul Mackerras
24  *
25  *  Updated to 2.5 framebuffer API by Ben Herrenschmidt
26  *  <benh@kernel.crashing.org>, Paul Mackerras <paulus@samba.org>,
27  *  and James Simmons <jsimmons@infradead.org>.
28  *
29  *  This file is subject to the terms and conditions of the GNU General Public
30  *  License. See the file COPYING in the main directory of this archive for
31  *  more details.
32  */
33
34 #include <linux/module.h>
35 #include <linux/kernel.h>
36 #include <linux/errno.h>
37 #include <linux/string.h>
38 #include <linux/mm.h>
39 #include <linux/slab.h>
40 #include <linux/vmalloc.h>
41 #include <linux/delay.h>
42 #include <linux/interrupt.h>
43 #include <linux/fb.h>
44 #include <linux/init.h>
45 #include <linux/pci.h>
46 #include <linux/nvram.h>
47 #include <linux/adb.h>
48 #include <linux/cuda.h>
49 #include <asm/io.h>
50 #include <asm/prom.h>
51 #include <asm/pgtable.h>
52 #include <asm/btext.h>
53
54 #include "macmodes.h"
55 #include "controlfb.h"
56
57 struct fb_par_control {
58         int     vmode, cmode;
59         int     xres, yres;
60         int     vxres, vyres;
61         int     xoffset, yoffset;
62         int     pitch;
63         struct control_regvals  regvals;
64         unsigned long sync;
65         unsigned char ctrl;
66 };
67
68 #define DIRTY(z) ((x)->z != (y)->z)
69 #define DIRTY_CMAP(z) (memcmp(&((x)->z), &((y)->z), sizeof((y)->z)))
70 static inline int PAR_EQUAL(struct fb_par_control *x, struct fb_par_control *y)
71 {
72         int i, results;
73
74         results = 1;
75         for (i = 0; i < 3; i++)
76                 results &= !DIRTY(regvals.clock_params[i]);
77         if (!results)
78                 return 0;
79         for (i = 0; i < 16; i++)
80                 results &= !DIRTY(regvals.regs[i]);
81         if (!results)
82                 return 0;
83         return (!DIRTY(cmode) && !DIRTY(xres) && !DIRTY(yres)
84                 && !DIRTY(vxres) && !DIRTY(vyres));
85 }
86 static inline int VAR_MATCH(struct fb_var_screeninfo *x, struct fb_var_screeninfo *y)
87 {
88         return (!DIRTY(bits_per_pixel) && !DIRTY(xres)
89                 && !DIRTY(yres) && !DIRTY(xres_virtual)
90                 && !DIRTY(yres_virtual)
91                 && !DIRTY_CMAP(red) && !DIRTY_CMAP(green) && !DIRTY_CMAP(blue));
92 }
93
94 struct fb_info_control {
95         struct fb_info          info;
96         struct fb_par_control   par;
97         u32                     pseudo_palette[16];
98                 
99         struct cmap_regs        __iomem *cmap_regs;
100         unsigned long           cmap_regs_phys;
101         
102         struct control_regs     __iomem *control_regs;
103         unsigned long           control_regs_phys;
104         unsigned long           control_regs_size;
105         
106         __u8                    __iomem *frame_buffer;
107         unsigned long           frame_buffer_phys;
108         unsigned long           fb_orig_base;
109         unsigned long           fb_orig_size;
110
111         int                     control_use_bank2;
112         unsigned long           total_vram;
113         unsigned char           vram_attr;
114 };
115
116 /* control register access macro */
117 #define CNTRL_REG(INFO,REG) (&(((INFO)->control_regs->REG).r))
118
119
120 /******************** Prototypes for exported functions ********************/
121 /*
122  * struct fb_ops
123  */
124 static int controlfb_pan_display(struct fb_var_screeninfo *var,
125         struct fb_info *info);
126 static int controlfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
127         u_int transp, struct fb_info *info);
128 static int controlfb_blank(int blank_mode, struct fb_info *info);
129 static int controlfb_mmap(struct fb_info *info,
130         struct vm_area_struct *vma);
131 static int controlfb_set_par (struct fb_info *info);
132 static int controlfb_check_var (struct fb_var_screeninfo *var, struct fb_info *info);
133
134 /******************** Prototypes for internal functions **********************/
135
136 static void set_control_clock(unsigned char *params);
137 static int init_control(struct fb_info_control *p);
138 static void control_set_hardware(struct fb_info_control *p,
139         struct fb_par_control *par);
140 static int control_of_init(struct device_node *dp);
141 static void find_vram_size(struct fb_info_control *p);
142 static int read_control_sense(struct fb_info_control *p);
143 static int calc_clock_params(unsigned long clk, unsigned char *param);
144 static int control_var_to_par(struct fb_var_screeninfo *var,
145         struct fb_par_control *par, const struct fb_info *fb_info);
146 static inline void control_par_to_var(struct fb_par_control *par,
147         struct fb_var_screeninfo *var);
148 static void control_init_info(struct fb_info *info, struct fb_info_control *p);
149 static void control_cleanup(void);
150
151
152 /************************** Internal variables *******************************/
153
154 static struct fb_info_control *control_fb;
155
156 static int default_vmode __initdata = VMODE_NVRAM;
157 static int default_cmode __initdata = CMODE_NVRAM;
158
159
160 static struct fb_ops controlfb_ops = {
161         .owner          = THIS_MODULE,
162         .fb_check_var   = controlfb_check_var,
163         .fb_set_par     = controlfb_set_par,
164         .fb_setcolreg   = controlfb_setcolreg,
165         .fb_pan_display = controlfb_pan_display,
166         .fb_blank       = controlfb_blank,
167         .fb_mmap        = controlfb_mmap,
168         .fb_fillrect    = cfb_fillrect,
169         .fb_copyarea    = cfb_copyarea,
170         .fb_imageblit   = cfb_imageblit,
171 };
172
173
174 /********************  The functions for controlfb_ops ********************/
175
176 #ifdef MODULE
177 MODULE_LICENSE("GPL");
178
179 int init_module(void)
180 {
181         struct device_node *dp;
182         int ret = -ENXIO;
183
184         dp = of_find_node_by_name(NULL, "control");
185         if (dp != 0 && !control_of_init(dp))
186                 ret = 0;
187         of_node_put(dp);
188
189         return ret;
190 }
191
192 void cleanup_module(void)
193 {
194         control_cleanup();
195 }
196 #endif
197
198 /*
199  * Checks a var structure
200  */
201 static int controlfb_check_var (struct fb_var_screeninfo *var, struct fb_info *info)
202 {
203         struct fb_par_control par;
204         int err;
205
206         err = control_var_to_par(var, &par, info);
207         if (err)
208                 return err;     
209         control_par_to_var(&par, var);
210
211         return 0;
212 }
213
214 /*
215  * Applies current var to display
216  */
217 static int controlfb_set_par (struct fb_info *info)
218 {
219         struct fb_info_control *p = (struct fb_info_control *) info;
220         struct fb_par_control par;
221         int err;
222
223         if((err = control_var_to_par(&info->var, &par, info))) {
224                 printk (KERN_ERR "controlfb_set_par: error calling"
225                                  " control_var_to_par: %d.\n", err);
226                 return err;
227         }
228         
229         control_set_hardware(p, &par);
230
231         info->fix.visual = (p->par.cmode == CMODE_8) ?
232                 FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR;
233         info->fix.line_length = p->par.pitch;
234         info->fix.xpanstep = 32 >> p->par.cmode;
235         info->fix.ypanstep = 1;
236
237         return 0;
238 }
239
240 /*
241  * Set screen start address according to var offset values
242  */
243 static inline void set_screen_start(int xoffset, int yoffset,
244         struct fb_info_control *p)
245 {
246         struct fb_par_control *par = &p->par;
247
248         par->xoffset = xoffset;
249         par->yoffset = yoffset;
250         out_le32(CNTRL_REG(p,start_addr),
251                  par->yoffset * par->pitch + (par->xoffset << par->cmode));
252 }
253
254
255 static int controlfb_pan_display(struct fb_var_screeninfo *var,
256                                  struct fb_info *info)
257 {
258         unsigned int xoffset, hstep;
259         struct fb_info_control *p = (struct fb_info_control *)info;
260         struct fb_par_control *par = &p->par;
261
262         /*
263          * make sure start addr will be 32-byte aligned
264          */
265         hstep = 0x1f >> par->cmode;
266         xoffset = (var->xoffset + hstep) & ~hstep;
267
268         if (xoffset+par->xres > par->vxres ||
269             var->yoffset+par->yres > par->vyres)
270                 return -EINVAL;
271
272         set_screen_start(xoffset, var->yoffset, p);
273
274         return 0;
275 }
276
277
278 /*
279  * Private mmap since we want to have a different caching on the framebuffer
280  * for controlfb.
281  * Note there's no locking in here; it's done in fb_mmap() in fbmem.c.
282  */
283 static int controlfb_mmap(struct fb_info *info,
284                        struct vm_area_struct *vma)
285 {
286        unsigned long off, start;
287        u32 len;
288
289        off = vma->vm_pgoff << PAGE_SHIFT;
290
291        /* frame buffer memory */
292        start = info->fix.smem_start;
293        len = PAGE_ALIGN((start & ~PAGE_MASK)+info->fix.smem_len);
294        if (off >= len) {
295                /* memory mapped io */
296                off -= len;
297                if (info->var.accel_flags)
298                        return -EINVAL;
299                start = info->fix.mmio_start;
300                len = PAGE_ALIGN((start & ~PAGE_MASK)+info->fix.mmio_len);
301                pgprot_val(vma->vm_page_prot) |= _PAGE_NO_CACHE|_PAGE_GUARDED;
302        } else {
303                /* framebuffer */
304                pgprot_val(vma->vm_page_prot) |= _PAGE_WRITETHRU;
305        }
306        start &= PAGE_MASK;
307        if ((vma->vm_end - vma->vm_start + off) > len)
308                 return -EINVAL;
309        off += start;
310        vma->vm_pgoff = off >> PAGE_SHIFT;
311        if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT,
312            vma->vm_end - vma->vm_start, vma->vm_page_prot))
313                return -EAGAIN;
314
315        return 0;
316 }
317
318 static int controlfb_blank(int blank_mode, struct fb_info *info)
319 {
320         struct fb_info_control *p = (struct fb_info_control *) info;
321         unsigned ctrl;
322
323         ctrl = ld_le32(CNTRL_REG(p,ctrl));
324         if (blank_mode > 0)
325                 switch (blank_mode) {
326                 case FB_BLANK_VSYNC_SUSPEND:
327                         ctrl &= ~3;
328                         break;
329                 case FB_BLANK_HSYNC_SUSPEND:
330                         ctrl &= ~0x30;
331                         break;
332                 case FB_BLANK_POWERDOWN:
333                         ctrl &= ~0x33;
334                         /* fall through */
335                 case FB_BLANK_NORMAL:
336                         ctrl |= 0x400;
337                         break;
338                 default:
339                         break;
340                 }
341         else {
342                 ctrl &= ~0x400;
343                 ctrl |= 0x33;
344         }
345         out_le32(CNTRL_REG(p,ctrl), ctrl);
346
347         return 0;
348 }
349
350 static int controlfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
351                              u_int transp, struct fb_info *info)
352 {
353         struct fb_info_control *p = (struct fb_info_control *) info;
354         __u8 r, g, b;
355
356         if (regno > 255)
357                 return 1;
358
359         r = red >> 8;
360         g = green >> 8;
361         b = blue >> 8;
362
363         out_8(&p->cmap_regs->addr, regno);      /* tell clut what addr to fill  */
364         out_8(&p->cmap_regs->lut, r);           /* send one color channel at    */
365         out_8(&p->cmap_regs->lut, g);           /* a time...                    */
366         out_8(&p->cmap_regs->lut, b);
367
368         if (regno < 16) {
369                 int i;
370                 switch (p->par.cmode) {
371                 case CMODE_16:
372                         p->pseudo_palette[regno] =
373                             (regno << 10) | (regno << 5) | regno;
374                         break;
375                 case CMODE_32:
376                         i = (regno << 8) | regno;
377                         p->pseudo_palette[regno] = (i << 16) | i;
378                         break;
379                 }
380         }
381
382         return 0;
383 }
384
385
386 /********************  End of controlfb_ops implementation  ******************/
387
388
389
390 static void set_control_clock(unsigned char *params)
391 {
392 #ifdef CONFIG_ADB_CUDA
393         struct adb_request req;
394         int i;
395
396         for (i = 0; i < 3; ++i) {
397                 cuda_request(&req, NULL, 5, CUDA_PACKET, CUDA_GET_SET_IIC,
398                              0x50, i + 1, params[i]);
399                 while (!req.complete)
400                         cuda_poll();
401         }
402 #endif  
403 }
404
405
406 /*
407  * finish off the driver initialization and register
408  */
409 static int __init init_control(struct fb_info_control *p)
410 {
411         int full, sense, vmode, cmode, vyres;
412         struct fb_var_screeninfo var;
413         int rc;
414         
415         printk(KERN_INFO "controlfb: ");
416
417         full = p->total_vram == 0x400000;
418
419         /* Try to pick a video mode out of NVRAM if we have one. */
420 #ifdef CONFIG_NVRAM
421         if (default_cmode == CMODE_NVRAM){
422                 cmode = nvram_read_byte(NV_CMODE);
423                 if(cmode < CMODE_8 || cmode > CMODE_32)
424                         cmode = CMODE_8;
425         } else
426 #endif
427                 cmode=default_cmode;
428 #ifdef CONFIG_NVRAM
429         if (default_vmode == VMODE_NVRAM) {
430                 vmode = nvram_read_byte(NV_VMODE);
431                 if (vmode < 1 || vmode > VMODE_MAX ||
432                     control_mac_modes[vmode - 1].m[full] < cmode) {
433                         sense = read_control_sense(p);
434                         printk("Monitor sense value = 0x%x, ", sense);
435                         vmode = mac_map_monitor_sense(sense);
436                         if (control_mac_modes[vmode - 1].m[full] < cmode)
437                                 vmode = VMODE_640_480_60;
438                 }
439         } else
440 #endif
441         {
442                 vmode=default_vmode;
443                 if (control_mac_modes[vmode - 1].m[full] < cmode) {
444                         if (cmode > CMODE_8)
445                                 cmode--;
446                         else
447                                 vmode = VMODE_640_480_60;
448                 }
449         }
450
451         /* Initialize info structure */
452         control_init_info(&p->info, p);
453
454         /* Setup default var */
455         if (mac_vmode_to_var(vmode, cmode, &var) < 0) {
456                 /* This shouldn't happen! */
457                 printk("mac_vmode_to_var(%d, %d,) failed\n", vmode, cmode);
458 try_again:
459                 vmode = VMODE_640_480_60;
460                 cmode = CMODE_8;
461                 if (mac_vmode_to_var(vmode, cmode, &var) < 0) {
462                         printk(KERN_ERR "controlfb: mac_vmode_to_var() failed\n");
463                         return -ENXIO;
464                 }
465                 printk(KERN_INFO "controlfb: ");
466         }
467         printk("using video mode %d and color mode %d.\n", vmode, cmode);
468
469         vyres = (p->total_vram - CTRLFB_OFF) / (var.xres << cmode);
470         if (vyres > var.yres)
471                 var.yres_virtual = vyres;
472
473         /* Apply default var */
474         var.activate = FB_ACTIVATE_NOW;
475         rc = fb_set_var(&p->info, &var);
476         if (rc && (vmode != VMODE_640_480_60 || cmode != CMODE_8))
477                 goto try_again;
478
479         /* Register with fbdev layer */
480         if (register_framebuffer(&p->info) < 0)
481                 return -ENXIO;
482         
483         printk(KERN_INFO "fb%d: control display adapter\n", p->info.node);      
484
485         return 0;
486 }
487
488 #define RADACAL_WRITE(a,d) \
489         out_8(&p->cmap_regs->addr, (a)); \
490         out_8(&p->cmap_regs->dat,   (d))
491
492 /* Now how about actually saying, Make it so! */
493 /* Some things in here probably don't need to be done each time. */
494 static void control_set_hardware(struct fb_info_control *p, struct fb_par_control *par)
495 {
496         struct control_regvals  *r;
497         volatile struct preg    __iomem *rp;
498         int                     i, cmode;
499
500         if (PAR_EQUAL(&p->par, par)) {
501                 /*
502                  * check if only xoffset or yoffset differs.
503                  * this prevents flickers in typical VT switch case.
504                  */
505                 if (p->par.xoffset != par->xoffset ||
506                     p->par.yoffset != par->yoffset)
507                         set_screen_start(par->xoffset, par->yoffset, p);
508                         
509                 return;
510         }
511         
512         p->par = *par;
513         cmode = p->par.cmode;
514         r = &par->regvals;
515         
516         /* Turn off display */
517         out_le32(CNTRL_REG(p,ctrl), 0x400 | par->ctrl);
518         
519         set_control_clock(r->clock_params);
520         
521         RADACAL_WRITE(0x20, r->radacal_ctrl);
522         RADACAL_WRITE(0x21, p->control_use_bank2 ? 0 : 1);
523         RADACAL_WRITE(0x10, 0);
524         RADACAL_WRITE(0x11, 0);
525
526         rp = &p->control_regs->vswin;
527         for (i = 0; i < 16; ++i, ++rp)
528                 out_le32(&rp->r, r->regs[i]);
529         
530         out_le32(CNTRL_REG(p,pitch), par->pitch);
531         out_le32(CNTRL_REG(p,mode), r->mode);
532         out_le32(CNTRL_REG(p,vram_attr), p->vram_attr);
533         out_le32(CNTRL_REG(p,start_addr), par->yoffset * par->pitch
534                  + (par->xoffset << cmode));
535         out_le32(CNTRL_REG(p,rfrcnt), 0x1e5);
536         out_le32(CNTRL_REG(p,intr_ena), 0);
537
538         /* Turn on display */
539         out_le32(CNTRL_REG(p,ctrl), par->ctrl);
540
541 #ifdef CONFIG_BOOTX_TEXT
542         btext_update_display(p->frame_buffer_phys + CTRLFB_OFF,
543                              p->par.xres, p->par.yres,
544                              (cmode == CMODE_32? 32: cmode == CMODE_16? 16: 8),
545                              p->par.pitch);
546 #endif /* CONFIG_BOOTX_TEXT */
547 }
548
549
550 /*
551  * Parse user speficied options (`video=controlfb:')
552  */
553 static void __init control_setup(char *options)
554 {
555         char *this_opt;
556
557         if (!options || !*options)
558                 return;
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                             control_mac_modes[vmode - 1].m[1] >= 0)
565                                 default_vmode = vmode;
566                 } else if (!strncmp(this_opt, "cmode:", 6)) {
567                         int depth = simple_strtoul(this_opt+6, NULL, 0);
568                         switch (depth) {
569                          case CMODE_8:
570                          case CMODE_16:
571                          case CMODE_32:
572                                 default_cmode = depth;
573                                 break;
574                          case 8:
575                                 default_cmode = CMODE_8;
576                                 break;
577                          case 15:
578                          case 16:
579                                 default_cmode = CMODE_16;
580                                 break;
581                          case 24:
582                          case 32:
583                                 default_cmode = CMODE_32;
584                                 break;
585                         }
586                 }
587         }
588 }
589
590 static int __init control_init(void)
591 {
592         struct device_node *dp;
593         char *option = NULL;
594         int ret = -ENXIO;
595
596         if (fb_get_options("controlfb", &option))
597                 return -ENODEV;
598         control_setup(option);
599
600         dp = of_find_node_by_name(NULL, "control");
601         if (dp != 0 && !control_of_init(dp))
602                 ret = 0;
603         of_node_put(dp);
604
605         return ret;
606 }
607
608 module_init(control_init);
609
610 /* Work out which banks of VRAM we have installed. */
611 /* danj: I guess the card just ignores writes to nonexistant VRAM... */
612
613 static void __init find_vram_size(struct fb_info_control *p)
614 {
615         int bank1, bank2;
616
617         /*
618          * Set VRAM in 2MB (bank 1) mode
619          * VRAM Bank 2 will be accessible through offset 0x600000 if present
620          * and VRAM Bank 1 will not respond at that offset even if present
621          */
622         out_le32(CNTRL_REG(p,vram_attr), 0x31);
623
624         out_8(&p->frame_buffer[0x600000], 0xb3);
625         out_8(&p->frame_buffer[0x600001], 0x71);
626         asm volatile("eieio; dcbf 0,%0" : : "r" (&p->frame_buffer[0x600000])
627                                         : "memory" );
628         mb();
629         asm volatile("eieio; dcbi 0,%0" : : "r" (&p->frame_buffer[0x600000])
630                                         : "memory" );
631         mb();
632
633         bank2 = (in_8(&p->frame_buffer[0x600000]) == 0xb3)
634                 && (in_8(&p->frame_buffer[0x600001]) == 0x71);
635
636         /*
637          * Set VRAM in 2MB (bank 2) mode
638          * VRAM Bank 1 will be accessible through offset 0x000000 if present
639          * and VRAM Bank 2 will not respond at that offset even if present
640          */
641         out_le32(CNTRL_REG(p,vram_attr), 0x39);
642
643         out_8(&p->frame_buffer[0], 0x5a);
644         out_8(&p->frame_buffer[1], 0xc7);
645         asm volatile("eieio; dcbf 0,%0" : : "r" (&p->frame_buffer[0])
646                                         : "memory" );
647         mb();
648         asm volatile("eieio; dcbi 0,%0" : : "r" (&p->frame_buffer[0])
649                                         : "memory" );
650         mb();
651
652         bank1 = (in_8(&p->frame_buffer[0]) == 0x5a)
653                 && (in_8(&p->frame_buffer[1]) == 0xc7);
654
655         if (bank2) {
656                 if (!bank1) {
657                         /*
658                          * vram bank 2 only
659                          */
660                         p->control_use_bank2 = 1;
661                         p->vram_attr = 0x39;
662                         p->frame_buffer += 0x600000;
663                         p->frame_buffer_phys += 0x600000;
664                 } else {
665                         /*
666                          * 4 MB vram
667                          */
668                         p->vram_attr = 0x51;
669                 }
670         } else {
671                 /*
672                  * vram bank 1 only
673                  */
674                 p->vram_attr = 0x31;
675         }
676
677         p->total_vram = (bank1 + bank2) * 0x200000;
678
679         printk(KERN_INFO "controlfb: VRAM Total = %dMB "
680                         "(%dMB @ bank 1, %dMB @ bank 2)\n",
681                         (bank1 + bank2) << 1, bank1 << 1, bank2 << 1);
682 }
683
684
685 /*
686  * find "control" and initialize
687  */
688 static int __init control_of_init(struct device_node *dp)
689 {
690         struct fb_info_control  *p;
691         struct resource         fb_res, reg_res;
692
693         if (control_fb) {
694                 printk(KERN_ERR "controlfb: only one control is supported\n");
695                 return -ENXIO;
696         }
697
698         if (of_pci_address_to_resource(dp, 2, &fb_res) ||
699             of_pci_address_to_resource(dp, 1, &reg_res)) {
700                 printk(KERN_ERR "can't get 2 addresses for control\n");
701                 return -ENXIO;
702         }
703         p = kzalloc(sizeof(*p), GFP_KERNEL);
704         if (p == 0)
705                 return -ENXIO;
706         control_fb = p; /* save it for cleanups */
707
708         /* Map in frame buffer and registers */
709         p->fb_orig_base = fb_res.start;
710         p->fb_orig_size = fb_res.end - fb_res.start + 1;
711         /* use the big-endian aperture (??) */
712         p->frame_buffer_phys = fb_res.start + 0x800000;
713         p->control_regs_phys = reg_res.start;
714         p->control_regs_size = reg_res.end - reg_res.start + 1;
715
716         if (!p->fb_orig_base ||
717             !request_mem_region(p->fb_orig_base,p->fb_orig_size,"controlfb")) {
718                 p->fb_orig_base = 0;
719                 goto error_out;
720         }
721         /* map at most 8MB for the frame buffer */
722         p->frame_buffer = __ioremap(p->frame_buffer_phys, 0x800000,
723                                     _PAGE_WRITETHRU);
724
725         if (!p->control_regs_phys ||
726             !request_mem_region(p->control_regs_phys, p->control_regs_size,
727             "controlfb regs")) {
728                 p->control_regs_phys = 0;
729                 goto error_out;
730         }
731         p->control_regs = ioremap(p->control_regs_phys, p->control_regs_size);
732
733         p->cmap_regs_phys = 0xf301b000;  /* XXX not in prom? */
734         if (!request_mem_region(p->cmap_regs_phys, 0x1000, "controlfb cmap")) {
735                 p->cmap_regs_phys = 0;
736                 goto error_out;
737         }
738         p->cmap_regs = ioremap(p->cmap_regs_phys, 0x1000);
739
740         if (!p->cmap_regs || !p->control_regs || !p->frame_buffer)
741                 goto error_out;
742
743         find_vram_size(p);
744         if (!p->total_vram)
745                 goto error_out;
746
747         if (init_control(p) < 0)
748                 goto error_out;
749
750         return 0;
751
752 error_out:
753         control_cleanup();
754         return -ENXIO;
755 }
756
757 /*
758  * Get the monitor sense value.
759  * Note that this can be called before calibrate_delay,
760  * so we can't use udelay.
761  */
762 static int read_control_sense(struct fb_info_control *p)
763 {
764         int sense;
765
766         out_le32(CNTRL_REG(p,mon_sense), 7);    /* drive all lines high */
767         __delay(200);
768         out_le32(CNTRL_REG(p,mon_sense), 077);  /* turn off drivers */
769         __delay(2000);
770         sense = (in_le32(CNTRL_REG(p,mon_sense)) & 0x1c0) << 2;
771
772         /* drive each sense line low in turn and collect the other 2 */
773         out_le32(CNTRL_REG(p,mon_sense), 033);  /* drive A low */
774         __delay(2000);
775         sense |= (in_le32(CNTRL_REG(p,mon_sense)) & 0xc0) >> 2;
776         out_le32(CNTRL_REG(p,mon_sense), 055);  /* drive B low */
777         __delay(2000);
778         sense |= ((in_le32(CNTRL_REG(p,mon_sense)) & 0x100) >> 5)
779                 | ((in_le32(CNTRL_REG(p,mon_sense)) & 0x40) >> 4);
780         out_le32(CNTRL_REG(p,mon_sense), 066);  /* drive C low */
781         __delay(2000);
782         sense |= (in_le32(CNTRL_REG(p,mon_sense)) & 0x180) >> 7;
783
784         out_le32(CNTRL_REG(p,mon_sense), 077);  /* turn off drivers */
785         
786         return sense;
787 }
788
789 /**********************  Various translation functions  **********************/
790
791 #define CONTROL_PIXCLOCK_BASE   256016
792 #define CONTROL_PIXCLOCK_MIN    5000    /* ~ 200 MHz dot clock */
793
794 /*
795  * calculate the clock paramaters to be sent to CUDA according to given
796  * pixclock in pico second.
797  */
798 static int calc_clock_params(unsigned long clk, unsigned char *param)
799 {
800         unsigned long p0, p1, p2, k, l, m, n, min;
801
802         if (clk > (CONTROL_PIXCLOCK_BASE << 3))
803                 return 1;
804
805         p2 = ((clk << 4) < CONTROL_PIXCLOCK_BASE)? 3: 2;
806         l = clk << p2;
807         p0 = 0;
808         p1 = 0;
809         for (k = 1, min = l; k < 32; k++) {
810                 unsigned long rem;
811
812                 m = CONTROL_PIXCLOCK_BASE * k;
813                 n = m / l;
814                 rem = m % l;
815                 if (n && (n < 128) && rem < min) {
816                         p0 = k;
817                         p1 = n;
818                         min = rem;
819                 }
820         }
821         if (!p0 || !p1)
822                 return 1;
823
824         param[0] = p0;
825         param[1] = p1;
826         param[2] = p2;
827
828         return 0;
829 }
830
831
832 /*
833  * This routine takes a user-supplied var, and picks the best vmode/cmode
834  * from it.
835  */
836
837 static int control_var_to_par(struct fb_var_screeninfo *var,
838         struct fb_par_control *par, const struct fb_info *fb_info)
839 {
840         int cmode, piped_diff, hstep;
841         unsigned hperiod, hssync, hsblank, hesync, heblank, piped, heq, hlfln,
842                  hserr, vperiod, vssync, vesync, veblank, vsblank, vswin, vewin;
843         unsigned long pixclock;
844         struct fb_info_control *p = (struct fb_info_control *) fb_info;
845         struct control_regvals *r = &par->regvals;
846
847         switch (var->bits_per_pixel) {
848         case 8:
849                 par->cmode = CMODE_8;
850                 if (p->total_vram > 0x200000) {
851                         r->mode = 3;
852                         r->radacal_ctrl = 0x20;
853                         piped_diff = 13;
854                 } else {
855                         r->mode = 2;
856                         r->radacal_ctrl = 0x10;
857                         piped_diff = 9;
858                 }
859                 break;
860         case 15:
861         case 16:
862                 par->cmode = CMODE_16;
863                 if (p->total_vram > 0x200000) {
864                         r->mode = 2;
865                         r->radacal_ctrl = 0x24;
866                         piped_diff = 5;
867                 } else {
868                         r->mode = 1;
869                         r->radacal_ctrl = 0x14;
870                         piped_diff = 3;
871                 }
872                 break;
873         case 32:
874                 par->cmode = CMODE_32;
875                 if (p->total_vram > 0x200000) {
876                         r->mode = 1;
877                         r->radacal_ctrl = 0x28;
878                 } else {
879                         r->mode = 0;
880                         r->radacal_ctrl = 0x18;
881                 }
882                 piped_diff = 1;
883                 break;
884         default:
885                 return -EINVAL;
886         }
887
888         /*
889          * adjust xres and vxres so that the corresponding memory widths are
890          * 32-byte aligned
891          */
892         hstep = 31 >> par->cmode;
893         par->xres = (var->xres + hstep) & ~hstep;
894         par->vxres = (var->xres_virtual + hstep) & ~hstep;
895         par->xoffset = (var->xoffset + hstep) & ~hstep;
896         if (par->vxres < par->xres)
897                 par->vxres = par->xres;
898         par->pitch = par->vxres << par->cmode;
899
900         par->yres = var->yres;
901         par->vyres = var->yres_virtual;
902         par->yoffset = var->yoffset;
903         if (par->vyres < par->yres)
904                 par->vyres = par->yres;
905
906         par->sync = var->sync;
907
908         if (par->pitch * par->vyres + CTRLFB_OFF > p->total_vram)
909                 return -EINVAL;
910
911         if (par->xoffset + par->xres > par->vxres)
912                 par->xoffset = par->vxres - par->xres;
913         if (par->yoffset + par->yres > par->vyres)
914                 par->yoffset = par->vyres - par->yres;
915
916         pixclock = (var->pixclock < CONTROL_PIXCLOCK_MIN)? CONTROL_PIXCLOCK_MIN:
917                    var->pixclock;
918         if (calc_clock_params(pixclock, r->clock_params))
919                 return -EINVAL;
920
921         hperiod = ((var->left_margin + par->xres + var->right_margin
922                     + var->hsync_len) >> 1) - 2;
923         hssync = hperiod + 1;
924         hsblank = hssync - (var->right_margin >> 1);
925         hesync = (var->hsync_len >> 1) - 1;
926         heblank = (var->left_margin >> 1) + hesync;
927         piped = heblank - piped_diff;
928         heq = var->hsync_len >> 2;
929         hlfln = (hperiod+2) >> 1;
930         hserr = hssync-hesync;
931         vperiod = (var->vsync_len + var->lower_margin + par->yres
932                    + var->upper_margin) << 1;
933         vssync = vperiod - 2;
934         vesync = (var->vsync_len << 1) - vperiod + vssync;
935         veblank = (var->upper_margin << 1) + vesync;
936         vsblank = vssync - (var->lower_margin << 1);
937         vswin = (vsblank+vssync) >> 1;
938         vewin = (vesync+veblank) >> 1;
939
940         r->regs[0] = vswin;
941         r->regs[1] = vsblank;
942         r->regs[2] = veblank;
943         r->regs[3] = vewin;
944         r->regs[4] = vesync;
945         r->regs[5] = vssync;
946         r->regs[6] = vperiod;
947         r->regs[7] = piped;
948         r->regs[8] = hperiod;
949         r->regs[9] = hsblank;
950         r->regs[10] = heblank;
951         r->regs[11] = hesync;
952         r->regs[12] = hssync;
953         r->regs[13] = heq;
954         r->regs[14] = hlfln;
955         r->regs[15] = hserr;
956
957         if (par->xres >= 1280 && par->cmode >= CMODE_16)
958                 par->ctrl = 0x7f;
959         else
960                 par->ctrl = 0x3b;
961
962         if (mac_var_to_vmode(var, &par->vmode, &cmode))
963                 par->vmode = 0;
964
965         return 0;
966 }
967
968
969 /*
970  * Convert hardware data in par to an fb_var_screeninfo
971  */
972
973 static void control_par_to_var(struct fb_par_control *par, struct fb_var_screeninfo *var)
974 {
975         struct control_regints *rv;
976         
977         rv = (struct control_regints *) par->regvals.regs;
978         
979         memset(var, 0, sizeof(*var));
980         var->xres = par->xres;
981         var->yres = par->yres;
982         var->xres_virtual = par->vxres;
983         var->yres_virtual = par->vyres;
984         var->xoffset = par->xoffset;
985         var->yoffset = par->yoffset;
986         
987         switch(par->cmode) {
988         default:
989         case CMODE_8:
990                 var->bits_per_pixel = 8;
991                 var->red.length = 8;
992                 var->green.length = 8;
993                 var->blue.length = 8;
994                 break;
995         case CMODE_16:  /* RGB 555 */
996                 var->bits_per_pixel = 16;
997                 var->red.offset = 10;
998                 var->red.length = 5;
999                 var->green.offset = 5;
1000                 var->green.length = 5;
1001                 var->blue.length = 5;
1002                 break;
1003         case CMODE_32:  /* RGB 888 */
1004                 var->bits_per_pixel = 32;
1005                 var->red.offset = 16;
1006                 var->red.length = 8;
1007                 var->green.offset = 8;
1008                 var->green.length = 8;
1009                 var->blue.length = 8;
1010                 var->transp.offset = 24;
1011                 var->transp.length = 8;
1012                 break;
1013         }
1014         var->height = -1;
1015         var->width = -1;
1016         var->vmode = FB_VMODE_NONINTERLACED;
1017
1018         var->left_margin = (rv->heblank - rv->hesync) << 1;
1019         var->right_margin = (rv->hssync - rv->hsblank) << 1;
1020         var->hsync_len = (rv->hperiod + 2 - rv->hssync + rv->hesync) << 1;
1021
1022         var->upper_margin = (rv->veblank - rv->vesync) >> 1;
1023         var->lower_margin = (rv->vssync - rv->vsblank) >> 1;
1024         var->vsync_len = (rv->vperiod - rv->vssync + rv->vesync) >> 1;
1025
1026         var->sync = par->sync;
1027
1028         /*
1029          * 10^12 * clock_params[0] / (3906400 * clock_params[1]
1030          *                            * 2^clock_params[2])
1031          * (10^12 * clock_params[0] / (3906400 * clock_params[1]))
1032          * >> clock_params[2]
1033          */
1034         /* (255990.17 * clock_params[0] / clock_params[1]) >> clock_params[2] */
1035         var->pixclock = CONTROL_PIXCLOCK_BASE * par->regvals.clock_params[0];
1036         var->pixclock /= par->regvals.clock_params[1];
1037         var->pixclock >>= par->regvals.clock_params[2];
1038 }
1039
1040 /*
1041  * Set misc info vars for this driver
1042  */
1043 static void __init control_init_info(struct fb_info *info, struct fb_info_control *p)
1044 {
1045         /* Fill fb_info */
1046         info->par = &p->par;
1047         info->fbops = &controlfb_ops;
1048         info->pseudo_palette = p->pseudo_palette;
1049         info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
1050         info->screen_base = p->frame_buffer + CTRLFB_OFF;
1051
1052         fb_alloc_cmap(&info->cmap, 256, 0);
1053
1054         /* Fill fix common fields */
1055         strcpy(info->fix.id, "control");
1056         info->fix.mmio_start = p->control_regs_phys;
1057         info->fix.mmio_len = sizeof(struct control_regs);
1058         info->fix.type = FB_TYPE_PACKED_PIXELS;
1059         info->fix.smem_start = p->frame_buffer_phys + CTRLFB_OFF;
1060         info->fix.smem_len = p->total_vram - CTRLFB_OFF;
1061         info->fix.ywrapstep = 0;
1062         info->fix.type_aux = 0;
1063         info->fix.accel = FB_ACCEL_NONE;
1064 }
1065
1066
1067 static void control_cleanup(void)
1068 {
1069         struct fb_info_control  *p = control_fb;
1070
1071         if (!p)
1072                 return;
1073
1074         if (p->cmap_regs)
1075                 iounmap(p->cmap_regs);
1076         if (p->control_regs)
1077                 iounmap(p->control_regs);
1078         if (p->frame_buffer) {
1079                 if (p->control_use_bank2)
1080                         p->frame_buffer -= 0x600000;
1081                 iounmap(p->frame_buffer);
1082         }
1083         if (p->cmap_regs_phys)
1084                 release_mem_region(p->cmap_regs_phys, 0x1000);
1085         if (p->control_regs_phys)
1086                 release_mem_region(p->control_regs_phys, p->control_regs_size);
1087         if (p->fb_orig_base)
1088                 release_mem_region(p->fb_orig_base, p->fb_orig_size);
1089         kfree(p);
1090 }
1091
1092