aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/nouveau/nouveau_dp.c
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2012-07-10 00:36:38 -0400
committerBen Skeggs <bskeggs@redhat.com>2012-10-02 23:12:46 -0400
commit4196faa8623264b79279a06fd186654c959f2767 (patch)
treed84bb1e28744a3dfbafc1e9203a2ea1fda43eb86 /drivers/gpu/drm/nouveau/nouveau_dp.c
parente0996aea4c349ba302b63203b7d5cab6034dbdca (diff)
drm/nouveau/i2c: port to subdev interfaces
v2/v3: Ben Skeggs <bskeggs@redhat.com> - fix typo in default bus selection - fix accidental loss of destructor v4: Dmitry Eremin-Solenikov <dmitry_eremin@mentor.com> - fix typo causing incorrect default i2c port settings when no BMP data Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/nouveau/nouveau_dp.c')
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_dp.c219
1 files changed, 16 insertions, 203 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_dp.c b/drivers/gpu/drm/nouveau/nouveau_dp.c
index 63c0e827c302..9e18b35803a8 100644
--- a/drivers/gpu/drm/nouveau/nouveau_dp.c
+++ b/drivers/gpu/drm/nouveau/nouveau_dp.c
@@ -23,143 +23,13 @@
23 */ 23 */
24 24
25#include "drmP.h" 25#include "drmP.h"
26#include "drm_dp_helper.h"
26 27
27#include "nouveau_drv.h" 28#include "nouveau_drv.h"
28#include <subdev/i2c.h>
29#include "nouveau_connector.h" 29#include "nouveau_connector.h"
30#include "nouveau_encoder.h" 30#include "nouveau_encoder.h"
31#include "nouveau_crtc.h" 31#include "nouveau_crtc.h"
32 32
33/******************************************************************************
34 * aux channel util functions
35 *****************************************************************************/
36#define AUX_DBG(fmt, args...) do { \
37 if (nouveau_reg_debug & NOUVEAU_REG_DEBUG_AUXCH) { \
38 NV_PRINTK(KERN_DEBUG, dev, "AUXCH(%d): " fmt, ch, ##args); \
39 } \
40} while (0)
41#define AUX_ERR(fmt, args...) NV_ERROR(dev, "AUXCH(%d): " fmt, ch, ##args)
42
43static void
44auxch_fini(struct drm_device *dev, int ch)
45{
46 nv_mask(dev, 0x00e4e4 + (ch * 0x50), 0x00310000, 0x00000000);
47}
48
49static int
50auxch_init(struct drm_device *dev, int ch)
51{
52 const u32 unksel = 1; /* nfi which to use, or if it matters.. */
53 const u32 ureq = unksel ? 0x00100000 : 0x00200000;
54 const u32 urep = unksel ? 0x01000000 : 0x02000000;
55 u32 ctrl, timeout;
56
57 /* wait up to 1ms for any previous transaction to be done... */
58 timeout = 1000;
59 do {
60 ctrl = nv_rd32(dev, 0x00e4e4 + (ch * 0x50));
61 udelay(1);
62 if (!timeout--) {
63 AUX_ERR("begin idle timeout 0x%08x", ctrl);
64 return -EBUSY;
65 }
66 } while (ctrl & 0x03010000);
67
68 /* set some magic, and wait up to 1ms for it to appear */
69 nv_mask(dev, 0x00e4e4 + (ch * 0x50), 0x00300000, ureq);
70 timeout = 1000;
71 do {
72 ctrl = nv_rd32(dev, 0x00e4e4 + (ch * 0x50));
73 udelay(1);
74 if (!timeout--) {
75 AUX_ERR("magic wait 0x%08x\n", ctrl);
76 auxch_fini(dev, ch);
77 return -EBUSY;
78 }
79 } while ((ctrl & 0x03000000) != urep);
80
81 return 0;
82}
83
84static int
85auxch_tx(struct drm_device *dev, int ch, u8 type, u32 addr, u8 *data, u8 size)
86{
87 u32 ctrl, stat, timeout, retries;
88 u32 xbuf[4] = {};
89 int ret, i;
90
91 AUX_DBG("%d: 0x%08x %d\n", type, addr, size);
92
93 ret = auxch_init(dev, ch);
94 if (ret)
95 goto out;
96
97 stat = nv_rd32(dev, 0x00e4e8 + (ch * 0x50));
98 if (!(stat & 0x10000000)) {
99 AUX_DBG("sink not detected\n");
100 ret = -ENXIO;
101 goto out;
102 }
103
104 if (!(type & 1)) {
105 memcpy(xbuf, data, size);
106 for (i = 0; i < 16; i += 4) {
107 AUX_DBG("wr 0x%08x\n", xbuf[i / 4]);
108 nv_wr32(dev, 0x00e4c0 + (ch * 0x50) + i, xbuf[i / 4]);
109 }
110 }
111
112 ctrl = nv_rd32(dev, 0x00e4e4 + (ch * 0x50));
113 ctrl &= ~0x0001f0ff;
114 ctrl |= type << 12;
115 ctrl |= size - 1;
116 nv_wr32(dev, 0x00e4e0 + (ch * 0x50), addr);
117
118 /* retry transaction a number of times on failure... */
119 ret = -EREMOTEIO;
120 for (retries = 0; retries < 32; retries++) {
121 /* reset, and delay a while if this is a retry */
122 nv_wr32(dev, 0x00e4e4 + (ch * 0x50), 0x80000000 | ctrl);
123 nv_wr32(dev, 0x00e4e4 + (ch * 0x50), 0x00000000 | ctrl);
124 if (retries)
125 udelay(400);
126
127 /* transaction request, wait up to 1ms for it to complete */
128 nv_wr32(dev, 0x00e4e4 + (ch * 0x50), 0x00010000 | ctrl);
129
130 timeout = 1000;
131 do {
132 ctrl = nv_rd32(dev, 0x00e4e4 + (ch * 0x50));
133 udelay(1);
134 if (!timeout--) {
135 AUX_ERR("tx req timeout 0x%08x\n", ctrl);
136 goto out;
137 }
138 } while (ctrl & 0x00010000);
139
140 /* read status, and check if transaction completed ok */
141 stat = nv_mask(dev, 0x00e4e8 + (ch * 0x50), 0, 0);
142 if (!(stat & 0x000f0f00)) {
143 ret = 0;
144 break;
145 }
146
147 AUX_DBG("%02d 0x%08x 0x%08x\n", retries, ctrl, stat);
148 }
149
150 if (type & 1) {
151 for (i = 0; i < 16; i += 4) {
152 xbuf[i / 4] = nv_rd32(dev, 0x00e4d0 + (ch * 0x50) + i);
153 AUX_DBG("rd 0x%08x\n", xbuf[i / 4]);
154 }
155 memcpy(data, xbuf, size);
156 }
157
158out:
159 auxch_fini(dev, ch);
160 return ret;
161}
162
163u8 * 33u8 *
164nouveau_dp_bios_data(struct drm_device *dev, struct dcb_entry *dcb, u8 **entry) 34nouveau_dp_bios_data(struct drm_device *dev, struct dcb_entry *dcb, u8 **entry)
165{ 35{
@@ -208,9 +78,9 @@ nouveau_dp_bios_data(struct drm_device *dev, struct dcb_entry *dcb, u8 **entry)
208 * link training 78 * link training
209 *****************************************************************************/ 79 *****************************************************************************/
210struct dp_state { 80struct dp_state {
81 struct nouveau_i2c_port *auxch;
211 struct dp_train_func *func; 82 struct dp_train_func *func;
212 struct dcb_entry *dcb; 83 struct dcb_entry *dcb;
213 int auxch;
214 int crtc; 84 int crtc;
215 u8 *dpcd; 85 u8 *dpcd;
216 int link_nr; 86 int link_nr;
@@ -236,7 +106,7 @@ dp_set_link_config(struct drm_device *dev, struct dp_state *dp)
236 if (dp->dpcd[2] & DP_ENHANCED_FRAME_CAP) 106 if (dp->dpcd[2] & DP_ENHANCED_FRAME_CAP)
237 sink[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN; 107 sink[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN;
238 108
239 auxch_tx(dev, dp->auxch, 8, DP_LINK_BW_SET, sink, 2); 109 auxch_wr(dev, dp->auxch, DP_LINK_BW_SET, sink, 2);
240} 110}
241 111
242static void 112static void
@@ -248,10 +118,10 @@ dp_set_training_pattern(struct drm_device *dev, struct dp_state *dp, u8 pattern)
248 118
249 dp->func->train_set(dev, dp->dcb, pattern); 119 dp->func->train_set(dev, dp->dcb, pattern);
250 120
251 auxch_tx(dev, dp->auxch, 9, DP_TRAINING_PATTERN_SET, &sink_tp, 1); 121 auxch_rd(dev, dp->auxch, DP_TRAINING_PATTERN_SET, &sink_tp, 1);
252 sink_tp &= ~DP_TRAINING_PATTERN_MASK; 122 sink_tp &= ~DP_TRAINING_PATTERN_MASK;
253 sink_tp |= pattern; 123 sink_tp |= pattern;
254 auxch_tx(dev, dp->auxch, 8, DP_TRAINING_PATTERN_SET, &sink_tp, 1); 124 auxch_wr(dev, dp->auxch, DP_TRAINING_PATTERN_SET, &sink_tp, 1);
255} 125}
256 126
257static int 127static int
@@ -274,7 +144,7 @@ dp_link_train_commit(struct drm_device *dev, struct dp_state *dp)
274 dp->func->train_adj(dev, dp->dcb, i, lvsw, lpre); 144 dp->func->train_adj(dev, dp->dcb, i, lvsw, lpre);
275 } 145 }
276 146
277 return auxch_tx(dev, dp->auxch, 8, DP_TRAINING_LANE0_SET, dp->conf, 4); 147 return auxch_wr(dev, dp->auxch, DP_TRAINING_LANE0_SET, dp->conf, 4);
278} 148}
279 149
280static int 150static int
@@ -284,7 +154,7 @@ dp_link_train_update(struct drm_device *dev, struct dp_state *dp, u32 delay)
284 154
285 udelay(delay); 155 udelay(delay);
286 156
287 ret = auxch_tx(dev, dp->auxch, 9, DP_LANE0_1_STATUS, dp->stat, 6); 157 ret = auxch_rd(dev, dp->auxch, DP_LANE0_1_STATUS, dp->stat, 6);
288 if (ret) 158 if (ret)
289 return ret; 159 return ret;
290 160
@@ -417,19 +287,17 @@ nouveau_dp_link_train(struct drm_encoder *encoder, u32 datarate,
417 struct nouveau_connector *nv_connector = 287 struct nouveau_connector *nv_connector =
418 nouveau_encoder_connector_get(nv_encoder); 288 nouveau_encoder_connector_get(nv_encoder);
419 struct drm_device *dev = encoder->dev; 289 struct drm_device *dev = encoder->dev;
420 struct nouveau_i2c_chan *auxch;
421 const u32 bw_list[] = { 270000, 162000, 0 }; 290 const u32 bw_list[] = { 270000, 162000, 0 };
422 const u32 *link_bw = bw_list; 291 const u32 *link_bw = bw_list;
423 struct dp_state dp; 292 struct dp_state dp;
424 293
425 auxch = nouveau_i2c_find(dev, nv_encoder->dcb->i2c_index); 294 dp.auxch = nouveau_i2c_find(dev, nv_encoder->dcb->i2c_index);
426 if (!auxch) 295 if (!dp.auxch)
427 return false; 296 return false;
428 297
429 dp.func = func; 298 dp.func = func;
430 dp.dcb = nv_encoder->dcb; 299 dp.dcb = nv_encoder->dcb;
431 dp.crtc = nv_crtc->index; 300 dp.crtc = nv_crtc->index;
432 dp.auxch = auxch->drive;
433 dp.dpcd = nv_encoder->dp.dpcd; 301 dp.dpcd = nv_encoder->dp.dpcd;
434 302
435 /* adjust required bandwidth for 8B/10B coding overhead */ 303 /* adjust required bandwidth for 8B/10B coding overhead */
@@ -491,7 +359,7 @@ nouveau_dp_dpms(struct drm_encoder *encoder, int mode, u32 datarate,
491 struct dp_train_func *func) 359 struct dp_train_func *func)
492{ 360{
493 struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); 361 struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
494 struct nouveau_i2c_chan *auxch; 362 struct nouveau_i2c_port *auxch;
495 u8 status; 363 u8 status;
496 364
497 auxch = nouveau_i2c_find(encoder->dev, nv_encoder->dcb->i2c_index); 365 auxch = nouveau_i2c_find(encoder->dev, nv_encoder->dcb->i2c_index);
@@ -503,14 +371,14 @@ nouveau_dp_dpms(struct drm_encoder *encoder, int mode, u32 datarate,
503 else 371 else
504 status = DP_SET_POWER_D3; 372 status = DP_SET_POWER_D3;
505 373
506 nouveau_dp_auxch(auxch, 8, DP_SET_POWER, &status, 1); 374 auxch_wr(encoder->dev, auxch, DP_SET_POWER, &status, 1);
507 375
508 if (mode == DRM_MODE_DPMS_ON) 376 if (mode == DRM_MODE_DPMS_ON)
509 nouveau_dp_link_train(encoder, datarate, func); 377 nouveau_dp_link_train(encoder, datarate, func);
510} 378}
511 379
512static void 380static void
513nouveau_dp_probe_oui(struct drm_device *dev, struct nouveau_i2c_chan *auxch, 381nouveau_dp_probe_oui(struct drm_device *dev, struct nouveau_i2c_port *auxch,
514 u8 *dpcd) 382 u8 *dpcd)
515{ 383{
516 u8 buf[3]; 384 u8 buf[3];
@@ -518,11 +386,11 @@ nouveau_dp_probe_oui(struct drm_device *dev, struct nouveau_i2c_chan *auxch,
518 if (!(dpcd[DP_DOWN_STREAM_PORT_COUNT] & DP_OUI_SUPPORT)) 386 if (!(dpcd[DP_DOWN_STREAM_PORT_COUNT] & DP_OUI_SUPPORT))
519 return; 387 return;
520 388
521 if (!auxch_tx(dev, auxch->drive, 9, DP_SINK_OUI, buf, 3)) 389 if (!auxch_rd(dev, auxch, DP_SINK_OUI, buf, 3))
522 NV_DEBUG_KMS(dev, "Sink OUI: %02hx%02hx%02hx\n", 390 NV_DEBUG_KMS(dev, "Sink OUI: %02hx%02hx%02hx\n",
523 buf[0], buf[1], buf[2]); 391 buf[0], buf[1], buf[2]);
524 392
525 if (!auxch_tx(dev, auxch->drive, 9, DP_BRANCH_OUI, buf, 3)) 393 if (!auxch_rd(dev, auxch, DP_BRANCH_OUI, buf, 3))
526 NV_DEBUG_KMS(dev, "Branch OUI: %02hx%02hx%02hx\n", 394 NV_DEBUG_KMS(dev, "Branch OUI: %02hx%02hx%02hx\n",
527 buf[0], buf[1], buf[2]); 395 buf[0], buf[1], buf[2]);
528 396
@@ -533,7 +401,7 @@ nouveau_dp_detect(struct drm_encoder *encoder)
533{ 401{
534 struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); 402 struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
535 struct drm_device *dev = encoder->dev; 403 struct drm_device *dev = encoder->dev;
536 struct nouveau_i2c_chan *auxch; 404 struct nouveau_i2c_port *auxch;
537 u8 *dpcd = nv_encoder->dp.dpcd; 405 u8 *dpcd = nv_encoder->dp.dpcd;
538 int ret; 406 int ret;
539 407
@@ -541,7 +409,7 @@ nouveau_dp_detect(struct drm_encoder *encoder)
541 if (!auxch) 409 if (!auxch)
542 return false; 410 return false;
543 411
544 ret = auxch_tx(dev, auxch->drive, 9, DP_DPCD_REV, dpcd, 8); 412 ret = auxch_rd(dev, auxch, DP_DPCD_REV, dpcd, 8);
545 if (ret) 413 if (ret)
546 return false; 414 return false;
547 415
@@ -566,58 +434,3 @@ nouveau_dp_detect(struct drm_encoder *encoder)
566 434
567 return true; 435 return true;
568} 436}
569
570int
571nouveau_dp_auxch(struct nouveau_i2c_chan *auxch, int cmd, int addr,
572 uint8_t *data, int data_nr)
573{
574 return auxch_tx(auxch->dev, auxch->drive, cmd, addr, data, data_nr);
575}
576
577static int
578nouveau_dp_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
579{
580 struct nouveau_i2c_chan *auxch = (struct nouveau_i2c_chan *)adap;
581 struct i2c_msg *msg = msgs;
582 int ret, mcnt = num;
583
584 while (mcnt--) {
585 u8 remaining = msg->len;
586 u8 *ptr = msg->buf;
587
588 while (remaining) {
589 u8 cnt = (remaining > 16) ? 16 : remaining;
590 u8 cmd;
591
592 if (msg->flags & I2C_M_RD)
593 cmd = AUX_I2C_READ;
594 else
595 cmd = AUX_I2C_WRITE;
596
597 if (mcnt || remaining > 16)
598 cmd |= AUX_I2C_MOT;
599
600 ret = nouveau_dp_auxch(auxch, cmd, msg->addr, ptr, cnt);
601 if (ret < 0)
602 return ret;
603
604 ptr += cnt;
605 remaining -= cnt;
606 }
607
608 msg++;
609 }
610
611 return num;
612}
613
614static u32
615nouveau_dp_i2c_func(struct i2c_adapter *adap)
616{
617 return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
618}
619
620const struct i2c_algorithm nouveau_dp_i2c_algo = {
621 .master_xfer = nouveau_dp_i2c_xfer,
622 .functionality = nouveau_dp_i2c_func
623};