1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17#include <linux/i2c.h>
18#include <linux/module.h>
19#include <media/i2c/ir-kbd-i2c.h>
20#include "pvrusb2-i2c-core.h"
21#include "pvrusb2-hdw-internal.h"
22#include "pvrusb2-debug.h"
23#include "pvrusb2-fx2-cmd.h"
24#include "pvrusb2.h"
25
26#define trace_i2c(...) pvr2_trace(PVR2_TRACE_I2C,__VA_ARGS__)
27
28
29
30
31
32
33
34
35static unsigned int i2c_scan;
36module_param(i2c_scan, int, S_IRUGO|S_IWUSR);
37MODULE_PARM_DESC(i2c_scan,"scan i2c bus at insmod time");
38
39static int ir_mode[PVR_NUM] = { [0 ... PVR_NUM-1] = 1 };
40module_param_array(ir_mode, int, NULL, 0444);
41MODULE_PARM_DESC(ir_mode,"specify: 0=disable IR reception, 1=normal IR");
42
43static int pvr2_disable_ir_video;
44module_param_named(disable_autoload_ir_video, pvr2_disable_ir_video,
45 int, S_IRUGO|S_IWUSR);
46MODULE_PARM_DESC(disable_autoload_ir_video,
47 "1=do not try to autoload ir_video IR receiver");
48
49static int pvr2_i2c_write(struct pvr2_hdw *hdw,
50 u8 i2c_addr,
51 u8 *data,
52 u16 length)
53{
54
55 int ret;
56
57
58 if (!data) length = 0;
59 if (length > (sizeof(hdw->cmd_buffer) - 3)) {
60 pvr2_trace(PVR2_TRACE_ERROR_LEGS,
61 "Killing an I2C write to %u that is too large (desired=%u limit=%u)",
62 i2c_addr,
63 length,(unsigned int)(sizeof(hdw->cmd_buffer) - 3));
64 return -ENOTSUPP;
65 }
66
67 LOCK_TAKE(hdw->ctl_lock);
68
69
70 memset(hdw->cmd_buffer, 0, sizeof(hdw->cmd_buffer));
71
72
73 hdw->cmd_buffer[0] = FX2CMD_I2C_WRITE;
74 hdw->cmd_buffer[1] = i2c_addr;
75 hdw->cmd_buffer[2] = length;
76 if (length) memcpy(hdw->cmd_buffer + 3, data, length);
77
78
79 ret = pvr2_send_request(hdw,
80 hdw->cmd_buffer,
81 length + 3,
82 hdw->cmd_buffer,
83 1);
84 if (!ret) {
85 if (hdw->cmd_buffer[0] != 8) {
86 ret = -EIO;
87 if (hdw->cmd_buffer[0] != 7) {
88 trace_i2c("unexpected status from i2_write[%d]: %d",
89 i2c_addr,hdw->cmd_buffer[0]);
90 }
91 }
92 }
93
94 LOCK_GIVE(hdw->ctl_lock);
95
96 return ret;
97}
98
99static int pvr2_i2c_read(struct pvr2_hdw *hdw,
100 u8 i2c_addr,
101 u8 *data,
102 u16 dlen,
103 u8 *res,
104 u16 rlen)
105{
106
107 int ret;
108
109
110 if (!data) dlen = 0;
111 if (dlen > (sizeof(hdw->cmd_buffer) - 4)) {
112 pvr2_trace(PVR2_TRACE_ERROR_LEGS,
113 "Killing an I2C read to %u that has wlen too large (desired=%u limit=%u)",
114 i2c_addr,
115 dlen,(unsigned int)(sizeof(hdw->cmd_buffer) - 4));
116 return -ENOTSUPP;
117 }
118 if (res && (rlen > (sizeof(hdw->cmd_buffer) - 1))) {
119 pvr2_trace(PVR2_TRACE_ERROR_LEGS,
120 "Killing an I2C read to %u that has rlen too large (desired=%u limit=%u)",
121 i2c_addr,
122 rlen,(unsigned int)(sizeof(hdw->cmd_buffer) - 1));
123 return -ENOTSUPP;
124 }
125
126 LOCK_TAKE(hdw->ctl_lock);
127
128
129 memset(hdw->cmd_buffer, 0, sizeof(hdw->cmd_buffer));
130
131
132 hdw->cmd_buffer[0] = FX2CMD_I2C_READ;
133 hdw->cmd_buffer[1] = dlen;
134 hdw->cmd_buffer[2] = rlen;
135
136 hdw->cmd_buffer[3] = i2c_addr;
137 if (dlen) memcpy(hdw->cmd_buffer + 4, data, dlen);
138
139
140 ret = pvr2_send_request(hdw,
141 hdw->cmd_buffer,
142 4 + dlen,
143 hdw->cmd_buffer,
144 rlen + 1);
145 if (!ret) {
146 if (hdw->cmd_buffer[0] != 8) {
147 ret = -EIO;
148 if (hdw->cmd_buffer[0] != 7) {
149 trace_i2c("unexpected status from i2_read[%d]: %d",
150 i2c_addr,hdw->cmd_buffer[0]);
151 }
152 }
153 }
154
155
156 if (res && rlen) {
157 if (ret) {
158
159 memset(res, 0, rlen);
160 } else {
161 memcpy(res, hdw->cmd_buffer + 1, rlen);
162 }
163 }
164
165 LOCK_GIVE(hdw->ctl_lock);
166
167 return ret;
168}
169
170
171
172static int pvr2_i2c_basic_op(struct pvr2_hdw *hdw,
173 u8 i2c_addr,
174 u8 *wdata,
175 u16 wlen,
176 u8 *rdata,
177 u16 rlen)
178{
179 if (!rdata) rlen = 0;
180 if (!wdata) wlen = 0;
181 if (rlen || !wlen) {
182 return pvr2_i2c_read(hdw,i2c_addr,wdata,wlen,rdata,rlen);
183 } else {
184 return pvr2_i2c_write(hdw,i2c_addr,wdata,wlen);
185 }
186}
187
188
189
190
191
192
193
194
195static int i2c_24xxx_ir(struct pvr2_hdw *hdw,
196 u8 i2c_addr,u8 *wdata,u16 wlen,u8 *rdata,u16 rlen)
197{
198 u8 dat[4];
199 unsigned int stat;
200
201 if (!(rlen || wlen)) {
202
203 return 0;
204 }
205
206
207 if ((wlen != 0) || (rlen == 0)) return -EIO;
208
209 if (rlen < 3) {
210
211
212
213
214
215
216
217 if (rlen > 0) rdata[0] = 0;
218 if (rlen > 1) rdata[1] = 0;
219 return 0;
220 }
221
222
223 LOCK_TAKE(hdw->ctl_lock); do {
224 hdw->cmd_buffer[0] = FX2CMD_GET_IR_CODE;
225 stat = pvr2_send_request(hdw,
226 hdw->cmd_buffer,1,
227 hdw->cmd_buffer,4);
228 dat[0] = hdw->cmd_buffer[0];
229 dat[1] = hdw->cmd_buffer[1];
230 dat[2] = hdw->cmd_buffer[2];
231 dat[3] = hdw->cmd_buffer[3];
232 } while (0); LOCK_GIVE(hdw->ctl_lock);
233
234
235 if (stat != 0) return stat;
236
237
238
239 rdata[2] = 0xc1;
240 if (dat[0] != 1) {
241
242 rdata[0] = 0;
243 rdata[1] = 0;
244 } else {
245 u16 val;
246
247
248 val = dat[1];
249 val <<= 8;
250 val |= dat[2];
251 val >>= 1;
252 val &= ~0x0003;
253 val |= 0x8000;
254 rdata[0] = (val >> 8) & 0xffu;
255 rdata[1] = val & 0xffu;
256 }
257
258 return 0;
259}
260
261
262
263
264
265static int i2c_hack_wm8775(struct pvr2_hdw *hdw,
266 u8 i2c_addr,u8 *wdata,u16 wlen,u8 *rdata,u16 rlen)
267{
268 if (!(rlen || wlen)) {
269
270 return 0;
271 }
272 return pvr2_i2c_basic_op(hdw,i2c_addr,wdata,wlen,rdata,rlen);
273}
274
275
276
277
278static int i2c_black_hole(struct pvr2_hdw *hdw,
279 u8 i2c_addr,u8 *wdata,u16 wlen,u8 *rdata,u16 rlen)
280{
281 return -EIO;
282}
283
284
285
286
287
288
289
290
291static int i2c_hack_cx25840(struct pvr2_hdw *hdw,
292 u8 i2c_addr,u8 *wdata,u16 wlen,u8 *rdata,u16 rlen)
293{
294 int ret;
295 unsigned int subaddr;
296 u8 wbuf[2];
297 int state = hdw->i2c_cx25840_hack_state;
298
299 if (!(rlen || wlen)) {
300
301
302
303 return 0;
304 }
305
306 if (state == 3) {
307 return pvr2_i2c_basic_op(hdw,i2c_addr,wdata,wlen,rdata,rlen);
308 }
309
310
311
312
313
314
315
316
317
318 if (wlen == 0) {
319 switch (state) {
320 case 1: subaddr = 0x0100; break;
321 case 2: subaddr = 0x0101; break;
322 default: goto fail;
323 }
324 } else if (wlen == 2) {
325 subaddr = (wdata[0] << 8) | wdata[1];
326 switch (subaddr) {
327 case 0x0100: state = 1; break;
328 case 0x0101: state = 2; break;
329 default: goto fail;
330 }
331 } else {
332 goto fail;
333 }
334 if (!rlen) goto success;
335 state = 0;
336 if (rlen != 1) goto fail;
337
338
339
340 wbuf[0] = subaddr >> 8;
341 wbuf[1] = subaddr;
342 ret = pvr2_i2c_basic_op(hdw,i2c_addr,wbuf,2,rdata,rlen);
343
344 if ((ret != 0) || (*rdata == 0x04) || (*rdata == 0x0a)) {
345 pvr2_trace(PVR2_TRACE_ERROR_LEGS,
346 "WARNING: Detected a wedged cx25840 chip; the device will not work.");
347 pvr2_trace(PVR2_TRACE_ERROR_LEGS,
348 "WARNING: Try power cycling the pvrusb2 device.");
349 pvr2_trace(PVR2_TRACE_ERROR_LEGS,
350 "WARNING: Disabling further access to the device to prevent other foul-ups.");
351
352 hdw->i2c_func[0x44] = NULL;
353 pvr2_hdw_render_useless(hdw);
354 goto fail;
355 }
356
357
358 pvr2_trace(PVR2_TRACE_CHIPS,"cx25840 appears to be OK.");
359 state = 3;
360
361 success:
362 hdw->i2c_cx25840_hack_state = state;
363 return 0;
364
365 fail:
366 hdw->i2c_cx25840_hack_state = state;
367 return -EIO;
368}
369
370
371
372static int pvr2_i2c_xfer(struct i2c_adapter *i2c_adap,
373 struct i2c_msg msgs[],
374 int num)
375{
376 int ret = -ENOTSUPP;
377 pvr2_i2c_func funcp = NULL;
378 struct pvr2_hdw *hdw = (struct pvr2_hdw *)(i2c_adap->algo_data);
379
380 if (!num) {
381 ret = -EINVAL;
382 goto done;
383 }
384 if (msgs[0].addr < PVR2_I2C_FUNC_CNT) {
385 funcp = hdw->i2c_func[msgs[0].addr];
386 }
387 if (!funcp) {
388 ret = -EIO;
389 goto done;
390 }
391
392 if (num == 1) {
393 if (msgs[0].flags & I2C_M_RD) {
394
395 u16 tcnt,bcnt,offs;
396 if (!msgs[0].len) {
397
398 if (funcp(hdw,msgs[0].addr,NULL,0,NULL,0)) {
399 ret = -EIO;
400 goto done;
401 }
402 ret = 1;
403 goto done;
404 }
405
406
407
408 tcnt = msgs[0].len;
409 offs = 0;
410 while (tcnt) {
411 bcnt = tcnt;
412 if (bcnt > sizeof(hdw->cmd_buffer)-1) {
413 bcnt = sizeof(hdw->cmd_buffer)-1;
414 }
415 if (funcp(hdw,msgs[0].addr,NULL,0,
416 msgs[0].buf+offs,bcnt)) {
417 ret = -EIO;
418 goto done;
419 }
420 offs += bcnt;
421 tcnt -= bcnt;
422 }
423 ret = 1;
424 goto done;
425 } else {
426
427 ret = 1;
428 if (funcp(hdw,msgs[0].addr,
429 msgs[0].buf,msgs[0].len,NULL,0)) {
430 ret = -EIO;
431 }
432 goto done;
433 }
434 } else if (num == 2) {
435 if (msgs[0].addr != msgs[1].addr) {
436 trace_i2c("i2c refusing 2 phase transfer with conflicting target addresses");
437 ret = -ENOTSUPP;
438 goto done;
439 }
440 if ((!((msgs[0].flags & I2C_M_RD))) &&
441 (msgs[1].flags & I2C_M_RD)) {
442 u16 tcnt,bcnt,wcnt,offs;
443
444
445
446
447 tcnt = msgs[1].len;
448 wcnt = msgs[0].len;
449 offs = 0;
450 while (tcnt || wcnt) {
451 bcnt = tcnt;
452 if (bcnt > sizeof(hdw->cmd_buffer)-1) {
453 bcnt = sizeof(hdw->cmd_buffer)-1;
454 }
455 if (funcp(hdw,msgs[0].addr,
456 msgs[0].buf,wcnt,
457 msgs[1].buf+offs,bcnt)) {
458 ret = -EIO;
459 goto done;
460 }
461 offs += bcnt;
462 tcnt -= bcnt;
463 wcnt = 0;
464 }
465 ret = 2;
466 goto done;
467 } else {
468 trace_i2c("i2c refusing complex transfer read0=%d read1=%d",
469 (msgs[0].flags & I2C_M_RD),
470 (msgs[1].flags & I2C_M_RD));
471 }
472 } else {
473 trace_i2c("i2c refusing %d phase transfer",num);
474 }
475
476 done:
477 if (pvrusb2_debug & PVR2_TRACE_I2C_TRAF) {
478 unsigned int idx,offs,cnt;
479 for (idx = 0; idx < num; idx++) {
480 cnt = msgs[idx].len;
481 printk(KERN_INFO
482 "pvrusb2 i2c xfer %u/%u: addr=0x%x len=%d %s",
483 idx+1,num,
484 msgs[idx].addr,
485 cnt,
486 (msgs[idx].flags & I2C_M_RD ?
487 "read" : "write"));
488 if ((ret > 0) || !(msgs[idx].flags & I2C_M_RD)) {
489 if (cnt > 8) cnt = 8;
490 printk(KERN_CONT " [");
491 for (offs = 0; offs < cnt; offs++) {
492 if (offs) printk(KERN_CONT " ");
493 printk(KERN_CONT "%02x",msgs[idx].buf[offs]);
494 }
495 if (offs < cnt) printk(KERN_CONT " ...");
496 printk(KERN_CONT "]");
497 }
498 if (idx+1 == num) {
499 printk(KERN_CONT " result=%d",ret);
500 }
501 printk(KERN_CONT "\n");
502 }
503 if (!num) {
504 printk(KERN_INFO
505 "pvrusb2 i2c xfer null transfer result=%d\n",
506 ret);
507 }
508 }
509 return ret;
510}
511
512static u32 pvr2_i2c_functionality(struct i2c_adapter *adap)
513{
514 return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_I2C;
515}
516
517static const struct i2c_algorithm pvr2_i2c_algo_template = {
518 .master_xfer = pvr2_i2c_xfer,
519 .functionality = pvr2_i2c_functionality,
520};
521
522static const struct i2c_adapter pvr2_i2c_adap_template = {
523 .owner = THIS_MODULE,
524 .class = 0,
525};
526
527
528
529static int do_i2c_probe(struct pvr2_hdw *hdw, int addr)
530{
531 struct i2c_msg msg[1];
532 int rc;
533 msg[0].addr = 0;
534 msg[0].flags = I2C_M_RD;
535 msg[0].len = 0;
536 msg[0].buf = NULL;
537 msg[0].addr = addr;
538 rc = i2c_transfer(&hdw->i2c_adap, msg, ARRAY_SIZE(msg));
539 return rc == 1;
540}
541
542static void do_i2c_scan(struct pvr2_hdw *hdw)
543{
544 int i;
545 printk(KERN_INFO "%s: i2c scan beginning\n", hdw->name);
546 for (i = 0; i < 128; i++) {
547 if (do_i2c_probe(hdw, i)) {
548 printk(KERN_INFO "%s: i2c scan: found device @ 0x%x\n",
549 hdw->name, i);
550 }
551 }
552 printk(KERN_INFO "%s: i2c scan done.\n", hdw->name);
553}
554
555static void pvr2_i2c_register_ir(struct pvr2_hdw *hdw)
556{
557 struct i2c_board_info info;
558 struct IR_i2c_init_data *init_data = &hdw->ir_init_data;
559 if (pvr2_disable_ir_video) {
560 pvr2_trace(PVR2_TRACE_INFO,
561 "Automatic binding of ir_video has been disabled.");
562 return;
563 }
564 memset(&info, 0, sizeof(struct i2c_board_info));
565 switch (hdw->ir_scheme_active) {
566 case PVR2_IR_SCHEME_24XXX:
567 case PVR2_IR_SCHEME_29XXX:
568 init_data->ir_codes = RC_MAP_HAUPPAUGE;
569 init_data->internal_get_key_func = IR_KBD_GET_KEY_HAUP;
570 init_data->type = RC_PROTO_BIT_RC5;
571 init_data->name = hdw->hdw_desc->description;
572 init_data->polling_interval = 100;
573
574 info.addr = 0x18;
575 info.platform_data = init_data;
576 strlcpy(info.type, "ir_video", I2C_NAME_SIZE);
577 pvr2_trace(PVR2_TRACE_INFO, "Binding %s to i2c address 0x%02x.",
578 info.type, info.addr);
579 i2c_new_device(&hdw->i2c_adap, &info);
580 break;
581 case PVR2_IR_SCHEME_ZILOG:
582 case PVR2_IR_SCHEME_24XXX_MCE:
583 init_data->ir_codes = RC_MAP_HAUPPAUGE;
584 init_data->internal_get_key_func = IR_KBD_GET_KEY_HAUP_XVR;
585 init_data->type = RC_PROTO_BIT_RC5 | RC_PROTO_BIT_RC6_MCE |
586 RC_PROTO_BIT_RC6_6A_32;
587 init_data->name = hdw->hdw_desc->description;
588
589 info.addr = 0x71;
590 info.platform_data = init_data;
591 strlcpy(info.type, "ir_z8f0811_haup", I2C_NAME_SIZE);
592 pvr2_trace(PVR2_TRACE_INFO, "Binding %s to i2c address 0x%02x.",
593 info.type, info.addr);
594 i2c_new_device(&hdw->i2c_adap, &info);
595 break;
596 default:
597
598
599 break;
600 }
601}
602
603void pvr2_i2c_core_init(struct pvr2_hdw *hdw)
604{
605 unsigned int idx;
606
607
608
609 for (idx = 0; idx < PVR2_I2C_FUNC_CNT; idx++) {
610 hdw->i2c_func[idx] = pvr2_i2c_basic_op;
611 }
612
613
614 if (ir_mode[hdw->unit_number] == 0) {
615 printk(KERN_INFO "%s: IR disabled\n",hdw->name);
616 hdw->i2c_func[0x18] = i2c_black_hole;
617 } else if (ir_mode[hdw->unit_number] == 1) {
618 if (hdw->ir_scheme_active == PVR2_IR_SCHEME_24XXX) {
619
620
621 hdw->i2c_func[0x18] = i2c_24xxx_ir;
622 }
623 }
624 if (hdw->hdw_desc->flag_has_cx25840) {
625 hdw->i2c_func[0x44] = i2c_hack_cx25840;
626 }
627 if (hdw->hdw_desc->flag_has_wm8775) {
628 hdw->i2c_func[0x1b] = i2c_hack_wm8775;
629 }
630
631
632 hdw->i2c_adap = pvr2_i2c_adap_template;
633 hdw->i2c_algo = pvr2_i2c_algo_template;
634 strlcpy(hdw->i2c_adap.name,hdw->name,sizeof(hdw->i2c_adap.name));
635 hdw->i2c_adap.dev.parent = &hdw->usb_dev->dev;
636 hdw->i2c_adap.algo = &hdw->i2c_algo;
637 hdw->i2c_adap.algo_data = hdw;
638 hdw->i2c_linked = !0;
639 i2c_set_adapdata(&hdw->i2c_adap, &hdw->v4l2_dev);
640 i2c_add_adapter(&hdw->i2c_adap);
641 if (hdw->i2c_func[0x18] == i2c_24xxx_ir) {
642
643
644
645
646
647
648 if (do_i2c_probe(hdw, 0x71)) {
649 pvr2_trace(PVR2_TRACE_INFO,
650 "Device has newer IR hardware; disabling unneeded virtual IR device");
651 hdw->i2c_func[0x18] = NULL;
652
653 hdw->ir_scheme_active = PVR2_IR_SCHEME_24XXX_MCE;
654 }
655 }
656 if (i2c_scan) do_i2c_scan(hdw);
657
658 pvr2_i2c_register_ir(hdw);
659}
660
661void pvr2_i2c_core_done(struct pvr2_hdw *hdw)
662{
663 if (hdw->i2c_linked) {
664 i2c_del_adapter(&hdw->i2c_adap);
665 hdw->i2c_linked = 0;
666 }
667}
668