in fbdev/stifb.c [1118:1348]
static int __init stifb_init_fb(struct sti_struct *sti, int bpp_pref)
{
struct fb_fix_screeninfo *fix;
struct fb_var_screeninfo *var;
struct stifb_info *fb;
struct fb_info *info;
unsigned long sti_rom_address;
char *dev_name;
int bpp, xres, yres;
fb = kzalloc(sizeof(*fb), GFP_ATOMIC);
if (!fb)
return -ENOMEM;
info = &fb->info;
/* set struct to a known state */
fix = &info->fix;
var = &info->var;
fb->sti = sti;
dev_name = sti->sti_data->inq_outptr.dev_name;
/* store upper 32bits of the graphics id */
fb->id = fb->sti->graphics_id[0];
/* only supported cards are allowed */
switch (fb->id) {
case CRT_ID_VISUALIZE_EG:
/* Visualize cards can run either in "double buffer" or
"standard" mode. Depending on the mode, the card reports
a different device name, e.g. "INTERNAL_EG_DX1024" in double
buffer mode and "INTERNAL_EG_X1024" in standard mode.
Since this driver only supports standard mode, we check
if the device name contains the string "DX" and tell the
user how to reconfigure the card. */
if (strstr(dev_name, "DX")) {
printk(KERN_WARNING
"WARNING: stifb framebuffer driver does not support '%s' in double-buffer mode.\n"
"WARNING: Please disable the double-buffer mode in IPL menu (the PARISC-BIOS).\n",
dev_name);
goto out_err0;
}
fallthrough;
case S9000_ID_ARTIST:
case S9000_ID_HCRX:
case S9000_ID_TIMBER:
case S9000_ID_A1659A:
case S9000_ID_A1439A:
break;
default:
printk(KERN_WARNING "stifb: '%s' (id: 0x%08x) not supported.\n",
dev_name, fb->id);
goto out_err0;
}
/* default to 8 bpp on most graphic chips */
bpp = 8;
xres = sti_onscreen_x(fb->sti);
yres = sti_onscreen_y(fb->sti);
ngleGetDeviceRomData(fb);
/* get (virtual) io region base addr */
fix->mmio_start = REGION_BASE(fb,2);
fix->mmio_len = 0x400000;
/* Reject any device not in the NGLE family */
switch (fb->id) {
case S9000_ID_A1659A: /* CRX/A1659A */
break;
case S9000_ID_ELM: /* GRX, grayscale but else same as A1659A */
var->grayscale = 1;
fb->id = S9000_ID_A1659A;
break;
case S9000_ID_TIMBER: /* HP9000/710 Any (may be a grayscale device) */
if (strstr(dev_name, "GRAYSCALE") ||
strstr(dev_name, "Grayscale") ||
strstr(dev_name, "grayscale"))
var->grayscale = 1;
break;
case S9000_ID_TOMCAT: /* Dual CRX, behaves else like a CRX */
/* FIXME: TomCat supports two heads:
* fb.iobase = REGION_BASE(fb_info,3);
* fb.screen_base = ioremap(REGION_BASE(fb_info,2),xxx);
* for now we only support the left one ! */
xres = fb->ngle_rom.x_size_visible;
yres = fb->ngle_rom.y_size_visible;
fb->id = S9000_ID_A1659A;
break;
case S9000_ID_A1439A: /* CRX24/A1439A */
bpp = 32;
break;
case S9000_ID_HCRX: /* Hyperdrive/HCRX */
memset(&fb->ngle_rom, 0, sizeof(fb->ngle_rom));
if ((fb->sti->regions_phys[0] & 0xfc000000) ==
(fb->sti->regions_phys[2] & 0xfc000000))
sti_rom_address = F_EXTEND(fb->sti->regions_phys[0]);
else
sti_rom_address = F_EXTEND(fb->sti->regions_phys[1]);
fb->deviceSpecificConfig = gsc_readl(sti_rom_address);
if (IS_24_DEVICE(fb)) {
if (bpp_pref == 8 || bpp_pref == 32)
bpp = bpp_pref;
else
bpp = 32;
} else
bpp = 8;
READ_WORD(fb, REG_15);
SETUP_HW(fb);
break;
case CRT_ID_VISUALIZE_EG:
case S9000_ID_ARTIST: /* Artist */
break;
default:
#ifdef FALLBACK_TO_1BPP
printk(KERN_WARNING
"stifb: Unsupported graphics card (id=0x%08x) "
"- now trying 1bpp mode instead\n",
fb->id);
bpp = 1; /* default to 1 bpp */
break;
#else
printk(KERN_WARNING
"stifb: Unsupported graphics card (id=0x%08x) "
"- skipping.\n",
fb->id);
goto out_err0;
#endif
}
/* get framebuffer physical and virtual base addr & len (64bit ready) */
fix->smem_start = F_EXTEND(fb->sti->regions_phys[1]);
fix->smem_len = fb->sti->regions[1].region_desc.length * 4096;
fix->line_length = (fb->sti->glob_cfg->total_x * bpp) / 8;
if (!fix->line_length)
fix->line_length = 2048; /* default */
/* limit fbsize to max visible screen size */
if (fix->smem_len > yres*fix->line_length)
fix->smem_len = yres*fix->line_length;
fix->accel = FB_ACCEL_NONE;
switch (bpp) {
case 1:
fix->type = FB_TYPE_PLANES; /* well, sort of */
fix->visual = FB_VISUAL_MONO10;
var->red.length = var->green.length = var->blue.length = 1;
break;
case 8:
fix->type = FB_TYPE_PACKED_PIXELS;
fix->visual = FB_VISUAL_PSEUDOCOLOR;
var->red.length = var->green.length = var->blue.length = 8;
break;
case 32:
fix->type = FB_TYPE_PACKED_PIXELS;
fix->visual = FB_VISUAL_DIRECTCOLOR;
var->red.length = var->green.length = var->blue.length = var->transp.length = 8;
var->blue.offset = 0;
var->green.offset = 8;
var->red.offset = 16;
var->transp.offset = 24;
break;
default:
break;
}
var->xres = var->xres_virtual = xres;
var->yres = var->yres_virtual = yres;
var->bits_per_pixel = bpp;
strcpy(fix->id, "stifb");
info->fbops = &stifb_ops;
info->screen_base = ioremap(REGION_BASE(fb,1), fix->smem_len);
if (!info->screen_base) {
printk(KERN_ERR "stifb: failed to map memory\n");
goto out_err0;
}
info->screen_size = fix->smem_len;
info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_COPYAREA;
info->pseudo_palette = &fb->pseudo_palette;
/* This has to be done !!! */
if (fb_alloc_cmap(&info->cmap, NR_PALETTE, 0))
goto out_err1;
stifb_init_display(fb);
if (!request_mem_region(fix->smem_start, fix->smem_len, "stifb fb")) {
printk(KERN_ERR "stifb: cannot reserve fb region 0x%04lx-0x%04lx\n",
fix->smem_start, fix->smem_start+fix->smem_len);
goto out_err2;
}
if (!request_mem_region(fix->mmio_start, fix->mmio_len, "stifb mmio")) {
printk(KERN_ERR "stifb: cannot reserve sti mmio region 0x%04lx-0x%04lx\n",
fix->mmio_start, fix->mmio_start+fix->mmio_len);
goto out_err3;
}
if (register_framebuffer(&fb->info) < 0)
goto out_err4;
sti->info = info; /* save for unregister_framebuffer() */
fb_info(&fb->info, "%s %dx%d-%d frame buffer device, %s, id: %04x, mmio: 0x%04lx\n",
fix->id,
var->xres,
var->yres,
var->bits_per_pixel,
dev_name,
fb->id,
fix->mmio_start);
return 0;
out_err4:
release_mem_region(fix->mmio_start, fix->mmio_len);
out_err3:
release_mem_region(fix->smem_start, fix->smem_len);
out_err2:
fb_dealloc_cmap(&info->cmap);
out_err1:
iounmap(info->screen_base);
out_err0:
kfree(fb);
return -ENXIO;
}