Loading...
1/*
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
25#include "drmP.h"
26#include "nouveau_drv.h"
27#include "nouveau_i2c.h"
28#include "nouveau_hw.h"
29
30static void
31nv04_i2c_setscl(void *data, int state)
32{
33 struct nouveau_i2c_chan *i2c = data;
34 struct drm_device *dev = i2c->dev;
35 uint8_t val;
36
37 val = (NVReadVgaCrtc(dev, 0, i2c->wr) & 0xd0) | (state ? 0x20 : 0);
38 NVWriteVgaCrtc(dev, 0, i2c->wr, val | 0x01);
39}
40
41static void
42nv04_i2c_setsda(void *data, int state)
43{
44 struct nouveau_i2c_chan *i2c = data;
45 struct drm_device *dev = i2c->dev;
46 uint8_t val;
47
48 val = (NVReadVgaCrtc(dev, 0, i2c->wr) & 0xe0) | (state ? 0x10 : 0);
49 NVWriteVgaCrtc(dev, 0, i2c->wr, val | 0x01);
50}
51
52static int
53nv04_i2c_getscl(void *data)
54{
55 struct nouveau_i2c_chan *i2c = data;
56 struct drm_device *dev = i2c->dev;
57
58 return !!(NVReadVgaCrtc(dev, 0, i2c->rd) & 4);
59}
60
61static int
62nv04_i2c_getsda(void *data)
63{
64 struct nouveau_i2c_chan *i2c = data;
65 struct drm_device *dev = i2c->dev;
66
67 return !!(NVReadVgaCrtc(dev, 0, i2c->rd) & 8);
68}
69
70static void
71nv4e_i2c_setscl(void *data, int state)
72{
73 struct nouveau_i2c_chan *i2c = data;
74 struct drm_device *dev = i2c->dev;
75 uint8_t val;
76
77 val = (nv_rd32(dev, i2c->wr) & 0xd0) | (state ? 0x20 : 0);
78 nv_wr32(dev, i2c->wr, val | 0x01);
79}
80
81static void
82nv4e_i2c_setsda(void *data, int state)
83{
84 struct nouveau_i2c_chan *i2c = data;
85 struct drm_device *dev = i2c->dev;
86 uint8_t val;
87
88 val = (nv_rd32(dev, i2c->wr) & 0xe0) | (state ? 0x10 : 0);
89 nv_wr32(dev, i2c->wr, val | 0x01);
90}
91
92static int
93nv4e_i2c_getscl(void *data)
94{
95 struct nouveau_i2c_chan *i2c = data;
96 struct drm_device *dev = i2c->dev;
97
98 return !!((nv_rd32(dev, i2c->rd) >> 16) & 4);
99}
100
101static int
102nv4e_i2c_getsda(void *data)
103{
104 struct nouveau_i2c_chan *i2c = data;
105 struct drm_device *dev = i2c->dev;
106
107 return !!((nv_rd32(dev, i2c->rd) >> 16) & 8);
108}
109
110static int
111nv50_i2c_getscl(void *data)
112{
113 struct nouveau_i2c_chan *i2c = data;
114 struct drm_device *dev = i2c->dev;
115
116 return !!(nv_rd32(dev, i2c->rd) & 1);
117}
118
119
120static int
121nv50_i2c_getsda(void *data)
122{
123 struct nouveau_i2c_chan *i2c = data;
124 struct drm_device *dev = i2c->dev;
125
126 return !!(nv_rd32(dev, i2c->rd) & 2);
127}
128
129static void
130nv50_i2c_setscl(void *data, int state)
131{
132 struct nouveau_i2c_chan *i2c = data;
133 struct drm_device *dev = i2c->dev;
134
135 nv_wr32(dev, i2c->wr, 4 | (i2c->data ? 2 : 0) | (state ? 1 : 0));
136}
137
138static void
139nv50_i2c_setsda(void *data, int state)
140{
141 struct nouveau_i2c_chan *i2c = data;
142 struct drm_device *dev = i2c->dev;
143
144 nv_wr32(dev, i2c->wr,
145 (nv_rd32(dev, i2c->rd) & 1) | 4 | (state ? 2 : 0));
146 i2c->data = state;
147}
148
149static const uint32_t nv50_i2c_port[] = {
150 0x00e138, 0x00e150, 0x00e168, 0x00e180,
151 0x00e254, 0x00e274, 0x00e764, 0x00e780,
152 0x00e79c, 0x00e7b8
153};
154#define NV50_I2C_PORTS ARRAY_SIZE(nv50_i2c_port)
155
156int
157nouveau_i2c_init(struct drm_device *dev, struct dcb_i2c_entry *entry, int index)
158{
159 struct drm_nouveau_private *dev_priv = dev->dev_private;
160 struct nouveau_i2c_chan *i2c;
161 int ret;
162
163 if (entry->chan)
164 return -EEXIST;
165
166 if (dev_priv->card_type >= NV_50 && entry->read >= NV50_I2C_PORTS) {
167 NV_ERROR(dev, "unknown i2c port %d\n", entry->read);
168 return -EINVAL;
169 }
170
171 i2c = kzalloc(sizeof(*i2c), GFP_KERNEL);
172 if (i2c == NULL)
173 return -ENOMEM;
174
175 switch (entry->port_type) {
176 case 0:
177 i2c->bit.setsda = nv04_i2c_setsda;
178 i2c->bit.setscl = nv04_i2c_setscl;
179 i2c->bit.getsda = nv04_i2c_getsda;
180 i2c->bit.getscl = nv04_i2c_getscl;
181 i2c->rd = entry->read;
182 i2c->wr = entry->write;
183 break;
184 case 4:
185 i2c->bit.setsda = nv4e_i2c_setsda;
186 i2c->bit.setscl = nv4e_i2c_setscl;
187 i2c->bit.getsda = nv4e_i2c_getsda;
188 i2c->bit.getscl = nv4e_i2c_getscl;
189 i2c->rd = 0x600800 + entry->read;
190 i2c->wr = 0x600800 + entry->write;
191 break;
192 case 5:
193 i2c->bit.setsda = nv50_i2c_setsda;
194 i2c->bit.setscl = nv50_i2c_setscl;
195 i2c->bit.getsda = nv50_i2c_getsda;
196 i2c->bit.getscl = nv50_i2c_getscl;
197 i2c->rd = nv50_i2c_port[entry->read];
198 i2c->wr = i2c->rd;
199 break;
200 case 6:
201 i2c->rd = entry->read;
202 i2c->wr = entry->write;
203 break;
204 default:
205 NV_ERROR(dev, "DCB I2C port type %d unknown\n",
206 entry->port_type);
207 kfree(i2c);
208 return -EINVAL;
209 }
210
211 snprintf(i2c->adapter.name, sizeof(i2c->adapter.name),
212 "nouveau-%s-%d", pci_name(dev->pdev), index);
213 i2c->adapter.owner = THIS_MODULE;
214 i2c->adapter.dev.parent = &dev->pdev->dev;
215 i2c->dev = dev;
216 i2c_set_adapdata(&i2c->adapter, i2c);
217
218 if (entry->port_type < 6) {
219 i2c->adapter.algo_data = &i2c->bit;
220 i2c->bit.udelay = 40;
221 i2c->bit.timeout = usecs_to_jiffies(5000);
222 i2c->bit.data = i2c;
223 ret = i2c_bit_add_bus(&i2c->adapter);
224 } else {
225 i2c->adapter.algo = &nouveau_dp_i2c_algo;
226 ret = i2c_add_adapter(&i2c->adapter);
227 }
228
229 if (ret) {
230 NV_ERROR(dev, "Failed to register i2c %d\n", index);
231 kfree(i2c);
232 return ret;
233 }
234
235 entry->chan = i2c;
236 return 0;
237}
238
239void
240nouveau_i2c_fini(struct drm_device *dev, struct dcb_i2c_entry *entry)
241{
242 if (!entry->chan)
243 return;
244
245 i2c_del_adapter(&entry->chan->adapter);
246 kfree(entry->chan);
247 entry->chan = NULL;
248}
249
250struct nouveau_i2c_chan *
251nouveau_i2c_find(struct drm_device *dev, int index)
252{
253 struct drm_nouveau_private *dev_priv = dev->dev_private;
254 struct dcb_i2c_entry *i2c = &dev_priv->vbios.dcb.i2c[index];
255
256 if (index >= DCB_MAX_NUM_I2C_ENTRIES)
257 return NULL;
258
259 if (dev_priv->card_type >= NV_50 && (i2c->entry & 0x00000100)) {
260 uint32_t reg = 0xe500, val;
261
262 if (i2c->port_type == 6) {
263 reg += i2c->read * 0x50;
264 val = 0x2002;
265 } else {
266 reg += ((i2c->entry & 0x1e00) >> 9) * 0x50;
267 val = 0xe001;
268 }
269
270 nv_wr32(dev, reg, (nv_rd32(dev, reg) & ~0xf003) | val);
271 }
272
273 if (!i2c->chan && nouveau_i2c_init(dev, i2c, index))
274 return NULL;
275 return i2c->chan;
276}
277
278bool
279nouveau_probe_i2c_addr(struct nouveau_i2c_chan *i2c, int addr)
280{
281 uint8_t buf[] = { 0 };
282 struct i2c_msg msgs[] = {
283 {
284 .addr = addr,
285 .flags = 0,
286 .len = 1,
287 .buf = buf,
288 },
289 {
290 .addr = addr,
291 .flags = I2C_M_RD,
292 .len = 1,
293 .buf = buf,
294 }
295 };
296
297 return i2c_transfer(&i2c->adapter, msgs, 2) == 2;
298}
299
300int
301nouveau_i2c_identify(struct drm_device *dev, const char *what,
302 struct i2c_board_info *info,
303 bool (*match)(struct nouveau_i2c_chan *,
304 struct i2c_board_info *),
305 int index)
306{
307 struct nouveau_i2c_chan *i2c = nouveau_i2c_find(dev, index);
308 int i;
309
310 NV_DEBUG(dev, "Probing %ss on I2C bus: %d\n", what, index);
311
312 for (i = 0; info[i].addr; i++) {
313 if (nouveau_probe_i2c_addr(i2c, info[i].addr) &&
314 (!match || match(i2c, &info[i]))) {
315 NV_INFO(dev, "Detected %s: %s\n", what, info[i].type);
316 return i;
317 }
318 }
319
320 NV_DEBUG(dev, "No devices found.\n");
321
322 return -ENODEV;
323}
1/*
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
25#include <linux/module.h>
26
27#include "drmP.h"
28#include "nouveau_drv.h"
29#include "nouveau_i2c.h"
30#include "nouveau_hw.h"
31
32static void
33i2c_drive_scl(void *data, int state)
34{
35 struct nouveau_i2c_chan *port = data;
36 if (port->type == 0) {
37 u8 val = NVReadVgaCrtc(port->dev, 0, port->drive);
38 if (state) val |= 0x20;
39 else val &= 0xdf;
40 NVWriteVgaCrtc(port->dev, 0, port->drive, val | 0x01);
41 } else
42 if (port->type == 4) {
43 nv_mask(port->dev, port->drive, 0x2f, state ? 0x21 : 0x01);
44 } else
45 if (port->type == 5) {
46 if (state) port->state |= 0x01;
47 else port->state &= 0xfe;
48 nv_wr32(port->dev, port->drive, 4 | port->state);
49 }
50}
51
52static void
53i2c_drive_sda(void *data, int state)
54{
55 struct nouveau_i2c_chan *port = data;
56 if (port->type == 0) {
57 u8 val = NVReadVgaCrtc(port->dev, 0, port->drive);
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 }
70}
71
72static int
73i2c_sense_scl(void *data)
74{
75 struct nouveau_i2c_chan *port = data;
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;
90}
91
92static int
93i2c_sense_sda(void *data)
94{
95 struct nouveau_i2c_chan *port = data;
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;
110}
111
112static const uint32_t nv50_i2c_port[] = {
113 0x00e138, 0x00e150, 0x00e168, 0x00e180,
114 0x00e254, 0x00e274, 0x00e764, 0x00e780,
115 0x00e79c, 0x00e7b8
116};
117
118static u8 *
119i2c_table(struct drm_device *dev, u8 *version)
120{
121 u8 *dcb = dcb_table(dev), *i2c = NULL;
122 if (dcb) {
123 if (dcb[0] >= 0x15)
124 i2c = ROMPTR(dev, dcb[2]);
125 if (dcb[0] >= 0x30)
126 i2c = ROMPTR(dev, dcb[4]);
127 }
128
129 /* early revisions had no version number, use dcb version */
130 if (i2c) {
131 *version = dcb[0];
132 if (*version >= 0x30)
133 *version = i2c[0];
134 }
135
136 return i2c;
137}
138
139int
140nouveau_i2c_init(struct drm_device *dev)
141{
142 struct drm_nouveau_private *dev_priv = dev->dev_private;
143 struct nvbios *bios = &dev_priv->vbios;
144 struct nouveau_i2c_chan *port;
145 u8 version = 0x00, entries, recordlen;
146 u8 *i2c, *entry, legacy[2][4] = {};
147 int ret, i;
148
149 INIT_LIST_HEAD(&dev_priv->i2c_ports);
150
151 i2c = i2c_table(dev, &version);
152 if (!i2c) {
153 u8 *bmp = &bios->data[bios->offset];
154 if (bios->type != NVBIOS_BMP)
155 return -ENODEV;
156
157 legacy[0][0] = NV_CIO_CRE_DDC_WR__INDEX;
158 legacy[0][1] = NV_CIO_CRE_DDC_STATUS__INDEX;
159 legacy[1][0] = NV_CIO_CRE_DDC0_WR__INDEX;
160 legacy[1][1] = NV_CIO_CRE_DDC0_STATUS__INDEX;
161
162 /* BMP (from v4.0) has i2c info in the structure, it's in a
163 * fixed location on earlier VBIOS
164 */
165 if (bmp[5] < 4)
166 i2c = &bios->data[0x48];
167 else
168 i2c = &bmp[0x36];
169
170 if (i2c[4]) legacy[0][0] = i2c[4];
171 if (i2c[5]) legacy[0][1] = i2c[5];
172 if (i2c[6]) legacy[1][0] = i2c[6];
173 if (i2c[7]) legacy[1][1] = i2c[7];
174 }
175
176 if (version >= 0x30) {
177 entry = i2c[1] + i2c;
178 entries = i2c[2];
179 recordlen = i2c[3];
180 } else
181 if (version) {
182 entry = i2c;
183 entries = 16;
184 recordlen = 4;
185 } else {
186 entry = legacy[0];
187 entries = 2;
188 recordlen = 4;
189 }
190
191 for (i = 0; i < entries; i++, entry += recordlen) {
192 port = kzalloc(sizeof(*port), GFP_KERNEL);
193 if (port == NULL) {
194 nouveau_i2c_fini(dev);
195 return -ENOMEM;
196 }
197
198 port->type = entry[3];
199 if (version < 0x30) {
200 port->type &= 0x07;
201 if (port->type == 0x07)
202 port->type = 0xff;
203 }
204
205 if (port->type == 0xff) {
206 kfree(port);
207 continue;
208 }
209
210 switch (port->type) {
211 case 0: /* NV04:NV50 */
212 port->drive = entry[0];
213 port->sense = entry[1];
214 break;
215 case 4: /* NV4E */
216 port->drive = 0x600800 + entry[1];
217 port->sense = port->drive;
218 break;
219 case 5: /* NV50- */
220 port->drive = entry[0] & 0x0f;
221 if (dev_priv->card_type < NV_D0) {
222 if (port->drive >= ARRAY_SIZE(nv50_i2c_port))
223 break;
224 port->drive = nv50_i2c_port[port->drive];
225 port->sense = port->drive;
226 } else {
227 port->drive = 0x00d014 + (port->drive * 0x20);
228 port->sense = port->drive;
229 }
230 break;
231 case 6: /* NV50- DP AUX */
232 port->drive = entry[0];
233 port->sense = port->drive;
234 port->adapter.algo = &nouveau_dp_i2c_algo;
235 break;
236 default:
237 break;
238 }
239
240 if (!port->adapter.algo && !port->drive) {
241 NV_ERROR(dev, "I2C%d: type %d index %x/%x unknown\n",
242 i, port->type, port->drive, port->sense);
243 kfree(port);
244 continue;
245 }
246
247 snprintf(port->adapter.name, sizeof(port->adapter.name),
248 "nouveau-%s-%d", pci_name(dev->pdev), i);
249 port->adapter.owner = THIS_MODULE;
250 port->adapter.dev.parent = &dev->pdev->dev;
251 port->dev = dev;
252 port->index = i;
253 port->dcb = ROM32(entry[0]);
254 i2c_set_adapdata(&port->adapter, i2c);
255
256 if (port->adapter.algo != &nouveau_dp_i2c_algo) {
257 port->adapter.algo_data = &port->bit;
258 port->bit.udelay = 10;
259 port->bit.timeout = usecs_to_jiffies(2200);
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
270 ret = i2c_bit_add_bus(&port->adapter);
271 } else {
272 port->adapter.algo = &nouveau_dp_i2c_algo;
273 ret = i2c_add_adapter(&port->adapter);
274 }
275
276 if (ret) {
277 NV_ERROR(dev, "I2C%d: failed register: %d\n", i, ret);
278 kfree(port);
279 continue;
280 }
281
282 list_add_tail(&port->head, &dev_priv->i2c_ports);
283 }
284
285 return 0;
286}
287
288void
289nouveau_i2c_fini(struct drm_device *dev)
290{
291 struct drm_nouveau_private *dev_priv = dev->dev_private;
292 struct nouveau_i2c_chan *port, *tmp;
293
294 list_for_each_entry_safe(port, tmp, &dev_priv->i2c_ports, head) {
295 i2c_del_adapter(&port->adapter);
296 kfree(port);
297 }
298}
299
300struct nouveau_i2c_chan *
301nouveau_i2c_find(struct drm_device *dev, u8 index)
302{
303 struct drm_nouveau_private *dev_priv = dev->dev_private;
304 struct nouveau_i2c_chan *port;
305
306 if (index == NV_I2C_DEFAULT(0) ||
307 index == NV_I2C_DEFAULT(1)) {
308 u8 version, *i2c = i2c_table(dev, &version);
309 if (i2c && version >= 0x30) {
310 if (index == NV_I2C_DEFAULT(0))
311 index = (i2c[4] & 0x0f);
312 else
313 index = (i2c[4] & 0xf0) >> 4;
314 } else {
315 index = 2;
316 }
317 }
318
319 list_for_each_entry(port, &dev_priv->i2c_ports, head) {
320 if (port->index == index)
321 break;
322 }
323
324 if (&port->head == &dev_priv->i2c_ports)
325 return NULL;
326
327 if (dev_priv->card_type >= NV_50 && (port->dcb & 0x00000100)) {
328 u32 reg = 0x00e500, val;
329 if (port->type == 6) {
330 reg += port->drive * 0x50;
331 val = 0x2002;
332 } else {
333 reg += ((port->dcb & 0x1e00) >> 9) * 0x50;
334 val = 0xe001;
335 }
336
337 /* nfi, but neither auxch or i2c work if it's 1 */
338 nv_mask(dev, reg + 0x0c, 0x00000001, 0x00000000);
339 /* nfi, but switches auxch vs normal i2c */
340 nv_mask(dev, reg + 0x00, 0x0000f003, val);
341 }
342
343 return port;
344}
345
346bool
347nouveau_probe_i2c_addr(struct nouveau_i2c_chan *i2c, int addr)
348{
349 uint8_t buf[] = { 0 };
350 struct i2c_msg msgs[] = {
351 {
352 .addr = addr,
353 .flags = 0,
354 .len = 1,
355 .buf = buf,
356 },
357 {
358 .addr = addr,
359 .flags = I2C_M_RD,
360 .len = 1,
361 .buf = buf,
362 }
363 };
364
365 return i2c_transfer(&i2c->adapter, msgs, 2) == 2;
366}
367
368int
369nouveau_i2c_identify(struct drm_device *dev, const char *what,
370 struct i2c_board_info *info,
371 bool (*match)(struct nouveau_i2c_chan *,
372 struct i2c_board_info *),
373 int index)
374{
375 struct nouveau_i2c_chan *i2c = nouveau_i2c_find(dev, index);
376 int i;
377
378 if (!i2c) {
379 NV_DEBUG(dev, "No bus when probing %s on %d\n", what, index);
380 return -ENODEV;
381 }
382
383 NV_DEBUG(dev, "Probing %ss on I2C bus: %d\n", what, i2c->index);
384 for (i = 0; info[i].addr; i++) {
385 if (nouveau_probe_i2c_addr(i2c, info[i].addr) &&
386 (!match || match(i2c, &info[i]))) {
387 NV_INFO(dev, "Detected %s: %s\n", what, info[i].type);
388 return i;
389 }
390 }
391
392 NV_DEBUG(dev, "No devices found.\n");
393 return -ENODEV;
394}