📄 aty128fb.c
字号:
case 0 ... 8: var->bits_per_pixel = 8; break; case 9 ... 16: var->bits_per_pixel = 16; break; case 17 ... 24: var->bits_per_pixel = 24; break; case 25 ... 32: var->bits_per_pixel = 32; break; default: return -EINVAL; } if ((err = aty128_decode_var(var, &par, info))) return err; aty128_encode_var(var, &par, info); if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_TEST) return 0; oldxres = display->var.xres; oldyres = display->var.yres; oldvxres = display->var.xres_virtual; oldvyres = display->var.yres_virtual; oldbpp = display->var.bits_per_pixel; oldgreen = display->var.green.length; oldaccel = display->var.accel_flags; display->var = *var; if (oldxres != var->xres || oldyres != var->yres || oldvxres != var->xres_virtual || oldvyres != var->yres_virtual || oldgreen != var->green.length || oldbpp != var->bits_per_pixel || oldaccel != var->accel_flags) { struct fb_fix_screeninfo fix; aty128_encode_fix(&fix, &par, info); display->screen_base = info->frame_buffer; display->visual = fix.visual; display->type = fix.type; display->type_aux = fix.type_aux; display->ypanstep = fix.ypanstep; display->ywrapstep = fix.ywrapstep; display->line_length = fix.line_length; display->can_soft_blank = 1; display->inverse = 0; accel = var->accel_flags & FB_ACCELF_TEXT; aty128_set_dispsw(display, info, par.crtc.bpp, accel); if (accel) display->scrollmode = SCROLL_YNOMOVE; else display->scrollmode = SCROLL_YREDRAW; if (info->fb_info.changevar) (*info->fb_info.changevar)(con); } if (!info->fb_info.display_fg || info->fb_info.display_fg->vc_num == con) aty128_set_par(&par, info); if (oldbpp != var->bits_per_pixel || oldgreen != var->green.length) { if ((err = fb_alloc_cmap(&display->cmap, 0, 0))) return err; do_install_cmap(con, &info->fb_info); } return 0;}static voidaty128_set_dispsw(struct display *disp, struct fb_info_aty128 *info, int bpp, int accel){ switch (bpp) {#ifdef FBCON_HAS_CFB8 case 8: disp->dispsw = accel ? &fbcon_aty128_8 : &fbcon_cfb8; break;#endif#ifdef FBCON_HAS_CFB16 case 16: disp->dispsw = accel ? &fbcon_aty128_16 : &fbcon_cfb16; disp->dispsw_data = info->fbcon_cmap.cfb16; break;#endif#ifdef FBCON_HAS_CFB24 case 24: disp->dispsw = accel ? &fbcon_aty128_24 : &fbcon_cfb24; disp->dispsw_data = info->fbcon_cmap.cfb24; break;#endif#ifdef FBCON_HAS_CFB32 case 32: disp->dispsw = accel ? &fbcon_aty128_32 : &fbcon_cfb32; disp->dispsw_data = info->fbcon_cmap.cfb32; break;#endif default: disp->dispsw = &fbcon_dummy; }}static voidaty128_encode_fix(struct fb_fix_screeninfo *fix, struct aty128fb_par *par, const struct fb_info_aty128 *info){ memset(fix, 0, sizeof(struct fb_fix_screeninfo)); strcpy(fix->id, aty128fb_name); fix->smem_start = (unsigned long)info->frame_buffer_phys; fix->mmio_start = (unsigned long)info->regbase_phys; fix->smem_len = info->vram_size; fix->mmio_len = 0x1fff; fix->type = FB_TYPE_PACKED_PIXELS; fix->type_aux = 0; fix->line_length = (par->crtc.vxres * par->crtc.bpp) >> 3; fix->visual = par->crtc.bpp == 8 ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR; fix->ywrapstep = 0; fix->xpanstep = 8; fix->ypanstep = 1; fix->accel = FB_ACCEL_ATI_RAGE128; return;} /* * Get the Fixed Part of the Display */static intaty128fb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *fb){ const struct fb_info_aty128 *info = (struct fb_info_aty128 *)fb; struct aty128fb_par par; if (con == -1) par = info->default_par; else aty128_decode_var(&fb_display[con].var, &par, info); aty128_encode_fix(fix, &par, info); return 0; } /* * Pan or Wrap the Display */static intaty128fb_pan_display(struct fb_var_screeninfo *var, int con, struct fb_info *fb){ struct fb_info_aty128 *info = (struct fb_info_aty128 *)fb; struct aty128fb_par *par = &info->current_par; u32 xoffset, yoffset; u32 offset; u32 xres, yres; xres = (((par->crtc.h_total >> 16) & 0xff) + 1) << 3; yres = ((par->crtc.v_total >> 16) & 0x7ff) + 1; xoffset = (var->xoffset +7) & ~7; yoffset = var->yoffset; if (xoffset+xres > par->crtc.vxres || yoffset+yres > par->crtc.vyres) return -EINVAL; par->crtc.xoffset = xoffset; par->crtc.yoffset = yoffset; offset = ((yoffset * par->crtc.vxres + xoffset)*(par->crtc.bpp >> 3)) & ~7; if (par->crtc.bpp == 24) offset += 8 * (offset % 3); /* Must be multiple of 8 and 3 */ aty_st_le32(CRTC_OFFSET, offset); return 0;} /* * Get the Colormap */static intaty128fb_get_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info){ struct fb_info_aty128 *fb = (struct fb_info_aty128 *)info; struct display *disp = (con < 0) ? info->disp : (fb_display + con); if (con == fb->currcon) /* current console? */ return fb_get_cmap(cmap, kspc, aty128_getcolreg, info); else if (disp->cmap.len) /* non default colormap? */ fb_copy_cmap(&disp->cmap, cmap, kspc ? 0 : 2); else fb_copy_cmap(fb_default_cmap((disp->var.bits_per_pixel==8) ? 256 : 32), cmap, kspc ? 0 : 2); return 0;} /* * Set the Colormap */static intaty128fb_set_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info){ struct fb_info_aty128 *fb = (struct fb_info_aty128 *)info; struct display *disp = (con < 0) ? info->disp : (fb_display + con); unsigned int cmap_len = (disp->var.bits_per_pixel==8) ? 256 : 32; if (disp->cmap.len != cmap_len) { int err = fb_alloc_cmap(&disp->cmap, cmap_len, 0); if (!disp->cmap.len) { /* no colormap allocated? */ int size = (disp->var.bits_per_pixel <= 8) ? 256 : 32; if ((err = fb_alloc_cmap(&disp->cmap, size, 0))) return err; } if (err) return err; } if (con == fb->currcon) /* current console? */ return fb_set_cmap(cmap, kspc, aty128_setcolreg, info); else fb_copy_cmap(cmap, &disp->cmap, kspc ? 0 : 1); return 0; } /* * Helper function to store a single palette register */static __inline__ voidaty128_st_pal(u_int regno, u_int red, u_int green, u_int blue, struct fb_info_aty128 *info){ /* Note: For now, on M3, we set palette on both heads, which may * be useless. Can someone with a M3 check this ? * * This code would still be useful if using the second CRTC to * do mirroring */ if (info->chip_gen == rage_M3) {#if 0 aty_st_le32(DAC_CNTL, aty_ld_le32(DAC_CNTL) | DAC_PALETTE_ACCESS_CNTL); aty_st_8(PALETTE_INDEX, regno); aty_st_le32(PALETTE_DATA, (red<<16)|(green<<8)|blue);#endif aty_st_le32(DAC_CNTL, aty_ld_le32(DAC_CNTL) & ~DAC_PALETTE_ACCESS_CNTL); } aty_st_8(PALETTE_INDEX, regno); aty_st_le32(PALETTE_DATA, (red<<16)|(green<<8)|blue);}static intaty128fb_rasterimg(struct fb_info *info, int start){ struct fb_info_aty128 *fb = (struct fb_info_aty128 *)info; if (fb->blitter_may_be_busy) wait_for_idle(fb); return 0;}int __initaty128fb_setup(char *options){ char *this_opt; if (!options || !*options) return 0; while ((this_opt = strsep(&options, ",")) != 0) { 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, "noaccel", 7)) { noaccel = 1;#ifdef CONFIG_PMAC_PBOOK } else if (!strncmp(this_opt, "lcd:", 4)) { default_lcd_on = simple_strtoul(this_opt+4, NULL, 0); } else if (!strncmp(this_opt, "crt:", 4)) { default_crt_on = simple_strtoul(this_opt+4, NULL, 0);#endif }#ifdef CONFIG_MTRR else if(!strncmp(this_opt, "nomtrr", 6)) { mtrr = 0; }#endif#ifdef CONFIG_PPC /* vmode and cmode depreciated */ else if (!strncmp(this_opt, "vmode:", 6)) { unsigned 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)) { unsigned int cmode = simple_strtoul(this_opt+6, NULL, 0); switch (cmode) { case 0: case 8: default_cmode = CMODE_8; break; case 15: case 16: default_cmode = CMODE_16; break; case 24: case 32: default_cmode = CMODE_32; break; } }#endif /* CONFIG_PPC */ else mode_option = this_opt; } return 0;} /* * Initialisation */static int __initaty128_init(struct fb_info_aty128 *info, const char *name){ struct fb_var_screeninfo var; u32 dac; int j, k; u8 chip_rev; const struct aty128_chip_info *aci = &aty128_pci_probe_list[0]; char *video_card = "Rage128"; if (!info->vram_size) /* may have already been probed */ info->vram_size = aty_ld_le32(CONFIG_MEMSIZE) & 0x03FFFFFF; /* Get the chip revision */ chip_rev = (aty_ld_le32(CONFIG_CNTL) >> 16) & 0x1F; /* put a name with the face */ while (aci->name && info->pdev->device != aci->device) { aci++; } video_card = (char *)aci->name; info->chip_gen = aci->chip_gen; printk(KERN_INFO "aty128fb: %s [chip rev 0x%x] ", video_card, chip_rev); if (info->vram_size % (1024 * 1024) == 0) printk("%dM %s\n", info->vram_size / (1024*1024), info->mem->name); else printk("%dk %s\n", info->vram_size / 1024, info->mem->name); /* fill in info */ strcpy(info->fb_info.modename, aty128fb_name); info->fb_info.node = -1; info->fb_info.fbops = &aty128fb_ops; info->fb_info.disp = &info->disp; strcpy(info->fb_info.fontname, fontname); info->fb_info.changevar = NULL; info->fb_info.switch_con = &aty128fbcon_switch; info->fb_info.updatevar = NULL; info->fb_info.blank = &aty128fbcon_blank; info->fb_info.flags = FBINFO_FLAG_DEFAULT;#ifdef CONFIG_PMAC_PBOOK info->lcd_on = default_lcd_on; info->crt_on = default_crt_on;#endif var = default_var;#ifdef CONFIG_PPC if (_machine == _MACH_Pmac) { if (mode_option) { if (!mac_find_mode(&var, &info->fb_info, mode_option, 8)) var = default_var; } else { if (default_vmode <= 0 || default_vmode > VMODE_MAX) default_vmode = VMODE_1024_768_60; /* iMacs need that resolution * PowerMac2,1 first r128 iMacs * PowerMac2,2 summer 2000 iMacs * PowerMac4,1 january 2001 iMacs "flower power" */ if (machine_is_compatible("PowerMac2,1") || machine_is_compatible("PowerMac2,2") || machine_is_compatible("PowerMac4,1")) default_vmode = VMODE_1024_768_75; /* iBook SE */ if (machine_is_compatible("PowerBook2,2")) default_vmode = VMODE_800_600_60; /* PowerBook Firewire (Pismo), iBook Dual USB */ if (machine_is_compatible("PowerBook3,1") || machine_is_compatible("PowerBook4,1")) default_vmode = VMODE_1024_768_60; /* PowerBook Titanium */ if (machine_is_compatible("PowerBook3,2")) default_vmode = VMODE_1152_768_60; if (default_cmode < CMODE_8 || default_cmode > CMODE_32) default_cmode = CMODE_8; if (mac_vmode_to_var(default_vmode, default_cmode, &var)) var = default_var; } } else#endif /* CONFIG_PPC */ { if (fb_find_mode(&var, &info->fb_info, mode_option, NULL, 0, &defaultmode, 8) == 0) var = default_var; } if (noaccel) var.accel_flags &= ~FB_ACCELF_TEXT; else var.accel_flags |= FB_ACCELF_TEXT; if (aty128_decode_var(&var, &info->default_par, info)) { printk(KERN_ERR "aty128fb: Cannot set default mode.\n"); return 0; } /* load up the palette with default colors */ for (j = 0; j < 16; j++) { k = color_table[j]; info->palette[j].red = default_red[k]; info->palette[j].green = default_grn[k]; info->palette[j].blue = default_blu[k]; } /* setup the DAC the way we like it */ dac = aty_ld_le32(DAC_CNTL); dac |= (DAC_8BIT_EN | DAC_RANGE_CNTL); dac |= DAC_MASK; if (info->chip_gen == rage_M3) dac |= DAC_PALETTE2_SNOOP_EN; aty_st_le32(DAC_CNTL, dac); /* turn off bus mastering, just in case */ aty_st_le32(BUS_CNTL, aty_ld_le32(BUS_CNTL) | BUS_MASTER_DIS); aty128fb_set_var(&var, -1, &info->fb_info); aty128_init_engine(&info->default_par, info); board_list = aty128_board_list_add(board_list, info); if (register_framebuffer(&info->fb_info) < 0) return 0;#ifdef CONFIG_PMAC_BACKLIGHT /* Could be extended to Rage128Pro LVDS output too */ if (info->chip_gen == rage_M3) register_backlight_controller(&aty128_backlight_controller, info, "ati");#endif /* CONFIG_PMAC_BACKLIGHT */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -