15 #include <linux/module.h>
16 #include <linux/kernel.h>
17 #include <linux/errno.h>
18 #include <linux/string.h>
20 #include <linux/tty.h>
25 #include <linux/pci.h>
47 { 0, {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0}, 0,
49 { 4, {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0}, 0,
51 { 4, {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0}, 1,
53 { 8, {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0}, 0,
57 {16, {11, 5, 0}, {5, 6, 0}, {0, 5, 0}, {0, 0, 0}, 0,
59 {32, {16, 8, 0}, {8, 8, 0}, {0, 8, 0}, {0, 0, 0}, 0,
64 static const struct svga_pll vt8623_pll = {2, 127, 2, 7, 0, 3,
65 60000, 300000, 14318};
76 static struct vga_regset vt8623_v_total_regs[] = {{0x06, 0, 7}, {0x07, 0, 0}, {0x07, 5, 5}, {0x35, 0, 0},
VGA_REGSET_END};
77 static struct vga_regset vt8623_v_display_regs[] = {{0x12, 0, 7}, {0x07, 1, 1}, {0x07, 6, 6}, {0x35, 2, 2},
VGA_REGSET_END};
78 static struct vga_regset vt8623_v_blank_start_regs[] = {{0x15, 0, 7}, {0x07, 3, 3}, {0x09, 5, 5}, {0x35, 3, 3},
VGA_REGSET_END};
80 static struct vga_regset vt8623_v_sync_start_regs[] = {{0x10, 0, 7}, {0x07, 2, 2}, {0x07, 7, 7}, {0x35, 1, 1},
VGA_REGSET_END};
84 static struct vga_regset vt8623_line_compare_regs[] = {{0x18, 0, 7}, {0x07, 4, 4}, {0x09, 6, 6}, {0x33, 0, 2}, {0x35, 4, 4},
VGA_REGSET_END};
86 static struct vga_regset vt8623_start_address_regs[] = {{0x0d, 0, 7}, {0x0c, 0, 7}, {0x34, 0, 7}, {0x48, 0, 1},
VGA_REGSET_END};
89 vt8623_h_total_regs, vt8623_h_display_regs, vt8623_h_blank_start_regs,
90 vt8623_h_blank_end_regs, vt8623_h_sync_start_regs, vt8623_h_sync_end_regs,
91 vt8623_v_total_regs, vt8623_v_display_regs, vt8623_v_blank_start_regs,
92 vt8623_v_blank_end_regs, vt8623_v_sync_start_regs, vt8623_v_sync_end_regs,
101 static char *mode_option =
"640x480-8@60";
109 MODULE_DESCRIPTION(
"fbdev driver for integrated graphics core in VIA VT8623 [CLE266]");
118 MODULE_PARM_DESC(mtrr,
"Enable write-combining with MTRR (1=enable, 0=disable, default=1)");
124 static void vt8623fb_tilecursor(
struct fb_info *
info,
struct fb_tilecursor *cursor)
131 static struct fb_tile_ops vt8623fb_tile_ops = {
136 .fb_tilecursor = vt8623fb_tilecursor,
145 static inline u32 expand_color(
u32 c)
147 return ((c & 1) | ((c & 2) << 7) | ((c & 4) << 14) | ((c & 8) << 21)) * 0xFF;
155 const u8 *src1, *
src;
163 + ((image->
dx / 8) * 4);
165 for (y = 0; y < image->
height; y++) {
168 for (x = 0; x < image->
width; x += 8) {
169 val = *(src++) * 0x01010101;
170 val = (val & fg) | (~val & bg);
173 src1 += image->
width / 8;
174 dst1 += info->
fix.line_length;
179 static void vt8623fb_iplan_fillrect(
struct fb_info *info,
const struct fb_fillrect *rect)
187 + ((rect->
dx / 8) * 4);
189 for (y = 0; y < rect->
height; y++) {
191 for (x = 0; x < rect->
width; x += 8) {
194 dst1 += info->
fix.line_length;
200 static inline u32 expand_pixel(
u32 c)
202 return (((c & 1) << 24) | ((c & 2) << 27) | ((c & 4) << 14) | ((c & 8) << 17) |
203 ((c & 16) << 4) | ((c & 32) << 7) | ((c & 64) >> 6) | ((c & 128) >> 3)) * 0xF;
207 static void vt8623fb_cfb4_imageblit(
struct fb_info *info,
const struct fb_image *image)
211 const u8 *src1, *
src;
219 + ((image->
dx / 8) * 4);
221 for (y = 0; y < image->
height; y++) {
224 for (x = 0; x < image->
width; x += 8) {
225 val = expand_pixel(*(src++));
226 val = (val & fg) | (~val & bg);
229 src1 += image->
width / 8;
230 dst1 += info->
fix.line_length;
234 static void vt8623fb_imageblit(
struct fb_info *info,
const struct fb_image *image)
236 if ((info->
var.bits_per_pixel == 4) && (image->
depth == 1)
237 && ((image->
width % 8) == 0) && ((image->
dx % 8) == 0)) {
239 vt8623fb_iplan_imageblit(info, image);
241 vt8623fb_cfb4_imageblit(info, image);
248 if ((info->
var.bits_per_pixel == 4)
249 && ((rect->
width % 8) == 0) && ((rect->
dx % 8) == 0)
251 vt8623fb_iplan_fillrect(info, rect);
260 static void vt8623_set_pixclock(
struct fb_info *info,
u32 pixclock)
269 printk(
KERN_ERR "fb%d: cannot set requested pixclock, keeping old value\n", info->
node);
278 vga_wseq(par->
state.vgabase, 0x46, (n | (r << 6)));
279 vga_wseq(par->
state.vgabase, 0x47, m);
284 svga_wseq_mask(par->
state.vgabase, 0x40, 0x02, 0x02);
285 svga_wseq_mask(par->
state.vgabase, 0x40, 0x00, 0x02);
289 static int vt8623fb_open(
struct fb_info *info,
int user)
298 par->
state.vgabase = vgabase;
300 par->
state.num_crtc = 0xA2;
301 par->
state.num_seq = 0x50;
311 static int vt8623fb_release(
struct fb_info *info,
int user)
350 step = vt8623fb_formats[rv].
xresstep - 1;
357 printk(
KERN_ERR "fb%d: not enough framebuffer memory (%d kB requested , %d kB available)\n", info->
node, mem >> 10, (
unsigned int) (info->
screen_size >> 10));
364 printk(
KERN_ERR "fb%d: text framebuffer size too large (%d kB requested, 256 kB possible)\n", info->
node, mem >> 10);
383 static int vt8623fb_set_par(
struct fb_info *info)
385 u32 mode, offset_value, fetch_value, screen_size;
390 info->
fix.ypanstep = 1;
391 info->
fix.line_length = (info->
var.xres_virtual *
bpp) / 8;
394 info->tileops =
NULL;
397 info->
pixmap.blit_x = (bpp == 4) ? (1 << (8 - 1)) : (~(
u32)0);
400 offset_value = (info->
var.xres_virtual *
bpp) / 64;
401 fetch_value = ((info->
var.xres *
bpp) / 128) + 4;
404 fetch_value = (info->
var.xres / 8) + 8;
406 screen_size = info->
var.yres_virtual * info->
fix.line_length;
408 info->
fix.ypanstep = 16;
409 info->
fix.line_length = 0;
412 info->tileops = &vt8623fb_tile_ops;
415 info->
pixmap.blit_x = 1 << (8 - 1);
416 info->
pixmap.blit_y = 1 << (16 - 1);
418 offset_value = info->
var.xres_virtual / 16;
419 fetch_value = (info->
var.xres / 8) + 8;
420 screen_size = (info->
var.xres_virtual * info->
var.yres_virtual) / 64;
423 info->
var.xoffset = 0;
424 info->
var.yoffset = 0;
428 svga_wseq_mask(par->
state.vgabase, 0x10, 0x01, 0x01);
429 svga_wcrt_mask(par->
state.vgabase, 0x11, 0x00, 0x80);
430 svga_wcrt_mask(par->
state.vgabase, 0x47, 0x00, 0x01);
433 svga_wseq_mask(par->
state.vgabase, 0x01, 0x20, 0x20);
434 svga_wcrt_mask(par->
state.vgabase, 0x36, 0x30, 0x30);
435 svga_wcrt_mask(par->
state.vgabase, 0x17, 0x00, 0x80);
449 svga_wcrt_mask(par->
state.vgabase, 0x03, 0x00, 0x60);
450 svga_wcrt_mask(par->
state.vgabase, 0x05, 0x00, 0x60);
453 svga_wcrt_mask(par->
state.vgabase, 0x09, 0x80, 0x80);
455 svga_wcrt_mask(par->
state.vgabase, 0x09, 0x00, 0x80);
457 svga_wseq_mask(par->
state.vgabase, 0x1E, 0xF0, 0xF0);
458 svga_wseq_mask(par->
state.vgabase, 0x2A, 0x0F, 0x0F);
459 svga_wseq_mask(par->
state.vgabase, 0x16, 0x08, 0xBF);
460 vga_wseq(par->
state.vgabase, 0x17, 0x1F);
461 vga_wseq(par->
state.vgabase, 0x18, 0x4E);
462 svga_wseq_mask(par->
state.vgabase, 0x1A, 0x08, 0x08);
464 vga_wcrt(par->
state.vgabase, 0x32, 0x00);
465 vga_wcrt(par->
state.vgabase, 0x34, 0x00);
466 vga_wcrt(par->
state.vgabase, 0x6A, 0x80);
467 vga_wcrt(par->
state.vgabase, 0x6A, 0xC0);
469 vga_wgfx(par->
state.vgabase, 0x20, 0x00);
470 vga_wgfx(par->
state.vgabase, 0x21, 0x00);
471 vga_wgfx(par->
state.vgabase, 0x22, 0x00);
479 svga_wseq_mask(par->
state.vgabase, 0x15, 0x00, 0xFE);
480 svga_wcrt_mask(par->
state.vgabase, 0x11, 0x60, 0x70);
485 svga_wseq_mask(par->
state.vgabase, 0x15, 0x20, 0xFE);
486 svga_wcrt_mask(par->
state.vgabase, 0x11, 0x00, 0x70);
489 pr_debug(
"fb%d: 4 bit pseudocolor, planar\n", info->
node);
490 svga_wseq_mask(par->
state.vgabase, 0x15, 0x00, 0xFE);
491 svga_wcrt_mask(par->
state.vgabase, 0x11, 0x00, 0x70);
495 svga_wseq_mask(par->
state.vgabase, 0x15, 0x22, 0xFE);
499 svga_wseq_mask(par->
state.vgabase, 0x15, 0xB6, 0xFE);
503 svga_wseq_mask(par->
state.vgabase, 0x15, 0xAE, 0xFE);
510 vt8623_set_pixclock(info, info->
var.pixclock);
518 svga_wcrt_mask(par->
state.vgabase, 0x17, 0x80, 0x80);
519 svga_wcrt_mask(par->
state.vgabase, 0x36, 0x00, 0x30);
520 svga_wseq_mask(par->
state.vgabase, 0x01, 0x00, 0x20);
529 switch (fb->
var.bits_per_pixel) {
555 if (fb->
var.green.length == 5)
557 ((green & 0xF800) >> 6) | ((blue & 0xF800) >> 11);
558 else if (fb->
var.green.length == 6)
560 ((green & 0xFC00) >> 5) | ((blue & 0xF800) >> 11);
571 (green & 0xFF00) | ((blue & 0xFF00) >> 8);
581 static int vt8623fb_blank(
int blank_mode,
struct fb_info *info)
585 switch (blank_mode) {
588 svga_wcrt_mask(par->
state.vgabase, 0x36, 0x00, 0x30);
589 svga_wseq_mask(par->
state.vgabase, 0x01, 0x00, 0x20);
593 svga_wcrt_mask(par->
state.vgabase, 0x36, 0x00, 0x30);
594 svga_wseq_mask(par->
state.vgabase, 0x01, 0x20, 0x20);
597 pr_debug(
"fb%d: DPMS standby (hsync off)\n", info->
node);
598 svga_wcrt_mask(par->
state.vgabase, 0x36, 0x10, 0x30);
599 svga_wseq_mask(par->
state.vgabase, 0x01, 0x20, 0x20);
602 pr_debug(
"fb%d: DPMS suspend (vsync off)\n", info->
node);
603 svga_wcrt_mask(par->
state.vgabase, 0x36, 0x20, 0x30);
604 svga_wseq_mask(par->
state.vgabase, 0x01, 0x20, 0x20);
608 svga_wcrt_mask(par->
state.vgabase, 0x36, 0x30, 0x30);
609 svga_wseq_mask(par->
state.vgabase, 0x01, 0x20, 0x20);
623 if (info->
var.bits_per_pixel == 0) {
624 offset = (var->
yoffset / 16) * info->
var.xres_virtual
626 offset = offset >> 3;
628 offset = (var->
yoffset * info->
fix.line_length) +
629 (var->
xoffset * info->
var.bits_per_pixel / 8);
630 offset = offset >> ((info->
var.bits_per_pixel == 4) ? 2 : 1);
645 static struct fb_ops vt8623fb_ops = {
647 .fb_open = vt8623fb_open,
648 .fb_release = vt8623fb_release,
649 .fb_check_var = vt8623fb_check_var,
650 .fb_set_par = vt8623fb_set_par,
651 .fb_setcolreg = vt8623fb_setcolreg,
652 .fb_blank = vt8623fb_blank,
653 .fb_pan_display = vt8623fb_pan_display,
654 .fb_fillrect = vt8623fb_fillrect,
656 .fb_imageblit = vt8623fb_imageblit,
669 unsigned int memsize1, memsize2;
673 if (! svga_primary_device(dev)) {
674 dev_info(&(dev->
dev),
"ignoring secondary device\n");
681 dev_err(&(dev->
dev),
"cannot allocate memory\n");
689 info->
fbops = &vt8623fb_ops;
696 goto err_enable_device;
701 dev_err(info->
device,
"cannot reserve framebuffer region\n");
702 goto err_request_regions;
726 bus_reg.end = 64 * 1024;
735 memsize1 = (vga_rseq(par->
state.vgabase, 0x34) + 1) >> 1;
736 memsize2 = vga_rseq(par->
state.vgabase, 0x39) << 2;
738 if ((16 <= memsize1) && (memsize1 <= 64) && (memsize1 == memsize2))
741 dev_err(info->
device,
"memory size detection failed (%x %x), suppose 16 MB\n", memsize1, memsize2);
749 info->
fix.ypanstep = 0;
758 if (! ((rc == 1) || (rc == 2))) {
777 pci_name(dev), info->
fix.smem_len >> 20);
780 pci_set_drvdata(dev, info);
812 struct fb_info *info = pci_get_drvdata(dev);
832 pci_set_drvdata(dev,
NULL);
843 struct fb_info *info = pci_get_drvdata(dev);
874 struct fb_info *info = pci_get_drvdata(dev);
893 vt8623fb_set_par(info);
903 #define vt8623_pci_suspend NULL
904 #define vt8623_pci_resume NULL
911 {0, 0, 0, 0, 0, 0, 0}
916 static struct pci_driver vt8623fb_pci_driver = {
918 .id_table = vt8623_devices,
919 .probe = vt8623_pci_probe,
927 static void __exit vt8623fb_cleanup(
void)
929 pr_debug(
"vt8623fb: cleaning up\n");
935 static int __init vt8623fb_init(
void)
944 if (option && *option)
948 pr_debug(
"vt8623fb: initializing\n");
949 return pci_register_driver(&vt8623fb_pci_driver);