blob: 36ffcb84f55ad6d8fe534b71279971c3e1b18ca6 [file] [log] [blame]
Ben Skeggs6ee73862009-12-11 19:24:15 +10001/*
2 * Copyright 2009 Red Hat Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * Authors: Ben Skeggs
23 */
24
Paul Gortmakere0cd3602011-08-30 11:04:30 -040025#include <linux/module.h>
26
Ben Skeggs6ee73862009-12-11 19:24:15 +100027#include "drmP.h"
28#include "nouveau_drv.h"
29#include "nouveau_i2c.h"
30#include "nouveau_hw.h"
31
32static void
33nv04_i2c_setscl(void *data, int state)
34{
35 struct nouveau_i2c_chan *i2c = data;
36 struct drm_device *dev = i2c->dev;
37 uint8_t val;
38
39 val = (NVReadVgaCrtc(dev, 0, i2c->wr) & 0xd0) | (state ? 0x20 : 0);
40 NVWriteVgaCrtc(dev, 0, i2c->wr, val | 0x01);
41}
42
43static void
44nv04_i2c_setsda(void *data, int state)
45{
46 struct nouveau_i2c_chan *i2c = data;
47 struct drm_device *dev = i2c->dev;
48 uint8_t val;
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
Ben Skeggs6ee73862009-12-11 19:24:15 +1000121static 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;
Ben Skeggs6ee73862009-12-11 19:24:15 +1000134
Ben Skeggseeb3ca12011-07-02 20:43:42 +1000135 nv_wr32(i2c->dev, i2c->wr, 4 | (i2c->data ? 2 : 0) | (state ? 1 : 0));
Ben Skeggs6ee73862009-12-11 19:24:15 +1000136}
137
138static void
139nv50_i2c_setsda(void *data, int state)
140{
141 struct nouveau_i2c_chan *i2c = data;
Ben Skeggs6ee73862009-12-11 19:24:15 +1000142
Ben Skeggseeb3ca12011-07-02 20:43:42 +1000143 nv_mask(i2c->dev, i2c->wr, 0x00000006, 4 | (state ? 2 : 0));
Ben Skeggs6ee73862009-12-11 19:24:15 +1000144 i2c->data = state;
145}
146
Ben Skeggseeb3ca12011-07-02 20:43:42 +1000147static int
148nvd0_i2c_getscl(void *data)
149{
150 struct nouveau_i2c_chan *i2c = data;
151 return !!(nv_rd32(i2c->dev, i2c->rd) & 0x10);
152}
153
154static int
155nvd0_i2c_getsda(void *data)
156{
157 struct nouveau_i2c_chan *i2c = data;
158 return !!(nv_rd32(i2c->dev, i2c->rd) & 0x20);
159}
Ben Skeggs6ee73862009-12-11 19:24:15 +1000160
Ben Skeggs486a45c2011-11-11 10:22:19 +1000161static const uint32_t nv50_i2c_port[] = {
162 0x00e138, 0x00e150, 0x00e168, 0x00e180,
163 0x00e254, 0x00e274, 0x00e764, 0x00e780,
164 0x00e79c, 0x00e7b8
165};
166
167static u8 *
168i2c_table(struct drm_device *dev, u8 *version)
169{
170 u8 *dcb = dcb_table(dev), *i2c = NULL;
171 if (dcb) {
172 if (dcb[0] >= 0x15)
173 i2c = ROMPTR(dev, dcb[2]);
174 if (dcb[0] >= 0x30)
175 i2c = ROMPTR(dev, dcb[4]);
176 }
177
178 /* early revisions had no version number, use dcb version */
179 if (i2c) {
180 *version = dcb[0];
181 if (*version >= 0x30)
182 *version = i2c[0];
183 }
184
185 return i2c;
186}
187
Ben Skeggs6ee73862009-12-11 19:24:15 +1000188int
Ben Skeggs486a45c2011-11-11 10:22:19 +1000189nouveau_i2c_init(struct drm_device *dev)
Ben Skeggs6ee73862009-12-11 19:24:15 +1000190{
191 struct drm_nouveau_private *dev_priv = dev->dev_private;
Ben Skeggs486a45c2011-11-11 10:22:19 +1000192 struct nvbios *bios = &dev_priv->vbios;
193 struct nouveau_i2c_chan *port;
194 u8 *i2c, *entry, legacy[2][4] = {};
195 u8 version, entries, recordlen;
196 int ret, i;
Ben Skeggs6ee73862009-12-11 19:24:15 +1000197
Ben Skeggs486a45c2011-11-11 10:22:19 +1000198 INIT_LIST_HEAD(&dev_priv->i2c_ports);
Ben Skeggs6ee73862009-12-11 19:24:15 +1000199
Ben Skeggs486a45c2011-11-11 10:22:19 +1000200 i2c = i2c_table(dev, &version);
201 if (!i2c) {
202 u8 *bmp = &bios->data[bios->offset];
203 if (bios->type != NVBIOS_BMP)
204 return -ENODEV;
205
206 legacy[0][0] = NV_CIO_CRE_DDC_WR__INDEX;
207 legacy[0][1] = NV_CIO_CRE_DDC_STATUS__INDEX;
208 legacy[1][0] = NV_CIO_CRE_DDC0_WR__INDEX;
209 legacy[1][1] = NV_CIO_CRE_DDC0_STATUS__INDEX;
210
211 /* BMP (from v4.0) has i2c info in the structure, it's in a
212 * fixed location on earlier VBIOS
213 */
214 if (bmp[5] < 4)
215 i2c = &bios->data[0x48];
216 else
217 i2c = &bmp[0x36];
218
219 if (i2c[4]) legacy[0][0] = i2c[4];
220 if (i2c[5]) legacy[0][1] = i2c[5];
221 if (i2c[6]) legacy[1][0] = i2c[6];
222 if (i2c[7]) legacy[1][1] = i2c[7];
Ben Skeggs6ee73862009-12-11 19:24:15 +1000223 }
224
Ben Skeggs486a45c2011-11-11 10:22:19 +1000225 if (i2c && version >= 0x30) {
226 entry = i2c[1] + i2c;
227 entries = i2c[2];
228 recordlen = i2c[3];
229 } else
230 if (i2c) {
231 entry = i2c;
232 entries = 16;
233 recordlen = 4;
Ben Skeggs6ee73862009-12-11 19:24:15 +1000234 } else {
Ben Skeggs486a45c2011-11-11 10:22:19 +1000235 entry = legacy[0];
236 entries = 2;
237 recordlen = 4;
Ben Skeggs6ee73862009-12-11 19:24:15 +1000238 }
239
Ben Skeggs486a45c2011-11-11 10:22:19 +1000240 for (i = 0; i < entries; i++, entry += recordlen) {
241 port = kzalloc(sizeof(*port), GFP_KERNEL);
242 if (port == NULL) {
243 nouveau_i2c_fini(dev);
244 return -ENOMEM;
245 }
246
247 port->type = entry[3];
248 if (version < 0x30) {
249 port->type &= 0x07;
250 if (port->type == 0x07)
251 port->type = 0xff;
252 }
253
254 if (port->type == 0xff) {
255 kfree(port);
256 continue;
257 }
258
259 switch (port->type) {
260 case 0: /* NV04:NV50 */
261 port->wr = entry[0];
262 port->rd = 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;
268 case 4: /* NV4E */
269 port->wr = 0x600800 + entry[1];
270 port->rd = port->wr;
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;
276 case 5: /* NV50- */
277 port->wr = entry[0] & 0x0f;
278 if (dev_priv->card_type < NV_D0) {
279 if (port->wr >= ARRAY_SIZE(nv50_i2c_port))
280 break;
281 port->wr = nv50_i2c_port[port->wr];
282 port->rd = port->wr;
283 port->bit.getsda = nv50_i2c_getsda;
284 port->bit.getscl = nv50_i2c_getscl;
285 } else {
286 port->wr = 0x00d014 + (port->wr * 0x20);
287 port->rd = port->wr;
288 port->bit.getsda = nvd0_i2c_getsda;
289 port->bit.getscl = nvd0_i2c_getscl;
290 }
291 port->bit.setsda = nv50_i2c_setsda;
292 port->bit.setscl = nv50_i2c_setscl;
293 break;
294 case 6: /* NV50- DP AUX */
295 port->wr = entry[0];
296 port->rd = port->wr;
297 port->adapter.algo = &nouveau_dp_i2c_algo;
298 break;
299 default:
300 break;
301 }
302
303 if (!port->adapter.algo && !port->wr) {
304 NV_ERROR(dev, "I2C%d: type %d index %x/%x unknown\n",
305 i, port->type, port->wr, port->rd);
306 kfree(port);
307 continue;
308 }
309
310 snprintf(port->adapter.name, sizeof(port->adapter.name),
311 "nouveau-%s-%d", pci_name(dev->pdev), i);
312 port->adapter.owner = THIS_MODULE;
313 port->adapter.dev.parent = &dev->pdev->dev;
314 port->dev = dev;
315 port->index = i;
316 port->dcb = ROM32(entry[0]);
317 i2c_set_adapdata(&port->adapter, i2c);
318
319 if (port->adapter.algo != &nouveau_dp_i2c_algo) {
320 port->adapter.algo_data = &port->bit;
321 port->bit.udelay = 40;
322 port->bit.timeout = usecs_to_jiffies(5000);
323 port->bit.data = port;
324 ret = i2c_bit_add_bus(&port->adapter);
325 } else {
326 port->adapter.algo = &nouveau_dp_i2c_algo;
327 ret = i2c_add_adapter(&port->adapter);
328 }
329
330 if (ret) {
331 NV_ERROR(dev, "I2C%d: failed register: %d\n", i, ret);
332 kfree(port);
333 continue;
334 }
335
336 list_add_tail(&port->head, &dev_priv->i2c_ports);
Ben Skeggs6ee73862009-12-11 19:24:15 +1000337 }
338
Ben Skeggs6ee73862009-12-11 19:24:15 +1000339 return 0;
340}
341
342void
Ben Skeggs486a45c2011-11-11 10:22:19 +1000343nouveau_i2c_fini(struct drm_device *dev)
Ben Skeggs6ee73862009-12-11 19:24:15 +1000344{
Ben Skeggs486a45c2011-11-11 10:22:19 +1000345 struct drm_nouveau_private *dev_priv = dev->dev_private;
346 struct nouveau_i2c_chan *port, *tmp;
Ben Skeggs6ee73862009-12-11 19:24:15 +1000347
Ben Skeggs486a45c2011-11-11 10:22:19 +1000348 list_for_each_entry_safe(port, tmp, &dev_priv->i2c_ports, head) {
349 i2c_del_adapter(&port->adapter);
350 kfree(port);
351 }
Ben Skeggs6ee73862009-12-11 19:24:15 +1000352}
353
354struct nouveau_i2c_chan *
Ben Skeggs486a45c2011-11-11 10:22:19 +1000355nouveau_i2c_find(struct drm_device *dev, u8 index)
Ben Skeggs6ee73862009-12-11 19:24:15 +1000356{
357 struct drm_nouveau_private *dev_priv = dev->dev_private;
Ben Skeggs486a45c2011-11-11 10:22:19 +1000358 struct nouveau_i2c_chan *port;
Ben Skeggs6ee73862009-12-11 19:24:15 +1000359
Ben Skeggs486a45c2011-11-11 10:22:19 +1000360 if (index == NV_I2C_DEFAULT(0) ||
361 index == NV_I2C_DEFAULT(1)) {
362 u8 version, *i2c = i2c_table(dev, &version);
363 if (i2c && version >= 0x30) {
364 if (index == NV_I2C_DEFAULT(0))
365 index = (i2c[4] & 0x0f);
366 else
367 index = (i2c[4] & 0xf0) >> 4;
368 } else {
369 index = 2;
370 }
371 }
372
373 list_for_each_entry(port, &dev_priv->i2c_ports, head) {
374 if (port->index == index)
375 break;
376 }
377
378 if (&port->head == &dev_priv->i2c_ports)
Ben Skeggs6ee73862009-12-11 19:24:15 +1000379 return NULL;
380
Ben Skeggs486a45c2011-11-11 10:22:19 +1000381 if (dev_priv->card_type >= NV_50 && (port->dcb & 0x00000100)) {
382 u32 reg = 0x00e500, val;
383 if (port->type == 6) {
384 reg += port->rd * 0x50;
Ben Skeggs7e99a9b2010-04-24 03:53:14 +1000385 val = 0x2002;
386 } else {
Ben Skeggs486a45c2011-11-11 10:22:19 +1000387 reg += ((port->dcb & 0x1e00) >> 9) * 0x50;
Ben Skeggs7e99a9b2010-04-24 03:53:14 +1000388 val = 0xe001;
389 }
390
Ben Skeggs6b70e482011-07-19 15:59:39 +1000391 /* nfi, but neither auxch or i2c work if it's 1 */
392 nv_mask(dev, reg + 0x0c, 0x00000001, 0x00000000);
393 /* nfi, but switches auxch vs normal i2c */
394 nv_mask(dev, reg + 0x00, 0x0000f003, val);
Ben Skeggs6ee73862009-12-11 19:24:15 +1000395 }
396
Ben Skeggs486a45c2011-11-11 10:22:19 +1000397 return port;
Ben Skeggs6ee73862009-12-11 19:24:15 +1000398}
399
Francisco Jerez6d416d82010-07-19 15:55:08 +0200400bool
401nouveau_probe_i2c_addr(struct nouveau_i2c_chan *i2c, int addr)
402{
Francisco Jerezf1feda72010-07-23 23:17:57 +0200403 uint8_t buf[] = { 0 };
404 struct i2c_msg msgs[] = {
405 {
406 .addr = addr,
407 .flags = 0,
408 .len = 1,
409 .buf = buf,
410 },
411 {
412 .addr = addr,
413 .flags = I2C_M_RD,
414 .len = 1,
415 .buf = buf,
416 }
Francisco Jerez6d416d82010-07-19 15:55:08 +0200417 };
418
Francisco Jerezf1feda72010-07-23 23:17:57 +0200419 return i2c_transfer(&i2c->adapter, msgs, 2) == 2;
Francisco Jerez6d416d82010-07-19 15:55:08 +0200420}
421
422int
423nouveau_i2c_identify(struct drm_device *dev, const char *what,
Francisco Jerez66146da2010-09-23 21:00:40 +0200424 struct i2c_board_info *info,
425 bool (*match)(struct nouveau_i2c_chan *,
426 struct i2c_board_info *),
427 int index)
Francisco Jerez6d416d82010-07-19 15:55:08 +0200428{
429 struct nouveau_i2c_chan *i2c = nouveau_i2c_find(dev, index);
Francisco Jerez946fd352010-07-24 17:41:48 +0200430 int i;
Francisco Jerez6d416d82010-07-19 15:55:08 +0200431
Francisco Jerez6d416d82010-07-19 15:55:08 +0200432 NV_DEBUG(dev, "Probing %ss on I2C bus: %d\n", what, index);
433
Ben Skeggs46b34882011-09-22 12:51:31 +1000434 for (i = 0; i2c && info[i].addr; i++) {
Francisco Jerez66146da2010-09-23 21:00:40 +0200435 if (nouveau_probe_i2c_addr(i2c, info[i].addr) &&
436 (!match || match(i2c, &info[i]))) {
Francisco Jerez6d416d82010-07-19 15:55:08 +0200437 NV_INFO(dev, "Detected %s: %s\n", what, info[i].type);
Francisco Jerez946fd352010-07-24 17:41:48 +0200438 return i;
Francisco Jerez6d416d82010-07-19 15:55:08 +0200439 }
440 }
441
442 NV_DEBUG(dev, "No devices found.\n");
Francisco Jerez6d416d82010-07-19 15:55:08 +0200443
Francisco Jerez946fd352010-07-24 17:41:48 +0200444 return -ENODEV;
Francisco Jerez6d416d82010-07-19 15:55:08 +0200445}