diff options
Diffstat (limited to 'drivers/video/s3fb.c')
-rw-r--r-- | drivers/video/s3fb.c | 341 |
1 files changed, 211 insertions, 130 deletions
diff --git a/drivers/video/s3fb.c b/drivers/video/s3fb.c index 75738a928610..ddedad9cd069 100644 --- a/drivers/video/s3fb.c +++ b/drivers/video/s3fb.c | |||
@@ -64,6 +64,8 @@ static const struct svga_fb_format s3fb_formats[] = { | |||
64 | 64 | ||
65 | static const struct svga_pll s3_pll = {3, 129, 3, 33, 0, 3, | 65 | static const struct svga_pll s3_pll = {3, 129, 3, 33, 0, 3, |
66 | 35000, 240000, 14318}; | 66 | 35000, 240000, 14318}; |
67 | static const struct svga_pll s3_trio3d_pll = {3, 129, 3, 31, 0, 4, | ||
68 | 230000, 460000, 14318}; | ||
67 | 69 | ||
68 | static const int s3_memsizes[] = {4096, 0, 3072, 8192, 2048, 6144, 1024, 512}; | 70 | static const int s3_memsizes[] = {4096, 0, 3072, 8192, 2048, 6144, 1024, 512}; |
69 | 71 | ||
@@ -72,7 +74,8 @@ static const char * const s3_names[] = {"S3 Unknown", "S3 Trio32", "S3 Trio64", | |||
72 | "S3 Plato/PX", "S3 Aurora64VP", "S3 Virge", | 74 | "S3 Plato/PX", "S3 Aurora64VP", "S3 Virge", |
73 | "S3 Virge/VX", "S3 Virge/DX", "S3 Virge/GX", | 75 | "S3 Virge/VX", "S3 Virge/DX", "S3 Virge/GX", |
74 | "S3 Virge/GX2", "S3 Virge/GX2P", "S3 Virge/GX2P", | 76 | "S3 Virge/GX2", "S3 Virge/GX2P", "S3 Virge/GX2P", |
75 | "S3 Trio3D/1X", "S3 Trio3D/2X", "S3 Trio3D/2X"}; | 77 | "S3 Trio3D/1X", "S3 Trio3D/2X", "S3 Trio3D/2X", |
78 | "S3 Trio3D"}; | ||
76 | 79 | ||
77 | #define CHIP_UNKNOWN 0x00 | 80 | #define CHIP_UNKNOWN 0x00 |
78 | #define CHIP_732_TRIO32 0x01 | 81 | #define CHIP_732_TRIO32 0x01 |
@@ -93,6 +96,7 @@ static const char * const s3_names[] = {"S3 Unknown", "S3 Trio32", "S3 Trio64", | |||
93 | #define CHIP_360_TRIO3D_1X 0x10 | 96 | #define CHIP_360_TRIO3D_1X 0x10 |
94 | #define CHIP_362_TRIO3D_2X 0x11 | 97 | #define CHIP_362_TRIO3D_2X 0x11 |
95 | #define CHIP_368_TRIO3D_2X 0x12 | 98 | #define CHIP_368_TRIO3D_2X 0x12 |
99 | #define CHIP_365_TRIO3D 0x13 | ||
96 | 100 | ||
97 | #define CHIP_XXX_TRIO 0x80 | 101 | #define CHIP_XXX_TRIO 0x80 |
98 | #define CHIP_XXX_TRIO64V2_DXGX 0x81 | 102 | #define CHIP_XXX_TRIO64V2_DXGX 0x81 |
@@ -119,9 +123,11 @@ static const struct vga_regset s3_v_sync_start_regs[] = {{0x10, 0, 7}, {0x07, | |||
119 | static const struct vga_regset s3_v_sync_end_regs[] = {{0x11, 0, 3}, VGA_REGSET_END}; | 123 | static const struct vga_regset s3_v_sync_end_regs[] = {{0x11, 0, 3}, VGA_REGSET_END}; |
120 | 124 | ||
121 | static const struct vga_regset s3_line_compare_regs[] = {{0x18, 0, 7}, {0x07, 4, 4}, {0x09, 6, 6}, {0x5E, 6, 6}, VGA_REGSET_END}; | 125 | static const struct vga_regset s3_line_compare_regs[] = {{0x18, 0, 7}, {0x07, 4, 4}, {0x09, 6, 6}, {0x5E, 6, 6}, VGA_REGSET_END}; |
122 | static const struct vga_regset s3_start_address_regs[] = {{0x0d, 0, 7}, {0x0c, 0, 7}, {0x31, 4, 5}, {0x51, 0, 1}, VGA_REGSET_END}; | 126 | static const struct vga_regset s3_start_address_regs[] = {{0x0d, 0, 7}, {0x0c, 0, 7}, {0x69, 0, 4}, VGA_REGSET_END}; |
123 | static const struct vga_regset s3_offset_regs[] = {{0x13, 0, 7}, {0x51, 4, 5}, VGA_REGSET_END}; /* set 0x43 bit 2 to 0 */ | 127 | static const struct vga_regset s3_offset_regs[] = {{0x13, 0, 7}, {0x51, 4, 5}, VGA_REGSET_END}; /* set 0x43 bit 2 to 0 */ |
124 | 128 | ||
129 | static const struct vga_regset s3_dtpc_regs[] = {{0x3B, 0, 7}, {0x5D, 6, 6}, VGA_REGSET_END}; | ||
130 | |||
125 | static const struct svga_timing_regs s3_timing_regs = { | 131 | static const struct svga_timing_regs s3_timing_regs = { |
126 | s3_h_total_regs, s3_h_display_regs, s3_h_blank_start_regs, | 132 | s3_h_total_regs, s3_h_display_regs, s3_h_blank_start_regs, |
127 | s3_h_blank_end_regs, s3_h_sync_start_regs, s3_h_sync_end_regs, | 133 | s3_h_blank_end_regs, s3_h_sync_start_regs, s3_h_sync_end_regs, |
@@ -188,12 +194,19 @@ static void s3fb_settile_fast(struct fb_info *info, struct fb_tilemap *map) | |||
188 | } | 194 | } |
189 | } | 195 | } |
190 | 196 | ||
197 | static void s3fb_tilecursor(struct fb_info *info, struct fb_tilecursor *cursor) | ||
198 | { | ||
199 | struct s3fb_info *par = info->par; | ||
200 | |||
201 | svga_tilecursor(par->state.vgabase, info, cursor); | ||
202 | } | ||
203 | |||
191 | static struct fb_tile_ops s3fb_tile_ops = { | 204 | static struct fb_tile_ops s3fb_tile_ops = { |
192 | .fb_settile = svga_settile, | 205 | .fb_settile = svga_settile, |
193 | .fb_tilecopy = svga_tilecopy, | 206 | .fb_tilecopy = svga_tilecopy, |
194 | .fb_tilefill = svga_tilefill, | 207 | .fb_tilefill = svga_tilefill, |
195 | .fb_tileblit = svga_tileblit, | 208 | .fb_tileblit = svga_tileblit, |
196 | .fb_tilecursor = svga_tilecursor, | 209 | .fb_tilecursor = s3fb_tilecursor, |
197 | .fb_get_tilemax = svga_get_tilemax, | 210 | .fb_get_tilemax = svga_get_tilemax, |
198 | }; | 211 | }; |
199 | 212 | ||
@@ -202,7 +215,7 @@ static struct fb_tile_ops s3fb_fast_tile_ops = { | |||
202 | .fb_tilecopy = svga_tilecopy, | 215 | .fb_tilecopy = svga_tilecopy, |
203 | .fb_tilefill = svga_tilefill, | 216 | .fb_tilefill = svga_tilefill, |
204 | .fb_tileblit = svga_tileblit, | 217 | .fb_tileblit = svga_tileblit, |
205 | .fb_tilecursor = svga_tilecursor, | 218 | .fb_tilecursor = s3fb_tilecursor, |
206 | .fb_get_tilemax = svga_get_tilemax, | 219 | .fb_get_tilemax = svga_get_tilemax, |
207 | }; | 220 | }; |
208 | 221 | ||
@@ -334,33 +347,34 @@ static void s3_set_pixclock(struct fb_info *info, u32 pixclock) | |||
334 | u8 regval; | 347 | u8 regval; |
335 | int rv; | 348 | int rv; |
336 | 349 | ||
337 | rv = svga_compute_pll(&s3_pll, 1000000000 / pixclock, &m, &n, &r, info->node); | 350 | rv = svga_compute_pll((par->chip == CHIP_365_TRIO3D) ? &s3_trio3d_pll : &s3_pll, |
351 | 1000000000 / pixclock, &m, &n, &r, info->node); | ||
338 | if (rv < 0) { | 352 | if (rv < 0) { |
339 | printk(KERN_ERR "fb%d: cannot set requested pixclock, keeping old value\n", info->node); | 353 | printk(KERN_ERR "fb%d: cannot set requested pixclock, keeping old value\n", info->node); |
340 | return; | 354 | return; |
341 | } | 355 | } |
342 | 356 | ||
343 | /* Set VGA misc register */ | 357 | /* Set VGA misc register */ |
344 | regval = vga_r(NULL, VGA_MIS_R); | 358 | regval = vga_r(par->state.vgabase, VGA_MIS_R); |
345 | vga_w(NULL, VGA_MIS_W, regval | VGA_MIS_ENB_PLL_LOAD); | 359 | vga_w(par->state.vgabase, VGA_MIS_W, regval | VGA_MIS_ENB_PLL_LOAD); |
346 | 360 | ||
347 | /* Set S3 clock registers */ | 361 | /* Set S3 clock registers */ |
348 | if (par->chip == CHIP_360_TRIO3D_1X || | 362 | if (par->chip == CHIP_360_TRIO3D_1X || |
349 | par->chip == CHIP_362_TRIO3D_2X || | 363 | par->chip == CHIP_362_TRIO3D_2X || |
350 | par->chip == CHIP_368_TRIO3D_2X) { | 364 | par->chip == CHIP_368_TRIO3D_2X) { |
351 | vga_wseq(NULL, 0x12, (n - 2) | ((r & 3) << 6)); /* n and two bits of r */ | 365 | vga_wseq(par->state.vgabase, 0x12, (n - 2) | ((r & 3) << 6)); /* n and two bits of r */ |
352 | vga_wseq(NULL, 0x29, r >> 2); /* remaining highest bit of r */ | 366 | vga_wseq(par->state.vgabase, 0x29, r >> 2); /* remaining highest bit of r */ |
353 | } else | 367 | } else |
354 | vga_wseq(NULL, 0x12, (n - 2) | (r << 5)); | 368 | vga_wseq(par->state.vgabase, 0x12, (n - 2) | (r << 5)); |
355 | vga_wseq(NULL, 0x13, m - 2); | 369 | vga_wseq(par->state.vgabase, 0x13, m - 2); |
356 | 370 | ||
357 | udelay(1000); | 371 | udelay(1000); |
358 | 372 | ||
359 | /* Activate clock - write 0, 1, 0 to seq/15 bit 5 */ | 373 | /* Activate clock - write 0, 1, 0 to seq/15 bit 5 */ |
360 | regval = vga_rseq (NULL, 0x15); /* | 0x80; */ | 374 | regval = vga_rseq (par->state.vgabase, 0x15); /* | 0x80; */ |
361 | vga_wseq(NULL, 0x15, regval & ~(1<<5)); | 375 | vga_wseq(par->state.vgabase, 0x15, regval & ~(1<<5)); |
362 | vga_wseq(NULL, 0x15, regval | (1<<5)); | 376 | vga_wseq(par->state.vgabase, 0x15, regval | (1<<5)); |
363 | vga_wseq(NULL, 0x15, regval & ~(1<<5)); | 377 | vga_wseq(par->state.vgabase, 0x15, regval & ~(1<<5)); |
364 | } | 378 | } |
365 | 379 | ||
366 | 380 | ||
@@ -372,7 +386,10 @@ static int s3fb_open(struct fb_info *info, int user) | |||
372 | 386 | ||
373 | mutex_lock(&(par->open_lock)); | 387 | mutex_lock(&(par->open_lock)); |
374 | if (par->ref_count == 0) { | 388 | if (par->ref_count == 0) { |
389 | void __iomem *vgabase = par->state.vgabase; | ||
390 | |||
375 | memset(&(par->state), 0, sizeof(struct vgastate)); | 391 | memset(&(par->state), 0, sizeof(struct vgastate)); |
392 | par->state.vgabase = vgabase; | ||
376 | par->state.flags = VGA_SAVE_MODE | VGA_SAVE_FONTS | VGA_SAVE_CMAP; | 393 | par->state.flags = VGA_SAVE_MODE | VGA_SAVE_FONTS | VGA_SAVE_CMAP; |
377 | par->state.num_crtc = 0x70; | 394 | par->state.num_crtc = 0x70; |
378 | par->state.num_seq = 0x20; | 395 | par->state.num_seq = 0x20; |
@@ -470,6 +487,7 @@ static int s3fb_set_par(struct fb_info *info) | |||
470 | struct s3fb_info *par = info->par; | 487 | struct s3fb_info *par = info->par; |
471 | u32 value, mode, hmul, offset_value, screen_size, multiplex, dbytes; | 488 | u32 value, mode, hmul, offset_value, screen_size, multiplex, dbytes; |
472 | u32 bpp = info->var.bits_per_pixel; | 489 | u32 bpp = info->var.bits_per_pixel; |
490 | u32 htotal, hsstart; | ||
473 | 491 | ||
474 | if (bpp != 0) { | 492 | if (bpp != 0) { |
475 | info->fix.ypanstep = 1; | 493 | info->fix.ypanstep = 1; |
@@ -504,99 +522,112 @@ static int s3fb_set_par(struct fb_info *info) | |||
504 | info->var.activate = FB_ACTIVATE_NOW; | 522 | info->var.activate = FB_ACTIVATE_NOW; |
505 | 523 | ||
506 | /* Unlock registers */ | 524 | /* Unlock registers */ |
507 | vga_wcrt(NULL, 0x38, 0x48); | 525 | vga_wcrt(par->state.vgabase, 0x38, 0x48); |
508 | vga_wcrt(NULL, 0x39, 0xA5); | 526 | vga_wcrt(par->state.vgabase, 0x39, 0xA5); |
509 | vga_wseq(NULL, 0x08, 0x06); | 527 | vga_wseq(par->state.vgabase, 0x08, 0x06); |
510 | svga_wcrt_mask(0x11, 0x00, 0x80); | 528 | svga_wcrt_mask(par->state.vgabase, 0x11, 0x00, 0x80); |
511 | 529 | ||
512 | /* Blank screen and turn off sync */ | 530 | /* Blank screen and turn off sync */ |
513 | svga_wseq_mask(0x01, 0x20, 0x20); | 531 | svga_wseq_mask(par->state.vgabase, 0x01, 0x20, 0x20); |
514 | svga_wcrt_mask(0x17, 0x00, 0x80); | 532 | svga_wcrt_mask(par->state.vgabase, 0x17, 0x00, 0x80); |
515 | 533 | ||
516 | /* Set default values */ | 534 | /* Set default values */ |
517 | svga_set_default_gfx_regs(); | 535 | svga_set_default_gfx_regs(par->state.vgabase); |
518 | svga_set_default_atc_regs(); | 536 | svga_set_default_atc_regs(par->state.vgabase); |
519 | svga_set_default_seq_regs(); | 537 | svga_set_default_seq_regs(par->state.vgabase); |
520 | svga_set_default_crt_regs(); | 538 | svga_set_default_crt_regs(par->state.vgabase); |
521 | svga_wcrt_multi(s3_line_compare_regs, 0xFFFFFFFF); | 539 | svga_wcrt_multi(par->state.vgabase, s3_line_compare_regs, 0xFFFFFFFF); |
522 | svga_wcrt_multi(s3_start_address_regs, 0); | 540 | svga_wcrt_multi(par->state.vgabase, s3_start_address_regs, 0); |
523 | 541 | ||
524 | /* S3 specific initialization */ | 542 | /* S3 specific initialization */ |
525 | svga_wcrt_mask(0x58, 0x10, 0x10); /* enable linear framebuffer */ | 543 | svga_wcrt_mask(par->state.vgabase, 0x58, 0x10, 0x10); /* enable linear framebuffer */ |
526 | svga_wcrt_mask(0x31, 0x08, 0x08); /* enable sequencer access to framebuffer above 256 kB */ | 544 | svga_wcrt_mask(par->state.vgabase, 0x31, 0x08, 0x08); /* enable sequencer access to framebuffer above 256 kB */ |
527 | 545 | ||
528 | /* svga_wcrt_mask(0x33, 0x08, 0x08); */ /* DDR ? */ | 546 | /* svga_wcrt_mask(par->state.vgabase, 0x33, 0x08, 0x08); */ /* DDR ? */ |
529 | /* svga_wcrt_mask(0x43, 0x01, 0x01); */ /* DDR ? */ | 547 | /* svga_wcrt_mask(par->state.vgabase, 0x43, 0x01, 0x01); */ /* DDR ? */ |
530 | svga_wcrt_mask(0x33, 0x00, 0x08); /* no DDR ? */ | 548 | svga_wcrt_mask(par->state.vgabase, 0x33, 0x00, 0x08); /* no DDR ? */ |
531 | svga_wcrt_mask(0x43, 0x00, 0x01); /* no DDR ? */ | 549 | svga_wcrt_mask(par->state.vgabase, 0x43, 0x00, 0x01); /* no DDR ? */ |
532 | 550 | ||
533 | svga_wcrt_mask(0x5D, 0x00, 0x28); /* Clear strange HSlen bits */ | 551 | svga_wcrt_mask(par->state.vgabase, 0x5D, 0x00, 0x28); /* Clear strange HSlen bits */ |
534 | 552 | ||
535 | /* svga_wcrt_mask(0x58, 0x03, 0x03); */ | 553 | /* svga_wcrt_mask(par->state.vgabase, 0x58, 0x03, 0x03); */ |
536 | 554 | ||
537 | /* svga_wcrt_mask(0x53, 0x12, 0x13); */ /* enable MMIO */ | 555 | /* svga_wcrt_mask(par->state.vgabase, 0x53, 0x12, 0x13); */ /* enable MMIO */ |
538 | /* svga_wcrt_mask(0x40, 0x08, 0x08); */ /* enable write buffer */ | 556 | /* svga_wcrt_mask(par->state.vgabase, 0x40, 0x08, 0x08); */ /* enable write buffer */ |
539 | 557 | ||
540 | 558 | ||
541 | /* Set the offset register */ | 559 | /* Set the offset register */ |
542 | pr_debug("fb%d: offset register : %d\n", info->node, offset_value); | 560 | pr_debug("fb%d: offset register : %d\n", info->node, offset_value); |
543 | svga_wcrt_multi(s3_offset_regs, offset_value); | 561 | svga_wcrt_multi(par->state.vgabase, s3_offset_regs, offset_value); |
544 | 562 | ||
545 | if (par->chip != CHIP_360_TRIO3D_1X && | 563 | if (par->chip != CHIP_360_TRIO3D_1X && |
546 | par->chip != CHIP_362_TRIO3D_2X && | 564 | par->chip != CHIP_362_TRIO3D_2X && |
547 | par->chip != CHIP_368_TRIO3D_2X) { | 565 | par->chip != CHIP_368_TRIO3D_2X) { |
548 | vga_wcrt(NULL, 0x54, 0x18); /* M parameter */ | 566 | vga_wcrt(par->state.vgabase, 0x54, 0x18); /* M parameter */ |
549 | vga_wcrt(NULL, 0x60, 0xff); /* N parameter */ | 567 | vga_wcrt(par->state.vgabase, 0x60, 0xff); /* N parameter */ |
550 | vga_wcrt(NULL, 0x61, 0xff); /* L parameter */ | 568 | vga_wcrt(par->state.vgabase, 0x61, 0xff); /* L parameter */ |
551 | vga_wcrt(NULL, 0x62, 0xff); /* L parameter */ | 569 | vga_wcrt(par->state.vgabase, 0x62, 0xff); /* L parameter */ |
552 | } | 570 | } |
553 | 571 | ||
554 | vga_wcrt(NULL, 0x3A, 0x35); | 572 | vga_wcrt(par->state.vgabase, 0x3A, 0x35); |
555 | svga_wattr(0x33, 0x00); | 573 | svga_wattr(par->state.vgabase, 0x33, 0x00); |
556 | 574 | ||
557 | if (info->var.vmode & FB_VMODE_DOUBLE) | 575 | if (info->var.vmode & FB_VMODE_DOUBLE) |
558 | svga_wcrt_mask(0x09, 0x80, 0x80); | 576 | svga_wcrt_mask(par->state.vgabase, 0x09, 0x80, 0x80); |
559 | else | 577 | else |
560 | svga_wcrt_mask(0x09, 0x00, 0x80); | 578 | svga_wcrt_mask(par->state.vgabase, 0x09, 0x00, 0x80); |
561 | 579 | ||
562 | if (info->var.vmode & FB_VMODE_INTERLACED) | 580 | if (info->var.vmode & FB_VMODE_INTERLACED) |
563 | svga_wcrt_mask(0x42, 0x20, 0x20); | 581 | svga_wcrt_mask(par->state.vgabase, 0x42, 0x20, 0x20); |
564 | else | 582 | else |
565 | svga_wcrt_mask(0x42, 0x00, 0x20); | 583 | svga_wcrt_mask(par->state.vgabase, 0x42, 0x00, 0x20); |
566 | 584 | ||
567 | /* Disable hardware graphics cursor */ | 585 | /* Disable hardware graphics cursor */ |
568 | svga_wcrt_mask(0x45, 0x00, 0x01); | 586 | svga_wcrt_mask(par->state.vgabase, 0x45, 0x00, 0x01); |
569 | /* Disable Streams engine */ | 587 | /* Disable Streams engine */ |
570 | svga_wcrt_mask(0x67, 0x00, 0x0C); | 588 | svga_wcrt_mask(par->state.vgabase, 0x67, 0x00, 0x0C); |
571 | 589 | ||
572 | mode = svga_match_format(s3fb_formats, &(info->var), &(info->fix)); | 590 | mode = svga_match_format(s3fb_formats, &(info->var), &(info->fix)); |
573 | 591 | ||
574 | /* S3 virge DX hack */ | 592 | /* S3 virge DX hack */ |
575 | if (par->chip == CHIP_375_VIRGE_DX) { | 593 | if (par->chip == CHIP_375_VIRGE_DX) { |
576 | vga_wcrt(NULL, 0x86, 0x80); | 594 | vga_wcrt(par->state.vgabase, 0x86, 0x80); |
577 | vga_wcrt(NULL, 0x90, 0x00); | 595 | vga_wcrt(par->state.vgabase, 0x90, 0x00); |
578 | } | 596 | } |
579 | 597 | ||
580 | /* S3 virge VX hack */ | 598 | /* S3 virge VX hack */ |
581 | if (par->chip == CHIP_988_VIRGE_VX) { | 599 | if (par->chip == CHIP_988_VIRGE_VX) { |
582 | vga_wcrt(NULL, 0x50, 0x00); | 600 | vga_wcrt(par->state.vgabase, 0x50, 0x00); |
583 | vga_wcrt(NULL, 0x67, 0x50); | 601 | vga_wcrt(par->state.vgabase, 0x67, 0x50); |
584 | 602 | ||
585 | vga_wcrt(NULL, 0x63, (mode <= 2) ? 0x90 : 0x09); | 603 | vga_wcrt(par->state.vgabase, 0x63, (mode <= 2) ? 0x90 : 0x09); |
586 | vga_wcrt(NULL, 0x66, 0x90); | 604 | vga_wcrt(par->state.vgabase, 0x66, 0x90); |
587 | } | 605 | } |
588 | 606 | ||
589 | if (par->chip == CHIP_360_TRIO3D_1X || | 607 | if (par->chip == CHIP_360_TRIO3D_1X || |
590 | par->chip == CHIP_362_TRIO3D_2X || | 608 | par->chip == CHIP_362_TRIO3D_2X || |
591 | par->chip == CHIP_368_TRIO3D_2X) { | 609 | par->chip == CHIP_368_TRIO3D_2X || |
610 | par->chip == CHIP_365_TRIO3D || | ||
611 | par->chip == CHIP_375_VIRGE_DX || | ||
612 | par->chip == CHIP_385_VIRGE_GX) { | ||
592 | dbytes = info->var.xres * ((bpp+7)/8); | 613 | dbytes = info->var.xres * ((bpp+7)/8); |
593 | vga_wcrt(NULL, 0x91, (dbytes + 7) / 8); | 614 | vga_wcrt(par->state.vgabase, 0x91, (dbytes + 7) / 8); |
594 | vga_wcrt(NULL, 0x90, (((dbytes + 7) / 8) >> 8) | 0x80); | 615 | vga_wcrt(par->state.vgabase, 0x90, (((dbytes + 7) / 8) >> 8) | 0x80); |
595 | 616 | ||
596 | vga_wcrt(NULL, 0x66, 0x81); | 617 | vga_wcrt(par->state.vgabase, 0x66, 0x81); |
597 | } | 618 | } |
598 | 619 | ||
599 | svga_wcrt_mask(0x31, 0x00, 0x40); | 620 | if (par->chip == CHIP_356_VIRGE_GX2 || |
621 | par->chip == CHIP_357_VIRGE_GX2P || | ||
622 | par->chip == CHIP_359_VIRGE_GX2P || | ||
623 | par->chip == CHIP_360_TRIO3D_1X || | ||
624 | par->chip == CHIP_362_TRIO3D_2X || | ||
625 | par->chip == CHIP_368_TRIO3D_2X) | ||
626 | vga_wcrt(par->state.vgabase, 0x34, 0x00); | ||
627 | else /* enable Data Transfer Position Control (DTPC) */ | ||
628 | vga_wcrt(par->state.vgabase, 0x34, 0x10); | ||
629 | |||
630 | svga_wcrt_mask(par->state.vgabase, 0x31, 0x00, 0x40); | ||
600 | multiplex = 0; | 631 | multiplex = 0; |
601 | hmul = 1; | 632 | hmul = 1; |
602 | 633 | ||
@@ -604,51 +635,51 @@ static int s3fb_set_par(struct fb_info *info) | |||
604 | switch (mode) { | 635 | switch (mode) { |
605 | case 0: | 636 | case 0: |
606 | pr_debug("fb%d: text mode\n", info->node); | 637 | pr_debug("fb%d: text mode\n", info->node); |
607 | svga_set_textmode_vga_regs(); | 638 | svga_set_textmode_vga_regs(par->state.vgabase); |
608 | 639 | ||
609 | /* Set additional registers like in 8-bit mode */ | 640 | /* Set additional registers like in 8-bit mode */ |
610 | svga_wcrt_mask(0x50, 0x00, 0x30); | 641 | svga_wcrt_mask(par->state.vgabase, 0x50, 0x00, 0x30); |
611 | svga_wcrt_mask(0x67, 0x00, 0xF0); | 642 | svga_wcrt_mask(par->state.vgabase, 0x67, 0x00, 0xF0); |
612 | 643 | ||
613 | /* Disable enhanced mode */ | 644 | /* Disable enhanced mode */ |
614 | svga_wcrt_mask(0x3A, 0x00, 0x30); | 645 | svga_wcrt_mask(par->state.vgabase, 0x3A, 0x00, 0x30); |
615 | 646 | ||
616 | if (fasttext) { | 647 | if (fasttext) { |
617 | pr_debug("fb%d: high speed text mode set\n", info->node); | 648 | pr_debug("fb%d: high speed text mode set\n", info->node); |
618 | svga_wcrt_mask(0x31, 0x40, 0x40); | 649 | svga_wcrt_mask(par->state.vgabase, 0x31, 0x40, 0x40); |
619 | } | 650 | } |
620 | break; | 651 | break; |
621 | case 1: | 652 | case 1: |
622 | pr_debug("fb%d: 4 bit pseudocolor\n", info->node); | 653 | pr_debug("fb%d: 4 bit pseudocolor\n", info->node); |
623 | vga_wgfx(NULL, VGA_GFX_MODE, 0x40); | 654 | vga_wgfx(par->state.vgabase, VGA_GFX_MODE, 0x40); |
624 | 655 | ||
625 | /* Set additional registers like in 8-bit mode */ | 656 | /* Set additional registers like in 8-bit mode */ |
626 | svga_wcrt_mask(0x50, 0x00, 0x30); | 657 | svga_wcrt_mask(par->state.vgabase, 0x50, 0x00, 0x30); |
627 | svga_wcrt_mask(0x67, 0x00, 0xF0); | 658 | svga_wcrt_mask(par->state.vgabase, 0x67, 0x00, 0xF0); |
628 | 659 | ||
629 | /* disable enhanced mode */ | 660 | /* disable enhanced mode */ |
630 | svga_wcrt_mask(0x3A, 0x00, 0x30); | 661 | svga_wcrt_mask(par->state.vgabase, 0x3A, 0x00, 0x30); |
631 | break; | 662 | break; |
632 | case 2: | 663 | case 2: |
633 | pr_debug("fb%d: 4 bit pseudocolor, planar\n", info->node); | 664 | pr_debug("fb%d: 4 bit pseudocolor, planar\n", info->node); |
634 | 665 | ||
635 | /* Set additional registers like in 8-bit mode */ | 666 | /* Set additional registers like in 8-bit mode */ |
636 | svga_wcrt_mask(0x50, 0x00, 0x30); | 667 | svga_wcrt_mask(par->state.vgabase, 0x50, 0x00, 0x30); |
637 | svga_wcrt_mask(0x67, 0x00, 0xF0); | 668 | svga_wcrt_mask(par->state.vgabase, 0x67, 0x00, 0xF0); |
638 | 669 | ||
639 | /* disable enhanced mode */ | 670 | /* disable enhanced mode */ |
640 | svga_wcrt_mask(0x3A, 0x00, 0x30); | 671 | svga_wcrt_mask(par->state.vgabase, 0x3A, 0x00, 0x30); |
641 | break; | 672 | break; |
642 | case 3: | 673 | case 3: |
643 | pr_debug("fb%d: 8 bit pseudocolor\n", info->node); | 674 | pr_debug("fb%d: 8 bit pseudocolor\n", info->node); |
644 | svga_wcrt_mask(0x50, 0x00, 0x30); | 675 | svga_wcrt_mask(par->state.vgabase, 0x50, 0x00, 0x30); |
645 | if (info->var.pixclock > 20000 || | 676 | if (info->var.pixclock > 20000 || |
646 | par->chip == CHIP_360_TRIO3D_1X || | 677 | par->chip == CHIP_360_TRIO3D_1X || |
647 | par->chip == CHIP_362_TRIO3D_2X || | 678 | par->chip == CHIP_362_TRIO3D_2X || |
648 | par->chip == CHIP_368_TRIO3D_2X) | 679 | par->chip == CHIP_368_TRIO3D_2X) |
649 | svga_wcrt_mask(0x67, 0x00, 0xF0); | 680 | svga_wcrt_mask(par->state.vgabase, 0x67, 0x00, 0xF0); |
650 | else { | 681 | else { |
651 | svga_wcrt_mask(0x67, 0x10, 0xF0); | 682 | svga_wcrt_mask(par->state.vgabase, 0x67, 0x10, 0xF0); |
652 | multiplex = 1; | 683 | multiplex = 1; |
653 | } | 684 | } |
654 | break; | 685 | break; |
@@ -656,12 +687,21 @@ static int s3fb_set_par(struct fb_info *info) | |||
656 | pr_debug("fb%d: 5/5/5 truecolor\n", info->node); | 687 | pr_debug("fb%d: 5/5/5 truecolor\n", info->node); |
657 | if (par->chip == CHIP_988_VIRGE_VX) { | 688 | if (par->chip == CHIP_988_VIRGE_VX) { |
658 | if (info->var.pixclock > 20000) | 689 | if (info->var.pixclock > 20000) |
659 | svga_wcrt_mask(0x67, 0x20, 0xF0); | 690 | svga_wcrt_mask(par->state.vgabase, 0x67, 0x20, 0xF0); |
660 | else | 691 | else |
661 | svga_wcrt_mask(0x67, 0x30, 0xF0); | 692 | svga_wcrt_mask(par->state.vgabase, 0x67, 0x30, 0xF0); |
693 | } else if (par->chip == CHIP_365_TRIO3D) { | ||
694 | svga_wcrt_mask(par->state.vgabase, 0x50, 0x10, 0x30); | ||
695 | if (info->var.pixclock > 8695) { | ||
696 | svga_wcrt_mask(par->state.vgabase, 0x67, 0x30, 0xF0); | ||
697 | hmul = 2; | ||
698 | } else { | ||
699 | svga_wcrt_mask(par->state.vgabase, 0x67, 0x20, 0xF0); | ||
700 | multiplex = 1; | ||
701 | } | ||
662 | } else { | 702 | } else { |
663 | svga_wcrt_mask(0x50, 0x10, 0x30); | 703 | svga_wcrt_mask(par->state.vgabase, 0x50, 0x10, 0x30); |
664 | svga_wcrt_mask(0x67, 0x30, 0xF0); | 704 | svga_wcrt_mask(par->state.vgabase, 0x67, 0x30, 0xF0); |
665 | if (par->chip != CHIP_360_TRIO3D_1X && | 705 | if (par->chip != CHIP_360_TRIO3D_1X && |
666 | par->chip != CHIP_362_TRIO3D_2X && | 706 | par->chip != CHIP_362_TRIO3D_2X && |
667 | par->chip != CHIP_368_TRIO3D_2X) | 707 | par->chip != CHIP_368_TRIO3D_2X) |
@@ -672,12 +712,21 @@ static int s3fb_set_par(struct fb_info *info) | |||
672 | pr_debug("fb%d: 5/6/5 truecolor\n", info->node); | 712 | pr_debug("fb%d: 5/6/5 truecolor\n", info->node); |
673 | if (par->chip == CHIP_988_VIRGE_VX) { | 713 | if (par->chip == CHIP_988_VIRGE_VX) { |
674 | if (info->var.pixclock > 20000) | 714 | if (info->var.pixclock > 20000) |
675 | svga_wcrt_mask(0x67, 0x40, 0xF0); | 715 | svga_wcrt_mask(par->state.vgabase, 0x67, 0x40, 0xF0); |
676 | else | 716 | else |
677 | svga_wcrt_mask(0x67, 0x50, 0xF0); | 717 | svga_wcrt_mask(par->state.vgabase, 0x67, 0x50, 0xF0); |
718 | } else if (par->chip == CHIP_365_TRIO3D) { | ||
719 | svga_wcrt_mask(par->state.vgabase, 0x50, 0x10, 0x30); | ||
720 | if (info->var.pixclock > 8695) { | ||
721 | svga_wcrt_mask(par->state.vgabase, 0x67, 0x50, 0xF0); | ||
722 | hmul = 2; | ||
723 | } else { | ||
724 | svga_wcrt_mask(par->state.vgabase, 0x67, 0x40, 0xF0); | ||
725 | multiplex = 1; | ||
726 | } | ||
678 | } else { | 727 | } else { |
679 | svga_wcrt_mask(0x50, 0x10, 0x30); | 728 | svga_wcrt_mask(par->state.vgabase, 0x50, 0x10, 0x30); |
680 | svga_wcrt_mask(0x67, 0x50, 0xF0); | 729 | svga_wcrt_mask(par->state.vgabase, 0x67, 0x50, 0xF0); |
681 | if (par->chip != CHIP_360_TRIO3D_1X && | 730 | if (par->chip != CHIP_360_TRIO3D_1X && |
682 | par->chip != CHIP_362_TRIO3D_2X && | 731 | par->chip != CHIP_362_TRIO3D_2X && |
683 | par->chip != CHIP_368_TRIO3D_2X) | 732 | par->chip != CHIP_368_TRIO3D_2X) |
@@ -687,12 +736,12 @@ static int s3fb_set_par(struct fb_info *info) | |||
687 | case 6: | 736 | case 6: |
688 | /* VIRGE VX case */ | 737 | /* VIRGE VX case */ |
689 | pr_debug("fb%d: 8/8/8 truecolor\n", info->node); | 738 | pr_debug("fb%d: 8/8/8 truecolor\n", info->node); |
690 | svga_wcrt_mask(0x67, 0xD0, 0xF0); | 739 | svga_wcrt_mask(par->state.vgabase, 0x67, 0xD0, 0xF0); |
691 | break; | 740 | break; |
692 | case 7: | 741 | case 7: |
693 | pr_debug("fb%d: 8/8/8/8 truecolor\n", info->node); | 742 | pr_debug("fb%d: 8/8/8/8 truecolor\n", info->node); |
694 | svga_wcrt_mask(0x50, 0x30, 0x30); | 743 | svga_wcrt_mask(par->state.vgabase, 0x50, 0x30, 0x30); |
695 | svga_wcrt_mask(0x67, 0xD0, 0xF0); | 744 | svga_wcrt_mask(par->state.vgabase, 0x67, 0xD0, 0xF0); |
696 | break; | 745 | break; |
697 | default: | 746 | default: |
698 | printk(KERN_ERR "fb%d: unsupported mode - bug\n", info->node); | 747 | printk(KERN_ERR "fb%d: unsupported mode - bug\n", info->node); |
@@ -700,25 +749,30 @@ static int s3fb_set_par(struct fb_info *info) | |||
700 | } | 749 | } |
701 | 750 | ||
702 | if (par->chip != CHIP_988_VIRGE_VX) { | 751 | if (par->chip != CHIP_988_VIRGE_VX) { |
703 | svga_wseq_mask(0x15, multiplex ? 0x10 : 0x00, 0x10); | 752 | svga_wseq_mask(par->state.vgabase, 0x15, multiplex ? 0x10 : 0x00, 0x10); |
704 | svga_wseq_mask(0x18, multiplex ? 0x80 : 0x00, 0x80); | 753 | svga_wseq_mask(par->state.vgabase, 0x18, multiplex ? 0x80 : 0x00, 0x80); |
705 | } | 754 | } |
706 | 755 | ||
707 | s3_set_pixclock(info, info->var.pixclock); | 756 | s3_set_pixclock(info, info->var.pixclock); |
708 | svga_set_timings(&s3_timing_regs, &(info->var), hmul, 1, | 757 | svga_set_timings(par->state.vgabase, &s3_timing_regs, &(info->var), hmul, 1, |
709 | (info->var.vmode & FB_VMODE_DOUBLE) ? 2 : 1, | 758 | (info->var.vmode & FB_VMODE_DOUBLE) ? 2 : 1, |
710 | (info->var.vmode & FB_VMODE_INTERLACED) ? 2 : 1, | 759 | (info->var.vmode & FB_VMODE_INTERLACED) ? 2 : 1, |
711 | hmul, info->node); | 760 | hmul, info->node); |
712 | 761 | ||
713 | /* Set interlaced mode start/end register */ | 762 | /* Set interlaced mode start/end register */ |
714 | value = info->var.xres + info->var.left_margin + info->var.right_margin + info->var.hsync_len; | 763 | htotal = info->var.xres + info->var.left_margin + info->var.right_margin + info->var.hsync_len; |
715 | value = ((value * hmul) / 8) - 5; | 764 | htotal = ((htotal * hmul) / 8) - 5; |
716 | vga_wcrt(NULL, 0x3C, (value + 1) / 2); | 765 | vga_wcrt(par->state.vgabase, 0x3C, (htotal + 1) / 2); |
766 | |||
767 | /* Set Data Transfer Position */ | ||
768 | hsstart = ((info->var.xres + info->var.right_margin) * hmul) / 8; | ||
769 | value = clamp((htotal + hsstart + 1) / 2, hsstart + 4, htotal + 1); | ||
770 | svga_wcrt_multi(par->state.vgabase, s3_dtpc_regs, value); | ||
717 | 771 | ||
718 | memset_io(info->screen_base, 0x00, screen_size); | 772 | memset_io(info->screen_base, 0x00, screen_size); |
719 | /* Device and screen back on */ | 773 | /* Device and screen back on */ |
720 | svga_wcrt_mask(0x17, 0x80, 0x80); | 774 | svga_wcrt_mask(par->state.vgabase, 0x17, 0x80, 0x80); |
721 | svga_wseq_mask(0x01, 0x00, 0x20); | 775 | svga_wseq_mask(par->state.vgabase, 0x01, 0x00, 0x20); |
722 | 776 | ||
723 | return 0; | 777 | return 0; |
724 | } | 778 | } |
@@ -788,31 +842,33 @@ static int s3fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, | |||
788 | 842 | ||
789 | static int s3fb_blank(int blank_mode, struct fb_info *info) | 843 | static int s3fb_blank(int blank_mode, struct fb_info *info) |
790 | { | 844 | { |
845 | struct s3fb_info *par = info->par; | ||
846 | |||
791 | switch (blank_mode) { | 847 | switch (blank_mode) { |
792 | case FB_BLANK_UNBLANK: | 848 | case FB_BLANK_UNBLANK: |
793 | pr_debug("fb%d: unblank\n", info->node); | 849 | pr_debug("fb%d: unblank\n", info->node); |
794 | svga_wcrt_mask(0x56, 0x00, 0x06); | 850 | svga_wcrt_mask(par->state.vgabase, 0x56, 0x00, 0x06); |
795 | svga_wseq_mask(0x01, 0x00, 0x20); | 851 | svga_wseq_mask(par->state.vgabase, 0x01, 0x00, 0x20); |
796 | break; | 852 | break; |
797 | case FB_BLANK_NORMAL: | 853 | case FB_BLANK_NORMAL: |
798 | pr_debug("fb%d: blank\n", info->node); | 854 | pr_debug("fb%d: blank\n", info->node); |
799 | svga_wcrt_mask(0x56, 0x00, 0x06); | 855 | svga_wcrt_mask(par->state.vgabase, 0x56, 0x00, 0x06); |
800 | svga_wseq_mask(0x01, 0x20, 0x20); | 856 | svga_wseq_mask(par->state.vgabase, 0x01, 0x20, 0x20); |
801 | break; | 857 | break; |
802 | case FB_BLANK_HSYNC_SUSPEND: | 858 | case FB_BLANK_HSYNC_SUSPEND: |
803 | pr_debug("fb%d: hsync\n", info->node); | 859 | pr_debug("fb%d: hsync\n", info->node); |
804 | svga_wcrt_mask(0x56, 0x02, 0x06); | 860 | svga_wcrt_mask(par->state.vgabase, 0x56, 0x02, 0x06); |
805 | svga_wseq_mask(0x01, 0x20, 0x20); | 861 | svga_wseq_mask(par->state.vgabase, 0x01, 0x20, 0x20); |
806 | break; | 862 | break; |
807 | case FB_BLANK_VSYNC_SUSPEND: | 863 | case FB_BLANK_VSYNC_SUSPEND: |
808 | pr_debug("fb%d: vsync\n", info->node); | 864 | pr_debug("fb%d: vsync\n", info->node); |
809 | svga_wcrt_mask(0x56, 0x04, 0x06); | 865 | svga_wcrt_mask(par->state.vgabase, 0x56, 0x04, 0x06); |
810 | svga_wseq_mask(0x01, 0x20, 0x20); | 866 | svga_wseq_mask(par->state.vgabase, 0x01, 0x20, 0x20); |
811 | break; | 867 | break; |
812 | case FB_BLANK_POWERDOWN: | 868 | case FB_BLANK_POWERDOWN: |
813 | pr_debug("fb%d: sync down\n", info->node); | 869 | pr_debug("fb%d: sync down\n", info->node); |
814 | svga_wcrt_mask(0x56, 0x06, 0x06); | 870 | svga_wcrt_mask(par->state.vgabase, 0x56, 0x06, 0x06); |
815 | svga_wseq_mask(0x01, 0x20, 0x20); | 871 | svga_wseq_mask(par->state.vgabase, 0x01, 0x20, 0x20); |
816 | break; | 872 | break; |
817 | } | 873 | } |
818 | 874 | ||
@@ -822,8 +878,9 @@ static int s3fb_blank(int blank_mode, struct fb_info *info) | |||
822 | 878 | ||
823 | /* Pan the display */ | 879 | /* Pan the display */ |
824 | 880 | ||
825 | static int s3fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) { | 881 | static int s3fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) |
826 | 882 | { | |
883 | struct s3fb_info *par = info->par; | ||
827 | unsigned int offset; | 884 | unsigned int offset; |
828 | 885 | ||
829 | /* Calculate the offset */ | 886 | /* Calculate the offset */ |
@@ -837,7 +894,7 @@ static int s3fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) | |||
837 | } | 894 | } |
838 | 895 | ||
839 | /* Set the offset */ | 896 | /* Set the offset */ |
840 | svga_wcrt_multi(s3_start_address_regs, offset); | 897 | svga_wcrt_multi(par->state.vgabase, s3_start_address_regs, offset); |
841 | 898 | ||
842 | return 0; | 899 | return 0; |
843 | } | 900 | } |
@@ -863,12 +920,14 @@ static struct fb_ops s3fb_ops = { | |||
863 | 920 | ||
864 | /* ------------------------------------------------------------------------- */ | 921 | /* ------------------------------------------------------------------------- */ |
865 | 922 | ||
866 | static int __devinit s3_identification(int chip) | 923 | static int __devinit s3_identification(struct s3fb_info *par) |
867 | { | 924 | { |
925 | int chip = par->chip; | ||
926 | |||
868 | if (chip == CHIP_XXX_TRIO) { | 927 | if (chip == CHIP_XXX_TRIO) { |
869 | u8 cr30 = vga_rcrt(NULL, 0x30); | 928 | u8 cr30 = vga_rcrt(par->state.vgabase, 0x30); |
870 | u8 cr2e = vga_rcrt(NULL, 0x2e); | 929 | u8 cr2e = vga_rcrt(par->state.vgabase, 0x2e); |
871 | u8 cr2f = vga_rcrt(NULL, 0x2f); | 930 | u8 cr2f = vga_rcrt(par->state.vgabase, 0x2f); |
872 | 931 | ||
873 | if ((cr30 == 0xE0) || (cr30 == 0xE1)) { | 932 | if ((cr30 == 0xE0) || (cr30 == 0xE1)) { |
874 | if (cr2e == 0x10) | 933 | if (cr2e == 0x10) |
@@ -883,7 +942,7 @@ static int __devinit s3_identification(int chip) | |||
883 | } | 942 | } |
884 | 943 | ||
885 | if (chip == CHIP_XXX_TRIO64V2_DXGX) { | 944 | if (chip == CHIP_XXX_TRIO64V2_DXGX) { |
886 | u8 cr6f = vga_rcrt(NULL, 0x6f); | 945 | u8 cr6f = vga_rcrt(par->state.vgabase, 0x6f); |
887 | 946 | ||
888 | if (! (cr6f & 0x01)) | 947 | if (! (cr6f & 0x01)) |
889 | return CHIP_775_TRIO64V2_DX; | 948 | return CHIP_775_TRIO64V2_DX; |
@@ -892,7 +951,7 @@ static int __devinit s3_identification(int chip) | |||
892 | } | 951 | } |
893 | 952 | ||
894 | if (chip == CHIP_XXX_VIRGE_DXGX) { | 953 | if (chip == CHIP_XXX_VIRGE_DXGX) { |
895 | u8 cr6f = vga_rcrt(NULL, 0x6f); | 954 | u8 cr6f = vga_rcrt(par->state.vgabase, 0x6f); |
896 | 955 | ||
897 | if (! (cr6f & 0x01)) | 956 | if (! (cr6f & 0x01)) |
898 | return CHIP_375_VIRGE_DX; | 957 | return CHIP_375_VIRGE_DX; |
@@ -901,7 +960,7 @@ static int __devinit s3_identification(int chip) | |||
901 | } | 960 | } |
902 | 961 | ||
903 | if (chip == CHIP_36X_TRIO3D_1X_2X) { | 962 | if (chip == CHIP_36X_TRIO3D_1X_2X) { |
904 | switch (vga_rcrt(NULL, 0x2f)) { | 963 | switch (vga_rcrt(par->state.vgabase, 0x2f)) { |
905 | case 0x00: | 964 | case 0x00: |
906 | return CHIP_360_TRIO3D_1X; | 965 | return CHIP_360_TRIO3D_1X; |
907 | case 0x01: | 966 | case 0x01: |
@@ -919,6 +978,8 @@ static int __devinit s3_identification(int chip) | |||
919 | 978 | ||
920 | static int __devinit s3_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) | 979 | static int __devinit s3_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) |
921 | { | 980 | { |
981 | struct pci_bus_region bus_reg; | ||
982 | struct resource vga_res; | ||
922 | struct fb_info *info; | 983 | struct fb_info *info; |
923 | struct s3fb_info *par; | 984 | struct s3fb_info *par; |
924 | int rc; | 985 | int rc; |
@@ -968,31 +1029,42 @@ static int __devinit s3_pci_probe(struct pci_dev *dev, const struct pci_device_i | |||
968 | goto err_iomap; | 1029 | goto err_iomap; |
969 | } | 1030 | } |
970 | 1031 | ||
1032 | bus_reg.start = 0; | ||
1033 | bus_reg.end = 64 * 1024; | ||
1034 | |||
1035 | vga_res.flags = IORESOURCE_IO; | ||
1036 | |||
1037 | pcibios_bus_to_resource(dev, &vga_res, &bus_reg); | ||
1038 | |||
1039 | par->state.vgabase = (void __iomem *) vga_res.start; | ||
1040 | |||
971 | /* Unlock regs */ | 1041 | /* Unlock regs */ |
972 | cr38 = vga_rcrt(NULL, 0x38); | 1042 | cr38 = vga_rcrt(par->state.vgabase, 0x38); |
973 | cr39 = vga_rcrt(NULL, 0x39); | 1043 | cr39 = vga_rcrt(par->state.vgabase, 0x39); |
974 | vga_wseq(NULL, 0x08, 0x06); | 1044 | vga_wseq(par->state.vgabase, 0x08, 0x06); |
975 | vga_wcrt(NULL, 0x38, 0x48); | 1045 | vga_wcrt(par->state.vgabase, 0x38, 0x48); |
976 | vga_wcrt(NULL, 0x39, 0xA5); | 1046 | vga_wcrt(par->state.vgabase, 0x39, 0xA5); |
977 | 1047 | ||
978 | /* Identify chip type */ | 1048 | /* Identify chip type */ |
979 | par->chip = id->driver_data & CHIP_MASK; | 1049 | par->chip = id->driver_data & CHIP_MASK; |
980 | par->rev = vga_rcrt(NULL, 0x2f); | 1050 | par->rev = vga_rcrt(par->state.vgabase, 0x2f); |
981 | if (par->chip & CHIP_UNDECIDED_FLAG) | 1051 | if (par->chip & CHIP_UNDECIDED_FLAG) |
982 | par->chip = s3_identification(par->chip); | 1052 | par->chip = s3_identification(par); |
983 | 1053 | ||
984 | /* Find how many physical memory there is on card */ | 1054 | /* Find how many physical memory there is on card */ |
985 | /* 0x36 register is accessible even if other registers are locked */ | 1055 | /* 0x36 register is accessible even if other registers are locked */ |
986 | regval = vga_rcrt(NULL, 0x36); | 1056 | regval = vga_rcrt(par->state.vgabase, 0x36); |
987 | if (par->chip == CHIP_360_TRIO3D_1X || | 1057 | if (par->chip == CHIP_360_TRIO3D_1X || |
988 | par->chip == CHIP_362_TRIO3D_2X || | 1058 | par->chip == CHIP_362_TRIO3D_2X || |
989 | par->chip == CHIP_368_TRIO3D_2X) { | 1059 | par->chip == CHIP_368_TRIO3D_2X || |
1060 | par->chip == CHIP_365_TRIO3D) { | ||
990 | switch ((regval & 0xE0) >> 5) { | 1061 | switch ((regval & 0xE0) >> 5) { |
991 | case 0: /* 8MB -- only 4MB usable for display */ | 1062 | case 0: /* 8MB -- only 4MB usable for display */ |
992 | case 1: /* 4MB with 32-bit bus */ | 1063 | case 1: /* 4MB with 32-bit bus */ |
993 | case 2: /* 4MB */ | 1064 | case 2: /* 4MB */ |
994 | info->screen_size = 4 << 20; | 1065 | info->screen_size = 4 << 20; |
995 | break; | 1066 | break; |
1067 | case 4: /* 2MB on 365 Trio3D */ | ||
996 | case 6: /* 2MB */ | 1068 | case 6: /* 2MB */ |
997 | info->screen_size = 2 << 20; | 1069 | info->screen_size = 2 << 20; |
998 | break; | 1070 | break; |
@@ -1002,13 +1074,13 @@ static int __devinit s3_pci_probe(struct pci_dev *dev, const struct pci_device_i | |||
1002 | info->fix.smem_len = info->screen_size; | 1074 | info->fix.smem_len = info->screen_size; |
1003 | 1075 | ||
1004 | /* Find MCLK frequency */ | 1076 | /* Find MCLK frequency */ |
1005 | regval = vga_rseq(NULL, 0x10); | 1077 | regval = vga_rseq(par->state.vgabase, 0x10); |
1006 | par->mclk_freq = ((vga_rseq(NULL, 0x11) + 2) * 14318) / ((regval & 0x1F) + 2); | 1078 | par->mclk_freq = ((vga_rseq(par->state.vgabase, 0x11) + 2) * 14318) / ((regval & 0x1F) + 2); |
1007 | par->mclk_freq = par->mclk_freq >> (regval >> 5); | 1079 | par->mclk_freq = par->mclk_freq >> (regval >> 5); |
1008 | 1080 | ||
1009 | /* Restore locks */ | 1081 | /* Restore locks */ |
1010 | vga_wcrt(NULL, 0x38, cr38); | 1082 | vga_wcrt(par->state.vgabase, 0x38, cr38); |
1011 | vga_wcrt(NULL, 0x39, cr39); | 1083 | vga_wcrt(par->state.vgabase, 0x39, cr39); |
1012 | 1084 | ||
1013 | strcpy(info->fix.id, s3_names [par->chip]); | 1085 | strcpy(info->fix.id, s3_names [par->chip]); |
1014 | info->fix.mmio_start = 0; | 1086 | info->fix.mmio_start = 0; |
@@ -1027,6 +1099,14 @@ static int __devinit s3_pci_probe(struct pci_dev *dev, const struct pci_device_i | |||
1027 | goto err_find_mode; | 1099 | goto err_find_mode; |
1028 | } | 1100 | } |
1029 | 1101 | ||
1102 | /* maximize virtual vertical size for fast scrolling */ | ||
1103 | info->var.yres_virtual = info->fix.smem_len * 8 / | ||
1104 | (info->var.bits_per_pixel * info->var.xres_virtual); | ||
1105 | if (info->var.yres_virtual < info->var.yres) { | ||
1106 | dev_err(info->device, "virtual vertical size smaller than real\n"); | ||
1107 | goto err_find_mode; | ||
1108 | } | ||
1109 | |||
1030 | rc = fb_alloc_cmap(&info->cmap, 256, 0); | 1110 | rc = fb_alloc_cmap(&info->cmap, 256, 0); |
1031 | if (rc < 0) { | 1111 | if (rc < 0) { |
1032 | dev_err(info->device, "cannot allocate colormap\n"); | 1112 | dev_err(info->device, "cannot allocate colormap\n"); |
@@ -1044,8 +1124,8 @@ static int __devinit s3_pci_probe(struct pci_dev *dev, const struct pci_device_i | |||
1044 | 1124 | ||
1045 | if (par->chip == CHIP_UNKNOWN) | 1125 | if (par->chip == CHIP_UNKNOWN) |
1046 | printk(KERN_INFO "fb%d: unknown chip, CR2D=%x, CR2E=%x, CRT2F=%x, CRT30=%x\n", | 1126 | printk(KERN_INFO "fb%d: unknown chip, CR2D=%x, CR2E=%x, CRT2F=%x, CRT30=%x\n", |
1047 | info->node, vga_rcrt(NULL, 0x2d), vga_rcrt(NULL, 0x2e), | 1127 | info->node, vga_rcrt(par->state.vgabase, 0x2d), vga_rcrt(par->state.vgabase, 0x2e), |
1048 | vga_rcrt(NULL, 0x2f), vga_rcrt(NULL, 0x30)); | 1128 | vga_rcrt(par->state.vgabase, 0x2f), vga_rcrt(par->state.vgabase, 0x30)); |
1049 | 1129 | ||
1050 | /* Record a reference to the driver data */ | 1130 | /* Record a reference to the driver data */ |
1051 | pci_set_drvdata(dev, info); | 1131 | pci_set_drvdata(dev, info); |
@@ -1192,6 +1272,7 @@ static struct pci_device_id s3_devices[] __devinitdata = { | |||
1192 | {PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A11), .driver_data = CHIP_357_VIRGE_GX2P}, | 1272 | {PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A11), .driver_data = CHIP_357_VIRGE_GX2P}, |
1193 | {PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A12), .driver_data = CHIP_359_VIRGE_GX2P}, | 1273 | {PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A12), .driver_data = CHIP_359_VIRGE_GX2P}, |
1194 | {PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A13), .driver_data = CHIP_36X_TRIO3D_1X_2X}, | 1274 | {PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A13), .driver_data = CHIP_36X_TRIO3D_1X_2X}, |
1275 | {PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8904), .driver_data = CHIP_365_TRIO3D}, | ||
1195 | 1276 | ||
1196 | {0, 0, 0, 0, 0, 0, 0} | 1277 | {0, 0, 0, 0, 0, 0, 0} |
1197 | }; | 1278 | }; |