diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/gpu/drm/nouveau/core/engine/disp/nv50.h | 10 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/core/engine/disp/nv94.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/core/engine/disp/nva3.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/core/engine/disp/nve0.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/core/engine/disp/sornv50.c | 14 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/core/engine/disp/sornv94.c | 58 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/core/include/core/class.h | 7 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_bios.c | 28 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_bios.h | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_dp.c | 105 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_encoder.h | 1 |
12 files changed, 111 insertions, 121 deletions
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.h b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.h index 3fb5920b6bed..a6bb931450f1 100644 --- a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.h +++ b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.h @@ -26,6 +26,12 @@ struct nv50_disp_priv { int (*power)(struct nv50_disp_priv *, int sor, u32 data); int (*hda_eld)(struct nv50_disp_priv *, int sor, u8 *, u32); int (*hdmi)(struct nv50_disp_priv *, int head, int sor, u32); + int (*dp_train_init)(struct nv50_disp_priv *, int sor, int link, + int head, u16 type, u16 mask, u32 data, + struct dcb_output *); + int (*dp_train_fini)(struct nv50_disp_priv *, int sor, int link, + int head, u16 type, u16 mask, u32 data, + struct dcb_output *); int (*dp_train)(struct nv50_disp_priv *, int sor, int link, u16 type, u16 mask, u32 data, struct dcb_output *); @@ -57,6 +63,10 @@ int nvd0_hdmi_ctrl(struct nv50_disp_priv *, int, int, u32); int nv50_sor_mthd(struct nouveau_object *, u32, void *, u32); int nv50_sor_power(struct nv50_disp_priv *, int, u32); +int nv94_sor_dp_train_init(struct nv50_disp_priv *, int, int, int, u16, u16, + u32, struct dcb_output *); +int nv94_sor_dp_train_fini(struct nv50_disp_priv *, int, int, int, u16, u16, + u32, struct dcb_output *); int nv94_sor_dp_train(struct nv50_disp_priv *, int, int, u16, u16, u32, struct dcb_output *); int nv94_sor_dp_lnkctl(struct nv50_disp_priv *, int, int, int, u16, u16, u32, diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nv94.c b/drivers/gpu/drm/nouveau/core/engine/disp/nv94.c index b5adcc0bc0da..ba9dfd4669a2 100644 --- a/drivers/gpu/drm/nouveau/core/engine/disp/nv94.c +++ b/drivers/gpu/drm/nouveau/core/engine/disp/nv94.c @@ -87,6 +87,8 @@ nv94_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine, priv->sor.power = nv50_sor_power; priv->sor.hdmi = nv84_hdmi_ctrl; priv->sor.dp_train = nv94_sor_dp_train; + priv->sor.dp_train_init = nv94_sor_dp_train_init; + priv->sor.dp_train_fini = nv94_sor_dp_train_fini; priv->sor.dp_lnkctl = nv94_sor_dp_lnkctl; priv->sor.dp_drvctl = nv94_sor_dp_drvctl; diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nva3.c b/drivers/gpu/drm/nouveau/core/engine/disp/nva3.c index 83ae695ac1df..e9192ca389fa 100644 --- a/drivers/gpu/drm/nouveau/core/engine/disp/nva3.c +++ b/drivers/gpu/drm/nouveau/core/engine/disp/nva3.c @@ -89,6 +89,8 @@ nva3_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine, priv->sor.hda_eld = nva3_hda_eld; priv->sor.hdmi = nva3_hdmi_ctrl; priv->sor.dp_train = nv94_sor_dp_train; + priv->sor.dp_train_init = nv94_sor_dp_train_init; + priv->sor.dp_train_fini = nv94_sor_dp_train_fini; priv->sor.dp_lnkctl = nv94_sor_dp_lnkctl; priv->sor.dp_drvctl = nv94_sor_dp_drvctl; diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c b/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c index a618f2213a14..24bcbc6a88bb 100644 --- a/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c +++ b/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c @@ -951,6 +951,8 @@ nvd0_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine, priv->sor.hda_eld = nvd0_hda_eld; priv->sor.hdmi = nvd0_hdmi_ctrl; priv->sor.dp_train = nvd0_sor_dp_train; + priv->sor.dp_train_init = nv94_sor_dp_train_init; + priv->sor.dp_train_fini = nv94_sor_dp_train_fini; priv->sor.dp_lnkctl = nvd0_sor_dp_lnkctl; priv->sor.dp_drvctl = nvd0_sor_dp_drvctl; diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nve0.c b/drivers/gpu/drm/nouveau/core/engine/disp/nve0.c index 9b83a70091f9..259537c4587e 100644 --- a/drivers/gpu/drm/nouveau/core/engine/disp/nve0.c +++ b/drivers/gpu/drm/nouveau/core/engine/disp/nve0.c @@ -72,6 +72,8 @@ nve0_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine, priv->sor.hda_eld = nvd0_hda_eld; priv->sor.hdmi = nvd0_hdmi_ctrl; priv->sor.dp_train = nvd0_sor_dp_train; + priv->sor.dp_train_init = nv94_sor_dp_train_init; + priv->sor.dp_train_fini = nv94_sor_dp_train_fini; priv->sor.dp_lnkctl = nvd0_sor_dp_lnkctl; priv->sor.dp_drvctl = nvd0_sor_dp_drvctl; diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/sornv50.c b/drivers/gpu/drm/nouveau/core/engine/disp/sornv50.c index 6fd25730a588..39b6b67732d0 100644 --- a/drivers/gpu/drm/nouveau/core/engine/disp/sornv50.c +++ b/drivers/gpu/drm/nouveau/core/engine/disp/sornv50.c @@ -80,7 +80,19 @@ nv50_sor_mthd(struct nouveau_object *object, u32 mthd, void *args, u32 size) ret = 0; break; case NV94_DISP_SOR_DP_TRAIN: - ret = priv->sor.dp_train(priv, or, link, type, mask, data, &outp); + switch (data & NV94_DISP_SOR_DP_TRAIN_OP) { + case NV94_DISP_SOR_DP_TRAIN_OP_PATTERN: + ret = priv->sor.dp_train(priv, or, link, type, mask, data, &outp); + break; + case NV94_DISP_SOR_DP_TRAIN_OP_INIT: + ret = priv->sor.dp_train_init(priv, or, link, head, type, mask, data, &outp); + break; + case NV94_DISP_SOR_DP_TRAIN_OP_FINI: + ret = priv->sor.dp_train_fini(priv, or, link, head, type, mask, data, &outp); + break; + default: + break; + } break; case NV94_DISP_SOR_DP_LNKCTL: ret = priv->sor.dp_lnkctl(priv, or, link, head, type, mask, data, &outp); diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/sornv94.c b/drivers/gpu/drm/nouveau/core/engine/disp/sornv94.c index 49bcc76261e6..f6edd009762e 100644 --- a/drivers/gpu/drm/nouveau/core/engine/disp/sornv94.c +++ b/drivers/gpu/drm/nouveau/core/engine/disp/sornv94.c @@ -43,6 +43,64 @@ nv94_sor_dp_lane_map(struct nv50_disp_priv *priv, u8 lane) } int +nv94_sor_dp_train_init(struct nv50_disp_priv *priv, int or, int link, int head, + u16 type, u16 mask, u32 data, struct dcb_output *dcbo) +{ + struct nouveau_bios *bios = nouveau_bios(priv); + struct nvbios_dpout info; + u8 ver, hdr, cnt, len; + u16 outp; + + outp = nvbios_dpout_match(bios, type, mask, &ver, &hdr, &cnt, &len, &info); + if (outp) { + struct nvbios_init init = { + .subdev = nv_subdev(priv), + .bios = bios, + .outp = dcbo, + .crtc = head, + .execute = 1, + }; + + if (data & NV94_DISP_SOR_DP_TRAIN_INIT_SPREAD_ON) + init.offset = info.script[2]; + else + init.offset = info.script[3]; + nvbios_exec(&init); + + init.offset = info.script[0]; + nvbios_exec(&init); + } + + return 0; +} + +int +nv94_sor_dp_train_fini(struct nv50_disp_priv *priv, int or, int link, int head, + u16 type, u16 mask, u32 data, struct dcb_output *dcbo) +{ + struct nouveau_bios *bios = nouveau_bios(priv); + struct nvbios_dpout info; + u8 ver, hdr, cnt, len; + u16 outp; + + outp = nvbios_dpout_match(bios, type, mask, &ver, &hdr, &cnt, &len, &info); + if (outp) { + struct nvbios_init init = { + .subdev = nv_subdev(priv), + .bios = bios, + .offset = info.script[1], + .outp = dcbo, + .crtc = head, + .execute = 1, + }; + + nvbios_exec(&init); + } + + return 0; +} + +int nv94_sor_dp_train(struct nv50_disp_priv *priv, int or, int link, u16 type, u16 mask, u32 data, struct dcb_output *info) { diff --git a/drivers/gpu/drm/nouveau/core/include/core/class.h b/drivers/gpu/drm/nouveau/core/include/core/class.h index dd060234b0b0..47c4b3a5bd3a 100644 --- a/drivers/gpu/drm/nouveau/core/include/core/class.h +++ b/drivers/gpu/drm/nouveau/core/include/core/class.h @@ -191,6 +191,13 @@ struct nve0_channel_ind_class { #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_OP 0xf0000000 +#define NV94_DISP_SOR_DP_TRAIN_OP_PATTERN 0x00000000 +#define NV94_DISP_SOR_DP_TRAIN_OP_INIT 0x10000000 +#define NV94_DISP_SOR_DP_TRAIN_OP_FINI 0x20000000 +#define NV94_DISP_SOR_DP_TRAIN_INIT_SPREAD 0x00000001 +#define NV94_DISP_SOR_DP_TRAIN_INIT_SPREAD_OFF 0x00000000 +#define NV94_DISP_SOR_DP_TRAIN_INIT_SPREAD_ON 0x00000001 #define NV94_DISP_SOR_DP_TRAIN_PATTERN 0x00000003 #define NV94_DISP_SOR_DP_TRAIN_PATTERN_DISABLED 0x00000000 #define NV94_DISP_SOR_DP_LNKCTL 0x00016040 diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.c b/drivers/gpu/drm/nouveau/nouveau_bios.c index 395d2b9372c8..865eddfa30a7 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bios.c +++ b/drivers/gpu/drm/nouveau/nouveau_bios.c @@ -624,34 +624,6 @@ int nouveau_bios_parse_lvds_table(struct drm_device *dev, int pxclk, bool *dl, b return 0; } -/* BIT 'U'/'d' table encoder subtables have hashes matching them to - * a particular set of encoders. - * - * This function returns true if a particular DCB entry matches. - */ -bool -bios_encoder_match(struct dcb_output *dcb, u32 hash) -{ - if ((hash & 0x000000f0) != (dcb->location << 4)) - return false; - if ((hash & 0x0000000f) != dcb->type) - return false; - if (!(hash & (dcb->or << 16))) - return false; - - switch (dcb->type) { - case DCB_OUTPUT_TMDS: - case DCB_OUTPUT_LVDS: - case DCB_OUTPUT_DP: - if (hash & 0x00c00000) { - if (!(hash & (dcb->sorconf.link << 22))) - return false; - } - default: - return true; - } -} - int run_tmds_table(struct drm_device *dev, struct dcb_output *dcbent, int head, int pxclk) { /* diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.h b/drivers/gpu/drm/nouveau/nouveau_bios.h index 9e364b68e603..f68c54ca422f 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bios.h +++ b/drivers/gpu/drm/nouveau/nouveau_bios.h @@ -187,6 +187,5 @@ int run_tmds_table(struct drm_device *, struct dcb_output *, int head, int pxclk); int call_lvds_script(struct drm_device *, struct dcb_output *, int head, enum LVDS_script, int pxclk); -bool bios_encoder_match(struct dcb_output *, u32 hash); #endif diff --git a/drivers/gpu/drm/nouveau/nouveau_dp.c b/drivers/gpu/drm/nouveau/nouveau_dp.c index e3f6550ae772..59838651ee8f 100644 --- a/drivers/gpu/drm/nouveau/nouveau_dp.c +++ b/drivers/gpu/drm/nouveau/nouveau_dp.c @@ -35,51 +35,6 @@ #include <subdev/gpio.h> #include <subdev/i2c.h> -u8 * -nouveau_dp_bios_data(struct drm_device *dev, struct dcb_output *dcb, u8 **entry) -{ - struct nouveau_drm *drm = nouveau_drm(dev); - struct bit_entry d; - u8 *table; - int i; - - if (bit_table(dev, 'd', &d)) { - NV_ERROR(drm, "BIT 'd' table not found\n"); - return NULL; - } - - if (d.version != 1) { - NV_ERROR(drm, "BIT 'd' table version %d unknown\n", d.version); - return NULL; - } - - table = ROMPTR(dev, d.data[0]); - if (!table) { - NV_ERROR(drm, "displayport table pointer invalid\n"); - return NULL; - } - - switch (table[0]) { - case 0x20: - case 0x21: - case 0x30: - case 0x40: - break; - default: - NV_ERROR(drm, "displayport table 0x%02x unknown\n", table[0]); - return NULL; - } - - for (i = 0; i < table[3]; i++) { - *entry = ROMPTR(dev, table[table[1] + (i * table[2])]); - if (*entry && bios_encoder_match(dcb, ROM32((*entry)[0]))) - return table; - } - - NV_ERROR(drm, "displayport encoder table not found\n"); - return NULL; -} - /****************************************************************************** * link training *****************************************************************************/ @@ -250,54 +205,27 @@ dp_link_train_eq(struct drm_device *dev, struct dp_state *dp) } static void -dp_set_downspread(struct drm_device *dev, struct dp_state *dp, bool enable) +dp_link_train_init(struct drm_device *dev, struct dp_state *dp, bool spread) { - u16 script = 0x0000; - u8 *entry, *table = nouveau_dp_bios_data(dev, dp->dcb, &entry); - if (table) { - if (table[0] >= 0x20 && table[0] <= 0x30) { - if (enable) script = ROM16(entry[12]); - else script = ROM16(entry[14]); - } else - if (table[0] == 0x40) { - if (enable) script = ROM16(entry[11]); - else script = ROM16(entry[13]); - } - } - - nouveau_bios_run_init_table(dev, script, dp->dcb, dp->crtc); -} - -static void -dp_link_train_init(struct drm_device *dev, struct dp_state *dp) -{ - u16 script = 0x0000; - u8 *entry, *table = nouveau_dp_bios_data(dev, dp->dcb, &entry); - if (table) { - if (table[0] >= 0x20 && table[0] <= 0x30) - script = ROM16(entry[6]); - else - if (table[0] == 0x40) - script = ROM16(entry[5]); - } + struct dcb_output *dcb = dp->dcb; + const u32 or = ffs(dcb->or) - 1, link = !(dcb->sorconf.link & 1); + const u32 moff = (dp->crtc << 3) | (link << 2) | or; - nouveau_bios_run_init_table(dev, script, dp->dcb, dp->crtc); + nv_call(dp->core, NV94_DISP_SOR_DP_TRAIN + moff, (spread ? + NV94_DISP_SOR_DP_TRAIN_INIT_SPREAD_ON : + NV94_DISP_SOR_DP_TRAIN_INIT_SPREAD_OFF) | + NV94_DISP_SOR_DP_TRAIN_OP_INIT); } static void dp_link_train_fini(struct drm_device *dev, struct dp_state *dp) { - u16 script = 0x0000; - u8 *entry, *table = nouveau_dp_bios_data(dev, dp->dcb, &entry); - if (table) { - if (table[0] >= 0x20 && table[0] <= 0x30) - script = ROM16(entry[8]); - else - if (table[0] == 0x40) - script = ROM16(entry[7]); - } + struct dcb_output *dcb = dp->dcb; + const u32 or = ffs(dcb->or) - 1, link = !(dcb->sorconf.link & 1); + const u32 moff = (dp->crtc << 3) | (link << 2) | or; - nouveau_bios_run_init_table(dev, script, dp->dcb, dp->crtc); + nv_call(dp->core, NV94_DISP_SOR_DP_TRAIN + moff, + NV94_DISP_SOR_DP_TRAIN_OP_FINI); } static bool @@ -334,11 +262,8 @@ nouveau_dp_link_train(struct drm_encoder *encoder, u32 datarate, */ gpio->irq(gpio, 0, nv_connector->hpd, 0xff, false); - /* enable down-spreading, if possible */ - dp_set_downspread(dev, &dp, nv_encoder->dp.dpcd[3] & 1); - - /* execute pre-train script from vbios */ - dp_link_train_init(dev, &dp); + /* enable down-spreading and execute pre-train script from vbios */ + dp_link_train_init(dev, &dp, nv_encoder->dp.dpcd[3] & 1); /* start off at highest link rate supported by encoder and display */ while (*link_bw > nv_encoder->dp.link_bw) diff --git a/drivers/gpu/drm/nouveau/nouveau_encoder.h b/drivers/gpu/drm/nouveau/nouveau_encoder.h index 06c1bb3a2f2a..6f642df67009 100644 --- a/drivers/gpu/drm/nouveau/nouveau_encoder.h +++ b/drivers/gpu/drm/nouveau/nouveau_encoder.h @@ -94,7 +94,6 @@ get_slave_funcs(struct drm_encoder *enc) bool nouveau_dp_detect(struct drm_encoder *); void nouveau_dp_dpms(struct drm_encoder *, int mode, u32 datarate, struct nouveau_object *); -u8 *nouveau_dp_bios_data(struct drm_device *, struct dcb_output *, u8 **); struct nouveau_connector * nouveau_encoder_connector_get(struct nouveau_encoder *encoder); |