Lines Matching +full:gfx +full:- +full:mem

1 // SPDX-License-Identifier: GPL-2.0-only
3 * linux/drivers/video/sstfb.c -- voodoo graphics frame buffer
5 * Copyright (c) 2000-2002 Ghozlane Toumi <[email protected]>
16 * (enable driver on big-endian machines (hppa), ioctl fixes)
26 * add /sys/class/graphics/fbX/vgapass sysfs-interface
34 * 0x000000 - 0x3fffff : registers (4MB)
35 * 0x400000 - 0x7fffff : linear frame buffer (4MB)
36 * 0x800000 - 0xffffff : texture memory (8MB)
42 -TODO: at one time or another test that the mode is acceptable by the monitor
43 -ASK: Can I choose different ordering for the color bitfields (rgba argb ...)
46 -TODO: in set_var check the validity of timings (hsync vsync)...
47 -TODO: check and recheck the use of sst_wait_idle : we don't flush the fifo via
50 -FIXME: in case of failure in the init sequence, be sure we return to a safe
52 - FIXME: Use accelerator for 2D scroll
53 -FIXME: 4MB boards have banked memory (FbiInit2 bits 1 & 20)
99 static int mem; /* mem size in MB, 0 = autodetect */ variable
116 #define IS_VOODOO2(par) ((par)->type == ID_VOODOO2)
174 #define sst_read(reg) __sst_read(par->mmio_vbase, reg)
175 #define sst_write(reg,val) __sst_write(par->mmio_vbase, reg, val)
176 #define sst_set_bits(reg,val) __sst_set_bits(par->mmio_vbase, reg, val)
177 #define sst_unset_bits(reg,val) __sst_unset_bits(par->mmio_vbase, reg, val)
178 #define sst_dac_read(reg) __sst_dac_read(par->mmio_vbase, reg)
179 #define sst_dac_write(reg,val) __sst_dac_write(par->mmio_vbase, reg, val)
180 #define dac_i_read(reg) __dac_i_read(par->mmio_vbase, reg)
181 #define dac_i_write(reg,val) __dac_i_write(par->mmio_vbase, reg, val)
215 #define sst_wait_idle() __sst_wait_idle(par->mmio_vbase)
282 * (ics datasheet : N <-> N1 , P <-> N2)
295 int best_n = -1; in sst_calc_pll()
296 int best_m = -1; in sst_calc_pll()
302 p--; in sst_calc_pll()
303 if (p == -1) in sst_calc_pll()
304 return -EINVAL; in sst_calc_pll()
307 m2 = (2 * freq * (1 << p) * (n + 2) ) / DAC_FREF - 4 ; in sst_calc_pll()
313 if ((abs(fout - freq) < best_err) && (m > 0)) { in sst_calc_pll()
316 best_err = abs(fout - freq); in sst_calc_pll()
321 if (best_n == -1) /* unlikely, but who knows ? */ in sst_calc_pll()
322 return -EINVAL; in sst_calc_pll()
323 t->p = p; in sst_calc_pll()
324 t->n = best_n; in sst_calc_pll()
325 t->m = best_m; in sst_calc_pll()
326 *freq_out = (DAC_FREF * (t->m + 2)) / ((1 << t->p) * (t->n + 2)); in sst_calc_pll()
328 t->m, t->n, t->p, *freq_out); in sst_calc_pll()
338 fb_memset_io(info->screen_base, 0, info->fix.smem_len); in sstfb_clear_screen()
343 * sstfb_check_var - Optional function. Validates a var passed in.
354 struct sstfb_par *par = info->par; in sstfb_check_var()
355 int hSyncOff = var->xres + var->right_margin + var->left_margin; in sstfb_check_var()
356 int vSyncOff = var->yres + var->lower_margin + var->upper_margin; in sstfb_check_var()
357 int vBackPorch = var->left_margin, yDim = var->yres; in sstfb_check_var()
358 int vSyncOn = var->vsync_len; in sstfb_check_var()
362 if (sst_calc_pll(PICOS2KHZ(var->pixclock), &freq, &par->pll)) { in sstfb_check_var()
364 PICOS2KHZ(var->pixclock)); in sstfb_check_var()
365 return -EINVAL; in sstfb_check_var()
367 var->pixclock = KHZ2PICOS(freq); in sstfb_check_var()
369 if (var->vmode & FB_VMODE_INTERLACED) in sstfb_check_var()
371 if (var->vmode & FB_VMODE_DOUBLE) { in sstfb_check_var()
378 switch (var->bits_per_pixel) { in sstfb_check_var()
380 var->bits_per_pixel = 16; in sstfb_check_var()
383 printk(KERN_ERR "sstfb: Unsupported bpp %d\n", var->bits_per_pixel); in sstfb_check_var()
384 return -EINVAL; in sstfb_check_var()
388 if (var->xres <= 1 || yDim <= 0 || var->hsync_len <= 1 || in sstfb_check_var()
389 hSyncOff <= 1 || var->left_margin <= 2 || vSyncOn <= 0 || in sstfb_check_var()
391 return -EINVAL; in sstfb_check_var()
396 tiles_in_X = (var->xres + 63 ) / 64 * 2; in sstfb_check_var()
398 if (var->xres > POW2(11) || yDim >= POW2(11)) { in sstfb_check_var()
400 var->xres, var->yres); in sstfb_check_var()
401 return -EINVAL; in sstfb_check_var()
404 if (var->hsync_len > POW2(9) || hSyncOff > POW2(11) || in sstfb_check_var()
405 var->left_margin - 2 >= POW2(9) || vSyncOn >= POW2(13) || in sstfb_check_var()
409 return -EINVAL; in sstfb_check_var()
413 tiles_in_X = (var->xres + 63 ) / 64; in sstfb_check_var()
415 if (var->vmode) { in sstfb_check_var()
417 var->vmode); in sstfb_check_var()
418 return -EINVAL; in sstfb_check_var()
420 if (var->xres > POW2(10) || var->yres >= POW2(10)) { in sstfb_check_var()
422 var->xres, var->yres); in sstfb_check_var()
423 return -EINVAL; in sstfb_check_var()
425 if (var->hsync_len > POW2(8) || hSyncOff - 1 > POW2(10) || in sstfb_check_var()
426 var->left_margin - 2 >= POW2(8) || vSyncOn >= POW2(12) || in sstfb_check_var()
430 return -EINVAL; in sstfb_check_var()
434 /* it seems that the fbi uses tiles of 64x16 pixels to "map" the mem */ in sstfb_check_var()
437 * ((var->bits_per_pixel == 16) ? 2 : 4); in sstfb_check_var()
439 if (real_length * yDim > info->fix.smem_len) { in sstfb_check_var()
441 return -ENOMEM; in sstfb_check_var()
444 var->sync &= (FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT); in sstfb_check_var()
445 var->vmode &= (FB_VMODE_INTERLACED | FB_VMODE_DOUBLE); in sstfb_check_var()
446 var->xoffset = 0; in sstfb_check_var()
447 var->yoffset = 0; in sstfb_check_var()
448 var->height = -1; in sstfb_check_var()
449 var->width = -1; in sstfb_check_var()
454 /* var->{red|green|blue}.msb_right = 0; */ in sstfb_check_var()
456 switch (var->bits_per_pixel) { in sstfb_check_var()
458 var->red.length = 5; in sstfb_check_var()
459 var->green.length = 6; in sstfb_check_var()
460 var->blue.length = 5; in sstfb_check_var()
461 var->transp.length = 0; in sstfb_check_var()
463 var->red.offset = 11; in sstfb_check_var()
464 var->green.offset = 5; in sstfb_check_var()
465 var->blue.offset = 0; in sstfb_check_var()
466 var->transp.offset = 0; in sstfb_check_var()
469 return -EINVAL; in sstfb_check_var()
475 * sstfb_set_par - Optional function. Alters the hardware state.
480 struct sstfb_par *par = info->par; in sstfb_set_par()
482 struct pci_dev *sst_dev = par->dev; in sstfb_set_par()
486 par->hSyncOff = info->var.xres + info->var.right_margin + info->var.left_margin; in sstfb_set_par()
488 par->yDim = info->var.yres; in sstfb_set_par()
489 par->vSyncOn = info->var.vsync_len; in sstfb_set_par()
490 par->vSyncOff = info->var.yres + info->var.lower_margin + info->var.upper_margin; in sstfb_set_par()
491 par->vBackPorch = info->var.upper_margin; in sstfb_set_par()
493 /* We need par->pll */ in sstfb_set_par()
494 sst_calc_pll(PICOS2KHZ(info->var.pixclock), &freq, &par->pll); in sstfb_set_par()
496 if (info->var.vmode & FB_VMODE_INTERLACED) in sstfb_set_par()
497 par->vBackPorch += (par->vBackPorch % 2); in sstfb_set_par()
498 if (info->var.vmode & FB_VMODE_DOUBLE) { in sstfb_set_par()
499 par->vBackPorch <<= 1; in sstfb_set_par()
500 par->yDim <<=1; in sstfb_set_par()
501 par->vSyncOn <<=1; in sstfb_set_par()
502 par->vSyncOff <<=1; in sstfb_set_par()
508 par->tiles_in_X = (info->var.xres + 63 ) / 64 * 2; in sstfb_set_par()
511 par->tiles_in_X = (info->var.xres + 63 ) / 64; in sstfb_set_par()
515 f_ddprintk("%-7d %-8d %-7d %-8d\n", in sstfb_set_par()
516 info->var.hsync_len, par->hSyncOff, in sstfb_set_par()
517 par->vSyncOn, par->vSyncOff); in sstfb_set_par()
519 f_ddprintk("%-10d %-10d %-4d %-4d %-8ld\n", in sstfb_set_par()
520 info->var.left_margin, info->var.upper_margin, in sstfb_set_par()
521 info->var.xres, info->var.yres, PICOS2KHZ(info->var.pixclock)); in sstfb_set_par()
533 sst_write(BACKPORCH, par->vBackPorch << 16 | (info->var.left_margin - 2)); in sstfb_set_par()
534 sst_write(VIDEODIMENSIONS, par->yDim << 16 | (info->var.xres - 1)); in sstfb_set_par()
535 sst_write(HSYNC, (par->hSyncOff - 1) << 16 | (info->var.hsync_len - 1)); in sstfb_set_par()
536 sst_write(VSYNC, par->vSyncOff << 16 | par->vSyncOn); in sstfb_set_par()
545 par->dac_sw.set_vidmod(info, info->var.bits_per_pixel); in sstfb_set_par()
548 par->dac_sw.set_pll(info, &par->pll, VID_CLOCK); in sstfb_set_par()
575 ntiles = par->tiles_in_X; in sstfb_set_par()
588 switch (info->var.bits_per_pixel) { in sstfb_set_par()
593 return -EINVAL; in sstfb_set_par()
599 if (info->var.vmode & FB_VMODE_INTERLACED) in sstfb_set_par()
601 if (info->var.vmode & FB_VMODE_DOUBLE) in sstfb_set_par()
603 if (info->var.sync & FB_SYNC_HOR_HIGH_ACT) in sstfb_set_par()
605 if (info->var.sync & FB_SYNC_VERT_HIGH_ACT) in sstfb_set_par()
618 switch (info->var.bits_per_pixel) { in sstfb_set_par()
623 return -EINVAL; in sstfb_set_par()
627 /* Enable byte-swizzle functionality in hardware. in sstfb_set_par()
628 * With this enabled, all our read- and write-accesses to in sstfb_set_par()
630 * the hardware will automatically convert it to little-endian. in sstfb_set_par()
631 * - tested on HP-PARISC, Helge Deller <[email protected]> */ in sstfb_set_par()
641 * the "behaviour is undefined" (_very_ undefined) - Urs in sstfb_set_par()
647 info->var.xres - 1, par->yDim - 1); in sstfb_set_par()
649 sst_write(CLIP_LEFT_RIGHT, info->var.xres); in sstfb_set_par()
650 sst_write(CLIP_LOWY_HIGHY, par->yDim); in sstfb_set_par()
660 * sstfb_setcolreg - Optional function. Sets a color register.
671 struct sstfb_par *par = info->par; in sstfb_setcolreg()
675 f_dddprintk("%-2d rgbt: %#x, %#x, %#x, %#x\n", in sstfb_setcolreg()
680 red >>= (16 - info->var.red.length); in sstfb_setcolreg()
681 green >>= (16 - info->var.green.length); in sstfb_setcolreg()
682 blue >>= (16 - info->var.blue.length); in sstfb_setcolreg()
683 transp >>= (16 - info->var.transp.length); in sstfb_setcolreg()
684 col = (red << info->var.red.offset) in sstfb_setcolreg()
685 | (green << info->var.green.offset) in sstfb_setcolreg()
686 | (blue << info->var.blue.offset) in sstfb_setcolreg()
687 | (transp << info->var.transp.offset); in sstfb_setcolreg()
689 par->palette[regno] = col; in sstfb_setcolreg()
696 struct sstfb_par *par = info->par; in sstfb_setvgapass()
697 struct pci_dev *sst_dev = par->dev; in sstfb_setvgapass()
701 if (par->vgapass == enable) in sstfb_setvgapass()
703 par->vgapass = enable; in sstfb_setvgapass()
709 if (par->vgapass) { in sstfb_setvgapass()
711 fb_info(info, "Enabling VGA pass-through\n"); in sstfb_setvgapass()
714 fb_info(info, "Disabling VGA pass-through\n"); in sstfb_setvgapass()
737 struct sstfb_par *par = info->par; in show_vgapass()
738 return sprintf(buf, "%d\n", par->vgapass); in show_vgapass()
756 return -EFAULT; in sstfb_ioctl()
760 par = info->par; in sstfb_ioctl()
761 val = par->vgapass; in sstfb_ioctl()
763 return -EFAULT; in sstfb_ioctl()
767 return -EINVAL; in sstfb_ioctl()
772 * Screen-to-Screen BitBlt 2D command (for the bmove fb op.) - Voodoo2 only
777 struct sstfb_par *par = info->par;
778 u32 stride = info->fix.line_length;
787 sst_write(BLTSRCXY, area->sx | (area->sy << 16));
788 sst_write(BLTDSTXY, area->dx | (area->dy << 16));
789 sst_write(BLTSIZE, area->width | (area->height << 16));
798 * FillRect 2D command (solidfill or invert (via ROP_XOR)) - Voodoo2 only
803 struct sstfb_par *par = info->par;
804 u32 stride = info->fix.line_length;
809 sst_write(BLTCLIPX, info->var.xres);
810 sst_write(BLTCLIPY, info->var.yres);
813 sst_write(BLTCOLOR, rect->color);
814 sst_write(BLTROP, rect->rop == ROP_COPY ? BLTROP_COPY : BLTROP_XOR);
816 sst_write(BLTDSTXY, rect->dx | (rect->dy << 16));
817 sst_write(BLTSIZE, rect->width | (rect->height << 16));
831 u8 __iomem *fbbase_virt = info->screen_base; in sst_get_memsize()
834 if (mem >= 1 && mem <= 4) { in sst_get_memsize()
835 *memsize = (mem * 0x100000); in sst_get_memsize()
869 /* fbi should be idle, and fifo emty and mem disabled */
874 struct sstfb_par *par = info->par; in sst_detect_att()
899 struct sstfb_par *par = info->par; in sst_detect_ti()
935 struct sstfb_par *par = info->par; in sst_detect_ics()
965 * gfx, video, pci fifo should be reset, dram refresh disabled
972 struct sstfb_par *par = info->par; in sst_set_pll_att_ti()
999 dac_i_write(DACREG_AC0_I, t->m); in sst_set_pll_att_ti()
1000 dac_i_write(DACREG_AC1_I, t->p << 6 | t->n); in sst_set_pll_att_ti()
1005 dac_i_write(DACREG_BD0_I, t->m); in sst_set_pll_att_ti()
1006 dac_i_write(DACREG_BD1_I, t->p << 6 | t->n); in sst_set_pll_att_ti()
1017 /* power up the dac & return to "normal" non-indexed mode */ in sst_set_pll_att_ti()
1026 struct sstfb_par *par = info->par; in sst_set_pll_ics()
1034 sst_dac_write(DACREG_ICS_PLLDATA, t->m); in sst_set_pll_ics()
1035 sst_dac_write(DACREG_ICS_PLLDATA, t->p << 5 | t->n); in sst_set_pll_ics()
1045 sst_dac_write(DACREG_ICS_PLLDATA, t->m); in sst_set_pll_ics()
1046 sst_dac_write(DACREG_ICS_PLLDATA, t->p << 5 | t->n); in sst_set_pll_ics()
1063 struct sstfb_par *par = info->par; in sst_set_vidmod_att_ti()
1092 struct sstfb_par *par = info->par; in sst_set_vidmod_ics()
1140 par->dac_sw = dacs[i]; in sst_detect_dactype()
1150 struct pci_dev *dev = par->dev; in sst_init()
1156 spec = &voodoo_spec[par->type]; in sst_init()
1170 /* reset gfx + pci fifo */ in sst_init()
1195 gfx_clock = spec->default_gfx_clock; in sst_init()
1196 if ((gfxclk >10 ) && (gfxclk < spec->max_gfxclk)) { in sst_init()
1204 par->dac_sw.set_pll(info, &gfx_timings, GFX_CLOCK); in sst_init()
1210 /* FbiInit0: unreset gfx, unreset fifo */ in sst_init()
1214 par->vgapass = vgapass; in sst_init()
1215 if (par->vgapass) in sst_init()
1248 struct sstfb_par *par = info->par; in sst_shutdown()
1249 struct pci_dev *dev = par->dev; in sst_shutdown()
1253 /* reset video, gfx, fifo, disable dram + remap fbiinit2/3 */ in sst_shutdown()
1261 /* set 20Mhz gfx clock */ in sst_shutdown()
1263 par->dac_sw.set_pll(info, &gfx_timings, GFX_CLOCK); in sst_shutdown()
1302 else if (!strncmp(this_opt, "mem:",4)) in sstfb_setup()
1303 mem = simple_strtoul (this_opt+4, NULL, 0); in sstfb_setup()
1341 info = framebuffer_alloc(sizeof(struct sstfb_par), &pdev->dev); in sstfb_probe()
1343 return -ENOMEM; in sstfb_probe()
1347 par = info->par; in sstfb_probe()
1348 fix = &info->fix; in sstfb_probe()
1350 par->type = id->driver_data; in sstfb_probe()
1351 spec = &voodoo_spec[par->type]; in sstfb_probe()
1352 f_ddprintk("found device : %s\n", spec->name); in sstfb_probe()
1354 par->dev = pdev; in sstfb_probe()
1355 par->revision = pdev->revision; in sstfb_probe()
1357 fix->mmio_start = pci_resource_start(pdev,0); in sstfb_probe()
1358 fix->mmio_len = 0x400000; in sstfb_probe()
1359 fix->smem_start = fix->mmio_start + 0x400000; in sstfb_probe()
1361 if (!request_mem_region(fix->mmio_start, fix->mmio_len, "sstfb MMIO")) { in sstfb_probe()
1366 if (!request_mem_region(fix->smem_start, 0x400000,"sstfb FB")) { in sstfb_probe()
1371 par->mmio_vbase = ioremap(fix->mmio_start, in sstfb_probe()
1372 fix->mmio_len); in sstfb_probe()
1373 if (!par->mmio_vbase) { in sstfb_probe()
1375 fix->mmio_start); in sstfb_probe()
1378 info->screen_base = ioremap(fix->smem_start, 0x400000); in sstfb_probe()
1379 if (!info->screen_base) { in sstfb_probe()
1381 fix->smem_start); in sstfb_probe()
1389 sst_get_memsize(info, &fix->smem_len); in sstfb_probe()
1390 strscpy(fix->id, spec->name, sizeof(fix->id)); in sstfb_probe()
1393 fix->id, par->revision, par->dac_sw.name); in sstfb_probe()
1395 fix->smem_start, info->screen_base, in sstfb_probe()
1396 fix->smem_len >> 20); in sstfb_probe()
1398 f_ddprintk("regbase_virt: %p\n", par->mmio_vbase); in sstfb_probe()
1399 f_ddprintk("membase_phys: %#lx\n", fix->smem_start); in sstfb_probe()
1400 f_ddprintk("fbbase_virt: %p\n", info->screen_base); in sstfb_probe()
1402 info->fbops = &sstfb_ops; in sstfb_probe()
1403 info->pseudo_palette = par->palette; in sstfb_probe()
1405 fix->type = FB_TYPE_PACKED_PIXELS; in sstfb_probe()
1406 fix->visual = FB_VISUAL_TRUECOLOR; in sstfb_probe()
1407 fix->accel = FB_ACCEL_NONE; /* FIXME */ in sstfb_probe()
1413 fix->line_length = 2048; /* default value, for 24 or 32bit: 4096 */ in sstfb_probe()
1415 fb_find_mode(&info->var, info, mode_option, NULL, 0, NULL, 16); in sstfb_probe()
1417 if (sstfb_check_var(&info->var, info)) { in sstfb_probe()
1427 if (fb_alloc_cmap(&info->cmap, 256, 0)) { in sstfb_probe()
1433 info->device = &pdev->dev; in sstfb_probe()
1442 if (device_create_file(info->dev, &device_attrs[0])) in sstfb_probe()
1447 fix->id, info->screen_base); in sstfb_probe()
1452 fb_dealloc_cmap(&info->cmap); in sstfb_probe()
1454 iounmap(info->screen_base); in sstfb_probe()
1456 iounmap(par->mmio_vbase); in sstfb_probe()
1458 release_mem_region(fix->smem_start, 0x400000); in sstfb_probe()
1460 release_mem_region(fix->mmio_start, info->fix.mmio_len); in sstfb_probe()
1463 return -ENXIO; /* no voodoo detected */ in sstfb_probe()
1472 par = info->par; in sstfb_remove()
1475 device_remove_file(info->dev, &device_attrs[0]); in sstfb_remove()
1478 iounmap(info->screen_base); in sstfb_remove()
1479 iounmap(par->mmio_vbase); in sstfb_remove()
1480 release_mem_region(info->fix.smem_start, 0x400000); in sstfb_remove()
1481 release_mem_region(info->fix.mmio_start, info->fix.mmio_len); in sstfb_remove()
1482 fb_dealloc_cmap(&info->cmap); in sstfb_remove()
1509 return -ENODEV; in sstfb_init()
1512 return -ENODEV; in sstfb_init()
1531 module_param(mem, int, 0);
1532 MODULE_PARM_DESC(mem, "Size of frame buffer memory in MB (1, 2, 4 MB, default=autodetect)");