From ed58aee93c45d5095253d9bc370b418e3d767940 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Thu, 8 Nov 2012 14:59:26 +1000 Subject: [PATCH] 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 --- .../gpu/drm/nouveau/core/engine/disp/nvd0.c | 50 ++++++++++++++++++ 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 8589b953b284..bf07248452a6 100644 --- a/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c +++ b/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c @@ -704,6 +704,47 @@ nvd0_display_unk1_handler(struct nv50_disp_priv *priv, u32 head, u32 mask) nv_wr32(priv, 0x6101d0, 0x80000000); } +static void +nvd0_display_unk2_calc_tu(struct nv50_disp_priv *priv, int head, int or) +{ + const u32 ctrl = nv_rd32(priv, 0x660200 + (or * 0x020)); + const u32 conf = nv_rd32(priv, 0x660404 + (head * 0x300)); + const u32 pclk = nv_rd32(priv, 0x660450 + (head * 0x300)) / 1000; + const u32 bits = ((conf & 0x3c0) == 0x080) ? 18 : 24; + const u32 link = ((ctrl & 0xf00) == 0x800) ? 0 : 1; + const u32 hoff = (head * 0x800); + const u32 soff = ( or * 0x800); + const u32 loff = (link * 0x080) + soff; + const u32 symbol = 100000; + const u32 TU = 64; + u32 dpctrl = nv_rd32(priv, 0x61c10c + loff) & 0x000f0000; + u32 clksor = nv_rd32(priv, 0x612300 + soff); + u32 datarate = (pclk * bits) / 8; + u32 link_nr, link_bw; + u64 ratio, value; + + if (dpctrl > 0x00030000) link_nr = 4; + else if (dpctrl > 0x00010000) link_nr = 2; + else link_nr = 1; + + link_bw = (clksor & 0x007c0000) >> 18; + link_bw *= 27000; + + ratio = datarate; + ratio *= symbol; + do_div(ratio, link_nr * link_bw); + + value = (symbol - ratio) * TU; + value *= ratio; + do_div(value, symbol); + do_div(value, symbol); + + value += 5; + value |= 0x08000000; + + nv_wr32(priv, 0x616610 + hoff, value); +} + static void nvd0_display_unk2_handler(struct nv50_disp_priv *priv, u32 head, u32 mask) { @@ -735,6 +776,15 @@ nvd0_display_unk2_handler(struct nv50_disp_priv *priv, u32 head, u32 mask) addr = 0x612280 + ((i - 0) * 0x800); mask = 0xffffffff; } else { + switch (mcp & 0x00000f00) { + case 0x00000800: + case 0x00000900: + nvd0_display_unk2_calc_tu(priv, head, i - 4); + break; + default: + break; + } + addr = 0x612300 + ((i - 4) * 0x800); mask = 0x00000707; if (cfg & 0x00000100) diff --git a/drivers/gpu/drm/nouveau/nvd0_display.c b/drivers/gpu/drm/nouveau/nvd0_display.c index 9acf4a0c5d9a..9bb28b030f4b 100644 --- a/drivers/gpu/drm/nouveau/nvd0_display.c +++ b/drivers/gpu/drm/nouveau/nvd0_display.c @@ -1339,52 +1339,6 @@ nvd0_sor_dp_link_set(struct drm_device *dev, struct dcb_output *dcb, int crtc, nv_call(disp->core, NV94_DISP_SOR_DP_LNKCTL + moff, data); } -static void -nvd0_sor_dp_link_get(struct drm_device *dev, struct dcb_output *dcb, - u32 *link_nr, u32 *link_bw) -{ - struct nouveau_device *device = nouveau_dev(dev); - const u32 or = ffs(dcb->or) - 1, link = !(dcb->sorconf.link & 1); - const u32 loff = (or * 0x800) + (link * 0x80); - const u32 soff = (or * 0x800); - u32 dpctrl = nv_rd32(device, 0x61c10c + loff) & 0x000f0000; - u32 clksor = nv_rd32(device, 0x612300 + soff); - - if (dpctrl > 0x00030000) *link_nr = 4; - else if (dpctrl > 0x00010000) *link_nr = 2; - else *link_nr = 1; - - *link_bw = (clksor & 0x007c0000) >> 18; - *link_bw *= 27000; -} - -static void -nvd0_sor_dp_calc_tu(struct drm_device *dev, struct dcb_output *dcb, - u32 crtc, u32 datarate) -{ - struct nouveau_device *device = nouveau_dev(dev); - const u32 symbol = 100000; - const u32 TU = 64; - u32 link_nr, link_bw; - u64 ratio, value; - - nvd0_sor_dp_link_get(dev, dcb, &link_nr, &link_bw); - - ratio = datarate; - ratio *= symbol; - do_div(ratio, link_nr * link_bw); - - value = (symbol - ratio) * TU; - value *= ratio; - do_div(value, symbol); - do_div(value, symbol); - - value += 5; - value |= 0x08000000; - - nv_wr32(device, 0x616610 + (crtc * 0x800), value); -} - static void nvd0_sor_dpms(struct drm_encoder *encoder, int mode) { @@ -1576,11 +1530,6 @@ nvd0_sor_mode_set(struct drm_encoder *encoder, struct drm_display_mode *umode, nvd0_sor_dpms(encoder, DRM_MODE_DPMS_ON); - if (nv_encoder->dcb->type == DCB_OUTPUT_DP) { - nvd0_sor_dp_calc_tu(dev, nv_encoder->dcb, nv_crtc->index, - nv_encoder->dp.datarate); - } - push = evo_wait(nvd0_mast(dev), 8); if (push) { evo_mthd(push, 0x0404 + (nv_crtc->index * 0x300), 2); -- 2.34.1