cregit-Linux how code gets into the kernel

Release 4.11 drivers/media/usb/dvb-usb-v2/az6007.c

/*
 * Driver for AzureWave 6007 DVB-C/T USB2.0 and clones
 *
 * Copyright (c) Henry Wang <Henry.wang@AzureWave.com>
 *
 * This driver was made publicly available by Terratec, at:
 *      http://linux.terratec.de/files/TERRATEC_H7/20110323_TERRATEC_H7_Linux.tar.gz
 * The original driver's license is GPL, as declared with MODULE_LICENSE()
 *
 * Copyright (c) 2010-2012 Mauro Carvalho Chehab
 *      Driver modified by in order to work with upstream drxk driver, and
 *      tons of bugs got fixed, and converted to use dvb-usb-v2.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation under version 2 of the License.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 */

#include "drxk.h"
#include "mt2063.h"
#include "dvb_ca_en50221.h"
#include "dvb_usb.h"
#include "cypress_firmware.h"


#define AZ6007_FIRMWARE "dvb-usb-terratec-h7-az6007.fw"


static int az6007_xfer_debug;
module_param_named(xfer_debug, az6007_xfer_debug, int, 0644);
MODULE_PARM_DESC(xfer_debug, "Enable xfer debug");


DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);

/* Known requests (Cypress FX2 firmware + az6007 "private" ones*/


#define FX2_OED			0xb5

#define AZ6007_READ_DATA	0xb7

#define AZ6007_I2C_RD		0xb9

#define AZ6007_POWER		0xbc

#define AZ6007_I2C_WR		0xbd

#define FX2_SCON1		0xc0

#define AZ6007_TS_THROUGH	0xc7

#define AZ6007_READ_IR		0xb4


struct az6007_device_state {
	
struct mutex		mutex;
	
struct mutex		ca_mutex;
	
struct dvb_ca_en50221	ca;
	
unsigned		warm:1;
	
int			(*gate_ctrl) (struct dvb_frontend *, int);
	
unsigned char		data[4096];
};


static struct drxk_config terratec_h7_drxk = {
	.adr = 0x29,
	.parallel_ts = true,
	.dynamic_clk = true,
	.single_master = true,
	.enable_merr_cfg = true,
	.no_i2c_bridge = false,
	.chunk_size = 64,
	.mpeg_out_clk_strength = 0x02,
	.qam_demod_parameter_count = 2,
	.microcode_name = "dvb-usb-terratec-h7-drxk.fw",
};


static struct drxk_config cablestar_hdci_drxk = {
	.adr = 0x29,
	.parallel_ts = true,
	.dynamic_clk = true,
	.single_master = true,
	.enable_merr_cfg = true,
	.no_i2c_bridge = false,
	.chunk_size = 64,
	.mpeg_out_clk_strength = 0x02,
	.qam_demod_parameter_count = 2,
	.microcode_name = "dvb-usb-technisat-cablestar-hdci-drxk.fw",
};


static int drxk_gate_ctrl(struct dvb_frontend *fe, int enable) { struct az6007_device_state *st = fe_to_priv(fe); struct dvb_usb_adapter *adap = fe->sec_priv; int status = 0; pr_debug("%s: %s\n", __func__, enable ? "enable" : "disable"); if (!adap || !st) return -EINVAL; if (enable) status = st->gate_ctrl(fe, 1); else status = st->gate_ctrl(fe, 0); return status; }

Contributors

PersonTokensPropCommitsCommitProp
Mauro Carvalho Chehab93100.00%7100.00%
Total93100.00%7100.00%

static struct mt2063_config az6007_mt2063_config = { .tuner_address = 0x60, .refclock = 36125000, };
static int __az6007_read(struct usb_device *udev, u8 req, u16 value, u16 index, u8 *b, int blen) { int ret; ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), req, USB_TYPE_VENDOR | USB_DIR_IN, value, index, b, blen, 5000); if (ret < 0) { pr_warn("usb read operation failed. (%d)\n", ret); return -EIO; } if (az6007_xfer_debug) { printk(KERN_DEBUG "az6007: IN req: %02x, value: %04x, index: %04x\n", req, value, index); print_hex_dump_bytes("az6007: payload: ", DUMP_PREFIX_NONE, b, blen); } return ret; }

Contributors

PersonTokensPropCommitsCommitProp
Mauro Carvalho Chehab111100.00%6100.00%
Total111100.00%6100.00%


static int az6007_read(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen) { struct az6007_device_state *st = d->priv; int ret; if (mutex_lock_interruptible(&st->mutex) < 0) return -EAGAIN; ret = __az6007_read(d->udev, req, value, index, b, blen); mutex_unlock(&st->mutex); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
Mauro Carvalho Chehab85100.00%2100.00%
Total85100.00%2100.00%


static int __az6007_write(struct usb_device *udev, u8 req, u16 value, u16 index, u8 *b, int blen) { int ret; if (az6007_xfer_debug) { printk(KERN_DEBUG "az6007: OUT req: %02x, value: %04x, index: %04x\n", req, value, index); print_hex_dump_bytes("az6007: payload: ", DUMP_PREFIX_NONE, b, blen); } if (blen > 64) { pr_err("az6007: tried to write %d bytes, but I2C max size is 64 bytes\n", blen); return -EOPNOTSUPP; } ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), req, USB_TYPE_VENDOR | USB_DIR_OUT, value, index, b, blen, 5000); if (ret != blen) { pr_err("usb write operation failed. (%d)\n", ret); return -EIO; } return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Mauro Carvalho Chehab130100.00%7100.00%
Total130100.00%7100.00%


static int az6007_write(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen) { struct az6007_device_state *st = d->priv; int ret; if (mutex_lock_interruptible(&st->mutex) < 0) return -EAGAIN; ret = __az6007_write(d->udev, req, value, index, b, blen); mutex_unlock(&st->mutex); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
Mauro Carvalho Chehab85100.00%1100.00%
Total85100.00%1100.00%


static int az6007_streaming_ctrl(struct dvb_frontend *fe, int onoff) { struct dvb_usb_device *d = fe_to_d(fe); pr_debug("%s: %s\n", __func__, onoff ? "enable" : "disable"); return az6007_write(d, 0xbc, onoff, 0, NULL, 0); }

Contributors

PersonTokensPropCommitsCommitProp
Mauro Carvalho Chehab53100.00%4100.00%
Total53100.00%4100.00%

#if IS_ENABLED(CONFIG_RC_CORE) /* remote control stuff (does not work with my box) */
static int az6007_rc_query(struct dvb_usb_device *d) { struct az6007_device_state *st = d_to_priv(d); unsigned code; enum rc_type proto; az6007_read(d, AZ6007_READ_IR, 0, 0, st->data, 10); if (st->data[1] == 0x44) return 0; if ((st->data[3] ^ st->data[4]) == 0xff) { if ((st->data[1] ^ st->data[2]) == 0xff) { code = RC_SCANCODE_NEC(st->data[1], st->data[3]); proto = RC_TYPE_NEC; } else { code = RC_SCANCODE_NECX(st->data[1] << 8 | st->data[2], st->data[3]); proto = RC_TYPE_NECX; } } else { code = RC_SCANCODE_NEC32(st->data[1] << 24 | st->data[2] << 16 | st->data[3] << 8 | st->data[4]); proto = RC_TYPE_NEC32; } rc_keydown(d->rc_dev, proto, code, st->data[5]); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Jose Alberto Reguero14764.47%120.00%
David Härdeman4921.49%120.00%
Sean Young219.21%120.00%
Mauro Carvalho Chehab114.82%240.00%
Total228100.00%5100.00%


static int az6007_get_rc_config(struct dvb_usb_device *d, struct dvb_usb_rc *rc) { pr_debug("Getting az6007 Remote Control properties\n"); rc->allowed_protos = RC_BIT_NEC | RC_BIT_NECX | RC_BIT_NEC32; rc->query = az6007_rc_query; rc->interval = 400; return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Antti Palosaari4291.30%150.00%
Sean Young48.70%150.00%
Total46100.00%2100.00%

#else #define az6007_get_rc_config NULL #endif
static int az6007_ci_read_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int address) { struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; struct az6007_device_state *state = d_to_priv(d); int ret; u8 req; u16 value; u16 index; int blen; u8 *b; if (slot != 0) return -EINVAL; b = kmalloc(12, GFP_KERNEL); if (!b) return -ENOMEM; mutex_lock(&state->ca_mutex); req = 0xC1; value = address; index = 0; blen = 1; ret = az6007_read(d, req, value, index, b, blen); if (ret < 0) { pr_warn("usb in operation failed. (%d)\n", ret); ret = -EINVAL; } else { ret = b[0]; } mutex_unlock(&state->ca_mutex); kfree(b); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
Jose Alberto Reguero17097.14%150.00%
Mauro Carvalho Chehab52.86%150.00%
Total175100.00%2100.00%


static int az6007_ci_write_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int address, u8 value) { struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; struct az6007_device_state *state = d_to_priv(d); int ret; u8 req; u16 value1; u16 index; int blen; pr_debug("%s(), slot %d\n", __func__, slot); if (slot != 0) return -EINVAL; mutex_lock(&state->ca_mutex); req = 0xC2; value1 = address; index = value; blen = 0; ret = az6007_write(d, req, value1, index, NULL, blen); if (ret != 0) pr_warn("usb out operation failed. (%d)\n", ret); mutex_unlock(&state->ca_mutex); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
Jose Alberto Reguero13695.10%150.00%
Mauro Carvalho Chehab74.90%150.00%
Total143100.00%2100.00%


static int az6007_ci_read_cam_control(struct dvb_ca_en50221 *ca, int slot, u8 address) { struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; struct az6007_device_state *state = d_to_priv(d); int ret; u8 req; u16 value; u16 index; int blen; u8 *b; if (slot != 0) return -EINVAL; b = kmalloc(12, GFP_KERNEL); if (!b) return -ENOMEM; mutex_lock(&state->ca_mutex); req = 0xC3; value = address; index = 0; blen = 2; ret = az6007_read(d, req, value, index, b, blen); if (ret < 0) { pr_warn("usb in operation failed. (%d)\n", ret); ret = -EINVAL; } else { if (b[0] == 0) pr_warn("Read CI IO error\n"); ret = b[1]; pr_debug("read cam data = %x from 0x%x\n", b[1], value); } mutex_unlock(&state->ca_mutex); kfree(b); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
Jose Alberto Reguero19295.52%150.00%
Mauro Carvalho Chehab94.48%150.00%
Total201100.00%2100.00%


static int az6007_ci_write_cam_control(struct dvb_ca_en50221 *ca, int slot, u8 address, u8 value) { struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; struct az6007_device_state *state = d_to_priv(d); int ret; u8 req; u16 value1; u16 index; int blen; if (slot != 0) return -EINVAL; mutex_lock(&state->ca_mutex); req = 0xC4; value1 = address; index = value; blen = 0; ret = az6007_write(d, req, value1, index, NULL, blen); if (ret != 0) { pr_warn("usb out operation failed. (%d)\n", ret); goto failed; } failed: mutex_unlock(&state->ca_mutex); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
Jose Alberto Reguero13696.45%150.00%
Mauro Carvalho Chehab53.55%150.00%
Total141100.00%2100.00%


static int CI_CamReady(struct dvb_ca_en50221 *ca, int slot) { struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; int ret; u8 req; u16 value; u16 index; int blen; u8 *b; b = kmalloc(12, GFP_KERNEL); if (!b) return -ENOMEM; req = 0xC8; value = 0; index = 0; blen = 1; ret = az6007_read(d, req, value, index, b, blen); if (ret < 0) { pr_warn("usb in operation failed. (%d)\n", ret); ret = -EIO; } else{ ret = b[0]; } kfree(b); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
Jose Alberto Reguero13498.53%150.00%
Mauro Carvalho Chehab21.47%150.00%
Total136100.00%2100.00%


static int az6007_ci_slot_reset(struct dvb_ca_en50221 *ca, int slot) { struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; struct az6007_device_state *state = d_to_priv(d); int ret, i; u8 req; u16 value; u16 index; int blen; mutex_lock(&state->ca_mutex); req = 0xC6; value = 1; index = 0; blen = 0; ret = az6007_write(d, req, value, index, NULL, blen); if (ret != 0) { pr_warn("usb out operation failed. (%d)\n", ret); goto failed; } msleep(500); req = 0xC6; value = 0; index = 0; blen = 0; ret = az6007_write(d, req, value, index, NULL, blen); if (ret != 0) { pr_warn("usb out operation failed. (%d)\n", ret); goto failed; } for (i = 0; i < 15; i++) { msleep(100); if (CI_CamReady(ca, slot)) { pr_debug("CAM Ready\n"); break; } } msleep(5000); failed: mutex_unlock(&state->ca_mutex); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
Jose Alberto Reguero21696.00%150.00%
Mauro Carvalho Chehab94.00%150.00%
Total225100.00%2100.00%


static int az6007_ci_slot_shutdown(struct dvb_ca_en50221 *ca, int slot) { return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Jose Alberto Reguero17100.00%1100.00%
Total17100.00%1100.00%


static int az6007_ci_slot_ts_enable(struct dvb_ca_en50221 *ca, int slot) { struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; struct az6007_device_state *state = d_to_priv(d); int ret; u8 req; u16 value; u16 index; int blen; pr_debug("%s()\n", __func__); mutex_lock(&state->ca_mutex); req = 0xC7; value = 1; index = 0; blen = 0; ret = az6007_write(d, req, value, index, NULL, blen); if (ret != 0) { pr_warn("usb out operation failed. (%d)\n", ret); goto failed; } failed: mutex_unlock(&state->ca_mutex); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
Jose Alberto Reguero12594.70%150.00%
Mauro Carvalho Chehab75.30%150.00%
Total132100.00%2100.00%


static int az6007_ci_poll_slot_status(struct dvb_ca_en50221 *ca, int slot, int open) { struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; struct az6007_device_state *state = d_to_priv(d); int ret; u8 req; u16 value; u16 index; int blen; u8 *b; b = kmalloc(12, GFP_KERNEL); if (!b) return -ENOMEM; mutex_lock(&state->ca_mutex); req = 0xC5; value = 0; index = 0; blen = 1; ret = az6007_read(d, req, value, index, b, blen); if (ret < 0) { pr_warn("usb in operation failed. (%d)\n", ret); ret = -EIO; } else ret = 0; if (!ret && b[0] == 1) { ret = DVB_CA_EN50221_POLL_CAM_PRESENT | DVB_CA_EN50221_POLL_CAM_READY; } mutex_unlock(&state->ca_mutex); kfree(b); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
Jose Alberto Reguero17597.22%150.00%
Mauro Carvalho Chehab52.78%150.00%
Total180100.00%2100.00%


static void az6007_ci_uninit(struct dvb_usb_device *d) { struct az6007_device_state *state; pr_debug("%s()\n", __func__); if (NULL == d) return; state = d_to_priv(d); if (NULL == state) return; if (NULL == state->ca.data) return; dvb_ca_en50221_release(&state->ca); memset(&state->ca, 0, sizeof(state->ca)); }

Contributors

PersonTokensPropCommitsCommitProp
Jose Alberto Reguero7593.75%150.00%
Mauro Carvalho Chehab56.25%150.00%
Total80100.00%2100.00%


static int az6007_ci_init(struct dvb_usb_adapter *adap) { struct dvb_usb_device *d = adap_to_d(adap); struct az6007_device_state *state = adap_to_priv(adap); int ret; pr_debug("%s()\n", __func__); mutex_init(&state->ca_mutex); state->ca.owner = THIS_MODULE; state->ca.read_attribute_mem = az6007_ci_read_attribute_mem; state->ca.write_attribute_mem = az6007_ci_write_attribute_mem; state->ca.read_cam_control = az6007_ci_read_cam_control; state->ca.write_cam_control = az6007_ci_write_cam_control; state->ca.slot_reset = az6007_ci_slot_reset; state->ca.slot_shutdown = az6007_ci_slot_shutdown; state->ca.slot_ts_enable = az6007_ci_slot_ts_enable; state->ca.poll_slot_status = az6007_ci_poll_slot_status; state->ca.data = d; ret = dvb_ca_en50221_init(&adap->dvb_adap, &state->ca, 0, /* flags */ 1);/* n_slots */ if (ret != 0) { pr_err("Cannot initialize CI: Error %d.\n", ret); memset(&state->ca, 0, sizeof(state->ca)); return ret; } pr_debug("CI initialized.\n"); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Jose Alberto Reguero13569.95%116.67%
Mauro Carvalho Chehab5830.05%583.33%
Total193100.00%6100.00%


static int az6007_read_mac_addr(struct dvb_usb_adapter *adap, u8 mac[6]) { struct dvb_usb_device *d = adap_to_d(adap); struct az6007_device_state *st = adap_to_priv(adap); int ret; ret = az6007_read(d, AZ6007_READ_DATA, 6, 0, st->data, 6); memcpy(mac, st->data, 6); if (ret > 0) pr_debug("%s: mac is %pM\n", __func__, mac); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
Mauro Carvalho Chehab8697.73%571.43%
Andy Shevchenko11.14%114.29%
Alan Cox11.14%114.29%
Total88100.00%7100.00%


static int az6007_frontend_attach(struct dvb_usb_adapter *adap) { struct az6007_device_state *st = adap_to_priv(adap); struct dvb_usb_device *d = adap_to_d(adap); pr_debug("attaching demod drxk\n"); adap->fe[0] = dvb_attach(drxk_attach, &terratec_h7_drxk, &d->i2c_adap); if (!adap->fe[0]) return -EINVAL; adap->fe[0]->sec_priv = adap; st->gate_ctrl = adap->fe[0]->ops.i2c_gate_ctrl; adap->fe[0]->ops.i2c_gate_ctrl = drxk_gate_ctrl; az6007_ci_init(adap); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Mauro Carvalho Chehab11295.73%685.71%
Jose Alberto Reguero54.27%114.29%
Total117100.00%7100.00%


static int az6007_cablestar_hdci_frontend_attach(struct dvb_usb_adapter *adap) { struct az6007_device_state *st = adap_to_priv(adap); struct dvb_usb_device *d = adap_to_d(adap); pr_debug("attaching demod drxk\n"); adap->fe[0] = dvb_attach(drxk_attach, &cablestar_hdci_drxk, &d->i2c_adap); if (!adap->fe[0]) return -EINVAL; adap->fe[0]->sec_priv = adap; st->gate_ctrl = adap->fe[0]->ops.i2c_gate_ctrl; adap->fe[0]->ops.i2c_gate_ctrl = drxk_gate_ctrl; az6007_ci_init(adap); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Roland Scheidegger117100.00%1100.00%
Total117100.00%1100.00%


static int az6007_tuner_attach(struct dvb_usb_adapter *adap) { struct dvb_usb_device *d = adap_to_d(adap); pr_debug("attaching tuner mt2063\n"); /* Attach mt2063 to DVB-C frontend */ if (adap->fe[0]->ops.i2c_gate_ctrl) adap->fe[0]->ops.i2c_gate_ctrl(adap->fe[0], 1); if (!dvb_attach(mt2063_attach, adap->fe[0], &az6007_mt2063_config, &d->i2c_adap)) return -EINVAL; if (adap->fe[0]->ops.i2c_gate_ctrl) adap->fe[0]->ops.i2c_gate_ctrl(adap->fe[0], 0); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Mauro Carvalho Chehab125100.00%2100.00%
Total125100.00%2100.00%


static int az6007_power_ctrl(struct dvb_usb_device *d, int onoff) { struct az6007_device_state *state = d_to_priv(d); int ret; pr_debug("%s()\n", __func__); if (!state->warm) { mutex_init(&state->mutex); ret = az6007_write(d, AZ6007_POWER, 0, 2, NULL, 0); if (ret < 0) return ret; msleep(60); ret = az6007_write(d, AZ6007_POWER, 1, 4, NULL, 0); if (ret < 0) return ret; msleep(100); ret = az6007_write(d, AZ6007_POWER, 1, 3, NULL, 0); if (ret < 0) return ret; msleep(20); ret = az6007_write(d, AZ6007_POWER, 1, 4, NULL, 0); if (ret < 0) return ret; msleep(400); ret = az6007_write(d, FX2_SCON1, 0, 3, NULL, 0); if (ret < 0) return ret; msleep(150); ret = az6007_write(d, FX2_SCON1, 1, 3, NULL, 0); if (ret < 0) return ret; msleep(430); ret = az6007_write(d, AZ6007_POWER, 0, 0, NULL, 0); if (ret < 0) return ret; state->warm = true; return 0; } if (!onoff) return 0; az6007_write(d, AZ6007_POWER, 0, 0, NULL, 0); az6007_write(d, AZ6007_TS_THROUGH, 0, 0, NULL, 0); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Mauro Carvalho Chehab313100.00%12100.00%
Total313100.00%12100.00%

/* I2C */
static int az6007_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) { struct dvb_usb_device *d = i2c_get_adapdata(adap); struct az6007_device_state *st = d_to_priv(d); int i, j, len; int ret = 0; u16 index; u16 value; int length; u8 req, addr; if (mutex_lock_interruptible(&st->mutex) < 0) return -EAGAIN; for (i = 0; i < num; i++) { addr = msgs[i].addr << 1; if (((i + 1) < num) && (msgs[i].len == 1) && ((msgs[i].flags & I2C_M_RD) != I2C_M_RD) && (msgs[i + 1].flags & I2C_M_RD) && (msgs[i].addr == msgs[i + 1].addr)) { /* * A write + read xfer for the same address, where * the first xfer has just 1 byte length. * Need to join both into one operation */ if (az6007_xfer_debug) printk(KERN_DEBUG "az6007: I2C W/R addr=0x%x len=%d/%d\n", addr, msgs[i].len, msgs[i + 1].len); req = AZ6007_I2C_RD; index = msgs[i].buf[0]; value = addr | (1 << 8); length = 6 + msgs[i + 1].len; len = msgs[i + 1].len; ret = __az6007_read(d->udev, req, value, index, st->data, length); if (ret >= len) { for (j = 0; j < len; j++) msgs[i + 1].buf[j] = st->data[j + 5]; } else ret = -EIO; i++; } else if (!(msgs[i].flags & I2C_M_RD)) { /* write bytes */ if (az6007_xfer_debug) printk(KERN_DEBUG "az6007: I2C W addr=0x%x len=%d\n", addr, msgs[i].len); req = AZ6007_I2C_WR; index = msgs[i].buf[0]; value = addr | (1 << 8); length = msgs[i].len - 1; len = msgs[i].len - 1; for (j = 0; j < len; j++) st->data[j] = msgs[i].buf[j + 1]; ret = __az6007_write(d->udev, req, value, index, st->data, length); } else { /* read bytes */ if (az6007_xfer_debug) printk(KERN_DEBUG "az6007: I2C R addr=0x%x len=%d\n", addr, msgs[i].len); req = AZ6007_I2C_RD; index = msgs[i].buf[0]; value = addr; length = msgs[i].len + 6; len = msgs[i].len; ret = __az6007_read(d->udev, req, value, index, st->data, length); for (j = 0; j < len; j++) msgs[i].buf[j] = st->data[j + 5]; } if (ret < 0) goto err; } err: mutex_unlock(&st->mutex); if (ret < 0) { pr_info("%s ERROR: %i\n", __func__, ret); return ret; } return num; }

Contributors

PersonTokensPropCommitsCommitProp
Mauro Carvalho Chehab625100.00%9100.00%
Total625100.00%9100.00%


static u32 az6007_i2c_func(struct i2c_adapter *adapter) { return I2C_FUNC_I2C; }

Contributors

PersonTokensPropCommitsCommitProp
Mauro Carvalho Chehab14100.00%1100.00%
Total14100.00%1100.00%

static struct i2c_algorithm az6007_i2c_algo = { .master_xfer = az6007_i2c_xfer, .functionality = az6007_i2c_func, };
static int az6007_identify_state(struct dvb_usb_device *d, const char **name) { int ret; u8 *mac; pr_debug("Identifying az6007 state\n"); mac = kmalloc(6, GFP_ATOMIC); if (!mac) return -ENOMEM; /* Try to read the mac address */ ret = __az6007_read(d->udev, AZ6007_READ_DATA, 6, 0, mac, 6); if (ret == 6) ret = WARM; else ret = COLD; kfree(mac); if (ret == COLD) { __az6007_write(d->udev, 0x09, 1, 0, NULL, 0); __az6007_write(d->udev, 0x00, 0, 0, NULL, 0); __az6007_write(d->udev, 0x00, 0, 0, NULL, 0); } pr_debug("Device is on %s state\n", ret == WARM ? "warm" : "cold"); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
Mauro Carvalho Chehab162100.00%7100.00%
Total162100.00%7100.00%


static void az6007_usb_disconnect(struct usb_interface *intf) { struct dvb_usb_device *d = usb_get_intfdata(intf); az6007_ci_uninit(d); dvb_usbv2_disconnect(intf); }

Contributors

PersonTokensPropCommitsCommitProp
Jose Alberto Reguero3096.77%150.00%
Mauro Carvalho Chehab13.23%150.00%
Total31100.00%2100.00%


static int az6007_download_firmware(struct dvb_usb_device *d, const struct firmware *fw) { pr_debug("Loading az6007 firmware\n"); return cypress_load_firmware(d->udev, fw, CYPRESS_FX2); }

Contributors

PersonTokensPropCommitsCommitProp
Mauro Carvalho Chehab3088.24%250.00%
Jose Alberto Reguero38.82%125.00%
Hans Verkuil12.94%125.00%
Total34100.00%4100.00%

/* DVB USB Driver stuff */ static struct dvb_usb_device_properties az6007_props = { .driver_name = KBUILD_MODNAME, .owner = THIS_MODULE, .firmware = AZ6007_FIRMWARE, .adapter_nr = adapter_nr, .size_of_priv = sizeof(struct az6007_device_state), .i2c_algo = &az6007_i2c_algo, .tuner_attach = az6007_tuner_attach, .frontend_attach = az6007_frontend_attach, .streaming_ctrl = az6007_streaming_ctrl, .get_rc_config = az6007_get_rc_config, .read_mac_address = az6007_read_mac_addr, .download_firmware = az6007_download_firmware, .identify_state = az6007_identify_state, .power_ctrl = az6007_power_ctrl, .num_adapters = 1, .adapter = { { .stream = DVB_USB_STREAM_BULK(0x02, 10, 4096), } } }; static struct dvb_usb_device_properties az6007_cablestar_hdci_props = { .driver_name = KBUILD_MODNAME, .owner = THIS_MODULE, .firmware = AZ6007_FIRMWARE, .adapter_nr = adapter_nr, .size_of_priv = sizeof(struct az6007_device_state), .i2c_algo = &az6007_i2c_algo, .tuner_attach = az6007_tuner_attach, .frontend_attach = az6007_cablestar_hdci_frontend_attach, .streaming_ctrl = az6007_streaming_ctrl, /* ditch get_rc_config as it can't work (TS35 remote, I believe it's rc5) */ .get_rc_config = NULL, .read_mac_address = az6007_read_mac_addr, .download_firmware = az6007_download_firmware, .identify_state = az6007_identify_state, .power_ctrl = az6007_power_ctrl, .num_adapters = 1, .adapter = { { .stream = DVB_USB_STREAM_BULK(0x02, 10, 4096), } } }; static struct usb_device_id az6007_usb_table[] = { {DVB_USB_DEVICE(USB_VID_AZUREWAVE, USB_PID_AZUREWAVE_6007, &az6007_props, "Azurewave 6007", RC_MAP_EMPTY)}, {DVB_USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_H7, &az6007_props, "Terratec H7", RC_MAP_NEC_TERRATEC_CINERGY_XS)}, {DVB_USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_H7_2, &az6007_props, "Terratec H7", RC_MAP_NEC_TERRATEC_CINERGY_XS)}, {DVB_USB_DEVICE(USB_VID_TECHNISAT, USB_PID_TECHNISAT_USB2_CABLESTAR_HDCI, &az6007_cablestar_hdci_props, "Technisat CableStar Combo HD CI", RC_MAP_EMPTY)}, {0}, }; MODULE_DEVICE_TABLE(usb, az6007_usb_table);
static int az6007_suspend(struct usb_interface *intf, pm_message_t msg) { struct dvb_usb_device *d = usb_get_intfdata(intf); az6007_ci_uninit(d); return dvb_usbv2_suspend(intf, msg); }

Contributors

PersonTokensPropCommitsCommitProp
Mauro Carvalho Chehab37100.00%1100.00%
Total37100.00%1100.00%


static int az6007_resume(struct usb_interface *intf) { struct dvb_usb_device *d = usb_get_intfdata(intf); struct dvb_usb_adapter *adap = &d->adapter[0]; az6007_ci_init(adap); return dvb_usbv2_resume(intf); }

Contributors

PersonTokensPropCommitsCommitProp
Mauro Carvalho Chehab45100.00%1100.00%
Total45100.00%1100.00%

/* usb specific object needed to register this driver with the usb subsystem */ static struct usb_driver az6007_usb_driver = { .name = KBUILD_MODNAME, .id_table = az6007_usb_table, .probe = dvb_usbv2_probe, .disconnect = az6007_usb_disconnect, .no_dynamic_id = 1, .soft_unbind = 1, /* * FIXME: need to implement reset_resume, likely with * dvb-usb-v2 core support */ .suspend = az6007_suspend, .resume = az6007_resume, }; module_usb_driver(az6007_usb_driver); MODULE_AUTHOR("Henry Wang <Henry.wang@AzureWave.com>"); MODULE_AUTHOR("Mauro Carvalho Chehab"); MODULE_DESCRIPTION("Driver for AzureWave 6007 DVB-C/T USB2.0 and clones"); MODULE_VERSION("2.0"); MODULE_LICENSE("GPL"); MODULE_FIRMWARE(AZ6007_FIRMWARE);

Overall Contributors

PersonTokensPropCommitsCommitProp
Mauro Carvalho Chehab269555.85%3477.27%
Jose Alberto Reguero170135.25%24.55%
Roland Scheidegger2966.13%12.27%
Antti Palosaari561.16%24.55%
David Härdeman491.02%12.27%
Sean Young250.52%12.27%
Hans Verkuil10.02%12.27%
Alan Cox10.02%12.27%
Andy Shevchenko10.02%12.27%
Total4825100.00%44100.00%
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with cregit.