diff options
author | Ben Skeggs <bskeggs@redhat.com> | 2012-11-07 23:59:26 -0500 |
---|---|---|
committer | Ben Skeggs <bskeggs@redhat.com> | 2012-11-28 18:57:48 -0500 |
commit | ed58aee93c45d5095253d9bc370b418e3d767940 (patch) | |
tree | dec967b4eafb7533cfaa10e4ba3c33265e813a31 /drivers/gpu/drm/nouveau/core/engine/disp | |
parent | 1c30cd09e37e0804f604f3932c695da13e9d442f (diff) |
drm/nvd0/disp: handle DP transfer unit setup from second supervisor interrupt
This is what we've done forever in nv50_display.c, and also allows the
last direct MMIO accesses to be removed from nvd0_display.c.
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/nouveau/core/engine/disp')
-rw-r--r-- | drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c | 50 |
1 files changed, 50 insertions, 0 deletions
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c b/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c index 8589b953b28..bf07248452a 100644 --- a/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c +++ b/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c | |||
@@ -705,6 +705,47 @@ nvd0_display_unk1_handler(struct nv50_disp_priv *priv, u32 head, u32 mask) | |||
705 | } | 705 | } |
706 | 706 | ||
707 | static void | 707 | static void |
708 | nvd0_display_unk2_calc_tu(struct nv50_disp_priv *priv, int head, int or) | ||
709 | { | ||
710 | const u32 ctrl = nv_rd32(priv, 0x660200 + (or * 0x020)); | ||
711 | const u32 conf = nv_rd32(priv, 0x660404 + (head * 0x300)); | ||
712 | const u32 pclk = nv_rd32(priv, 0x660450 + (head * 0x300)) / 1000; | ||
713 | const u32 bits = ((conf & 0x3c0) == 0x080) ? 18 : 24; | ||
714 | const u32 link = ((ctrl & 0xf00) == 0x800) ? 0 : 1; | ||
715 | const u32 hoff = (head * 0x800); | ||
716 | const u32 soff = ( or * 0x800); | ||
717 | const u32 loff = (link * 0x080) + soff; | ||
718 | const u32 symbol = 100000; | ||
719 | const u32 TU = 64; | ||
720 | u32 dpctrl = nv_rd32(priv, 0x61c10c + loff) & 0x000f0000; | ||
721 | u32 clksor = nv_rd32(priv, 0x612300 + soff); | ||
722 | u32 datarate = (pclk * bits) / 8; | ||
723 | u32 link_nr, link_bw; | ||
724 | u64 ratio, value; | ||
725 | |||
726 | if (dpctrl > 0x00030000) link_nr = 4; | ||
727 | else if (dpctrl > 0x00010000) link_nr = 2; | ||
728 | else link_nr = 1; | ||
729 | |||
730 | link_bw = (clksor & 0x007c0000) >> 18; | ||
731 | link_bw *= 27000; | ||
732 | |||
733 | ratio = datarate; | ||
734 | ratio *= symbol; | ||
735 | do_div(ratio, link_nr * link_bw); | ||
736 | |||
737 | value = (symbol - ratio) * TU; | ||
738 | value *= ratio; | ||
739 | do_div(value, symbol); | ||
740 | do_div(value, symbol); | ||
741 | |||
742 | value += 5; | ||
743 | value |= 0x08000000; | ||
744 | |||
745 | nv_wr32(priv, 0x616610 + hoff, value); | ||
746 | } | ||
747 | |||
748 | static void | ||
708 | nvd0_display_unk2_handler(struct nv50_disp_priv *priv, u32 head, u32 mask) | 749 | nvd0_display_unk2_handler(struct nv50_disp_priv *priv, u32 head, u32 mask) |
709 | { | 750 | { |
710 | u32 pclk; | 751 | u32 pclk; |
@@ -735,6 +776,15 @@ nvd0_display_unk2_handler(struct nv50_disp_priv *priv, u32 head, u32 mask) | |||
735 | addr = 0x612280 + ((i - 0) * 0x800); | 776 | addr = 0x612280 + ((i - 0) * 0x800); |
736 | mask = 0xffffffff; | 777 | mask = 0xffffffff; |
737 | } else { | 778 | } else { |
779 | switch (mcp & 0x00000f00) { | ||
780 | case 0x00000800: | ||
781 | case 0x00000900: | ||
782 | nvd0_display_unk2_calc_tu(priv, head, i - 4); | ||
783 | break; | ||
784 | default: | ||
785 | break; | ||
786 | } | ||
787 | |||
738 | addr = 0x612300 + ((i - 4) * 0x800); | 788 | addr = 0x612300 + ((i - 4) * 0x800); |
739 | mask = 0x00000707; | 789 | mask = 0x00000707; |
740 | if (cfg & 0x00000100) | 790 | if (cfg & 0x00000100) |