brintos

brintos / linux-shallow public Read only

0
0
Text · 22.0 KiB · 2410054 Raw
993 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Driver for AzureWave 6007 DVB-C/T USB2.0 and clones4 *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.gz9 * The original driver's license is GPL, as declared with MODULE_LICENSE()10 *11 * Copyright (c) 2010-2012 Mauro Carvalho Chehab12 *	Driver modified by in order to work with upstream drxk driver, and13 *	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			0xb533#define AZ6007_READ_DATA	0xb734#define AZ6007_I2C_RD		0xb935#define AZ6007_POWER		0xbc36#define AZ6007_I2C_WR		0xbd37#define FX2_SCON1		0xc038#define AZ6007_TS_THROUGH	0xc739#define AZ6007_READ_IR		0xb440 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	else90		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	if (az6007_read(d, AZ6007_READ_IR, 0, 0, st->data, 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(d->rc_dev, proto, code, 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#else245	#define az6007_get_rc_config NULL246#endif247 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(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(&state->ca_mutex);285	kfree(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, value1, index, NULL, blen);314	if (ret != 0)315		pr_warn("usb out operation failed. (%d)\n", ret);316 317	mutex_unlock(&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(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(&state->ca_mutex);362	kfree(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, 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(&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(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(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(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(100);469 470		if (CI_CamReady(ca, slot)) {471			pr_debug("CAM Ready\n");472			break;473		}474	}475	msleep(5000);476 477failed:478	mutex_unlock(&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(&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(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	} else542		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(&state->ca_mutex);550	kfree(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(&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(&adap->dvb_adap,598				  &state->ca,599				  0, /* flags */600				  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, 6, 0, st->data, 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, 0, 2, NULL, 0);700		if (ret < 0)701			return ret;702		msleep(60);703		ret = az6007_write(d, AZ6007_POWER, 1, 4, NULL, 0);704		if (ret < 0)705			return ret;706		msleep(100);707		ret = az6007_write(d, AZ6007_POWER, 1, 3, NULL, 0);708		if (ret < 0)709			return ret;710		msleep(20);711		ret = az6007_write(d, AZ6007_POWER, 1, 4, NULL, 0);712		if (ret < 0)713			return ret;714 715		msleep(400);716		ret = az6007_write(d, FX2_SCON1, 0, 3, NULL, 0);717		if (ret < 0)718			return ret;719		msleep(150);720		ret = az6007_write(d, FX2_SCON1, 1, 3, NULL, 0);721		if (ret < 0)722			return ret;723		msleep(430);724		ret = az6007_write(d, AZ6007_POWER, 0, 0, NULL, 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, 0, 0, NULL, 0);737	az6007_write(d, AZ6007_TS_THROUGH, 0, 0, NULL, 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, where767			 * the first xfer has just 1 byte length.768			 * Need to join both into one operation769			 */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(d->udev, req, value, index,779					    st->data, length);780			if (ret >= len) {781				for (j = 0; j < len; j++)782					msgs[i + 1].buf[j] = st->data[j + 5];783			} else784				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(d->udev, req, value, index,803					      st->data, 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(d->udev, req, value, index,819					    st->data, 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(&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(6, GFP_ATOMIC);854	if (!mac)855		return -ENOMEM;856 857	/* Try to read the mac address */858	ret = __az6007_read(d->udev, AZ6007_READ_DATA, 6, 0, mac, 6);859	if (ret == 6)860		ret = WARM;861	else862		ret = COLD;863 864	kfree(mac);865 866	if (ret == COLD) {867		__az6007_write(d->udev, 0x09, 1, 0, NULL, 0);868		__az6007_write(d->udev, 0x00, 0, 0, NULL, 0);869		__az6007_write(d->udev, 0x00, 0, 0, NULL, 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 with979	 * dvb-usb-v2 core support980	 */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