The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/drivers/video/valkyriefb.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  *  valkyriefb.c -- frame buffer device for the PowerMac 'valkyrie' display
    3  *
    4  *  Created 8 August 1998 by 
    5  *  Martin Costabel <costabel@wanadoo.fr> and Kevin Schoedel
    6  *
    7  *  Vmode-switching changes and vmode 15/17 modifications created 29 August
    8  *  1998 by Barry K. Nathan <barryn@pobox.com>.
    9  *
   10  *  Ported to m68k Macintosh by David Huggins-Daines <dhd@debian.org>
   11  *
   12  *  Derived directly from:
   13  *
   14  *   controlfb.c -- frame buffer device for the PowerMac 'control' display
   15  *   Copyright (C) 1998 Dan Jacobowitz <dan@debian.org>
   16  *
   17  *   pmc-valkyrie.c -- Console support for PowerMac "valkyrie" display adaptor.
   18  *   Copyright (C) 1997 Paul Mackerras.
   19  *
   20  *  and indirectly:
   21  *
   22  *  Frame buffer structure from:
   23  *    drivers/video/chipsfb.c -- frame buffer device for
   24  *    Chips & Technologies 65550 chip.
   25  *
   26  *    Copyright (C) 1998 Paul Mackerras
   27  *
   28  *    This file is derived from the Powermac "chips" driver:
   29  *    Copyright (C) 1997 Fabio Riccardi.
   30  *    And from the frame buffer device for Open Firmware-initialized devices:
   31  *    Copyright (C) 1997 Geert Uytterhoeven.
   32  *
   33  *  Hardware information from:
   34  *    control.c: Console support for PowerMac "control" display adaptor.
   35  *    Copyright (C) 1996 Paul Mackerras
   36  *
   37  *  This file is subject to the terms and conditions of the GNU General Public
   38  *  License. See the file COPYING in the main directory of this archive for
   39  *  more details.
   40  */
   41 
   42 #include <linux/config.h>
   43 #include <linux/module.h>
   44 #include <linux/kernel.h>
   45 #include <linux/errno.h>
   46 #include <linux/string.h>
   47 #include <linux/mm.h>
   48 #include <linux/tty.h>
   49 #include <linux/slab.h>
   50 #include <linux/vmalloc.h>
   51 #include <linux/delay.h>
   52 #include <linux/interrupt.h>
   53 #include <linux/fb.h>
   54 #include <linux/selection.h>
   55 #include <linux/init.h>
   56 #include <linux/pci.h>
   57 #include <linux/nvram.h>
   58 #ifdef CONFIG_FB_COMPAT_XPMAC
   59 #include <asm/vc_ioctl.h>
   60 #endif
   61 #include <linux/adb.h>
   62 #include <linux/cuda.h>
   63 #include <asm/io.h>
   64 #ifdef CONFIG_MAC
   65 #include <asm/bootinfo.h>
   66 #include <asm/macintosh.h>
   67 #else
   68 #include <asm/prom.h>
   69 #endif
   70 #include <asm/pgtable.h>
   71 
   72 #include <video/fbcon.h>
   73 #include <video/fbcon-cfb8.h>
   74 #include <video/fbcon-cfb16.h>
   75 #include <video/macmodes.h>
   76 
   77 #include "valkyriefb.h"
   78 
   79 static int can_soft_blank = 1;
   80 
   81 #ifdef CONFIG_MAC
   82 /* We don't yet have functions to read the PRAM... perhaps we can
   83    adapt them from the PPC code? */
   84 static int default_vmode = VMODE_640_480_67;
   85 static int default_cmode = CMODE_8;
   86 #else
   87 static int default_vmode = VMODE_NVRAM;
   88 static int default_cmode = CMODE_NVRAM;
   89 #endif
   90 static char fontname[40] __initdata = { 0 };
   91 
   92 static int currcon = 0;
   93 static int switching = 0;
   94 
   95 struct fb_par_valkyrie {
   96         int     vmode, cmode;
   97         int     xres, yres;
   98         int     vxres, vyres;
   99         int     xoffset, yoffset;
  100 };
  101 
  102 struct fb_info_valkyrie {
  103         struct fb_info                  info;
  104         struct fb_fix_screeninfo        fix;
  105         struct fb_var_screeninfo        var;
  106         struct display                  disp;
  107         struct fb_par_valkyrie          par;
  108         struct {
  109             __u8 red, green, blue;
  110         }                       palette[256];
  111         
  112         struct cmap_regs        *cmap_regs;
  113         unsigned long           cmap_regs_phys;
  114         
  115         struct valkyrie_regs    *valkyrie_regs;
  116         unsigned long           valkyrie_regs_phys;
  117         
  118         __u8                    *frame_buffer;
  119         unsigned long           frame_buffer_phys;
  120         
  121         int                     sense;
  122         unsigned long           total_vram;
  123 #ifdef FBCON_HAS_CFB16
  124         u16 fbcon_cfb16_cmap[16];
  125 #endif
  126 };
  127 
  128 /*
  129  * Exported functions
  130  */
  131 int valkyriefb_init(void);
  132 int valkyriefb_setup(char*);
  133 
  134 static int valkyrie_get_fix(struct fb_fix_screeninfo *fix, int con,
  135                          struct fb_info *info);
  136 static int valkyrie_get_var(struct fb_var_screeninfo *var, int con,
  137                          struct fb_info *info);
  138 static int valkyrie_set_var(struct fb_var_screeninfo *var, int con,
  139                          struct fb_info *info);
  140 static int valkyrie_get_cmap(struct fb_cmap *cmap, int kspc, int con,
  141                           struct fb_info *info);
  142 static int valkyrie_set_cmap(struct fb_cmap *cmap, int kspc, int con,
  143                           struct fb_info *info);
  144 
  145 static int read_valkyrie_sense(struct fb_info_valkyrie *p);
  146 static inline int valkyrie_vram_reqd(int video_mode, int color_mode);
  147 static void set_valkyrie_clock(unsigned char *params);
  148 static void valkyrie_set_par(const struct fb_par_valkyrie *p, struct fb_info_valkyrie *info);
  149 static inline int valkyrie_par_to_var(struct fb_par_valkyrie *par, struct fb_var_screeninfo *var);
  150 static int valkyrie_var_to_par(struct fb_var_screeninfo *var,
  151         struct fb_par_valkyrie *par, const struct fb_info *fb_info);
  152 
  153 static void valkyrie_init_info(struct fb_info *info, struct fb_info_valkyrie *p);
  154 static void valkyrie_par_to_display(struct fb_par_valkyrie *par,
  155   struct display *disp, struct fb_fix_screeninfo *fix, struct fb_info_valkyrie *p);
  156 static void valkyrie_init_display(struct display *disp);
  157 static void valkyrie_par_to_fix(struct fb_par_valkyrie *par, struct fb_fix_screeninfo *fix,
  158         struct fb_info_valkyrie *p);
  159 static void valkyrie_init_fix(struct fb_fix_screeninfo *fix, struct fb_info_valkyrie *p);
  160 
  161 static struct fb_ops valkyriefb_ops = {
  162         owner:          THIS_MODULE,
  163         fb_get_fix:     valkyrie_get_fix,
  164         fb_get_var:     valkyrie_get_var,
  165         fb_set_var:     valkyrie_set_var,
  166         fb_get_cmap:    valkyrie_get_cmap,
  167         fb_set_cmap:    valkyrie_set_cmap,
  168 };
  169 
  170 static int valkyriefb_getcolreg(u_int regno, u_int *red, u_int *green,
  171                              u_int *blue, u_int *transp, struct fb_info *info);
  172 static int valkyriefb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
  173                              u_int transp, struct fb_info *info);
  174 static void do_install_cmap(int con, struct fb_info *info);
  175 
  176 static int valkyrie_get_fix(struct fb_fix_screeninfo *fix, int con,
  177                          struct fb_info *info)
  178 {
  179         struct fb_info_valkyrie *cp = (struct fb_info_valkyrie *) info;
  180 
  181         *fix = cp->fix;
  182         return 0;
  183 }
  184 
  185 static int valkyrie_get_var(struct fb_var_screeninfo *var, int con,
  186                          struct fb_info *info)
  187 {
  188         struct fb_info_valkyrie *cp = (struct fb_info_valkyrie *) info;
  189 
  190         *var = cp->var;
  191         return 0;
  192 }
  193 
  194 /* Sets everything according to var */
  195 static int valkyrie_set_var(struct fb_var_screeninfo *var, int con,
  196                          struct fb_info *info)
  197 {
  198         struct fb_info_valkyrie *p = (struct fb_info_valkyrie *) info;
  199         struct display *disp;
  200         struct fb_par_valkyrie par;
  201         int depthchange, err;
  202 
  203         disp = (con >= 0) ? &fb_display[con] : &p->disp;
  204         if ((err = valkyrie_var_to_par(var, &par, info))) {
  205                  /* printk (KERN_ERR "Error in valkyrie_set_var, calling valkyrie_var_to_par: %d.\n", err); */
  206                 return err;
  207         }
  208         
  209         if ((var->activate & FB_ACTIVATE_MASK) != FB_ACTIVATE_NOW) {
  210                 /* printk(KERN_ERR "Not activating, in valkyrie_set_var.\n"); */
  211                 valkyrie_par_to_var(&par, var);
  212                 return 0;
  213         }
  214 
  215         /*
  216          * I know, we want to use fb_display[con], but grab certain info
  217          * from p->var instead.
  218          */
  219 #define DIRTY(x) (p->var.x != var->x)
  220         depthchange = DIRTY(bits_per_pixel);
  221         /* adding "&& !DIRTY(pixclock)" corrects vmode-switching problems */
  222         if(!DIRTY(xres) && !DIRTY(yres) && !DIRTY(xres_virtual) &&
  223            !DIRTY(yres_virtual) && !DIRTY(bits_per_pixel) && !DIRTY(pixclock)) {
  224                 valkyrie_par_to_var(&par, var);
  225                 p->var = disp->var = *var;
  226                 return 0;
  227         }
  228 
  229         p->par = par;
  230         valkyrie_par_to_var(&par, var);
  231         p->var = *var;
  232         valkyrie_par_to_fix(&par, &p->fix, p);
  233         valkyrie_par_to_display(&par, disp, &p->fix, p);
  234         p->disp = *disp;
  235         
  236         if (info->changevar && !switching) {
  237                 /* Don't want to do this if just switching consoles. */
  238                 (*info->changevar)(con);
  239         }
  240         if (con == currcon)
  241                 valkyrie_set_par(&par, p);
  242         if (depthchange)
  243                 if ((err = fb_alloc_cmap(&disp->cmap, 0, 0)))
  244                         return err;
  245         if (depthchange || switching)
  246                 do_install_cmap(con, info);
  247         return 0;
  248 }
  249 
  250 static int valkyrie_get_cmap(struct fb_cmap *cmap, int kspc, int con,
  251                           struct fb_info *info)
  252 {
  253         if (con == currcon)     {
  254                 /* current console? */
  255                 return fb_get_cmap(cmap, kspc, valkyriefb_getcolreg, info);
  256         }
  257         if (fb_display[con].cmap.len) { /* non default colormap? */
  258                 fb_copy_cmap(&fb_display[con].cmap, cmap, kspc? 0: 2);
  259         }
  260         else {
  261                 int size = fb_display[con].var.bits_per_pixel == 16 ? 32 : 256;
  262                 fb_copy_cmap(fb_default_cmap(size), cmap, kspc ? 0 : 2);
  263         }
  264         return 0;
  265 }
  266 
  267 static int valkyrie_set_cmap(struct fb_cmap *cmap, int kspc, int con,
  268                          struct fb_info *info)
  269 {
  270         struct display *disp = &fb_display[con];
  271         int err;
  272 
  273         if (disp->cmap.len == 0) {
  274                 int size = fb_display[con].var.bits_per_pixel == 16 ? 32 : 256;
  275                 err = fb_alloc_cmap(&disp->cmap, size, 0);
  276                 if (err) {
  277                         return err;
  278                 }
  279         }
  280 
  281         if (con == currcon) {
  282                 return fb_set_cmap(cmap, kspc, valkyriefb_setcolreg, info);
  283         }
  284         fb_copy_cmap(cmap, &disp->cmap, kspc ? 0 : 1);
  285         return 0;
  286 }
  287 
  288 static int valkyriefb_switch(int con, struct fb_info *fb)
  289 {
  290         struct fb_info_valkyrie *info = (struct fb_info_valkyrie *) fb;
  291         struct fb_par_valkyrie par;
  292 
  293         if (fb_display[currcon].cmap.len)
  294                 fb_get_cmap(&fb_display[currcon].cmap, 1, valkyriefb_getcolreg,
  295                             fb);
  296         currcon = con;
  297 #if 1
  298         valkyrie_var_to_par(&fb_display[currcon].var, &par, fb);
  299         valkyrie_set_par(&par, info);
  300         do_install_cmap(con, fb);
  301 #else
  302         /* I see no reason not to do this.  Minus info->changevar(). */
  303         /* DOH.  This makes valkyrie_set_var compare, you guessed it, */
  304         /* fb_display[con].var (first param), and fb_display[con].var! */
  305         /* Perhaps I just fixed that... */
  306         switching = 1;
  307         valkyrie_set_var(&fb_display[con].var, con, info);
  308         switching = 0;
  309 #endif
  310         return 0;
  311 }
  312 
  313 static int valkyriefb_updatevar(int con, struct fb_info *info)
  314 {
  315         return 0;
  316 }
  317 
  318 static void valkyriefb_blank(int blank_mode, struct fb_info *info)
  319 {
  320 /*
  321  *  Blank the screen if blank_mode != 0, else unblank. If blank_mode == NULL
  322  *  then the caller blanks by setting the CLUT (Color Look Up Table) to all
  323  *  black. Return 0 if blanking succeeded, != 0 if un-/blanking failed due
  324  *  to e.g. a video mode which doesn't support it. Implements VESA suspend
  325  *  and powerdown modes on hardware that supports disabling hsync/vsync:
  326  *    blank_mode == 2: suspend vsync
  327  *    blank_mode == 3: suspend hsync
  328  *    blank_mode == 4: powerdown
  329  */
  330         struct fb_info_valkyrie *p = (struct fb_info_valkyrie *) info;
  331         struct valkyrie_regvals *init;
  332         unsigned char vmode;
  333 
  334         if (p->disp.can_soft_blank
  335          && ((vmode = p->par.vmode) > 0)
  336          && (vmode <= VMODE_MAX)
  337          && ((init = valkyrie_reg_init[vmode - 1]) != NULL)) {
  338                 if (blank_mode)
  339                         --blank_mode;
  340                 switch (blank_mode) {
  341                 default:        /* unblank */
  342                         out_8(&p->valkyrie_regs->mode.r, init->mode);
  343                         break;
  344                 case VESA_VSYNC_SUSPEND:
  345                 case VESA_HSYNC_SUSPEND:
  346                         /*
  347                          * [kps] Value extracted from MacOS. I don't know
  348                          * whether this bit disables hsync or vsync, or
  349                          * whether the hardware can do the other as well.
  350                          */
  351                         out_8(&p->valkyrie_regs->mode.r, init->mode | 0x40);
  352                         break;
  353                 case VESA_POWERDOWN:
  354                         out_8(&p->valkyrie_regs->mode.r, 0x66);
  355                         break;
  356                 }
  357         }
  358 }
  359 
  360 static int valkyriefb_getcolreg(u_int regno, u_int *red, u_int *green,
  361                              u_int *blue, u_int *transp, struct fb_info *info)
  362 {
  363         struct fb_info_valkyrie *p = (struct fb_info_valkyrie *) info;
  364 
  365         if (regno > 255)
  366                 return 1;
  367         *red = (p->palette[regno].red<<8) | p->palette[regno].red;
  368         *green = (p->palette[regno].green<<8) | p->palette[regno].green;
  369         *blue = (p->palette[regno].blue<<8) | p->palette[regno].blue;
  370 
  371         return 0;
  372 }
  373 
  374 static int valkyriefb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
  375                              u_int transp, struct fb_info *info)
  376 {
  377         struct fb_info_valkyrie *p = (struct fb_info_valkyrie *) info;
  378         volatile struct cmap_regs *cmap_regs = p->cmap_regs;
  379 
  380 
  381         if (regno > 255)
  382                 return 1;
  383         red >>= 8;
  384         green >>= 8;
  385         blue >>= 8;
  386         p->palette[regno].red = red;
  387         p->palette[regno].green = green;
  388         p->palette[regno].blue = blue;
  389 
  390         /* tell clut which address to fill */
  391         out_8(&p->cmap_regs->addr, regno);
  392         udelay(1);
  393         /* send one color channel at a time */
  394         out_8(&cmap_regs->lut, red);
  395         out_8(&cmap_regs->lut, green);
  396         out_8(&cmap_regs->lut, blue);
  397 
  398         if (regno < 16) {
  399 #ifdef FBCON_HAS_CFB16
  400                 p->fbcon_cfb16_cmap[regno] = (regno << 10) | (regno << 5) | regno;
  401 #endif
  402         }
  403 
  404         return 0;
  405 }
  406 
  407 static void do_install_cmap(int con, struct fb_info *info)
  408 {
  409         if (con != currcon)
  410                 return;
  411         if (fb_display[con].cmap.len) {
  412                 fb_set_cmap(&fb_display[con].cmap, 1, valkyriefb_setcolreg,
  413                             info);
  414         }
  415         else {
  416                 int size = fb_display[con].var.bits_per_pixel == 16 ? 32 : 256;
  417                 fb_set_cmap(fb_default_cmap(size), 1, valkyriefb_setcolreg,
  418                             info);
  419         }
  420 }
  421 
  422 #ifdef CONFIG_FB_COMPAT_XPMAC
  423 extern struct vc_mode display_info;
  424 extern struct fb_info *console_fb_info;
  425 #endif /* CONFIG_FB_COMPAT_XPMAC */
  426 
  427 static int valkyrie_vram_reqd(int video_mode, int color_mode)
  428 {
  429         int pitch;
  430         
  431         if ((pitch = valkyrie_reg_init[video_mode-1]->pitch[color_mode]) == 0)
  432                 pitch = 2 * valkyrie_reg_init[video_mode-1]->pitch[0];
  433         return valkyrie_reg_init[video_mode-1]->vres * pitch;
  434 }
  435 
  436 static void set_valkyrie_clock(unsigned char *params)
  437 {
  438         struct adb_request req;
  439         int i;
  440 
  441 #ifdef CONFIG_ADB_CUDA
  442         for (i = 0; i < 3; ++i) {
  443                 cuda_request(&req, NULL, 5, CUDA_PACKET, CUDA_GET_SET_IIC,
  444                              0x50, i + 1, params[i]);
  445                 while (!req.complete)
  446                         cuda_poll();
  447         }
  448 #endif
  449 }
  450 
  451 static void __init init_valkyrie(struct fb_info_valkyrie *p)
  452 {
  453         struct fb_par_valkyrie *par = &p->par;
  454         struct fb_var_screeninfo var;
  455         int j, k;
  456 
  457         p->sense = read_valkyrie_sense(p);
  458         printk(KERN_INFO "Monitor sense value = 0x%x, ", p->sense);
  459 
  460 #ifdef CONFIG_NVRAM
  461         /* Try to pick a video mode out of NVRAM if we have one. */
  462         if (default_vmode == VMODE_NVRAM) {
  463                 default_vmode = nvram_read_byte(NV_VMODE);
  464                 if (default_vmode <= 0
  465                  || default_vmode > VMODE_MAX
  466                  || !valkyrie_reg_init[default_vmode - 1])
  467                         default_vmode = VMODE_CHOOSE;
  468         }
  469         if (default_cmode == CMODE_NVRAM)
  470                 default_cmode = nvram_read_byte(NV_CMODE);
  471 #endif
  472         if (default_vmode == VMODE_CHOOSE)
  473                 default_vmode = mac_map_monitor_sense(p->sense);
  474         if (!valkyrie_reg_init[default_vmode - 1])
  475                 default_vmode = VMODE_640_480_67;
  476 
  477         /*
  478          * Reduce the pixel size if we don't have enough VRAM or bandwitdh.
  479          */
  480         if (default_cmode < CMODE_8
  481          || default_cmode > CMODE_16
  482          || valkyrie_reg_init[default_vmode-1]->pitch[default_cmode] == 0
  483          || valkyrie_vram_reqd(default_vmode, default_cmode) > p->total_vram)
  484                 default_cmode = CMODE_8;
  485         
  486         printk(KERN_INFO "using video mode %d and color mode %d.\n", default_vmode, default_cmode);
  487 
  488         mac_vmode_to_var(default_vmode, default_cmode, &var);
  489         if (valkyrie_var_to_par(&var, par, &p->info)) {
  490             printk(KERN_ERR "valkyriefb: can't set default video mode\n");
  491             return ;
  492         }
  493         
  494         valkyrie_init_fix(&p->fix, p);
  495         valkyrie_par_to_fix(&p->par, &p->fix, p);
  496         valkyrie_par_to_var(&p->par, &p->var);
  497         valkyrie_init_display(&p->disp);
  498         valkyrie_par_to_display(&p->par, &p->disp, &p->fix, p);
  499         valkyrie_init_info(&p->info, p);
  500 
  501         /* Initialize colormap */
  502         for (j = 0; j < 16; j++) {
  503                 k = color_table[j];
  504                 p->palette[j].red = default_red[k];
  505                 p->palette[j].green = default_grn[k];
  506                 p->palette[j].blue = default_blu[k];
  507         }
  508         
  509         valkyrie_set_var (&var, -1, &p->info);
  510 
  511         if (register_framebuffer(&p->info) < 0) {
  512                 kfree(p);
  513                 return;
  514         }
  515         
  516         printk(KERN_INFO "fb%d: valkyrie frame buffer device\n", GET_FB_IDX(p->info.node));     
  517 }
  518 
  519 static void valkyrie_set_par(const struct fb_par_valkyrie *par,
  520                              struct fb_info_valkyrie *p)
  521 {
  522         struct valkyrie_regvals *init;
  523         volatile struct valkyrie_regs *valkyrie_regs = p->valkyrie_regs;
  524         int vmode, cmode;
  525         
  526         vmode = par->vmode;
  527         cmode = par->cmode;
  528         
  529         if (vmode <= 0
  530          || vmode > VMODE_MAX
  531          || (init = valkyrie_reg_init[vmode - 1]) == NULL)
  532                 panic("valkyrie: display mode %d not supported", vmode);
  533 
  534         /* Reset the valkyrie */
  535         out_8(&valkyrie_regs->status.r, 0);
  536         udelay(100);
  537 
  538         /* Initialize display timing registers */
  539         out_8(&valkyrie_regs->mode.r, init->mode | 0x80);
  540         out_8(&valkyrie_regs->depth.r, cmode + 3);
  541         set_valkyrie_clock(init->clock_params);
  542         udelay(100);
  543 
  544         /* Turn on display */
  545         out_8(&valkyrie_regs->mode.r, init->mode);
  546 
  547 #ifdef CONFIG_FB_COMPAT_XPMAC
  548         /* And let the world know the truth. */
  549         if (!console_fb_info || console_fb_info == &p->info) {
  550                 display_info.height = p->var.yres;
  551                 display_info.width = p->var.xres;
  552                 display_info.depth = (cmode == CMODE_16) ? 16 : 8;
  553                 display_info.pitch = p->fix.line_length;
  554                 display_info.mode = vmode;
  555                 strncpy(display_info.name, "valkyrie",
  556                         sizeof(display_info.name));
  557                 display_info.fb_address = p->frame_buffer_phys + 0x1000;
  558                 display_info.cmap_adr_address = p->cmap_regs_phys;
  559                 display_info.cmap_data_address = p->cmap_regs_phys + 8;
  560                 display_info.disp_reg_address = p->valkyrie_regs_phys;
  561                 console_fb_info = &p->info;
  562         }
  563 #endif /* CONFIG_FB_COMPAT_XPMAC */
  564 }
  565 
  566 int __init valkyriefb_init(void)
  567 {
  568         struct fb_info_valkyrie *p;
  569         unsigned long frame_buffer_phys, cmap_regs_phys, flags;
  570 
  571 #ifdef CONFIG_MAC
  572         if (!MACH_IS_MAC)
  573                 return 0;
  574         if (!(mac_bi_data.id == MAC_MODEL_Q630
  575               /* I'm not sure about this one */
  576             || mac_bi_data.id == MAC_MODEL_P588))
  577                 return 0;
  578 
  579         /* Hardcoded addresses... welcome to 68k Macintosh country :-) */
  580         frame_buffer_phys = 0xf9000000;
  581         cmap_regs_phys = 0x50f24000;
  582         flags = IOMAP_NOCACHE_SER; /* IOMAP_WRITETHROUGH?? */
  583 #else /* ppc (!CONFIG_MAC) */
  584         struct device_node *dp;
  585 
  586         dp = find_devices("valkyrie");
  587         if (dp == 0)
  588                 return 0;
  589 
  590         if(dp->n_addrs != 1) {
  591                 printk(KERN_ERR "expecting 1 address for valkyrie (got %d)", dp->n_addrs);
  592                 return 0;
  593         }       
  594 
  595         frame_buffer_phys = dp->addrs[0].address;
  596         cmap_regs_phys = dp->addrs[0].address+0x304000;
  597         flags = _PAGE_WRITETHRU;
  598 #endif /* ppc (!CONFIG_MAC) */
  599 
  600         p = kmalloc(sizeof(*p), GFP_ATOMIC);
  601         if (p == 0)
  602                 return 0;
  603         memset(p, 0, sizeof(*p));
  604 
  605         /* Map in frame buffer and registers */
  606         if (!request_mem_region(frame_buffer_phys, 0x100000, "valkyriefb")) {
  607                 kfree(p);
  608                 return 0;
  609         }
  610         p->total_vram = 0x100000;
  611         p->frame_buffer_phys  = frame_buffer_phys;
  612         p->frame_buffer = __ioremap(frame_buffer_phys, p->total_vram, flags);
  613         p->cmap_regs_phys = cmap_regs_phys;
  614         p->cmap_regs = ioremap(p->cmap_regs_phys, 0x1000);
  615         p->valkyrie_regs_phys = cmap_regs_phys+0x6000;
  616         p->valkyrie_regs = ioremap(p->valkyrie_regs_phys, 0x1000);
  617         init_valkyrie(p);
  618         return 0;
  619 }
  620 
  621 /*
  622  * Get the monitor sense value.
  623  */
  624 static int read_valkyrie_sense(struct fb_info_valkyrie *p)
  625 {
  626         int sense, in;
  627 
  628     out_8(&p->valkyrie_regs->msense.r, 0);   /* release all lines */
  629     __delay(20000);
  630     sense = ((in = in_8(&p->valkyrie_regs->msense.r)) & 0x70) << 4;
  631     /* drive each sense line low in turn and collect the other 2 */
  632     out_8(&p->valkyrie_regs->msense.r, 4);   /* drive A low */
  633     __delay(20000);
  634     sense |= ((in = in_8(&p->valkyrie_regs->msense.r)) & 0x30);
  635     out_8(&p->valkyrie_regs->msense.r, 2);   /* drive B low */
  636     __delay(20000);
  637     sense |= ((in = in_8(&p->valkyrie_regs->msense.r)) & 0x40) >> 3;
  638         sense |= (in & 0x10) >> 2;
  639     out_8(&p->valkyrie_regs->msense.r, 1);   /* drive C low */
  640     __delay(20000);
  641     sense |= ((in = in_8(&p->valkyrie_regs->msense.r)) & 0x60) >> 5;
  642 
  643     out_8(&p->valkyrie_regs->msense.r, 7);
  644 
  645         return sense;
  646 }
  647 
  648 /*
  649  * This routine takes a user-supplied var,
  650  * and picks the best vmode/cmode from it.
  651  */
  652 static int valkyrie_var_to_par(struct fb_var_screeninfo *var,
  653         struct fb_par_valkyrie *par, const struct fb_info *fb_info)
  654 
  655 /* [bkn] I did a major overhaul of this function.
  656  *
  657  * Much of the old code was "swiped by jonh from atyfb.c". Because
  658  * macmodes has mac_var_to_vmode, I felt that it would be better to
  659  * rework this function to use that, instead of reinventing the wheel to
  660  * add support for vmode 17. This was reinforced by the fact that
  661  * the previously swiped atyfb.c code is no longer there.
  662  *
  663  * So, I swiped and adapted platinum_var_to_par (from platinumfb.c), replacing
  664  * most, but not all, of the old code in the process. One side benefit of
  665  * swiping the platinumfb code is that we now have more comprehensible error
  666  * messages when a vmode/cmode switch fails. (Most of the error messages are
  667  * platinumfb.c, but I added two of my own, and I also changed some commas
  668  * into colons to make the messages more consistent with other Linux error
  669  * messages.) In addition, I think the new code *might* fix some vmode-
  670  * switching oddities, but I'm not sure.
  671  *
  672  * There may be some more opportunities for cleanup in here, but this is a
  673  * good start...
  674  */
  675 
  676 {
  677         int bpp = var->bits_per_pixel;
  678         struct valkyrie_regvals *init;
  679         struct fb_info_valkyrie *p = (struct fb_info_valkyrie *) fb_info;
  680 
  681 
  682         if(mac_var_to_vmode(var, &par->vmode, &par->cmode) != 0) {
  683                 printk(KERN_ERR "valkyrie_var_to_par: %dx%dx%d unsuccessful.\n",var->xres,var->yres,var->bits_per_pixel);
  684                 return -EINVAL;
  685         }
  686 
  687         /* Check if we know about the wanted video mode */
  688         if(!valkyrie_reg_init[par->vmode-1]) {
  689                 printk(KERN_ERR "valkyrie_var_to_par: vmode %d not valid.\n", par->vmode);
  690                 return -EINVAL;
  691         }
  692 
  693         par->xres = var->xres;
  694         par->yres = var->yres;
  695         par->xoffset = 0;
  696         par->yoffset = 0;
  697         par->vxres = par->xres;
  698         par->vyres = par->yres;
  699         
  700         if (var->xres_virtual > var->xres || var->yres_virtual > var->yres
  701                 || var->xoffset != 0 || var->yoffset != 0) {
  702                 return -EINVAL;
  703         }
  704 
  705         if (bpp <= 8)
  706                 par->cmode = CMODE_8;
  707         else if (bpp <= 16)
  708                 par->cmode = CMODE_16;
  709         else {
  710                 printk(KERN_ERR "valkyrie_var_to_par: cmode %d not supported.\n", par->cmode);
  711                 return -EINVAL;
  712         }
  713 
  714         init = valkyrie_reg_init[par->vmode-1];
  715         if (init->pitch[par->cmode] == 0) {
  716                 printk(KERN_ERR "valkyrie_var_to_par: vmode %d does not support cmode %d.\n", par->vmode, par->cmode);
  717                 return -EINVAL;
  718         }
  719 
  720         if (valkyrie_vram_reqd(par->vmode, par->cmode) > p->total_vram) {
  721                 printk(KERN_ERR "valkyrie_var_to_par: not enough ram for vmode %d, cmode %d.\n", par->vmode, par->cmode);
  722                 return -EINVAL;
  723         }
  724 
  725         return 0;
  726 }
  727 
  728 static int valkyrie_par_to_var(struct fb_par_valkyrie *par, struct fb_var_screeninfo *var)
  729 {
  730         return mac_vmode_to_var(par->vmode, par->cmode, var);
  731 }
  732 
  733 static void valkyrie_init_fix(struct fb_fix_screeninfo *fix, struct fb_info_valkyrie *p)
  734 {
  735         memset(fix, 0, sizeof(*fix));
  736         strcpy(fix->id, "valkyrie");
  737         fix->mmio_start = p->valkyrie_regs_phys;
  738         fix->mmio_len = sizeof(struct valkyrie_regs);
  739         fix->type = FB_TYPE_PACKED_PIXELS;
  740         
  741         fix->type_aux = 0;
  742         fix->ywrapstep = 0;
  743         fix->ypanstep = 0;
  744         fix->xpanstep = 0;
  745         
  746 }
  747 
  748 /* Fix must already be inited above */
  749 static void valkyrie_par_to_fix(struct fb_par_valkyrie *par,
  750         struct fb_fix_screeninfo *fix,
  751         struct fb_info_valkyrie *p)
  752 {
  753         fix->smem_start = p->frame_buffer_phys + 0x1000;
  754 #if 1
  755         fix->smem_len = valkyrie_vram_reqd(par->vmode, par->cmode);
  756 #else
  757         fix->smem_len = p->total_vram;
  758 #endif
  759         fix->visual = (par->cmode == CMODE_8) ?
  760                 FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR;
  761         fix->line_length = par->vxres << par->cmode;
  762                 /* ywrapstep, xpanstep, ypanstep */
  763 }
  764 
  765 static void valkyrie_init_display(struct display *disp)
  766 {
  767         memset(disp, 0, sizeof(*disp));
  768         disp->type = /* fix->type */ FB_TYPE_PACKED_PIXELS;
  769         disp->can_soft_blank = can_soft_blank;
  770         disp->scrollmode = SCROLL_YREDRAW;
  771 }
  772 
  773 static void valkyrie_par_to_display(struct fb_par_valkyrie *par,
  774   struct display *disp, struct fb_fix_screeninfo *fix, struct fb_info_valkyrie *p)
  775 {
  776         disp->var = p->var;
  777         disp->screen_base = (char *) p->frame_buffer + 0x1000;
  778         disp->visual = fix->visual;
  779         disp->line_length = fix->line_length;
  780 
  781         if(disp->scrollmode != SCROLL_YREDRAW) {
  782                 printk(KERN_ERR "Scroll mode not YREDRAW in valkyrie_par_to_display\n");
  783                 disp->scrollmode = SCROLL_YREDRAW;
  784         }
  785         switch (par->cmode) {
  786 #ifdef FBCON_HAS_CFB8
  787                 case CMODE_8:
  788                         disp->dispsw = &fbcon_cfb8;
  789                         break;
  790 #endif
  791 #ifdef FBCON_HAS_CFB16
  792                 case CMODE_16:
  793                         disp->dispsw = &fbcon_cfb16;
  794                         disp->dispsw_data = p->fbcon_cfb16_cmap;
  795                         break;
  796 #endif
  797                 default:
  798                         disp->dispsw = &fbcon_dummy;
  799                         break;
  800         }
  801 }
  802 
  803 static void __init valkyrie_init_info(struct fb_info *info, struct fb_info_valkyrie *p)
  804 {
  805         strcpy(info->modename, p->fix.id);
  806         info->node = -1;        /* ??? danj */
  807         info->fbops = &valkyriefb_ops;
  808         info->disp = &p->disp;
  809         strcpy(info->fontname, fontname);
  810         info->changevar = NULL;
  811         info->switch_con = &valkyriefb_switch;
  812         info->updatevar = &valkyriefb_updatevar;
  813         info->blank = &valkyriefb_blank;
  814         info->flags = FBINFO_FLAG_DEFAULT;
  815 }
  816 
  817 
  818 /*
  819  * Parse user speficied options (`video=valkyriefb:')
  820  */
  821 int __init valkyriefb_setup(char *options)
  822 {
  823         char *this_opt;
  824 
  825         if (!options || !*options)
  826                 return 0;
  827 
  828         while ((this_opt = strsep(&options, ",")) != NULL) {
  829                 if (!strncmp(this_opt, "font:", 5)) {
  830                         char *p;
  831                         int i;
  832 
  833                         p = this_opt + 5;
  834                         for (i = 0; i < sizeof(fontname) - 1; i++)
  835                                 if (!*p || *p == ' ' || *p == ',')
  836                                         break;
  837                         memcpy(fontname, this_opt + 5, i);
  838                         fontname[i] = 0;
  839                 }
  840                 else if (!strncmp(this_opt, "vmode:", 6)) {
  841                         int vmode = simple_strtoul(this_opt+6, NULL, 0);
  842                 if (vmode > 0 && vmode <= VMODE_MAX)
  843                                 default_vmode = vmode;
  844                 }
  845                 else if (!strncmp(this_opt, "cmode:", 6)) {
  846                         int depth = simple_strtoul(this_opt+6, NULL, 0);
  847                         switch (depth) {
  848                          case 8:
  849                             default_cmode = CMODE_8;
  850                             break;
  851                          case 15:
  852                          case 16:
  853                             default_cmode = CMODE_16;
  854                             break;
  855                         }
  856                 }
  857                 /* XXX - remove these options once blanking has been tested */
  858                 else if (!strncmp(this_opt, "noblank", 7)) {
  859                         can_soft_blank = 0;
  860                 }
  861                 else if (!strncmp(this_opt, "blank", 5)) {
  862                         can_soft_blank = 1;
  863                 }
  864         }
  865         return 0;
  866 }
  867 
  868 MODULE_LICENSE("GPL");

Cache object: 455ba386bffa39ff9ada5335e2e85fde


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.