diff options
Diffstat (limited to 'drivers/video/vt8623fb.c')
-rw-r--r-- | drivers/video/vt8623fb.c | 157 |
1 files changed, 91 insertions, 66 deletions
diff --git a/drivers/video/vt8623fb.c b/drivers/video/vt8623fb.c index a2965ab92cfb..f9b3e3dc2421 100644 --- a/drivers/video/vt8623fb.c +++ b/drivers/video/vt8623fb.c | |||
@@ -121,13 +121,19 @@ MODULE_PARM_DESC(mtrr, "Enable write-combining with MTRR (1=enable, 0=disable, d | |||
121 | 121 | ||
122 | /* ------------------------------------------------------------------------- */ | 122 | /* ------------------------------------------------------------------------- */ |
123 | 123 | ||
124 | static void vt8623fb_tilecursor(struct fb_info *info, struct fb_tilecursor *cursor) | ||
125 | { | ||
126 | struct vt8623fb_info *par = info->par; | ||
127 | |||
128 | svga_tilecursor(par->state.vgabase, info, cursor); | ||
129 | } | ||
124 | 130 | ||
125 | static struct fb_tile_ops vt8623fb_tile_ops = { | 131 | static struct fb_tile_ops vt8623fb_tile_ops = { |
126 | .fb_settile = svga_settile, | 132 | .fb_settile = svga_settile, |
127 | .fb_tilecopy = svga_tilecopy, | 133 | .fb_tilecopy = svga_tilecopy, |
128 | .fb_tilefill = svga_tilefill, | 134 | .fb_tilefill = svga_tilefill, |
129 | .fb_tileblit = svga_tileblit, | 135 | .fb_tileblit = svga_tileblit, |
130 | .fb_tilecursor = svga_tilecursor, | 136 | .fb_tilecursor = vt8623fb_tilecursor, |
131 | .fb_get_tilemax = svga_get_tilemax, | 137 | .fb_get_tilemax = svga_get_tilemax, |
132 | }; | 138 | }; |
133 | 139 | ||
@@ -253,6 +259,7 @@ static void vt8623fb_fillrect(struct fb_info *info, const struct fb_fillrect *re | |||
253 | 259 | ||
254 | static void vt8623_set_pixclock(struct fb_info *info, u32 pixclock) | 260 | static void vt8623_set_pixclock(struct fb_info *info, u32 pixclock) |
255 | { | 261 | { |
262 | struct vt8623fb_info *par = info->par; | ||
256 | u16 m, n, r; | 263 | u16 m, n, r; |
257 | u8 regval; | 264 | u8 regval; |
258 | int rv; | 265 | int rv; |
@@ -264,18 +271,18 @@ static void vt8623_set_pixclock(struct fb_info *info, u32 pixclock) | |||
264 | } | 271 | } |
265 | 272 | ||
266 | /* Set VGA misc register */ | 273 | /* Set VGA misc register */ |
267 | regval = vga_r(NULL, VGA_MIS_R); | 274 | regval = vga_r(par->state.vgabase, VGA_MIS_R); |
268 | vga_w(NULL, VGA_MIS_W, regval | VGA_MIS_ENB_PLL_LOAD); | 275 | vga_w(par->state.vgabase, VGA_MIS_W, regval | VGA_MIS_ENB_PLL_LOAD); |
269 | 276 | ||
270 | /* Set clock registers */ | 277 | /* Set clock registers */ |
271 | vga_wseq(NULL, 0x46, (n | (r << 6))); | 278 | vga_wseq(par->state.vgabase, 0x46, (n | (r << 6))); |
272 | vga_wseq(NULL, 0x47, m); | 279 | vga_wseq(par->state.vgabase, 0x47, m); |
273 | 280 | ||
274 | udelay(1000); | 281 | udelay(1000); |
275 | 282 | ||
276 | /* PLL reset */ | 283 | /* PLL reset */ |
277 | svga_wseq_mask(0x40, 0x02, 0x02); | 284 | svga_wseq_mask(par->state.vgabase, 0x40, 0x02, 0x02); |
278 | svga_wseq_mask(0x40, 0x00, 0x02); | 285 | svga_wseq_mask(par->state.vgabase, 0x40, 0x00, 0x02); |
279 | } | 286 | } |
280 | 287 | ||
281 | 288 | ||
@@ -285,7 +292,10 @@ static int vt8623fb_open(struct fb_info *info, int user) | |||
285 | 292 | ||
286 | mutex_lock(&(par->open_lock)); | 293 | mutex_lock(&(par->open_lock)); |
287 | if (par->ref_count == 0) { | 294 | if (par->ref_count == 0) { |
295 | void __iomem *vgabase = par->state.vgabase; | ||
296 | |||
288 | memset(&(par->state), 0, sizeof(struct vgastate)); | 297 | memset(&(par->state), 0, sizeof(struct vgastate)); |
298 | par->state.vgabase = vgabase; | ||
289 | par->state.flags = VGA_SAVE_MODE | VGA_SAVE_FONTS | VGA_SAVE_CMAP; | 299 | par->state.flags = VGA_SAVE_MODE | VGA_SAVE_FONTS | VGA_SAVE_CMAP; |
290 | par->state.num_crtc = 0xA2; | 300 | par->state.num_crtc = 0xA2; |
291 | par->state.num_seq = 0x50; | 301 | par->state.num_seq = 0x50; |
@@ -373,6 +383,7 @@ static int vt8623fb_check_var(struct fb_var_screeninfo *var, struct fb_info *inf | |||
373 | static int vt8623fb_set_par(struct fb_info *info) | 383 | static int vt8623fb_set_par(struct fb_info *info) |
374 | { | 384 | { |
375 | u32 mode, offset_value, fetch_value, screen_size; | 385 | u32 mode, offset_value, fetch_value, screen_size; |
386 | struct vt8623fb_info *par = info->par; | ||
376 | u32 bpp = info->var.bits_per_pixel; | 387 | u32 bpp = info->var.bits_per_pixel; |
377 | 388 | ||
378 | if (bpp != 0) { | 389 | if (bpp != 0) { |
@@ -414,82 +425,82 @@ static int vt8623fb_set_par(struct fb_info *info) | |||
414 | info->var.activate = FB_ACTIVATE_NOW; | 425 | info->var.activate = FB_ACTIVATE_NOW; |
415 | 426 | ||
416 | /* Unlock registers */ | 427 | /* Unlock registers */ |
417 | svga_wseq_mask(0x10, 0x01, 0x01); | 428 | svga_wseq_mask(par->state.vgabase, 0x10, 0x01, 0x01); |
418 | svga_wcrt_mask(0x11, 0x00, 0x80); | 429 | svga_wcrt_mask(par->state.vgabase, 0x11, 0x00, 0x80); |
419 | svga_wcrt_mask(0x47, 0x00, 0x01); | 430 | svga_wcrt_mask(par->state.vgabase, 0x47, 0x00, 0x01); |
420 | 431 | ||
421 | /* Device, screen and sync off */ | 432 | /* Device, screen and sync off */ |
422 | svga_wseq_mask(0x01, 0x20, 0x20); | 433 | svga_wseq_mask(par->state.vgabase, 0x01, 0x20, 0x20); |
423 | svga_wcrt_mask(0x36, 0x30, 0x30); | 434 | svga_wcrt_mask(par->state.vgabase, 0x36, 0x30, 0x30); |
424 | svga_wcrt_mask(0x17, 0x00, 0x80); | 435 | svga_wcrt_mask(par->state.vgabase, 0x17, 0x00, 0x80); |
425 | 436 | ||
426 | /* Set default values */ | 437 | /* Set default values */ |
427 | svga_set_default_gfx_regs(); | 438 | svga_set_default_gfx_regs(par->state.vgabase); |
428 | svga_set_default_atc_regs(); | 439 | svga_set_default_atc_regs(par->state.vgabase); |
429 | svga_set_default_seq_regs(); | 440 | svga_set_default_seq_regs(par->state.vgabase); |
430 | svga_set_default_crt_regs(); | 441 | svga_set_default_crt_regs(par->state.vgabase); |
431 | svga_wcrt_multi(vt8623_line_compare_regs, 0xFFFFFFFF); | 442 | svga_wcrt_multi(par->state.vgabase, vt8623_line_compare_regs, 0xFFFFFFFF); |
432 | svga_wcrt_multi(vt8623_start_address_regs, 0); | 443 | svga_wcrt_multi(par->state.vgabase, vt8623_start_address_regs, 0); |
433 | 444 | ||
434 | svga_wcrt_multi(vt8623_offset_regs, offset_value); | 445 | svga_wcrt_multi(par->state.vgabase, vt8623_offset_regs, offset_value); |
435 | svga_wseq_multi(vt8623_fetch_count_regs, fetch_value); | 446 | svga_wseq_multi(par->state.vgabase, vt8623_fetch_count_regs, fetch_value); |
436 | 447 | ||
437 | /* Clear H/V Skew */ | 448 | /* Clear H/V Skew */ |
438 | svga_wcrt_mask(0x03, 0x00, 0x60); | 449 | svga_wcrt_mask(par->state.vgabase, 0x03, 0x00, 0x60); |
439 | svga_wcrt_mask(0x05, 0x00, 0x60); | 450 | svga_wcrt_mask(par->state.vgabase, 0x05, 0x00, 0x60); |
440 | 451 | ||
441 | if (info->var.vmode & FB_VMODE_DOUBLE) | 452 | if (info->var.vmode & FB_VMODE_DOUBLE) |
442 | svga_wcrt_mask(0x09, 0x80, 0x80); | 453 | svga_wcrt_mask(par->state.vgabase, 0x09, 0x80, 0x80); |
443 | else | 454 | else |
444 | svga_wcrt_mask(0x09, 0x00, 0x80); | 455 | svga_wcrt_mask(par->state.vgabase, 0x09, 0x00, 0x80); |
445 | 456 | ||
446 | svga_wseq_mask(0x1E, 0xF0, 0xF0); // DI/DVP bus | 457 | svga_wseq_mask(par->state.vgabase, 0x1E, 0xF0, 0xF0); // DI/DVP bus |
447 | svga_wseq_mask(0x2A, 0x0F, 0x0F); // DI/DVP bus | 458 | svga_wseq_mask(par->state.vgabase, 0x2A, 0x0F, 0x0F); // DI/DVP bus |
448 | svga_wseq_mask(0x16, 0x08, 0xBF); // FIFO read threshold | 459 | svga_wseq_mask(par->state.vgabase, 0x16, 0x08, 0xBF); // FIFO read threshold |
449 | vga_wseq(NULL, 0x17, 0x1F); // FIFO depth | 460 | vga_wseq(par->state.vgabase, 0x17, 0x1F); // FIFO depth |
450 | vga_wseq(NULL, 0x18, 0x4E); | 461 | vga_wseq(par->state.vgabase, 0x18, 0x4E); |
451 | svga_wseq_mask(0x1A, 0x08, 0x08); // enable MMIO ? | 462 | svga_wseq_mask(par->state.vgabase, 0x1A, 0x08, 0x08); // enable MMIO ? |
452 | 463 | ||
453 | vga_wcrt(NULL, 0x32, 0x00); | 464 | vga_wcrt(par->state.vgabase, 0x32, 0x00); |
454 | vga_wcrt(NULL, 0x34, 0x00); | 465 | vga_wcrt(par->state.vgabase, 0x34, 0x00); |
455 | vga_wcrt(NULL, 0x6A, 0x80); | 466 | vga_wcrt(par->state.vgabase, 0x6A, 0x80); |
456 | vga_wcrt(NULL, 0x6A, 0xC0); | 467 | vga_wcrt(par->state.vgabase, 0x6A, 0xC0); |
457 | 468 | ||
458 | vga_wgfx(NULL, 0x20, 0x00); | 469 | vga_wgfx(par->state.vgabase, 0x20, 0x00); |
459 | vga_wgfx(NULL, 0x21, 0x00); | 470 | vga_wgfx(par->state.vgabase, 0x21, 0x00); |
460 | vga_wgfx(NULL, 0x22, 0x00); | 471 | vga_wgfx(par->state.vgabase, 0x22, 0x00); |
461 | 472 | ||
462 | /* Set SR15 according to number of bits per pixel */ | 473 | /* Set SR15 according to number of bits per pixel */ |
463 | mode = svga_match_format(vt8623fb_formats, &(info->var), &(info->fix)); | 474 | mode = svga_match_format(vt8623fb_formats, &(info->var), &(info->fix)); |
464 | switch (mode) { | 475 | switch (mode) { |
465 | case 0: | 476 | case 0: |
466 | pr_debug("fb%d: text mode\n", info->node); | 477 | pr_debug("fb%d: text mode\n", info->node); |
467 | svga_set_textmode_vga_regs(); | 478 | svga_set_textmode_vga_regs(par->state.vgabase); |
468 | svga_wseq_mask(0x15, 0x00, 0xFE); | 479 | svga_wseq_mask(par->state.vgabase, 0x15, 0x00, 0xFE); |
469 | svga_wcrt_mask(0x11, 0x60, 0x70); | 480 | svga_wcrt_mask(par->state.vgabase, 0x11, 0x60, 0x70); |
470 | break; | 481 | break; |
471 | case 1: | 482 | case 1: |
472 | pr_debug("fb%d: 4 bit pseudocolor\n", info->node); | 483 | pr_debug("fb%d: 4 bit pseudocolor\n", info->node); |
473 | vga_wgfx(NULL, VGA_GFX_MODE, 0x40); | 484 | vga_wgfx(par->state.vgabase, VGA_GFX_MODE, 0x40); |
474 | svga_wseq_mask(0x15, 0x20, 0xFE); | 485 | svga_wseq_mask(par->state.vgabase, 0x15, 0x20, 0xFE); |
475 | svga_wcrt_mask(0x11, 0x00, 0x70); | 486 | svga_wcrt_mask(par->state.vgabase, 0x11, 0x00, 0x70); |
476 | break; | 487 | break; |
477 | case 2: | 488 | case 2: |
478 | pr_debug("fb%d: 4 bit pseudocolor, planar\n", info->node); | 489 | pr_debug("fb%d: 4 bit pseudocolor, planar\n", info->node); |
479 | svga_wseq_mask(0x15, 0x00, 0xFE); | 490 | svga_wseq_mask(par->state.vgabase, 0x15, 0x00, 0xFE); |
480 | svga_wcrt_mask(0x11, 0x00, 0x70); | 491 | svga_wcrt_mask(par->state.vgabase, 0x11, 0x00, 0x70); |
481 | break; | 492 | break; |
482 | case 3: | 493 | case 3: |
483 | pr_debug("fb%d: 8 bit pseudocolor\n", info->node); | 494 | pr_debug("fb%d: 8 bit pseudocolor\n", info->node); |
484 | svga_wseq_mask(0x15, 0x22, 0xFE); | 495 | svga_wseq_mask(par->state.vgabase, 0x15, 0x22, 0xFE); |
485 | break; | 496 | break; |
486 | case 4: | 497 | case 4: |
487 | pr_debug("fb%d: 5/6/5 truecolor\n", info->node); | 498 | pr_debug("fb%d: 5/6/5 truecolor\n", info->node); |
488 | svga_wseq_mask(0x15, 0xB6, 0xFE); | 499 | svga_wseq_mask(par->state.vgabase, 0x15, 0xB6, 0xFE); |
489 | break; | 500 | break; |
490 | case 5: | 501 | case 5: |
491 | pr_debug("fb%d: 8/8/8 truecolor\n", info->node); | 502 | pr_debug("fb%d: 8/8/8 truecolor\n", info->node); |
492 | svga_wseq_mask(0x15, 0xAE, 0xFE); | 503 | svga_wseq_mask(par->state.vgabase, 0x15, 0xAE, 0xFE); |
493 | break; | 504 | break; |
494 | default: | 505 | default: |
495 | printk(KERN_ERR "vt8623fb: unsupported mode - bug\n"); | 506 | printk(KERN_ERR "vt8623fb: unsupported mode - bug\n"); |
@@ -497,16 +508,16 @@ static int vt8623fb_set_par(struct fb_info *info) | |||
497 | } | 508 | } |
498 | 509 | ||
499 | vt8623_set_pixclock(info, info->var.pixclock); | 510 | vt8623_set_pixclock(info, info->var.pixclock); |
500 | svga_set_timings(&vt8623_timing_regs, &(info->var), 1, 1, | 511 | svga_set_timings(par->state.vgabase, &vt8623_timing_regs, &(info->var), 1, 1, |
501 | (info->var.vmode & FB_VMODE_DOUBLE) ? 2 : 1, 1, | 512 | (info->var.vmode & FB_VMODE_DOUBLE) ? 2 : 1, 1, |
502 | 1, info->node); | 513 | 1, info->node); |
503 | 514 | ||
504 | memset_io(info->screen_base, 0x00, screen_size); | 515 | memset_io(info->screen_base, 0x00, screen_size); |
505 | 516 | ||
506 | /* Device and screen back on */ | 517 | /* Device and screen back on */ |
507 | svga_wcrt_mask(0x17, 0x80, 0x80); | 518 | svga_wcrt_mask(par->state.vgabase, 0x17, 0x80, 0x80); |
508 | svga_wcrt_mask(0x36, 0x00, 0x30); | 519 | svga_wcrt_mask(par->state.vgabase, 0x36, 0x00, 0x30); |
509 | svga_wseq_mask(0x01, 0x00, 0x20); | 520 | svga_wseq_mask(par->state.vgabase, 0x01, 0x00, 0x20); |
510 | 521 | ||
511 | return 0; | 522 | return 0; |
512 | } | 523 | } |
@@ -569,31 +580,33 @@ static int vt8623fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, | |||
569 | 580 | ||
570 | static int vt8623fb_blank(int blank_mode, struct fb_info *info) | 581 | static int vt8623fb_blank(int blank_mode, struct fb_info *info) |
571 | { | 582 | { |
583 | struct vt8623fb_info *par = info->par; | ||
584 | |||
572 | switch (blank_mode) { | 585 | switch (blank_mode) { |
573 | case FB_BLANK_UNBLANK: | 586 | case FB_BLANK_UNBLANK: |
574 | pr_debug("fb%d: unblank\n", info->node); | 587 | pr_debug("fb%d: unblank\n", info->node); |
575 | svga_wcrt_mask(0x36, 0x00, 0x30); | 588 | svga_wcrt_mask(par->state.vgabase, 0x36, 0x00, 0x30); |
576 | svga_wseq_mask(0x01, 0x00, 0x20); | 589 | svga_wseq_mask(par->state.vgabase, 0x01, 0x00, 0x20); |
577 | break; | 590 | break; |
578 | case FB_BLANK_NORMAL: | 591 | case FB_BLANK_NORMAL: |
579 | pr_debug("fb%d: blank\n", info->node); | 592 | pr_debug("fb%d: blank\n", info->node); |
580 | svga_wcrt_mask(0x36, 0x00, 0x30); | 593 | svga_wcrt_mask(par->state.vgabase, 0x36, 0x00, 0x30); |
581 | svga_wseq_mask(0x01, 0x20, 0x20); | 594 | svga_wseq_mask(par->state.vgabase, 0x01, 0x20, 0x20); |
582 | break; | 595 | break; |
583 | case FB_BLANK_HSYNC_SUSPEND: | 596 | case FB_BLANK_HSYNC_SUSPEND: |
584 | pr_debug("fb%d: DPMS standby (hsync off)\n", info->node); | 597 | pr_debug("fb%d: DPMS standby (hsync off)\n", info->node); |
585 | svga_wcrt_mask(0x36, 0x10, 0x30); | 598 | svga_wcrt_mask(par->state.vgabase, 0x36, 0x10, 0x30); |
586 | svga_wseq_mask(0x01, 0x20, 0x20); | 599 | svga_wseq_mask(par->state.vgabase, 0x01, 0x20, 0x20); |
587 | break; | 600 | break; |
588 | case FB_BLANK_VSYNC_SUSPEND: | 601 | case FB_BLANK_VSYNC_SUSPEND: |
589 | pr_debug("fb%d: DPMS suspend (vsync off)\n", info->node); | 602 | pr_debug("fb%d: DPMS suspend (vsync off)\n", info->node); |
590 | svga_wcrt_mask(0x36, 0x20, 0x30); | 603 | svga_wcrt_mask(par->state.vgabase, 0x36, 0x20, 0x30); |
591 | svga_wseq_mask(0x01, 0x20, 0x20); | 604 | svga_wseq_mask(par->state.vgabase, 0x01, 0x20, 0x20); |
592 | break; | 605 | break; |
593 | case FB_BLANK_POWERDOWN: | 606 | case FB_BLANK_POWERDOWN: |
594 | pr_debug("fb%d: DPMS off (no sync)\n", info->node); | 607 | pr_debug("fb%d: DPMS off (no sync)\n", info->node); |
595 | svga_wcrt_mask(0x36, 0x30, 0x30); | 608 | svga_wcrt_mask(par->state.vgabase, 0x36, 0x30, 0x30); |
596 | svga_wseq_mask(0x01, 0x20, 0x20); | 609 | svga_wseq_mask(par->state.vgabase, 0x01, 0x20, 0x20); |
597 | break; | 610 | break; |
598 | } | 611 | } |
599 | 612 | ||
@@ -603,6 +616,7 @@ static int vt8623fb_blank(int blank_mode, struct fb_info *info) | |||
603 | 616 | ||
604 | static int vt8623fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) | 617 | static int vt8623fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) |
605 | { | 618 | { |
619 | struct vt8623fb_info *par = info->par; | ||
606 | unsigned int offset; | 620 | unsigned int offset; |
607 | 621 | ||
608 | /* Calculate the offset */ | 622 | /* Calculate the offset */ |
@@ -616,7 +630,7 @@ static int vt8623fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *i | |||
616 | } | 630 | } |
617 | 631 | ||
618 | /* Set the offset */ | 632 | /* Set the offset */ |
619 | svga_wcrt_multi(vt8623_start_address_regs, offset); | 633 | svga_wcrt_multi(par->state.vgabase, vt8623_start_address_regs, offset); |
620 | 634 | ||
621 | return 0; | 635 | return 0; |
622 | } | 636 | } |
@@ -647,6 +661,8 @@ static struct fb_ops vt8623fb_ops = { | |||
647 | 661 | ||
648 | static int __devinit vt8623_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) | 662 | static int __devinit vt8623_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) |
649 | { | 663 | { |
664 | struct pci_bus_region bus_reg; | ||
665 | struct resource vga_res; | ||
650 | struct fb_info *info; | 666 | struct fb_info *info; |
651 | struct vt8623fb_info *par; | 667 | struct vt8623fb_info *par; |
652 | unsigned int memsize1, memsize2; | 668 | unsigned int memsize1, memsize2; |
@@ -705,9 +721,18 @@ static int __devinit vt8623_pci_probe(struct pci_dev *dev, const struct pci_devi | |||
705 | goto err_iomap_2; | 721 | goto err_iomap_2; |
706 | } | 722 | } |
707 | 723 | ||
724 | bus_reg.start = 0; | ||
725 | bus_reg.end = 64 * 1024; | ||
726 | |||
727 | vga_res.flags = IORESOURCE_IO; | ||
728 | |||
729 | pcibios_bus_to_resource(dev, &vga_res, &bus_reg); | ||
730 | |||
731 | par->state.vgabase = (void __iomem *) vga_res.start; | ||
732 | |||
708 | /* Find how many physical memory there is on card */ | 733 | /* Find how many physical memory there is on card */ |
709 | memsize1 = (vga_rseq(NULL, 0x34) + 1) >> 1; | 734 | memsize1 = (vga_rseq(par->state.vgabase, 0x34) + 1) >> 1; |
710 | memsize2 = vga_rseq(NULL, 0x39) << 2; | 735 | memsize2 = vga_rseq(par->state.vgabase, 0x39) << 2; |
711 | 736 | ||
712 | if ((16 <= memsize1) && (memsize1 <= 64) && (memsize1 == memsize2)) | 737 | if ((16 <= memsize1) && (memsize1 <= 64) && (memsize1 == memsize2)) |
713 | info->screen_size = memsize1 << 20; | 738 | info->screen_size = memsize1 << 20; |