📄 valkyriefb.c
字号:
static void set_valkyrie_clock(unsigned char *params){ struct adb_request req; int i;#ifdef CONFIG_ADB_CUDA for (i = 0; i < 3; ++i) { cuda_request(&req, NULL, 5, CUDA_PACKET, CUDA_GET_SET_IIC, 0x50, i + 1, params[i]); while (!req.complete) cuda_poll(); }#endif}static void __init init_valkyrie(struct fb_info_valkyrie *p){ struct fb_par_valkyrie *par = &p->par; struct fb_var_screeninfo var; int j, k; p->sense = read_valkyrie_sense(p); printk(KERN_INFO "Monitor sense value = 0x%x, ", p->sense);#ifdef CONFIG_NVRAM /* Try to pick a video mode out of NVRAM if we have one. */ if (default_vmode == VMODE_NVRAM) { default_vmode = nvram_read_byte(NV_VMODE); if (default_vmode <= 0 || default_vmode > VMODE_MAX || !valkyrie_reg_init[default_vmode - 1]) default_vmode = VMODE_CHOOSE; } if (default_cmode == CMODE_NVRAM) default_cmode = nvram_read_byte(NV_CMODE);#endif if (default_vmode == VMODE_CHOOSE) default_vmode = mac_map_monitor_sense(p->sense); if (!valkyrie_reg_init[default_vmode - 1]) default_vmode = VMODE_640_480_67; /* * Reduce the pixel size if we don't have enough VRAM or bandwitdh. */ if (default_cmode < CMODE_8 || default_cmode > CMODE_16 || valkyrie_reg_init[default_vmode-1]->pitch[default_cmode] == 0 || valkyrie_vram_reqd(default_vmode, default_cmode) > p->total_vram) default_cmode = CMODE_8; printk(KERN_INFO "using video mode %d and color mode %d.\n", default_vmode, default_cmode); mac_vmode_to_var(default_vmode, default_cmode, &var); if (valkyrie_var_to_par(&var, par, &p->info)) { printk(KERN_ERR "valkyriefb: can't set default video mode\n"); return ; } valkyrie_init_fix(&p->fix, p); valkyrie_par_to_fix(&p->par, &p->fix, p); valkyrie_par_to_var(&p->par, &p->var); valkyrie_init_display(&p->disp); valkyrie_par_to_display(&p->par, &p->disp, &p->fix, p); valkyrie_init_info(&p->info, p); /* Initialize colormap */ for (j = 0; j < 16; j++) { k = color_table[j]; p->palette[j].red = default_red[k]; p->palette[j].green = default_grn[k]; p->palette[j].blue = default_blu[k]; } valkyrie_set_var (&var, -1, &p->info); if (register_framebuffer(&p->info) < 0) { kfree(p); return; } printk(KERN_INFO "fb%d: valkyrie frame buffer device\n", GET_FB_IDX(p->info.node)); }static void valkyrie_set_par(const struct fb_par_valkyrie *par, struct fb_info_valkyrie *p){ struct valkyrie_regvals *init; volatile struct valkyrie_regs *valkyrie_regs = p->valkyrie_regs; int vmode, cmode; vmode = par->vmode; cmode = par->cmode; if (vmode <= 0 || vmode > VMODE_MAX || (init = valkyrie_reg_init[vmode - 1]) == NULL) panic("valkyrie: display mode %d not supported", vmode); /* Reset the valkyrie */ out_8(&valkyrie_regs->status.r, 0); udelay(100); /* Initialize display timing registers */ out_8(&valkyrie_regs->mode.r, init->mode | 0x80); out_8(&valkyrie_regs->depth.r, cmode + 3); set_valkyrie_clock(init->clock_params); udelay(100); /* Turn on display */ out_8(&valkyrie_regs->mode.r, init->mode);#ifdef CONFIG_FB_COMPAT_XPMAC /* And let the world know the truth. */ if (!console_fb_info || console_fb_info == &p->info) { display_info.height = p->var.yres; display_info.width = p->var.xres; display_info.depth = (cmode == CMODE_16) ? 16 : 8; display_info.pitch = p->fix.line_length; display_info.mode = vmode; strncpy(display_info.name, "valkyrie", sizeof(display_info.name)); display_info.fb_address = p->frame_buffer_phys + 0x1000; display_info.cmap_adr_address = p->cmap_regs_phys; display_info.cmap_data_address = p->cmap_regs_phys + 8; display_info.disp_reg_address = p->valkyrie_regs_phys; console_fb_info = &p->info; }#endif /* CONFIG_FB_COMPAT_XPMAC */}int __init valkyriefb_init(void){ struct fb_info_valkyrie *p; unsigned long frame_buffer_phys, cmap_regs_phys, flags;#ifdef CONFIG_MAC if (!MACH_IS_MAC) return 0; if (!(mac_bi_data.id == MAC_MODEL_Q630 /* I'm not sure about this one */ || mac_bi_data.id == MAC_MODEL_P588)) return 0; /* Hardcoded addresses... welcome to 68k Macintosh country :-) */ frame_buffer_phys = 0xf9000000; cmap_regs_phys = 0x50f24000; flags = IOMAP_NOCACHE_SER; /* IOMAP_WRITETHROUGH?? */#else /* ppc (!CONFIG_MAC) */ struct device_node *dp; dp = find_devices("valkyrie"); if (dp == 0) return 0; if(dp->n_addrs != 1) { printk(KERN_ERR "expecting 1 address for valkyrie (got %d)", dp->n_addrs); return 0; } frame_buffer_phys = dp->addrs[0].address; cmap_regs_phys = dp->addrs[0].address+0x304000; flags = _PAGE_WRITETHRU;#endif /* ppc (!CONFIG_MAC) */ p = kmalloc(sizeof(*p), GFP_ATOMIC); if (p == 0) return 0; memset(p, 0, sizeof(*p)); /* Map in frame buffer and registers */ if (!request_mem_region(frame_buffer_phys, 0x100000, "valkyriefb")) { kfree(p); return 0; } p->total_vram = 0x100000; p->frame_buffer_phys = frame_buffer_phys; p->frame_buffer = __ioremap(frame_buffer_phys, p->total_vram, flags); p->cmap_regs_phys = cmap_regs_phys; p->cmap_regs = ioremap(p->cmap_regs_phys, 0x1000); p->valkyrie_regs_phys = cmap_regs_phys+0x6000; p->valkyrie_regs = ioremap(p->valkyrie_regs_phys, 0x1000); init_valkyrie(p); return 0;}/* * Get the monitor sense value. */static int read_valkyrie_sense(struct fb_info_valkyrie *p){ int sense, in; out_8(&p->valkyrie_regs->msense.r, 0); /* release all lines */ __delay(20000); sense = ((in = in_8(&p->valkyrie_regs->msense.r)) & 0x70) << 4; /* drive each sense line low in turn and collect the other 2 */ out_8(&p->valkyrie_regs->msense.r, 4); /* drive A low */ __delay(20000); sense |= ((in = in_8(&p->valkyrie_regs->msense.r)) & 0x30); out_8(&p->valkyrie_regs->msense.r, 2); /* drive B low */ __delay(20000); sense |= ((in = in_8(&p->valkyrie_regs->msense.r)) & 0x40) >> 3; sense |= (in & 0x10) >> 2; out_8(&p->valkyrie_regs->msense.r, 1); /* drive C low */ __delay(20000); sense |= ((in = in_8(&p->valkyrie_regs->msense.r)) & 0x60) >> 5; out_8(&p->valkyrie_regs->msense.r, 7); return sense;}/* * This routine takes a user-supplied var, * and picks the best vmode/cmode from it. */static int valkyrie_var_to_par(struct fb_var_screeninfo *var, struct fb_par_valkyrie *par, const struct fb_info *fb_info)/* [bkn] I did a major overhaul of this function. * * Much of the old code was "swiped by jonh from atyfb.c". Because * macmodes has mac_var_to_vmode, I felt that it would be better to * rework this function to use that, instead of reinventing the wheel to * add support for vmode 17. This was reinforced by the fact that * the previously swiped atyfb.c code is no longer there. * * So, I swiped and adapted platinum_var_to_par (from platinumfb.c), replacing * most, but not all, of the old code in the process. One side benefit of * swiping the platinumfb code is that we now have more comprehensible error * messages when a vmode/cmode switch fails. (Most of the error messages are * platinumfb.c, but I added two of my own, and I also changed some commas * into colons to make the messages more consistent with other Linux error * messages.) In addition, I think the new code *might* fix some vmode- * switching oddities, but I'm not sure. * * There may be some more opportunities for cleanup in here, but this is a * good start... */{ int bpp = var->bits_per_pixel; struct valkyrie_regvals *init; struct fb_info_valkyrie *p = (struct fb_info_valkyrie *) fb_info; if(mac_var_to_vmode(var, &par->vmode, &par->cmode) != 0) { printk(KERN_ERR "valkyrie_var_to_par: %dx%dx%d unsuccessful.\n",var->xres,var->yres,var->bits_per_pixel); return -EINVAL; } /* Check if we know about the wanted video mode */ if(!valkyrie_reg_init[par->vmode-1]) { printk(KERN_ERR "valkyrie_var_to_par: vmode %d not valid.\n", par->vmode); return -EINVAL; } par->xres = var->xres; par->yres = var->yres; par->xoffset = 0; par->yoffset = 0; par->vxres = par->xres; par->vyres = par->yres; if (var->xres_virtual > var->xres || var->yres_virtual > var->yres || var->xoffset != 0 || var->yoffset != 0) { return -EINVAL; } if (bpp <= 8) par->cmode = CMODE_8; else if (bpp <= 16) par->cmode = CMODE_16; else { printk(KERN_ERR "valkyrie_var_to_par: cmode %d not supported.\n", par->cmode); return -EINVAL; } init = valkyrie_reg_init[par->vmode-1]; if (init->pitch[par->cmode] == 0) { printk(KERN_ERR "valkyrie_var_to_par: vmode %d does not support cmode %d.\n", par->vmode, par->cmode); return -EINVAL; } if (valkyrie_vram_reqd(par->vmode, par->cmode) > p->total_vram) { printk(KERN_ERR "valkyrie_var_to_par: not enough ram for vmode %d, cmode %d.\n", par->vmode, par->cmode); return -EINVAL; } return 0;}static int valkyrie_par_to_var(struct fb_par_valkyrie *par, struct fb_var_screeninfo *var){ return mac_vmode_to_var(par->vmode, par->cmode, var);}static void valkyrie_init_fix(struct fb_fix_screeninfo *fix, struct fb_info_valkyrie *p){ memset(fix, 0, sizeof(*fix)); strcpy(fix->id, "valkyrie"); fix->mmio_start = p->valkyrie_regs_phys; fix->mmio_len = sizeof(struct valkyrie_regs); fix->type = FB_TYPE_PACKED_PIXELS; fix->type_aux = 0; fix->ywrapstep = 0; fix->ypanstep = 0; fix->xpanstep = 0; }/* Fix must already be inited above */static void valkyrie_par_to_fix(struct fb_par_valkyrie *par, struct fb_fix_screeninfo *fix, struct fb_info_valkyrie *p){ fix->smem_start = p->frame_buffer_phys + 0x1000;#if 1 fix->smem_len = valkyrie_vram_reqd(par->vmode, par->cmode);#else fix->smem_len = p->total_vram;#endif fix->visual = (par->cmode == CMODE_8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR; fix->line_length = par->vxres << par->cmode; /* ywrapstep, xpanstep, ypanstep */}static void valkyrie_init_display(struct display *disp){ memset(disp, 0, sizeof(*disp)); disp->type = /* fix->type */ FB_TYPE_PACKED_PIXELS; disp->can_soft_blank = can_soft_blank; disp->scrollmode = SCROLL_YREDRAW;}static void valkyrie_par_to_display(struct fb_par_valkyrie *par, struct display *disp, struct fb_fix_screeninfo *fix, struct fb_info_valkyrie *p){ disp->var = p->var; disp->screen_base = (char *) p->frame_buffer + 0x1000; disp->visual = fix->visual; disp->line_length = fix->line_length; if(disp->scrollmode != SCROLL_YREDRAW) { printk(KERN_ERR "Scroll mode not YREDRAW in valkyrie_par_to_display\n"); disp->scrollmode = SCROLL_YREDRAW; } switch (par->cmode) {#ifdef FBCON_HAS_CFB8 case CMODE_8: disp->dispsw = &fbcon_cfb8; break;#endif#ifdef FBCON_HAS_CFB16 case CMODE_16: disp->dispsw = &fbcon_cfb16; disp->dispsw_data = p->fbcon_cfb16_cmap; break;#endif default: disp->dispsw = &fbcon_dummy; break; }}static void __init valkyrie_init_info(struct fb_info *info, struct fb_info_valkyrie *p){ strcpy(info->modename, p->fix.id); info->node = -1; /* ??? danj */ info->fbops = &valkyriefb_ops; info->disp = &p->disp; strcpy(info->fontname, fontname); info->changevar = NULL; info->switch_con = &valkyriefb_switch; info->updatevar = &valkyriefb_updatevar; info->blank = &valkyriefb_blank; info->flags = FBINFO_FLAG_DEFAULT;}/* * Parse user speficied options (`video=valkyriefb:') */int __init valkyriefb_setup(char *options){ char *this_opt; if (!options || !*options) return 0; while ((this_opt = strsep(&options, ",")) != NULL) { if (!strncmp(this_opt, "font:", 5)) { char *p; int i; p = this_opt + 5; for (i = 0; i < sizeof(fontname) - 1; i++) if (!*p || *p == ' ' || *p == ',') break; memcpy(fontname, this_opt + 5, i); fontname[i] = 0; } else if (!strncmp(this_opt, "vmode:", 6)) { int vmode = simple_strtoul(this_opt+6, NULL, 0); if (vmode > 0 && vmode <= VMODE_MAX) default_vmode = vmode; } else if (!strncmp(this_opt, "cmode:", 6)) { int depth = simple_strtoul(this_opt+6, NULL, 0); switch (depth) { case 8: default_cmode = CMODE_8; break; case 15: case 16: default_cmode = CMODE_16; break; } } /* XXX - remove these options once blanking has been tested */ else if (!strncmp(this_opt, "noblank", 7)) { can_soft_blank = 0; } else if (!strncmp(this_opt, "blank", 5)) { can_soft_blank = 1; } } return 0;}MODULE_LICENSE("GPL");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -