aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2011-11-16 22:56:14 -0500
committerBen Skeggs <bskeggs@redhat.com>2011-12-21 04:01:40 -0500
commit2bdb06e3cff066c546fb41152bc582a5ec73e899 (patch)
tree919e599c07672b170f1a1b6c3ab9d13294974729
parent486a45c2a6c19b159602d044ab601a92cd81f524 (diff)
drm/nouveau/i2c: tidy up bit-bang helpers, also fixing nv50 setsda bug
Was using nv_mask, which is bad. Reading the reg senses the current line states, which aren't necessarily the states we're trying to drive the lines to. Fixed to store SCL driver state just as we already do for SDA. Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_dp.c6
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_i2c.c230
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_i2c.h6
3 files changed, 94 insertions, 148 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_dp.c b/drivers/gpu/drm/nouveau/nouveau_dp.c
index 5722fd55764..07bac360245 100644
--- a/drivers/gpu/drm/nouveau/nouveau_dp.c
+++ b/drivers/gpu/drm/nouveau/nouveau_dp.c
@@ -578,7 +578,7 @@ nouveau_dp_link_train(struct drm_encoder *encoder, u32 datarate)
578 578
579 dp.dcb = nv_encoder->dcb; 579 dp.dcb = nv_encoder->dcb;
580 dp.crtc = nv_crtc->index; 580 dp.crtc = nv_crtc->index;
581 dp.auxch = auxch->rd; 581 dp.auxch = auxch->drive;
582 dp.or = nv_encoder->or; 582 dp.or = nv_encoder->or;
583 dp.link = !(nv_encoder->dcb->sorconf.link & 1); 583 dp.link = !(nv_encoder->dcb->sorconf.link & 1);
584 dp.dpcd = nv_encoder->dp.dpcd; 584 dp.dpcd = nv_encoder->dp.dpcd;
@@ -653,7 +653,7 @@ nouveau_dp_detect(struct drm_encoder *encoder)
653 if (!auxch) 653 if (!auxch)
654 return false; 654 return false;
655 655
656 ret = auxch_tx(dev, auxch->rd, 9, DP_DPCD_REV, dpcd, 8); 656 ret = auxch_tx(dev, auxch->drive, 9, DP_DPCD_REV, dpcd, 8);
657 if (ret) 657 if (ret)
658 return false; 658 return false;
659 659
@@ -681,7 +681,7 @@ int
681nouveau_dp_auxch(struct nouveau_i2c_chan *auxch, int cmd, int addr, 681nouveau_dp_auxch(struct nouveau_i2c_chan *auxch, int cmd, int addr,
682 uint8_t *data, int data_nr) 682 uint8_t *data, int data_nr)
683{ 683{
684 return auxch_tx(auxch->dev, auxch->rd, cmd, addr, data, data_nr); 684 return auxch_tx(auxch->dev, auxch->drive, cmd, addr, data, data_nr);
685} 685}
686 686
687static int 687static int
diff --git a/drivers/gpu/drm/nouveau/nouveau_i2c.c b/drivers/gpu/drm/nouveau/nouveau_i2c.c
index 36ffcb84f55..d0d581440d5 100644
--- a/drivers/gpu/drm/nouveau/nouveau_i2c.c
+++ b/drivers/gpu/drm/nouveau/nouveau_i2c.c
@@ -30,132 +30,83 @@
30#include "nouveau_hw.h" 30#include "nouveau_hw.h"
31 31
32static void 32static void
33nv04_i2c_setscl(void *data, int state) 33i2c_drive_scl(void *data, int state)
34{ 34{
35 struct nouveau_i2c_chan *i2c = data; 35 struct nouveau_i2c_chan *port = data;
36 struct drm_device *dev = i2c->dev; 36 if (port->type == 0) {
37 uint8_t val; 37 u8 val = NVReadVgaCrtc(port->dev, 0, port->drive);
38 38 if (state) val |= 0x20;
39 val = (NVReadVgaCrtc(dev, 0, i2c->wr) & 0xd0) | (state ? 0x20 : 0); 39 else val &= 0xdf;
40 NVWriteVgaCrtc(dev, 0, i2c->wr, val | 0x01); 40 NVWriteVgaCrtc(port->dev, 0, port->drive, val | 0x01);
41} 41 } else
42 42 if (port->type == 4) {
43static void 43 nv_mask(port->dev, port->drive, 0x2f, state ? 0x21 : 0x01);
44nv04_i2c_setsda(void *data, int state) 44 } else
45{ 45 if (port->type == 5) {
46 struct nouveau_i2c_chan *i2c = data; 46 if (state) port->state |= 0x01;
47 struct drm_device *dev = i2c->dev; 47 else port->state &= 0xfe;
48 uint8_t val; 48 nv_wr32(port->dev, port->drive, 4 | port->state);
49 49 }
50 val = (NVReadVgaCrtc(dev, 0, i2c->wr) & 0xe0) | (state ? 0x10 : 0);
51 NVWriteVgaCrtc(dev, 0, i2c->wr, val | 0x01);
52}
53
54static int
55nv04_i2c_getscl(void *data)
56{
57 struct nouveau_i2c_chan *i2c = data;
58 struct drm_device *dev = i2c->dev;
59
60 return !!(NVReadVgaCrtc(dev, 0, i2c->rd) & 4);
61}
62
63static int
64nv04_i2c_getsda(void *data)
65{
66 struct nouveau_i2c_chan *i2c = data;
67 struct drm_device *dev = i2c->dev;
68
69 return !!(NVReadVgaCrtc(dev, 0, i2c->rd) & 8);
70}
71
72static void
73nv4e_i2c_setscl(void *data, int state)
74{
75 struct nouveau_i2c_chan *i2c = data;
76 struct drm_device *dev = i2c->dev;
77 uint8_t val;
78
79 val = (nv_rd32(dev, i2c->wr) & 0xd0) | (state ? 0x20 : 0);
80 nv_wr32(dev, i2c->wr, val | 0x01);
81}
82
83static void
84nv4e_i2c_setsda(void *data, int state)
85{
86 struct nouveau_i2c_chan *i2c = data;
87 struct drm_device *dev = i2c->dev;
88 uint8_t val;
89
90 val = (nv_rd32(dev, i2c->wr) & 0xe0) | (state ? 0x10 : 0);
91 nv_wr32(dev, i2c->wr, val | 0x01);
92}
93
94static int
95nv4e_i2c_getscl(void *data)
96{
97 struct nouveau_i2c_chan *i2c = data;
98 struct drm_device *dev = i2c->dev;
99
100 return !!((nv_rd32(dev, i2c->rd) >> 16) & 4);
101}
102
103static int
104nv4e_i2c_getsda(void *data)
105{
106 struct nouveau_i2c_chan *i2c = data;
107 struct drm_device *dev = i2c->dev;
108
109 return !!((nv_rd32(dev, i2c->rd) >> 16) & 8);
110}
111
112static int
113nv50_i2c_getscl(void *data)
114{
115 struct nouveau_i2c_chan *i2c = data;
116 struct drm_device *dev = i2c->dev;
117
118 return !!(nv_rd32(dev, i2c->rd) & 1);
119}
120
121static int
122nv50_i2c_getsda(void *data)
123{
124 struct nouveau_i2c_chan *i2c = data;
125 struct drm_device *dev = i2c->dev;
126
127 return !!(nv_rd32(dev, i2c->rd) & 2);
128}
129
130static void
131nv50_i2c_setscl(void *data, int state)
132{
133 struct nouveau_i2c_chan *i2c = data;
134
135 nv_wr32(i2c->dev, i2c->wr, 4 | (i2c->data ? 2 : 0) | (state ? 1 : 0));
136} 50}
137 51
138static void 52static void
139nv50_i2c_setsda(void *data, int state) 53i2c_drive_sda(void *data, int state)
140{ 54{
141 struct nouveau_i2c_chan *i2c = data; 55 struct nouveau_i2c_chan *port = data;
142 56 if (port->type == 0) {
143 nv_mask(i2c->dev, i2c->wr, 0x00000006, 4 | (state ? 2 : 0)); 57 u8 val = NVReadVgaCrtc(port->dev, 0, port->drive);
144 i2c->data = state; 58 if (state) val |= 0x10;
59 else val &= 0xef;
60 NVWriteVgaCrtc(port->dev, 0, port->drive, val | 0x01);
61 } else
62 if (port->type == 4) {
63 nv_mask(port->dev, port->drive, 0x1f, state ? 0x11 : 0x01);
64 } else
65 if (port->type == 5) {
66 if (state) port->state |= 0x02;
67 else port->state &= 0xfd;
68 nv_wr32(port->dev, port->drive, 4 | port->state);
69 }
145} 70}
146 71
147static int 72static int
148nvd0_i2c_getscl(void *data) 73i2c_sense_scl(void *data)
149{ 74{
150 struct nouveau_i2c_chan *i2c = data; 75 struct nouveau_i2c_chan *port = data;
151 return !!(nv_rd32(i2c->dev, i2c->rd) & 0x10); 76 struct drm_nouveau_private *dev_priv = port->dev->dev_private;
77 if (port->type == 0) {
78 return !!(NVReadVgaCrtc(port->dev, 0, port->sense) & 0x04);
79 } else
80 if (port->type == 4) {
81 return !!(nv_rd32(port->dev, port->sense) & 0x00040000);
82 } else
83 if (port->type == 5) {
84 if (dev_priv->card_type < NV_D0)
85 return !!(nv_rd32(port->dev, port->sense) & 0x01);
86 else
87 return !!(nv_rd32(port->dev, port->sense) & 0x10);
88 }
89 return 0;
152} 90}
153 91
154static int 92static int
155nvd0_i2c_getsda(void *data) 93i2c_sense_sda(void *data)
156{ 94{
157 struct nouveau_i2c_chan *i2c = data; 95 struct nouveau_i2c_chan *port = data;
158 return !!(nv_rd32(i2c->dev, i2c->rd) & 0x20); 96 struct drm_nouveau_private *dev_priv = port->dev->dev_private;
97 if (port->type == 0) {
98 return !!(NVReadVgaCrtc(port->dev, 0, port->sense) & 0x08);
99 } else
100 if (port->type == 4) {
101 return !!(nv_rd32(port->dev, port->sense) & 0x00080000);
102 } else
103 if (port->type == 5) {
104 if (dev_priv->card_type < NV_D0)
105 return !!(nv_rd32(port->dev, port->sense) & 0x02);
106 else
107 return !!(nv_rd32(port->dev, port->sense) & 0x20);
108 }
109 return 0;
159} 110}
160 111
161static const uint32_t nv50_i2c_port[] = { 112static const uint32_t nv50_i2c_port[] = {
@@ -258,51 +209,37 @@ nouveau_i2c_init(struct drm_device *dev)
258 209
259 switch (port->type) { 210 switch (port->type) {
260 case 0: /* NV04:NV50 */ 211 case 0: /* NV04:NV50 */
261 port->wr = entry[0]; 212 port->drive = entry[0];
262 port->rd = entry[1]; 213 port->sense = entry[1];
263 port->bit.setsda = nv04_i2c_setsda;
264 port->bit.setscl = nv04_i2c_setscl;
265 port->bit.getsda = nv04_i2c_getsda;
266 port->bit.getscl = nv04_i2c_getscl;
267 break; 214 break;
268 case 4: /* NV4E */ 215 case 4: /* NV4E */
269 port->wr = 0x600800 + entry[1]; 216 port->drive = 0x600800 + entry[1];
270 port->rd = port->wr; 217 port->sense = port->drive;
271 port->bit.setsda = nv4e_i2c_setsda;
272 port->bit.setscl = nv4e_i2c_setscl;
273 port->bit.getsda = nv4e_i2c_getsda;
274 port->bit.getscl = nv4e_i2c_getscl;
275 break; 218 break;
276 case 5: /* NV50- */ 219 case 5: /* NV50- */
277 port->wr = entry[0] & 0x0f; 220 port->drive = entry[0] & 0x0f;
278 if (dev_priv->card_type < NV_D0) { 221 if (dev_priv->card_type < NV_D0) {
279 if (port->wr >= ARRAY_SIZE(nv50_i2c_port)) 222 if (port->drive >= ARRAY_SIZE(nv50_i2c_port))
280 break; 223 break;
281 port->wr = nv50_i2c_port[port->wr]; 224 port->drive = nv50_i2c_port[port->drive];
282 port->rd = port->wr; 225 port->sense = port->drive;
283 port->bit.getsda = nv50_i2c_getsda;
284 port->bit.getscl = nv50_i2c_getscl;
285 } else { 226 } else {
286 port->wr = 0x00d014 + (port->wr * 0x20); 227 port->drive = 0x00d014 + (port->drive * 0x20);
287 port->rd = port->wr; 228 port->sense = port->drive;
288 port->bit.getsda = nvd0_i2c_getsda;
289 port->bit.getscl = nvd0_i2c_getscl;
290 } 229 }
291 port->bit.setsda = nv50_i2c_setsda;
292 port->bit.setscl = nv50_i2c_setscl;
293 break; 230 break;
294 case 6: /* NV50- DP AUX */ 231 case 6: /* NV50- DP AUX */
295 port->wr = entry[0]; 232 port->drive = entry[0];
296 port->rd = port->wr; 233 port->sense = port->drive;
297 port->adapter.algo = &nouveau_dp_i2c_algo; 234 port->adapter.algo = &nouveau_dp_i2c_algo;
298 break; 235 break;
299 default: 236 default:
300 break; 237 break;
301 } 238 }
302 239
303 if (!port->adapter.algo && !port->wr) { 240 if (!port->adapter.algo && !port->drive) {
304 NV_ERROR(dev, "I2C%d: type %d index %x/%x unknown\n", 241 NV_ERROR(dev, "I2C%d: type %d index %x/%x unknown\n",
305 i, port->type, port->wr, port->rd); 242 i, port->type, port->drive, port->sense);
306 kfree(port); 243 kfree(port);
307 continue; 244 continue;
308 } 245 }
@@ -321,6 +258,15 @@ nouveau_i2c_init(struct drm_device *dev)
321 port->bit.udelay = 40; 258 port->bit.udelay = 40;
322 port->bit.timeout = usecs_to_jiffies(5000); 259 port->bit.timeout = usecs_to_jiffies(5000);
323 port->bit.data = port; 260 port->bit.data = port;
261 port->bit.setsda = i2c_drive_sda;
262 port->bit.setscl = i2c_drive_scl;
263 port->bit.getsda = i2c_sense_sda;
264 port->bit.getscl = i2c_sense_scl;
265
266 i2c_drive_scl(port, 0);
267 i2c_drive_sda(port, 1);
268 i2c_drive_scl(port, 1);
269
324 ret = i2c_bit_add_bus(&port->adapter); 270 ret = i2c_bit_add_bus(&port->adapter);
325 } else { 271 } else {
326 port->adapter.algo = &nouveau_dp_i2c_algo; 272 port->adapter.algo = &nouveau_dp_i2c_algo;
@@ -381,7 +327,7 @@ nouveau_i2c_find(struct drm_device *dev, u8 index)
381 if (dev_priv->card_type >= NV_50 && (port->dcb & 0x00000100)) { 327 if (dev_priv->card_type >= NV_50 && (port->dcb & 0x00000100)) {
382 u32 reg = 0x00e500, val; 328 u32 reg = 0x00e500, val;
383 if (port->type == 6) { 329 if (port->type == 6) {
384 reg += port->rd * 0x50; 330 reg += port->drive * 0x50;
385 val = 0x2002; 331 val = 0x2002;
386 } else { 332 } else {
387 reg += ((port->dcb & 0x1e00) >> 9) * 0x50; 333 reg += ((port->dcb & 0x1e00) >> 9) * 0x50;
diff --git a/drivers/gpu/drm/nouveau/nouveau_i2c.h b/drivers/gpu/drm/nouveau/nouveau_i2c.h
index cf5f67d51fb..1d083893a4d 100644
--- a/drivers/gpu/drm/nouveau/nouveau_i2c.h
+++ b/drivers/gpu/drm/nouveau/nouveau_i2c.h
@@ -39,9 +39,9 @@ struct nouveau_i2c_chan {
39 u8 index; 39 u8 index;
40 u8 type; 40 u8 type;
41 u32 dcb; 41 u32 dcb;
42 unsigned rd; 42 u32 drive;
43 unsigned wr; 43 u32 sense;
44 unsigned data; 44 u32 state;
45}; 45};
46 46
47int nouveau_i2c_init(struct drm_device *); 47int nouveau_i2c_init(struct drm_device *);