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 },
        {},
 
                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;
 };
 
 
 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 },
        {},
 
 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 },
 
        { 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 },
 
        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
        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);
 
        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);
 
        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;
 
 #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
 
                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));
        }
 
 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;
                        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:
 
                        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) {
                        mode_ctrl |= 0x00000800;
                else
                        mode_ctrl |= 0x00000900;
-
-               or_config = (mode_ctrl & 0x00000f00) >> 8;
                break;
        default:
                BUG_ON(1);
                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));
        }