diff options
Diffstat (limited to 'drivers/media/dvb/frontends/dibx000_common.c')
-rw-r--r-- | drivers/media/dvb/frontends/dibx000_common.c | 514 |
1 files changed, 514 insertions, 0 deletions
diff --git a/drivers/media/dvb/frontends/dibx000_common.c b/drivers/media/dvb/frontends/dibx000_common.c new file mode 100644 index 00000000000..774d507b66c --- /dev/null +++ b/drivers/media/dvb/frontends/dibx000_common.c | |||
@@ -0,0 +1,514 @@ | |||
1 | #include <linux/i2c.h> | ||
2 | #include <linux/mutex.h> | ||
3 | |||
4 | #include "dibx000_common.h" | ||
5 | |||
6 | static int debug; | ||
7 | module_param(debug, int, 0644); | ||
8 | MODULE_PARM_DESC(debug, "turn on debugging (default: 0)"); | ||
9 | |||
10 | #define dprintk(args...) do { if (debug) { printk(KERN_DEBUG "DiBX000: "); printk(args); printk("\n"); } } while (0) | ||
11 | |||
12 | static int dibx000_write_word(struct dibx000_i2c_master *mst, u16 reg, u16 val) | ||
13 | { | ||
14 | int ret; | ||
15 | |||
16 | if (mutex_lock_interruptible(&mst->i2c_buffer_lock) < 0) { | ||
17 | dprintk("could not acquire lock"); | ||
18 | return -EINVAL; | ||
19 | } | ||
20 | |||
21 | mst->i2c_write_buffer[0] = (reg >> 8) & 0xff; | ||
22 | mst->i2c_write_buffer[1] = reg & 0xff; | ||
23 | mst->i2c_write_buffer[2] = (val >> 8) & 0xff; | ||
24 | mst->i2c_write_buffer[3] = val & 0xff; | ||
25 | |||
26 | memset(mst->msg, 0, sizeof(struct i2c_msg)); | ||
27 | mst->msg[0].addr = mst->i2c_addr; | ||
28 | mst->msg[0].flags = 0; | ||
29 | mst->msg[0].buf = mst->i2c_write_buffer; | ||
30 | mst->msg[0].len = 4; | ||
31 | |||
32 | ret = i2c_transfer(mst->i2c_adap, mst->msg, 1) != 1 ? -EREMOTEIO : 0; | ||
33 | mutex_unlock(&mst->i2c_buffer_lock); | ||
34 | |||
35 | return ret; | ||
36 | } | ||
37 | |||
38 | static u16 dibx000_read_word(struct dibx000_i2c_master *mst, u16 reg) | ||
39 | { | ||
40 | u16 ret; | ||
41 | |||
42 | if (mutex_lock_interruptible(&mst->i2c_buffer_lock) < 0) { | ||
43 | dprintk("could not acquire lock"); | ||
44 | return 0; | ||
45 | } | ||
46 | |||
47 | mst->i2c_write_buffer[0] = reg >> 8; | ||
48 | mst->i2c_write_buffer[1] = reg & 0xff; | ||
49 | |||
50 | memset(mst->msg, 0, 2 * sizeof(struct i2c_msg)); | ||
51 | mst->msg[0].addr = mst->i2c_addr; | ||
52 | mst->msg[0].flags = 0; | ||
53 | mst->msg[0].buf = mst->i2c_write_buffer; | ||
54 | mst->msg[0].len = 2; | ||
55 | mst->msg[1].addr = mst->i2c_addr; | ||
56 | mst->msg[1].flags = I2C_M_RD; | ||
57 | mst->msg[1].buf = mst->i2c_read_buffer; | ||
58 | mst->msg[1].len = 2; | ||
59 | |||
60 | if (i2c_transfer(mst->i2c_adap, mst->msg, 2) != 2) | ||
61 | dprintk("i2c read error on %d", reg); | ||
62 | |||
63 | ret = (mst->i2c_read_buffer[0] << 8) | mst->i2c_read_buffer[1]; | ||
64 | mutex_unlock(&mst->i2c_buffer_lock); | ||
65 | |||
66 | return ret; | ||
67 | } | ||
68 | |||
69 | static int dibx000_is_i2c_done(struct dibx000_i2c_master *mst) | ||
70 | { | ||
71 | int i = 100; | ||
72 | u16 status; | ||
73 | |||
74 | while (((status = dibx000_read_word(mst, mst->base_reg + 2)) & 0x0100) == 0 && --i > 0) | ||
75 | ; | ||
76 | |||
77 | /* i2c timed out */ | ||
78 | if (i == 0) | ||
79 | return -EREMOTEIO; | ||
80 | |||
81 | /* no acknowledge */ | ||
82 | if ((status & 0x0080) == 0) | ||
83 | return -EREMOTEIO; | ||
84 | |||
85 | return 0; | ||
86 | } | ||
87 | |||
88 | static int dibx000_master_i2c_write(struct dibx000_i2c_master *mst, struct i2c_msg *msg, u8 stop) | ||
89 | { | ||
90 | u16 data; | ||
91 | u16 da; | ||
92 | u16 i; | ||
93 | u16 txlen = msg->len, len; | ||
94 | const u8 *b = msg->buf; | ||
95 | |||
96 | while (txlen) { | ||
97 | dibx000_read_word(mst, mst->base_reg + 2); | ||
98 | |||
99 | len = txlen > 8 ? 8 : txlen; | ||
100 | for (i = 0; i < len; i += 2) { | ||
101 | data = *b++ << 8; | ||
102 | if (i+1 < len) | ||
103 | data |= *b++; | ||
104 | dibx000_write_word(mst, mst->base_reg, data); | ||
105 | } | ||
106 | da = (((u8) (msg->addr)) << 9) | | ||
107 | (1 << 8) | | ||
108 | (1 << 7) | | ||
109 | (0 << 6) | | ||
110 | (0 << 5) | | ||
111 | ((len & 0x7) << 2) | | ||
112 | (0 << 1) | | ||
113 | (0 << 0); | ||
114 | |||
115 | if (txlen == msg->len) | ||
116 | da |= 1 << 5; /* start */ | ||
117 | |||
118 | if (txlen-len == 0 && stop) | ||
119 | da |= 1 << 6; /* stop */ | ||
120 | |||
121 | dibx000_write_word(mst, mst->base_reg+1, da); | ||
122 | |||
123 | if (dibx000_is_i2c_done(mst) != 0) | ||
124 | return -EREMOTEIO; | ||
125 | txlen -= len; | ||
126 | } | ||
127 | |||
128 | return 0; | ||
129 | } | ||
130 | |||
131 | static int dibx000_master_i2c_read(struct dibx000_i2c_master *mst, struct i2c_msg *msg) | ||
132 | { | ||
133 | u16 da; | ||
134 | u8 *b = msg->buf; | ||
135 | u16 rxlen = msg->len, len; | ||
136 | |||
137 | while (rxlen) { | ||
138 | len = rxlen > 8 ? 8 : rxlen; | ||
139 | da = (((u8) (msg->addr)) << 9) | | ||
140 | (1 << 8) | | ||
141 | (1 << 7) | | ||
142 | (0 << 6) | | ||
143 | (0 << 5) | | ||
144 | ((len & 0x7) << 2) | | ||
145 | (1 << 1) | | ||
146 | (0 << 0); | ||
147 | |||
148 | if (rxlen == msg->len) | ||
149 | da |= 1 << 5; /* start */ | ||
150 | |||
151 | if (rxlen-len == 0) | ||
152 | da |= 1 << 6; /* stop */ | ||
153 | dibx000_write_word(mst, mst->base_reg+1, da); | ||
154 | |||
155 | if (dibx000_is_i2c_done(mst) != 0) | ||
156 | return -EREMOTEIO; | ||
157 | |||
158 | rxlen -= len; | ||
159 | |||
160 | while (len) { | ||
161 | da = dibx000_read_word(mst, mst->base_reg); | ||
162 | *b++ = (da >> 8) & 0xff; | ||
163 | len--; | ||
164 | if (len >= 1) { | ||
165 | *b++ = da & 0xff; | ||
166 | len--; | ||
167 | } | ||
168 | } | ||
169 | } | ||
170 | |||
171 | return 0; | ||
172 | } | ||
173 | |||
174 | int dibx000_i2c_set_speed(struct i2c_adapter *i2c_adap, u16 speed) | ||
175 | { | ||
176 | struct dibx000_i2c_master *mst = i2c_get_adapdata(i2c_adap); | ||
177 | |||
178 | if (mst->device_rev < DIB7000MC && speed < 235) | ||
179 | speed = 235; | ||
180 | return dibx000_write_word(mst, mst->base_reg + 3, (u16)(60000 / speed)); | ||
181 | |||
182 | } | ||
183 | EXPORT_SYMBOL(dibx000_i2c_set_speed); | ||
184 | |||
185 | static u32 dibx000_i2c_func(struct i2c_adapter *adapter) | ||
186 | { | ||
187 | return I2C_FUNC_I2C; | ||
188 | } | ||
189 | |||
190 | static int dibx000_i2c_select_interface(struct dibx000_i2c_master *mst, | ||
191 | enum dibx000_i2c_interface intf) | ||
192 | { | ||
193 | if (mst->device_rev > DIB3000MC && mst->selected_interface != intf) { | ||
194 | dprintk("selecting interface: %d", intf); | ||
195 | mst->selected_interface = intf; | ||
196 | return dibx000_write_word(mst, mst->base_reg + 4, intf); | ||
197 | } | ||
198 | return 0; | ||
199 | } | ||
200 | |||
201 | static int dibx000_i2c_master_xfer_gpio12(struct i2c_adapter *i2c_adap, struct i2c_msg msg[], int num) | ||
202 | { | ||
203 | struct dibx000_i2c_master *mst = i2c_get_adapdata(i2c_adap); | ||
204 | int msg_index; | ||
205 | int ret = 0; | ||
206 | |||
207 | dibx000_i2c_select_interface(mst, DIBX000_I2C_INTERFACE_GPIO_1_2); | ||
208 | for (msg_index = 0; msg_index < num; msg_index++) { | ||
209 | if (msg[msg_index].flags & I2C_M_RD) { | ||
210 | ret = dibx000_master_i2c_read(mst, &msg[msg_index]); | ||
211 | if (ret != 0) | ||
212 | return 0; | ||
213 | } else { | ||
214 | ret = dibx000_master_i2c_write(mst, &msg[msg_index], 1); | ||
215 | if (ret != 0) | ||
216 | return 0; | ||
217 | } | ||
218 | } | ||
219 | |||
220 | return num; | ||
221 | } | ||
222 | |||
223 | static int dibx000_i2c_master_xfer_gpio34(struct i2c_adapter *i2c_adap, struct i2c_msg msg[], int num) | ||
224 | { | ||
225 | struct dibx000_i2c_master *mst = i2c_get_adapdata(i2c_adap); | ||
226 | int msg_index; | ||
227 | int ret = 0; | ||
228 | |||
229 | dibx000_i2c_select_interface(mst, DIBX000_I2C_INTERFACE_GPIO_3_4); | ||
230 | for (msg_index = 0; msg_index < num; msg_index++) { | ||
231 | if (msg[msg_index].flags & I2C_M_RD) { | ||
232 | ret = dibx000_master_i2c_read(mst, &msg[msg_index]); | ||
233 | if (ret != 0) | ||
234 | return 0; | ||
235 | } else { | ||
236 | ret = dibx000_master_i2c_write(mst, &msg[msg_index], 1); | ||
237 | if (ret != 0) | ||
238 | return 0; | ||
239 | } | ||
240 | } | ||
241 | |||
242 | return num; | ||
243 | } | ||
244 | |||
245 | static struct i2c_algorithm dibx000_i2c_master_gpio12_xfer_algo = { | ||
246 | .master_xfer = dibx000_i2c_master_xfer_gpio12, | ||
247 | .functionality = dibx000_i2c_func, | ||
248 | }; | ||
249 | |||
250 | static struct i2c_algorithm dibx000_i2c_master_gpio34_xfer_algo = { | ||
251 | .master_xfer = dibx000_i2c_master_xfer_gpio34, | ||
252 | .functionality = dibx000_i2c_func, | ||
253 | }; | ||
254 | |||
255 | static int dibx000_i2c_gate_ctrl(struct dibx000_i2c_master *mst, u8 tx[4], | ||
256 | u8 addr, int onoff) | ||
257 | { | ||
258 | u16 val; | ||
259 | |||
260 | |||
261 | if (onoff) | ||
262 | val = addr << 8; // bit 7 = use master or not, if 0, the gate is open | ||
263 | else | ||
264 | val = 1 << 7; | ||
265 | |||
266 | if (mst->device_rev > DIB7000) | ||
267 | val <<= 1; | ||
268 | |||
269 | tx[0] = (((mst->base_reg + 1) >> 8) & 0xff); | ||
270 | tx[1] = ((mst->base_reg + 1) & 0xff); | ||
271 | tx[2] = val >> 8; | ||
272 | tx[3] = val & 0xff; | ||
273 | |||
274 | return 0; | ||
275 | } | ||
276 | |||
277 | static int dibx000_i2c_gated_gpio67_xfer(struct i2c_adapter *i2c_adap, | ||
278 | struct i2c_msg msg[], int num) | ||
279 | { | ||
280 | struct dibx000_i2c_master *mst = i2c_get_adapdata(i2c_adap); | ||
281 | int ret; | ||
282 | |||
283 | if (num > 32) { | ||
284 | dprintk("%s: too much I2C message to be transmitted (%i).\ | ||
285 | Maximum is 32", __func__, num); | ||
286 | return -ENOMEM; | ||
287 | } | ||
288 | |||
289 | dibx000_i2c_select_interface(mst, DIBX000_I2C_INTERFACE_GPIO_6_7); | ||
290 | |||
291 | if (mutex_lock_interruptible(&mst->i2c_buffer_lock) < 0) { | ||
292 | dprintk("could not acquire lock"); | ||
293 | return -EINVAL; | ||
294 | } | ||
295 | |||
296 | memset(mst->msg, 0, sizeof(struct i2c_msg) * (2 + num)); | ||
297 | |||
298 | /* open the gate */ | ||
299 | dibx000_i2c_gate_ctrl(mst, &mst->i2c_write_buffer[0], msg[0].addr, 1); | ||
300 | mst->msg[0].addr = mst->i2c_addr; | ||
301 | mst->msg[0].buf = &mst->i2c_write_buffer[0]; | ||
302 | mst->msg[0].len = 4; | ||
303 | |||
304 | memcpy(&mst->msg[1], msg, sizeof(struct i2c_msg) * num); | ||
305 | |||
306 | /* close the gate */ | ||
307 | dibx000_i2c_gate_ctrl(mst, &mst->i2c_write_buffer[4], 0, 0); | ||
308 | mst->msg[num + 1].addr = mst->i2c_addr; | ||
309 | mst->msg[num + 1].buf = &mst->i2c_write_buffer[4]; | ||
310 | mst->msg[num + 1].len = 4; | ||
311 | |||
312 | ret = (i2c_transfer(mst->i2c_adap, mst->msg, 2 + num) == 2 + num ? | ||
313 | num : -EIO); | ||
314 | |||
315 | mutex_unlock(&mst->i2c_buffer_lock); | ||
316 | return ret; | ||
317 | } | ||
318 | |||
319 | static struct i2c_algorithm dibx000_i2c_gated_gpio67_algo = { | ||
320 | .master_xfer = dibx000_i2c_gated_gpio67_xfer, | ||
321 | .functionality = dibx000_i2c_func, | ||
322 | }; | ||
323 | |||
324 | static int dibx000_i2c_gated_tuner_xfer(struct i2c_adapter *i2c_adap, | ||
325 | struct i2c_msg msg[], int num) | ||
326 | { | ||
327 | struct dibx000_i2c_master *mst = i2c_get_adapdata(i2c_adap); | ||
328 | int ret; | ||
329 | |||
330 | if (num > 32) { | ||
331 | dprintk("%s: too much I2C message to be transmitted (%i).\ | ||
332 | Maximum is 32", __func__, num); | ||
333 | return -ENOMEM; | ||
334 | } | ||
335 | |||
336 | dibx000_i2c_select_interface(mst, DIBX000_I2C_INTERFACE_TUNER); | ||
337 | |||
338 | if (mutex_lock_interruptible(&mst->i2c_buffer_lock) < 0) { | ||
339 | dprintk("could not acquire lock"); | ||
340 | return -EINVAL; | ||
341 | } | ||
342 | memset(mst->msg, 0, sizeof(struct i2c_msg) * (2 + num)); | ||
343 | |||
344 | /* open the gate */ | ||
345 | dibx000_i2c_gate_ctrl(mst, &mst->i2c_write_buffer[0], msg[0].addr, 1); | ||
346 | mst->msg[0].addr = mst->i2c_addr; | ||
347 | mst->msg[0].buf = &mst->i2c_write_buffer[0]; | ||
348 | mst->msg[0].len = 4; | ||
349 | |||
350 | memcpy(&mst->msg[1], msg, sizeof(struct i2c_msg) * num); | ||
351 | |||
352 | /* close the gate */ | ||
353 | dibx000_i2c_gate_ctrl(mst, &mst->i2c_write_buffer[4], 0, 0); | ||
354 | mst->msg[num + 1].addr = mst->i2c_addr; | ||
355 | mst->msg[num + 1].buf = &mst->i2c_write_buffer[4]; | ||
356 | mst->msg[num + 1].len = 4; | ||
357 | |||
358 | ret = (i2c_transfer(mst->i2c_adap, mst->msg, 2 + num) == 2 + num ? | ||
359 | num : -EIO); | ||
360 | mutex_unlock(&mst->i2c_buffer_lock); | ||
361 | return ret; | ||
362 | } | ||
363 | |||
364 | static struct i2c_algorithm dibx000_i2c_gated_tuner_algo = { | ||
365 | .master_xfer = dibx000_i2c_gated_tuner_xfer, | ||
366 | .functionality = dibx000_i2c_func, | ||
367 | }; | ||
368 | |||
369 | struct i2c_adapter *dibx000_get_i2c_adapter(struct dibx000_i2c_master *mst, | ||
370 | enum dibx000_i2c_interface intf, | ||
371 | int gating) | ||
372 | { | ||
373 | struct i2c_adapter *i2c = NULL; | ||
374 | |||
375 | switch (intf) { | ||
376 | case DIBX000_I2C_INTERFACE_TUNER: | ||
377 | if (gating) | ||
378 | i2c = &mst->gated_tuner_i2c_adap; | ||
379 | break; | ||
380 | case DIBX000_I2C_INTERFACE_GPIO_1_2: | ||
381 | if (!gating) | ||
382 | i2c = &mst->master_i2c_adap_gpio12; | ||
383 | break; | ||
384 | case DIBX000_I2C_INTERFACE_GPIO_3_4: | ||
385 | if (!gating) | ||
386 | i2c = &mst->master_i2c_adap_gpio34; | ||
387 | break; | ||
388 | case DIBX000_I2C_INTERFACE_GPIO_6_7: | ||
389 | if (gating) | ||
390 | i2c = &mst->master_i2c_adap_gpio67; | ||
391 | break; | ||
392 | default: | ||
393 | printk(KERN_ERR "DiBX000: incorrect I2C interface selected\n"); | ||
394 | break; | ||
395 | } | ||
396 | |||
397 | return i2c; | ||
398 | } | ||
399 | |||
400 | EXPORT_SYMBOL(dibx000_get_i2c_adapter); | ||
401 | |||
402 | void dibx000_reset_i2c_master(struct dibx000_i2c_master *mst) | ||
403 | { | ||
404 | /* initialize the i2c-master by closing the gate */ | ||
405 | u8 tx[4]; | ||
406 | struct i2c_msg m = {.addr = mst->i2c_addr,.buf = tx,.len = 4 }; | ||
407 | |||
408 | dibx000_i2c_gate_ctrl(mst, tx, 0, 0); | ||
409 | i2c_transfer(mst->i2c_adap, &m, 1); | ||
410 | mst->selected_interface = 0xff; // the first time force a select of the I2C | ||
411 | dibx000_i2c_select_interface(mst, DIBX000_I2C_INTERFACE_TUNER); | ||
412 | } | ||
413 | |||
414 | EXPORT_SYMBOL(dibx000_reset_i2c_master); | ||
415 | |||
416 | static int i2c_adapter_init(struct i2c_adapter *i2c_adap, | ||
417 | struct i2c_algorithm *algo, const char *name, | ||
418 | struct dibx000_i2c_master *mst) | ||
419 | { | ||
420 | strncpy(i2c_adap->name, name, sizeof(i2c_adap->name)); | ||
421 | i2c_adap->algo = algo; | ||
422 | i2c_adap->algo_data = NULL; | ||
423 | i2c_set_adapdata(i2c_adap, mst); | ||
424 | if (i2c_add_adapter(i2c_adap) < 0) | ||
425 | return -ENODEV; | ||
426 | return 0; | ||
427 | } | ||
428 | |||
429 | int dibx000_init_i2c_master(struct dibx000_i2c_master *mst, u16 device_rev, | ||
430 | struct i2c_adapter *i2c_adap, u8 i2c_addr) | ||
431 | { | ||
432 | int ret; | ||
433 | |||
434 | mutex_init(&mst->i2c_buffer_lock); | ||
435 | if (mutex_lock_interruptible(&mst->i2c_buffer_lock) < 0) { | ||
436 | dprintk("could not acquire lock"); | ||
437 | return -EINVAL; | ||
438 | } | ||
439 | memset(mst->msg, 0, sizeof(struct i2c_msg)); | ||
440 | mst->msg[0].addr = i2c_addr >> 1; | ||
441 | mst->msg[0].flags = 0; | ||
442 | mst->msg[0].buf = mst->i2c_write_buffer; | ||
443 | mst->msg[0].len = 4; | ||
444 | |||
445 | mst->device_rev = device_rev; | ||
446 | mst->i2c_adap = i2c_adap; | ||
447 | mst->i2c_addr = i2c_addr >> 1; | ||
448 | |||
449 | if (device_rev == DIB7000P || device_rev == DIB8000) | ||
450 | mst->base_reg = 1024; | ||
451 | else | ||
452 | mst->base_reg = 768; | ||
453 | |||
454 | mst->gated_tuner_i2c_adap.dev.parent = mst->i2c_adap->dev.parent; | ||
455 | if (i2c_adapter_init | ||
456 | (&mst->gated_tuner_i2c_adap, &dibx000_i2c_gated_tuner_algo, | ||
457 | "DiBX000 tuner I2C bus", mst) != 0) | ||
458 | printk(KERN_ERR | ||
459 | "DiBX000: could not initialize the tuner i2c_adapter\n"); | ||
460 | |||
461 | mst->master_i2c_adap_gpio12.dev.parent = mst->i2c_adap->dev.parent; | ||
462 | if (i2c_adapter_init | ||
463 | (&mst->master_i2c_adap_gpio12, &dibx000_i2c_master_gpio12_xfer_algo, | ||
464 | "DiBX000 master GPIO12 I2C bus", mst) != 0) | ||
465 | printk(KERN_ERR | ||
466 | "DiBX000: could not initialize the master i2c_adapter\n"); | ||
467 | |||
468 | mst->master_i2c_adap_gpio34.dev.parent = mst->i2c_adap->dev.parent; | ||
469 | if (i2c_adapter_init | ||
470 | (&mst->master_i2c_adap_gpio34, &dibx000_i2c_master_gpio34_xfer_algo, | ||
471 | "DiBX000 master GPIO34 I2C bus", mst) != 0) | ||
472 | printk(KERN_ERR | ||
473 | "DiBX000: could not initialize the master i2c_adapter\n"); | ||
474 | |||
475 | mst->master_i2c_adap_gpio67.dev.parent = mst->i2c_adap->dev.parent; | ||
476 | if (i2c_adapter_init | ||
477 | (&mst->master_i2c_adap_gpio67, &dibx000_i2c_gated_gpio67_algo, | ||
478 | "DiBX000 master GPIO67 I2C bus", mst) != 0) | ||
479 | printk(KERN_ERR | ||
480 | "DiBX000: could not initialize the master i2c_adapter\n"); | ||
481 | |||
482 | /* initialize the i2c-master by closing the gate */ | ||
483 | dibx000_i2c_gate_ctrl(mst, mst->i2c_write_buffer, 0, 0); | ||
484 | |||
485 | ret = (i2c_transfer(i2c_adap, mst->msg, 1) == 1); | ||
486 | mutex_unlock(&mst->i2c_buffer_lock); | ||
487 | |||
488 | return ret; | ||
489 | } | ||
490 | |||
491 | EXPORT_SYMBOL(dibx000_init_i2c_master); | ||
492 | |||
493 | void dibx000_exit_i2c_master(struct dibx000_i2c_master *mst) | ||
494 | { | ||
495 | i2c_del_adapter(&mst->gated_tuner_i2c_adap); | ||
496 | i2c_del_adapter(&mst->master_i2c_adap_gpio12); | ||
497 | i2c_del_adapter(&mst->master_i2c_adap_gpio34); | ||
498 | i2c_del_adapter(&mst->master_i2c_adap_gpio67); | ||
499 | } | ||
500 | EXPORT_SYMBOL(dibx000_exit_i2c_master); | ||
501 | |||
502 | |||
503 | u32 systime(void) | ||
504 | { | ||
505 | struct timespec t; | ||
506 | |||
507 | t = current_kernel_time(); | ||
508 | return (t.tv_sec * 10000) + (t.tv_nsec / 100000); | ||
509 | } | ||
510 | EXPORT_SYMBOL(systime); | ||
511 | |||
512 | MODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>"); | ||
513 | MODULE_DESCRIPTION("Common function the DiBcom demodulator family"); | ||
514 | MODULE_LICENSE("GPL"); | ||