cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

az6007.c (22631B)


      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(udev,
    106			      usb_rcvctrlpipe(udev, 0),
    107			      req,
    108			      USB_TYPE_VENDOR | USB_DIR_IN,
    109			      value, index, b, blen, 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(d->udev, req, value, index, b, blen);
    135
    136	mutex_unlock(&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(udev,
    160			      usb_sndctrlpipe(udev, 0),
    161			      req,
    162			      USB_TYPE_VENDOR | USB_DIR_OUT,
    163			      value, index, b, blen, 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(d->udev, req, value, index, b, blen);
    182
    183	mutex_unlock(&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, 0xbc, onoff, 0, NULL, 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	az6007_read(d, AZ6007_READ_IR, 0, 0, st->data, 10);
    206
    207	if (st->data[1] == 0x44)
    208		return 0;
    209
    210	if ((st->data[3] ^ st->data[4]) == 0xff) {
    211		if ((st->data[1] ^ st->data[2]) == 0xff) {
    212			code = RC_SCANCODE_NEC(st->data[1], st->data[3]);
    213			proto = RC_PROTO_NEC;
    214		} else {
    215			code = RC_SCANCODE_NECX(st->data[1] << 8 | st->data[2],
    216						st->data[3]);
    217			proto = RC_PROTO_NECX;
    218		}
    219	} else {
    220		code = RC_SCANCODE_NEC32(st->data[1] << 24 |
    221					 st->data[2] << 16 |
    222					 st->data[3] << 8  |
    223					 st->data[4]);
    224		proto = RC_PROTO_NEC32;
    225	}
    226
    227	rc_keydown(d->rc_dev, proto, code, st->data[5]);
    228
    229	return 0;
    230}
    231
    232static int az6007_get_rc_config(struct dvb_usb_device *d, struct dvb_usb_rc *rc)
    233{
    234	pr_debug("Getting az6007 Remote Control properties\n");
    235
    236	rc->allowed_protos = RC_PROTO_BIT_NEC | RC_PROTO_BIT_NECX |
    237						RC_PROTO_BIT_NEC32;
    238	rc->query          = az6007_rc_query;
    239	rc->interval       = 400;
    240
    241	return 0;
    242}
    243#else
    244	#define az6007_get_rc_config NULL
    245#endif
    246
    247static int az6007_ci_read_attribute_mem(struct dvb_ca_en50221 *ca,
    248					int slot,
    249					int address)
    250{
    251	struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data;
    252	struct az6007_device_state *state = d_to_priv(d);
    253
    254	int ret;
    255	u8 req;
    256	u16 value;
    257	u16 index;
    258	int blen;
    259	u8 *b;
    260
    261	if (slot != 0)
    262		return -EINVAL;
    263
    264	b = kmalloc(12, GFP_KERNEL);
    265	if (!b)
    266		return -ENOMEM;
    267
    268	mutex_lock(&state->ca_mutex);
    269
    270	req = 0xC1;
    271	value = address;
    272	index = 0;
    273	blen = 1;
    274
    275	ret = az6007_read(d, req, value, index, b, blen);
    276	if (ret < 0) {
    277		pr_warn("usb in operation failed. (%d)\n", ret);
    278		ret = -EINVAL;
    279	} else {
    280		ret = b[0];
    281	}
    282
    283	mutex_unlock(&state->ca_mutex);
    284	kfree(b);
    285	return ret;
    286}
    287
    288static int az6007_ci_write_attribute_mem(struct dvb_ca_en50221 *ca,
    289					 int slot,
    290					 int address,
    291					 u8 value)
    292{
    293	struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data;
    294	struct az6007_device_state *state = d_to_priv(d);
    295
    296	int ret;
    297	u8 req;
    298	u16 value1;
    299	u16 index;
    300	int blen;
    301
    302	pr_debug("%s(), slot %d\n", __func__, slot);
    303	if (slot != 0)
    304		return -EINVAL;
    305
    306	mutex_lock(&state->ca_mutex);
    307	req = 0xC2;
    308	value1 = address;
    309	index = value;
    310	blen = 0;
    311
    312	ret = az6007_write(d, req, value1, index, NULL, blen);
    313	if (ret != 0)
    314		pr_warn("usb out operation failed. (%d)\n", ret);
    315
    316	mutex_unlock(&state->ca_mutex);
    317	return ret;
    318}
    319
    320static int az6007_ci_read_cam_control(struct dvb_ca_en50221 *ca,
    321				      int slot,
    322				      u8 address)
    323{
    324	struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data;
    325	struct az6007_device_state *state = d_to_priv(d);
    326
    327	int ret;
    328	u8 req;
    329	u16 value;
    330	u16 index;
    331	int blen;
    332	u8 *b;
    333
    334	if (slot != 0)
    335		return -EINVAL;
    336
    337	b = kmalloc(12, GFP_KERNEL);
    338	if (!b)
    339		return -ENOMEM;
    340
    341	mutex_lock(&state->ca_mutex);
    342
    343	req = 0xC3;
    344	value = address;
    345	index = 0;
    346	blen = 2;
    347
    348	ret = az6007_read(d, req, value, index, b, blen);
    349	if (ret < 0) {
    350		pr_warn("usb in operation failed. (%d)\n", ret);
    351		ret = -EINVAL;
    352	} else {
    353		if (b[0] == 0)
    354			pr_warn("Read CI IO error\n");
    355
    356		ret = b[1];
    357		pr_debug("read cam data = %x from 0x%x\n", b[1], value);
    358	}
    359
    360	mutex_unlock(&state->ca_mutex);
    361	kfree(b);
    362	return ret;
    363}
    364
    365static int az6007_ci_write_cam_control(struct dvb_ca_en50221 *ca,
    366				       int slot,
    367				       u8 address,
    368				       u8 value)
    369{
    370	struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data;
    371	struct az6007_device_state *state = d_to_priv(d);
    372
    373	int ret;
    374	u8 req;
    375	u16 value1;
    376	u16 index;
    377	int blen;
    378
    379	if (slot != 0)
    380		return -EINVAL;
    381
    382	mutex_lock(&state->ca_mutex);
    383	req = 0xC4;
    384	value1 = address;
    385	index = value;
    386	blen = 0;
    387
    388	ret = az6007_write(d, req, value1, index, NULL, blen);
    389	if (ret != 0) {
    390		pr_warn("usb out operation failed. (%d)\n", ret);
    391		goto failed;
    392	}
    393
    394failed:
    395	mutex_unlock(&state->ca_mutex);
    396	return ret;
    397}
    398
    399static int CI_CamReady(struct dvb_ca_en50221 *ca, int slot)
    400{
    401	struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data;
    402
    403	int ret;
    404	u8 req;
    405	u16 value;
    406	u16 index;
    407	int blen;
    408	u8 *b;
    409
    410	b = kmalloc(12, GFP_KERNEL);
    411	if (!b)
    412		return -ENOMEM;
    413
    414	req = 0xC8;
    415	value = 0;
    416	index = 0;
    417	blen = 1;
    418
    419	ret = az6007_read(d, req, value, index, b, blen);
    420	if (ret < 0) {
    421		pr_warn("usb in operation failed. (%d)\n", ret);
    422		ret = -EIO;
    423	} else{
    424		ret = b[0];
    425	}
    426	kfree(b);
    427	return ret;
    428}
    429
    430static int az6007_ci_slot_reset(struct dvb_ca_en50221 *ca, int slot)
    431{
    432	struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data;
    433	struct az6007_device_state *state = d_to_priv(d);
    434
    435	int ret, i;
    436	u8 req;
    437	u16 value;
    438	u16 index;
    439	int blen;
    440
    441	mutex_lock(&state->ca_mutex);
    442
    443	req = 0xC6;
    444	value = 1;
    445	index = 0;
    446	blen = 0;
    447
    448	ret = az6007_write(d, req, value, index, NULL, blen);
    449	if (ret != 0) {
    450		pr_warn("usb out operation failed. (%d)\n", ret);
    451		goto failed;
    452	}
    453
    454	msleep(500);
    455	req = 0xC6;
    456	value = 0;
    457	index = 0;
    458	blen = 0;
    459
    460	ret = az6007_write(d, req, value, index, NULL, blen);
    461	if (ret != 0) {
    462		pr_warn("usb out operation failed. (%d)\n", ret);
    463		goto failed;
    464	}
    465
    466	for (i = 0; i < 15; i++) {
    467		msleep(100);
    468
    469		if (CI_CamReady(ca, slot)) {
    470			pr_debug("CAM Ready\n");
    471			break;
    472		}
    473	}
    474	msleep(5000);
    475
    476failed:
    477	mutex_unlock(&state->ca_mutex);
    478	return ret;
    479}
    480
    481static int az6007_ci_slot_shutdown(struct dvb_ca_en50221 *ca, int slot)
    482{
    483	return 0;
    484}
    485
    486static int az6007_ci_slot_ts_enable(struct dvb_ca_en50221 *ca, int slot)
    487{
    488	struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data;
    489	struct az6007_device_state *state = d_to_priv(d);
    490
    491	int ret;
    492	u8 req;
    493	u16 value;
    494	u16 index;
    495	int blen;
    496
    497	pr_debug("%s()\n", __func__);
    498	mutex_lock(&state->ca_mutex);
    499	req = 0xC7;
    500	value = 1;
    501	index = 0;
    502	blen = 0;
    503
    504	ret = az6007_write(d, req, value, index, NULL, blen);
    505	if (ret != 0) {
    506		pr_warn("usb out operation failed. (%d)\n", ret);
    507		goto failed;
    508	}
    509
    510failed:
    511	mutex_unlock(&state->ca_mutex);
    512	return ret;
    513}
    514
    515static int az6007_ci_poll_slot_status(struct dvb_ca_en50221 *ca, int slot, int open)
    516{
    517	struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data;
    518	struct az6007_device_state *state = d_to_priv(d);
    519	int ret;
    520	u8 req;
    521	u16 value;
    522	u16 index;
    523	int blen;
    524	u8 *b;
    525
    526	b = kmalloc(12, GFP_KERNEL);
    527	if (!b)
    528		return -ENOMEM;
    529	mutex_lock(&state->ca_mutex);
    530
    531	req = 0xC5;
    532	value = 0;
    533	index = 0;
    534	blen = 1;
    535
    536	ret = az6007_read(d, req, value, index, b, blen);
    537	if (ret < 0) {
    538		pr_warn("usb in operation failed. (%d)\n", ret);
    539		ret = -EIO;
    540	} else
    541		ret = 0;
    542
    543	if (!ret && b[0] == 1) {
    544		ret = DVB_CA_EN50221_POLL_CAM_PRESENT |
    545		      DVB_CA_EN50221_POLL_CAM_READY;
    546	}
    547
    548	mutex_unlock(&state->ca_mutex);
    549	kfree(b);
    550	return ret;
    551}
    552
    553
    554static void az6007_ci_uninit(struct dvb_usb_device *d)
    555{
    556	struct az6007_device_state *state;
    557
    558	pr_debug("%s()\n", __func__);
    559
    560	if (NULL == d)
    561		return;
    562
    563	state = d_to_priv(d);
    564	if (NULL == state)
    565		return;
    566
    567	if (NULL == state->ca.data)
    568		return;
    569
    570	dvb_ca_en50221_release(&state->ca);
    571
    572	memset(&state->ca, 0, sizeof(state->ca));
    573}
    574
    575
    576static int az6007_ci_init(struct dvb_usb_adapter *adap)
    577{
    578	struct dvb_usb_device *d = adap_to_d(adap);
    579	struct az6007_device_state *state = adap_to_priv(adap);
    580	int ret;
    581
    582	pr_debug("%s()\n", __func__);
    583
    584	mutex_init(&state->ca_mutex);
    585	state->ca.owner			= THIS_MODULE;
    586	state->ca.read_attribute_mem	= az6007_ci_read_attribute_mem;
    587	state->ca.write_attribute_mem	= az6007_ci_write_attribute_mem;
    588	state->ca.read_cam_control	= az6007_ci_read_cam_control;
    589	state->ca.write_cam_control	= az6007_ci_write_cam_control;
    590	state->ca.slot_reset		= az6007_ci_slot_reset;
    591	state->ca.slot_shutdown		= az6007_ci_slot_shutdown;
    592	state->ca.slot_ts_enable	= az6007_ci_slot_ts_enable;
    593	state->ca.poll_slot_status	= az6007_ci_poll_slot_status;
    594	state->ca.data			= d;
    595
    596	ret = dvb_ca_en50221_init(&adap->dvb_adap,
    597				  &state->ca,
    598				  0, /* flags */
    599				  1);/* n_slots */
    600	if (ret != 0) {
    601		pr_err("Cannot initialize CI: Error %d.\n", ret);
    602		memset(&state->ca, 0, sizeof(state->ca));
    603		return ret;
    604	}
    605
    606	pr_debug("CI initialized.\n");
    607
    608	return 0;
    609}
    610
    611static int az6007_read_mac_addr(struct dvb_usb_adapter *adap, u8 mac[6])
    612{
    613	struct dvb_usb_device *d = adap_to_d(adap);
    614	struct az6007_device_state *st = adap_to_priv(adap);
    615	int ret;
    616
    617	ret = az6007_read(d, AZ6007_READ_DATA, 6, 0, st->data, 6);
    618	memcpy(mac, st->data, 6);
    619
    620	if (ret > 0)
    621		pr_debug("%s: mac is %pM\n", __func__, mac);
    622
    623	return ret;
    624}
    625
    626static int az6007_frontend_attach(struct dvb_usb_adapter *adap)
    627{
    628	struct az6007_device_state *st = adap_to_priv(adap);
    629	struct dvb_usb_device *d = adap_to_d(adap);
    630
    631	pr_debug("attaching demod drxk\n");
    632
    633	adap->fe[0] = dvb_attach(drxk_attach, &terratec_h7_drxk,
    634				 &d->i2c_adap);
    635	if (!adap->fe[0])
    636		return -EINVAL;
    637
    638	adap->fe[0]->sec_priv = adap;
    639	st->gate_ctrl = adap->fe[0]->ops.i2c_gate_ctrl;
    640	adap->fe[0]->ops.i2c_gate_ctrl = drxk_gate_ctrl;
    641
    642	az6007_ci_init(adap);
    643
    644	return 0;
    645}
    646
    647static int az6007_cablestar_hdci_frontend_attach(struct dvb_usb_adapter *adap)
    648{
    649	struct az6007_device_state *st = adap_to_priv(adap);
    650	struct dvb_usb_device *d = adap_to_d(adap);
    651
    652	pr_debug("attaching demod drxk\n");
    653
    654	adap->fe[0] = dvb_attach(drxk_attach, &cablestar_hdci_drxk,
    655				 &d->i2c_adap);
    656	if (!adap->fe[0])
    657		return -EINVAL;
    658
    659	adap->fe[0]->sec_priv = adap;
    660	st->gate_ctrl = adap->fe[0]->ops.i2c_gate_ctrl;
    661	adap->fe[0]->ops.i2c_gate_ctrl = drxk_gate_ctrl;
    662
    663	az6007_ci_init(adap);
    664
    665	return 0;
    666}
    667
    668static int az6007_tuner_attach(struct dvb_usb_adapter *adap)
    669{
    670	struct dvb_usb_device *d = adap_to_d(adap);
    671
    672	pr_debug("attaching tuner mt2063\n");
    673
    674	/* Attach mt2063 to DVB-C frontend */
    675	if (adap->fe[0]->ops.i2c_gate_ctrl)
    676		adap->fe[0]->ops.i2c_gate_ctrl(adap->fe[0], 1);
    677	if (!dvb_attach(mt2063_attach, adap->fe[0],
    678			&az6007_mt2063_config,
    679			&d->i2c_adap))
    680		return -EINVAL;
    681
    682	if (adap->fe[0]->ops.i2c_gate_ctrl)
    683		adap->fe[0]->ops.i2c_gate_ctrl(adap->fe[0], 0);
    684
    685	return 0;
    686}
    687
    688static int az6007_power_ctrl(struct dvb_usb_device *d, int onoff)
    689{
    690	struct az6007_device_state *state = d_to_priv(d);
    691	int ret;
    692
    693	pr_debug("%s()\n", __func__);
    694
    695	if (!state->warm) {
    696		mutex_init(&state->mutex);
    697
    698		ret = az6007_write(d, AZ6007_POWER, 0, 2, NULL, 0);
    699		if (ret < 0)
    700			return ret;
    701		msleep(60);
    702		ret = az6007_write(d, AZ6007_POWER, 1, 4, NULL, 0);
    703		if (ret < 0)
    704			return ret;
    705		msleep(100);
    706		ret = az6007_write(d, AZ6007_POWER, 1, 3, NULL, 0);
    707		if (ret < 0)
    708			return ret;
    709		msleep(20);
    710		ret = az6007_write(d, AZ6007_POWER, 1, 4, NULL, 0);
    711		if (ret < 0)
    712			return ret;
    713
    714		msleep(400);
    715		ret = az6007_write(d, FX2_SCON1, 0, 3, NULL, 0);
    716		if (ret < 0)
    717			return ret;
    718		msleep(150);
    719		ret = az6007_write(d, FX2_SCON1, 1, 3, NULL, 0);
    720		if (ret < 0)
    721			return ret;
    722		msleep(430);
    723		ret = az6007_write(d, AZ6007_POWER, 0, 0, NULL, 0);
    724		if (ret < 0)
    725			return ret;
    726
    727		state->warm = true;
    728
    729		return 0;
    730	}
    731
    732	if (!onoff)
    733		return 0;
    734
    735	az6007_write(d, AZ6007_POWER, 0, 0, NULL, 0);
    736	az6007_write(d, AZ6007_TS_THROUGH, 0, 0, NULL, 0);
    737
    738	return 0;
    739}
    740
    741/* I2C */
    742static int az6007_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[],
    743			   int num)
    744{
    745	struct dvb_usb_device *d = i2c_get_adapdata(adap);
    746	struct az6007_device_state *st = d_to_priv(d);
    747	int i, j, len;
    748	int ret = 0;
    749	u16 index;
    750	u16 value;
    751	int length;
    752	u8 req, addr;
    753
    754	if (mutex_lock_interruptible(&st->mutex) < 0)
    755		return -EAGAIN;
    756
    757	for (i = 0; i < num; i++) {
    758		addr = msgs[i].addr << 1;
    759		if (((i + 1) < num)
    760		    && (msgs[i].len == 1)
    761		    && ((msgs[i].flags & I2C_M_RD) != I2C_M_RD)
    762		    && (msgs[i + 1].flags & I2C_M_RD)
    763		    && (msgs[i].addr == msgs[i + 1].addr)) {
    764			/*
    765			 * A write + read xfer for the same address, where
    766			 * the first xfer has just 1 byte length.
    767			 * Need to join both into one operation
    768			 */
    769			if (az6007_xfer_debug)
    770				printk(KERN_DEBUG "az6007: I2C W/R addr=0x%x len=%d/%d\n",
    771				       addr, msgs[i].len, msgs[i + 1].len);
    772			req = AZ6007_I2C_RD;
    773			index = msgs[i].buf[0];
    774			value = addr | (1 << 8);
    775			length = 6 + msgs[i + 1].len;
    776			len = msgs[i + 1].len;
    777			ret = __az6007_read(d->udev, req, value, index,
    778					    st->data, length);
    779			if (ret >= len) {
    780				for (j = 0; j < len; j++)
    781					msgs[i + 1].buf[j] = st->data[j + 5];
    782			} else
    783				ret = -EIO;
    784			i++;
    785		} else if (!(msgs[i].flags & I2C_M_RD)) {
    786			/* write bytes */
    787			if (az6007_xfer_debug)
    788				printk(KERN_DEBUG "az6007: I2C W addr=0x%x len=%d\n",
    789				       addr, msgs[i].len);
    790			req = AZ6007_I2C_WR;
    791			index = msgs[i].buf[0];
    792			value = addr | (1 << 8);
    793			length = msgs[i].len - 1;
    794			len = msgs[i].len - 1;
    795			for (j = 0; j < len; j++)
    796				st->data[j] = msgs[i].buf[j + 1];
    797			ret =  __az6007_write(d->udev, req, value, index,
    798					      st->data, length);
    799		} else {
    800			/* read bytes */
    801			if (az6007_xfer_debug)
    802				printk(KERN_DEBUG "az6007: I2C R addr=0x%x len=%d\n",
    803				       addr, msgs[i].len);
    804			req = AZ6007_I2C_RD;
    805			index = msgs[i].buf[0];
    806			value = addr;
    807			length = msgs[i].len + 6;
    808			len = msgs[i].len;
    809			ret = __az6007_read(d->udev, req, value, index,
    810					    st->data, length);
    811			for (j = 0; j < len; j++)
    812				msgs[i].buf[j] = st->data[j + 5];
    813		}
    814		if (ret < 0)
    815			goto err;
    816	}
    817err:
    818	mutex_unlock(&st->mutex);
    819
    820	if (ret < 0) {
    821		pr_info("%s ERROR: %i\n", __func__, ret);
    822		return ret;
    823	}
    824	return num;
    825}
    826
    827static u32 az6007_i2c_func(struct i2c_adapter *adapter)
    828{
    829	return I2C_FUNC_I2C;
    830}
    831
    832static struct i2c_algorithm az6007_i2c_algo = {
    833	.master_xfer = az6007_i2c_xfer,
    834	.functionality = az6007_i2c_func,
    835};
    836
    837static int az6007_identify_state(struct dvb_usb_device *d, const char **name)
    838{
    839	int ret;
    840	u8 *mac;
    841
    842	pr_debug("Identifying az6007 state\n");
    843
    844	mac = kmalloc(6, GFP_ATOMIC);
    845	if (!mac)
    846		return -ENOMEM;
    847
    848	/* Try to read the mac address */
    849	ret = __az6007_read(d->udev, AZ6007_READ_DATA, 6, 0, mac, 6);
    850	if (ret == 6)
    851		ret = WARM;
    852	else
    853		ret = COLD;
    854
    855	kfree(mac);
    856
    857	if (ret == COLD) {
    858		__az6007_write(d->udev, 0x09, 1, 0, NULL, 0);
    859		__az6007_write(d->udev, 0x00, 0, 0, NULL, 0);
    860		__az6007_write(d->udev, 0x00, 0, 0, NULL, 0);
    861	}
    862
    863	pr_debug("Device is on %s state\n",
    864		 ret == WARM ? "warm" : "cold");
    865	return ret;
    866}
    867
    868static void az6007_usb_disconnect(struct usb_interface *intf)
    869{
    870	struct dvb_usb_device *d = usb_get_intfdata(intf);
    871	az6007_ci_uninit(d);
    872	dvb_usbv2_disconnect(intf);
    873}
    874
    875static int az6007_download_firmware(struct dvb_usb_device *d,
    876	const struct firmware *fw)
    877{
    878	pr_debug("Loading az6007 firmware\n");
    879
    880	return cypress_load_firmware(d->udev, fw, CYPRESS_FX2);
    881}
    882
    883/* DVB USB Driver stuff */
    884static struct dvb_usb_device_properties az6007_props = {
    885	.driver_name         = KBUILD_MODNAME,
    886	.owner               = THIS_MODULE,
    887	.firmware            = AZ6007_FIRMWARE,
    888
    889	.adapter_nr          = adapter_nr,
    890	.size_of_priv        = sizeof(struct az6007_device_state),
    891	.i2c_algo            = &az6007_i2c_algo,
    892	.tuner_attach        = az6007_tuner_attach,
    893	.frontend_attach     = az6007_frontend_attach,
    894	.streaming_ctrl      = az6007_streaming_ctrl,
    895	.get_rc_config       = az6007_get_rc_config,
    896	.read_mac_address    = az6007_read_mac_addr,
    897	.download_firmware   = az6007_download_firmware,
    898	.identify_state	     = az6007_identify_state,
    899	.power_ctrl          = az6007_power_ctrl,
    900	.num_adapters        = 1,
    901	.adapter             = {
    902		{ .stream = DVB_USB_STREAM_BULK(0x02, 10, 4096), }
    903	}
    904};
    905
    906static struct dvb_usb_device_properties az6007_cablestar_hdci_props = {
    907	.driver_name         = KBUILD_MODNAME,
    908	.owner               = THIS_MODULE,
    909	.firmware            = AZ6007_FIRMWARE,
    910
    911	.adapter_nr          = adapter_nr,
    912	.size_of_priv        = sizeof(struct az6007_device_state),
    913	.i2c_algo            = &az6007_i2c_algo,
    914	.tuner_attach        = az6007_tuner_attach,
    915	.frontend_attach     = az6007_cablestar_hdci_frontend_attach,
    916	.streaming_ctrl      = az6007_streaming_ctrl,
    917/* ditch get_rc_config as it can't work (TS35 remote, I believe it's rc5) */
    918	.get_rc_config       = NULL,
    919	.read_mac_address    = az6007_read_mac_addr,
    920	.download_firmware   = az6007_download_firmware,
    921	.identify_state	     = az6007_identify_state,
    922	.power_ctrl          = az6007_power_ctrl,
    923	.num_adapters        = 1,
    924	.adapter             = {
    925		{ .stream = DVB_USB_STREAM_BULK(0x02, 10, 4096), }
    926	}
    927};
    928
    929static const struct usb_device_id az6007_usb_table[] = {
    930	{DVB_USB_DEVICE(USB_VID_AZUREWAVE, USB_PID_AZUREWAVE_6007,
    931		&az6007_props, "Azurewave 6007", RC_MAP_EMPTY)},
    932	{DVB_USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_H7,
    933		&az6007_props, "Terratec H7", RC_MAP_NEC_TERRATEC_CINERGY_XS)},
    934	{DVB_USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_H7_2,
    935		&az6007_props, "Terratec H7", RC_MAP_NEC_TERRATEC_CINERGY_XS)},
    936	{DVB_USB_DEVICE(USB_VID_TECHNISAT, USB_PID_TECHNISAT_USB2_CABLESTAR_HDCI,
    937		&az6007_cablestar_hdci_props, "Technisat CableStar Combo HD CI", RC_MAP_EMPTY)},
    938	{0},
    939};
    940
    941MODULE_DEVICE_TABLE(usb, az6007_usb_table);
    942
    943static int az6007_suspend(struct usb_interface *intf, pm_message_t msg)
    944{
    945	struct dvb_usb_device *d = usb_get_intfdata(intf);
    946
    947	az6007_ci_uninit(d);
    948	return dvb_usbv2_suspend(intf, msg);
    949}
    950
    951static int az6007_resume(struct usb_interface *intf)
    952{
    953	struct dvb_usb_device *d = usb_get_intfdata(intf);
    954	struct dvb_usb_adapter *adap = &d->adapter[0];
    955
    956	az6007_ci_init(adap);
    957	return dvb_usbv2_resume(intf);
    958}
    959
    960/* usb specific object needed to register this driver with the usb subsystem */
    961static struct usb_driver az6007_usb_driver = {
    962	.name		= KBUILD_MODNAME,
    963	.id_table	= az6007_usb_table,
    964	.probe		= dvb_usbv2_probe,
    965	.disconnect	= az6007_usb_disconnect,
    966	.no_dynamic_id	= 1,
    967	.soft_unbind	= 1,
    968	/*
    969	 * FIXME: need to implement reset_resume, likely with
    970	 * dvb-usb-v2 core support
    971	 */
    972	.suspend	= az6007_suspend,
    973	.resume		= az6007_resume,
    974};
    975
    976module_usb_driver(az6007_usb_driver);
    977
    978MODULE_AUTHOR("Henry Wang <Henry.wang@AzureWave.com>");
    979MODULE_AUTHOR("Mauro Carvalho Chehab");
    980MODULE_DESCRIPTION("Driver for AzureWave 6007 DVB-C/T USB2.0 and clones");
    981MODULE_VERSION("2.0");
    982MODULE_LICENSE("GPL");
    983MODULE_FIRMWARE(AZ6007_FIRMWARE);