diff options
author | Dave Airlie <airlied@linux.ie> | 2006-03-31 02:08:52 -0500 |
---|---|---|
committer | Dave Airlie <airlied@linux.ie> | 2006-04-02 21:43:29 -0400 |
commit | 3aff13cfb8810cc228e8fdcb92103ed0b11ee38e (patch) | |
tree | f2fe6212fcee1952a81022c33afa9dbc836c2e71 /drivers/video/intelfb | |
parent | 46f60b8e67e6fceede851dc69cdee2d7c0de27b9 (diff) |
intelfb: fixup p calculation
This fixes up the p calculation of p1 and p2 for the i9xx chipsets.
This seems to work a lot better for lower pixel clocks..
Signed-off-by: Dave Airlie <airlied@linux.ie>
Diffstat (limited to 'drivers/video/intelfb')
-rw-r--r-- | drivers/video/intelfb/intelfb.h | 2 | ||||
-rw-r--r-- | drivers/video/intelfb/intelfbdrv.c | 2 | ||||
-rw-r--r-- | drivers/video/intelfb/intelfbhw.c | 216 | ||||
-rw-r--r-- | drivers/video/intelfb/intelfbhw.h | 1 |
4 files changed, 137 insertions, 84 deletions
diff --git a/drivers/video/intelfb/intelfb.h b/drivers/video/intelfb/intelfb.h index 43128f9b68f0..631a3a95de40 100644 --- a/drivers/video/intelfb/intelfb.h +++ b/drivers/video/intelfb/intelfb.h | |||
@@ -286,7 +286,7 @@ struct intelfb_info { | |||
286 | int pll_index; | 286 | int pll_index; |
287 | }; | 287 | }; |
288 | 288 | ||
289 | #define IS_I9xx(dinfo) (((dinfo)->chipset == INTEL_915G)||(dinfo->chipset == INTEL_915GM)||((dinfo)->chipset == INTEL_945G)||(dinfo->chipset==INTEL_945GM)) | 289 | #define IS_I9XX(dinfo) (((dinfo)->chipset == INTEL_915G)||(dinfo->chipset == INTEL_915GM)||((dinfo)->chipset == INTEL_945G)||(dinfo->chipset==INTEL_945GM)) |
290 | 290 | ||
291 | /*** function prototypes ***/ | 291 | /*** function prototypes ***/ |
292 | 292 | ||
diff --git a/drivers/video/intelfb/intelfbdrv.c b/drivers/video/intelfb/intelfbdrv.c index 54ce74547a3e..9e83664e345c 100644 --- a/drivers/video/intelfb/intelfbdrv.c +++ b/drivers/video/intelfb/intelfbdrv.c | |||
@@ -1480,7 +1480,7 @@ intelfb_cursor(struct fb_info *info, struct fb_cursor *cursor) | |||
1480 | intelfbhw_cursor_hide(dinfo); | 1480 | intelfbhw_cursor_hide(dinfo); |
1481 | 1481 | ||
1482 | /* If XFree killed the cursor - restore it */ | 1482 | /* If XFree killed the cursor - restore it */ |
1483 | physical = (dinfo->mobile || IS_I9xx(dinfo)) ? dinfo->cursor.physical : | 1483 | physical = (dinfo->mobile || IS_I9XX(dinfo)) ? dinfo->cursor.physical : |
1484 | (dinfo->cursor.offset << 12); | 1484 | (dinfo->cursor.offset << 12); |
1485 | 1485 | ||
1486 | if (INREG(CURSOR_A_BASEADDR) != physical) { | 1486 | if (INREG(CURSOR_A_BASEADDR) != physical) { |
diff --git a/drivers/video/intelfb/intelfbhw.c b/drivers/video/intelfb/intelfbhw.c index 0c3553c35808..2bcf249bdf22 100644 --- a/drivers/video/intelfb/intelfbhw.c +++ b/drivers/video/intelfb/intelfbhw.c | |||
@@ -47,8 +47,8 @@ struct pll_min_max { | |||
47 | int min_n, max_n; | 47 | int min_n, max_n; |
48 | int min_p, max_p; | 48 | int min_p, max_p; |
49 | int min_p1, max_p1; | 49 | int min_p1, max_p1; |
50 | int min_vco_freq, max_vco_freq; | 50 | int min_vco, max_vco; |
51 | int p_transition_clock; | 51 | int p_transition_clk, ref_clk; |
52 | int p_inc_lo, p_inc_hi; | 52 | int p_inc_lo, p_inc_hi; |
53 | }; | 53 | }; |
54 | 54 | ||
@@ -57,8 +57,8 @@ struct pll_min_max { | |||
57 | #define PLLS_MAX 2 | 57 | #define PLLS_MAX 2 |
58 | 58 | ||
59 | static struct pll_min_max plls[PLLS_MAX] = { | 59 | static struct pll_min_max plls[PLLS_MAX] = { |
60 | { 108, 140, 18, 26, 6, 16, 3, 16, 4, 128, 0, 31, 930000, 1400000, 165000, 4, 22 }, //I8xx | 60 | { 108, 140, 18, 26, 6, 16, 3, 16, 4, 128, 0, 31, 930000, 1400000, 165000, 48000, 4, 22 }, //I8xx |
61 | { 75, 120, 10, 20, 5, 9, 4, 7, 5, 80, 1, 8, 930000, 2800000, 200000, 10, 5 } //I9xx | 61 | { 75, 120, 10, 20, 5, 9, 4, 7, 5, 80, 1, 8, 930000, 2800000, 200000, 96000, 10, 5 } //I9xx |
62 | }; | 62 | }; |
63 | 63 | ||
64 | int | 64 | int |
@@ -570,21 +570,26 @@ static int calc_vclock3(int index, int m, int n, int p) | |||
570 | { | 570 | { |
571 | if (p == 0 || n == 0) | 571 | if (p == 0 || n == 0) |
572 | return 0; | 572 | return 0; |
573 | return PLL_REFCLK * m / n / p; | 573 | return plls[index].ref_clk * m / n / p; |
574 | } | 574 | } |
575 | 575 | ||
576 | static int calc_vclock(int index, int m1, int m2, int n, int p1, int p2) | 576 | static int calc_vclock(int index, int m1, int m2, int n, int p1, int p2, int lvds) |
577 | { | 577 | { |
578 | int p2_val; | ||
578 | switch(index) | 579 | switch(index) |
579 | { | 580 | { |
580 | case PLLS_I9xx: | 581 | case PLLS_I9xx: |
581 | if (p1 == 0) | 582 | if (p1 == 0) |
582 | return 0; | 583 | return 0; |
583 | return ((PLL_REFCLK * (5 * (m1 + 2) + (m2 + 2)) / (n + 2) / | 584 | if (lvds) |
584 | ((p1)) * (p2 ? 10 : 5))); | 585 | p2_val = p2 ? 7 : 14; |
586 | else | ||
587 | p2_val = p2 ? 5 : 10; | ||
588 | return ((plls[index].ref_clk * (5 * (m1 + 2) + (m2 + 2)) / (n + 2) / | ||
589 | ((p1)) * (p2_val))); | ||
585 | case PLLS_I8xx: | 590 | case PLLS_I8xx: |
586 | default: | 591 | default: |
587 | return ((PLL_REFCLK * (5 * (m1 + 2) + (m2 + 2)) / (n + 2) / | 592 | return ((plls[index].ref_clk * (5 * (m1 + 2) + (m2 + 2)) / (n + 2) / |
588 | ((p1+2) * (1 << (p2 + 1))))); | 593 | ((p1+2) * (1 << (p2 + 1))))); |
589 | } | 594 | } |
590 | } | 595 | } |
@@ -596,7 +601,7 @@ intelfbhw_print_hw_state(struct intelfb_info *dinfo, struct intelfb_hwstate *hw) | |||
596 | int i, m1, m2, n, p1, p2; | 601 | int i, m1, m2, n, p1, p2; |
597 | int index = dinfo->pll_index; | 602 | int index = dinfo->pll_index; |
598 | DBG_MSG("intelfbhw_print_hw_state\n"); | 603 | DBG_MSG("intelfbhw_print_hw_state\n"); |
599 | 604 | ||
600 | if (!hw || !dinfo) | 605 | if (!hw || !dinfo) |
601 | return; | 606 | return; |
602 | /* Read in as much of the HW state as possible. */ | 607 | /* Read in as much of the HW state as possible. */ |
@@ -611,12 +616,14 @@ intelfbhw_print_hw_state(struct intelfb_info *dinfo, struct intelfb_hwstate *hw) | |||
611 | p1 = 0; | 616 | p1 = 0; |
612 | else | 617 | else |
613 | p1 = (hw->vga_pd >> VGAPD_0_P1_SHIFT) & DPLL_P1_MASK; | 618 | p1 = (hw->vga_pd >> VGAPD_0_P1_SHIFT) & DPLL_P1_MASK; |
619 | |||
614 | p2 = (hw->vga_pd >> VGAPD_0_P2_SHIFT) & DPLL_P2_MASK; | 620 | p2 = (hw->vga_pd >> VGAPD_0_P2_SHIFT) & DPLL_P2_MASK; |
621 | |||
615 | printk(" VGA0: (m1, m2, n, p1, p2) = (%d, %d, %d, %d, %d)\n", | 622 | printk(" VGA0: (m1, m2, n, p1, p2) = (%d, %d, %d, %d, %d)\n", |
616 | m1, m2, n, p1, p2); | 623 | m1, m2, n, p1, p2); |
617 | printk(" VGA0: clock is %d\n", | 624 | printk(" VGA0: clock is %d\n", |
618 | calc_vclock(index, m1, m2, n, p1, p2)); | 625 | calc_vclock(index, m1, m2, n, p1, p2, 0)); |
619 | 626 | ||
620 | n = (hw->vga1_divisor >> FP_N_DIVISOR_SHIFT) & FP_DIVISOR_MASK; | 627 | n = (hw->vga1_divisor >> FP_N_DIVISOR_SHIFT) & FP_DIVISOR_MASK; |
621 | m1 = (hw->vga1_divisor >> FP_M1_DIVISOR_SHIFT) & FP_DIVISOR_MASK; | 628 | m1 = (hw->vga1_divisor >> FP_M1_DIVISOR_SHIFT) & FP_DIVISOR_MASK; |
622 | m2 = (hw->vga1_divisor >> FP_M2_DIVISOR_SHIFT) & FP_DIVISOR_MASK; | 629 | m2 = (hw->vga1_divisor >> FP_M2_DIVISOR_SHIFT) & FP_DIVISOR_MASK; |
@@ -627,39 +634,96 @@ intelfbhw_print_hw_state(struct intelfb_info *dinfo, struct intelfb_hwstate *hw) | |||
627 | p2 = (hw->vga_pd >> VGAPD_1_P2_SHIFT) & DPLL_P2_MASK; | 634 | p2 = (hw->vga_pd >> VGAPD_1_P2_SHIFT) & DPLL_P2_MASK; |
628 | printk(" VGA1: (m1, m2, n, p1, p2) = (%d, %d, %d, %d, %d)\n", | 635 | printk(" VGA1: (m1, m2, n, p1, p2) = (%d, %d, %d, %d, %d)\n", |
629 | m1, m2, n, p1, p2); | 636 | m1, m2, n, p1, p2); |
630 | printk(" VGA1: clock is %d\n", calc_vclock(index, m1, m2, n, p1, p2)); | 637 | printk(" VGA1: clock is %d\n", calc_vclock(index, m1, m2, n, p1, p2, 0)); |
631 | 638 | ||
632 | printk(" DPLL_A: 0x%08x\n", hw->dpll_a); | 639 | printk(" DPLL_A: 0x%08x\n", hw->dpll_a); |
633 | printk(" DPLL_B: 0x%08x\n", hw->dpll_b); | 640 | printk(" DPLL_B: 0x%08x\n", hw->dpll_b); |
634 | printk(" FPA0: 0x%08x\n", hw->fpa0); | 641 | printk(" FPA0: 0x%08x\n", hw->fpa0); |
635 | printk(" FPA1: 0x%08x\n", hw->fpa1); | 642 | printk(" FPA1: 0x%08x\n", hw->fpa1); |
636 | printk(" FPB0: 0x%08x\n", hw->fpb0); | 643 | printk(" FPB0: 0x%08x\n", hw->fpb0); |
637 | printk(" FPB1: 0x%08x\n", hw->fpb1); | 644 | printk(" FPB1: 0x%08x\n", hw->fpb1); |
638 | 645 | ||
639 | n = (hw->fpa0 >> FP_N_DIVISOR_SHIFT) & FP_DIVISOR_MASK; | 646 | n = (hw->fpa0 >> FP_N_DIVISOR_SHIFT) & FP_DIVISOR_MASK; |
640 | m1 = (hw->fpa0 >> FP_M1_DIVISOR_SHIFT) & FP_DIVISOR_MASK; | 647 | m1 = (hw->fpa0 >> FP_M1_DIVISOR_SHIFT) & FP_DIVISOR_MASK; |
641 | m2 = (hw->fpa0 >> FP_M2_DIVISOR_SHIFT) & FP_DIVISOR_MASK; | 648 | m2 = (hw->fpa0 >> FP_M2_DIVISOR_SHIFT) & FP_DIVISOR_MASK; |
642 | if (hw->dpll_a & DPLL_P1_FORCE_DIV2) | 649 | |
643 | p1 = 0; | 650 | if (IS_I9XX(dinfo)) { |
644 | else | 651 | int tmpp1; |
645 | p1 = (hw->dpll_a >> DPLL_P1_SHIFT) & DPLL_P1_MASK; | 652 | |
646 | p2 = (hw->dpll_a >> DPLL_P2_SHIFT) & DPLL_P2_MASK; | 653 | if (hw->dpll_a & DPLL_P1_FORCE_DIV2) |
654 | p1 = 0; | ||
655 | else | ||
656 | p1 = (hw->dpll_a >> DPLL_P1_SHIFT) & 0xff; | ||
657 | |||
658 | tmpp1 = p1; | ||
659 | |||
660 | switch (tmpp1) | ||
661 | { | ||
662 | case 0x1: p1 = 1; break; | ||
663 | case 0x2: p1 = 2; break; | ||
664 | case 0x4: p1 = 3; break; | ||
665 | case 0x8: p1 = 4; break; | ||
666 | case 0x10: p1 = 5; break; | ||
667 | case 0x20: p1 = 6; break; | ||
668 | case 0x40: p1 = 7; break; | ||
669 | case 0x80: p1 = 8; break; | ||
670 | default: break; | ||
671 | } | ||
672 | |||
673 | p2 = (hw->dpll_a >> DPLL_I9XX_P2_SHIFT) & DPLL_P2_MASK; | ||
674 | |||
675 | } else { | ||
676 | if (hw->dpll_a & DPLL_P1_FORCE_DIV2) | ||
677 | p1 = 0; | ||
678 | else | ||
679 | p1 = (hw->dpll_a >> DPLL_P1_SHIFT) & DPLL_P1_MASK; | ||
680 | p2 = (hw->dpll_a >> DPLL_P2_SHIFT) & DPLL_P2_MASK; | ||
681 | } | ||
682 | |||
647 | printk(" PLLA0: (m1, m2, n, p1, p2) = (%d, %d, %d, %d, %d)\n", | 683 | printk(" PLLA0: (m1, m2, n, p1, p2) = (%d, %d, %d, %d, %d)\n", |
648 | m1, m2, n, p1, p2); | 684 | m1, m2, n, p1, p2); |
649 | printk(" PLLA0: clock is %d\n", calc_vclock(index, m1, m2, n, p1, p2)); | 685 | printk(" PLLA0: clock is %d\n", calc_vclock(index, m1, m2, n, p1, p2, 0)); |
650 | 686 | ||
651 | n = (hw->fpa1 >> FP_N_DIVISOR_SHIFT) & FP_DIVISOR_MASK; | 687 | n = (hw->fpa1 >> FP_N_DIVISOR_SHIFT) & FP_DIVISOR_MASK; |
652 | m1 = (hw->fpa1 >> FP_M1_DIVISOR_SHIFT) & FP_DIVISOR_MASK; | 688 | m1 = (hw->fpa1 >> FP_M1_DIVISOR_SHIFT) & FP_DIVISOR_MASK; |
653 | m2 = (hw->fpa1 >> FP_M2_DIVISOR_SHIFT) & FP_DIVISOR_MASK; | 689 | m2 = (hw->fpa1 >> FP_M2_DIVISOR_SHIFT) & FP_DIVISOR_MASK; |
654 | if (hw->dpll_a & DPLL_P1_FORCE_DIV2) | 690 | |
655 | p1 = 0; | 691 | if (IS_I9XX(dinfo)) { |
656 | else | 692 | int tmpp1; |
657 | p1 = (hw->dpll_a >> DPLL_P1_SHIFT) & DPLL_P1_MASK; | 693 | |
658 | p2 = (hw->dpll_a >> DPLL_P2_SHIFT) & DPLL_P2_MASK; | 694 | if (hw->dpll_a & DPLL_P1_FORCE_DIV2) |
695 | p1 = 0; | ||
696 | else | ||
697 | p1 = (hw->dpll_a >> DPLL_P1_SHIFT) & 0xff; | ||
698 | |||
699 | tmpp1 = p1; | ||
700 | |||
701 | switch (tmpp1) | ||
702 | { | ||
703 | case 0x1: p1 = 1; break; | ||
704 | case 0x2: p1 = 2; break; | ||
705 | case 0x4: p1 = 3; break; | ||
706 | case 0x8: p1 = 4; break; | ||
707 | case 0x10: p1 = 5; break; | ||
708 | case 0x20: p1 = 6; break; | ||
709 | case 0x40: p1 = 7; break; | ||
710 | case 0x80: p1 = 8; break; | ||
711 | default: break; | ||
712 | } | ||
713 | |||
714 | p2 = (hw->dpll_a >> DPLL_I9XX_P2_SHIFT) & DPLL_P2_MASK; | ||
715 | |||
716 | } else { | ||
717 | if (hw->dpll_a & DPLL_P1_FORCE_DIV2) | ||
718 | p1 = 0; | ||
719 | else | ||
720 | p1 = (hw->dpll_a >> DPLL_P1_SHIFT) & DPLL_P1_MASK; | ||
721 | p2 = (hw->dpll_a >> DPLL_P2_SHIFT) & DPLL_P2_MASK; | ||
722 | } | ||
659 | printk(" PLLA1: (m1, m2, n, p1, p2) = (%d, %d, %d, %d, %d)\n", | 723 | printk(" PLLA1: (m1, m2, n, p1, p2) = (%d, %d, %d, %d, %d)\n", |
660 | m1, m2, n, p1, p2); | 724 | m1, m2, n, p1, p2); |
661 | printk(" PLLA1: clock is %d\n", calc_vclock(index, m1, m2, n, p1, p2)); | 725 | printk(" PLLA1: clock is %d\n", calc_vclock(index, m1, m2, n, p1, p2, 0)); |
662 | 726 | ||
663 | #if 0 | 727 | #if 0 |
664 | printk(" PALETTE_A:\n"); | 728 | printk(" PALETTE_A:\n"); |
665 | for (i = 0; i < PALETTE_8_ENTRIES) | 729 | for (i = 0; i < PALETTE_8_ENTRIES) |
@@ -767,7 +831,7 @@ splitm(int index, unsigned int m, unsigned int *retm1, unsigned int *retm2) | |||
767 | /* no point optimising too much - brute force m */ | 831 | /* no point optimising too much - brute force m */ |
768 | for (m1 = plls[index].min_m1; m1 < plls[index].max_m1+1; m1++) { | 832 | for (m1 = plls[index].min_m1; m1 < plls[index].max_m1+1; m1++) { |
769 | for (m2 = plls[index].min_m2; m2 < plls[index].max_m2+1; m2++) { | 833 | for (m2 = plls[index].min_m2; m2 < plls[index].max_m2+1; m2++) { |
770 | testm = ( 5 * ( m1 + 2 )) + (m2 + 2); | 834 | testm = (5 * (m1 + 2)) + (m2 + 2); |
771 | if (testm == m) { | 835 | if (testm == m) { |
772 | *retm1 = (unsigned int)m1; | 836 | *retm1 = (unsigned int)m1; |
773 | *retm2 = (unsigned int)m2; | 837 | *retm2 = (unsigned int)m2; |
@@ -785,21 +849,11 @@ splitp(int index, unsigned int p, unsigned int *retp1, unsigned int *retp2) | |||
785 | int p1, p2; | 849 | int p1, p2; |
786 | 850 | ||
787 | if (index == PLLS_I9xx) { | 851 | if (index == PLLS_I9xx) { |
788 | switch (p) { | 852 | |
789 | case 10: | 853 | p2 = 0; // for now |
790 | p1 = 2; | 854 | |
791 | p2 = 0; | 855 | p1 = p / (p2 ? 5 : 10); |
792 | break; | 856 | |
793 | case 20: | ||
794 | p1 = 1; | ||
795 | p2 = 0; | ||
796 | break; | ||
797 | default: | ||
798 | p1 = (p / 10) + 1; | ||
799 | p2 = 0; | ||
800 | break; | ||
801 | } | ||
802 | |||
803 | *retp1 = (unsigned int)p1; | 857 | *retp1 = (unsigned int)p1; |
804 | *retp2 = (unsigned int)p2; | 858 | *retp2 = (unsigned int)p2; |
805 | return 0; | 859 | return 0; |
@@ -844,13 +898,13 @@ calc_pll_params(int index, int clock, u32 *retm1, u32 *retm2, u32 *retn, u32 *re | |||
844 | 898 | ||
845 | DBG_MSG("Clock is %d\n", clock); | 899 | DBG_MSG("Clock is %d\n", clock); |
846 | 900 | ||
847 | div_max = plls[index].max_vco_freq / clock; | 901 | div_max = plls[index].max_vco / clock; |
848 | if (index == PLLS_I9xx) | 902 | if (index == PLLS_I9xx) |
849 | div_min = 5; | 903 | div_min = 5; |
850 | else | 904 | else |
851 | div_min = ROUND_UP_TO(plls[index].min_vco_freq, clock) / clock; | 905 | div_min = ROUND_UP_TO(plls[index].min_vco, clock) / clock; |
852 | 906 | ||
853 | if (clock <= plls[index].p_transition_clock) | 907 | if (clock <= plls[index].p_transition_clk) |
854 | p_inc = plls[index].p_inc_lo; | 908 | p_inc = plls[index].p_inc_lo; |
855 | else | 909 | else |
856 | p_inc = plls[index].p_inc_hi; | 910 | p_inc = plls[index].p_inc_hi; |
@@ -861,15 +915,6 @@ calc_pll_params(int index, int clock, u32 *retm1, u32 *retm2, u32 *retn, u32 *re | |||
861 | if (p_max > plls[index].max_p) | 915 | if (p_max > plls[index].max_p) |
862 | p_max = plls[index].max_p; | 916 | p_max = plls[index].max_p; |
863 | 917 | ||
864 | if (clock < PLL_REFCLK && index == PLLS_I9xx) { | ||
865 | p_min = 10; | ||
866 | p_max = 20; | ||
867 | /* this makes 640x480 work it really shouldn't | ||
868 | - SOMEONE WITHOUT DOCS WOZ HERE */ | ||
869 | if (clock < 30000) | ||
870 | clock *= 4; | ||
871 | } | ||
872 | |||
873 | DBG_MSG("p range is %d-%d (%d)\n", p_min, p_max, p_inc); | 918 | DBG_MSG("p range is %d-%d (%d)\n", p_min, p_max, p_inc); |
874 | 919 | ||
875 | p = p_min; | 920 | p = p_min; |
@@ -883,7 +928,7 @@ calc_pll_params(int index, int clock, u32 *retm1, u32 *retm2, u32 *retn, u32 *re | |||
883 | f_vco = clock * p; | 928 | f_vco = clock * p; |
884 | 929 | ||
885 | do { | 930 | do { |
886 | m = ROUND_UP_TO(f_vco * n, PLL_REFCLK) / PLL_REFCLK; | 931 | m = ROUND_UP_TO(f_vco * n, plls[index].ref_clk) / plls[index].ref_clk; |
887 | if (m < plls[index].min_m) | 932 | if (m < plls[index].min_m) |
888 | m = plls[index].min_m + 1; | 933 | m = plls[index].min_m + 1; |
889 | if (m > plls[index].max_m) | 934 | if (m > plls[index].max_m) |
@@ -899,7 +944,7 @@ calc_pll_params(int index, int clock, u32 *retm1, u32 *retm2, u32 *retn, u32 *re | |||
899 | f_err = clock - f_out; | 944 | f_err = clock - f_out; |
900 | else/* slightly bias the error for bigger clocks */ | 945 | else/* slightly bias the error for bigger clocks */ |
901 | f_err = f_out - clock + 1; | 946 | f_err = f_out - clock + 1; |
902 | 947 | ||
903 | if (f_err < err_best) { | 948 | if (f_err < err_best) { |
904 | m_best = m; | 949 | m_best = m; |
905 | n_best = n; | 950 | n_best = n; |
@@ -928,14 +973,14 @@ calc_pll_params(int index, int clock, u32 *retm1, u32 *retm2, u32 *retn, u32 *re | |||
928 | "f: %d (%d), VCO: %d\n", | 973 | "f: %d (%d), VCO: %d\n", |
929 | m, m1, m2, n, n1, p, p1, p2, | 974 | m, m1, m2, n, n1, p, p1, p2, |
930 | calc_vclock3(index, m, n, p), | 975 | calc_vclock3(index, m, n, p), |
931 | calc_vclock(index, m1, m2, n1, p1, p2), | 976 | calc_vclock(index, m1, m2, n1, p1, p2, 0), |
932 | calc_vclock3(index, m, n, p) * p); | 977 | calc_vclock3(index, m, n, p) * p); |
933 | *retm1 = m1; | 978 | *retm1 = m1; |
934 | *retm2 = m2; | 979 | *retm2 = m2; |
935 | *retn = n1; | 980 | *retn = n1; |
936 | *retp1 = p1; | 981 | *retp1 = p1; |
937 | *retp2 = p2; | 982 | *retp2 = p2; |
938 | *retclock = calc_vclock(index, m1, m2, n1, p1, p2); | 983 | *retclock = calc_vclock(index, m1, m2, n1, p1, p2, 0); |
939 | 984 | ||
940 | return 0; | 985 | return 0; |
941 | } | 986 | } |
@@ -1032,7 +1077,7 @@ intelfbhw_mode_to_hw(struct intelfb_info *dinfo, struct intelfb_hwstate *hw, | |||
1032 | /* Desired clock in kHz */ | 1077 | /* Desired clock in kHz */ |
1033 | clock_target = 1000000000 / var->pixclock; | 1078 | clock_target = 1000000000 / var->pixclock; |
1034 | 1079 | ||
1035 | if (calc_pll_params(dinfo->pll_index, clock_target, &m1, &m2, | 1080 | if (calc_pll_params(dinfo->pll_index, clock_target, &m1, &m2, |
1036 | &n, &p1, &p2, &clock)) { | 1081 | &n, &p1, &p2, &clock)) { |
1037 | WRN_MSG("calc_pll_params failed\n"); | 1082 | WRN_MSG("calc_pll_params failed\n"); |
1038 | return 1; | 1083 | return 1; |
@@ -1053,7 +1098,14 @@ intelfbhw_mode_to_hw(struct intelfb_info *dinfo, struct intelfb_hwstate *hw, | |||
1053 | *dpll &= ~DPLL_P1_FORCE_DIV2; | 1098 | *dpll &= ~DPLL_P1_FORCE_DIV2; |
1054 | *dpll &= ~((DPLL_P2_MASK << DPLL_P2_SHIFT) | | 1099 | *dpll &= ~((DPLL_P2_MASK << DPLL_P2_SHIFT) | |
1055 | (DPLL_P1_MASK << DPLL_P1_SHIFT)); | 1100 | (DPLL_P1_MASK << DPLL_P1_SHIFT)); |
1056 | *dpll |= (p2 << DPLL_P2_SHIFT) | (p1 << DPLL_P1_SHIFT); | 1101 | |
1102 | if (IS_I9XX(dinfo)) { | ||
1103 | *dpll |= (p2 << DPLL_I9XX_P2_SHIFT); | ||
1104 | *dpll |= (1 << (p1 - 1)) << DPLL_P1_SHIFT; | ||
1105 | } else { | ||
1106 | *dpll |= (p2 << DPLL_P2_SHIFT) | (p1 << DPLL_P1_SHIFT); | ||
1107 | } | ||
1108 | |||
1057 | *fp0 = (n << FP_N_DIVISOR_SHIFT) | | 1109 | *fp0 = (n << FP_N_DIVISOR_SHIFT) | |
1058 | (m1 << FP_M1_DIVISOR_SHIFT) | | 1110 | (m1 << FP_M1_DIVISOR_SHIFT) | |
1059 | (m2 << FP_M2_DIVISOR_SHIFT); | 1111 | (m2 << FP_M2_DIVISOR_SHIFT); |
@@ -1264,19 +1316,19 @@ intelfbhw_program_mode(struct intelfb_info *dinfo, | |||
1264 | tmp = INREG(pipe_conf_reg); | 1316 | tmp = INREG(pipe_conf_reg); |
1265 | tmp &= ~PIPECONF_ENABLE; | 1317 | tmp &= ~PIPECONF_ENABLE; |
1266 | OUTREG(pipe_conf_reg, tmp); | 1318 | OUTREG(pipe_conf_reg, tmp); |
1267 | 1319 | ||
1268 | count = 0; | 1320 | count = 0; |
1269 | do { | 1321 | do { |
1270 | tmp_val[count%3] = INREG(0x70000); | 1322 | tmp_val[count%3] = INREG(0x70000); |
1271 | if ((tmp_val[0] == tmp_val[1]) && (tmp_val[1]==tmp_val[2])) | 1323 | if ((tmp_val[0] == tmp_val[1]) && (tmp_val[1]==tmp_val[2])) |
1272 | break; | 1324 | break; |
1273 | count++; | 1325 | count++; |
1274 | udelay(1); | 1326 | udelay(1); |
1275 | if (count % 200 == 0) { | 1327 | if (count % 200 == 0) { |
1276 | tmp = INREG(pipe_conf_reg); | 1328 | tmp = INREG(pipe_conf_reg); |
1277 | tmp &= ~PIPECONF_ENABLE; | 1329 | tmp &= ~PIPECONF_ENABLE; |
1278 | OUTREG(pipe_conf_reg, tmp); | 1330 | OUTREG(pipe_conf_reg, tmp); |
1279 | } | 1331 | } |
1280 | } while(count < 2000); | 1332 | } while(count < 2000); |
1281 | 1333 | ||
1282 | OUTREG(ADPA, INREG(ADPA) & ~ADPA_DAC_ENABLE); | 1334 | OUTREG(ADPA, INREG(ADPA) & ~ADPA_DAC_ENABLE); |
@@ -1289,7 +1341,7 @@ intelfbhw_program_mode(struct intelfb_info *dinfo, | |||
1289 | tmp &= ~DISPPLANE_PLANE_ENABLE; | 1341 | tmp &= ~DISPPLANE_PLANE_ENABLE; |
1290 | OUTREG(DSPBCNTR, tmp); | 1342 | OUTREG(DSPBCNTR, tmp); |
1291 | 1343 | ||
1292 | /* Wait for vblank. For now, just wait for a 50Hz cycle (20ms)) */ | 1344 | /* Wait for vblank. For now, just wait for a 50Hz cycle (20ms)) */ |
1293 | mdelay(20); | 1345 | mdelay(20); |
1294 | 1346 | ||
1295 | /* Disable Sync */ | 1347 | /* Disable Sync */ |
@@ -1359,7 +1411,7 @@ intelfbhw_program_mode(struct intelfb_info *dinfo, | |||
1359 | OUTREG(DSPACNTR, | 1411 | OUTREG(DSPACNTR, |
1360 | hw->disp_a_ctrl|DISPPLANE_PLANE_ENABLE); | 1412 | hw->disp_a_ctrl|DISPPLANE_PLANE_ENABLE); |
1361 | mdelay(1); | 1413 | mdelay(1); |
1362 | } | 1414 | } |
1363 | } | 1415 | } |
1364 | 1416 | ||
1365 | OUTREG(DSPACNTR, hw->disp_a_ctrl & ~DISPPLANE_PLANE_ENABLE); | 1417 | OUTREG(DSPACNTR, hw->disp_a_ctrl & ~DISPPLANE_PLANE_ENABLE); |
@@ -1744,7 +1796,7 @@ intelfbhw_cursor_init(struct intelfb_info *dinfo) | |||
1744 | DBG_MSG("intelfbhw_cursor_init\n"); | 1796 | DBG_MSG("intelfbhw_cursor_init\n"); |
1745 | #endif | 1797 | #endif |
1746 | 1798 | ||
1747 | if (dinfo->mobile || IS_I9xx(dinfo)) { | 1799 | if (dinfo->mobile || IS_I9XX(dinfo)) { |
1748 | if (!dinfo->cursor.physical) | 1800 | if (!dinfo->cursor.physical) |
1749 | return; | 1801 | return; |
1750 | tmp = INREG(CURSOR_A_CONTROL); | 1802 | tmp = INREG(CURSOR_A_CONTROL); |
@@ -1777,7 +1829,7 @@ intelfbhw_cursor_hide(struct intelfb_info *dinfo) | |||
1777 | #endif | 1829 | #endif |
1778 | 1830 | ||
1779 | dinfo->cursor_on = 0; | 1831 | dinfo->cursor_on = 0; |
1780 | if (dinfo->mobile || IS_I9xx(dinfo)) { | 1832 | if (dinfo->mobile || IS_I9XX(dinfo)) { |
1781 | if (!dinfo->cursor.physical) | 1833 | if (!dinfo->cursor.physical) |
1782 | return; | 1834 | return; |
1783 | tmp = INREG(CURSOR_A_CONTROL); | 1835 | tmp = INREG(CURSOR_A_CONTROL); |
@@ -1807,7 +1859,7 @@ intelfbhw_cursor_show(struct intelfb_info *dinfo) | |||
1807 | if (dinfo->cursor_blanked) | 1859 | if (dinfo->cursor_blanked) |
1808 | return; | 1860 | return; |
1809 | 1861 | ||
1810 | if (dinfo->mobile || IS_I9xx(dinfo)) { | 1862 | if (dinfo->mobile || IS_I9XX(dinfo)) { |
1811 | if (!dinfo->cursor.physical) | 1863 | if (!dinfo->cursor.physical) |
1812 | return; | 1864 | return; |
1813 | tmp = INREG(CURSOR_A_CONTROL); | 1865 | tmp = INREG(CURSOR_A_CONTROL); |
@@ -1833,8 +1885,8 @@ intelfbhw_cursor_setpos(struct intelfb_info *dinfo, int x, int y) | |||
1833 | #endif | 1885 | #endif |
1834 | 1886 | ||
1835 | /* | 1887 | /* |
1836 | * Sets the position. The coordinates are assumed to already | 1888 | * Sets the position. The coordinates are assumed to already |
1837 | * have any offset adjusted. Assume that the cursor is never | 1889 | * have any offset adjusted. Assume that the cursor is never |
1838 | * completely off-screen, and that x, y are always >= 0. | 1890 | * completely off-screen, and that x, y are always >= 0. |
1839 | */ | 1891 | */ |
1840 | 1892 | ||
@@ -1842,7 +1894,7 @@ intelfbhw_cursor_setpos(struct intelfb_info *dinfo, int x, int y) | |||
1842 | ((y & CURSOR_POS_MASK) << CURSOR_Y_SHIFT); | 1894 | ((y & CURSOR_POS_MASK) << CURSOR_Y_SHIFT); |
1843 | OUTREG(CURSOR_A_POSITION, tmp); | 1895 | OUTREG(CURSOR_A_POSITION, tmp); |
1844 | 1896 | ||
1845 | if (IS_I9xx(dinfo)) { | 1897 | if (IS_I9XX(dinfo)) { |
1846 | OUTREG(CURSOR_A_BASEADDR, dinfo->cursor.physical); | 1898 | OUTREG(CURSOR_A_BASEADDR, dinfo->cursor.physical); |
1847 | } | 1899 | } |
1848 | } | 1900 | } |
diff --git a/drivers/video/intelfb/intelfbhw.h b/drivers/video/intelfb/intelfbhw.h index a3ec8f92eb64..10acda098b71 100644 --- a/drivers/video/intelfb/intelfbhw.h +++ b/drivers/video/intelfb/intelfbhw.h | |||
@@ -133,6 +133,7 @@ | |||
133 | #define DPLL_VGA_MODE_DISABLE (1 << 28) | 133 | #define DPLL_VGA_MODE_DISABLE (1 << 28) |
134 | #define DPLL_P2_MASK 1 | 134 | #define DPLL_P2_MASK 1 |
135 | #define DPLL_P2_SHIFT 23 | 135 | #define DPLL_P2_SHIFT 23 |
136 | #define DPLL_I9XX_P2_SHIFT 24 | ||
136 | #define DPLL_P1_FORCE_DIV2 (1 << 21) | 137 | #define DPLL_P1_FORCE_DIV2 (1 << 21) |
137 | #define DPLL_P1_MASK 0x1f | 138 | #define DPLL_P1_MASK 0x1f |
138 | #define DPLL_P1_SHIFT 16 | 139 | #define DPLL_P1_SHIFT 16 |