drm/nouveau/disp/dp: make use of existing output data for link training
authorBen Skeggs <bskeggs@redhat.com>
Mon, 19 May 2014 04:06:07 +0000 (14:06 +1000)
committerBen Skeggs <bskeggs@redhat.com>
Wed, 11 Jun 2014 06:10:45 +0000 (16:10 +1000)
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
16 files changed:
drivers/gpu/drm/nouveau/core/engine/disp/dport.c
drivers/gpu/drm/nouveau/core/engine/disp/dport.h
drivers/gpu/drm/nouveau/core/engine/disp/gm107.c
drivers/gpu/drm/nouveau/core/engine/disp/nv50.c
drivers/gpu/drm/nouveau/core/engine/disp/nv50.h
drivers/gpu/drm/nouveau/core/engine/disp/nv84.c
drivers/gpu/drm/nouveau/core/engine/disp/nv94.c
drivers/gpu/drm/nouveau/core/engine/disp/nva0.c
drivers/gpu/drm/nouveau/core/engine/disp/nva3.c
drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c
drivers/gpu/drm/nouveau/core/engine/disp/nve0.c
drivers/gpu/drm/nouveau/core/engine/disp/nvf0.c
drivers/gpu/drm/nouveau/core/engine/disp/outpdp.h
drivers/gpu/drm/nouveau/core/engine/disp/piornv50.c
drivers/gpu/drm/nouveau/core/engine/disp/sornv94.c
drivers/gpu/drm/nouveau/core/engine/disp/sornvd0.c

index 3814c3d33812797afdcc2f7de09a67dcbe32a855..efccbabca18c8e39e8238ebc6e521de234fdac01 100644 (file)
 #include <core/class.h>
 
 #include "dport.h"
-
-#define DBG(fmt, args...) nv_debug(dp->disp, "DP:%04x:%04x: " fmt,             \
-                                  dp->outp->hasht, dp->outp->hashm, ##args)
-#define ERR(fmt, args...) nv_error(dp->disp, "DP:%04x:%04x: " fmt,             \
-                                  dp->outp->hasht, dp->outp->hashm, ##args)
+#include "outpdp.h"
 
 /******************************************************************************
  * link training
  *****************************************************************************/
 struct dp_state {
-       const struct nouveau_dp_func *func;
-       struct nouveau_disp *disp;
-       struct dcb_output *outp;
-       struct nvbios_dpout info;
-       u8 version;
-       struct nouveau_i2c_port *aux;
-       int head;
-       u8  dpcd[16];
+       struct nvkm_output_dp *outp;
        int link_nr;
        u32 link_bw;
        u8  stat[6];
@@ -63,14 +52,16 @@ struct dp_state {
 static int
 dp_set_link_config(struct dp_state *dp)
 {
-       struct nouveau_disp *disp = dp->disp;
+       struct nvkm_output_dp_impl *impl = (void *)nv_oclass(dp->outp);
+       struct nvkm_output_dp *outp = dp->outp;
+       struct nouveau_disp *disp = nouveau_disp(outp);
        struct nouveau_bios *bios = nouveau_bios(disp);
        struct nvbios_init init = {
-               .subdev = nv_subdev(dp->disp),
+               .subdev = nv_subdev(disp),
                .bios = bios,
                .offset = 0x0000,
-               .outp = dp->outp,
-               .crtc = dp->head,
+               .outp = &outp->base.info,
+               .crtc = -1,
                .execute = 1,
        };
        u32 lnkcmp;
@@ -80,8 +71,8 @@ dp_set_link_config(struct dp_state *dp)
        DBG("%d lanes at %d KB/s\n", dp->link_nr, dp->link_bw);
 
        /* set desired link configuration on the source */
-       if ((lnkcmp = dp->info.lnkcmp)) {
-               if (dp->version < 0x30) {
+       if ((lnkcmp = dp->outp->info.lnkcmp)) {
+               if (outp->version < 0x30) {
                        while ((dp->link_bw / 10) < nv_ro16(bios, lnkcmp))
                                lnkcmp += 4;
                        init.offset = nv_ro16(bios, lnkcmp + 2);
@@ -94,43 +85,45 @@ dp_set_link_config(struct dp_state *dp)
                nvbios_exec(&init);
        }
 
-       ret = dp->func->lnk_ctl(dp->disp, dp->outp, dp->head,
-                               dp->link_nr, dp->link_bw / 27000,
-                               dp->dpcd[DPCD_RC02] &
-                                        DPCD_RC02_ENHANCED_FRAME_CAP);
+       ret = impl->lnk_ctl(outp, dp->link_nr, dp->link_bw / 27000,
+                           outp->dpcd[DPCD_RC02] &
+                                      DPCD_RC02_ENHANCED_FRAME_CAP);
        if (ret) {
-               ERR("lnk_ctl failed with %d\n", ret);
+               if (ret < 0)
+                       ERR("lnk_ctl failed with %d\n", ret);
                return ret;
        }
 
        /* set desired link configuration on the sink */
        sink[0] = dp->link_bw / 27000;
        sink[1] = dp->link_nr;
-       if (dp->dpcd[DPCD_RC02] & DPCD_RC02_ENHANCED_FRAME_CAP)
+       if (outp->dpcd[DPCD_RC02] & DPCD_RC02_ENHANCED_FRAME_CAP)
                sink[1] |= DPCD_LC01_ENHANCED_FRAME_EN;
 
-       return nv_wraux(dp->aux, DPCD_LC00, sink, 2);
+       return nv_wraux(outp->base.edid, DPCD_LC00, sink, 2);
 }
 
 static void
 dp_set_training_pattern(struct dp_state *dp, u8 pattern)
 {
+       struct nvkm_output_dp_impl *impl = (void *)nv_oclass(dp->outp);
+       struct nvkm_output_dp *outp = dp->outp;
        u8 sink_tp;
 
        DBG("training pattern %d\n", pattern);
-       dp->func->pattern(dp->disp, dp->outp, dp->head, pattern);
+       impl->pattern(outp, pattern);
 
-       nv_rdaux(dp->aux, DPCD_LC02, &sink_tp, 1);
+       nv_rdaux(outp->base.edid, DPCD_LC02, &sink_tp, 1);
        sink_tp &= ~DPCD_LC02_TRAINING_PATTERN_SET;
        sink_tp |= pattern;
-       nv_wraux(dp->aux, DPCD_LC02, &sink_tp, 1);
+       nv_wraux(outp->base.edid, DPCD_LC02, &sink_tp, 1);
 }
 
 static int
 dp_link_train_commit(struct dp_state *dp, bool pc)
 {
-       const struct nouveau_dp_func *func = dp->func;
-       struct nouveau_disp *disp = dp->disp;
+       struct nvkm_output_dp_impl *impl = (void *)nv_oclass(dp->outp);
+       struct nvkm_output_dp *outp = dp->outp;
        int ret, i;
 
        for (i = 0; i < dp->link_nr; i++) {
@@ -146,15 +139,15 @@ dp_link_train_commit(struct dp_state *dp, bool pc)
                dp->pc2conf[i >> 1] |= 4 << ((i & 1) * 4);
 
                DBG("config lane %d %02x\n", i, dp->conf[i]);
-               func->drv_ctl(disp, dp->outp, dp->head, i, lvsw, lpre);
+               impl->drv_ctl(outp, i, lvsw, lpre, 0);
        }
 
-       ret = nv_wraux(dp->aux, DPCD_LC03(0), dp->conf, 4);
+       ret = nv_wraux(outp->base.edid, DPCD_LC03(0), dp->conf, 4);
        if (ret)
                return ret;
 
        if (pc) {
-               ret = nv_wraux(dp->aux, DPCD_LC0F, dp->pc2conf, 2);
+               ret = nv_wraux(outp->base.edid, DPCD_LC0F, dp->pc2conf, 2);
                if (ret)
                        return ret;
        }
@@ -165,19 +158,20 @@ dp_link_train_commit(struct dp_state *dp, bool pc)
 static int
 dp_link_train_update(struct dp_state *dp, bool pc, u32 delay)
 {
+       struct nvkm_output_dp *outp = dp->outp;
        int ret;
 
-       if (dp->dpcd[DPCD_RC0E_AUX_RD_INTERVAL])
-               mdelay(dp->dpcd[DPCD_RC0E_AUX_RD_INTERVAL] * 4);
+       if (outp->dpcd[DPCD_RC0E_AUX_RD_INTERVAL])
+               mdelay(outp->dpcd[DPCD_RC0E_AUX_RD_INTERVAL] * 4);
        else
                udelay(delay);
 
-       ret = nv_rdaux(dp->aux, DPCD_LS02, dp->stat, 6);
+       ret = nv_rdaux(outp->base.edid, DPCD_LS02, dp->stat, 6);
        if (ret)
                return ret;
 
        if (pc) {
-               ret = nv_rdaux(dp->aux, DPCD_LS0C, &dp->pc2stat, 1);
+               ret = nv_rdaux(outp->base.edid, DPCD_LS0C, &dp->pc2stat, 1);
                if (ret)
                        dp->pc2stat = 0x00;
                DBG("status %6ph pc2 %02x\n", dp->stat, dp->pc2stat);
@@ -225,10 +219,11 @@ dp_link_train_cr(struct dp_state *dp)
 static int
 dp_link_train_eq(struct dp_state *dp)
 {
+       struct nvkm_output_dp *outp = dp->outp;
        bool eq_done = false, cr_done = true;
        int tries = 0, i;
 
-       if (dp->dpcd[2] & DPCD_RC02_TPS3_SUPPORTED)
+       if (outp->dpcd[2] & DPCD_RC02_TPS3_SUPPORTED)
                dp_set_training_pattern(dp, 3);
        else
                dp_set_training_pattern(dp, 2);
@@ -257,39 +252,45 @@ dp_link_train_eq(struct dp_state *dp)
 static void
 dp_link_train_init(struct dp_state *dp, bool spread)
 {
+       struct nvkm_output_dp *outp = dp->outp;
+       struct nouveau_disp *disp = nouveau_disp(outp);
+       struct nouveau_bios *bios = nouveau_bios(disp);
        struct nvbios_init init = {
-               .subdev = nv_subdev(dp->disp),
-               .bios = nouveau_bios(dp->disp),
-               .outp = dp->outp,
-               .crtc = dp->head,
+               .subdev = nv_subdev(disp),
+               .bios = bios,
+               .outp = &outp->base.info,
+               .crtc = -1,
                .execute = 1,
        };
 
        /* set desired spread */
        if (spread)
-               init.offset = dp->info.script[2];
+               init.offset = outp->info.script[2];
        else
-               init.offset = dp->info.script[3];
+               init.offset = outp->info.script[3];
        nvbios_exec(&init);
 
        /* pre-train script */
-       init.offset = dp->info.script[0];
+       init.offset = outp->info.script[0];
        nvbios_exec(&init);
 }
 
 static void
 dp_link_train_fini(struct dp_state *dp)
 {
+       struct nvkm_output_dp *outp = dp->outp;
+       struct nouveau_disp *disp = nouveau_disp(outp);
+       struct nouveau_bios *bios = nouveau_bios(disp);
        struct nvbios_init init = {
-               .subdev = nv_subdev(dp->disp),
-               .bios = nouveau_bios(dp->disp),
-               .outp = dp->outp,
-               .crtc = dp->head,
+               .subdev = nv_subdev(disp),
+               .bios = bios,
+               .outp = &outp->base.info,
+               .crtc = -1,
                .execute = 1,
        };
 
        /* post-train script */
-       init.offset = dp->info.script[1],
+       init.offset = outp->info.script[1],
        nvbios_exec(&init);
 }
 
@@ -311,65 +312,25 @@ static const struct dp_rates {
 };
 
 int
-nouveau_dp_train(struct nouveau_disp *disp, const struct nouveau_dp_func *func,
-                struct dcb_output *outp, int head, u32 datarate)
+nouveau_dp_train(struct nvkm_output_dp *outp, u32 datarate)
 {
-       struct nouveau_bios *bios = nouveau_bios(disp);
-       struct nouveau_i2c *i2c = nouveau_i2c(disp);
+       struct nouveau_disp *disp = nouveau_disp(outp);
        const struct dp_rates *cfg = nouveau_dp_rates;
        struct dp_state _dp = {
-               .disp = disp,
-               .func = func,
                .outp = outp,
-               .head = head,
        }, *dp = &_dp;
-       u8  hdr, cnt, len;
-       u32 data;
        int ret;
 
-       /* find the bios displayport data relevant to this output */
-       data = nvbios_dpout_match(bios, outp->hasht, outp->hashm, &dp->version,
-                                &hdr, &cnt, &len, &dp->info);
-       if (!data) {
-               ERR("bios data not found\n");
-               return -EINVAL;
-       }
-
-       /* acquire the aux channel and fetch some info about the display */
-       if (outp->location)
-               dp->aux = i2c->find_type(i2c, NV_I2C_TYPE_EXTAUX(outp->extdev));
-       else
-               dp->aux = i2c->find(i2c, NV_I2C_TYPE_DCBI2C(outp->i2c_index));
-       if (!dp->aux) {
-               ERR("no aux channel?!\n");
-               return -ENODEV;
-       }
-
-       ret = nv_rdaux(dp->aux, 0x00000, dp->dpcd, sizeof(dp->dpcd));
-       if (ret) {
-               /* it's possible the display has been unplugged before we
-                * get here.  we still need to execute the full set of
-                * vbios scripts, and program the OR at a high enough
-                * frequency to satisfy the target mode.  failure to do
-                * so results at best in an UPDATE hanging, and at worst
-                * with PDISP running away to join the circus.
-                */
-               dp->dpcd[1] = dp->outp->dpconf.link_bw;
-               dp->dpcd[2] = dp->outp->dpconf.link_nr;
-               dp->dpcd[3] = 0x00;
-               ERR("failed to read DPCD\n");
-       }
-
        /* bring capabilities within encoder limits */
        if (nv_mclass(disp) < NVD0_DISP_CLASS)
-               dp->dpcd[2] &= ~DPCD_RC02_TPS3_SUPPORTED;
-       if ((dp->dpcd[2] & 0x1f) > dp->outp->dpconf.link_nr) {
-               dp->dpcd[2] &= ~DPCD_RC02_MAX_LANE_COUNT;
-               dp->dpcd[2] |= dp->outp->dpconf.link_nr;
+               outp->dpcd[2] &= ~DPCD_RC02_TPS3_SUPPORTED;
+       if ((outp->dpcd[2] & 0x1f) > outp->base.info.dpconf.link_nr) {
+               outp->dpcd[2] &= ~DPCD_RC02_MAX_LANE_COUNT;
+               outp->dpcd[2] |= outp->base.info.dpconf.link_nr;
        }
-       if (dp->dpcd[1] > dp->outp->dpconf.link_bw)
-               dp->dpcd[1] = dp->outp->dpconf.link_bw;
-       dp->pc2 = dp->dpcd[2] & DPCD_RC02_TPS3_SUPPORTED;
+       if (outp->dpcd[1] > outp->base.info.dpconf.link_bw)
+               outp->dpcd[1] = outp->base.info.dpconf.link_bw;
+       dp->pc2 = outp->dpcd[2] & DPCD_RC02_TPS3_SUPPORTED;
 
        /* restrict link config to the lowest required rate, if requested */
        if (datarate) {
@@ -380,12 +341,12 @@ nouveau_dp_train(struct nouveau_disp *disp, const struct nouveau_dp_func *func,
        cfg--;
 
        /* enable down-spreading and execute pre-train script from vbios */
-       dp_link_train_init(dp, dp->dpcd[3] & 0x01);
+       dp_link_train_init(dp, outp->dpcd[3] & 0x01);
 
        while (ret = -EIO, (++cfg)->rate) {
                /* select next configuration supported by encoder and sink */
-               while (cfg->nr > (dp->dpcd[2] & DPCD_RC02_MAX_LANE_COUNT) ||
-                      cfg->bw > (dp->dpcd[DPCD_RC01_MAX_LINK_RATE]))
+               while (cfg->nr > (outp->dpcd[2] & DPCD_RC02_MAX_LANE_COUNT) ||
+                      cfg->bw > (outp->dpcd[DPCD_RC01_MAX_LINK_RATE]))
                        cfg++;
                dp->link_bw = cfg->bw * 27000;
                dp->link_nr = cfg->nr;
index 436358e5cfc85d83f36d97341d4d7b63985c8710..2712e31c9ce87e185baaa4fdb623f1590fddeb33 100644 (file)
 #define DPCD_LS0C_LANE1_POST_CURSOR2                                       0x0c
 #define DPCD_LS0C_LANE0_POST_CURSOR2                                       0x03
 
-struct nouveau_disp;
-struct dcb_output;
-
-struct nouveau_dp_func {
-       int (*pattern)(struct nouveau_disp *, struct dcb_output *,
-                      int head, int pattern);
-       int (*lnk_ctl)(struct nouveau_disp *, struct dcb_output *, int head,
-                      int link_nr, int link_bw, bool enh_frame);
-       int (*drv_ctl)(struct nouveau_disp *, struct dcb_output *, int head,
-                      int lane, int swing, int preem);
-};
-
-extern const struct nouveau_dp_func nv94_sor_dp_func;
-extern const struct nouveau_dp_func nvd0_sor_dp_func;
-extern const struct nouveau_dp_func nv50_pior_dp_func;
-
-int nouveau_dp_train(struct nouveau_disp *, const struct nouveau_dp_func *,
-                    struct dcb_output *, int, u32);
-
 #endif
index a5b0ad6d3bfab6004650d28ca992d9265f0ad2cd..9fc7447fec90815121e7cd060771ecb03455341e 100644 (file)
@@ -81,7 +81,6 @@ gm107_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        priv->sor.power = nv50_sor_power;
        priv->sor.hda_eld = nvd0_hda_eld;
        priv->sor.hdmi = nvd0_hdmi_ctrl;
-       priv->sor.dp = &nvd0_sor_dp_func;
        return 0;
 }
 
index d2553c91df7ddb05427fffadb79a4fe9ccc3f0b0..2b9ef826959a5cc82a872bab912292abf21ec8d8 100644 (file)
@@ -1471,8 +1471,7 @@ nv50_disp_intr_unk20_2(struct nv50_disp_priv *priv, int head)
                        break;
                }
 
-               nouveau_dp_train(&priv->base, priv->sor.dp,
-                                &outp->info, head, datarate);
+               nouveau_dp_train((void *)outp, datarate);
        }
 
        exec_clkcmp(priv, head, 0, pclk, &conf);
@@ -1551,8 +1550,7 @@ nv50_disp_intr_unk40_0(struct nv50_disp_priv *priv, int head)
                        break;
                }
 
-               nouveau_dp_train(&priv->base, priv->pior.dp,
-                                &outp->info, head, datarate);
+               nouveau_dp_train((void *)outp, datarate);
        }
 }
 
@@ -1665,7 +1663,6 @@ nv50_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        priv->dac.sense = nv50_dac_sense;
        priv->sor.power = nv50_sor_power;
        priv->pior.power = nv50_pior_power;
-       priv->pior.dp = &nv50_pior_dp_func;
        return 0;
 }
 
index d5468a61f5e0902078149b15dc2d024975cfcc3e..67ad3f1f829cbf9f6738b670547e3eadf1ee2882 100644 (file)
@@ -45,13 +45,11 @@ struct nv50_disp_priv {
                int (*hda_eld)(struct nv50_disp_priv *, int sor, u8 *, u32);
                int (*hdmi)(struct nv50_disp_priv *, int head, int sor, u32);
                u32 lvdsconf;
-               const struct nouveau_dp_func *dp;
        } sor;
        struct {
                int nr;
                int (*power)(struct nv50_disp_priv *, int ext, u32 data);
                u8 type[3];
-               const struct nouveau_dp_func *dp;
        } pior;
 };
 
index 436f0a5eb46dc09e2be7c1717d6c8862e6a3f059..1cc62e4346833ee02f3b92b74087f9549e6642e2 100644 (file)
@@ -264,7 +264,6 @@ nv84_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        priv->sor.power = nv50_sor_power;
        priv->sor.hdmi = nv84_hdmi_ctrl;
        priv->pior.power = nv50_pior_power;
-       priv->pior.dp = &nv50_pior_dp_func;
        return 0;
 }
 
index 14f53143b81b2bd9584d45f4cea6f9350fa3dd91..240b69a89b7b8b386ae8c482d1fff83bd539627d 100644 (file)
@@ -122,9 +122,7 @@ nv94_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        priv->dac.sense = nv50_dac_sense;
        priv->sor.power = nv50_sor_power;
        priv->sor.hdmi = nv84_hdmi_ctrl;
-       priv->sor.dp = &nv94_sor_dp_func;
        priv->pior.power = nv50_pior_power;
-       priv->pior.dp = &nv50_pior_dp_func;
        return 0;
 }
 
index b8926200baa751e460720eb9c9bec6e2ffa9e66c..6237a9a36f709cf6cd4f503049373c02aec0eb38 100644 (file)
@@ -126,7 +126,6 @@ nva0_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        priv->sor.power = nv50_sor_power;
        priv->sor.hdmi = nv84_hdmi_ctrl;
        priv->pior.power = nv50_pior_power;
-       priv->pior.dp = &nv50_pior_dp_func;
        return 0;
 }
 
index aae561ff838a328d8d81a7bb69c8a16da321f608..705c6784fb68e5cf25a08388dae8f247cd8b0290 100644 (file)
@@ -96,9 +96,7 @@ nva3_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        priv->sor.power = nv50_sor_power;
        priv->sor.hda_eld = nva3_hda_eld;
        priv->sor.hdmi = nva3_hdmi_ctrl;
-       priv->sor.dp = &nv94_sor_dp_func;
        priv->pior.power = nv50_pior_power;
-       priv->pior.dp = &nv50_pior_dp_func;
        return 0;
 }
 
index 27ec9954a70bb80a8ae6dfe241804f40b2d8931b..77e7ade11af52e3aba9be8bae80f03ea8288ee97 100644 (file)
@@ -1149,8 +1149,7 @@ nvd0_disp_intr_unk2_2(struct nv50_disp_priv *priv, int head)
                        break;
                }
 
-               nouveau_dp_train(&priv->base, priv->sor.dp,
-                                &outp->info, head, pclk);
+               nouveau_dp_train((void *)outp, pclk);
        }
 
        exec_clkcmp(priv, head, 0, pclk, &conf);
@@ -1360,7 +1359,6 @@ nvd0_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        priv->sor.power = nv50_sor_power;
        priv->sor.hda_eld = nvd0_hda_eld;
        priv->sor.hdmi = nvd0_hdmi_ctrl;
-       priv->sor.dp = &nvd0_sor_dp_func;
        return 0;
 }
 
index 90f79be94bd79c66fb05ae5fbb2a42ba0f5c3c7c..11328e3f5df1140472d396d4e346958d86a211fb 100644 (file)
@@ -246,7 +246,6 @@ nve0_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        priv->sor.power = nv50_sor_power;
        priv->sor.hda_eld = nvd0_hda_eld;
        priv->sor.hdmi = nvd0_hdmi_ctrl;
-       priv->sor.dp = &nvd0_sor_dp_func;
        return 0;
 }
 
index 25a18dffcb44e9bd0cc5b29f60004134fafcc8d1..104388081d7329e9bd636c0539a820b1a79917c0 100644 (file)
@@ -81,7 +81,6 @@ nvf0_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        priv->sor.power = nv50_sor_power;
        priv->sor.hda_eld = nvd0_hda_eld;
        priv->sor.hdmi = nvd0_hdmi_ctrl;
-       priv->sor.dp = &nvd0_sor_dp_func;
        return 0;
 }
 
index 228b5d8456404a79db7f94e14c7dc71c993ce6a0..ab328dcad041b7fabafdd71fa4b6ef49d6e2d029 100644 (file)
@@ -48,6 +48,11 @@ int  _nvkm_output_dp_fini(struct nouveau_object *, bool);
 
 struct nvkm_output_dp_impl {
        struct nvkm_output_impl base;
+       int (*pattern)(struct nvkm_output_dp *, int);
+       int (*lnk_ctl)(struct nvkm_output_dp *, int nr, int bw, bool ef);
+       int (*drv_ctl)(struct nvkm_output_dp *, int ln, int vs, int pe, int pc);
 };
 
+int nouveau_dp_train(struct nvkm_output_dp *, u32 rate);
+
 #endif
index 2c1eacd8019a970f2f69e56ca6c165f161f63fd7..491e4d83b9210bad8a56db7b71d622e3796a7078 100644 (file)
@@ -70,70 +70,33 @@ nv50_pior_tmds_impl = {
  * DisplayPort
  *****************************************************************************/
 
-static struct nouveau_i2c_port *
-nv50_pior_dp_find(struct nouveau_disp *disp, struct dcb_output *outp)
-{
-       struct nouveau_i2c *i2c = nouveau_i2c(disp);
-       return i2c->find_type(i2c, NV_I2C_TYPE_EXTAUX(outp->extdev));
-}
-
 static int
-nv50_pior_dp_pattern(struct nouveau_disp *disp, struct dcb_output *outp,
-                    int head, int pattern)
+nv50_pior_dp_pattern(struct nvkm_output_dp *outp, int pattern)
 {
-       struct nouveau_i2c_port *port;
-       int ret = -EINVAL;
-
-       port = nv50_pior_dp_find(disp, outp);
-       if (port) {
-               if (port->func->pattern)
-                       ret = port->func->pattern(port, pattern);
-               else
-                       ret = 0;
-       }
-
-       return ret;
+       struct nouveau_i2c_port *port = outp->base.edid;
+       if (port && port->func->pattern)
+               return port->func->pattern(port, pattern);
+       return port ? 0 : -ENODEV;
 }
 
 static int
-nv50_pior_dp_lnk_ctl(struct nouveau_disp *disp, struct dcb_output *outp,
-                    int head, int lane_nr, int link_bw, bool enh)
+nv50_pior_dp_lnk_ctl(struct nvkm_output_dp *outp, int nr, int bw, bool ef)
 {
-       struct nouveau_i2c_port *port;
-       int ret = -EINVAL;
-
-       port = nv50_pior_dp_find(disp, outp);
+       struct nouveau_i2c_port *port = outp->base.edid;
        if (port && port->func->lnk_ctl)
-               ret = port->func->lnk_ctl(port, lane_nr, link_bw, enh);
-
-       return ret;
+               return port->func->lnk_ctl(port, nr, bw, ef);
+       return port ? 0 : -ENODEV;
 }
 
 static int
-nv50_pior_dp_drv_ctl(struct nouveau_disp *disp, struct dcb_output *outp,
-                    int head, int lane, int vsw, int pre)
+nv50_pior_dp_drv_ctl(struct nvkm_output_dp *outp, int ln, int vs, int pe, int pc)
 {
-       struct nouveau_i2c_port *port;
-       int ret = -EINVAL;
-
-       port = nv50_pior_dp_find(disp, outp);
-       if (port) {
-               if (port->func->drv_ctl)
-                       ret = port->func->drv_ctl(port, lane, vsw, pre);
-               else
-                       ret = 0;
-       }
-
-       return ret;
+       struct nouveau_i2c_port *port = outp->base.edid;
+       if (port && port->func->drv_ctl)
+               return port->func->drv_ctl(port, ln, vs, pe);
+       return port ? 0 : -ENODEV;
 }
 
-const struct nouveau_dp_func
-nv50_pior_dp_func = {
-       .pattern = nv50_pior_dp_pattern,
-       .lnk_ctl = nv50_pior_dp_lnk_ctl,
-       .drv_ctl = nv50_pior_dp_drv_ctl,
-};
-
 static int
 nv50_pior_dp_ctor(struct nouveau_object *parent,
                  struct nouveau_object *engine,
@@ -163,6 +126,9 @@ nv50_pior_dp_impl = {
                .init = _nvkm_output_dp_init,
                .fini = _nvkm_output_dp_fini,
        },
+       .pattern = nv50_pior_dp_pattern,
+       .lnk_ctl = nv50_pior_dp_lnk_ctl,
+       .drv_ctl = nv50_pior_dp_drv_ctl,
 };
 
 /******************************************************************************
index ca551eabc1c9350072dcb7239cdf9d85bbcdf93e..5ee9a12be4463eb1f26cec3c6b8c5e0859a9b741 100644 (file)
 #include "outpdp.h"
 
 static inline u32
-nv94_sor_soff(struct dcb_output *outp)
+nv94_sor_soff(struct nvkm_output_dp *outp)
 {
-       return (ffs(outp->or) - 1) * 0x800;
+       return (ffs(outp->base.info.or) - 1) * 0x800;
 }
 
 static inline u32
-nv94_sor_loff(struct dcb_output *outp)
+nv94_sor_loff(struct nvkm_output_dp *outp)
 {
-       return nv94_sor_soff(outp) + !(outp->sorconf.link & 1) * 0x80;
+       return nv94_sor_soff(outp) + !(outp->base.info.sorconf.link & 1) * 0x80;
 }
 
 static inline u32
@@ -56,20 +56,18 @@ nv94_sor_dp_lane_map(struct nv50_disp_priv *priv, u8 lane)
 }
 
 static int
-nv94_sor_dp_pattern(struct nouveau_disp *disp, struct dcb_output *outp,
-                   int head, int pattern)
+nv94_sor_dp_pattern(struct nvkm_output_dp *outp, int pattern)
 {
-       struct nv50_disp_priv *priv = (void *)disp;
+       struct nv50_disp_priv *priv = (void *)nouveau_disp(outp);
        const u32 loff = nv94_sor_loff(outp);
        nv_mask(priv, 0x61c10c + loff, 0x0f000000, pattern << 24);
        return 0;
 }
 
 static int
-nv94_sor_dp_lnk_ctl(struct nouveau_disp *disp, struct dcb_output *outp,
-                   int head, int link_nr, int link_bw, bool enh_frame)
+nv94_sor_dp_lnk_ctl(struct nvkm_output_dp *outp, int nr, int bw, bool ef)
 {
-       struct nv50_disp_priv *priv = (void *)disp;
+       struct nv50_disp_priv *priv = (void *)nouveau_disp(outp);
        const u32 soff = nv94_sor_soff(outp);
        const u32 loff = nv94_sor_loff(outp);
        u32 dpctrl = 0x00000000;
@@ -77,13 +75,13 @@ nv94_sor_dp_lnk_ctl(struct nouveau_disp *disp, struct dcb_output *outp,
        u32 lane = 0;
        int i;
 
-       dpctrl |= ((1 << link_nr) - 1) << 16;
-       if (enh_frame)
+       dpctrl |= ((1 << nr) - 1) << 16;
+       if (ef)
                dpctrl |= 0x00004000;
-       if (link_bw > 0x06)
+       if (bw > 0x06)
                clksor |= 0x00040000;
 
-       for (i = 0; i < link_nr; i++)
+       for (i = 0; i < nr; i++)
                lane |= 1 << (nv94_sor_dp_lane_map(priv, i) >> 3);
 
        nv_mask(priv, 0x614300 + soff, 0x000c0000, clksor);
@@ -93,24 +91,24 @@ nv94_sor_dp_lnk_ctl(struct nouveau_disp *disp, struct dcb_output *outp,
 }
 
 static int
-nv94_sor_dp_drv_ctl(struct nouveau_disp *disp, struct dcb_output *outp,
-                   int head, int lane, int swing, int preem)
+nv94_sor_dp_drv_ctl(struct nvkm_output_dp *outp, int ln, int vs, int pe, int pc)
 {
-       struct nouveau_bios *bios = nouveau_bios(disp);
-       struct nv50_disp_priv *priv = (void *)disp;
-       const u32 shift = nv94_sor_dp_lane_map(priv, lane);
+       struct nv50_disp_priv *priv = (void *)nouveau_disp(outp);
+       struct nouveau_bios *bios = nouveau_bios(priv);
+       const u32 shift = nv94_sor_dp_lane_map(priv, ln);
        const u32 loff = nv94_sor_loff(outp);
        u32 addr, data[3];
        u8  ver, hdr, cnt, len;
        struct nvbios_dpout info;
        struct nvbios_dpcfg ocfg;
 
-       addr = nvbios_dpout_match(bios, outp->hasht, outp->hashm,
+       addr = nvbios_dpout_match(bios, outp->base.info.hasht,
+                                       outp->base.info.hashm,
                                 &ver, &hdr, &cnt, &len, &info);
        if (!addr)
                return -ENODEV;
 
-       addr = nvbios_dpcfg_match(bios, addr, 0, swing, preem,
+       addr = nvbios_dpcfg_match(bios, addr, 0, vs, pe,
                                 &ver, &hdr, &cnt, &len, &ocfg);
        if (!addr)
                return -EINVAL;
@@ -124,13 +122,6 @@ nv94_sor_dp_drv_ctl(struct nouveau_disp *disp, struct dcb_output *outp,
        return 0;
 }
 
-const struct nouveau_dp_func
-nv94_sor_dp_func = {
-       .pattern = nv94_sor_dp_pattern,
-       .lnk_ctl = nv94_sor_dp_lnk_ctl,
-       .drv_ctl = nv94_sor_dp_drv_ctl,
-};
-
 struct nvkm_output_dp_impl
 nv94_sor_dp_impl = {
        .base.base.handle = DCB_OUTPUT_DP,
@@ -140,4 +131,7 @@ nv94_sor_dp_impl = {
                .init = _nvkm_output_dp_init,
                .fini = _nvkm_output_dp_fini,
        },
+       .pattern = nv94_sor_dp_pattern,
+       .lnk_ctl = nv94_sor_dp_lnk_ctl,
+       .drv_ctl = nv94_sor_dp_drv_ctl,
 };
index ffd4531d81bb3ffd345ace6768d1d071a6b42010..c3120a7620701cdf6a95e43569c779765f87edf2 100644 (file)
 #include "nv50.h"
 
 static inline u32
-nvd0_sor_soff(struct dcb_output *outp)
+nvd0_sor_soff(struct nvkm_output_dp *outp)
 {
-       return (ffs(outp->or) - 1) * 0x800;
+       return (ffs(outp->base.info.or) - 1) * 0x800;
 }
 
 static inline u32
-nvd0_sor_loff(struct dcb_output *outp)
+nvd0_sor_loff(struct nvkm_output_dp *outp)
 {
-       return nvd0_sor_soff(outp) + !(outp->sorconf.link & 1) * 0x80;
+       return nvd0_sor_soff(outp) + !(outp->base.info.sorconf.link & 1) * 0x80;
 }
 
 static inline u32
@@ -52,20 +52,18 @@ nvd0_sor_dp_lane_map(struct nv50_disp_priv *priv, u8 lane)
 }
 
 static int
-nvd0_sor_dp_pattern(struct nouveau_disp *disp, struct dcb_output *outp,
-                   int head, int pattern)
+nvd0_sor_dp_pattern(struct nvkm_output_dp *outp, int pattern)
 {
-       struct nv50_disp_priv *priv = (void *)disp;
+       struct nv50_disp_priv *priv = (void *)nouveau_disp(outp);
        const u32 loff = nvd0_sor_loff(outp);
        nv_mask(priv, 0x61c110 + loff, 0x0f0f0f0f, 0x01010101 * pattern);
        return 0;
 }
 
 static int
-nvd0_sor_dp_lnk_ctl(struct nouveau_disp *disp, struct dcb_output *outp,
-                   int head, int link_nr, int link_bw, bool enh_frame)
+nvd0_sor_dp_lnk_ctl(struct nvkm_output_dp *outp, int nr, int bw, bool ef)
 {
-       struct nv50_disp_priv *priv = (void *)disp;
+       struct nv50_disp_priv *priv = (void *)nouveau_disp(outp);
        const u32 soff = nvd0_sor_soff(outp);
        const u32 loff = nvd0_sor_loff(outp);
        u32 dpctrl = 0x00000000;
@@ -73,12 +71,12 @@ nvd0_sor_dp_lnk_ctl(struct nouveau_disp *disp, struct dcb_output *outp,
        u32 lane = 0;
        int i;
 
-       clksor |= link_bw << 18;
-       dpctrl |= ((1 << link_nr) - 1) << 16;
-       if (enh_frame)
+       clksor |= bw << 18;
+       dpctrl |= ((1 << nr) - 1) << 16;
+       if (ef)
                dpctrl |= 0x00004000;
 
-       for (i = 0; i < link_nr; i++)
+       for (i = 0; i < nr; i++)
                lane |= 1 << (nvd0_sor_dp_lane_map(priv, i) >> 3);
 
        nv_mask(priv, 0x612300 + soff, 0x007c0000, clksor);
@@ -88,24 +86,24 @@ nvd0_sor_dp_lnk_ctl(struct nouveau_disp *disp, struct dcb_output *outp,
 }
 
 static int
-nvd0_sor_dp_drv_ctl(struct nouveau_disp *disp, struct dcb_output *outp,
-                   int head, int lane, int swing, int preem)
+nvd0_sor_dp_drv_ctl(struct nvkm_output_dp *outp, int ln, int vs, int pe, int pc)
 {
-       struct nouveau_bios *bios = nouveau_bios(disp);
-       struct nv50_disp_priv *priv = (void *)disp;
-       const u32 shift = nvd0_sor_dp_lane_map(priv, lane);
+       struct nv50_disp_priv *priv = (void *)nouveau_disp(outp);
+       struct nouveau_bios *bios = nouveau_bios(priv);
+       const u32 shift = nvd0_sor_dp_lane_map(priv, ln);
        const u32 loff = nvd0_sor_loff(outp);
        u32 addr, data[3];
        u8  ver, hdr, cnt, len;
        struct nvbios_dpout info;
        struct nvbios_dpcfg ocfg;
 
-       addr = nvbios_dpout_match(bios, outp->hasht, outp->hashm,
+       addr = nvbios_dpout_match(bios, outp->base.info.hasht,
+                                       outp->base.info.hashm,
                                 &ver, &hdr, &cnt, &len, &info);
        if (!addr)
                return -ENODEV;
 
-       addr = nvbios_dpcfg_match(bios, addr, 0, swing, preem,
+       addr = nvbios_dpcfg_match(bios, addr, 0, vs, pe,
                                 &ver, &hdr, &cnt, &len, &ocfg);
        if (!addr)
                return -EINVAL;
@@ -120,13 +118,6 @@ nvd0_sor_dp_drv_ctl(struct nouveau_disp *disp, struct dcb_output *outp,
        return 0;
 }
 
-const struct nouveau_dp_func
-nvd0_sor_dp_func = {
-       .pattern = nvd0_sor_dp_pattern,
-       .lnk_ctl = nvd0_sor_dp_lnk_ctl,
-       .drv_ctl = nvd0_sor_dp_drv_ctl,
-};
-
 struct nvkm_output_dp_impl
 nvd0_sor_dp_impl = {
        .base.base.handle = DCB_OUTPUT_DP,
@@ -136,4 +127,7 @@ nvd0_sor_dp_impl = {
                .init = _nvkm_output_dp_init,
                .fini = _nvkm_output_dp_fini,
        },
+       .pattern = nvd0_sor_dp_pattern,
+       .lnk_ctl = nvd0_sor_dp_lnk_ctl,
+       .drv_ctl = nvd0_sor_dp_drv_ctl,
 };