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 | |
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>
-rw-r--r-- | drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c | 50 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nvd0_display.c | 51 |
2 files changed, 50 insertions, 51 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) |
diff --git a/drivers/gpu/drm/nouveau/nvd0_display.c b/drivers/gpu/drm/nouveau/nvd0_display.c index 9acf4a0c5d9..9bb28b030f4 100644 --- a/drivers/gpu/drm/nouveau/nvd0_display.c +++ b/drivers/gpu/drm/nouveau/nvd0_display.c | |||
@@ -1340,52 +1340,6 @@ nvd0_sor_dp_link_set(struct drm_device *dev, struct dcb_output *dcb, int crtc, | |||
1340 | } | 1340 | } |
1341 | 1341 | ||
1342 | static void | 1342 | static void |
1343 | nvd0_sor_dp_link_get(struct drm_device *dev, struct dcb_output *dcb, | ||
1344 | u32 *link_nr, u32 *link_bw) | ||
1345 | { | ||
1346 | struct nouveau_device *device = nouveau_dev(dev); | ||
1347 | const u32 or = ffs(dcb->or) - 1, link = !(dcb->sorconf.link & 1); | ||
1348 | const u32 loff = (or * 0x800) + (link * 0x80); | ||
1349 | const u32 soff = (or * 0x800); | ||
1350 | u32 dpctrl = nv_rd32(device, 0x61c10c + loff) & 0x000f0000; | ||
1351 | u32 clksor = nv_rd32(device, 0x612300 + soff); | ||
1352 | |||
1353 | if (dpctrl > 0x00030000) *link_nr = 4; | ||
1354 | else if (dpctrl > 0x00010000) *link_nr = 2; | ||
1355 | else *link_nr = 1; | ||
1356 | |||
1357 | *link_bw = (clksor & 0x007c0000) >> 18; | ||
1358 | *link_bw *= 27000; | ||
1359 | } | ||
1360 | |||
1361 | static void | ||
1362 | nvd0_sor_dp_calc_tu(struct drm_device *dev, struct dcb_output *dcb, | ||
1363 | u32 crtc, u32 datarate) | ||
1364 | { | ||
1365 | struct nouveau_device *device = nouveau_dev(dev); | ||
1366 | const u32 symbol = 100000; | ||
1367 | const u32 TU = 64; | ||
1368 | u32 link_nr, link_bw; | ||
1369 | u64 ratio, value; | ||
1370 | |||
1371 | nvd0_sor_dp_link_get(dev, dcb, &link_nr, &link_bw); | ||
1372 | |||
1373 | ratio = datarate; | ||
1374 | ratio *= symbol; | ||
1375 | do_div(ratio, link_nr * link_bw); | ||
1376 | |||
1377 | value = (symbol - ratio) * TU; | ||
1378 | value *= ratio; | ||
1379 | do_div(value, symbol); | ||
1380 | do_div(value, symbol); | ||
1381 | |||
1382 | value += 5; | ||
1383 | value |= 0x08000000; | ||
1384 | |||
1385 | nv_wr32(device, 0x616610 + (crtc * 0x800), value); | ||
1386 | } | ||
1387 | |||
1388 | static void | ||
1389 | nvd0_sor_dpms(struct drm_encoder *encoder, int mode) | 1343 | nvd0_sor_dpms(struct drm_encoder *encoder, int mode) |
1390 | { | 1344 | { |
1391 | struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); | 1345 | struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); |
@@ -1576,11 +1530,6 @@ nvd0_sor_mode_set(struct drm_encoder *encoder, struct drm_display_mode *umode, | |||
1576 | 1530 | ||
1577 | nvd0_sor_dpms(encoder, DRM_MODE_DPMS_ON); | 1531 | nvd0_sor_dpms(encoder, DRM_MODE_DPMS_ON); |
1578 | 1532 | ||
1579 | if (nv_encoder->dcb->type == DCB_OUTPUT_DP) { | ||
1580 | nvd0_sor_dp_calc_tu(dev, nv_encoder->dcb, nv_crtc->index, | ||
1581 | nv_encoder->dp.datarate); | ||
1582 | } | ||
1583 | |||
1584 | push = evo_wait(nvd0_mast(dev), 8); | 1533 | push = evo_wait(nvd0_mast(dev), 8); |
1585 | if (push) { | 1534 | if (push) { |
1586 | evo_mthd(push, 0x0404 + (nv_crtc->index * 0x300), 2); | 1535 | evo_mthd(push, 0x0404 + (nv_crtc->index * 0x300), 2); |