in fbdev/amifb.c [3542:3762]
static int __init amifb_probe(struct platform_device *pdev)
{
struct fb_info *info;
int tag, i, err = 0;
u_long chipptr;
u_int defmode;
#ifndef MODULE
char *option = NULL;
if (fb_get_options("amifb", &option)) {
amifb_video_off();
return -ENODEV;
}
amifb_setup(option);
#endif
custom.dmacon = DMAF_ALL | DMAF_MASTER;
info = framebuffer_alloc(sizeof(struct amifb_par), &pdev->dev);
if (!info)
return -ENOMEM;
strcpy(info->fix.id, "Amiga ");
info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
info->fix.accel = FB_ACCEL_AMIGABLITT;
switch (amiga_chipset) {
#ifdef CONFIG_FB_AMIGA_OCS
case CS_OCS:
strcat(info->fix.id, "OCS");
default_chipset:
chipset = TAG_OCS;
maxdepth[TAG_SHRES] = 0; /* OCS means no SHRES */
maxdepth[TAG_HIRES] = 4;
maxdepth[TAG_LORES] = 6;
maxfmode = TAG_FMODE_1;
defmode = amiga_vblank == 50 ? DEFMODE_PAL : DEFMODE_NTSC;
info->fix.smem_len = VIDEOMEMSIZE_OCS;
break;
#endif /* CONFIG_FB_AMIGA_OCS */
#ifdef CONFIG_FB_AMIGA_ECS
case CS_ECS:
strcat(info->fix.id, "ECS");
chipset = TAG_ECS;
maxdepth[TAG_SHRES] = 2;
maxdepth[TAG_HIRES] = 4;
maxdepth[TAG_LORES] = 6;
maxfmode = TAG_FMODE_1;
if (AMIGAHW_PRESENT(AMBER_FF))
defmode = amiga_vblank == 50 ? DEFMODE_AMBER_PAL
: DEFMODE_AMBER_NTSC;
else
defmode = amiga_vblank == 50 ? DEFMODE_PAL
: DEFMODE_NTSC;
if (amiga_chip_avail() - CHIPRAM_SAFETY_LIMIT >
VIDEOMEMSIZE_ECS_2M)
info->fix.smem_len = VIDEOMEMSIZE_ECS_2M;
else
info->fix.smem_len = VIDEOMEMSIZE_ECS_1M;
break;
#endif /* CONFIG_FB_AMIGA_ECS */
#ifdef CONFIG_FB_AMIGA_AGA
case CS_AGA:
strcat(info->fix.id, "AGA");
chipset = TAG_AGA;
maxdepth[TAG_SHRES] = 8;
maxdepth[TAG_HIRES] = 8;
maxdepth[TAG_LORES] = 8;
maxfmode = TAG_FMODE_4;
defmode = DEFMODE_AGA;
if (amiga_chip_avail() - CHIPRAM_SAFETY_LIMIT >
VIDEOMEMSIZE_AGA_2M)
info->fix.smem_len = VIDEOMEMSIZE_AGA_2M;
else
info->fix.smem_len = VIDEOMEMSIZE_AGA_1M;
break;
#endif /* CONFIG_FB_AMIGA_AGA */
default:
#ifdef CONFIG_FB_AMIGA_OCS
printk("Unknown graphics chipset, defaulting to OCS\n");
strcat(info->fix.id, "Unknown");
goto default_chipset;
#else /* CONFIG_FB_AMIGA_OCS */
err = -ENODEV;
goto release;
#endif /* CONFIG_FB_AMIGA_OCS */
break;
}
/*
* Calculate the Pixel Clock Values for this Machine
*/
{
u_long tmp = DIVUL(200000000000ULL, amiga_eclock);
pixclock[TAG_SHRES] = (tmp + 4) / 8; /* SHRES: 35 ns / 28 MHz */
pixclock[TAG_HIRES] = (tmp + 2) / 4; /* HIRES: 70 ns / 14 MHz */
pixclock[TAG_LORES] = (tmp + 1) / 2; /* LORES: 140 ns / 7 MHz */
}
/*
* Replace the Tag Values with the Real Pixel Clock Values
*/
for (i = 0; i < NUM_TOTAL_MODES; i++) {
struct fb_videomode *mode = &ami_modedb[i];
tag = mode->pixclock;
if (tag == TAG_SHRES || tag == TAG_HIRES || tag == TAG_LORES) {
mode->pixclock = pixclock[tag];
}
}
if (amifb_hfmin) {
info->monspecs.hfmin = amifb_hfmin;
info->monspecs.hfmax = amifb_hfmax;
info->monspecs.vfmin = amifb_vfmin;
info->monspecs.vfmax = amifb_vfmax;
} else {
/*
* These are for a typical Amiga monitor (e.g. A1960)
*/
info->monspecs.hfmin = 15000;
info->monspecs.hfmax = 38000;
info->monspecs.vfmin = 49;
info->monspecs.vfmax = 90;
}
info->fbops = &amifb_ops;
info->flags = FBINFO_DEFAULT;
info->device = &pdev->dev;
if (!fb_find_mode(&info->var, info, mode_option, ami_modedb,
NUM_TOTAL_MODES, &ami_modedb[defmode], 4)) {
err = -EINVAL;
goto release;
}
fb_videomode_to_modelist(ami_modedb, NUM_TOTAL_MODES,
&info->modelist);
round_down_bpp = 0;
chipptr = chipalloc(info->fix.smem_len + SPRITEMEMSIZE +
DUMMYSPRITEMEMSIZE + COPINITSIZE +
4 * COPLISTSIZE);
if (!chipptr) {
err = -ENOMEM;
goto release;
}
assignchunk(videomemory, u_long, chipptr, info->fix.smem_len);
assignchunk(spritememory, u_long, chipptr, SPRITEMEMSIZE);
assignchunk(dummysprite, u_short *, chipptr, DUMMYSPRITEMEMSIZE);
assignchunk(copdisplay.init, copins *, chipptr, COPINITSIZE);
assignchunk(copdisplay.list[0][0], copins *, chipptr, COPLISTSIZE);
assignchunk(copdisplay.list[0][1], copins *, chipptr, COPLISTSIZE);
assignchunk(copdisplay.list[1][0], copins *, chipptr, COPLISTSIZE);
assignchunk(copdisplay.list[1][1], copins *, chipptr, COPLISTSIZE);
/*
* access the videomem with writethrough cache
*/
info->fix.smem_start = (u_long)ZTWO_PADDR(videomemory);
videomemory = (u_long)ioremap_wt(info->fix.smem_start,
info->fix.smem_len);
if (!videomemory) {
dev_warn(&pdev->dev,
"Unable to map videomem cached writethrough\n");
info->screen_base = ZTWO_VADDR(info->fix.smem_start);
} else
info->screen_base = (char *)videomemory;
memset(dummysprite, 0, DUMMYSPRITEMEMSIZE);
/*
* Make sure the Copper has something to do
*/
ami_init_copper();
/*
* Enable Display DMA
*/
custom.dmacon = DMAF_SETCLR | DMAF_MASTER | DMAF_RASTER | DMAF_COPPER |
DMAF_BLITTER | DMAF_SPRITE;
err = request_irq(IRQ_AMIGA_COPPER, amifb_interrupt, 0,
"fb vertb handler", info->par);
if (err)
goto disable_dma;
err = fb_alloc_cmap(&info->cmap, 1 << info->var.bits_per_pixel, 0);
if (err)
goto free_irq;
platform_set_drvdata(pdev, info);
err = register_framebuffer(info);
if (err)
goto unset_drvdata;
fb_info(info, "%s frame buffer device, using %dK of video memory\n",
info->fix.id, info->fix.smem_len>>10);
return 0;
unset_drvdata:
fb_dealloc_cmap(&info->cmap);
free_irq:
free_irq(IRQ_AMIGA_COPPER, info->par);
disable_dma:
custom.dmacon = DMAF_ALL | DMAF_MASTER;
if (videomemory)
iounmap((void *)videomemory);
chipfree();
release:
framebuffer_release(info);
return err;
}