aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2012-11-15 03:56:02 -0500
committerBen Skeggs <bskeggs@redhat.com>2012-11-28 18:57:53 -0500
commit6c8e4633d351f6f794c8a5c03f19e8d5a25f9639 (patch)
treec7a834aed353c7dfc2e34e71c4dda40a51b48318 /drivers/gpu/drm
parentb6e4ad200a726a32c7083f491383713bc8680f86 (diff)
drm/nouveau/dp: move core link training calls to common code
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'drivers/gpu/drm')
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_dp.c34
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_encoder.h2
-rw-r--r--drivers/gpu/drm/nouveau/nv50_sor.c44
-rw-r--r--drivers/gpu/drm/nouveau/nvd0_display.c44
4 files changed, 30 insertions, 94 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_dp.c b/drivers/gpu/drm/nouveau/nouveau_dp.c
index 978a108ba7a..e3f6550ae77 100644
--- a/drivers/gpu/drm/nouveau/nouveau_dp.c
+++ b/drivers/gpu/drm/nouveau/nouveau_dp.c
@@ -30,6 +30,8 @@
30#include "nouveau_encoder.h" 30#include "nouveau_encoder.h"
31#include "nouveau_crtc.h" 31#include "nouveau_crtc.h"
32 32
33#include <core/class.h>
34
33#include <subdev/gpio.h> 35#include <subdev/gpio.h>
34#include <subdev/i2c.h> 36#include <subdev/i2c.h>
35 37
@@ -83,7 +85,7 @@ nouveau_dp_bios_data(struct drm_device *dev, struct dcb_output *dcb, u8 **entry)
83 *****************************************************************************/ 85 *****************************************************************************/
84struct dp_state { 86struct dp_state {
85 struct nouveau_i2c_port *auxch; 87 struct nouveau_i2c_port *auxch;
86 struct dp_train_func *func; 88 struct nouveau_object *core;
87 struct dcb_output *dcb; 89 struct dcb_output *dcb;
88 int crtc; 90 int crtc;
89 u8 *dpcd; 91 u8 *dpcd;
@@ -97,13 +99,20 @@ static void
97dp_set_link_config(struct drm_device *dev, struct dp_state *dp) 99dp_set_link_config(struct drm_device *dev, struct dp_state *dp)
98{ 100{
99 struct nouveau_drm *drm = nouveau_drm(dev); 101 struct nouveau_drm *drm = nouveau_drm(dev);
102 struct dcb_output *dcb = dp->dcb;
103 const u32 or = ffs(dcb->or) - 1, link = !(dcb->sorconf.link & 1);
104 const u32 moff = (dp->crtc << 3) | (link << 2) | or;
100 u8 sink[2]; 105 u8 sink[2];
106 u32 data;
101 107
102 NV_DEBUG(drm, "%d lanes at %d KB/s\n", dp->link_nr, dp->link_bw); 108 NV_DEBUG(drm, "%d lanes at %d KB/s\n", dp->link_nr, dp->link_bw);
103 109
104 /* set desired link configuration on the source */ 110 /* set desired link configuration on the source */
105 dp->func->link_set(dev, dp->dcb, dp->crtc, dp->link_nr, dp->link_bw, 111 data = ((dp->link_bw / 27000) << 8) | dp->link_nr;
106 dp->dpcd[2] & DP_ENHANCED_FRAME_CAP); 112 if (dp->dpcd[2] & DP_ENHANCED_FRAME_CAP)
113 data |= NV94_DISP_SOR_DP_LNKCTL_FRAME_ENH;
114
115 nv_call(dp->core, NV94_DISP_SOR_DP_LNKCTL + moff, data);
107 116
108 /* inform the sink of the new configuration */ 117 /* inform the sink of the new configuration */
109 sink[0] = dp->link_bw / 27000; 118 sink[0] = dp->link_bw / 27000;
@@ -118,11 +127,14 @@ static void
118dp_set_training_pattern(struct drm_device *dev, struct dp_state *dp, u8 pattern) 127dp_set_training_pattern(struct drm_device *dev, struct dp_state *dp, u8 pattern)
119{ 128{
120 struct nouveau_drm *drm = nouveau_drm(dev); 129 struct nouveau_drm *drm = nouveau_drm(dev);
130 struct dcb_output *dcb = dp->dcb;
131 const u32 or = ffs(dcb->or) - 1, link = !(dcb->sorconf.link & 1);
132 const u32 moff = (dp->crtc << 3) | (link << 2) | or;
121 u8 sink_tp; 133 u8 sink_tp;
122 134
123 NV_DEBUG(drm, "training pattern %d\n", pattern); 135 NV_DEBUG(drm, "training pattern %d\n", pattern);
124 136
125 dp->func->train_set(dev, dp->dcb, pattern); 137 nv_call(dp->core, NV94_DISP_SOR_DP_TRAIN + moff, pattern);
126 138
127 nv_rdaux(dp->auxch, DP_TRAINING_PATTERN_SET, &sink_tp, 1); 139 nv_rdaux(dp->auxch, DP_TRAINING_PATTERN_SET, &sink_tp, 1);
128 sink_tp &= ~DP_TRAINING_PATTERN_MASK; 140 sink_tp &= ~DP_TRAINING_PATTERN_MASK;
@@ -134,6 +146,9 @@ static int
134dp_link_train_commit(struct drm_device *dev, struct dp_state *dp) 146dp_link_train_commit(struct drm_device *dev, struct dp_state *dp)
135{ 147{
136 struct nouveau_drm *drm = nouveau_drm(dev); 148 struct nouveau_drm *drm = nouveau_drm(dev);
149 struct dcb_output *dcb = dp->dcb;
150 const u32 or = ffs(dcb->or) - 1, link = !(dcb->sorconf.link & 1);
151 const u32 moff = (dp->crtc << 3) | (link << 2) | or;
137 int i; 152 int i;
138 153
139 for (i = 0; i < dp->link_nr; i++) { 154 for (i = 0; i < dp->link_nr; i++) {
@@ -148,7 +163,8 @@ dp_link_train_commit(struct drm_device *dev, struct dp_state *dp)
148 dp->conf[i] |= DP_TRAIN_MAX_PRE_EMPHASIS_REACHED; 163 dp->conf[i] |= DP_TRAIN_MAX_PRE_EMPHASIS_REACHED;
149 164
150 NV_DEBUG(drm, "config lane %d %02x\n", i, dp->conf[i]); 165 NV_DEBUG(drm, "config lane %d %02x\n", i, dp->conf[i]);
151 dp->func->train_adj(dev, dp->dcb, i, lvsw, lpre); 166
167 nv_call(dp->core, NV94_DISP_SOR_DP_DRVCTL(i) + moff, (lvsw << 8) | lpre);
152 } 168 }
153 169
154 return nv_wraux(dp->auxch, DP_TRAINING_LANE0_SET, dp->conf, 4); 170 return nv_wraux(dp->auxch, DP_TRAINING_LANE0_SET, dp->conf, 4);
@@ -286,7 +302,7 @@ dp_link_train_fini(struct drm_device *dev, struct dp_state *dp)
286 302
287static bool 303static bool
288nouveau_dp_link_train(struct drm_encoder *encoder, u32 datarate, 304nouveau_dp_link_train(struct drm_encoder *encoder, u32 datarate,
289 struct dp_train_func *func) 305 struct nouveau_object *core)
290{ 306{
291 struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); 307 struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
292 struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc); 308 struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc);
@@ -304,7 +320,7 @@ nouveau_dp_link_train(struct drm_encoder *encoder, u32 datarate,
304 if (!dp.auxch) 320 if (!dp.auxch)
305 return false; 321 return false;
306 322
307 dp.func = func; 323 dp.core = core;
308 dp.dcb = nv_encoder->dcb; 324 dp.dcb = nv_encoder->dcb;
309 dp.crtc = nv_crtc->index; 325 dp.crtc = nv_crtc->index;
310 dp.dpcd = nv_encoder->dp.dpcd; 326 dp.dpcd = nv_encoder->dp.dpcd;
@@ -365,7 +381,7 @@ nouveau_dp_link_train(struct drm_encoder *encoder, u32 datarate,
365 381
366void 382void
367nouveau_dp_dpms(struct drm_encoder *encoder, int mode, u32 datarate, 383nouveau_dp_dpms(struct drm_encoder *encoder, int mode, u32 datarate,
368 struct dp_train_func *func) 384 struct nouveau_object *core)
369{ 385{
370 struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); 386 struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
371 struct nouveau_drm *drm = nouveau_drm(encoder->dev); 387 struct nouveau_drm *drm = nouveau_drm(encoder->dev);
@@ -385,7 +401,7 @@ nouveau_dp_dpms(struct drm_encoder *encoder, int mode, u32 datarate,
385 nv_wraux(auxch, DP_SET_POWER, &status, 1); 401 nv_wraux(auxch, DP_SET_POWER, &status, 1);
386 402
387 if (mode == DRM_MODE_DPMS_ON) 403 if (mode == DRM_MODE_DPMS_ON)
388 nouveau_dp_link_train(encoder, datarate, func); 404 nouveau_dp_link_train(encoder, datarate, core);
389} 405}
390 406
391static void 407static void
diff --git a/drivers/gpu/drm/nouveau/nouveau_encoder.h b/drivers/gpu/drm/nouveau/nouveau_encoder.h
index 6a17bf2ba9a..06c1bb3a2f2 100644
--- a/drivers/gpu/drm/nouveau/nouveau_encoder.h
+++ b/drivers/gpu/drm/nouveau/nouveau_encoder.h
@@ -93,7 +93,7 @@ get_slave_funcs(struct drm_encoder *enc)
93/* nouveau_dp.c */ 93/* nouveau_dp.c */
94bool nouveau_dp_detect(struct drm_encoder *); 94bool nouveau_dp_detect(struct drm_encoder *);
95void nouveau_dp_dpms(struct drm_encoder *, int mode, u32 datarate, 95void nouveau_dp_dpms(struct drm_encoder *, int mode, u32 datarate,
96 struct dp_train_func *); 96 struct nouveau_object *);
97u8 *nouveau_dp_bios_data(struct drm_device *, struct dcb_output *, u8 **); 97u8 *nouveau_dp_bios_data(struct drm_device *, struct dcb_output *, u8 **);
98 98
99struct nouveau_connector * 99struct nouveau_connector *
diff --git a/drivers/gpu/drm/nouveau/nv50_sor.c b/drivers/gpu/drm/nouveau/nv50_sor.c
index ae4f24a0a54..5499c23cb79 100644
--- a/drivers/gpu/drm/nouveau/nv50_sor.c
+++ b/drivers/gpu/drm/nouveau/nv50_sor.c
@@ -41,39 +41,6 @@
41#include <subdev/timer.h> 41#include <subdev/timer.h>
42 42
43static void 43static void
44nv50_sor_dp_train_set(struct drm_device *dev, struct dcb_output *dcb, u8 pattern)
45{
46 struct nv50_display *disp = nv50_display(dev);
47 const u32 or = ffs(dcb->or) - 1, link = !(dcb->sorconf.link & 1);
48 const u32 moff = (link << 2) | or;
49 nv_call(disp->core, NV94_DISP_SOR_DP_TRAIN + moff, pattern);
50}
51
52static void
53nv50_sor_dp_train_adj(struct drm_device *dev, struct dcb_output *dcb,
54 u8 lane, u8 swing, u8 preem)
55{
56 struct nv50_display *disp = nv50_display(dev);
57 const u32 or = ffs(dcb->or) - 1, link = !(dcb->sorconf.link & 1);
58 const u32 moff = (link << 2) | or;
59 const u32 data = (swing << 8) | preem;
60 nv_call(disp->core, NV94_DISP_SOR_DP_DRVCTL(lane) + moff, data);
61}
62
63static void
64nv50_sor_dp_link_set(struct drm_device *dev, struct dcb_output *dcb, int crtc,
65 int link_nr, u32 link_bw, bool enhframe)
66{
67 struct nv50_display *disp = nv50_display(dev);
68 const u32 or = ffs(dcb->or) - 1, link = !(dcb->sorconf.link & 1);
69 const u32 moff = (crtc << 3) | (link << 2) | or;
70 u32 data = ((link_bw / 27000) << 8) | link_nr;
71 if (enhframe)
72 data |= NV94_DISP_SOR_DP_LNKCTL_FRAME_ENH;
73 nv_call(disp->core, NV94_DISP_SOR_DP_LNKCTL + moff, data);
74}
75
76static void
77nv50_sor_disconnect(struct drm_encoder *encoder) 44nv50_sor_disconnect(struct drm_encoder *encoder)
78{ 45{
79 struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); 46 struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
@@ -133,15 +100,8 @@ nv50_sor_dpms(struct drm_encoder *encoder, int mode)
133 100
134 nv_call(priv->core, NV50_DISP_SOR_PWR + or, (mode == DRM_MODE_DPMS_ON)); 101 nv_call(priv->core, NV50_DISP_SOR_PWR + or, (mode == DRM_MODE_DPMS_ON));
135 102
136 if (nv_encoder->dcb->type == DCB_OUTPUT_DP) { 103 if (nv_encoder->dcb->type == DCB_OUTPUT_DP)
137 struct dp_train_func func = { 104 nouveau_dp_dpms(encoder, mode, nv_encoder->dp.datarate, priv->core);
138 .link_set = nv50_sor_dp_link_set,
139 .train_set = nv50_sor_dp_train_set,
140 .train_adj = nv50_sor_dp_train_adj
141 };
142
143 nouveau_dp_dpms(encoder, mode, nv_encoder->dp.datarate, &func);
144 }
145} 105}
146 106
147static void 107static void
diff --git a/drivers/gpu/drm/nouveau/nvd0_display.c b/drivers/gpu/drm/nouveau/nvd0_display.c
index 518f1a5342a..98c93513189 100644
--- a/drivers/gpu/drm/nouveau/nvd0_display.c
+++ b/drivers/gpu/drm/nouveau/nvd0_display.c
@@ -1306,39 +1306,6 @@ nvd0_hdmi_disconnect(struct drm_encoder *encoder)
1306 * SOR 1306 * SOR
1307 *****************************************************************************/ 1307 *****************************************************************************/
1308static void 1308static void
1309nvd0_sor_dp_train_set(struct drm_device *dev, struct dcb_output *dcb, u8 pattern)
1310{
1311 struct nvd0_disp *disp = nvd0_disp(dev);
1312 const u32 or = ffs(dcb->or) - 1, link = !(dcb->sorconf.link & 1);
1313 const u32 moff = (link << 2) | or;
1314 nv_call(disp->core, NV94_DISP_SOR_DP_TRAIN + moff, pattern);
1315}
1316
1317static void
1318nvd0_sor_dp_train_adj(struct drm_device *dev, struct dcb_output *dcb,
1319 u8 lane, u8 swing, u8 preem)
1320{
1321 struct nvd0_disp *disp = nvd0_disp(dev);
1322 const u32 or = ffs(dcb->or) - 1, link = !(dcb->sorconf.link & 1);
1323 const u32 moff = (link << 2) | or;
1324 const u32 data = (swing << 8) | preem;
1325 nv_call(disp->core, NV94_DISP_SOR_DP_DRVCTL(lane) + moff, data);
1326}
1327
1328static void
1329nvd0_sor_dp_link_set(struct drm_device *dev, struct dcb_output *dcb, int crtc,
1330 int link_nr, u32 link_bw, bool enhframe)
1331{
1332 struct nvd0_disp *disp = nvd0_disp(dev);
1333 const u32 or = ffs(dcb->or) - 1, link = !(dcb->sorconf.link & 1);
1334 const u32 moff = (crtc << 3) | (link << 2) | or;
1335 u32 data = ((link_bw / 27000) << 8) | link_nr;
1336 if (enhframe)
1337 data |= NV94_DISP_SOR_DP_LNKCTL_FRAME_ENH;
1338 nv_call(disp->core, NV94_DISP_SOR_DP_LNKCTL + moff, data);
1339}
1340
1341static void
1342nvd0_sor_dpms(struct drm_encoder *encoder, int mode) 1309nvd0_sor_dpms(struct drm_encoder *encoder, int mode)
1343{ 1310{
1344 struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); 1311 struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
@@ -1365,15 +1332,8 @@ nvd0_sor_dpms(struct drm_encoder *encoder, int mode)
1365 1332
1366 nv_call(disp->core, NV50_DISP_SOR_PWR + or, (mode == DRM_MODE_DPMS_ON)); 1333 nv_call(disp->core, NV50_DISP_SOR_PWR + or, (mode == DRM_MODE_DPMS_ON));
1367 1334
1368 if (nv_encoder->dcb->type == DCB_OUTPUT_DP) { 1335 if (nv_encoder->dcb->type == DCB_OUTPUT_DP)
1369 struct dp_train_func func = { 1336 nouveau_dp_dpms(encoder, mode, nv_encoder->dp.datarate, disp->core);
1370 .link_set = nvd0_sor_dp_link_set,
1371 .train_set = nvd0_sor_dp_train_set,
1372 .train_adj = nvd0_sor_dp_train_adj
1373 };
1374
1375 nouveau_dp_dpms(encoder, mode, nv_encoder->dp.datarate, &func);
1376 }
1377} 1337}
1378 1338
1379static bool 1339static bool