mirror of https://gitee.com/openkylin/linux.git
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>
This commit is contained in:
parent
1c30cd09e3
commit
ed58aee93c
|
@ -704,6 +704,47 @@ nvd0_display_unk1_handler(struct nv50_disp_priv *priv, u32 head, u32 mask)
|
||||||
nv_wr32(priv, 0x6101d0, 0x80000000);
|
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
|
static void
|
||||||
nvd0_display_unk2_handler(struct nv50_disp_priv *priv, u32 head, u32 mask)
|
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);
|
addr = 0x612280 + ((i - 0) * 0x800);
|
||||||
mask = 0xffffffff;
|
mask = 0xffffffff;
|
||||||
} else {
|
} 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);
|
addr = 0x612300 + ((i - 4) * 0x800);
|
||||||
mask = 0x00000707;
|
mask = 0x00000707;
|
||||||
if (cfg & 0x00000100)
|
if (cfg & 0x00000100)
|
||||||
|
|
|
@ -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);
|
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
|
static void
|
||||||
nvd0_sor_dpms(struct drm_encoder *encoder, int mode)
|
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);
|
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);
|
push = evo_wait(nvd0_mast(dev), 8);
|
||||||
if (push) {
|
if (push) {
|
||||||
evo_mthd(push, 0x0404 + (nv_crtc->index * 0x300), 2);
|
evo_mthd(push, 0x0404 + (nv_crtc->index * 0x300), 2);
|
||||||
|
|
Loading…
Reference in New Issue