aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/nouveau/nouveau_dp.c
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2012-10-02 23:26:15 -0400
committerDave Airlie <airlied@redhat.com>2012-10-02 23:26:15 -0400
commit268d28371cd326be4dfcd7eba5917bf4b9d30c8f (patch)
treefec4f9e98bde15301b5d5338038a9a31f7555456 /drivers/gpu/drm/nouveau/nouveau_dp.c
parentdf86b5765a48d5f557489577652bd6df145b0e1b (diff)
parentb9f10852fcb1f09369d931dcbfbaad89ad1da4ad (diff)
Merge branch 'drm-nouveau-next' of git://anongit.freedesktop.org/git/nouveau/linux-2.6 into drm-next
This is a major rework of the nouveau driver core, to reflect more closely how the hw is used and to make it easier to implement newer features now that the GPUs are more clearly understood than when nouveau started. It also contains a few other bits: thermal patches nv41/44 pcie gart fixes i2c unregistering fixes. * 'drm-nouveau-next' of git://anongit.freedesktop.org/git/nouveau/linux-2.6: (191 commits) drm/nv98/crypt: fix fuc build with latest envyas drm/nouveau/devinit: fixup various issues with subdev ctor/init ordering drm/nv41/vm: fix and enable use of "real" pciegart drm/nv44/vm: fix and enable use of "real" pciegart drm/nv04/dmaobj: fixup vm target handling in preparation for nv4x pcie drm/nouveau: store supported dma mask in vmmgr drm/nvc0/ibus: initial implementation of subdev drm/nouveau/therm: add support for fan-control modes drm/nouveau/hwmon: rename pwm0* to pmw1* to follow hwmon's rules drm/nouveau/therm: calculate the pwm divisor on nv50+ drm/nouveau/fan: rewrite the fan tachometer driver to get more precision, faster drm/nouveau/therm: move thermal-related functions to the therm subdev drm/nouveau/bios: parse the pwm divisor from the perf table drm/nouveau/therm: use the EXTDEV table to detect i2c monitoring devices drm/nouveau/therm: rework thermal table parsing drm/nouveau/gpio: expose the PWM/TOGGLE parameter found in the gpio vbios table drm/nouveau: fix pm initialization order drm/nouveau/bios: check that fixed tvdac gpio data is valid before using it drm/nouveau: log channel debug/error messages from client object rather than drm client drm/nouveau: have drm debugging macros build on top of core macros ... Conflicts: drivers/gpu/drm/nouveau/nouveau_dp.c
Diffstat (limited to 'drivers/gpu/drm/nouveau/nouveau_dp.c')
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_dp.c278
1 files changed, 53 insertions, 225 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_dp.c b/drivers/gpu/drm/nouveau/nouveau_dp.c
index e754aa32edf1..72266ae91fa1 100644
--- a/drivers/gpu/drm/nouveau/nouveau_dp.c
+++ b/drivers/gpu/drm/nouveau/nouveau_dp.c
@@ -23,164 +23,37 @@
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_drm.h"
28#include "nouveau_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#include "nouveau_gpio.h"
33 32
34/****************************************************************************** 33#include <subdev/gpio.h>
35 * aux channel util functions 34#include <subdev/i2c.h>
36 *****************************************************************************/
37#define AUX_DBG(fmt, args...) do { \
38 if (nouveau_reg_debug & NOUVEAU_REG_DEBUG_AUXCH) { \
39 NV_PRINTK(KERN_DEBUG, dev, "AUXCH(%d): " fmt, ch, ##args); \
40 } \
41} while (0)
42#define AUX_ERR(fmt, args...) NV_ERROR(dev, "AUXCH(%d): " fmt, ch, ##args)
43
44static void
45auxch_fini(struct drm_device *dev, int ch)
46{
47 nv_mask(dev, 0x00e4e4 + (ch * 0x50), 0x00310000, 0x00000000);
48}
49
50static int
51auxch_init(struct drm_device *dev, int ch)
52{
53 const u32 unksel = 1; /* nfi which to use, or if it matters.. */
54 const u32 ureq = unksel ? 0x00100000 : 0x00200000;
55 const u32 urep = unksel ? 0x01000000 : 0x02000000;
56 u32 ctrl, timeout;
57
58 /* wait up to 1ms for any previous transaction to be done... */
59 timeout = 1000;
60 do {
61 ctrl = nv_rd32(dev, 0x00e4e4 + (ch * 0x50));
62 udelay(1);
63 if (!timeout--) {
64 AUX_ERR("begin idle timeout 0x%08x", ctrl);
65 return -EBUSY;
66 }
67 } while (ctrl & 0x03010000);
68
69 /* set some magic, and wait up to 1ms for it to appear */
70 nv_mask(dev, 0x00e4e4 + (ch * 0x50), 0x00300000, ureq);
71 timeout = 1000;
72 do {
73 ctrl = nv_rd32(dev, 0x00e4e4 + (ch * 0x50));
74 udelay(1);
75 if (!timeout--) {
76 AUX_ERR("magic wait 0x%08x\n", ctrl);
77 auxch_fini(dev, ch);
78 return -EBUSY;
79 }
80 } while ((ctrl & 0x03000000) != urep);
81
82 return 0;
83}
84
85static int
86auxch_tx(struct drm_device *dev, int ch, u8 type, u32 addr, u8 *data, u8 size)
87{
88 u32 ctrl, stat, timeout, retries;
89 u32 xbuf[4] = {};
90 int ret, i;
91
92 AUX_DBG("%d: 0x%08x %d\n", type, addr, size);
93
94 ret = auxch_init(dev, ch);
95 if (ret)
96 goto out;
97
98 stat = nv_rd32(dev, 0x00e4e8 + (ch * 0x50));
99 if (!(stat & 0x10000000)) {
100 AUX_DBG("sink not detected\n");
101 ret = -ENXIO;
102 goto out;
103 }
104
105 if (!(type & 1)) {
106 memcpy(xbuf, data, size);
107 for (i = 0; i < 16; i += 4) {
108 AUX_DBG("wr 0x%08x\n", xbuf[i / 4]);
109 nv_wr32(dev, 0x00e4c0 + (ch * 0x50) + i, xbuf[i / 4]);
110 }
111 }
112
113 ctrl = nv_rd32(dev, 0x00e4e4 + (ch * 0x50));
114 ctrl &= ~0x0001f0ff;
115 ctrl |= type << 12;
116 ctrl |= size - 1;
117 nv_wr32(dev, 0x00e4e0 + (ch * 0x50), addr);
118
119 /* retry transaction a number of times on failure... */
120 ret = -EREMOTEIO;
121 for (retries = 0; retries < 32; retries++) {
122 /* reset, and delay a while if this is a retry */
123 nv_wr32(dev, 0x00e4e4 + (ch * 0x50), 0x80000000 | ctrl);
124 nv_wr32(dev, 0x00e4e4 + (ch * 0x50), 0x00000000 | ctrl);
125 if (retries)
126 udelay(400);
127
128 /* transaction request, wait up to 1ms for it to complete */
129 nv_wr32(dev, 0x00e4e4 + (ch * 0x50), 0x00010000 | ctrl);
130
131 timeout = 1000;
132 do {
133 ctrl = nv_rd32(dev, 0x00e4e4 + (ch * 0x50));
134 udelay(1);
135 if (!timeout--) {
136 AUX_ERR("tx req timeout 0x%08x\n", ctrl);
137 goto out;
138 }
139 } while (ctrl & 0x00010000);
140
141 /* read status, and check if transaction completed ok */
142 stat = nv_mask(dev, 0x00e4e8 + (ch * 0x50), 0, 0);
143 if (!(stat & 0x000f0f00)) {
144 ret = 0;
145 break;
146 }
147
148 AUX_DBG("%02d 0x%08x 0x%08x\n", retries, ctrl, stat);
149 }
150
151 if (type & 1) {
152 for (i = 0; i < 16; i += 4) {
153 xbuf[i / 4] = nv_rd32(dev, 0x00e4d0 + (ch * 0x50) + i);
154 AUX_DBG("rd 0x%08x\n", xbuf[i / 4]);
155 }
156 memcpy(data, xbuf, size);
157 }
158
159out:
160 auxch_fini(dev, ch);
161 return ret;
162}
163 35
164u8 * 36u8 *
165nouveau_dp_bios_data(struct drm_device *dev, struct dcb_entry *dcb, u8 **entry) 37nouveau_dp_bios_data(struct drm_device *dev, struct dcb_output *dcb, u8 **entry)
166{ 38{
39 struct nouveau_drm *drm = nouveau_drm(dev);
167 struct bit_entry d; 40 struct bit_entry d;
168 u8 *table; 41 u8 *table;
169 int i; 42 int i;
170 43
171 if (bit_table(dev, 'd', &d)) { 44 if (bit_table(dev, 'd', &d)) {
172 NV_ERROR(dev, "BIT 'd' table not found\n"); 45 NV_ERROR(drm, "BIT 'd' table not found\n");
173 return NULL; 46 return NULL;
174 } 47 }
175 48
176 if (d.version != 1) { 49 if (d.version != 1) {
177 NV_ERROR(dev, "BIT 'd' table version %d unknown\n", d.version); 50 NV_ERROR(drm, "BIT 'd' table version %d unknown\n", d.version);
178 return NULL; 51 return NULL;
179 } 52 }
180 53
181 table = ROMPTR(dev, d.data[0]); 54 table = ROMPTR(dev, d.data[0]);
182 if (!table) { 55 if (!table) {
183 NV_ERROR(dev, "displayport table pointer invalid\n"); 56 NV_ERROR(drm, "displayport table pointer invalid\n");
184 return NULL; 57 return NULL;
185 } 58 }
186 59
@@ -191,7 +64,7 @@ nouveau_dp_bios_data(struct drm_device *dev, struct dcb_entry *dcb, u8 **entry)
191 case 0x40: 64 case 0x40:
192 break; 65 break;
193 default: 66 default:
194 NV_ERROR(dev, "displayport table 0x%02x unknown\n", table[0]); 67 NV_ERROR(drm, "displayport table 0x%02x unknown\n", table[0]);
195 return NULL; 68 return NULL;
196 } 69 }
197 70
@@ -201,7 +74,7 @@ nouveau_dp_bios_data(struct drm_device *dev, struct dcb_entry *dcb, u8 **entry)
201 return table; 74 return table;
202 } 75 }
203 76
204 NV_ERROR(dev, "displayport encoder table not found\n"); 77 NV_ERROR(drm, "displayport encoder table not found\n");
205 return NULL; 78 return NULL;
206} 79}
207 80
@@ -209,9 +82,9 @@ nouveau_dp_bios_data(struct drm_device *dev, struct dcb_entry *dcb, u8 **entry)
209 * link training 82 * link training
210 *****************************************************************************/ 83 *****************************************************************************/
211struct dp_state { 84struct dp_state {
85 struct nouveau_i2c_port *auxch;
212 struct dp_train_func *func; 86 struct dp_train_func *func;
213 struct dcb_entry *dcb; 87 struct dcb_output *dcb;
214 int auxch;
215 int crtc; 88 int crtc;
216 u8 *dpcd; 89 u8 *dpcd;
217 int link_nr; 90 int link_nr;
@@ -223,9 +96,10 @@ struct dp_state {
223static void 96static void
224dp_set_link_config(struct drm_device *dev, struct dp_state *dp) 97dp_set_link_config(struct drm_device *dev, struct dp_state *dp)
225{ 98{
99 struct nouveau_drm *drm = nouveau_drm(dev);
226 u8 sink[2]; 100 u8 sink[2];
227 101
228 NV_DEBUG_KMS(dev, "%d lanes at %d KB/s\n", dp->link_nr, dp->link_bw); 102 NV_DEBUG(drm, "%d lanes at %d KB/s\n", dp->link_nr, dp->link_bw);
229 103
230 /* set desired link configuration on the source */ 104 /* set desired link configuration on the source */
231 dp->func->link_set(dev, dp->dcb, dp->crtc, dp->link_nr, dp->link_bw, 105 dp->func->link_set(dev, dp->dcb, dp->crtc, dp->link_nr, dp->link_bw,
@@ -237,27 +111,29 @@ dp_set_link_config(struct drm_device *dev, struct dp_state *dp)
237 if (dp->dpcd[2] & DP_ENHANCED_FRAME_CAP) 111 if (dp->dpcd[2] & DP_ENHANCED_FRAME_CAP)
238 sink[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN; 112 sink[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN;
239 113
240 auxch_tx(dev, dp->auxch, 8, DP_LINK_BW_SET, sink, 2); 114 nv_wraux(dp->auxch, DP_LINK_BW_SET, sink, 2);
241} 115}
242 116
243static void 117static void
244dp_set_training_pattern(struct drm_device *dev, struct dp_state *dp, u8 pattern) 118dp_set_training_pattern(struct drm_device *dev, struct dp_state *dp, u8 pattern)
245{ 119{
120 struct nouveau_drm *drm = nouveau_drm(dev);
246 u8 sink_tp; 121 u8 sink_tp;
247 122
248 NV_DEBUG_KMS(dev, "training pattern %d\n", pattern); 123 NV_DEBUG(drm, "training pattern %d\n", pattern);
249 124
250 dp->func->train_set(dev, dp->dcb, pattern); 125 dp->func->train_set(dev, dp->dcb, pattern);
251 126
252 auxch_tx(dev, dp->auxch, 9, DP_TRAINING_PATTERN_SET, &sink_tp, 1); 127 nv_rdaux(dp->auxch, DP_TRAINING_PATTERN_SET, &sink_tp, 1);
253 sink_tp &= ~DP_TRAINING_PATTERN_MASK; 128 sink_tp &= ~DP_TRAINING_PATTERN_MASK;
254 sink_tp |= pattern; 129 sink_tp |= pattern;
255 auxch_tx(dev, dp->auxch, 8, DP_TRAINING_PATTERN_SET, &sink_tp, 1); 130 nv_wraux(dp->auxch, DP_TRAINING_PATTERN_SET, &sink_tp, 1);
256} 131}
257 132
258static int 133static int
259dp_link_train_commit(struct drm_device *dev, struct dp_state *dp) 134dp_link_train_commit(struct drm_device *dev, struct dp_state *dp)
260{ 135{
136 struct nouveau_drm *drm = nouveau_drm(dev);
261 int i; 137 int i;
262 138
263 for (i = 0; i < dp->link_nr; i++) { 139 for (i = 0; i < dp->link_nr; i++) {
@@ -271,25 +147,26 @@ dp_link_train_commit(struct drm_device *dev, struct dp_state *dp)
271 if ((lpre << 3) == DP_TRAIN_PRE_EMPHASIS_9_5) 147 if ((lpre << 3) == DP_TRAIN_PRE_EMPHASIS_9_5)
272 dp->conf[i] |= DP_TRAIN_MAX_PRE_EMPHASIS_REACHED; 148 dp->conf[i] |= DP_TRAIN_MAX_PRE_EMPHASIS_REACHED;
273 149
274 NV_DEBUG_KMS(dev, "config lane %d %02x\n", i, dp->conf[i]); 150 NV_DEBUG(drm, "config lane %d %02x\n", i, dp->conf[i]);
275 dp->func->train_adj(dev, dp->dcb, i, lvsw, lpre); 151 dp->func->train_adj(dev, dp->dcb, i, lvsw, lpre);
276 } 152 }
277 153
278 return auxch_tx(dev, dp->auxch, 8, DP_TRAINING_LANE0_SET, dp->conf, 4); 154 return nv_wraux(dp->auxch, DP_TRAINING_LANE0_SET, dp->conf, 4);
279} 155}
280 156
281static int 157static int
282dp_link_train_update(struct drm_device *dev, struct dp_state *dp, u32 delay) 158dp_link_train_update(struct drm_device *dev, struct dp_state *dp, u32 delay)
283{ 159{
160 struct nouveau_drm *drm = nouveau_drm(dev);
284 int ret; 161 int ret;
285 162
286 udelay(delay); 163 udelay(delay);
287 164
288 ret = auxch_tx(dev, dp->auxch, 9, DP_LANE0_1_STATUS, dp->stat, 6); 165 ret = nv_rdaux(dp->auxch, DP_LANE0_1_STATUS, dp->stat, 6);
289 if (ret) 166 if (ret)
290 return ret; 167 return ret;
291 168
292 NV_DEBUG_KMS(dev, "status %*ph\n", 6, dp->stat); 169 NV_DEBUG(drm, "status %*ph\n", 6, dp->stat);
293 return 0; 170 return 0;
294} 171}
295 172
@@ -407,7 +284,7 @@ dp_link_train_fini(struct drm_device *dev, struct dp_state *dp)
407 nouveau_bios_run_init_table(dev, script, dp->dcb, dp->crtc); 284 nouveau_bios_run_init_table(dev, script, dp->dcb, dp->crtc);
408} 285}
409 286
410bool 287static bool
411nouveau_dp_link_train(struct drm_encoder *encoder, u32 datarate, 288nouveau_dp_link_train(struct drm_encoder *encoder, u32 datarate,
412 struct dp_train_func *func) 289 struct dp_train_func *func)
413{ 290{
@@ -416,19 +293,20 @@ nouveau_dp_link_train(struct drm_encoder *encoder, u32 datarate,
416 struct nouveau_connector *nv_connector = 293 struct nouveau_connector *nv_connector =
417 nouveau_encoder_connector_get(nv_encoder); 294 nouveau_encoder_connector_get(nv_encoder);
418 struct drm_device *dev = encoder->dev; 295 struct drm_device *dev = encoder->dev;
419 struct nouveau_i2c_chan *auxch; 296 struct nouveau_drm *drm = nouveau_drm(dev);
297 struct nouveau_i2c *i2c = nouveau_i2c(drm->device);
298 struct nouveau_gpio *gpio = nouveau_gpio(drm->device);
420 const u32 bw_list[] = { 270000, 162000, 0 }; 299 const u32 bw_list[] = { 270000, 162000, 0 };
421 const u32 *link_bw = bw_list; 300 const u32 *link_bw = bw_list;
422 struct dp_state dp; 301 struct dp_state dp;
423 302
424 auxch = nouveau_i2c_find(dev, nv_encoder->dcb->i2c_index); 303 dp.auxch = i2c->find(i2c, nv_encoder->dcb->i2c_index);
425 if (!auxch) 304 if (!dp.auxch)
426 return false; 305 return false;
427 306
428 dp.func = func; 307 dp.func = func;
429 dp.dcb = nv_encoder->dcb; 308 dp.dcb = nv_encoder->dcb;
430 dp.crtc = nv_crtc->index; 309 dp.crtc = nv_crtc->index;
431 dp.auxch = auxch->drive;
432 dp.dpcd = nv_encoder->dp.dpcd; 310 dp.dpcd = nv_encoder->dp.dpcd;
433 311
434 /* adjust required bandwidth for 8B/10B coding overhead */ 312 /* adjust required bandwidth for 8B/10B coding overhead */
@@ -438,7 +316,7 @@ nouveau_dp_link_train(struct drm_encoder *encoder, u32 datarate,
438 * we take during link training (DP_SET_POWER is one), we need 316 * we take during link training (DP_SET_POWER is one), we need
439 * to ignore them for the moment to avoid races. 317 * to ignore them for the moment to avoid races.
440 */ 318 */
441 nouveau_gpio_irq(dev, 0, nv_connector->hpd, 0xff, false); 319 gpio->irq(gpio, 0, nv_connector->hpd, 0xff, false);
442 320
443 /* enable down-spreading, if possible */ 321 /* enable down-spreading, if possible */
444 dp_set_downspread(dev, &dp, nv_encoder->dp.dpcd[3] & 1); 322 dp_set_downspread(dev, &dp, nv_encoder->dp.dpcd[3] & 1);
@@ -481,7 +359,7 @@ nouveau_dp_link_train(struct drm_encoder *encoder, u32 datarate,
481 dp_link_train_fini(dev, &dp); 359 dp_link_train_fini(dev, &dp);
482 360
483 /* re-enable hotplug detect */ 361 /* re-enable hotplug detect */
484 nouveau_gpio_irq(dev, 0, nv_connector->hpd, 0xff, true); 362 gpio->irq(gpio, 0, nv_connector->hpd, 0xff, true);
485 return true; 363 return true;
486} 364}
487 365
@@ -490,10 +368,12 @@ nouveau_dp_dpms(struct drm_encoder *encoder, int mode, u32 datarate,
490 struct dp_train_func *func) 368 struct dp_train_func *func)
491{ 369{
492 struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); 370 struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
493 struct nouveau_i2c_chan *auxch; 371 struct nouveau_drm *drm = nouveau_drm(encoder->dev);
372 struct nouveau_i2c *i2c = nouveau_i2c(drm->device);
373 struct nouveau_i2c_port *auxch;
494 u8 status; 374 u8 status;
495 375
496 auxch = nouveau_i2c_find(encoder->dev, nv_encoder->dcb->i2c_index); 376 auxch = i2c->find(i2c, nv_encoder->dcb->i2c_index);
497 if (!auxch) 377 if (!auxch)
498 return; 378 return;
499 379
@@ -502,27 +382,28 @@ nouveau_dp_dpms(struct drm_encoder *encoder, int mode, u32 datarate,
502 else 382 else
503 status = DP_SET_POWER_D3; 383 status = DP_SET_POWER_D3;
504 384
505 nouveau_dp_auxch(auxch, 8, DP_SET_POWER, &status, 1); 385 nv_wraux(auxch, DP_SET_POWER, &status, 1);
506 386
507 if (mode == DRM_MODE_DPMS_ON) 387 if (mode == DRM_MODE_DPMS_ON)
508 nouveau_dp_link_train(encoder, datarate, func); 388 nouveau_dp_link_train(encoder, datarate, func);
509} 389}
510 390
511static void 391static void
512nouveau_dp_probe_oui(struct drm_device *dev, struct nouveau_i2c_chan *auxch, 392nouveau_dp_probe_oui(struct drm_device *dev, struct nouveau_i2c_port *auxch,
513 u8 *dpcd) 393 u8 *dpcd)
514{ 394{
395 struct nouveau_drm *drm = nouveau_drm(dev);
515 u8 buf[3]; 396 u8 buf[3];
516 397
517 if (!(dpcd[DP_DOWN_STREAM_PORT_COUNT] & DP_OUI_SUPPORT)) 398 if (!(dpcd[DP_DOWN_STREAM_PORT_COUNT] & DP_OUI_SUPPORT))
518 return; 399 return;
519 400
520 if (!auxch_tx(dev, auxch->drive, 9, DP_SINK_OUI, buf, 3)) 401 if (!nv_rdaux(auxch, DP_SINK_OUI, buf, 3))
521 NV_DEBUG_KMS(dev, "Sink OUI: %02hx%02hx%02hx\n", 402 NV_DEBUG(drm, "Sink OUI: %02hx%02hx%02hx\n",
522 buf[0], buf[1], buf[2]); 403 buf[0], buf[1], buf[2]);
523 404
524 if (!auxch_tx(dev, auxch->drive, 9, DP_BRANCH_OUI, buf, 3)) 405 if (!nv_rdaux(auxch, DP_BRANCH_OUI, buf, 3))
525 NV_DEBUG_KMS(dev, "Branch OUI: %02hx%02hx%02hx\n", 406 NV_DEBUG(drm, "Branch OUI: %02hx%02hx%02hx\n",
526 buf[0], buf[1], buf[2]); 407 buf[0], buf[1], buf[2]);
527 408
528} 409}
@@ -532,24 +413,26 @@ nouveau_dp_detect(struct drm_encoder *encoder)
532{ 413{
533 struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); 414 struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
534 struct drm_device *dev = encoder->dev; 415 struct drm_device *dev = encoder->dev;
535 struct nouveau_i2c_chan *auxch; 416 struct nouveau_drm *drm = nouveau_drm(dev);
417 struct nouveau_i2c *i2c = nouveau_i2c(drm->device);
418 struct nouveau_i2c_port *auxch;
536 u8 *dpcd = nv_encoder->dp.dpcd; 419 u8 *dpcd = nv_encoder->dp.dpcd;
537 int ret; 420 int ret;
538 421
539 auxch = nouveau_i2c_find(dev, nv_encoder->dcb->i2c_index); 422 auxch = i2c->find(i2c, nv_encoder->dcb->i2c_index);
540 if (!auxch) 423 if (!auxch)
541 return false; 424 return false;
542 425
543 ret = auxch_tx(dev, auxch->drive, 9, DP_DPCD_REV, dpcd, 8); 426 ret = nv_rdaux(auxch, DP_DPCD_REV, dpcd, 8);
544 if (ret) 427 if (ret)
545 return false; 428 return false;
546 429
547 nv_encoder->dp.link_bw = 27000 * dpcd[1]; 430 nv_encoder->dp.link_bw = 27000 * dpcd[1];
548 nv_encoder->dp.link_nr = dpcd[2] & DP_MAX_LANE_COUNT_MASK; 431 nv_encoder->dp.link_nr = dpcd[2] & DP_MAX_LANE_COUNT_MASK;
549 432
550 NV_DEBUG_KMS(dev, "display: %dx%d dpcd 0x%02x\n", 433 NV_DEBUG(drm, "display: %dx%d dpcd 0x%02x\n",
551 nv_encoder->dp.link_nr, nv_encoder->dp.link_bw, dpcd[0]); 434 nv_encoder->dp.link_nr, nv_encoder->dp.link_bw, dpcd[0]);
552 NV_DEBUG_KMS(dev, "encoder: %dx%d\n", 435 NV_DEBUG(drm, "encoder: %dx%d\n",
553 nv_encoder->dcb->dpconf.link_nr, 436 nv_encoder->dcb->dpconf.link_nr,
554 nv_encoder->dcb->dpconf.link_bw); 437 nv_encoder->dcb->dpconf.link_bw);
555 438
@@ -558,65 +441,10 @@ nouveau_dp_detect(struct drm_encoder *encoder)
558 if (nv_encoder->dcb->dpconf.link_bw < nv_encoder->dp.link_bw) 441 if (nv_encoder->dcb->dpconf.link_bw < nv_encoder->dp.link_bw)
559 nv_encoder->dp.link_bw = nv_encoder->dcb->dpconf.link_bw; 442 nv_encoder->dp.link_bw = nv_encoder->dcb->dpconf.link_bw;
560 443
561 NV_DEBUG_KMS(dev, "maximum: %dx%d\n", 444 NV_DEBUG(drm, "maximum: %dx%d\n",
562 nv_encoder->dp.link_nr, nv_encoder->dp.link_bw); 445 nv_encoder->dp.link_nr, nv_encoder->dp.link_bw);
563 446
564 nouveau_dp_probe_oui(dev, auxch, dpcd); 447 nouveau_dp_probe_oui(dev, auxch, dpcd);
565 448
566 return true; 449 return true;
567} 450}
568
569int
570nouveau_dp_auxch(struct nouveau_i2c_chan *auxch, int cmd, int addr,
571 uint8_t *data, int data_nr)
572{
573 return auxch_tx(auxch->dev, auxch->drive, cmd, addr, data, data_nr);
574}
575
576static int
577nouveau_dp_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
578{
579 struct nouveau_i2c_chan *auxch = (struct nouveau_i2c_chan *)adap;
580 struct i2c_msg *msg = msgs;
581 int ret, mcnt = num;
582
583 while (mcnt--) {
584 u8 remaining = msg->len;
585 u8 *ptr = msg->buf;
586
587 while (remaining) {
588 u8 cnt = (remaining > 16) ? 16 : remaining;
589 u8 cmd;
590
591 if (msg->flags & I2C_M_RD)
592 cmd = AUX_I2C_READ;
593 else
594 cmd = AUX_I2C_WRITE;
595
596 if (mcnt || remaining > 16)
597 cmd |= AUX_I2C_MOT;
598
599 ret = nouveau_dp_auxch(auxch, cmd, msg->addr, ptr, cnt);
600 if (ret < 0)
601 return ret;
602
603 ptr += cnt;
604 remaining -= cnt;
605 }
606
607 msg++;
608 }
609
610 return num;
611}
612
613static u32
614nouveau_dp_i2c_func(struct i2c_adapter *adap)
615{
616 return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
617}
618
619const struct i2c_algorithm nouveau_dp_i2c_algo = {
620 .master_xfer = nouveau_dp_i2c_xfer,
621 .functionality = nouveau_dp_i2c_func
622};