From: Ben Skeggs Date: Fri, 9 Nov 2012 01:25:37 +0000 (+1000) Subject: drm/nvd0/disp: calculate U script id in supervisor interrupt X-Git-Url: https://git.karo-electronics.de/?a=commitdiff_plain;h=4a230fa61884ffe6b6a806563eee82f12a60fa1e;p=linux-beck.git drm/nvd0/disp: calculate U script id in supervisor interrupt This is like we do on nv50:nvd9 already. There's been no problems seen yet with using this *seemingly* scratch register to store the value, but we won't be able to do this anymore once nv50's code is merged. Signed-off-by: Ben Skeggs --- diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c index bc397bc38ac7..1b1a3845444b 100644 --- a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c +++ b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c @@ -656,6 +656,7 @@ nv50_disp_base_ofuncs = { static struct nouveau_omthds nv50_disp_base_omthds[] = { { SOR_MTHD(NV50_DISP_SOR_PWR) , nv50_sor_mthd }, + { SOR_MTHD(NV50_DISP_SOR_LVDS_SCRIPT) , nv50_sor_mthd }, { DAC_MTHD(NV50_DISP_DAC_PWR) , nv50_dac_mthd }, { DAC_MTHD(NV50_DISP_DAC_LOAD) , nv50_dac_mthd }, {}, diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.h b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.h index 18aa5c0a67a0..3fb5920b6bed 100644 --- a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.h +++ b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.h @@ -35,6 +35,7 @@ struct nv50_disp_priv { int (*dp_drvctl)(struct nv50_disp_priv *, int sor, int link, int lane, u16 type, u16 mask, u32 data, struct dcb_output *); + u32 lvdsconf; } sor; }; diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nv84.c b/drivers/gpu/drm/nouveau/core/engine/disp/nv84.c index 806e24a8c00d..fc84eacdfbec 100644 --- a/drivers/gpu/drm/nouveau/core/engine/disp/nv84.c +++ b/drivers/gpu/drm/nouveau/core/engine/disp/nv84.c @@ -43,6 +43,7 @@ struct nouveau_omthds nv84_disp_base_omthds[] = { { SOR_MTHD(NV50_DISP_SOR_PWR) , nv50_sor_mthd }, { SOR_MTHD(NV84_DISP_SOR_HDMI_PWR) , nv50_sor_mthd }, + { SOR_MTHD(NV50_DISP_SOR_LVDS_SCRIPT) , nv50_sor_mthd }, { DAC_MTHD(NV50_DISP_DAC_PWR) , nv50_dac_mthd }, { DAC_MTHD(NV50_DISP_DAC_LOAD) , nv50_dac_mthd }, {}, diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nv94.c b/drivers/gpu/drm/nouveau/core/engine/disp/nv94.c index cde10e7568e3..b5adcc0bc0da 100644 --- a/drivers/gpu/drm/nouveau/core/engine/disp/nv94.c +++ b/drivers/gpu/drm/nouveau/core/engine/disp/nv94.c @@ -43,6 +43,7 @@ static struct nouveau_omthds nv94_disp_base_omthds[] = { { SOR_MTHD(NV50_DISP_SOR_PWR) , nv50_sor_mthd }, { SOR_MTHD(NV84_DISP_SOR_HDMI_PWR) , nv50_sor_mthd }, + { SOR_MTHD(NV50_DISP_SOR_LVDS_SCRIPT) , nv50_sor_mthd }, { SOR_MTHD(NV94_DISP_SOR_DP_TRAIN) , nv50_sor_mthd }, { SOR_MTHD(NV94_DISP_SOR_DP_LNKCTL) , nv50_sor_mthd }, { SOR_MTHD(NV94_DISP_SOR_DP_DRVCTL(0)), nv50_sor_mthd }, diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nva3.c b/drivers/gpu/drm/nouveau/core/engine/disp/nva3.c index a38ea93ebef6..83ae695ac1df 100644 --- a/drivers/gpu/drm/nouveau/core/engine/disp/nva3.c +++ b/drivers/gpu/drm/nouveau/core/engine/disp/nva3.c @@ -44,6 +44,7 @@ nva3_disp_base_omthds[] = { { SOR_MTHD(NV50_DISP_SOR_PWR) , nv50_sor_mthd }, { SOR_MTHD(NVA3_DISP_SOR_HDA_ELD) , nv50_sor_mthd }, { SOR_MTHD(NV84_DISP_SOR_HDMI_PWR) , nv50_sor_mthd }, + { SOR_MTHD(NV50_DISP_SOR_LVDS_SCRIPT) , nv50_sor_mthd }, { SOR_MTHD(NV94_DISP_SOR_DP_TRAIN) , nv50_sor_mthd }, { SOR_MTHD(NV94_DISP_SOR_DP_LNKCTL) , nv50_sor_mthd }, { SOR_MTHD(NV94_DISP_SOR_DP_DRVCTL(0)), nv50_sor_mthd }, diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c b/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c index 5ac8c429852d..a618f2213a14 100644 --- a/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c +++ b/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c @@ -634,38 +634,59 @@ exec_script(struct nv50_disp_priv *priv, int head, int outp, u32 ctrl, int id) return false; } -static bool +static u32 exec_clkcmp(struct nv50_disp_priv *priv, int head, int outp, - u32 ctrl, u32 conf, int id, u32 pclk) + u32 ctrl, int id, u32 pclk) { struct nouveau_bios *bios = nouveau_bios(priv); struct nvbios_outp info1; struct nvbios_ocfg info2; struct dcb_output dcb; u8 ver, hdr, cnt, len; - u16 data; + u16 data, conf; data = exec_lookup(priv, head, outp, ctrl, &dcb, &ver, &hdr, &cnt, &len, &info1); + if (data == 0x0000) + return false; + + switch (dcb.type) { + case DCB_OUTPUT_TMDS: + conf = (ctrl & 0x00000f00) >> 8; + if (pclk >= 165000) + conf |= 0x0100; + break; + case DCB_OUTPUT_LVDS: + conf = priv->sor.lvdsconf; + break; + case DCB_OUTPUT_DP: + conf = (ctrl & 0x00000f00) >> 8; + break; + case DCB_OUTPUT_ANALOG: + default: + conf = 0x00ff; + break; + } + + data = nvbios_ocfg_match(bios, data, conf, &ver, &hdr, &cnt, &len, &info2); if (data) { - data = nvbios_ocfg_match(bios, data, conf, &ver, &hdr, &cnt, &len, &info2); + data = nvbios_oclk_match(bios, info2.clkcmp[id], pclk); if (data) { - data = nvbios_oclk_match(bios, info2.clkcmp[id], pclk); - if (data) { - struct nvbios_init init = { - .subdev = nv_subdev(priv), - .bios = bios, - .offset = data, - .outp = &dcb, - .crtc = head, - .execute = 1, - }; - - return nvbios_exec(&init) == 0; - } + struct nvbios_init init = { + .subdev = nv_subdev(priv), + .bios = bios, + .offset = data, + .outp = &dcb, + .crtc = head, + .execute = 1, + }; + + if (nvbios_exec(&init)) + return 0x0000; + return conf; } } - return false; + return 0x0000; } static void @@ -747,10 +768,9 @@ nvd0_display_unk2_handler(struct nv50_disp_priv *priv, u32 head, u32 mask) nv_wr32(priv, 0x612200 + (head * 0x800), 0x00000000); for (i = 0; mask && i < 8; i++) { - u32 mcp = nv_rd32(priv, 0x660180 + (i * 0x20)); - u32 cfg = nv_rd32(priv, 0x660184 + (i * 0x20)); + u32 mcp = nv_rd32(priv, 0x660180 + (i * 0x20)), cfg; if (mcp & (1 << head)) { - if (exec_clkcmp(priv, head, i, mcp, cfg, 0, pclk)) { + if ((cfg = exec_clkcmp(priv, head, i, mcp, 0, pclk))) { u32 addr, mask, data = 0x00000000; if (i < 4) { addr = 0x612280 + ((i - 0) * 0x800); @@ -790,9 +810,8 @@ nvd0_display_unk4_handler(struct nv50_disp_priv *priv, u32 head, u32 mask) for (i = 0; mask && i < 8; i++) { u32 mcp = nv_rd32(priv, 0x660180 + (i * 0x20)); - u32 cfg = nv_rd32(priv, 0x660184 + (i * 0x20)); if (mcp & (1 << head)) - exec_clkcmp(priv, head, i, mcp, cfg, 1, pclk); + exec_clkcmp(priv, head, i, mcp, 1, pclk); } nv_wr32(priv, 0x6101d4, 0x00000000); diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/sornv50.c b/drivers/gpu/drm/nouveau/core/engine/disp/sornv50.c index 0ca12b9230fd..6fd25730a588 100644 --- a/drivers/gpu/drm/nouveau/core/engine/disp/sornv50.c +++ b/drivers/gpu/drm/nouveau/core/engine/disp/sornv50.c @@ -75,6 +75,10 @@ nv50_sor_mthd(struct nouveau_object *object, u32 mthd, void *args, u32 size) case NV84_DISP_SOR_HDMI_PWR: ret = priv->sor.hdmi(priv, head, or, data); break; + case NV50_DISP_SOR_LVDS_SCRIPT: + priv->sor.lvdsconf = data & NV50_DISP_SOR_LVDS_SCRIPT_ID; + ret = 0; + break; case NV94_DISP_SOR_DP_TRAIN: ret = priv->sor.dp_train(priv, or, link, type, mask, data, &outp); break; diff --git a/drivers/gpu/drm/nouveau/core/include/core/class.h b/drivers/gpu/drm/nouveau/core/include/core/class.h index de3ce108221e..dd060234b0b0 100644 --- a/drivers/gpu/drm/nouveau/core/include/core/class.h +++ b/drivers/gpu/drm/nouveau/core/include/core/class.h @@ -188,6 +188,8 @@ struct nve0_channel_ind_class { #define NV84_DISP_SOR_HDMI_PWR_STATE_ON 0x40000000 #define NV84_DISP_SOR_HDMI_PWR_MAX_AC_PACKET 0x001f0000 #define NV84_DISP_SOR_HDMI_PWR_REKEY 0x0000007f +#define NV50_DISP_SOR_LVDS_SCRIPT 0x00013000 +#define NV50_DISP_SOR_LVDS_SCRIPT_ID 0x0000ffff #define NV94_DISP_SOR_DP_TRAIN 0x00016000 #define NV94_DISP_SOR_DP_TRAIN_PATTERN 0x00000003 #define NV94_DISP_SOR_DP_TRAIN_PATTERN_DISABLED 0x00000000 diff --git a/drivers/gpu/drm/nouveau/nvd0_display.c b/drivers/gpu/drm/nouveau/nvd0_display.c index 758daf709a99..518f1a5342aa 100644 --- a/drivers/gpu/drm/nouveau/nvd0_display.c +++ b/drivers/gpu/drm/nouveau/nvd0_display.c @@ -1139,9 +1139,8 @@ nvd0_dac_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, evo_mthd(push, 0x0404 + (nv_crtc->index * 0x300), 2); evo_data(push, syncs); evo_data(push, magic); - evo_mthd(push, 0x0180 + (nv_encoder->or * 0x020), 2); + evo_mthd(push, 0x0180 + (nv_encoder->or * 0x020), 1); evo_data(push, 1 << nv_crtc->index); - evo_data(push, 0x00ff); evo_kick(push, nvd0_mast(encoder->dev)); } @@ -1440,12 +1439,14 @@ static void nvd0_sor_mode_set(struct drm_encoder *encoder, struct drm_display_mode *umode, struct drm_display_mode *mode) { + struct nvd0_disp *disp = nvd0_disp(encoder->dev); struct drm_device *dev = encoder->dev; struct nouveau_drm *drm = nouveau_drm(dev); struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc); struct nouveau_connector *nv_connector; struct nvbios *bios = &drm->vbios; + int or = nv_encoder->or; u32 mode_ctrl = (1 << nv_crtc->index); u32 syncs, magic, *push; u32 or_config; @@ -1472,10 +1473,6 @@ nvd0_sor_mode_set(struct drm_encoder *encoder, struct drm_display_mode *umode, mode_ctrl |= 0x00000200; } - or_config = (mode_ctrl & 0x00000f00) >> 8; - if (mode->clock >= 165000) - or_config |= 0x0100; - nvd0_hdmi_mode_set(encoder, mode); break; case DCB_OUTPUT_LVDS: @@ -1504,8 +1501,9 @@ nvd0_sor_mode_set(struct drm_encoder *encoder, struct drm_display_mode *umode, if (nv_connector->base.display_info.bpc == 8) or_config |= 0x0200; - } + + nv_call(disp->core, NV50_DISP_SOR_LVDS_SCRIPT + or, or_config); break; case DCB_OUTPUT_DP: if (nv_connector->base.display_info.bpc == 6) { @@ -1520,8 +1518,6 @@ nvd0_sor_mode_set(struct drm_encoder *encoder, struct drm_display_mode *umode, mode_ctrl |= 0x00000800; else mode_ctrl |= 0x00000900; - - or_config = (mode_ctrl & 0x00000f00) >> 8; break; default: BUG_ON(1); @@ -1535,9 +1531,8 @@ nvd0_sor_mode_set(struct drm_encoder *encoder, struct drm_display_mode *umode, evo_mthd(push, 0x0404 + (nv_crtc->index * 0x300), 2); evo_data(push, syncs); evo_data(push, magic); - evo_mthd(push, 0x0200 + (nv_encoder->or * 0x020), 2); + evo_mthd(push, 0x0200 + (nv_encoder->or * 0x020), 1); evo_data(push, mode_ctrl); - evo_data(push, or_config); evo_kick(push, nvd0_mast(dev)); }