1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * Driver for AzureWave 6007 DVB-C/T USB2.0 and clones
4 *
5 * Copyright (c) Henry Wang <Henry.wang@AzureWave.com>
6 *
7 * This driver was made publicly available by Terratec, at:
8 * http://linux.terratec.de/files/TERRATEC_H7/20110323_TERRATEC_H7_Linux.tar.gz
9 * The original driver's license is GPL, as declared with MODULE_LICENSE()
10 *
11 * Copyright (c) 2010-2012 Mauro Carvalho Chehab
12 * Driver modified by in order to work with upstream drxk driver, and
13 * tons of bugs got fixed, and converted to use dvb-usb-v2.
14 */
15
16#include "drxk.h"
17#include "mt2063.h"
18#include <media/dvb_ca_en50221.h>
19#include "dvb_usb.h"
20#include "cypress_firmware.h"
21
22#define AZ6007_FIRMWARE "dvb-usb-terratec-h7-az6007.fw"
23
24static int az6007_xfer_debug;
25module_param_named(xfer_debug, az6007_xfer_debug, int, 0644);
26MODULE_PARM_DESC(xfer_debug, "Enable xfer debug");
27
28DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
29
30/* Known requests (Cypress FX2 firmware + az6007 "private" ones*/
31
32#define FX2_OED 0xb5
33#define AZ6007_READ_DATA 0xb7
34#define AZ6007_I2C_RD 0xb9
35#define AZ6007_POWER 0xbc
36#define AZ6007_I2C_WR 0xbd
37#define FX2_SCON1 0xc0
38#define AZ6007_TS_THROUGH 0xc7
39#define AZ6007_READ_IR 0xb4
40
41struct az6007_device_state {
42 struct mutex mutex;
43 struct mutex ca_mutex;
44 struct dvb_ca_en50221 ca;
45 unsigned warm:1;
46 int (*gate_ctrl) (struct dvb_frontend *, int);
47 unsigned char data[4096];
48};
49
50static struct drxk_config terratec_h7_drxk = {
51 .adr = 0x29,
52 .parallel_ts = true,
53 .dynamic_clk = true,
54 .single_master = true,
55 .enable_merr_cfg = true,
56 .no_i2c_bridge = false,
57 .chunk_size = 64,
58 .mpeg_out_clk_strength = 0x02,
59 .qam_demod_parameter_count = 2,
60 .microcode_name = "dvb-usb-terratec-h7-drxk.fw",
61};
62
63static struct drxk_config cablestar_hdci_drxk = {
64 .adr = 0x29,
65 .parallel_ts = true,
66 .dynamic_clk = true,
67 .single_master = true,
68 .enable_merr_cfg = true,
69 .no_i2c_bridge = false,
70 .chunk_size = 64,
71 .mpeg_out_clk_strength = 0x02,
72 .qam_demod_parameter_count = 2,
73 .microcode_name = "dvb-usb-technisat-cablestar-hdci-drxk.fw",
74};
75
76static int drxk_gate_ctrl(struct dvb_frontend *fe, int enable)
77{
78 struct az6007_device_state *st = fe_to_priv(fe);
79 struct dvb_usb_adapter *adap = fe->sec_priv;
80 int status = 0;
81
82 pr_debug("%s: %s\n", __func__, enable ? "enable" : "disable");
83
84 if (!adap || !st)
85 return -EINVAL;
86
87 if (enable)
88 status = st->gate_ctrl(fe, 1);
89 else
90 status = st->gate_ctrl(fe, 0);
91
92 return status;
93}
94
95static struct mt2063_config az6007_mt2063_config = {
96 .tuner_address = 0x60,
97 .refclock = 36125000,
98};
99
100static int __az6007_read(struct usb_device *udev, u8 req, u16 value,
101 u16 index, u8 *b, int blen)
102{
103 int ret;
104
105 ret = usb_control_msg(dev: udev,
106 usb_rcvctrlpipe(udev, 0),
107 request: req,
108 USB_TYPE_VENDOR | USB_DIR_IN,
109 value, index, data: b, size: blen, timeout: 5000);
110 if (ret < 0) {
111 pr_warn("usb read operation failed. (%d)\n", ret);
112 return -EIO;
113 }
114
115 if (az6007_xfer_debug) {
116 printk(KERN_DEBUG "az6007: IN req: %02x, value: %04x, index: %04x\n",
117 req, value, index);
118 print_hex_dump_bytes("az6007: payload: ",
119 DUMP_PREFIX_NONE, b, blen);
120 }
121
122 return ret;
123}
124
125static int az6007_read(struct dvb_usb_device *d, u8 req, u16 value,
126 u16 index, u8 *b, int blen)
127{
128 struct az6007_device_state *st = d->priv;
129 int ret;
130
131 if (mutex_lock_interruptible(&st->mutex) < 0)
132 return -EAGAIN;
133
134 ret = __az6007_read(udev: d->udev, req, value, index, b, blen);
135
136 mutex_unlock(lock: &st->mutex);
137
138 return ret;
139}
140
141static int __az6007_write(struct usb_device *udev, u8 req, u16 value,
142 u16 index, u8 *b, int blen)
143{
144 int ret;
145
146 if (az6007_xfer_debug) {
147 printk(KERN_DEBUG "az6007: OUT req: %02x, value: %04x, index: %04x\n",
148 req, value, index);
149 print_hex_dump_bytes("az6007: payload: ",
150 DUMP_PREFIX_NONE, b, blen);
151 }
152
153 if (blen > 64) {
154 pr_err("az6007: tried to write %d bytes, but I2C max size is 64 bytes\n",
155 blen);
156 return -EOPNOTSUPP;
157 }
158
159 ret = usb_control_msg(dev: udev,
160 usb_sndctrlpipe(udev, 0),
161 request: req,
162 USB_TYPE_VENDOR | USB_DIR_OUT,
163 value, index, data: b, size: blen, timeout: 5000);
164 if (ret != blen) {
165 pr_err("usb write operation failed. (%d)\n", ret);
166 return -EIO;
167 }
168
169 return 0;
170}
171
172static int az6007_write(struct dvb_usb_device *d, u8 req, u16 value,
173 u16 index, u8 *b, int blen)
174{
175 struct az6007_device_state *st = d->priv;
176 int ret;
177
178 if (mutex_lock_interruptible(&st->mutex) < 0)
179 return -EAGAIN;
180
181 ret = __az6007_write(udev: d->udev, req, value, index, b, blen);
182
183 mutex_unlock(lock: &st->mutex);
184
185 return ret;
186}
187
188static int az6007_streaming_ctrl(struct dvb_frontend *fe, int onoff)
189{
190 struct dvb_usb_device *d = fe_to_d(fe);
191
192 pr_debug("%s: %s\n", __func__, onoff ? "enable" : "disable");
193
194 return az6007_write(d, req: 0xbc, value: onoff, index: 0, NULL, blen: 0);
195}
196
197#if IS_ENABLED(CONFIG_RC_CORE)
198/* remote control stuff (does not work with my box) */
199static int az6007_rc_query(struct dvb_usb_device *d)
200{
201 struct az6007_device_state *st = d_to_priv(d);
202 unsigned code;
203 enum rc_proto proto;
204
205 if (az6007_read(d, AZ6007_READ_IR, value: 0, index: 0, b: st->data, blen: 10) < 0)
206 return -EIO;
207
208 if (st->data[1] == 0x44)
209 return 0;
210
211 if ((st->data[3] ^ st->data[4]) == 0xff) {
212 if ((st->data[1] ^ st->data[2]) == 0xff) {
213 code = RC_SCANCODE_NEC(st->data[1], st->data[3]);
214 proto = RC_PROTO_NEC;
215 } else {
216 code = RC_SCANCODE_NECX(st->data[1] << 8 | st->data[2],
217 st->data[3]);
218 proto = RC_PROTO_NECX;
219 }
220 } else {
221 code = RC_SCANCODE_NEC32(st->data[1] << 24 |
222 st->data[2] << 16 |
223 st->data[3] << 8 |
224 st->data[4]);
225 proto = RC_PROTO_NEC32;
226 }
227
228 rc_keydown(dev: d->rc_dev, protocol: proto, scancode: code, toggle: st->data[5]);
229
230 return 0;
231}
232
233static int az6007_get_rc_config(struct dvb_usb_device *d, struct dvb_usb_rc *rc)
234{
235 pr_debug("Getting az6007 Remote Control properties\n");
236
237 rc->allowed_protos = RC_PROTO_BIT_NEC | RC_PROTO_BIT_NECX |
238 RC_PROTO_BIT_NEC32;
239 rc->query = az6007_rc_query;
240 rc->interval = 400;
241
242 return 0;
243}
244#else
245 #define az6007_get_rc_config NULL
246#endif
247
248static int az6007_ci_read_attribute_mem(struct dvb_ca_en50221 *ca,
249 int slot,
250 int address)
251{
252 struct dvb_usb_device *d = ca->data;
253 struct az6007_device_state *state = d_to_priv(d);
254
255 int ret;
256 u8 req;
257 u16 value;
258 u16 index;
259 int blen;
260 u8 *b;
261
262 if (slot != 0)
263 return -EINVAL;
264
265 b = kmalloc(size: 12, GFP_KERNEL);
266 if (!b)
267 return -ENOMEM;
268
269 mutex_lock(&state->ca_mutex);
270
271 req = 0xC1;
272 value = address;
273 index = 0;
274 blen = 1;
275
276 ret = az6007_read(d, req, value, index, b, blen);
277 if (ret < 0) {
278 pr_warn("usb in operation failed. (%d)\n", ret);
279 ret = -EINVAL;
280 } else {
281 ret = b[0];
282 }
283
284 mutex_unlock(lock: &state->ca_mutex);
285 kfree(objp: b);
286 return ret;
287}
288
289static int az6007_ci_write_attribute_mem(struct dvb_ca_en50221 *ca,
290 int slot,
291 int address,
292 u8 value)
293{
294 struct dvb_usb_device *d = ca->data;
295 struct az6007_device_state *state = d_to_priv(d);
296
297 int ret;
298 u8 req;
299 u16 value1;
300 u16 index;
301 int blen;
302
303 pr_debug("%s(), slot %d\n", __func__, slot);
304 if (slot != 0)
305 return -EINVAL;
306
307 mutex_lock(&state->ca_mutex);
308 req = 0xC2;
309 value1 = address;
310 index = value;
311 blen = 0;
312
313 ret = az6007_write(d, req, value: value1, index, NULL, blen);
314 if (ret != 0)
315 pr_warn("usb out operation failed. (%d)\n", ret);
316
317 mutex_unlock(lock: &state->ca_mutex);
318 return ret;
319}
320
321static int az6007_ci_read_cam_control(struct dvb_ca_en50221 *ca,
322 int slot,
323 u8 address)
324{
325 struct dvb_usb_device *d = ca->data;
326 struct az6007_device_state *state = d_to_priv(d);
327
328 int ret;
329 u8 req;
330 u16 value;
331 u16 index;
332 int blen;
333 u8 *b;
334
335 if (slot != 0)
336 return -EINVAL;
337
338 b = kmalloc(size: 12, GFP_KERNEL);
339 if (!b)
340 return -ENOMEM;
341
342 mutex_lock(&state->ca_mutex);
343
344 req = 0xC3;
345 value = address;
346 index = 0;
347 blen = 2;
348
349 ret = az6007_read(d, req, value, index, b, blen);
350 if (ret < 0) {
351 pr_warn("usb in operation failed. (%d)\n", ret);
352 ret = -EINVAL;
353 } else {
354 if (b[0] == 0)
355 pr_warn("Read CI IO error\n");
356
357 ret = b[1];
358 pr_debug("read cam data = %x from 0x%x\n", b[1], value);
359 }
360
361 mutex_unlock(lock: &state->ca_mutex);
362 kfree(objp: b);
363 return ret;
364}
365
366static int az6007_ci_write_cam_control(struct dvb_ca_en50221 *ca,
367 int slot,
368 u8 address,
369 u8 value)
370{
371 struct dvb_usb_device *d = ca->data;
372 struct az6007_device_state *state = d_to_priv(d);
373
374 int ret;
375 u8 req;
376 u16 value1;
377 u16 index;
378 int blen;
379
380 if (slot != 0)
381 return -EINVAL;
382
383 mutex_lock(&state->ca_mutex);
384 req = 0xC4;
385 value1 = address;
386 index = value;
387 blen = 0;
388
389 ret = az6007_write(d, req, value: value1, index, NULL, blen);
390 if (ret != 0) {
391 pr_warn("usb out operation failed. (%d)\n", ret);
392 goto failed;
393 }
394
395failed:
396 mutex_unlock(lock: &state->ca_mutex);
397 return ret;
398}
399
400static int CI_CamReady(struct dvb_ca_en50221 *ca, int slot)
401{
402 struct dvb_usb_device *d = ca->data;
403
404 int ret;
405 u8 req;
406 u16 value;
407 u16 index;
408 int blen;
409 u8 *b;
410
411 b = kmalloc(size: 12, GFP_KERNEL);
412 if (!b)
413 return -ENOMEM;
414
415 req = 0xC8;
416 value = 0;
417 index = 0;
418 blen = 1;
419
420 ret = az6007_read(d, req, value, index, b, blen);
421 if (ret < 0) {
422 pr_warn("usb in operation failed. (%d)\n", ret);
423 ret = -EIO;
424 } else{
425 ret = b[0];
426 }
427 kfree(objp: b);
428 return ret;
429}
430
431static int az6007_ci_slot_reset(struct dvb_ca_en50221 *ca, int slot)
432{
433 struct dvb_usb_device *d = ca->data;
434 struct az6007_device_state *state = d_to_priv(d);
435
436 int ret, i;
437 u8 req;
438 u16 value;
439 u16 index;
440 int blen;
441
442 mutex_lock(&state->ca_mutex);
443
444 req = 0xC6;
445 value = 1;
446 index = 0;
447 blen = 0;
448
449 ret = az6007_write(d, req, value, index, NULL, blen);
450 if (ret != 0) {
451 pr_warn("usb out operation failed. (%d)\n", ret);
452 goto failed;
453 }
454
455 msleep(msecs: 500);
456 req = 0xC6;
457 value = 0;
458 index = 0;
459 blen = 0;
460
461 ret = az6007_write(d, req, value, index, NULL, blen);
462 if (ret != 0) {
463 pr_warn("usb out operation failed. (%d)\n", ret);
464 goto failed;
465 }
466
467 for (i = 0; i < 15; i++) {
468 msleep(msecs: 100);
469
470 if (CI_CamReady(ca, slot)) {
471 pr_debug("CAM Ready\n");
472 break;
473 }
474 }
475 msleep(msecs: 5000);
476
477failed:
478 mutex_unlock(lock: &state->ca_mutex);
479 return ret;
480}
481
482static int az6007_ci_slot_shutdown(struct dvb_ca_en50221 *ca, int slot)
483{
484 return 0;
485}
486
487static int az6007_ci_slot_ts_enable(struct dvb_ca_en50221 *ca, int slot)
488{
489 struct dvb_usb_device *d = ca->data;
490 struct az6007_device_state *state = d_to_priv(d);
491
492 int ret;
493 u8 req;
494 u16 value;
495 u16 index;
496 int blen;
497
498 pr_debug("%s()\n", __func__);
499 mutex_lock(&state->ca_mutex);
500 req = 0xC7;
501 value = 1;
502 index = 0;
503 blen = 0;
504
505 ret = az6007_write(d, req, value, index, NULL, blen);
506 if (ret != 0) {
507 pr_warn("usb out operation failed. (%d)\n", ret);
508 goto failed;
509 }
510
511failed:
512 mutex_unlock(lock: &state->ca_mutex);
513 return ret;
514}
515
516static int az6007_ci_poll_slot_status(struct dvb_ca_en50221 *ca, int slot, int open)
517{
518 struct dvb_usb_device *d = ca->data;
519 struct az6007_device_state *state = d_to_priv(d);
520 int ret;
521 u8 req;
522 u16 value;
523 u16 index;
524 int blen;
525 u8 *b;
526
527 b = kmalloc(size: 12, GFP_KERNEL);
528 if (!b)
529 return -ENOMEM;
530 mutex_lock(&state->ca_mutex);
531
532 req = 0xC5;
533 value = 0;
534 index = 0;
535 blen = 1;
536
537 ret = az6007_read(d, req, value, index, b, blen);
538 if (ret < 0) {
539 pr_warn("usb in operation failed. (%d)\n", ret);
540 ret = -EIO;
541 } else
542 ret = 0;
543
544 if (!ret && b[0] == 1) {
545 ret = DVB_CA_EN50221_POLL_CAM_PRESENT |
546 DVB_CA_EN50221_POLL_CAM_READY;
547 }
548
549 mutex_unlock(lock: &state->ca_mutex);
550 kfree(objp: b);
551 return ret;
552}
553
554
555static void az6007_ci_uninit(struct dvb_usb_device *d)
556{
557 struct az6007_device_state *state;
558
559 pr_debug("%s()\n", __func__);
560
561 if (NULL == d)
562 return;
563
564 state = d_to_priv(d);
565 if (NULL == state)
566 return;
567
568 if (NULL == state->ca.data)
569 return;
570
571 dvb_ca_en50221_release(ca: &state->ca);
572
573 memset(&state->ca, 0, sizeof(state->ca));
574}
575
576
577static int az6007_ci_init(struct dvb_usb_adapter *adap)
578{
579 struct dvb_usb_device *d = adap_to_d(adap);
580 struct az6007_device_state *state = adap_to_priv(adap);
581 int ret;
582
583 pr_debug("%s()\n", __func__);
584
585 mutex_init(&state->ca_mutex);
586 state->ca.owner = THIS_MODULE;
587 state->ca.read_attribute_mem = az6007_ci_read_attribute_mem;
588 state->ca.write_attribute_mem = az6007_ci_write_attribute_mem;
589 state->ca.read_cam_control = az6007_ci_read_cam_control;
590 state->ca.write_cam_control = az6007_ci_write_cam_control;
591 state->ca.slot_reset = az6007_ci_slot_reset;
592 state->ca.slot_shutdown = az6007_ci_slot_shutdown;
593 state->ca.slot_ts_enable = az6007_ci_slot_ts_enable;
594 state->ca.poll_slot_status = az6007_ci_poll_slot_status;
595 state->ca.data = d;
596
597 ret = dvb_ca_en50221_init(dvb_adapter: &adap->dvb_adap,
598 ca: &state->ca,
599 flags: 0, /* flags */
600 slot_count: 1);/* n_slots */
601 if (ret != 0) {
602 pr_err("Cannot initialize CI: Error %d.\n", ret);
603 memset(&state->ca, 0, sizeof(state->ca));
604 return ret;
605 }
606
607 pr_debug("CI initialized.\n");
608
609 return 0;
610}
611
612static int az6007_read_mac_addr(struct dvb_usb_adapter *adap, u8 mac[6])
613{
614 struct dvb_usb_device *d = adap_to_d(adap);
615 struct az6007_device_state *st = adap_to_priv(adap);
616 int ret;
617
618 ret = az6007_read(d, AZ6007_READ_DATA, value: 6, index: 0, b: st->data, blen: 6);
619 memcpy(mac, st->data, 6);
620
621 if (ret > 0)
622 pr_debug("%s: mac is %pM\n", __func__, mac);
623
624 return ret;
625}
626
627static int az6007_frontend_attach(struct dvb_usb_adapter *adap)
628{
629 struct az6007_device_state *st = adap_to_priv(adap);
630 struct dvb_usb_device *d = adap_to_d(adap);
631
632 pr_debug("attaching demod drxk\n");
633
634 adap->fe[0] = dvb_attach(drxk_attach, &terratec_h7_drxk,
635 &d->i2c_adap);
636 if (!adap->fe[0])
637 return -EINVAL;
638
639 adap->fe[0]->sec_priv = adap;
640 st->gate_ctrl = adap->fe[0]->ops.i2c_gate_ctrl;
641 adap->fe[0]->ops.i2c_gate_ctrl = drxk_gate_ctrl;
642
643 az6007_ci_init(adap);
644
645 return 0;
646}
647
648static int az6007_cablestar_hdci_frontend_attach(struct dvb_usb_adapter *adap)
649{
650 struct az6007_device_state *st = adap_to_priv(adap);
651 struct dvb_usb_device *d = adap_to_d(adap);
652
653 pr_debug("attaching demod drxk\n");
654
655 adap->fe[0] = dvb_attach(drxk_attach, &cablestar_hdci_drxk,
656 &d->i2c_adap);
657 if (!adap->fe[0])
658 return -EINVAL;
659
660 adap->fe[0]->sec_priv = adap;
661 st->gate_ctrl = adap->fe[0]->ops.i2c_gate_ctrl;
662 adap->fe[0]->ops.i2c_gate_ctrl = drxk_gate_ctrl;
663
664 az6007_ci_init(adap);
665
666 return 0;
667}
668
669static int az6007_tuner_attach(struct dvb_usb_adapter *adap)
670{
671 struct dvb_usb_device *d = adap_to_d(adap);
672
673 pr_debug("attaching tuner mt2063\n");
674
675 /* Attach mt2063 to DVB-C frontend */
676 if (adap->fe[0]->ops.i2c_gate_ctrl)
677 adap->fe[0]->ops.i2c_gate_ctrl(adap->fe[0], 1);
678 if (!dvb_attach(mt2063_attach, adap->fe[0],
679 &az6007_mt2063_config,
680 &d->i2c_adap))
681 return -EINVAL;
682
683 if (adap->fe[0]->ops.i2c_gate_ctrl)
684 adap->fe[0]->ops.i2c_gate_ctrl(adap->fe[0], 0);
685
686 return 0;
687}
688
689static int az6007_power_ctrl(struct dvb_usb_device *d, int onoff)
690{
691 struct az6007_device_state *state = d_to_priv(d);
692 int ret;
693
694 pr_debug("%s()\n", __func__);
695
696 if (!state->warm) {
697 mutex_init(&state->mutex);
698
699 ret = az6007_write(d, AZ6007_POWER, value: 0, index: 2, NULL, blen: 0);
700 if (ret < 0)
701 return ret;
702 msleep(msecs: 60);
703 ret = az6007_write(d, AZ6007_POWER, value: 1, index: 4, NULL, blen: 0);
704 if (ret < 0)
705 return ret;
706 msleep(msecs: 100);
707 ret = az6007_write(d, AZ6007_POWER, value: 1, index: 3, NULL, blen: 0);
708 if (ret < 0)
709 return ret;
710 msleep(msecs: 20);
711 ret = az6007_write(d, AZ6007_POWER, value: 1, index: 4, NULL, blen: 0);
712 if (ret < 0)
713 return ret;
714
715 msleep(msecs: 400);
716 ret = az6007_write(d, FX2_SCON1, value: 0, index: 3, NULL, blen: 0);
717 if (ret < 0)
718 return ret;
719 msleep(msecs: 150);
720 ret = az6007_write(d, FX2_SCON1, value: 1, index: 3, NULL, blen: 0);
721 if (ret < 0)
722 return ret;
723 msleep(msecs: 430);
724 ret = az6007_write(d, AZ6007_POWER, value: 0, index: 0, NULL, blen: 0);
725 if (ret < 0)
726 return ret;
727
728 state->warm = true;
729
730 return 0;
731 }
732
733 if (!onoff)
734 return 0;
735
736 az6007_write(d, AZ6007_POWER, value: 0, index: 0, NULL, blen: 0);
737 az6007_write(d, AZ6007_TS_THROUGH, value: 0, index: 0, NULL, blen: 0);
738
739 return 0;
740}
741
742/* I2C */
743static int az6007_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[],
744 int num)
745{
746 struct dvb_usb_device *d = i2c_get_adapdata(adap);
747 struct az6007_device_state *st = d_to_priv(d);
748 int i, j, len;
749 int ret = 0;
750 u16 index;
751 u16 value;
752 int length;
753 u8 req, addr;
754
755 if (mutex_lock_interruptible(&st->mutex) < 0)
756 return -EAGAIN;
757
758 for (i = 0; i < num; i++) {
759 addr = msgs[i].addr << 1;
760 if (((i + 1) < num)
761 && (msgs[i].len == 1)
762 && ((msgs[i].flags & I2C_M_RD) != I2C_M_RD)
763 && (msgs[i + 1].flags & I2C_M_RD)
764 && (msgs[i].addr == msgs[i + 1].addr)) {
765 /*
766 * A write + read xfer for the same address, where
767 * the first xfer has just 1 byte length.
768 * Need to join both into one operation
769 */
770 if (az6007_xfer_debug)
771 printk(KERN_DEBUG "az6007: I2C W/R addr=0x%x len=%d/%d\n",
772 addr, msgs[i].len, msgs[i + 1].len);
773 req = AZ6007_I2C_RD;
774 index = msgs[i].buf[0];
775 value = addr | (1 << 8);
776 length = 6 + msgs[i + 1].len;
777 len = msgs[i + 1].len;
778 ret = __az6007_read(udev: d->udev, req, value, index,
779 b: st->data, blen: length);
780 if (ret >= len) {
781 for (j = 0; j < len; j++)
782 msgs[i + 1].buf[j] = st->data[j + 5];
783 } else
784 ret = -EIO;
785 i++;
786 } else if (!(msgs[i].flags & I2C_M_RD)) {
787 /* write bytes */
788 if (az6007_xfer_debug)
789 printk(KERN_DEBUG "az6007: I2C W addr=0x%x len=%d\n",
790 addr, msgs[i].len);
791 if (msgs[i].len < 1) {
792 ret = -EIO;
793 goto err;
794 }
795 req = AZ6007_I2C_WR;
796 index = msgs[i].buf[0];
797 value = addr | (1 << 8);
798 length = msgs[i].len - 1;
799 len = msgs[i].len - 1;
800 for (j = 0; j < len; j++)
801 st->data[j] = msgs[i].buf[j + 1];
802 ret = __az6007_write(udev: d->udev, req, value, index,
803 b: st->data, blen: length);
804 } else {
805 /* read bytes */
806 if (az6007_xfer_debug)
807 printk(KERN_DEBUG "az6007: I2C R addr=0x%x len=%d\n",
808 addr, msgs[i].len);
809 if (msgs[i].len < 1) {
810 ret = -EIO;
811 goto err;
812 }
813 req = AZ6007_I2C_RD;
814 index = msgs[i].buf[0];
815 value = addr;
816 length = msgs[i].len + 6;
817 len = msgs[i].len;
818 ret = __az6007_read(udev: d->udev, req, value, index,
819 b: st->data, blen: length);
820 for (j = 0; j < len; j++)
821 msgs[i].buf[j] = st->data[j + 5];
822 }
823 if (ret < 0)
824 goto err;
825 }
826err:
827 mutex_unlock(lock: &st->mutex);
828
829 if (ret < 0) {
830 pr_info("%s ERROR: %i\n", __func__, ret);
831 return ret;
832 }
833 return num;
834}
835
836static u32 az6007_i2c_func(struct i2c_adapter *adapter)
837{
838 return I2C_FUNC_I2C;
839}
840
841static struct i2c_algorithm az6007_i2c_algo = {
842 .master_xfer = az6007_i2c_xfer,
843 .functionality = az6007_i2c_func,
844};
845
846static int az6007_identify_state(struct dvb_usb_device *d, const char **name)
847{
848 int ret;
849 u8 *mac;
850
851 pr_debug("Identifying az6007 state\n");
852
853 mac = kmalloc(size: 6, GFP_ATOMIC);
854 if (!mac)
855 return -ENOMEM;
856
857 /* Try to read the mac address */
858 ret = __az6007_read(udev: d->udev, AZ6007_READ_DATA, value: 6, index: 0, b: mac, blen: 6);
859 if (ret == 6)
860 ret = WARM;
861 else
862 ret = COLD;
863
864 kfree(objp: mac);
865
866 if (ret == COLD) {
867 __az6007_write(udev: d->udev, req: 0x09, value: 1, index: 0, NULL, blen: 0);
868 __az6007_write(udev: d->udev, req: 0x00, value: 0, index: 0, NULL, blen: 0);
869 __az6007_write(udev: d->udev, req: 0x00, value: 0, index: 0, NULL, blen: 0);
870 }
871
872 pr_debug("Device is on %s state\n",
873 ret == WARM ? "warm" : "cold");
874 return ret;
875}
876
877static void az6007_usb_disconnect(struct usb_interface *intf)
878{
879 struct dvb_usb_device *d = usb_get_intfdata(intf);
880 az6007_ci_uninit(d);
881 dvb_usbv2_disconnect(intf);
882}
883
884static int az6007_download_firmware(struct dvb_usb_device *d,
885 const struct firmware *fw)
886{
887 pr_debug("Loading az6007 firmware\n");
888
889 return cypress_load_firmware(d->udev, fw, CYPRESS_FX2);
890}
891
892/* DVB USB Driver stuff */
893static struct dvb_usb_device_properties az6007_props = {
894 .driver_name = KBUILD_MODNAME,
895 .owner = THIS_MODULE,
896 .firmware = AZ6007_FIRMWARE,
897
898 .adapter_nr = adapter_nr,
899 .size_of_priv = sizeof(struct az6007_device_state),
900 .i2c_algo = &az6007_i2c_algo,
901 .tuner_attach = az6007_tuner_attach,
902 .frontend_attach = az6007_frontend_attach,
903 .streaming_ctrl = az6007_streaming_ctrl,
904 .get_rc_config = az6007_get_rc_config,
905 .read_mac_address = az6007_read_mac_addr,
906 .download_firmware = az6007_download_firmware,
907 .identify_state = az6007_identify_state,
908 .power_ctrl = az6007_power_ctrl,
909 .num_adapters = 1,
910 .adapter = {
911 { .stream = DVB_USB_STREAM_BULK(0x02, 10, 4096), }
912 }
913};
914
915static struct dvb_usb_device_properties az6007_cablestar_hdci_props = {
916 .driver_name = KBUILD_MODNAME,
917 .owner = THIS_MODULE,
918 .firmware = AZ6007_FIRMWARE,
919
920 .adapter_nr = adapter_nr,
921 .size_of_priv = sizeof(struct az6007_device_state),
922 .i2c_algo = &az6007_i2c_algo,
923 .tuner_attach = az6007_tuner_attach,
924 .frontend_attach = az6007_cablestar_hdci_frontend_attach,
925 .streaming_ctrl = az6007_streaming_ctrl,
926/* ditch get_rc_config as it can't work (TS35 remote, I believe it's rc5) */
927 .get_rc_config = NULL,
928 .read_mac_address = az6007_read_mac_addr,
929 .download_firmware = az6007_download_firmware,
930 .identify_state = az6007_identify_state,
931 .power_ctrl = az6007_power_ctrl,
932 .num_adapters = 1,
933 .adapter = {
934 { .stream = DVB_USB_STREAM_BULK(0x02, 10, 4096), }
935 }
936};
937
938static const struct usb_device_id az6007_usb_table[] = {
939 {DVB_USB_DEVICE(USB_VID_AZUREWAVE, USB_PID_AZUREWAVE_6007,
940 &az6007_props, "Azurewave 6007", RC_MAP_EMPTY)},
941 {DVB_USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_H7,
942 &az6007_props, "Terratec H7", RC_MAP_NEC_TERRATEC_CINERGY_XS)},
943 {DVB_USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_H7_2,
944 &az6007_props, "Terratec H7", RC_MAP_NEC_TERRATEC_CINERGY_XS)},
945 {DVB_USB_DEVICE(USB_VID_TECHNISAT, USB_PID_TECHNISAT_USB2_CABLESTAR_HDCI,
946 &az6007_cablestar_hdci_props, "Technisat CableStar Combo HD CI", RC_MAP_EMPTY)},
947 {0},
948};
949
950MODULE_DEVICE_TABLE(usb, az6007_usb_table);
951
952static int az6007_suspend(struct usb_interface *intf, pm_message_t msg)
953{
954 struct dvb_usb_device *d = usb_get_intfdata(intf);
955
956 az6007_ci_uninit(d);
957 return dvb_usbv2_suspend(intf, msg);
958}
959
960static int az6007_resume(struct usb_interface *intf)
961{
962 struct dvb_usb_device *d = usb_get_intfdata(intf);
963 struct dvb_usb_adapter *adap = &d->adapter[0];
964
965 az6007_ci_init(adap);
966 return dvb_usbv2_resume(intf);
967}
968
969/* usb specific object needed to register this driver with the usb subsystem */
970static struct usb_driver az6007_usb_driver = {
971 .name = KBUILD_MODNAME,
972 .id_table = az6007_usb_table,
973 .probe = dvb_usbv2_probe,
974 .disconnect = az6007_usb_disconnect,
975 .no_dynamic_id = 1,
976 .soft_unbind = 1,
977 /*
978 * FIXME: need to implement reset_resume, likely with
979 * dvb-usb-v2 core support
980 */
981 .suspend = az6007_suspend,
982 .resume = az6007_resume,
983};
984
985module_usb_driver(az6007_usb_driver);
986
987MODULE_AUTHOR("Henry Wang <Henry.wang@AzureWave.com>");
988MODULE_AUTHOR("Mauro Carvalho Chehab");
989MODULE_DESCRIPTION("Driver for AzureWave 6007 DVB-C/T USB2.0 and clones");
990MODULE_VERSION("2.0");
991MODULE_LICENSE("GPL");
992MODULE_FIRMWARE(AZ6007_FIRMWARE);
993

source code of linux/drivers/media/usb/dvb-usb-v2/az6007.c