aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2012-11-07 23:59:26 -0500
committerBen Skeggs <bskeggs@redhat.com>2012-11-28 18:57:48 -0500
commited58aee93c45d5095253d9bc370b418e3d767940 (patch)
treedec967b4eafb7533cfaa10e4ba3c33265e813a31
parent1c30cd09e37e0804f604f3932c695da13e9d442f (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.c50
-rw-r--r--drivers/gpu/drm/nouveau/nvd0_display.c51
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
707static void 707static void
708nvd0_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
748static void
708nvd0_display_unk2_handler(struct nv50_disp_priv *priv, u32 head, u32 mask) 749nvd0_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
1342static void 1342static void
1343nvd0_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
1361static void
1362nvd0_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
1388static void
1389nvd0_sor_dpms(struct drm_encoder *encoder, int mode) 1343nvd0_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);