From 71d676345698b275955b2584803ae550972249e5 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 21 Jul 2011 17:46:41 -0300 Subject: [media] dvb: Add a new driver for az6007 Import the az6007 driver from Terratec H7 source, as-is. It won't compile or run, so latter patches are needed in order to fix it. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/az6007.c | 627 +++++++++++++++++++++++++++++++++++++ drivers/media/dvb/dvb-usb/az6007.h | 18 ++ 2 files changed, 645 insertions(+) create mode 100644 drivers/media/dvb/dvb-usb/az6007.c create mode 100644 drivers/media/dvb/dvb-usb/az6007.h (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/dvb-usb/az6007.c b/drivers/media/dvb/dvb-usb/az6007.c new file mode 100644 index 000000000000..cd5dd4cecd0b --- /dev/null +++ b/drivers/media/dvb/dvb-usb/az6007.c @@ -0,0 +1,627 @@ +/* DVB USB compliant Linux driver for the AzureWave 6017 USB2.0 DVB-S + * receiver. + * see Documentation/dvb/README.dvb-usb for more information + */ + +#include "az6007.h" +#include "drxk.h" +#include "mt2063.h" +#include "dvb_ca_en50221.h" + +/* debug */ +int dvb_usb_az6007_debug; +module_param_named(debug,dvb_usb_az6007_debug, int, 0644); +MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2,rc=4 (or-able))." DVB_USB_DEBUG_STATUS); + + +static int az6007_type =0; +module_param(az6007_type, int, 0644); +MODULE_PARM_DESC(az6007_type, "select delivery mode (0=DVB-T, 1=DVB-T"); + +//module_param_named(type, 6007_type, int, 0644); +//MODULE_PARM_DESC(type, "select delivery mode (0=DVB-T, 1=DVB-C)"); + +DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); + + +struct az6007_device_state { + struct dvb_ca_en50221 ca; + struct mutex ca_mutex; + u8 power_state; +}; + +struct drxk3913_config az6007_drxk3913_config_DVBT = { + .demod_address = 0x52, + .min_delay_ms = 100, + .standard = MTTUNEA_DVBT, + .set_tuner = mt2063_setTune, + .tuner_getlocked = mt2063_lockStatus, + .tuner_MT2063_Open = tuner_MT2063_Open, + .tuner_MT2063_SoftwareShutdown = tuner_MT2063_SoftwareShutdown, + .tuner_MT2063_ClearPowerMaskBits = tuner_MT2063_ClearPowerMaskBits, +}; + +struct drxk3913_config az6007_drxk3913_config_DVBC = { + .demod_address = 0x52, + .min_delay_ms = 100, + .standard = MTTUNEA_DVBC, + .set_tuner = mt2063_setTune, + .tuner_getlocked = mt2063_lockStatus, + .tuner_MT2063_Open = tuner_MT2063_Open, + .tuner_MT2063_SoftwareShutdown = tuner_MT2063_SoftwareShutdown, + .tuner_MT2063_ClearPowerMaskBits = tuner_MT2063_ClearPowerMaskBits, +}; + +struct mt2063_config az6007_mt2063_config = { + .tuner_address = 0xc0, + .refclock = 36125000, +}; + +/* check for mutex FIXME */ +int az6007_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen) +{ + int ret = -1; + + ret = usb_control_msg(d->udev, + usb_rcvctrlpipe(d->udev,0), + req, + USB_TYPE_VENDOR | USB_DIR_IN, + value,index,b,blen, + 5000); + + if (ret < 0) { + warn("usb in operation failed. (%d)", ret); + ret = -EIO; + } else + ret = 0; + + + deb_xfer("in: req. %02x, val: %04x, ind: %04x, buffer: ",req,value,index); + debug_dump(b,blen,deb_xfer); + + return ret; +} + +static int az6007_usb_out_op(struct dvb_usb_device *d, u8 req, u16 value, + u16 index, u8 *b, int blen) +{ + int ret; + +#if 0 + int i=0, cyc=0, rem=0; + cyc = blen/64; + rem = blen%64; +#endif + + deb_xfer("out: req. %02x, val: %04x, ind: %04x, buffer: ",req,value,index); + debug_dump(b,blen,deb_xfer); + + +#if 0 + if (blen>64) + { + for (i=0; iudev, + usb_sndctrlpipe(d->udev,0), + req, + USB_TYPE_VENDOR | USB_DIR_OUT, + value,index+i*64,b+i*64,64, + 5000)) != 64) { + warn("usb out operation failed. (%d)",ret); + return -EIO; + } + } + + if (rem>0) + { + if ((ret = usb_control_msg(d->udev, + usb_sndctrlpipe(d->udev,0), + req, + USB_TYPE_VENDOR | USB_DIR_OUT, + value,index+cyc*64,b+cyc*64,rem, + 5000)) != rem) { + warn("usb out operation failed. (%d)",ret); + return -EIO; + } + } + } + else +#endif + { + if ((ret = usb_control_msg(d->udev, + usb_sndctrlpipe(d->udev,0), + req, + USB_TYPE_VENDOR | USB_DIR_OUT, + value,index,b,blen, + 5000)) != blen) { + warn("usb out operation failed. (%d)",ret); + return -EIO; + } + } + + return 0; +} + +static int az6007_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) +{ + return 0; +} + +/* keys for the enclosed remote control */ +static struct dvb_usb_rc_key az6007_rc_keys[] = { + { 0x00, 0x01, KEY_1 }, + { 0x00, 0x02, KEY_2 }, +}; + +/* remote control stuff (does not work with my box) */ +static int az6007_rc_query(struct dvb_usb_device *d, u32 *event, int *state) +{ + return 0; +#if 0 + u8 key[10]; + int i; + +/* remove the following return to enabled remote querying */ + + + az6007_usb_in_op(d,READ_REMOTE_REQ,0,0,key,10); + + deb_rc("remote query key: %x %d\n",key[1],key[1]); + + if (key[1] == 0x44) { + *state = REMOTE_NO_KEY_PRESSED; + return 0; + } + + for (i = 0; i < ARRAY_SIZE(az6007_rc_keys); i++) + if (az6007_rc_keys[i].custom == key[1]) { + *state = REMOTE_KEY_PRESSED; + *event = az6007_rc_keys[i].event; + break; + } + return 0; +#endif +} + +/* +int az6007_power_ctrl(struct dvb_usb_device *d, int onoff) +{ + u8 v = onoff; + return az6007_usb_out_op(d,0xBC,v,3,NULL,1); +} +*/ + +static int az6007_read_mac_addr(struct dvb_usb_device *d,u8 mac[6]) +{ + az6007_usb_in_op(d, 0xb7, 6, 0, &mac[0], 6); + return 0; +} + +static int az6007_frontend_poweron(struct dvb_usb_adapter *adap) +{ + int ret; + u8 req; + u16 value; + u16 index; + int blen; + + info("az6007_frontend_poweron adap=%p adap->dev=%p\n", adap, adap->dev); + + req = 0xBC; + value = 1;//power on + index = 3; + blen =0; + + if((ret = az6007_usb_out_op(adap->dev,req,value,index,NULL,blen)) != 0) + { + err("az6007_frontend_poweron failed!!!"); + return -EIO; + } + + msleep_interruptible(200); + + req = 0xBC; + value = 0;//power on + index = 3; + blen =0; + + if((ret = az6007_usb_out_op(adap->dev,req,value,index,NULL,blen)) != 0) + { + err("az6007_frontend_poweron failed!!!"); + return -EIO; + } + + msleep_interruptible(200); + + req = 0xBC; + value = 1;//power on + index = 3; + blen =0; + + if((ret = az6007_usb_out_op(adap->dev,req,value,index,NULL,blen)) != 0) + { + err("az6007_frontend_poweron failed!!!"); + return -EIO; + } + info("az6007_frontend_poweron\n"); + return 0; +} + +static int az6007_frontend_reset(struct dvb_usb_adapter *adap) +{ + int ret; + u8 req; + u16 value; + u16 index; + int blen; + + info("az6007_frontend_reset adap=%p adap->dev=%p\n", adap, adap->dev); + + //reset demodulator + req = 0xC0; + value = 1;//high + index = 3; + blen =0; + if((ret = az6007_usb_out_op(adap->dev,req,value,index,NULL,blen)) != 0) + { + err("az6007_frontend_reset failed 1 !!!"); + return -EIO; + } + + req = 0xC0; + value = 0;//low + index = 3; + blen =0; + msleep_interruptible(200); + if((ret = az6007_usb_out_op(adap->dev,req,value,index,NULL,blen)) != 0) + { + err("az6007_frontend_reset failed 2 !!!"); + return -EIO; + } + msleep_interruptible(200); + req = 0xC0; + value = 1;//high + index = 3; + blen =0; + + if((ret = az6007_usb_out_op(adap->dev,req,value,index,NULL,blen)) != 0) + { + err("az6007_frontend_reset failed 3 !!!"); + return -EIO; + } + + msleep_interruptible(200); + + info("reset az6007 frontend\n"); + + return 0; +} + +static int az6007_led_on_off(struct usb_interface *intf, int onoff) +{ + int ret = -1; + u8 req; + u16 value; + u16 index; + int blen; + //TS through + req = 0xBC; + value = onoff; + index = 0; + blen =0; + + ret = usb_control_msg(interface_to_usbdev(intf), + usb_rcvctrlpipe(interface_to_usbdev(intf),0), + req, + USB_TYPE_VENDOR | USB_DIR_OUT, + value,index,NULL,blen, + 2000); + + if (ret < 0) { + warn("usb in operation failed. (%d)", ret); + ret = -EIO; + } else + ret = 0; + + + deb_xfer("in: req. %02x, val: %04x, ind: %04x, buffer: ",req,value,index); + + return ret; +} + +static int az6007_frontend_tsbypass(struct dvb_usb_adapter *adap,int onoff) +{ + int ret; + u8 req; + u16 value; + u16 index; + int blen; + //TS through + req = 0xC7; + value = onoff; + index = 0; + blen =0; + + if((ret = az6007_usb_out_op(adap->dev,req,value,index,NULL,blen)) != 0) + return -EIO; + return 0; +} + +static int az6007_frontend_attach(struct dvb_usb_adapter *adap) +{ + az6007_frontend_poweron(adap); + az6007_frontend_reset(adap); + + info("az6007_frontend_attach\n"); + + if (az6007_type == 0) + { + info("az6007_drxk3913_config_DVBT\n"); + adap->fe = drxk3913_attach(&az6007_drxk3913_config_DVBT, &adap->dev->i2c_adap); + } + else + { + info("az6007_drxk3913_config_DVBC\n"); + adap->fe = drxk3913_attach(&az6007_drxk3913_config_DVBC, &adap->dev->i2c_adap); + } + if (adap->fe) { + if (mt2063_attach(adap->fe, &az6007_mt2063_config, &adap->dev->i2c_adap)) { + info("found STB6100 DVB-C/DVB-T frontend @0x%02x\n",az6007_mt2063_config.tuner_address); + + //vp6027_ci_init(adap); + } else { + adap->fe = NULL; + } + } + else + { + adap->fe = NULL; + err("no front-end attached\n"); + } + //az6007_frontend_tsbypass(adap,0); + + return 0; +} + +static struct dvb_usb_device_properties az6007_properties; + +static void +az6007_usb_disconnect(struct usb_interface *intf) +{ + dvb_usb_device_exit (intf); +} + +/* I2C */ +static int az6007_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num) +{ + struct dvb_usb_device *d = i2c_get_adapdata(adap); + int j=0,len=0; + int ret=0; + u16 index; + u16 value; + int length; + u8 req; + u8 data[512]; + + if (mutex_lock_interruptible(&d->i2c_mutex) < 0) + return -EAGAIN; + if (num > 2) + warn("more than 2 i2c messages at a time is not handled yet. TODO."); + + + if (msg[0].addr == 0xc0) //MT2063 + { + if (msg[0].flags != I2C_M_RD) //write + { + //printk("Tuner Tuner Write DevAddr=%02x RegAddr=%d\n", msg[0].addr, msg[0].buf[0]); + req = 0xBD; + index = msg[0].buf[0]; + value = msg[0].addr | (1<<8); + length = msg[0].len - 1; + len = msg[0].len - 1; + //printk("Tuner Tuner WriteDATA len=%d ", len); + for(j=0;ji2c_mutex); + return ret; +} + + +static u32 az6007_i2c_func(struct i2c_adapter *adapter) +{ + return I2C_FUNC_I2C; +} + +static struct i2c_algorithm az6007_i2c_algo = { + .master_xfer = az6007_i2c_xfer, + .functionality = az6007_i2c_func, +#ifdef NEED_ALGO_CONTROL + .algo_control = dummy_algo_control, +#endif +}; + +int az6007_identify_state(struct usb_device *udev, struct dvb_usb_device_properties *props, + struct dvb_usb_device_description **desc, int *cold) +{ + u8 b[16]; + s16 ret = usb_control_msg(udev, usb_rcvctrlpipe(udev,0), + 0xb7, USB_TYPE_VENDOR | USB_DIR_IN, 6, 0, b, 6, USB_CTRL_GET_TIMEOUT); + + info("FW GET_VERSION length: %d\n",ret); + + *cold = ret <= 0; + + info("cold: %d\n", *cold); + return 0; +} + +static int az6007_usb_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + az6007_led_on_off(intf, 0); + + return dvb_usb_device_init(intf, &az6007_properties, + THIS_MODULE, NULL, adapter_nr); +} + +static struct usb_device_id az6007_usb_table [] = { + { USB_DEVICE(USB_VID_AZUREWAVE, USB_PID_AZUREWAVE_6007) }, + { USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_H7) }, + { 0 }, +}; + +MODULE_DEVICE_TABLE(usb, az6007_usb_table); + +static struct dvb_usb_device_properties az6007_properties = { + .caps = DVB_USB_IS_AN_I2C_ADAPTER, + .usb_ctrl = CYPRESS_FX2, + //.download_firmware = az6007_download_firmware, + .firmware = "dvb-usb-az6007-03.fw", + .no_reconnect = 1, + + .size_of_priv = sizeof(struct az6007_device_state), + .identify_state = az6007_identify_state, + .num_adapters = 1, + .adapter = { + { + //.caps = DVB_USB_ADAP_RECEIVES_204_BYTE_TS, + + .streaming_ctrl = az6007_streaming_ctrl, + .frontend_attach = az6007_frontend_attach, + + /* parameter for the MPEG2-data transfer */ + .stream = { + .type = USB_BULK, + .count = 10, + .endpoint = 0x02, + .u = { + .bulk = { + .buffersize = 4096, + } + } + }, + .size_of_priv = 0,//sizeof(struct az6007_state), + } + }, + //.power_ctrl = az6007_power_ctrl, + .read_mac_address = az6007_read_mac_addr, + + .rc_key_map = az6007_rc_keys, + .rc_key_map_size = ARRAY_SIZE(az6007_rc_keys), + .rc_interval = 400, + .rc_query = az6007_rc_query, + .i2c_algo = &az6007_i2c_algo, + + .num_device_descs = 2, + .devices = { + { .name = "AzureWave DTV StarBox DVB-T/C USB2.0 (az6007)", + .cold_ids = { &az6007_usb_table[0], NULL }, + .warm_ids = { NULL }, + }, + { .name = "TerraTec DTV StarBox DVB-T/C USB2.0 (az6007)", + .cold_ids = { &az6007_usb_table[1], NULL }, + .warm_ids = { NULL }, + }, + { NULL }, + } +}; + +/* usb specific object needed to register this driver with the usb subsystem */ +static struct usb_driver az6007_usb_driver = { + .name = "dvb_usb_az6007", + .probe = az6007_usb_probe, + .disconnect = dvb_usb_device_exit, + //.disconnect = az6007_usb_disconnect, + .id_table = az6007_usb_table, +}; + +/* module stuff */ +static int __init az6007_usb_module_init(void) +{ + int result; + info("henry :: az6007 usb module init"); + if ((result = usb_register(&az6007_usb_driver))) { + err("usb_register failed. (%d)",result); + return result; + } + + return 0; +} + +static void __exit az6007_usb_module_exit(void) +{ + /* deregister this driver from the USB subsystem */ + info("henry :: az6007 usb module exit"); + usb_deregister(&az6007_usb_driver); +} + +module_init(az6007_usb_module_init); +module_exit(az6007_usb_module_exit); + +MODULE_AUTHOR("Henry Wang "); +MODULE_DESCRIPTION("Driver for AzureWave 6007 DVB-C/T USB2.0 and clones"); +MODULE_VERSION("1.0"); +MODULE_LICENSE("GPL"); diff --git a/drivers/media/dvb/dvb-usb/az6007.h b/drivers/media/dvb/dvb-usb/az6007.h new file mode 100644 index 000000000000..aefa5b506ee6 --- /dev/null +++ b/drivers/media/dvb/dvb-usb/az6007.h @@ -0,0 +1,18 @@ +#ifndef _DVB_USB_AZ6007_H_ +#define _DVB_USB_AZ6007_H_ + +#define DVB_USB_LOG_PREFIX "az6007" +#include "dvb-usb.h" + + +extern int dvb_usb_az6007_debug; +#define deb_info(args...) dprintk(dvb_usb_az6007_debug,0x01,args) +#define deb_xfer(args...) dprintk(dvb_usb_az6007_debug,0x02,args) +#define deb_rc(args...) dprintk(dvb_usb_az6007_debug,0x04,args) +#define deb_fe(args...) dprintk(dvb_usb_az6007_debug,0x08,args) + + +extern int vp702x_usb_out_op(struct dvb_usb_device *d, u8 *o, int olen, u8 *i, int ilen, int msec); +extern int vp702x_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen); + +#endif -- cgit v1.2.3 From 6da347065062d28de035c01b298c6aebab2723fb Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 21 Jul 2011 18:31:14 -0300 Subject: [media] az6007: Fix compilation troubles at az6007 Some changes are needed, in order to make az6007 compile with the upstream tree. Most of the changes are due to the upstream drxk module. Even allowing its compilation, the driver is not working yet. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/tuners/mt2063.c | 2 +- drivers/media/dvb/dvb-usb/az6007.c | 174 +++++++++++++++++++++-------------- 2 files changed, 104 insertions(+), 72 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/common/tuners/mt2063.c b/drivers/media/common/tuners/mt2063.c index c89af3cd5eba..7bbf25da3efe 100644 --- a/drivers/media/common/tuners/mt2063.c +++ b/drivers/media/common/tuners/mt2063.c @@ -350,7 +350,7 @@ static int MT2063_Sleep(struct dvb_frontend *fe) /* * ToDo: Add code here to implement a OS blocking */ - msleep(10); + msleep(100); return 0; } diff --git a/drivers/media/dvb/dvb-usb/az6007.c b/drivers/media/dvb/dvb-usb/az6007.c index cd5dd4cecd0b..5873759f5db4 100644 --- a/drivers/media/dvb/dvb-usb/az6007.c +++ b/drivers/media/dvb/dvb-usb/az6007.c @@ -8,6 +8,10 @@ #include "mt2063.h" #include "dvb_ca_en50221.h" +/* HACK: Should be moved to the right place */ +#define USB_PID_AZUREWAVE_6007 0xccd +#define USB_PID_TERRATEC_H7 0x10b4 + /* debug */ int dvb_usb_az6007_debug; module_param_named(debug,dvb_usb_az6007_debug, int, 0644); @@ -28,30 +32,39 @@ struct az6007_device_state { struct dvb_ca_en50221 ca; struct mutex ca_mutex; u8 power_state; -}; -struct drxk3913_config az6007_drxk3913_config_DVBT = { - .demod_address = 0x52, - .min_delay_ms = 100, - .standard = MTTUNEA_DVBT, - .set_tuner = mt2063_setTune, - .tuner_getlocked = mt2063_lockStatus, - .tuner_MT2063_Open = tuner_MT2063_Open, - .tuner_MT2063_SoftwareShutdown = tuner_MT2063_SoftwareShutdown, - .tuner_MT2063_ClearPowerMaskBits = tuner_MT2063_ClearPowerMaskBits, + /* Due to DRX-K - probably need changes */ + int (*gate_ctrl)(struct dvb_frontend *, int); + struct semaphore pll_mutex; + bool dont_attach_fe1; }; -struct drxk3913_config az6007_drxk3913_config_DVBC = { - .demod_address = 0x52, - .min_delay_ms = 100, - .standard = MTTUNEA_DVBC, - .set_tuner = mt2063_setTune, - .tuner_getlocked = mt2063_lockStatus, - .tuner_MT2063_Open = tuner_MT2063_Open, - .tuner_MT2063_SoftwareShutdown = tuner_MT2063_SoftwareShutdown, - .tuner_MT2063_ClearPowerMaskBits = tuner_MT2063_ClearPowerMaskBits, +struct drxk_config terratec_h7_drxk = { + .adr = 0x29, + .single_master = 1, + .no_i2c_bridge = 1, + .microcode_name = "dvb-usb-terratec-h5-drxk.fw", }; +static int drxk_gate_ctrl(struct dvb_frontend *fe, int enable) +{ + struct dvb_usb_adapter *adap = fe->sec_priv; + struct az6007_device_state *st = adap->priv; + int status; + + if (!adap || !st) + return -EINVAL; + + if (enable) { + down(&st->pll_mutex); + status = st->gate_ctrl(fe, 1); + } else { + status = st->gate_ctrl(fe, 0); + up(&st->pll_mutex); + } + return status; +} + struct mt2063_config az6007_mt2063_config = { .tuner_address = 0xc0, .refclock = 36125000, @@ -87,7 +100,7 @@ static int az6007_usb_out_op(struct dvb_usb_device *d, u8 req, u16 value, { int ret; -#if 0 +#if 0 int i=0, cyc=0, rem=0; cyc = blen/64; rem = blen%64; @@ -96,7 +109,7 @@ static int az6007_usb_out_op(struct dvb_usb_device *d, u8 req, u16 value, deb_xfer("out: req. %02x, val: %04x, ind: %04x, buffer: ",req,value,index); debug_dump(b,blen,deb_xfer); - + #if 0 if (blen>64) { @@ -110,7 +123,7 @@ static int az6007_usb_out_op(struct dvb_usb_device *d, u8 req, u16 value, 5000)) != 64) { warn("usb out operation failed. (%d)",ret); return -EIO; - } + } } if (rem>0) @@ -127,7 +140,7 @@ static int az6007_usb_out_op(struct dvb_usb_device *d, u8 req, u16 value, } } else -#endif +#endif { if ((ret = usb_control_msg(d->udev, usb_sndctrlpipe(d->udev,0), @@ -139,7 +152,7 @@ static int az6007_usb_out_op(struct dvb_usb_device *d, u8 req, u16 value, return -EIO; } } - + return 0; } @@ -149,9 +162,9 @@ static int az6007_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) } /* keys for the enclosed remote control */ -static struct dvb_usb_rc_key az6007_rc_keys[] = { - { 0x00, 0x01, KEY_1 }, - { 0x00, 0x02, KEY_2 }, +struct rc_map_table rc_map_az6007_table[] = { + { 0x0001, KEY_1 }, + { 0x0002, KEY_2 }, }; /* remote control stuff (does not work with my box) */ @@ -163,7 +176,7 @@ static int az6007_rc_query(struct dvb_usb_device *d, u32 *event, int *state) int i; /* remove the following return to enabled remote querying */ - + az6007_usb_in_op(d,READ_REMOTE_REQ,0,0,key,10); @@ -257,7 +270,7 @@ static int az6007_frontend_reset(struct dvb_usb_adapter *adap) int blen; info("az6007_frontend_reset adap=%p adap->dev=%p\n", adap, adap->dev); - + //reset demodulator req = 0xC0; value = 1;//high @@ -268,7 +281,7 @@ static int az6007_frontend_reset(struct dvb_usb_adapter *adap) err("az6007_frontend_reset failed 1 !!!"); return -EIO; } - + req = 0xC0; value = 0;//low index = 3; @@ -290,11 +303,11 @@ static int az6007_frontend_reset(struct dvb_usb_adapter *adap) err("az6007_frontend_reset failed 3 !!!"); return -EIO; } - + msleep_interruptible(200); - + info("reset az6007 frontend\n"); - + return 0; } @@ -350,38 +363,55 @@ static int az6007_frontend_tsbypass(struct dvb_usb_adapter *adap,int onoff) static int az6007_frontend_attach(struct dvb_usb_adapter *adap) { + struct az6007_device_state *st = adap->priv; + + int result; + az6007_frontend_poweron(adap); az6007_frontend_reset(adap); info("az6007_frontend_attach\n"); - if (az6007_type == 0) - { - info("az6007_drxk3913_config_DVBT\n"); - adap->fe = drxk3913_attach(&az6007_drxk3913_config_DVBT, &adap->dev->i2c_adap); + adap->fe = dvb_attach(drxk_attach, &terratec_h7_drxk, + &adap->dev->i2c_adap, &adap->fe2); + if (!adap->fe) { + result = -EINVAL; + goto out_free; } - else - { - info("az6007_drxk3913_config_DVBC\n"); - adap->fe = drxk3913_attach(&az6007_drxk3913_config_DVBC, &adap->dev->i2c_adap); - } - if (adap->fe) { - if (mt2063_attach(adap->fe, &az6007_mt2063_config, &adap->dev->i2c_adap)) { - info("found STB6100 DVB-C/DVB-T frontend @0x%02x\n",az6007_mt2063_config.tuner_address); - - //vp6027_ci_init(adap); - } else { - adap->fe = NULL; - } - } - else - { - adap->fe = NULL; - err("no front-end attached\n"); + + /* FIXME: do we need a pll semaphore? */ + adap->fe->sec_priv = adap; + sema_init(&st->pll_mutex, 1); + st->gate_ctrl = adap->fe->ops.i2c_gate_ctrl; + adap->fe->ops.i2c_gate_ctrl = drxk_gate_ctrl; + adap->fe2->id = 1; + + /* Attach mt2063 to DVB-C frontend */ + if (adap->fe->ops.i2c_gate_ctrl) + adap->fe->ops.i2c_gate_ctrl(adap->fe, 1); + if (!dvb_attach(mt2063_attach, adap->fe, &az6007_mt2063_config, + &adap->dev->i2c_adap)) { + result = -EINVAL; + + goto out_free; } - //az6007_frontend_tsbypass(adap,0); - + if (adap->fe->ops.i2c_gate_ctrl) + adap->fe->ops.i2c_gate_ctrl(adap->fe, 0); + + /* Hack - needed due to drxk */ + adap->fe2->tuner_priv = adap->fe->tuner_priv; + memcpy(&adap->fe2->ops.tuner_ops, + &adap->fe->ops.tuner_ops, + sizeof(adap->fe->ops.tuner_ops)); return 0; + +out_free: + if (adap->fe) + dvb_frontend_detach(adap->fe); + adap->fe = NULL; + adap->fe2 = NULL; + + return result; } static struct dvb_usb_device_properties az6007_properties; @@ -403,7 +433,7 @@ static int az6007_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num int length; u8 req; u8 data[512]; - + if (mutex_lock_interruptible(&d->i2c_mutex) < 0) return -EAGAIN; if (num > 2) @@ -442,7 +472,7 @@ static int az6007_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num //printk("Tuner Tuner ReadDATA len=%d ", len); for (j=0; j Date: Fri, 22 Jul 2011 10:31:25 -0300 Subject: [media] az6007: Fix it to allow loading it without crash Add some fixes to allow frontend attachment. The patch is not complete yet, as just the frontend 0 is initialized. So, more changes will be needed, including some changes at dvb-usb core. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/az6007.c | 190 +++++++++++++++++++------------------ 1 file changed, 98 insertions(+), 92 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/dvb-usb/az6007.c b/drivers/media/dvb/dvb-usb/az6007.c index 5873759f5db4..6a21f928550a 100644 --- a/drivers/media/dvb/dvb-usb/az6007.c +++ b/drivers/media/dvb/dvb-usb/az6007.c @@ -49,12 +49,20 @@ struct drxk_config terratec_h7_drxk = { static int drxk_gate_ctrl(struct dvb_frontend *fe, int enable) { struct dvb_usb_adapter *adap = fe->sec_priv; - struct az6007_device_state *st = adap->priv; + struct az6007_device_state *st; int status; - if (!adap || !st) + info("%s", __func__); + + if (!adap) + return -EINVAL; + + st = adap->priv; + + if (!st) return -EINVAL; + if (enable) { down(&st->pll_mutex); status = st->gate_ctrl(fe, 1); @@ -66,7 +74,7 @@ static int drxk_gate_ctrl(struct dvb_frontend *fe, int enable) } struct mt2063_config az6007_mt2063_config = { - .tuner_address = 0xc0, + .tuner_address = 0x60, .refclock = 36125000, }; @@ -84,10 +92,8 @@ int az6007_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 if (ret < 0) { warn("usb in operation failed. (%d)", ret); - ret = -EIO; - } else - ret = 0; - + return -EIO; + } deb_xfer("in: req. %02x, val: %04x, ind: %04x, buffer: ",req,value,index); debug_dump(b,blen,deb_xfer); @@ -219,7 +225,7 @@ static int az6007_frontend_poweron(struct dvb_usb_adapter *adap) u16 index; int blen; - info("az6007_frontend_poweron adap=%p adap->dev=%p\n", adap, adap->dev); + info("az6007_frontend_poweron adap=%p adap->dev=%p", adap, adap->dev); req = 0xBC; value = 1;//power on @@ -257,7 +263,8 @@ static int az6007_frontend_poweron(struct dvb_usb_adapter *adap) err("az6007_frontend_poweron failed!!!"); return -EIO; } - info("az6007_frontend_poweron\n"); + info("az6007_frontend_poweron: OK"); + return 0; } @@ -269,7 +276,7 @@ static int az6007_frontend_reset(struct dvb_usb_adapter *adap) u16 index; int blen; - info("az6007_frontend_reset adap=%p adap->dev=%p\n", adap, adap->dev); + info("az6007_frontend_reset adap=%p adap->dev=%p", adap, adap->dev); //reset demodulator req = 0xC0; @@ -306,7 +313,7 @@ static int az6007_frontend_reset(struct dvb_usb_adapter *adap) msleep_interruptible(200); - info("reset az6007 frontend\n"); + info("reset az6007 frontend"); return 0; } @@ -367,10 +374,12 @@ static int az6007_frontend_attach(struct dvb_usb_adapter *adap) int result; + BUG_ON(!st); + az6007_frontend_poweron(adap); az6007_frontend_reset(adap); - info("az6007_frontend_attach\n"); + info("az6007_frontend_attach: drxk"); adap->fe = dvb_attach(drxk_attach, &terratec_h7_drxk, &adap->dev->i2c_adap, &adap->fe2); @@ -379,6 +388,8 @@ static int az6007_frontend_attach(struct dvb_usb_adapter *adap) goto out_free; } + info("Setting hacks"); + /* FIXME: do we need a pll semaphore? */ adap->fe->sec_priv = adap; sema_init(&st->pll_mutex, 1); @@ -386,6 +397,7 @@ static int az6007_frontend_attach(struct dvb_usb_adapter *adap) adap->fe->ops.i2c_gate_ctrl = drxk_gate_ctrl; adap->fe2->id = 1; + info("az6007_frontend_attach: mt2063"); /* Attach mt2063 to DVB-C frontend */ if (adap->fe->ops.i2c_gate_ctrl) adap->fe->ops.i2c_gate_ctrl(adap->fe, 1); @@ -423,100 +435,95 @@ az6007_usb_disconnect(struct usb_interface *intf) } /* I2C */ -static int az6007_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num) +static int az6007_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msgs[],int num) { struct dvb_usb_device *d = i2c_get_adapdata(adap); - int j=0,len=0; - int ret=0; + int i, j, len; + int ret = 0; u16 index; u16 value; int length; - u8 req; + u8 req, addr; u8 data[512]; if (mutex_lock_interruptible(&d->i2c_mutex) < 0) return -EAGAIN; - if (num > 2) - warn("more than 2 i2c messages at a time is not handled yet. TODO."); - - if (msg[0].addr == 0xc0) //MT2063 - { - if (msg[0].flags != I2C_M_RD) //write - { - //printk("Tuner Tuner Write DevAddr=%02x RegAddr=%d\n", msg[0].addr, msg[0].buf[0]); - req = 0xBD; - index = msg[0].buf[0]; - value = msg[0].addr | (1<<8); - length = msg[0].len - 1; - len = msg[0].len - 1; - //printk("Tuner Tuner WriteDATA len=%d ", len); - for(j=0;j= len) { + for (j = 0; j < len; j++) { + msgs[i + 1].buf[j] = data[j + 5]; + printk("0x%02x ", msgs[i + 1].buf[j]); + } + } else + ret = -EIO; + i++; + } else if (!(msgs[i].flags & I2C_M_RD)) { + /* write bytes */ +// printk("az6007 I2C xfer write addr=0x%x len=%d: ", +// addr, msgs[i].len); + req = 0xbd; + index = msgs[i].buf[0]; + value = addr | (1 << 8); + length = msgs[i].len - 1; + len = msgs[i].len - 1; +// printk("(0x%02x) ", msgs[i].buf[0]); + for (j = 0; j < len; j++) { - data[j] = msg[0].buf[j+1]; - //printk("data[%d]=%02x ", j, data[j]); + data[j] = msgs[i].buf[j + 1]; +// printk("0x%02x ", data[j]); } - //printk("\n"); ret = az6007_usb_out_op(d,req,value,index,data,length); - } - else //read - { - //printk("Demodulator Read DevAddr=%02x RegAddr=%02x\n", msg[0].addr, msg[0].buf[0]); - req = 0xB9; - index = 0; - value = msg[0].addr + (0 << 8); - length = msg[0].len + 6; + } else { + /* read bytes */ +// printk("az6007 I2C xfer read addr=0x%x len=%d: ", +// addr, msgs[i].len); + req = 0xb9; + index = msgs[i].buf[0]; + value = addr; + length = msgs[i].len + 6; + len = msgs[i].len; ret = az6007_usb_in_op(d,req,value,index,data,length); - len = msg[0].len; - //printk("Demodulator ReadDATA len=%d ", len); - for (j=0; ji2c_mutex); - return ret; + + if (ret < 0) { + info("%s ERROR: %i\n", __func__, ret); + return ret; + } + return num; } @@ -540,11 +547,11 @@ int az6007_identify_state(struct usb_device *udev, struct dvb_usb_device_propert s16 ret = usb_control_msg(udev, usb_rcvctrlpipe(udev,0), 0xb7, USB_TYPE_VENDOR | USB_DIR_IN, 6, 0, b, 6, USB_CTRL_GET_TIMEOUT); - info("FW GET_VERSION length: %d\n",ret); + info("FW GET_VERSION length: %d",ret); *cold = ret <= 0; - info("cold: %d\n", *cold); + info("cold: %d", *cold); return 0; } @@ -572,7 +579,6 @@ static struct dvb_usb_device_properties az6007_properties = { .firmware = "dvb-usb-az6007-03.fw", .no_reconnect = 1, - .size_of_priv = sizeof(struct az6007_device_state), .identify_state = az6007_identify_state, .num_adapters = 1, .adapter = { @@ -593,7 +599,7 @@ static struct dvb_usb_device_properties az6007_properties = { } } }, - .size_of_priv = 0,//sizeof(struct az6007_state), + .size_of_priv = sizeof(struct az6007_device_state), } }, //.power_ctrl = az6007_power_ctrl, @@ -634,7 +640,7 @@ static struct usb_driver az6007_usb_driver = { static int __init az6007_usb_module_init(void) { int result; - info("henry :: az6007 usb module init"); + info("az6007 usb module init"); if ((result = usb_register(&az6007_usb_driver))) { err("usb_register failed. (%d)",result); return result; @@ -646,7 +652,7 @@ static int __init az6007_usb_module_init(void) static void __exit az6007_usb_module_exit(void) { /* deregister this driver from the USB subsystem */ - info("henry :: az6007 usb module exit"); + info("az6007 usb module exit"); usb_deregister(&az6007_usb_driver); } -- cgit v1.2.3 From d20a7f7277785e6f7fbe02eb469f7a99a9f058a4 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 23 Jul 2011 09:51:12 -0300 Subject: [media] az6007: Fix the I2C code in order to handle mt2063 mt2063 uses a one-byte transfer. This requires a special handling inside the i2c code. Fix it to properly accept i2c reads. This is needed to make the mt2063 to be detected. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/az6007.c | 47 ++++++++++++++++++++++++-------------- 1 file changed, 30 insertions(+), 17 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/dvb-usb/az6007.c b/drivers/media/dvb/dvb-usb/az6007.c index 6a21f928550a..56126d41a604 100644 --- a/drivers/media/dvb/dvb-usb/az6007.c +++ b/drivers/media/dvb/dvb-usb/az6007.c @@ -42,7 +42,7 @@ struct az6007_device_state { struct drxk_config terratec_h7_drxk = { .adr = 0x29, .single_master = 1, - .no_i2c_bridge = 1, + .no_i2c_bridge = 0, .microcode_name = "dvb-usb-terratec-h5-drxk.fw", }; @@ -451,7 +451,6 @@ static int az6007_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msgs[],int nu 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) @@ -462,44 +461,55 @@ static int az6007_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msgs[],int nu * the first xfer has just 1 byte length. * Need to join both into one operation */ - printk("az6007 I2C xfer write+read addr=0x%x len=%d/%d: ", - addr, msgs[i].len, msgs[i + 1].len); + if (dvb_usb_az6007_debug & 2) + printk(KERN_DEBUG + "az6007 I2C xfer write+read addr=0x%x len=%d/%d: ", + addr, msgs[i].len, msgs[i + 1].len); req = 0xb9; - index = 0; - value = addr; - for (j = 0; j < msgs[i].len; j++) - data[j] = msgs[i].buf[j]; + index = msgs[i].buf[0]; + value = addr | (1 << 8); length = 6 + msgs[i + 1].len; len = msgs[i + 1].len; ret = az6007_usb_in_op(d,req,value,index,data,length); if (ret >= len) { for (j = 0; j < len; j++) { msgs[i + 1].buf[j] = data[j + 5]; - printk("0x%02x ", msgs[i + 1].buf[j]); + if (dvb_usb_az6007_debug & 2) + printk(KERN_CONT + "0x%02x ", + msgs[i + 1].buf[j]); } } else ret = -EIO; i++; } else if (!(msgs[i].flags & I2C_M_RD)) { /* write bytes */ -// printk("az6007 I2C xfer write addr=0x%x len=%d: ", -// addr, msgs[i].len); + if (dvb_usb_az6007_debug & 2) + printk(KERN_DEBUG + "az6007 I2C xfer write addr=0x%x len=%d: ", + addr, msgs[i].len); req = 0xbd; index = msgs[i].buf[0]; value = addr | (1 << 8); length = msgs[i].len - 1; len = msgs[i].len - 1; -// printk("(0x%02x) ", msgs[i].buf[0]); + if (dvb_usb_az6007_debug & 2) + printk(KERN_CONT + "(0x%02x) ", msgs[i].buf[0]); for (j = 0; j < len; j++) { data[j] = msgs[i].buf[j + 1]; -// printk("0x%02x ", data[j]); + if (dvb_usb_az6007_debug & 2) + printk(KERN_CONT + "0x%02x ", data[j]); } ret = az6007_usb_out_op(d,req,value,index,data,length); } else { /* read bytes */ -// printk("az6007 I2C xfer read addr=0x%x len=%d: ", -// addr, msgs[i].len); + if (dvb_usb_az6007_debug & 2) + printk(KERN_DEBUG + "az6007 I2C xfer read addr=0x%x len=%d: ", + addr, msgs[i].len); req = 0xb9; index = msgs[i].buf[0]; value = addr; @@ -509,10 +519,13 @@ static int az6007_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msgs[],int nu for (j = 0; j < len; j++) { msgs[i].buf[j] = data[j + 5]; -// printk("0x%02x ", data[j + 5]); + if (dvb_usb_az6007_debug & 2) + printk(KERN_CONT + "0x%02x ", data[j + 5]); } } -// printk("\n"); + if (dvb_usb_az6007_debug & 2) + printk(KERN_CONT "\n"); if (ret < 0) goto err; } -- cgit v1.2.3 From 2212501ffad7fee1c2fcf9d6d55a24b489da18ad Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 23 Jul 2011 09:58:38 -0300 Subject: [media] az6007: Comment the gate_ctl mutex The mutex is there to protect the I2C gate. However, for some reason, it is being called twice: [ 2103.542796] usbcore: registered new interface driver dvb_usb_az6007 [ 2103.772392] az6007: drxk_gate_ctrl: enable [ 2103.793900] az6007: drxk_gate_ctrl: enable For now, let's just comment, to allow the driver to run. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/az6007.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/dvb-usb/az6007.c b/drivers/media/dvb/dvb-usb/az6007.c index 56126d41a604..ed376b8292ce 100644 --- a/drivers/media/dvb/dvb-usb/az6007.c +++ b/drivers/media/dvb/dvb-usb/az6007.c @@ -52,7 +52,7 @@ static int drxk_gate_ctrl(struct dvb_frontend *fe, int enable) struct az6007_device_state *st; int status; - info("%s", __func__); + info("%s: %s", __func__, enable? "enable" : "disable" ); if (!adap) return -EINVAL; @@ -64,10 +64,14 @@ static int drxk_gate_ctrl(struct dvb_frontend *fe, int enable) if (enable) { +#if 0 down(&st->pll_mutex); +#endif status = st->gate_ctrl(fe, 1); } else { +#if 0 status = st->gate_ctrl(fe, 0); +#endif up(&st->pll_mutex); } return status; -- cgit v1.2.3 From 357535800d98174ceddc6ad1f3092f1dce0ea04c Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 23 Jul 2011 10:12:12 -0300 Subject: [media] az6007: Remove some dead code that doesn't seem to be needed Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/az6007.c | 79 ++++++++------------------------------ 1 file changed, 16 insertions(+), 63 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/dvb-usb/az6007.c b/drivers/media/dvb/dvb-usb/az6007.c index ed376b8292ce..1fc174b86a77 100644 --- a/drivers/media/dvb/dvb-usb/az6007.c +++ b/drivers/media/dvb/dvb-usb/az6007.c @@ -17,17 +17,8 @@ int dvb_usb_az6007_debug; module_param_named(debug,dvb_usb_az6007_debug, int, 0644); MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2,rc=4 (or-able))." DVB_USB_DEBUG_STATUS); - -static int az6007_type =0; -module_param(az6007_type, int, 0644); -MODULE_PARM_DESC(az6007_type, "select delivery mode (0=DVB-T, 1=DVB-T"); - -//module_param_named(type, 6007_type, int, 0644); -//MODULE_PARM_DESC(type, "select delivery mode (0=DVB-T, 1=DVB-C)"); - DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); - struct az6007_device_state { struct dvb_ca_en50221 ca; struct mutex ca_mutex; @@ -110,57 +101,22 @@ static int az6007_usb_out_op(struct dvb_usb_device *d, u8 req, u16 value, { int ret; -#if 0 - int i=0, cyc=0, rem=0; - cyc = blen/64; - rem = blen%64; -#endif - deb_xfer("out: req. %02x, val: %04x, ind: %04x, buffer: ",req,value,index); debug_dump(b,blen,deb_xfer); - -#if 0 - if (blen>64) - { - for (i=0; iudev, - usb_sndctrlpipe(d->udev,0), - req, - USB_TYPE_VENDOR | USB_DIR_OUT, - value,index+i*64,b+i*64,64, - 5000)) != 64) { - warn("usb out operation failed. (%d)",ret); - return -EIO; - } - } - - if (rem>0) - { - if ((ret = usb_control_msg(d->udev, - usb_sndctrlpipe(d->udev,0), - req, - USB_TYPE_VENDOR | USB_DIR_OUT, - value,index+cyc*64,b+cyc*64,rem, - 5000)) != rem) { - warn("usb out operation failed. (%d)",ret); - return -EIO; - } - } + if (blen > 64) { + printk(KERN_ERR "az6007: doesn't suport I2C transactions longer than 64 bytes\n"); + return -EOPNOTSUPP; } - else -#endif - { - if ((ret = usb_control_msg(d->udev, - usb_sndctrlpipe(d->udev,0), - req, - USB_TYPE_VENDOR | USB_DIR_OUT, - value,index,b,blen, - 5000)) != blen) { - warn("usb out operation failed. (%d)",ret); - return -EIO; - } + + if ((ret = usb_control_msg(d->udev, + usb_sndctrlpipe(d->udev,0), + req, + USB_TYPE_VENDOR | USB_DIR_OUT, + value,index,b,blen, + 5000)) != blen) { + warn("usb out operation failed. (%d)",ret); + return -EIO; } return 0; @@ -232,7 +188,7 @@ static int az6007_frontend_poweron(struct dvb_usb_adapter *adap) info("az6007_frontend_poweron adap=%p adap->dev=%p", adap, adap->dev); req = 0xBC; - value = 1;//power on + value = 1; /* power on */ index = 3; blen =0; @@ -245,7 +201,7 @@ static int az6007_frontend_poweron(struct dvb_usb_adapter *adap) msleep_interruptible(200); req = 0xBC; - value = 0;//power on + value = 0; /* power off */ index = 3; blen =0; @@ -258,7 +214,7 @@ static int az6007_frontend_poweron(struct dvb_usb_adapter *adap) msleep_interruptible(200); req = 0xBC; - value = 1;//power on + value = 1; /* power on */ index = 3; blen =0; @@ -552,9 +508,6 @@ static u32 az6007_i2c_func(struct i2c_adapter *adapter) static struct i2c_algorithm az6007_i2c_algo = { .master_xfer = az6007_i2c_xfer, .functionality = az6007_i2c_func, -#ifdef NEED_ALGO_CONTROL - .algo_control = dummy_algo_control, -#endif }; int az6007_identify_state(struct usb_device *udev, struct dvb_usb_device_properties *props, @@ -678,5 +631,5 @@ module_exit(az6007_usb_module_exit); MODULE_AUTHOR("Henry Wang "); MODULE_DESCRIPTION("Driver for AzureWave 6007 DVB-C/T USB2.0 and clones"); -MODULE_VERSION("1.0"); +MODULE_VERSION("1.1"); MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 93b32126f94333afd012daf5b48b594b86ae8128 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 23 Jul 2011 10:40:08 -0300 Subject: [media] az6007: CodingStyle cleanup make checkpatch.pl happy Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/az6007.c | 239 +++++++++++++++++++------------------ 1 file changed, 120 insertions(+), 119 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/dvb-usb/az6007.c b/drivers/media/dvb/dvb-usb/az6007.c index 1fc174b86a77..a709cec16b00 100644 --- a/drivers/media/dvb/dvb-usb/az6007.c +++ b/drivers/media/dvb/dvb-usb/az6007.c @@ -14,23 +14,24 @@ /* debug */ int dvb_usb_az6007_debug; -module_param_named(debug,dvb_usb_az6007_debug, int, 0644); -MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2,rc=4 (or-able))." DVB_USB_DEBUG_STATUS); +module_param_named(debug, dvb_usb_az6007_debug, int, 0644); +MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2,rc=4 (or-able))." + DVB_USB_DEBUG_STATUS); DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); struct az6007_device_state { - struct dvb_ca_en50221 ca; - struct mutex ca_mutex; - u8 power_state; + struct dvb_ca_en50221 ca; + struct mutex ca_mutex; + u8 power_state; /* Due to DRX-K - probably need changes */ - int (*gate_ctrl)(struct dvb_frontend *, int); - struct semaphore pll_mutex; + int (*gate_ctrl) (struct dvb_frontend *, int); + struct semaphore pll_mutex; bool dont_attach_fe1; }; -struct drxk_config terratec_h7_drxk = { +static struct drxk_config terratec_h7_drxk = { .adr = 0x29, .single_master = 1, .no_i2c_bridge = 0, @@ -43,7 +44,7 @@ static int drxk_gate_ctrl(struct dvb_frontend *fe, int enable) struct az6007_device_state *st; int status; - info("%s: %s", __func__, enable? "enable" : "disable" ); + info("%s: %s", __func__, enable ? "enable" : "disable"); if (!adap) return -EINVAL; @@ -53,7 +54,6 @@ static int drxk_gate_ctrl(struct dvb_frontend *fe, int enable) if (!st) return -EINVAL; - if (enable) { #if 0 down(&st->pll_mutex); @@ -68,30 +68,31 @@ static int drxk_gate_ctrl(struct dvb_frontend *fe, int enable) return status; } -struct mt2063_config az6007_mt2063_config = { +static struct mt2063_config az6007_mt2063_config = { .tuner_address = 0x60, .refclock = 36125000, }; /* check for mutex FIXME */ -int az6007_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen) +static int az6007_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, + u16 index, u8 *b, int blen) { int ret = -1; - ret = usb_control_msg(d->udev, - usb_rcvctrlpipe(d->udev,0), - req, - USB_TYPE_VENDOR | USB_DIR_IN, - value,index,b,blen, - 5000); + ret = usb_control_msg(d->udev, + usb_rcvctrlpipe(d->udev, 0), + req, + USB_TYPE_VENDOR | USB_DIR_IN, + value, index, b, blen, 5000); if (ret < 0) { warn("usb in operation failed. (%d)", ret); return -EIO; } - deb_xfer("in: req. %02x, val: %04x, ind: %04x, buffer: ",req,value,index); - debug_dump(b,blen,deb_xfer); + deb_xfer("in: req. %02x, val: %04x, ind: %04x, buffer: ", req, value, + index); + debug_dump(b, blen, deb_xfer); return ret; } @@ -101,21 +102,23 @@ static int az6007_usb_out_op(struct dvb_usb_device *d, u8 req, u16 value, { int ret; - deb_xfer("out: req. %02x, val: %04x, ind: %04x, buffer: ",req,value,index); - debug_dump(b,blen,deb_xfer); + deb_xfer("out: req. %02x, val: %04x, ind: %04x, buffer: ", req, value, + index); + debug_dump(b, blen, deb_xfer); if (blen > 64) { - printk(KERN_ERR "az6007: doesn't suport I2C transactions longer than 64 bytes\n"); + printk(KERN_ERR + "az6007: doesn't suport I2C transactions longer than 64 bytes\n"); return -EOPNOTSUPP; } - if ((ret = usb_control_msg(d->udev, - usb_sndctrlpipe(d->udev,0), - req, - USB_TYPE_VENDOR | USB_DIR_OUT, - value,index,b,blen, - 5000)) != blen) { - warn("usb out operation failed. (%d)",ret); + ret = usb_control_msg(d->udev, + usb_sndctrlpipe(d->udev, 0), + req, + USB_TYPE_VENDOR | USB_DIR_OUT, + value, index, b, blen, 5000); + if (ret != blen) { + warn("usb out operation failed. (%d)", ret); return -EIO; } @@ -128,25 +131,24 @@ static int az6007_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) } /* keys for the enclosed remote control */ -struct rc_map_table rc_map_az6007_table[] = { - { 0x0001, KEY_1 }, - { 0x0002, KEY_2 }, +static struct rc_map_table rc_map_az6007_table[] = { + {0x0001, KEY_1}, + {0x0002, KEY_2}, }; /* remote control stuff (does not work with my box) */ -static int az6007_rc_query(struct dvb_usb_device *d, u32 *event, int *state) +static int az6007_rc_query(struct dvb_usb_device *d, u32 * event, int *state) { return 0; #if 0 u8 key[10]; int i; -/* remove the following return to enabled remote querying */ - + /* remove the following return to enabled remote querying */ - az6007_usb_in_op(d,READ_REMOTE_REQ,0,0,key,10); + az6007_usb_in_op(d, READ_REMOTE_REQ, 0, 0, key, 10); - deb_rc("remote query key: %x %d\n",key[1],key[1]); + deb_rc("remote query key: %x %d\n", key[1], key[1]); if (key[1] == 0x44) { *state = REMOTE_NO_KEY_PRESSED; @@ -171,7 +173,7 @@ int az6007_power_ctrl(struct dvb_usb_device *d, int onoff) } */ -static int az6007_read_mac_addr(struct dvb_usb_device *d,u8 mac[6]) +static int az6007_read_mac_addr(struct dvb_usb_device *d, u8 mac[6]) { az6007_usb_in_op(d, 0xb7, 6, 0, &mac[0], 6); return 0; @@ -190,12 +192,12 @@ static int az6007_frontend_poweron(struct dvb_usb_adapter *adap) req = 0xBC; value = 1; /* power on */ index = 3; - blen =0; + blen = 0; - if((ret = az6007_usb_out_op(adap->dev,req,value,index,NULL,blen)) != 0) - { + ret = az6007_usb_out_op(adap->dev, req, value, index, NULL, blen); + if (ret != 0) { err("az6007_frontend_poweron failed!!!"); - return -EIO; + return -EIO; } msleep_interruptible(200); @@ -203,12 +205,12 @@ static int az6007_frontend_poweron(struct dvb_usb_adapter *adap) req = 0xBC; value = 0; /* power off */ index = 3; - blen =0; + blen = 0; - if((ret = az6007_usb_out_op(adap->dev,req,value,index,NULL,blen)) != 0) - { + ret = az6007_usb_out_op(adap->dev, req, value, index, NULL, blen); + if (ret != 0) { err("az6007_frontend_poweron failed!!!"); - return -EIO; + return -EIO; } msleep_interruptible(200); @@ -216,12 +218,12 @@ static int az6007_frontend_poweron(struct dvb_usb_adapter *adap) req = 0xBC; value = 1; /* power on */ index = 3; - blen =0; + blen = 0; - if((ret = az6007_usb_out_op(adap->dev,req,value,index,NULL,blen)) != 0) - { + ret = az6007_usb_out_op(adap->dev, req, value, index, NULL, blen); + if (ret != 0) { err("az6007_frontend_poweron failed!!!"); - return -EIO; + return -EIO; } info("az6007_frontend_poweron: OK"); @@ -238,37 +240,37 @@ static int az6007_frontend_reset(struct dvb_usb_adapter *adap) info("az6007_frontend_reset adap=%p adap->dev=%p", adap, adap->dev); - //reset demodulator + /* reset demodulator */ req = 0xC0; - value = 1;//high + value = 1; /* high */ index = 3; - blen =0; - if((ret = az6007_usb_out_op(adap->dev,req,value,index,NULL,blen)) != 0) - { + blen = 0; + ret = az6007_usb_out_op(adap->dev, req, value, index, NULL, blen); + if (ret != 0) { err("az6007_frontend_reset failed 1 !!!"); - return -EIO; + return -EIO; } req = 0xC0; - value = 0;//low + value = 0; /* low */ index = 3; - blen =0; + blen = 0; msleep_interruptible(200); - if((ret = az6007_usb_out_op(adap->dev,req,value,index,NULL,blen)) != 0) - { + ret = az6007_usb_out_op(adap->dev, req, value, index, NULL, blen); + if (ret != 0) { err("az6007_frontend_reset failed 2 !!!"); - return -EIO; + return -EIO; } msleep_interruptible(200); req = 0xC0; - value = 1;//high + value = 1; /* high */ index = 3; - blen =0; + blen = 0; - if((ret = az6007_usb_out_op(adap->dev,req,value,index,NULL,blen)) != 0) - { + ret = az6007_usb_out_op(adap->dev, req, value, index, NULL, blen); + if (ret != 0) { err("az6007_frontend_reset failed 3 !!!"); - return -EIO; + return -EIO; } msleep_interruptible(200); @@ -285,18 +287,17 @@ static int az6007_led_on_off(struct usb_interface *intf, int onoff) u16 value; u16 index; int blen; - //TS through + /* TS through */ req = 0xBC; value = onoff; index = 0; - blen =0; + blen = 0; ret = usb_control_msg(interface_to_usbdev(intf), - usb_rcvctrlpipe(interface_to_usbdev(intf),0), - req, - USB_TYPE_VENDOR | USB_DIR_OUT, - value,index,NULL,blen, - 2000); + usb_rcvctrlpipe(interface_to_usbdev(intf), 0), + req, + USB_TYPE_VENDOR | USB_DIR_OUT, + value, index, NULL, blen, 2000); if (ret < 0) { warn("usb in operation failed. (%d)", ret); @@ -304,27 +305,28 @@ static int az6007_led_on_off(struct usb_interface *intf, int onoff) } else ret = 0; - - deb_xfer("in: req. %02x, val: %04x, ind: %04x, buffer: ",req,value,index); + deb_xfer("in: req. %02x, val: %04x, ind: %04x, buffer: ", req, value, + index); return ret; } -static int az6007_frontend_tsbypass(struct dvb_usb_adapter *adap,int onoff) +static int az6007_frontend_tsbypass(struct dvb_usb_adapter *adap, int onoff) { int ret; u8 req; u16 value; u16 index; int blen; - //TS through + /* TS through */ req = 0xC7; value = onoff; index = 0; - blen =0; + blen = 0; - if((ret = az6007_usb_out_op(adap->dev,req,value,index,NULL,blen)) != 0) - return -EIO; + ret = az6007_usb_out_op(adap->dev, req, value, index, NULL, blen); + if (ret != 0) + return -EIO; return 0; } @@ -373,8 +375,7 @@ static int az6007_frontend_attach(struct dvb_usb_adapter *adap) /* Hack - needed due to drxk */ adap->fe2->tuner_priv = adap->fe->tuner_priv; memcpy(&adap->fe2->ops.tuner_ops, - &adap->fe->ops.tuner_ops, - sizeof(adap->fe->ops.tuner_ops)); + &adap->fe->ops.tuner_ops, sizeof(adap->fe->ops.tuner_ops)); return 0; out_free: @@ -388,14 +389,14 @@ out_free: static struct dvb_usb_device_properties az6007_properties; -static void -az6007_usb_disconnect(struct usb_interface *intf) +static void az6007_usb_disconnect(struct usb_interface *intf) { - dvb_usb_device_exit (intf); + dvb_usb_device_exit(intf); } /* I2C */ -static int az6007_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msgs[],int num) +static int az6007_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], + int num) { struct dvb_usb_device *d = i2c_get_adapdata(adap); int i, j, len; @@ -430,7 +431,8 @@ static int az6007_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msgs[],int nu value = addr | (1 << 8); length = 6 + msgs[i + 1].len; len = msgs[i + 1].len; - ret = az6007_usb_in_op(d,req,value,index,data,length); + ret = az6007_usb_in_op(d, req, value, index, data, + length); if (ret >= len) { for (j = 0; j < len; j++) { msgs[i + 1].buf[j] = data[j + 5]; @@ -454,16 +456,14 @@ static int az6007_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msgs[],int nu length = msgs[i].len - 1; len = msgs[i].len - 1; if (dvb_usb_az6007_debug & 2) - printk(KERN_CONT - "(0x%02x) ", msgs[i].buf[0]); - for (j = 0; j < len; j++) - { + printk(KERN_CONT "(0x%02x) ", msgs[i].buf[0]); + for (j = 0; j < len; j++) { data[j] = msgs[i].buf[j + 1]; if (dvb_usb_az6007_debug & 2) - printk(KERN_CONT - "0x%02x ", data[j]); + printk(KERN_CONT "0x%02x ", data[j]); } - ret = az6007_usb_out_op(d,req,value,index,data,length); + ret = az6007_usb_out_op(d, req, value, index, data, + length); } else { /* read bytes */ if (dvb_usb_az6007_debug & 2) @@ -475,9 +475,9 @@ static int az6007_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msgs[],int nu value = addr; length = msgs[i].len + 6; len = msgs[i].len; - ret = az6007_usb_in_op(d,req,value,index,data,length); - for (j = 0; j < len; j++) - { + ret = az6007_usb_in_op(d, req, value, index, data, + length); + for (j = 0; j < len; j++) { msgs[i].buf[j] = data[j + 5]; if (dvb_usb_az6007_debug & 2) printk(KERN_CONT @@ -499,25 +499,26 @@ err: return num; } - static u32 az6007_i2c_func(struct i2c_adapter *adapter) { return I2C_FUNC_I2C; } static struct i2c_algorithm az6007_i2c_algo = { - .master_xfer = az6007_i2c_xfer, + .master_xfer = az6007_i2c_xfer, .functionality = az6007_i2c_func, }; -int az6007_identify_state(struct usb_device *udev, struct dvb_usb_device_properties *props, - struct dvb_usb_device_description **desc, int *cold) +int az6007_identify_state(struct usb_device *udev, + struct dvb_usb_device_properties *props, + struct dvb_usb_device_description **desc, int *cold) { u8 b[16]; - s16 ret = usb_control_msg(udev, usb_rcvctrlpipe(udev,0), - 0xb7, USB_TYPE_VENDOR | USB_DIR_IN, 6, 0, b, 6, USB_CTRL_GET_TIMEOUT); + s16 ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), + 0xb7, USB_TYPE_VENDOR | USB_DIR_IN, 6, 0, b, + 6, USB_CTRL_GET_TIMEOUT); - info("FW GET_VERSION length: %d",ret); + info("FW GET_VERSION length: %d", ret); *cold = ret <= 0; @@ -526,7 +527,7 @@ int az6007_identify_state(struct usb_device *udev, struct dvb_usb_device_propert } static int az6007_usb_probe(struct usb_interface *intf, - const struct usb_device_id *id) + const struct usb_device_id *id) { az6007_led_on_off(intf, 0); @@ -534,10 +535,10 @@ static int az6007_usb_probe(struct usb_interface *intf, THIS_MODULE, NULL, adapter_nr); } -static struct usb_device_id az6007_usb_table [] = { - { USB_DEVICE(USB_VID_AZUREWAVE, USB_PID_AZUREWAVE_6007) }, - { USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_H7) }, - { 0 }, +static struct usb_device_id az6007_usb_table[] = { + {USB_DEVICE(USB_VID_AZUREWAVE, USB_PID_AZUREWAVE_6007)}, + {USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_H7)}, + {0}, }; MODULE_DEVICE_TABLE(usb, az6007_usb_table); @@ -545,7 +546,6 @@ MODULE_DEVICE_TABLE(usb, az6007_usb_table); static struct dvb_usb_device_properties az6007_properties = { .caps = DVB_USB_IS_AN_I2C_ADAPTER, .usb_ctrl = CYPRESS_FX2, - //.download_firmware = az6007_download_firmware, .firmware = "dvb-usb-az6007-03.fw", .no_reconnect = 1, @@ -553,8 +553,7 @@ static struct dvb_usb_device_properties az6007_properties = { .num_adapters = 1, .adapter = { { - //.caps = DVB_USB_ADAP_RECEIVES_204_BYTE_TS, - + /* .caps = DVB_USB_ADAP_RECEIVES_204_BYTE_TS, */ .streaming_ctrl = az6007_streaming_ctrl, .frontend_attach = az6007_frontend_attach, @@ -572,7 +571,7 @@ static struct dvb_usb_device_properties az6007_properties = { .size_of_priv = sizeof(struct az6007_device_state), } }, - //.power_ctrl = az6007_power_ctrl, + /* .power_ctrl = az6007_power_ctrl, */ .read_mac_address = az6007_read_mac_addr, .rc.legacy = { @@ -600,10 +599,10 @@ static struct dvb_usb_device_properties az6007_properties = { /* usb specific object needed to register this driver with the usb subsystem */ static struct usb_driver az6007_usb_driver = { .name = "dvb_usb_az6007", - .probe = az6007_usb_probe, + .probe = az6007_usb_probe, .disconnect = dvb_usb_device_exit, - //.disconnect = az6007_usb_disconnect, - .id_table = az6007_usb_table, + /* .disconnect = az6007_usb_disconnect, */ + .id_table = az6007_usb_table, }; /* module stuff */ @@ -611,8 +610,10 @@ static int __init az6007_usb_module_init(void) { int result; info("az6007 usb module init"); - if ((result = usb_register(&az6007_usb_driver))) { - err("usb_register failed. (%d)",result); + + result = usb_register(&az6007_usb_driver); + if (result) { + err("usb_register failed. (%d)", result); return result; } -- cgit v1.2.3 From 70fa444d81b4fea992c2899467d5c4939a35100c Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 23 Jul 2011 10:55:10 -0300 Subject: [media] az6007: Get rid of az6007.h The header file serves for no purpose and exports some things that should be static. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/az6007.c | 11 +++++++++-- drivers/media/dvb/dvb-usb/az6007.h | 18 ------------------ 2 files changed, 9 insertions(+), 20 deletions(-) delete mode 100644 drivers/media/dvb/dvb-usb/az6007.h (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/dvb-usb/az6007.c b/drivers/media/dvb/dvb-usb/az6007.c index a709cec16b00..1791cb088629 100644 --- a/drivers/media/dvb/dvb-usb/az6007.c +++ b/drivers/media/dvb/dvb-usb/az6007.c @@ -3,13 +3,15 @@ * see Documentation/dvb/README.dvb-usb for more information */ -#include "az6007.h" #include "drxk.h" #include "mt2063.h" #include "dvb_ca_en50221.h" +#include "dvb-usb.h" + +#define DVB_USB_LOG_PREFIX "az6007" /* HACK: Should be moved to the right place */ -#define USB_PID_AZUREWAVE_6007 0xccd +#define USB_PID_AZUREWAVE_6007 0x0ccd #define USB_PID_TERRATEC_H7 0x10b4 /* debug */ @@ -18,6 +20,11 @@ module_param_named(debug, dvb_usb_az6007_debug, int, 0644); MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2,rc=4 (or-able))." DVB_USB_DEBUG_STATUS); +#define deb_info(args...) dprintk(dvb_usb_az6007_debug, 0x01, args) +#define deb_xfer(args...) dprintk(dvb_usb_az6007_debug, 0x02, args) +#define deb_rc(args...) dprintk(dvb_usb_az6007_debug, 0x04, args) +#define deb_fe(args...) dprintk(dvb_usb_az6007_debug, 0x08, args) + DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); struct az6007_device_state { diff --git a/drivers/media/dvb/dvb-usb/az6007.h b/drivers/media/dvb/dvb-usb/az6007.h deleted file mode 100644 index aefa5b506ee6..000000000000 --- a/drivers/media/dvb/dvb-usb/az6007.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef _DVB_USB_AZ6007_H_ -#define _DVB_USB_AZ6007_H_ - -#define DVB_USB_LOG_PREFIX "az6007" -#include "dvb-usb.h" - - -extern int dvb_usb_az6007_debug; -#define deb_info(args...) dprintk(dvb_usb_az6007_debug,0x01,args) -#define deb_xfer(args...) dprintk(dvb_usb_az6007_debug,0x02,args) -#define deb_rc(args...) dprintk(dvb_usb_az6007_debug,0x04,args) -#define deb_fe(args...) dprintk(dvb_usb_az6007_debug,0x08,args) - - -extern int vp702x_usb_out_op(struct dvb_usb_device *d, u8 *o, int olen, u8 *i, int ilen, int msec); -extern int vp702x_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen); - -#endif -- cgit v1.2.3 From 25c1646670fb4220c6c3ca91e1423c6aa76b3f87 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 23 Jul 2011 10:59:25 -0300 Subject: [media] az6007: Replace the comments at the beginning of the driver The comments there is wrong. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/az6007.c | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/dvb-usb/az6007.c b/drivers/media/dvb/dvb-usb/az6007.c index 1791cb088629..f946b1b65b1d 100644 --- a/drivers/media/dvb/dvb-usb/az6007.c +++ b/drivers/media/dvb/dvb-usb/az6007.c @@ -1,6 +1,23 @@ -/* DVB USB compliant Linux driver for the AzureWave 6017 USB2.0 DVB-S - * receiver. - * see Documentation/dvb/README.dvb-usb for more information +/* + * Driver for AzureWave 6007 DVB-C/T USB2.0 and clones + * + * Copyright (c) Henry Wang + * + * 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() + * + * Driver modifiyed by Mauro Carvalho Chehab in order + * to work with upstream drxk driver, and to fix some bugs. + * + * 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" -- cgit v1.2.3 From 067fb88c9d423d67dbf432010b3bfc5336a2bbed Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 23 Jul 2011 11:10:10 -0300 Subject: [media] az6007: move device PID's to the proper place Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/az6007.c | 4 ---- drivers/media/dvb/dvb-usb/dvb-usb-ids.h | 2 ++ 2 files changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/dvb-usb/az6007.c b/drivers/media/dvb/dvb-usb/az6007.c index f946b1b65b1d..780a480fb703 100644 --- a/drivers/media/dvb/dvb-usb/az6007.c +++ b/drivers/media/dvb/dvb-usb/az6007.c @@ -27,10 +27,6 @@ #define DVB_USB_LOG_PREFIX "az6007" -/* HACK: Should be moved to the right place */ -#define USB_PID_AZUREWAVE_6007 0x0ccd -#define USB_PID_TERRATEC_H7 0x10b4 - /* debug */ int dvb_usb_az6007_debug; module_param_named(debug, dvb_usb_az6007_debug, int, 0644); diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h index d390ddaa5a53..b3e7be4718a6 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h +++ b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h @@ -80,6 +80,7 @@ #define USB_PID_ANSONIC_DVBT_USB 0x6000 #define USB_PID_ANYSEE 0x861f #define USB_PID_AZUREWAVE_AD_TU700 0x3237 +#define USB_PID_AZUREWAVE_6007 0x0ccd #define USB_PID_AVERMEDIA_DVBT_USB_COLD 0x0001 #define USB_PID_AVERMEDIA_DVBT_USB_WARM 0x0002 #define USB_PID_AVERMEDIA_DVBT_USB2_COLD 0xa800 @@ -226,6 +227,7 @@ #define USB_PID_TERRATEC_CINERGY_T_EXPRESS 0x0062 #define USB_PID_TERRATEC_CINERGY_T_XXS 0x0078 #define USB_PID_TERRATEC_CINERGY_T_XXS_2 0x00ab +#define USB_PID_TERRATEC_H7 0x10b4 #define USB_PID_TERRATEC_T3 0x10a0 #define USB_PID_TERRATEC_T5 0x10a1 #define USB_PID_PINNACLE_EXPRESSCARD_320CX 0x022e -- cgit v1.2.3 From f2ba9e5dda2afd4615dbd3c48afe64fe2ce70d4e Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 23 Jul 2011 11:54:40 -0300 Subject: [media] az6007: make driver less verbose Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/az6007.c | 35 +++++++++++++++++------------------ 1 file changed, 17 insertions(+), 18 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/dvb-usb/az6007.c b/drivers/media/dvb/dvb-usb/az6007.c index 780a480fb703..bb597c67cc9f 100644 --- a/drivers/media/dvb/dvb-usb/az6007.c +++ b/drivers/media/dvb/dvb-usb/az6007.c @@ -62,9 +62,9 @@ static int drxk_gate_ctrl(struct dvb_frontend *fe, int enable) { struct dvb_usb_adapter *adap = fe->sec_priv; struct az6007_device_state *st; - int status; + int status = 0; - info("%s: %s", __func__, enable ? "enable" : "disable"); + deb_info("%s: %s\n", __func__, enable ? "enable" : "disable"); if (!adap) return -EINVAL; @@ -127,8 +127,7 @@ static int az6007_usb_out_op(struct dvb_usb_device *d, u8 req, u16 value, debug_dump(b, blen, deb_xfer); if (blen > 64) { - printk(KERN_ERR - "az6007: doesn't suport I2C transactions longer than 64 bytes\n"); + err("az6007: doesn't suport I2C transactions longer than 64 bytes\n"); return -EOPNOTSUPP; } @@ -138,7 +137,7 @@ static int az6007_usb_out_op(struct dvb_usb_device *d, u8 req, u16 value, USB_TYPE_VENDOR | USB_DIR_OUT, value, index, b, blen, 5000); if (ret != blen) { - warn("usb out operation failed. (%d)", ret); + err("usb out operation failed. (%d)", ret); return -EIO; } @@ -207,7 +206,8 @@ static int az6007_frontend_poweron(struct dvb_usb_adapter *adap) u16 index; int blen; - info("az6007_frontend_poweron adap=%p adap->dev=%p", adap, adap->dev); + deb_info("az6007_frontend_poweron adap=%p adap->dev=%p\n", + adap, adap->dev); req = 0xBC; value = 1; /* power on */ @@ -245,7 +245,7 @@ static int az6007_frontend_poweron(struct dvb_usb_adapter *adap) err("az6007_frontend_poweron failed!!!"); return -EIO; } - info("az6007_frontend_poweron: OK"); + deb_info("az6007_frontend_poweron: OK\n"); return 0; } @@ -258,7 +258,7 @@ static int az6007_frontend_reset(struct dvb_usb_adapter *adap) u16 index; int blen; - info("az6007_frontend_reset adap=%p adap->dev=%p", adap, adap->dev); + deb_info("az6007_frontend_reset adap=%p adap->dev=%p\n", adap, adap->dev); /* reset demodulator */ req = 0xC0; @@ -295,7 +295,7 @@ static int az6007_frontend_reset(struct dvb_usb_adapter *adap) msleep_interruptible(200); - info("reset az6007 frontend"); + deb_info("reset az6007 frontend\n"); return 0; } @@ -361,8 +361,7 @@ static int az6007_frontend_attach(struct dvb_usb_adapter *adap) az6007_frontend_poweron(adap); az6007_frontend_reset(adap); - info("az6007_frontend_attach: drxk"); - + info("az6007: attaching demod drxk"); adap->fe = dvb_attach(drxk_attach, &terratec_h7_drxk, &adap->dev->i2c_adap, &adap->fe2); if (!adap->fe) { @@ -370,7 +369,7 @@ static int az6007_frontend_attach(struct dvb_usb_adapter *adap) goto out_free; } - info("Setting hacks"); + deb_info("Setting hacks\n"); /* FIXME: do we need a pll semaphore? */ adap->fe->sec_priv = adap; @@ -379,7 +378,7 @@ static int az6007_frontend_attach(struct dvb_usb_adapter *adap) adap->fe->ops.i2c_gate_ctrl = drxk_gate_ctrl; adap->fe2->id = 1; - info("az6007_frontend_attach: mt2063"); + info("az6007: attaching tuner mt2063"); /* Attach mt2063 to DVB-C frontend */ if (adap->fe->ops.i2c_gate_ctrl) adap->fe->ops.i2c_gate_ctrl(adap->fe, 1); @@ -513,7 +512,7 @@ err: mutex_unlock(&d->i2c_mutex); if (ret < 0) { - info("%s ERROR: %i\n", __func__, ret); + info("%s ERROR: %i", __func__, ret); return ret; } return num; @@ -538,11 +537,11 @@ int az6007_identify_state(struct usb_device *udev, 0xb7, USB_TYPE_VENDOR | USB_DIR_IN, 6, 0, b, 6, USB_CTRL_GET_TIMEOUT); - info("FW GET_VERSION length: %d", ret); + deb_info("FW GET_VERSION length: %d\n", ret); *cold = ret <= 0; - info("cold: %d", *cold); + deb_info("cold: %d\n", *cold); return 0; } @@ -629,7 +628,7 @@ static struct usb_driver az6007_usb_driver = { static int __init az6007_usb_module_init(void) { int result; - info("az6007 usb module init"); + deb_info("az6007 usb module init\n"); result = usb_register(&az6007_usb_driver); if (result) { @@ -643,7 +642,7 @@ static int __init az6007_usb_module_init(void) static void __exit az6007_usb_module_exit(void) { /* deregister this driver from the USB subsystem */ - info("az6007 usb module exit"); + deb_info("az6007 usb module exit\n"); usb_deregister(&az6007_usb_driver); } -- cgit v1.2.3 From da989e0bc7f2b3db3fea417c0bae3c20c6455995 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 24 Jul 2011 09:25:39 -0300 Subject: [media] drxk: Don't assume a default firmware name Move the ngene/ddbridge firmware into their drivers. There are two reasons for that: 1) The firmware used there didn't work for a few devices I tested here (Terratec H5, H6 and H7); 2) At least Terratec H7 doesn't seem to require a firmware for it to work. After this change, if firmware is not specified, the driver will use a rom-based firmware (this seems to be the case for Terratec H7, although I need to better check the USB dumps to be sure about that). In any case, the firmware seems to be optional, as the DRX-K driver don't return the firmware load error. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/ddbridge/ddbridge-core.c | 1 + drivers/media/dvb/dvb-usb/az6007.c | 8 +++++--- drivers/media/dvb/frontends/drxk_hard.c | 4 +--- drivers/media/dvb/ngene/ngene-cards.c | 1 + 4 files changed, 8 insertions(+), 6 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/ddbridge/ddbridge-core.c b/drivers/media/dvb/ddbridge/ddbridge-core.c index 2f31648bba90..243dbb37bd5a 100644 --- a/drivers/media/dvb/ddbridge/ddbridge-core.c +++ b/drivers/media/dvb/ddbridge/ddbridge-core.c @@ -578,6 +578,7 @@ static int demod_attach_drxk(struct ddb_input *input) struct drxk_config config; memset(&config, 0, sizeof(config)); + config.microcode_name = "drxk_a3.mc"; config.adr = 0x29 + (input->nr & 1); fe = input->fe = dvb_attach(drxk_attach, &config, i2c); diff --git a/drivers/media/dvb/dvb-usb/az6007.c b/drivers/media/dvb/dvb-usb/az6007.c index bb597c67cc9f..523972f9ef56 100644 --- a/drivers/media/dvb/dvb-usb/az6007.c +++ b/drivers/media/dvb/dvb-usb/az6007.c @@ -55,7 +55,8 @@ static struct drxk_config terratec_h7_drxk = { .adr = 0x29, .single_master = 1, .no_i2c_bridge = 0, - .microcode_name = "dvb-usb-terratec-h5-drxk.fw", + .max_size = 64, +// .microcode_name = "dvb-usb-terratec-h5-drxk.fw", }; static int drxk_gate_ctrl(struct dvb_frontend *fe, int enable) @@ -127,7 +128,8 @@ static int az6007_usb_out_op(struct dvb_usb_device *d, u8 req, u16 value, debug_dump(b, blen, deb_xfer); if (blen > 64) { - err("az6007: doesn't suport I2C transactions longer than 64 bytes\n"); + err("az6007: tried to write %d bytes, but I2C max size is 64 bytes\n", + blen); return -EOPNOTSUPP; } @@ -395,6 +397,7 @@ static int az6007_frontend_attach(struct dvb_usb_adapter *adap) adap->fe2->tuner_priv = adap->fe->tuner_priv; memcpy(&adap->fe2->ops.tuner_ops, &adap->fe->ops.tuner_ops, sizeof(adap->fe->ops.tuner_ops)); + return 0; out_free: @@ -572,7 +575,6 @@ static struct dvb_usb_device_properties az6007_properties = { .num_adapters = 1, .adapter = { { - /* .caps = DVB_USB_ADAP_RECEIVES_204_BYTE_TS, */ .streaming_ctrl = az6007_streaming_ctrl, .frontend_attach = az6007_frontend_attach, diff --git a/drivers/media/dvb/frontends/drxk_hard.c b/drivers/media/dvb/frontends/drxk_hard.c index 6980ed7b8786..4b99255f7ba0 100644 --- a/drivers/media/dvb/frontends/drxk_hard.c +++ b/drivers/media/dvb/frontends/drxk_hard.c @@ -6070,9 +6070,7 @@ static int init_drxk(struct drxk_state *state) if (status < 0) goto error; - if (!state->microcode_name) - load_microcode(state, "drxk_a3.mc"); - else + if (state->microcode_name) load_microcode(state, state->microcode_name); /* disable token-ring bus through OFDM block for possible ucode upload */ diff --git a/drivers/media/dvb/ngene/ngene-cards.c b/drivers/media/dvb/ngene/ngene-cards.c index 8418c02bcefe..7539a5d71029 100644 --- a/drivers/media/dvb/ngene/ngene-cards.c +++ b/drivers/media/dvb/ngene/ngene-cards.c @@ -216,6 +216,7 @@ static int demod_attach_drxk(struct ngene_channel *chan, struct drxk_config config; memset(&config, 0, sizeof(config)); + config.microcode_name = "drxk_a3.mc"; config.adr = 0x29 + (chan->number ^ 2); chan->fe = dvb_attach(drxk_attach, &config, i2c); -- cgit v1.2.3 From c108a5a0ef1fc20f7ae36318dd154f40dcf1d345 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 25 Jul 2011 10:38:20 -0300 Subject: [media] az6007: need to define drivers name before including dvb-usb.h Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/az6007.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/dvb-usb/az6007.c b/drivers/media/dvb/dvb-usb/az6007.c index 523972f9ef56..87dff933289c 100644 --- a/drivers/media/dvb/dvb-usb/az6007.c +++ b/drivers/media/dvb/dvb-usb/az6007.c @@ -23,9 +23,9 @@ #include "drxk.h" #include "mt2063.h" #include "dvb_ca_en50221.h" -#include "dvb-usb.h" #define DVB_USB_LOG_PREFIX "az6007" +#include "dvb-usb.h" /* debug */ int dvb_usb_az6007_debug; -- cgit v1.2.3 From 81091144ebdb7bdc6197559cd3547d8be7e4e18e Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 25 Jul 2011 11:07:20 -0300 Subject: [media] az6007: Fix some init sequences and use the right firmwares Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/az6007.c | 105 +++++++++++++++---------------------- 1 file changed, 43 insertions(+), 62 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/dvb-usb/az6007.c b/drivers/media/dvb/dvb-usb/az6007.c index 87dff933289c..03e318d2d4bf 100644 --- a/drivers/media/dvb/dvb-usb/az6007.c +++ b/drivers/media/dvb/dvb-usb/az6007.c @@ -56,7 +56,8 @@ static struct drxk_config terratec_h7_drxk = { .single_master = 1, .no_i2c_bridge = 0, .max_size = 64, -// .microcode_name = "dvb-usb-terratec-h5-drxk.fw", + .microcode_name = "dvb-usb-terratec-h7-drxk.fw", + .parallel_ts = 1, }; static int drxk_gate_ctrl(struct dvb_frontend *fe, int enable) @@ -200,53 +201,31 @@ static int az6007_read_mac_addr(struct dvb_usb_device *d, u8 mac[6]) return 0; } +#define AZ6007_POWER 0xbc +#define FX2_SCON1 0xc0 +#define AZ6007_TS_THROUGH 0xc7 + static int az6007_frontend_poweron(struct dvb_usb_adapter *adap) { - int ret; - u8 req; - u16 value; - u16 index; - int blen; + struct dvb_usb_device *d = adap->dev; deb_info("az6007_frontend_poweron adap=%p adap->dev=%p\n", adap, adap->dev); - req = 0xBC; - value = 1; /* power on */ - index = 3; - blen = 0; - - ret = az6007_usb_out_op(adap->dev, req, value, index, NULL, blen); - if (ret != 0) { - err("az6007_frontend_poweron failed!!!"); - return -EIO; - } - - msleep_interruptible(200); - - req = 0xBC; - value = 0; /* power off */ - index = 3; - blen = 0; - - ret = az6007_usb_out_op(adap->dev, req, value, index, NULL, blen); - if (ret != 0) { - err("az6007_frontend_poweron failed!!!"); - return -EIO; - } - - msleep_interruptible(200); - - req = 0xBC; - value = 1; /* power on */ - index = 3; - blen = 0; + az6007_usb_out_op(d, AZ6007_POWER /* 0xbc */, 0, 2, NULL, 0); + msleep(150); + az6007_usb_out_op(d, AZ6007_POWER /* 0xbc */, 1, 4, NULL, 0); + msleep(100); + az6007_usb_out_op(d, AZ6007_POWER /* 0xbc */, 1, 3, NULL, 0); + msleep(100); + az6007_usb_out_op(d, AZ6007_POWER /* 0xbc */, 1, 4, NULL, 0); + msleep(100); + az6007_usb_out_op(d, FX2_SCON1 /* 0xc0 */, 0, 3, NULL, 0); + msleep (10); + az6007_usb_out_op(d, FX2_SCON1 /* 0xc0 */, 1, 3, NULL, 0); + msleep (10); + az6007_usb_out_op(d, AZ6007_POWER /* 0xbc */, 0, 0, NULL, 0); - ret = az6007_usb_out_op(adap->dev, req, value, index, NULL, blen); - if (ret != 0) { - err("az6007_frontend_poweron failed!!!"); - return -EIO; - } deb_info("az6007_frontend_poweron: OK\n"); return 0; @@ -333,25 +312,6 @@ static int az6007_led_on_off(struct usb_interface *intf, int onoff) return ret; } -static int az6007_frontend_tsbypass(struct dvb_usb_adapter *adap, int onoff) -{ - int ret; - u8 req; - u16 value; - u16 index; - int blen; - /* TS through */ - req = 0xC7; - value = onoff; - index = 0; - blen = 0; - - ret = az6007_usb_out_op(adap->dev, req, value, index, NULL, blen); - if (ret != 0) - return -EIO; - return 0; -} - static int az6007_frontend_attach(struct dvb_usb_adapter *adap) { struct az6007_device_state *st = adap->priv; @@ -409,6 +369,27 @@ out_free: return result; } +int az6007_power_ctrl(struct dvb_usb_device *d, int onoff) +{ + if (!onoff) + return 0; + + + info("Sending poweron sequence"); + + az6007_usb_out_op(d, AZ6007_TS_THROUGH /* 0xc7 */, 0, 0, NULL, 0); + +#if 0 + // Seems to be a poweroff sequence + az6007_usb_out_op(d, 0xbc, 1, 3, NULL, 0); + az6007_usb_out_op(d, 0xbc, 1, 4, NULL, 0); + az6007_usb_out_op(d, 0xc0, 0, 3, NULL, 0); + az6007_usb_out_op(d, 0xc0, 1, 3, NULL, 0); + az6007_usb_out_op(d, 0xbc, 0, 1, NULL, 0); +#endif + return 0; +} + static struct dvb_usb_device_properties az6007_properties; static void az6007_usb_disconnect(struct usb_interface *intf) @@ -568,7 +549,7 @@ MODULE_DEVICE_TABLE(usb, az6007_usb_table); static struct dvb_usb_device_properties az6007_properties = { .caps = DVB_USB_IS_AN_I2C_ADAPTER, .usb_ctrl = CYPRESS_FX2, - .firmware = "dvb-usb-az6007-03.fw", + .firmware = "dvb-usb-terratec-h7-az6007.fw", .no_reconnect = 1, .identify_state = az6007_identify_state, @@ -592,7 +573,7 @@ static struct dvb_usb_device_properties az6007_properties = { .size_of_priv = sizeof(struct az6007_device_state), } }, - /* .power_ctrl = az6007_power_ctrl, */ + .power_ctrl = az6007_power_ctrl, .read_mac_address = az6007_read_mac_addr, .rc.legacy = { -- cgit v1.2.3 From 3af2f4f15a61b55469a8512d186221eaf7652eec Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 25 Jul 2011 11:17:41 -0300 Subject: [media] az6007: Change the az6007 read/write routine parameter Use usb_device for those routines, as it allows using them on all places. While there, rename to better express the meaning. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/az6007.c | 56 +++++++++++++++++++------------------- 1 file changed, 28 insertions(+), 28 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/dvb-usb/az6007.c b/drivers/media/dvb/dvb-usb/az6007.c index 03e318d2d4bf..f098e47102ee 100644 --- a/drivers/media/dvb/dvb-usb/az6007.c +++ b/drivers/media/dvb/dvb-usb/az6007.c @@ -96,13 +96,13 @@ static struct mt2063_config az6007_mt2063_config = { }; /* check for mutex FIXME */ -static int az6007_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, +static int az6007_read(struct usb_device *udev, u8 req, u16 value, u16 index, u8 *b, int blen) { int ret = -1; - ret = usb_control_msg(d->udev, - usb_rcvctrlpipe(d->udev, 0), + ret = usb_control_msg(udev, + usb_rcvctrlpipe(udev, 0), req, USB_TYPE_VENDOR | USB_DIR_IN, value, index, b, blen, 5000); @@ -119,7 +119,7 @@ static int az6007_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, return ret; } -static int az6007_usb_out_op(struct dvb_usb_device *d, u8 req, u16 value, +static int az6007_write(struct usb_device *udev, u8 req, u16 value, u16 index, u8 *b, int blen) { int ret; @@ -134,8 +134,8 @@ static int az6007_usb_out_op(struct dvb_usb_device *d, u8 req, u16 value, return -EOPNOTSUPP; } - ret = usb_control_msg(d->udev, - usb_sndctrlpipe(d->udev, 0), + ret = usb_control_msg(udev, + usb_sndctrlpipe(udev, 0), req, USB_TYPE_VENDOR | USB_DIR_OUT, value, index, b, blen, 5000); @@ -168,7 +168,7 @@ static int az6007_rc_query(struct dvb_usb_device *d, u32 * event, int *state) /* remove the following return to enabled remote querying */ - az6007_usb_in_op(d, READ_REMOTE_REQ, 0, 0, key, 10); + az6007_read(d->udev, READ_REMOTE_REQ, 0, 0, key, 10); deb_rc("remote query key: %x %d\n", key[1], key[1]); @@ -191,13 +191,13 @@ static int az6007_rc_query(struct dvb_usb_device *d, u32 * event, int *state) int az6007_power_ctrl(struct dvb_usb_device *d, int onoff) { u8 v = onoff; - return az6007_usb_out_op(d,0xBC,v,3,NULL,1); + return az6007_write(d->udev,0xBC,v,3,NULL,1); } */ static int az6007_read_mac_addr(struct dvb_usb_device *d, u8 mac[6]) { - az6007_usb_in_op(d, 0xb7, 6, 0, &mac[0], 6); + az6007_read(d->udev, 0xb7, 6, 0, &mac[0], 6); return 0; } @@ -212,19 +212,19 @@ static int az6007_frontend_poweron(struct dvb_usb_adapter *adap) deb_info("az6007_frontend_poweron adap=%p adap->dev=%p\n", adap, adap->dev); - az6007_usb_out_op(d, AZ6007_POWER /* 0xbc */, 0, 2, NULL, 0); + az6007_write(d->udev, AZ6007_POWER /* 0xbc */, 0, 2, NULL, 0); msleep(150); - az6007_usb_out_op(d, AZ6007_POWER /* 0xbc */, 1, 4, NULL, 0); + az6007_write(d->udev, AZ6007_POWER /* 0xbc */, 1, 4, NULL, 0); msleep(100); - az6007_usb_out_op(d, AZ6007_POWER /* 0xbc */, 1, 3, NULL, 0); + az6007_write(d->udev, AZ6007_POWER /* 0xbc */, 1, 3, NULL, 0); msleep(100); - az6007_usb_out_op(d, AZ6007_POWER /* 0xbc */, 1, 4, NULL, 0); + az6007_write(d->udev, AZ6007_POWER /* 0xbc */, 1, 4, NULL, 0); msleep(100); - az6007_usb_out_op(d, FX2_SCON1 /* 0xc0 */, 0, 3, NULL, 0); + az6007_write(d->udev, FX2_SCON1 /* 0xc0 */, 0, 3, NULL, 0); msleep (10); - az6007_usb_out_op(d, FX2_SCON1 /* 0xc0 */, 1, 3, NULL, 0); + az6007_write(d->udev, FX2_SCON1 /* 0xc0 */, 1, 3, NULL, 0); msleep (10); - az6007_usb_out_op(d, AZ6007_POWER /* 0xbc */, 0, 0, NULL, 0); + az6007_write(d->udev, AZ6007_POWER /* 0xbc */, 0, 0, NULL, 0); deb_info("az6007_frontend_poweron: OK\n"); @@ -246,7 +246,7 @@ static int az6007_frontend_reset(struct dvb_usb_adapter *adap) value = 1; /* high */ index = 3; blen = 0; - ret = az6007_usb_out_op(adap->dev, req, value, index, NULL, blen); + ret = az6007_write(adap->dev->udev, req, value, index, NULL, blen); if (ret != 0) { err("az6007_frontend_reset failed 1 !!!"); return -EIO; @@ -257,7 +257,7 @@ static int az6007_frontend_reset(struct dvb_usb_adapter *adap) index = 3; blen = 0; msleep_interruptible(200); - ret = az6007_usb_out_op(adap->dev, req, value, index, NULL, blen); + ret = az6007_write(adap->dev->udev, req, value, index, NULL, blen); if (ret != 0) { err("az6007_frontend_reset failed 2 !!!"); return -EIO; @@ -268,7 +268,7 @@ static int az6007_frontend_reset(struct dvb_usb_adapter *adap) index = 3; blen = 0; - ret = az6007_usb_out_op(adap->dev, req, value, index, NULL, blen); + ret = az6007_write(adap->dev->udev, req, value, index, NULL, blen); if (ret != 0) { err("az6007_frontend_reset failed 3 !!!"); return -EIO; @@ -377,15 +377,15 @@ int az6007_power_ctrl(struct dvb_usb_device *d, int onoff) info("Sending poweron sequence"); - az6007_usb_out_op(d, AZ6007_TS_THROUGH /* 0xc7 */, 0, 0, NULL, 0); + az6007_write(d->udev, AZ6007_TS_THROUGH /* 0xc7 */, 0, 0, NULL, 0); #if 0 // Seems to be a poweroff sequence - az6007_usb_out_op(d, 0xbc, 1, 3, NULL, 0); - az6007_usb_out_op(d, 0xbc, 1, 4, NULL, 0); - az6007_usb_out_op(d, 0xc0, 0, 3, NULL, 0); - az6007_usb_out_op(d, 0xc0, 1, 3, NULL, 0); - az6007_usb_out_op(d, 0xbc, 0, 1, NULL, 0); + az6007_write(d->udev, 0xbc, 1, 3, NULL, 0); + az6007_write(d->udev, 0xbc, 1, 4, NULL, 0); + az6007_write(d->udev, 0xc0, 0, 3, NULL, 0); + az6007_write(d->udev, 0xc0, 1, 3, NULL, 0); + az6007_write(d->udev, 0xbc, 0, 1, NULL, 0); #endif return 0; } @@ -434,7 +434,7 @@ static int az6007_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], value = addr | (1 << 8); length = 6 + msgs[i + 1].len; len = msgs[i + 1].len; - ret = az6007_usb_in_op(d, req, value, index, data, + ret = az6007_read(d->udev, req, value, index, data, length); if (ret >= len) { for (j = 0; j < len; j++) { @@ -465,7 +465,7 @@ static int az6007_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], if (dvb_usb_az6007_debug & 2) printk(KERN_CONT "0x%02x ", data[j]); } - ret = az6007_usb_out_op(d, req, value, index, data, + ret = az6007_write(d->udev, req, value, index, data, length); } else { /* read bytes */ @@ -478,7 +478,7 @@ static int az6007_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], value = addr; length = msgs[i].len + 6; len = msgs[i].len; - ret = az6007_usb_in_op(d, req, value, index, data, + ret = az6007_read(d->udev, req, value, index, data, length); for (j = 0; j < len; j++) { msgs[i].buf[j] = data[j + 5]; -- cgit v1.2.3 From 3aecf2c5a9881024dc7742568146e2f9a10f19a6 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 25 Jul 2011 12:45:16 -0300 Subject: [media] az6007: Simplify the read/write logic This patch introduces no functional changes. It basically defines a macro for each different req found at the driver, and cleans the code to use them, making easier to understand the code. With regards to the IR handling code, although the original code doesn't define what's the request, it is clear, from the USB logs, that 0xc5 is for IR polling. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/az6007.c | 185 +++++++++++++++++-------------------- 1 file changed, 87 insertions(+), 98 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/dvb-usb/az6007.c b/drivers/media/dvb/dvb-usb/az6007.c index f098e47102ee..8add81ade087 100644 --- a/drivers/media/dvb/dvb-usb/az6007.c +++ b/drivers/media/dvb/dvb-usb/az6007.c @@ -40,6 +40,17 @@ MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2,rc=4 (or-able))." 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 0xc5 + struct az6007_device_state { struct dvb_ca_en50221 ca; struct mutex ca_mutex; @@ -168,7 +179,7 @@ static int az6007_rc_query(struct dvb_usb_device *d, u32 * event, int *state) /* remove the following return to enabled remote querying */ - az6007_read(d->udev, READ_REMOTE_REQ, 0, 0, key, 10); + az6007_read(d->udev, AZ6007_READ_IR, 0, 0, key, 10); deb_rc("remote query key: %x %d\n", key[1], key[1]); @@ -187,127 +198,104 @@ static int az6007_rc_query(struct dvb_usb_device *d, u32 * event, int *state) #endif } -/* +#if 0 int az6007_power_ctrl(struct dvb_usb_device *d, int onoff) { u8 v = onoff; - return az6007_write(d->udev,0xBC,v,3,NULL,1); + return az6007_write(d->udev, AZ6007_POWER, v , 3, NULL, 1); } -*/ +#endif static int az6007_read_mac_addr(struct dvb_usb_device *d, u8 mac[6]) { - az6007_read(d->udev, 0xb7, 6, 0, &mac[0], 6); - return 0; -} + int ret; + ret = az6007_read(d->udev, AZ6007_READ_DATA, 6, 0, mac, 6); -#define AZ6007_POWER 0xbc -#define FX2_SCON1 0xc0 -#define AZ6007_TS_THROUGH 0xc7 + if (ret > 0) + deb_info("%s: mac is %02x:%02x:%02x:%02x:%02x:%02x\n", + __func__, mac[0], mac[1], mac[2], + mac[3], mac[4], mac[5]); + + return ret; +} static int az6007_frontend_poweron(struct dvb_usb_adapter *adap) { - struct dvb_usb_device *d = adap->dev; + int ret; + struct usb_device *udev = adap->dev->udev; - deb_info("az6007_frontend_poweron adap=%p adap->dev=%p\n", - adap, adap->dev); + deb_info("%s: adap=%p adap->dev=%p\n", __func__, adap, adap->dev); - az6007_write(d->udev, AZ6007_POWER /* 0xbc */, 0, 2, NULL, 0); + ret = az6007_write(udev, AZ6007_POWER, 0, 2, NULL, 0); + if (ret < 0) + goto error; msleep(150); - az6007_write(d->udev, AZ6007_POWER /* 0xbc */, 1, 4, NULL, 0); + ret = az6007_write(udev, AZ6007_POWER, 1, 4, NULL, 0); + if (ret < 0) + goto error; msleep(100); - az6007_write(d->udev, AZ6007_POWER /* 0xbc */, 1, 3, NULL, 0); + ret = az6007_write(udev, AZ6007_POWER, 1, 3, NULL, 0); + if (ret < 0) + goto error; msleep(100); - az6007_write(d->udev, AZ6007_POWER /* 0xbc */, 1, 4, NULL, 0); + ret = az6007_write(udev, AZ6007_POWER, 1, 4, NULL, 0); + if (ret < 0) + goto error; msleep(100); - az6007_write(d->udev, FX2_SCON1 /* 0xc0 */, 0, 3, NULL, 0); + ret = az6007_write(udev, FX2_SCON1, 0, 3, NULL, 0); + if (ret < 0) + goto error; msleep (10); - az6007_write(d->udev, FX2_SCON1 /* 0xc0 */, 1, 3, NULL, 0); + ret = az6007_write(udev, FX2_SCON1, 1, 3, NULL, 0); + if (ret < 0) + goto error; msleep (10); - az6007_write(d->udev, AZ6007_POWER /* 0xbc */, 0, 0, NULL, 0); + ret = az6007_write(udev, AZ6007_POWER, 0, 0, NULL, 0); - deb_info("az6007_frontend_poweron: OK\n"); +error: + if (ret < 0) + err("%s failed with error %d", __func__, ret); - return 0; + return ret; } static int az6007_frontend_reset(struct dvb_usb_adapter *adap) { + struct usb_device *udev = adap->dev->udev; int ret; - u8 req; - u16 value; - u16 index; - int blen; deb_info("az6007_frontend_reset adap=%p adap->dev=%p\n", adap, adap->dev); /* reset demodulator */ - req = 0xC0; - value = 1; /* high */ - index = 3; - blen = 0; - ret = az6007_write(adap->dev->udev, req, value, index, NULL, blen); - if (ret != 0) { - err("az6007_frontend_reset failed 1 !!!"); - return -EIO; - } + ret = az6007_write(udev, FX2_SCON1, 1, 3, NULL, 0); + if (ret < 0) + goto error; + msleep(200); + ret = az6007_write(udev, FX2_SCON1, 0, 3, NULL, 0); + if (ret < 0) + goto error; + msleep(200); + ret = az6007_write(udev, FX2_SCON1, 1, 3, NULL, 0); + if (ret < 0) + goto error; + msleep(200); + +error: + if (ret < 0) + err("%s failed with error %d", __func__, ret); - req = 0xC0; - value = 0; /* low */ - index = 3; - blen = 0; - msleep_interruptible(200); - ret = az6007_write(adap->dev->udev, req, value, index, NULL, blen); - if (ret != 0) { - err("az6007_frontend_reset failed 2 !!!"); - return -EIO; - } - msleep_interruptible(200); - req = 0xC0; - value = 1; /* high */ - index = 3; - blen = 0; - - ret = az6007_write(adap->dev->udev, req, value, index, NULL, blen); - if (ret != 0) { - err("az6007_frontend_reset failed 3 !!!"); - return -EIO; - } - - msleep_interruptible(200); - - deb_info("reset az6007 frontend\n"); - - return 0; + return ret; } static int az6007_led_on_off(struct usb_interface *intf, int onoff) { - int ret = -1; - u8 req; - u16 value; - u16 index; - int blen; - /* TS through */ - req = 0xBC; - value = onoff; - index = 0; - blen = 0; - - ret = usb_control_msg(interface_to_usbdev(intf), - usb_rcvctrlpipe(interface_to_usbdev(intf), 0), - req, - USB_TYPE_VENDOR | USB_DIR_OUT, - value, index, NULL, blen, 2000); - - if (ret < 0) { - warn("usb in operation failed. (%d)", ret); - ret = -EIO; - } else - ret = 0; + struct usb_device *udev = interface_to_usbdev(intf); + int ret; - deb_xfer("in: req. %02x, val: %04x, ind: %04x, buffer: ", req, value, - index); + /* TS through */ + ret = az6007_write(udev, AZ6007_POWER, onoff, 0, NULL, 0); + if (ret < 0) + err("%s failed with error %d", __func__, ret); return ret; } @@ -377,7 +365,7 @@ int az6007_power_ctrl(struct dvb_usb_device *d, int onoff) info("Sending poweron sequence"); - az6007_write(d->udev, AZ6007_TS_THROUGH /* 0xc7 */, 0, 0, NULL, 0); + az6007_write(d->udev, AZ6007_TS_THROUGH, 0, 0, NULL, 0); #if 0 // Seems to be a poweroff sequence @@ -429,7 +417,7 @@ static int az6007_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], printk(KERN_DEBUG "az6007 I2C xfer write+read addr=0x%x len=%d/%d: ", addr, msgs[i].len, msgs[i + 1].len); - req = 0xb9; + req = AZ6007_I2C_RD; index = msgs[i].buf[0]; value = addr | (1 << 8); length = 6 + msgs[i + 1].len; @@ -453,7 +441,7 @@ static int az6007_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], printk(KERN_DEBUG "az6007 I2C xfer write addr=0x%x len=%d: ", addr, msgs[i].len); - req = 0xbd; + req = AZ6007_I2C_WR; index = msgs[i].buf[0]; value = addr | (1 << 8); length = msgs[i].len - 1; @@ -473,7 +461,7 @@ static int az6007_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], printk(KERN_DEBUG "az6007 I2C xfer read addr=0x%x len=%d: ", addr, msgs[i].len); - req = 0xb9; + req = AZ6007_I2C_RD; index = msgs[i].buf[0]; value = addr; length = msgs[i].len + 6; @@ -516,16 +504,17 @@ int az6007_identify_state(struct usb_device *udev, struct dvb_usb_device_properties *props, struct dvb_usb_device_description **desc, int *cold) { - u8 b[16]; - s16 ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), - 0xb7, USB_TYPE_VENDOR | USB_DIR_IN, 6, 0, b, - 6, USB_CTRL_GET_TIMEOUT); - - deb_info("FW GET_VERSION length: %d\n", ret); + int ret; + u8 mac[6]; - *cold = ret <= 0; + /* Try to read the mac address */ + ret = az6007_read(udev, AZ6007_READ_DATA, 6, 0, mac, 6); + if (ret == 6) + *cold = 0; + else + *cold = 1; - deb_info("cold: %d\n", *cold); + deb_info("Device is on %s state\n", *cold? "warm" : "cold"); return 0; } -- cgit v1.2.3 From ba02473eaaaa9e579a4bdbe9f15a5ad777764580 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 25 Jul 2011 12:49:46 -0300 Subject: [media] az6007: Simplify the code by removing an uneeded function Everything to reset the demod is already at az6007_frontend_poweron(). Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/az6007.c | 29 ----------------------------- 1 file changed, 29 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/dvb-usb/az6007.c b/drivers/media/dvb/dvb-usb/az6007.c index 8add81ade087..912ba67bc393 100644 --- a/drivers/media/dvb/dvb-usb/az6007.c +++ b/drivers/media/dvb/dvb-usb/az6007.c @@ -259,34 +259,6 @@ error: return ret; } -static int az6007_frontend_reset(struct dvb_usb_adapter *adap) -{ - struct usb_device *udev = adap->dev->udev; - int ret; - - deb_info("az6007_frontend_reset adap=%p adap->dev=%p\n", adap, adap->dev); - - /* reset demodulator */ - ret = az6007_write(udev, FX2_SCON1, 1, 3, NULL, 0); - if (ret < 0) - goto error; - msleep(200); - ret = az6007_write(udev, FX2_SCON1, 0, 3, NULL, 0); - if (ret < 0) - goto error; - msleep(200); - ret = az6007_write(udev, FX2_SCON1, 1, 3, NULL, 0); - if (ret < 0) - goto error; - msleep(200); - -error: - if (ret < 0) - err("%s failed with error %d", __func__, ret); - - return ret; -} - static int az6007_led_on_off(struct usb_interface *intf, int onoff) { struct usb_device *udev = interface_to_usbdev(intf); @@ -309,7 +281,6 @@ static int az6007_frontend_attach(struct dvb_usb_adapter *adap) BUG_ON(!st); az6007_frontend_poweron(adap); - az6007_frontend_reset(adap); info("az6007: attaching demod drxk"); adap->fe = dvb_attach(drxk_attach, &terratec_h7_drxk, -- cgit v1.2.3 From 2d5161b7714ae75ac62cd58bf4c5c11ca6c2da59 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 29 Jul 2011 11:31:13 -0300 Subject: [media] az6007: Fix IR receive code The code still needs to be commented, as there's a mutex missing at the az6007_read() call. A mutex there is needed, in order to prevent RC (or CI) calls while other operations are in progress. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/az6007.c | 37 ++++++++++++++++++++++++++----------- 1 file changed, 26 insertions(+), 11 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/dvb-usb/az6007.c b/drivers/media/dvb/dvb-usb/az6007.c index 912ba67bc393..c9743ee2ba75 100644 --- a/drivers/media/dvb/dvb-usb/az6007.c +++ b/drivers/media/dvb/dvb-usb/az6007.c @@ -49,7 +49,7 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); #define AZ6007_I2C_WR 0xbd #define FX2_SCON1 0xc0 #define AZ6007_TS_THROUGH 0xc7 -#define AZ6007_READ_IR 0xc5 +#define AZ6007_READ_IR 0xb4 struct az6007_device_state { struct dvb_ca_en50221 ca; @@ -172,30 +172,45 @@ static struct rc_map_table rc_map_az6007_table[] = { /* remote control stuff (does not work with my box) */ static int az6007_rc_query(struct dvb_usb_device *d, u32 * event, int *state) { - return 0; -#if 0 + struct rc_map_table *keymap = d->props.rc.legacy.rc_map_table; u8 key[10]; int i; - /* remove the following return to enabled remote querying */ + /* + * FIXME: remove the following return to enabled remote querying + * The driver likely needs proper locking to avoid troubles between + * this call and other concurrent calls. + */ + return 0; az6007_read(d->udev, AZ6007_READ_IR, 0, 0, key, 10); - deb_rc("remote query key: %x %d\n", key[1], key[1]); - if (key[1] == 0x44) { *state = REMOTE_NO_KEY_PRESSED; return 0; } - for (i = 0; i < ARRAY_SIZE(az6007_rc_keys); i++) - if (az6007_rc_keys[i].custom == key[1]) { + /* + * FIXME: need to make something useful with the keycodes and to + * convert it to the non-legacy mode. Yet, it is producing some + * debug info already, like: + * 88 04 eb 02 fd ff 00 82 63 82 (terratec IR) + * 88 04 eb 03 fc 00 00 82 63 82 (terratec IR) + * 88 80 7e 0d f2 ff 00 82 63 82 (another NEC-extended based IR) + * I suspect that the IR data is at bytes 1 to 4, and byte 5 is parity + */ + deb_rc("remote query key: %x %d\n", key[1], key[1]); + print_hex_dump_bytes("Remote: ", DUMP_PREFIX_NONE, key, 10); + + for (i = 0; i < d->props.rc.legacy.rc_map_size; i++) { + if (rc5_custom(&keymap[i]) == key[1]) { + *event = keymap[i].keycode; *state = REMOTE_KEY_PRESSED; - *event = az6007_rc_keys[i].event; - break; + + return 0; } + } return 0; -#endif } #if 0 -- cgit v1.2.3 From 9b01f3d498a9f39de1824609c08edbd137b774b6 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 29 Jul 2011 11:40:40 -0300 Subject: [media] az6007: improve the error messages for az6007 read/write calls Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/az6007.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/dvb-usb/az6007.c b/drivers/media/dvb/dvb-usb/az6007.c index c9743ee2ba75..c9b6f8077905 100644 --- a/drivers/media/dvb/dvb-usb/az6007.c +++ b/drivers/media/dvb/dvb-usb/az6007.c @@ -110,16 +110,15 @@ static struct mt2063_config az6007_mt2063_config = { static int az6007_read(struct usb_device *udev, u8 req, u16 value, u16 index, u8 *b, int blen) { - int ret = -1; + 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) { - warn("usb in operation failed. (%d)", ret); + warn("usb read operation failed. (%d)", ret); return -EIO; } @@ -151,7 +150,7 @@ static int az6007_write(struct usb_device *udev, u8 req, u16 value, USB_TYPE_VENDOR | USB_DIR_OUT, value, index, b, blen, 5000); if (ret != blen) { - err("usb out operation failed. (%d)", ret); + err("usb write operation failed. (%d)", ret); return -EIO; } -- cgit v1.2.3 From 1c9a284fbd3d25dc1a1a1da32be1eaff021c4029 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 31 Jul 2011 10:11:32 -0300 Subject: [media] az6007: Use the new MFE support at dvb-usb Use the newly dvb-usb MFE support added by changeset 9bd9e3bd2c57530dfe3057dd0aa9bdb37824925d. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/az6007.c | 74 +++++++++++++++++++------------------- 1 file changed, 38 insertions(+), 36 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/dvb-usb/az6007.c b/drivers/media/dvb/dvb-usb/az6007.c index c9b6f8077905..b667854bdbf0 100644 --- a/drivers/media/dvb/dvb-usb/az6007.c +++ b/drivers/media/dvb/dvb-usb/az6007.c @@ -59,7 +59,7 @@ struct az6007_device_state { /* Due to DRX-K - probably need changes */ int (*gate_ctrl) (struct dvb_frontend *, int); struct semaphore pll_mutex; - bool dont_attach_fe1; + bool tuner_attached; }; static struct drxk_config terratec_h7_drxk = { @@ -290,56 +290,56 @@ static int az6007_frontend_attach(struct dvb_usb_adapter *adap) { struct az6007_device_state *st = adap->priv; - int result; + /* FIXME: dvb-usb will call this function twice! */ + if (adap->fe[0]) + return 0; BUG_ON(!st); az6007_frontend_poweron(adap); - info("az6007: attaching demod drxk"); - adap->fe = dvb_attach(drxk_attach, &terratec_h7_drxk, - &adap->dev->i2c_adap, &adap->fe2); - if (!adap->fe) { - result = -EINVAL; - goto out_free; - } - - deb_info("Setting hacks\n"); + info("attaching demod drxk"); + adap->fe[0] = dvb_attach(drxk_attach, &terratec_h7_drxk, + &adap->dev->i2c_adap, &adap->fe[1]); + if (!adap->fe[0]) + return -EINVAL; + adap->fe[0]->sec_priv = adap; /* FIXME: do we need a pll semaphore? */ - adap->fe->sec_priv = adap; sema_init(&st->pll_mutex, 1); - st->gate_ctrl = adap->fe->ops.i2c_gate_ctrl; - adap->fe->ops.i2c_gate_ctrl = drxk_gate_ctrl; - adap->fe2->id = 1; + st->gate_ctrl = adap->fe[0]->ops.i2c_gate_ctrl; + adap->fe[0]->ops.i2c_gate_ctrl = drxk_gate_ctrl; + adap->dont_attach_fe[1] = true; + + return 0; +} + +static int az6007_tuner_attach(struct dvb_usb_adapter *adap) +{ + struct az6007_device_state *st = adap->priv; + + if (st->tuner_attached) + return 0; + + st->tuner_attached = true; - info("az6007: attaching tuner mt2063"); + info("attaching tuner mt2063"); /* Attach mt2063 to DVB-C frontend */ - if (adap->fe->ops.i2c_gate_ctrl) - adap->fe->ops.i2c_gate_ctrl(adap->fe, 1); - if (!dvb_attach(mt2063_attach, adap->fe, &az6007_mt2063_config, - &adap->dev->i2c_adap)) { - result = -EINVAL; + 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, + &adap->dev->i2c_adap)) + return -EINVAL; - goto out_free; - } - if (adap->fe->ops.i2c_gate_ctrl) - adap->fe->ops.i2c_gate_ctrl(adap->fe, 0); + if (adap->fe[0]->ops.i2c_gate_ctrl) + adap->fe[0]->ops.i2c_gate_ctrl(adap->fe[0], 0); /* Hack - needed due to drxk */ - adap->fe2->tuner_priv = adap->fe->tuner_priv; - memcpy(&adap->fe2->ops.tuner_ops, - &adap->fe->ops.tuner_ops, sizeof(adap->fe->ops.tuner_ops)); + adap->fe[1]->tuner_priv = adap->fe[0]->tuner_priv; + memcpy(&adap->fe[1]->ops.tuner_ops, + &adap->fe[0]->ops.tuner_ops, sizeof(adap->fe[0]->ops.tuner_ops)); return 0; - -out_free: - if (adap->fe) - dvb_frontend_detach(adap->fe); - adap->fe = NULL; - adap->fe2 = NULL; - - return result; } int az6007_power_ctrl(struct dvb_usb_device *d, int onoff) @@ -530,7 +530,9 @@ static struct dvb_usb_device_properties az6007_properties = { .num_adapters = 1, .adapter = { { + .num_frontends = 2, .streaming_ctrl = az6007_streaming_ctrl, + .tuner_attach = az6007_tuner_attach, .frontend_attach = az6007_frontend_attach, /* parameter for the MPEG2-data transfer */ -- cgit v1.2.3 From 781dacc82ac8105e19dd62e76b8d4278e680af81 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 16 Jan 2012 18:57:51 -0300 Subject: [media] az6007: Change it to use the MFE solution adopted at dvb-usb This driver were written to use a previous solution for MFE at dvb-usb. Due to the internal API changes, change the binding to work with the new way. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/az6007.c | 42 +++++++++++++++----------------------- 1 file changed, 17 insertions(+), 25 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/dvb-usb/az6007.c b/drivers/media/dvb/dvb-usb/az6007.c index b667854bdbf0..92ded30b2cc6 100644 --- a/drivers/media/dvb/dvb-usb/az6007.c +++ b/drivers/media/dvb/dvb-usb/az6007.c @@ -66,7 +66,7 @@ static struct drxk_config terratec_h7_drxk = { .adr = 0x29, .single_master = 1, .no_i2c_bridge = 0, - .max_size = 64, + .chunk_size = 64, .microcode_name = "dvb-usb-terratec-h7-drxk.fw", .parallel_ts = 1, }; @@ -290,26 +290,21 @@ static int az6007_frontend_attach(struct dvb_usb_adapter *adap) { struct az6007_device_state *st = adap->priv; - /* FIXME: dvb-usb will call this function twice! */ - if (adap->fe[0]) - return 0; - BUG_ON(!st); az6007_frontend_poweron(adap); info("attaching demod drxk"); - adap->fe[0] = dvb_attach(drxk_attach, &terratec_h7_drxk, - &adap->dev->i2c_adap, &adap->fe[1]); - if (!adap->fe[0]) + adap->fe_adap[0].fe = dvb_attach(drxk_attach, &terratec_h7_drxk, + &adap->dev->i2c_adap); + if (!adap->fe_adap[0].fe) return -EINVAL; - adap->fe[0]->sec_priv = adap; + adap->fe_adap[0].fe->sec_priv = adap; /* FIXME: do we need a pll semaphore? */ sema_init(&st->pll_mutex, 1); - st->gate_ctrl = adap->fe[0]->ops.i2c_gate_ctrl; - adap->fe[0]->ops.i2c_gate_ctrl = drxk_gate_ctrl; - adap->dont_attach_fe[1] = true; + st->gate_ctrl = adap->fe_adap[0].fe->ops.i2c_gate_ctrl; + adap->fe_adap[0].fe->ops.i2c_gate_ctrl = drxk_gate_ctrl; return 0; } @@ -325,19 +320,15 @@ static int az6007_tuner_attach(struct dvb_usb_adapter *adap) info("attaching tuner mt2063"); /* 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, + if (adap->fe_adap[0].fe->ops.i2c_gate_ctrl) + adap->fe_adap[0].fe->ops.i2c_gate_ctrl(adap->fe_adap[0].fe, 1); + if (!dvb_attach(mt2063_attach, adap->fe_adap[0].fe, + &az6007_mt2063_config, &adap->dev->i2c_adap)) return -EINVAL; - if (adap->fe[0]->ops.i2c_gate_ctrl) - adap->fe[0]->ops.i2c_gate_ctrl(adap->fe[0], 0); - - /* Hack - needed due to drxk */ - adap->fe[1]->tuner_priv = adap->fe[0]->tuner_priv; - memcpy(&adap->fe[1]->ops.tuner_ops, - &adap->fe[0]->ops.tuner_ops, sizeof(adap->fe[0]->ops.tuner_ops)); + if (adap->fe_adap[0].fe->ops.i2c_gate_ctrl) + adap->fe_adap[0].fe->ops.i2c_gate_ctrl(adap->fe_adap[0].fe, 0); return 0; } @@ -530,7 +521,8 @@ static struct dvb_usb_device_properties az6007_properties = { .num_adapters = 1, .adapter = { { - .num_frontends = 2, + .num_frontends = 1, + .fe = {{ .streaming_ctrl = az6007_streaming_ctrl, .tuner_attach = az6007_tuner_attach, .frontend_attach = az6007_frontend_attach, @@ -547,8 +539,8 @@ static struct dvb_usb_device_properties az6007_properties = { } }, .size_of_priv = sizeof(struct az6007_device_state), - } - }, + }} + } }, .power_ctrl = az6007_power_ctrl, .read_mac_address = az6007_read_mac_addr, -- cgit v1.2.3 From 978c26c3672a15fd545da2e927467b5b6bd67acb Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 16 Jan 2012 20:37:13 -0300 Subject: [media] az6007: Use a per device private struct Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/az6007.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/dvb-usb/az6007.c b/drivers/media/dvb/dvb-usb/az6007.c index 92ded30b2cc6..342f9292c17e 100644 --- a/drivers/media/dvb/dvb-usb/az6007.c +++ b/drivers/media/dvb/dvb-usb/az6007.c @@ -82,7 +82,7 @@ static int drxk_gate_ctrl(struct dvb_frontend *fe, int enable) if (!adap) return -EINVAL; - st = adap->priv; + st = adap->dev->priv; if (!st) return -EINVAL; @@ -288,7 +288,7 @@ static int az6007_led_on_off(struct usb_interface *intf, int onoff) static int az6007_frontend_attach(struct dvb_usb_adapter *adap) { - struct az6007_device_state *st = adap->priv; + struct az6007_device_state *st = adap->dev->priv; BUG_ON(!st); @@ -311,7 +311,7 @@ static int az6007_frontend_attach(struct dvb_usb_adapter *adap) static int az6007_tuner_attach(struct dvb_usb_adapter *adap) { - struct az6007_device_state *st = adap->priv; + struct az6007_device_state *st = adap->dev->priv; if (st->tuner_attached) return 0; @@ -516,8 +516,8 @@ static struct dvb_usb_device_properties az6007_properties = { .usb_ctrl = CYPRESS_FX2, .firmware = "dvb-usb-terratec-h7-az6007.fw", .no_reconnect = 1, - - .identify_state = az6007_identify_state, + .size_of_priv = sizeof(struct az6007_device_state), + .identify_state = az6007_identify_state, .num_adapters = 1, .adapter = { { @@ -538,7 +538,6 @@ static struct dvb_usb_device_properties az6007_properties = { } } }, - .size_of_priv = sizeof(struct az6007_device_state), }} } }, .power_ctrl = az6007_power_ctrl, -- cgit v1.2.3 From 67f04617377ecd4ee1547fd9ab3a97af38d572d0 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 20 Jan 2012 18:30:58 -0300 Subject: [media] drxk: Allow setting it on dynamic_clock mode This is used on az6007. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/drxk.h | 17 ++++++++++------- drivers/media/dvb/frontends/drxk_hard.c | 14 +++++++++----- 2 files changed, 19 insertions(+), 12 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/frontends/drxk.h b/drivers/media/dvb/frontends/drxk.h index 020981844a86..6b0fd2c5dcd6 100644 --- a/drivers/media/dvb/frontends/drxk.h +++ b/drivers/media/dvb/frontends/drxk.h @@ -7,15 +7,17 @@ /** * struct drxk_config - Configure the initial parameters for DRX-K * - * adr: I2C Address of the DRX-K - * parallel_ts: true means that the device uses parallel TS, + * @adr: I2C Address of the DRX-K + * @parallel_ts: True means that the device uses parallel TS, * Serial otherwise. - * single_master: Device is on the single master mode - * no_i2c_bridge: Don't switch the I2C bridge to talk with tuner - * antenna_gpio: GPIO bit used to control the antenna - * antenna_dvbt: GPIO bit for changing antenna to DVB-C. A value of 1 + * @dynamic_clk: True means that the clock will be dynamically + * adjusted. Static clock otherwise. + * @single_master: Device is on the single master mode + * @no_i2c_bridge: Don't switch the I2C bridge to talk with tuner + * @antenna_gpio: GPIO bit used to control the antenna + * @antenna_dvbt: GPIO bit for changing antenna to DVB-C. A value of 1 * means that 1=DVBC, 0 = DVBT. Zero means the opposite. - * microcode_name: Name of the firmware file with the microcode + * @microcode_name: Name of the firmware file with the microcode * * On the *_gpio vars, bit 0 is UIO-1, bit 1 is UIO-2 and bit 2 is * UIO-3. @@ -25,6 +27,7 @@ struct drxk_config { bool single_master; bool no_i2c_bridge; bool parallel_ts; + bool dynamic_clk; bool antenna_dvbt; u16 antenna_gpio; diff --git a/drivers/media/dvb/frontends/drxk_hard.c b/drivers/media/dvb/frontends/drxk_hard.c index 4b99255f7ba0..65703968d8ae 100644 --- a/drivers/media/dvb/frontends/drxk_hard.c +++ b/drivers/media/dvb/frontends/drxk_hard.c @@ -650,9 +650,6 @@ static int init_state(struct drxk_state *state) u32 ulQual83 = DEFAULT_MER_83; u32 ulQual93 = DEFAULT_MER_93; - u32 ulDVBTStaticTSClock = 1; - u32 ulDVBCStaticTSClock = 1; - u32 ulMpegLockTimeOut = DEFAULT_DRXK_MPEG_LOCK_TIMEOUT; u32 ulDemodLockTimeOut = DEFAULT_DRXK_DEMOD_LOCK_TIMEOUT; @@ -815,8 +812,7 @@ static int init_state(struct drxk_state *state) state->m_invertSTR = false; /* If TRUE; invert STR signals */ state->m_invertVAL = false; /* If TRUE; invert VAL signals */ state->m_invertCLK = (ulInvertTSClock != 0); /* If TRUE; invert CLK signals */ - state->m_DVBTStaticCLK = (ulDVBTStaticTSClock != 0); - state->m_DVBCStaticCLK = (ulDVBCStaticTSClock != 0); + /* If TRUE; static MPEG clockrate will be used; otherwise clockrate will adapt to the bitrate of the TS */ @@ -6390,6 +6386,14 @@ struct dvb_frontend *drxk_attach(const struct drxk_config *config, state->antenna_dvbt = config->antenna_dvbt; state->m_ChunkSize = config->chunk_size; + if (config->dynamic_clk) { + state->m_DVBTStaticCLK = 0; + state->m_DVBCStaticCLK = 0; + } else { + state->m_DVBTStaticCLK = 1; + state->m_DVBCStaticCLK = 1; + } + if (config->parallel_ts) state->m_enableParallel = true; else -- cgit v1.2.3 From 6e5caf8493fabbb1c6aec1cb98adb9667182a1c6 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 20 Jan 2012 18:36:26 -0300 Subject: [media] az6007: Use DRX-K dynamic clock mode Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/az6007.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/dvb-usb/az6007.c b/drivers/media/dvb/dvb-usb/az6007.c index 342f9292c17e..00a0bf1c795e 100644 --- a/drivers/media/dvb/dvb-usb/az6007.c +++ b/drivers/media/dvb/dvb-usb/az6007.c @@ -64,11 +64,12 @@ struct az6007_device_state { static struct drxk_config terratec_h7_drxk = { .adr = 0x29, - .single_master = 1, - .no_i2c_bridge = 0, + .parallel_ts = true, + .dynamic_clk = true, + .single_master = true, + .no_i2c_bridge = false, .chunk_size = 64, - .microcode_name = "dvb-usb-terratec-h7-drxk.fw", - .parallel_ts = 1, + .microcode_name = "dvb-usb-terratec-h7-az6007.fw", }; static int drxk_gate_ctrl(struct dvb_frontend *fe, int enable) -- cgit v1.2.3 From 6fb65a66a227013ba1825efcf47e3c5df1a39131 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 20 Jan 2012 19:13:07 -0300 Subject: [media] drxk: add support for Mpeg output clock drive strength config Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/az6007.c | 3 +-- drivers/media/dvb/frontends/drxk.h | 4 +++- drivers/media/dvb/frontends/drxk_hard.c | 12 ++++++------ 3 files changed, 10 insertions(+), 9 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/dvb-usb/az6007.c b/drivers/media/dvb/dvb-usb/az6007.c index 00a0bf1c795e..bf8d20151b05 100644 --- a/drivers/media/dvb/dvb-usb/az6007.c +++ b/drivers/media/dvb/dvb-usb/az6007.c @@ -69,6 +69,7 @@ static struct drxk_config terratec_h7_drxk = { .single_master = true, .no_i2c_bridge = false, .chunk_size = 64, + .mpeg_out_clk_strength = 0x02, .microcode_name = "dvb-usb-terratec-h7-az6007.fw", }; @@ -278,12 +279,10 @@ static int az6007_led_on_off(struct usb_interface *intf, int onoff) { struct usb_device *udev = interface_to_usbdev(intf); int ret; - /* TS through */ ret = az6007_write(udev, AZ6007_POWER, onoff, 0, NULL, 0); if (ret < 0) err("%s failed with error %d", __func__, ret); - return ret; } diff --git a/drivers/media/dvb/frontends/drxk.h b/drivers/media/dvb/frontends/drxk.h index 6b0fd2c5dcd6..ca921c77f71f 100644 --- a/drivers/media/dvb/frontends/drxk.h +++ b/drivers/media/dvb/frontends/drxk.h @@ -17,6 +17,7 @@ * @antenna_gpio: GPIO bit used to control the antenna * @antenna_dvbt: GPIO bit for changing antenna to DVB-C. A value of 1 * means that 1=DVBC, 0 = DVBT. Zero means the opposite. + * @mpeg_out_clk_strength: DRXK Mpeg output clock drive strength. * @microcode_name: Name of the firmware file with the microcode * * On the *_gpio vars, bit 0 is UIO-1, bit 1 is UIO-2 and bit 2 is @@ -32,7 +33,8 @@ struct drxk_config { bool antenna_dvbt; u16 antenna_gpio; - int chunk_size; + u8 mpeg_out_clk_strength; + int chunk_size; const char *microcode_name; }; diff --git a/drivers/media/dvb/frontends/drxk_hard.c b/drivers/media/dvb/frontends/drxk_hard.c index 65703968d8ae..d25b0d20038b 100644 --- a/drivers/media/dvb/frontends/drxk_hard.c +++ b/drivers/media/dvb/frontends/drxk_hard.c @@ -91,10 +91,6 @@ bool IsA1WithRomCode(struct drxk_state *state) #define DRXK_MPEG_PARALLEL_OUTPUT_PIN_DRIVE_STRENGTH (0x03) #endif -#ifndef DRXK_MPEG_OUTPUT_CLK_DRIVE_STRENGTH -#define DRXK_MPEG_OUTPUT_CLK_DRIVE_STRENGTH (0x06) -#endif - #define DEFAULT_DRXK_MPEG_LOCK_TIMEOUT 700 #define DEFAULT_DRXK_DEMOD_LOCK_TIMEOUT 500 @@ -659,7 +655,6 @@ static int init_state(struct drxk_state *state) u32 ulGPIOCfg = 0x0113; u32 ulInvertTSClock = 0; u32 ulTSDataStrength = DRXK_MPEG_SERIAL_OUTPUT_PIN_DRIVE_STRENGTH; - u32 ulTSClockkStrength = DRXK_MPEG_OUTPUT_CLK_DRIVE_STRENGTH; u32 ulDVBTBitrate = 50000000; u32 ulDVBCBitrate = DRXK_QAM_SYMBOLRATE_MAX * 8; @@ -820,7 +815,6 @@ static int init_state(struct drxk_state *state) state->m_DVBCBitrate = ulDVBCBitrate; state->m_TSDataStrength = (ulTSDataStrength & 0x07); - state->m_TSClockkStrength = (ulTSClockkStrength & 0x07); /* Maximum bitrate in b/s in case static clockrate is selected */ state->m_mpegTsStaticBitrate = 19392658; @@ -6394,6 +6388,12 @@ struct dvb_frontend *drxk_attach(const struct drxk_config *config, state->m_DVBCStaticCLK = 1; } + + if (config->mpeg_out_clk_strength) + state->m_TSClockkStrength = config->mpeg_out_clk_strength & 0x07; + else + state->m_TSClockkStrength = 0x06; + if (config->parallel_ts) state->m_enableParallel = true; else -- cgit v1.2.3 From d585681374ed23a707b572a1199d510e518d7522 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 21 Jan 2012 07:57:06 -0300 Subject: [media] drxk: Allow enabling MERR/MVAL cfg Those two settings are different when used with az6007. Add a config option to enable it. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/az6007.c | 1 + drivers/media/dvb/frontends/drxk.h | 2 ++ drivers/media/dvb/frontends/drxk_hard.c | 11 +++++++++-- drivers/media/dvb/frontends/drxk_hard.h | 1 + 4 files changed, 13 insertions(+), 2 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/dvb-usb/az6007.c b/drivers/media/dvb/dvb-usb/az6007.c index bf8d20151b05..81fdc90be449 100644 --- a/drivers/media/dvb/dvb-usb/az6007.c +++ b/drivers/media/dvb/dvb-usb/az6007.c @@ -67,6 +67,7 @@ static struct drxk_config terratec_h7_drxk = { .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, diff --git a/drivers/media/dvb/frontends/drxk.h b/drivers/media/dvb/frontends/drxk.h index ca921c77f71f..9d64e4fea066 100644 --- a/drivers/media/dvb/frontends/drxk.h +++ b/drivers/media/dvb/frontends/drxk.h @@ -12,6 +12,7 @@ * Serial otherwise. * @dynamic_clk: True means that the clock will be dynamically * adjusted. Static clock otherwise. + * @enable_merr_cfg: Enable SIO_PDR_PERR_CFG/SIO_PDR_MVAL_CFG. * @single_master: Device is on the single master mode * @no_i2c_bridge: Don't switch the I2C bridge to talk with tuner * @antenna_gpio: GPIO bit used to control the antenna @@ -29,6 +30,7 @@ struct drxk_config { bool no_i2c_bridge; bool parallel_ts; bool dynamic_clk; + bool enable_merr_cfg; bool antenna_dvbt; u16 antenna_gpio; diff --git a/drivers/media/dvb/frontends/drxk_hard.c b/drivers/media/dvb/frontends/drxk_hard.c index d25b0d20038b..5fa192731fcd 100644 --- a/drivers/media/dvb/frontends/drxk_hard.c +++ b/drivers/media/dvb/frontends/drxk_hard.c @@ -1179,6 +1179,7 @@ static int MPEGTSConfigurePins(struct drxk_state *state, bool mpegEnable) int status = -1; u16 sioPdrMclkCfg = 0; u16 sioPdrMdxCfg = 0; + u16 err_cfg = 0; dprintk(1, ": mpeg %s, %s mode\n", mpegEnable ? "enable" : "disable", @@ -1244,12 +1245,17 @@ static int MPEGTSConfigurePins(struct drxk_state *state, bool mpegEnable) status = write16(state, SIO_PDR_MSTRT_CFG__A, sioPdrMdxCfg); if (status < 0) goto error; - status = write16(state, SIO_PDR_MERR_CFG__A, 0x0000); /* Disable */ + + if (state->enable_merr_cfg) + err_cfg = sioPdrMdxCfg; + + status = write16(state, SIO_PDR_MERR_CFG__A, err_cfg); if (status < 0) goto error; - status = write16(state, SIO_PDR_MVAL_CFG__A, 0x0000); /* Disable */ + status = write16(state, SIO_PDR_MVAL_CFG__A, err_cfg); if (status < 0) goto error; + if (state->m_enableParallel == true) { /* paralel -> enable MD1 to MD7 */ status = write16(state, SIO_PDR_MD1_CFG__A, sioPdrMdxCfg); @@ -6379,6 +6385,7 @@ struct dvb_frontend *drxk_attach(const struct drxk_config *config, state->antenna_gpio = config->antenna_gpio; state->antenna_dvbt = config->antenna_dvbt; state->m_ChunkSize = config->chunk_size; + state->enable_merr_cfg = config->enable_merr_cfg; if (config->dynamic_clk) { state->m_DVBTStaticCLK = 0; diff --git a/drivers/media/dvb/frontends/drxk_hard.h b/drivers/media/dvb/frontends/drxk_hard.h index 3a58b73eb9b9..4bbf841de83a 100644 --- a/drivers/media/dvb/frontends/drxk_hard.h +++ b/drivers/media/dvb/frontends/drxk_hard.h @@ -332,6 +332,7 @@ struct drxk_state { u16 UIO_mask; /* Bits used by UIO */ + bool enable_merr_cfg; bool single_master; bool no_i2c_bridge; bool antenna_dvbt; -- cgit v1.2.3 From b19280cf2bee7df489f9488bda45220f8518e39f Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 20 Jan 2012 18:37:01 -0300 Subject: [media] az6007: code cleanups and fixes Several changes were needed to make az6007 to work, producing the same commands as the original driver. This patch does that. While here, be less verbose when debug is not enabled. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/az6007.c | 148 +++++++++++++++++++++---------------- 1 file changed, 83 insertions(+), 65 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/dvb-usb/az6007.c b/drivers/media/dvb/dvb-usb/az6007.c index 81fdc90be449..f0e4c013bb5d 100644 --- a/drivers/media/dvb/dvb-usb/az6007.c +++ b/drivers/media/dvb/dvb-usb/az6007.c @@ -54,12 +54,16 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); struct az6007_device_state { struct dvb_ca_en50221 ca; struct mutex ca_mutex; - u8 power_state; + unsigned warm : 1; /* Due to DRX-K - probably need changes */ int (*gate_ctrl) (struct dvb_frontend *, int); struct semaphore pll_mutex; bool tuner_attached; + + unsigned char data[4096]; + + struct usb_data_stream *stream; }; static struct drxk_config terratec_h7_drxk = { @@ -71,7 +75,7 @@ static struct drxk_config terratec_h7_drxk = { .no_i2c_bridge = false, .chunk_size = 64, .mpeg_out_clk_strength = 0x02, - .microcode_name = "dvb-usb-terratec-h7-az6007.fw", + .microcode_name = "dvb-usb-terratec-h7-drxk.fw", }; static int drxk_gate_ctrl(struct dvb_frontend *fe, int enable) @@ -162,7 +166,9 @@ static int az6007_write(struct usb_device *udev, u8 req, u16 value, static int az6007_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) { - return 0; + deb_info("%s: %s", __func__, onoff ? "enable" : "disable"); + + return az6007_write(adap->dev->udev, 0xbc, onoff, 0, NULL, 0); } /* keys for the enclosed remote control */ @@ -236,46 +242,6 @@ static int az6007_read_mac_addr(struct dvb_usb_device *d, u8 mac[6]) return ret; } -static int az6007_frontend_poweron(struct dvb_usb_adapter *adap) -{ - int ret; - struct usb_device *udev = adap->dev->udev; - - deb_info("%s: adap=%p adap->dev=%p\n", __func__, adap, adap->dev); - - ret = az6007_write(udev, AZ6007_POWER, 0, 2, NULL, 0); - if (ret < 0) - goto error; - msleep(150); - ret = az6007_write(udev, AZ6007_POWER, 1, 4, NULL, 0); - if (ret < 0) - goto error; - msleep(100); - ret = az6007_write(udev, AZ6007_POWER, 1, 3, NULL, 0); - if (ret < 0) - goto error; - msleep(100); - ret = az6007_write(udev, AZ6007_POWER, 1, 4, NULL, 0); - if (ret < 0) - goto error; - msleep(100); - ret = az6007_write(udev, FX2_SCON1, 0, 3, NULL, 0); - if (ret < 0) - goto error; - msleep (10); - ret = az6007_write(udev, FX2_SCON1, 1, 3, NULL, 0); - if (ret < 0) - goto error; - msleep (10); - ret = az6007_write(udev, AZ6007_POWER, 0, 0, NULL, 0); - -error: - if (ret < 0) - err("%s failed with error %d", __func__, ret); - - return ret; -} - static int az6007_led_on_off(struct usb_interface *intf, int onoff) { struct usb_device *udev = interface_to_usbdev(intf); @@ -293,9 +259,8 @@ static int az6007_frontend_attach(struct dvb_usb_adapter *adap) BUG_ON(!st); - az6007_frontend_poweron(adap); + deb_info("attaching demod drxk"); - info("attaching demod drxk"); adap->fe_adap[0].fe = dvb_attach(drxk_attach, &terratec_h7_drxk, &adap->dev->i2c_adap); if (!adap->fe_adap[0].fe) @@ -319,11 +284,11 @@ static int az6007_tuner_attach(struct dvb_usb_adapter *adap) st->tuner_attached = true; - info("attaching tuner mt2063"); + deb_info("attaching tuner mt2063"); /* Attach mt2063 to DVB-C frontend */ if (adap->fe_adap[0].fe->ops.i2c_gate_ctrl) adap->fe_adap[0].fe->ops.i2c_gate_ctrl(adap->fe_adap[0].fe, 1); - if (!dvb_attach(mt2063_attach, adap->fe_adap[0].fe, + if (!dvb_attach(mt2063_attach, adap->fe_adap[0].fe, &az6007_mt2063_config, &adap->dev->i2c_adap)) return -EINVAL; @@ -336,22 +301,69 @@ static int az6007_tuner_attach(struct dvb_usb_adapter *adap) int az6007_power_ctrl(struct dvb_usb_device *d, int onoff) { - if (!onoff) - return 0; + struct az6007_device_state *st = d->priv; + struct usb_device *udev = d->udev; + int ret; + + deb_info("%s()\n", __func__); + + if (!st->warm) { + u8 data[6]; + + az6007_read(udev, FX2_OED, 1, 0, data, 1); /* {0x01} */ + az6007_read(udev, AZ6007_READ_DATA, 0, 8160, data, 1); /* {0x20} */ + az6007_read(udev, AZ6007_READ_DATA, 0, 0, data, 5); /* {0x00, 0x00, 0x00, 0x00, 0x0a} */ + az6007_read(udev, AZ6007_READ_DATA, 0, 4080, data, 6); /* {0x00, 0x08, 0x00, 0x0c, 0x22, 0x38} */ + + ret = az6007_write(udev, AZ6007_POWER, 0, 2, NULL, 0); + if (ret < 0) + return ret; + msleep(60); + ret = az6007_write(udev, AZ6007_POWER, 1, 4, NULL, 0); + if (ret < 0) + return ret; + msleep(100); + ret = az6007_write(udev, AZ6007_POWER, 1, 3, NULL, 0); + if (ret < 0) + return ret; + msleep(20); + ret = az6007_write(udev, AZ6007_POWER, 1, 4, NULL, 0); + if (ret < 0) + return ret; + + msleep(400); + ret = az6007_write(udev, FX2_SCON1, 0, 3, NULL, 0); + if (ret < 0) + return ret; + msleep (150); + ret = az6007_write(udev, FX2_SCON1, 1, 3, NULL, 0); + if (ret < 0) + return ret; + msleep (430); + ret = az6007_write(udev, AZ6007_POWER, 0, 0, NULL, 0); + if (ret < 0) + return ret; + st->warm = true; - info("Sending poweron sequence"); + return 0; + } - az6007_write(d->udev, AZ6007_TS_THROUGH, 0, 0, NULL, 0); + if (!onoff) + return 0; + + az6007_write(udev, AZ6007_POWER, 0, 0, NULL, 0); + az6007_write(udev, AZ6007_TS_THROUGH, 0, 0, NULL, 0); #if 0 // Seems to be a poweroff sequence - az6007_write(d->udev, 0xbc, 1, 3, NULL, 0); - az6007_write(d->udev, 0xbc, 1, 4, NULL, 0); - az6007_write(d->udev, 0xc0, 0, 3, NULL, 0); - az6007_write(d->udev, 0xc0, 1, 3, NULL, 0); - az6007_write(d->udev, 0xbc, 0, 1, NULL, 0); + az6007_write(udev, 0xbc, 1, 3, NULL, 0); + az6007_write(udev, 0xbc, 1, 4, NULL, 0); + az6007_write(udev, 0xc0, 0, 3, NULL, 0); + az6007_write(udev, 0xc0, 1, 3, NULL, 0); + az6007_write(udev, 0xbc, 0, 1, NULL, 0); #endif + return 0; } @@ -367,13 +379,13 @@ 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->priv; int i, j, len; int ret = 0; u16 index; u16 value; int length; u8 req, addr; - u8 data[512]; if (mutex_lock_interruptible(&d->i2c_mutex) < 0) return -EAGAIN; @@ -399,11 +411,11 @@ static int az6007_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], value = addr | (1 << 8); length = 6 + msgs[i + 1].len; len = msgs[i + 1].len; - ret = az6007_read(d->udev, req, value, index, data, + 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] = data[j + 5]; + msgs[i + 1].buf[j] = st->data[j + 5]; if (dvb_usb_az6007_debug & 2) printk(KERN_CONT "0x%02x ", @@ -426,11 +438,11 @@ static int az6007_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], if (dvb_usb_az6007_debug & 2) printk(KERN_CONT "(0x%02x) ", msgs[i].buf[0]); for (j = 0; j < len; j++) { - data[j] = msgs[i].buf[j + 1]; + st->data[j] = msgs[i].buf[j + 1]; if (dvb_usb_az6007_debug & 2) - printk(KERN_CONT "0x%02x ", data[j]); + printk(KERN_CONT "0x%02x ", st->data[j]); } - ret = az6007_write(d->udev, req, value, index, data, + ret = az6007_write(d->udev, req, value, index, st->data, length); } else { /* read bytes */ @@ -443,13 +455,13 @@ static int az6007_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], value = addr; length = msgs[i].len + 6; len = msgs[i].len; - ret = az6007_read(d->udev, req, value, index, data, + ret = az6007_read(d->udev, req, value, index, st->data, length); for (j = 0; j < len; j++) { - msgs[i].buf[j] = data[j + 5]; + msgs[i].buf[j] = st->data[j + 5]; if (dvb_usb_az6007_debug & 2) printk(KERN_CONT - "0x%02x ", data[j + 5]); + "0x%02x ", st->data[j + 5]); } } if (dvb_usb_az6007_debug & 2) @@ -491,6 +503,12 @@ int az6007_identify_state(struct usb_device *udev, else *cold = 1; + if (*cold) { + az6007_write(udev, 0x09, 1, 0, NULL, 0); + az6007_write(udev, 0x00, 0, 0, NULL, 0); + az6007_write(udev, 0x00, 0, 0, NULL, 0); + } + deb_info("Device is on %s state\n", *cold? "warm" : "cold"); return 0; } -- cgit v1.2.3 From 04e3ece7153054e2694a882f6ffa54941574049c Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 21 Jan 2012 10:35:12 -0300 Subject: [media] az6007: Driver cleanup Remove commented test code, remove unused poweroff stuff, and fix the copyright data. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/az6007.c | 56 +++++++++----------------------------- 1 file changed, 13 insertions(+), 43 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/dvb-usb/az6007.c b/drivers/media/dvb/dvb-usb/az6007.c index f0e4c013bb5d..534d3267c86e 100644 --- a/drivers/media/dvb/dvb-usb/az6007.c +++ b/drivers/media/dvb/dvb-usb/az6007.c @@ -7,8 +7,9 @@ * 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() * - * Driver modifiyed by Mauro Carvalho Chehab in order - * to work with upstream drxk driver, and to fix some bugs. + * Copyright (c) 2010-2011 Mauro Carvalho Chehab + * Driver modified by in order to work with upstream drxk driver, and + * tons of bugs got fixed. * * 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 @@ -58,7 +59,6 @@ struct az6007_device_state { /* Due to DRX-K - probably need changes */ int (*gate_ctrl) (struct dvb_frontend *, int); - struct semaphore pll_mutex; bool tuner_attached; unsigned char data[4096]; @@ -94,17 +94,11 @@ static int drxk_gate_ctrl(struct dvb_frontend *fe, int enable) if (!st) return -EINVAL; - if (enable) { -#if 0 - down(&st->pll_mutex); -#endif + if (enable) status = st->gate_ctrl(fe, 1); - } else { -#if 0 + else status = st->gate_ctrl(fe, 0); -#endif - up(&st->pll_mutex); - } + return status; } @@ -221,14 +215,6 @@ static int az6007_rc_query(struct dvb_usb_device *d, u32 * event, int *state) return 0; } -#if 0 -int az6007_power_ctrl(struct dvb_usb_device *d, int onoff) -{ - u8 v = onoff; - return az6007_write(d->udev, AZ6007_POWER, v , 3, NULL, 1); -} -#endif - static int az6007_read_mac_addr(struct dvb_usb_device *d, u8 mac[6]) { int ret; @@ -246,6 +232,7 @@ static int az6007_led_on_off(struct usb_interface *intf, int onoff) { struct usb_device *udev = interface_to_usbdev(intf); int ret; + /* TS through */ ret = az6007_write(udev, AZ6007_POWER, onoff, 0, NULL, 0); if (ret < 0) @@ -257,8 +244,6 @@ static int az6007_frontend_attach(struct dvb_usb_adapter *adap) { struct az6007_device_state *st = adap->dev->priv; - BUG_ON(!st); - deb_info("attaching demod drxk"); adap->fe_adap[0].fe = dvb_attach(drxk_attach, &terratec_h7_drxk, @@ -267,8 +252,6 @@ static int az6007_frontend_attach(struct dvb_usb_adapter *adap) return -EINVAL; adap->fe_adap[0].fe->sec_priv = adap; - /* FIXME: do we need a pll semaphore? */ - sema_init(&st->pll_mutex, 1); st->gate_ctrl = adap->fe_adap[0].fe->ops.i2c_gate_ctrl; adap->fe_adap[0].fe->ops.i2c_gate_ctrl = drxk_gate_ctrl; @@ -282,9 +265,8 @@ static int az6007_tuner_attach(struct dvb_usb_adapter *adap) if (st->tuner_attached) return 0; - st->tuner_attached = true; - deb_info("attaching tuner mt2063"); + /* Attach mt2063 to DVB-C frontend */ if (adap->fe_adap[0].fe->ops.i2c_gate_ctrl) adap->fe_adap[0].fe->ops.i2c_gate_ctrl(adap->fe_adap[0].fe, 1); @@ -296,6 +278,8 @@ static int az6007_tuner_attach(struct dvb_usb_adapter *adap) if (adap->fe_adap[0].fe->ops.i2c_gate_ctrl) adap->fe_adap[0].fe->ops.i2c_gate_ctrl(adap->fe_adap[0].fe, 0); + st->tuner_attached = true; + return 0; } @@ -355,25 +339,9 @@ int az6007_power_ctrl(struct dvb_usb_device *d, int onoff) az6007_write(udev, AZ6007_POWER, 0, 0, NULL, 0); az6007_write(udev, AZ6007_TS_THROUGH, 0, 0, NULL, 0); -#if 0 - // Seems to be a poweroff sequence - az6007_write(udev, 0xbc, 1, 3, NULL, 0); - az6007_write(udev, 0xbc, 1, 4, NULL, 0); - az6007_write(udev, 0xc0, 0, 3, NULL, 0); - az6007_write(udev, 0xc0, 1, 3, NULL, 0); - az6007_write(udev, 0xbc, 0, 1, NULL, 0); -#endif - return 0; } -static struct dvb_usb_device_properties az6007_properties; - -static void az6007_usb_disconnect(struct usb_interface *intf) -{ - dvb_usb_device_exit(intf); -} - /* I2C */ static int az6007_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) @@ -513,6 +481,8 @@ int az6007_identify_state(struct usb_device *udev, return 0; } +static struct dvb_usb_device_properties az6007_properties; + static int az6007_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) { @@ -589,7 +559,6 @@ static struct usb_driver az6007_usb_driver = { .name = "dvb_usb_az6007", .probe = az6007_usb_probe, .disconnect = dvb_usb_device_exit, - /* .disconnect = az6007_usb_disconnect, */ .id_table = az6007_usb_table, }; @@ -619,6 +588,7 @@ module_init(az6007_usb_module_init); module_exit(az6007_usb_module_exit); MODULE_AUTHOR("Henry Wang "); +MODULE_AUTHOR("Mauro Carvalho Chehab "); MODULE_DESCRIPTION("Driver for AzureWave 6007 DVB-C/T USB2.0 and clones"); MODULE_VERSION("1.1"); MODULE_LICENSE("GPL"); -- cgit v1.2.3 From a2c35d346d9e9555db930f9035d0e628bf7f3393 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 21 Jan 2012 11:19:16 -0300 Subject: [media] az6007: Protect read/write calls with a mutex This will avoid interference with CI and IR I/O operations. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/az6007.c | 122 +++++++++++++++++++------------------ 1 file changed, 62 insertions(+), 60 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/dvb-usb/az6007.c b/drivers/media/dvb/dvb-usb/az6007.c index 534d3267c86e..6177332a7a0e 100644 --- a/drivers/media/dvb/dvb-usb/az6007.c +++ b/drivers/media/dvb/dvb-usb/az6007.c @@ -53,17 +53,11 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); #define AZ6007_READ_IR 0xb4 struct az6007_device_state { - struct dvb_ca_en50221 ca; - struct mutex ca_mutex; - unsigned warm : 1; - - /* Due to DRX-K - probably need changes */ + struct mutex mutex; + struct dvb_ca_en50221 ca; + unsigned warm:1; int (*gate_ctrl) (struct dvb_frontend *, int); - bool tuner_attached; - unsigned char data[4096]; - - struct usb_data_stream *stream; }; static struct drxk_config terratec_h7_drxk = { @@ -107,8 +101,7 @@ static struct mt2063_config az6007_mt2063_config = { .refclock = 36125000, }; -/* check for mutex FIXME */ -static int az6007_read(struct usb_device *udev, u8 req, u16 value, +static int __az6007_read(struct usb_device *udev, u8 req, u16 value, u16 index, u8 *b, int blen) { int ret; @@ -130,7 +123,23 @@ static int az6007_read(struct usb_device *udev, u8 req, u16 value, return ret; } -static int az6007_write(struct usb_device *udev, u8 req, u16 value, +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; +} + +static int __az6007_write(struct usb_device *udev, u8 req, u16 value, u16 index, u8 *b, int blen) { int ret; @@ -158,11 +167,29 @@ static int az6007_write(struct usb_device *udev, u8 req, u16 value, return 0; } +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; +} + static int az6007_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) { + struct dvb_usb_device *d = adap->dev; + deb_info("%s: %s", __func__, onoff ? "enable" : "disable"); - return az6007_write(adap->dev->udev, 0xbc, onoff, 0, NULL, 0); + return az6007_write(d, 0xbc, onoff, 0, NULL, 0); } /* keys for the enclosed remote control */ @@ -185,7 +212,7 @@ static int az6007_rc_query(struct dvb_usb_device *d, u32 * event, int *state) */ return 0; - az6007_read(d->udev, AZ6007_READ_IR, 0, 0, key, 10); + az6007_read(d, AZ6007_READ_IR, 0, 0, key, 10); if (key[1] == 0x44) { *state = REMOTE_NO_KEY_PRESSED; @@ -218,7 +245,7 @@ static int az6007_rc_query(struct dvb_usb_device *d, u32 * event, int *state) static int az6007_read_mac_addr(struct dvb_usb_device *d, u8 mac[6]) { int ret; - ret = az6007_read(d->udev, AZ6007_READ_DATA, 6, 0, mac, 6); + ret = az6007_read(d, AZ6007_READ_DATA, 6, 0, mac, 6); if (ret > 0) deb_info("%s: mac is %02x:%02x:%02x:%02x:%02x:%02x\n", @@ -228,18 +255,6 @@ static int az6007_read_mac_addr(struct dvb_usb_device *d, u8 mac[6]) return ret; } -static int az6007_led_on_off(struct usb_interface *intf, int onoff) -{ - struct usb_device *udev = interface_to_usbdev(intf); - int ret; - - /* TS through */ - ret = az6007_write(udev, AZ6007_POWER, onoff, 0, NULL, 0); - if (ret < 0) - err("%s failed with error %d", __func__, ret); - return ret; -} - static int az6007_frontend_attach(struct dvb_usb_adapter *adap) { struct az6007_device_state *st = adap->dev->priv; @@ -260,11 +275,6 @@ static int az6007_frontend_attach(struct dvb_usb_adapter *adap) static int az6007_tuner_attach(struct dvb_usb_adapter *adap) { - struct az6007_device_state *st = adap->dev->priv; - - if (st->tuner_attached) - return 0; - deb_info("attaching tuner mt2063"); /* Attach mt2063 to DVB-C frontend */ @@ -278,53 +288,45 @@ static int az6007_tuner_attach(struct dvb_usb_adapter *adap) if (adap->fe_adap[0].fe->ops.i2c_gate_ctrl) adap->fe_adap[0].fe->ops.i2c_gate_ctrl(adap->fe_adap[0].fe, 0); - st->tuner_attached = true; - return 0; } int az6007_power_ctrl(struct dvb_usb_device *d, int onoff) { struct az6007_device_state *st = d->priv; - struct usb_device *udev = d->udev; int ret; deb_info("%s()\n", __func__); if (!st->warm) { - u8 data[6]; + mutex_init(&st->mutex); - az6007_read(udev, FX2_OED, 1, 0, data, 1); /* {0x01} */ - az6007_read(udev, AZ6007_READ_DATA, 0, 8160, data, 1); /* {0x20} */ - az6007_read(udev, AZ6007_READ_DATA, 0, 0, data, 5); /* {0x00, 0x00, 0x00, 0x00, 0x0a} */ - az6007_read(udev, AZ6007_READ_DATA, 0, 4080, data, 6); /* {0x00, 0x08, 0x00, 0x0c, 0x22, 0x38} */ - - ret = az6007_write(udev, AZ6007_POWER, 0, 2, NULL, 0); + ret = az6007_write(d, AZ6007_POWER, 0, 2, NULL, 0); if (ret < 0) return ret; msleep(60); - ret = az6007_write(udev, AZ6007_POWER, 1, 4, NULL, 0); + ret = az6007_write(d, AZ6007_POWER, 1, 4, NULL, 0); if (ret < 0) return ret; msleep(100); - ret = az6007_write(udev, AZ6007_POWER, 1, 3, NULL, 0); + ret = az6007_write(d, AZ6007_POWER, 1, 3, NULL, 0); if (ret < 0) return ret; msleep(20); - ret = az6007_write(udev, AZ6007_POWER, 1, 4, NULL, 0); + ret = az6007_write(d, AZ6007_POWER, 1, 4, NULL, 0); if (ret < 0) return ret; msleep(400); - ret = az6007_write(udev, FX2_SCON1, 0, 3, NULL, 0); + ret = az6007_write(d, FX2_SCON1, 0, 3, NULL, 0); if (ret < 0) return ret; msleep (150); - ret = az6007_write(udev, FX2_SCON1, 1, 3, NULL, 0); + ret = az6007_write(d, FX2_SCON1, 1, 3, NULL, 0); if (ret < 0) return ret; msleep (430); - ret = az6007_write(udev, AZ6007_POWER, 0, 0, NULL, 0); + ret = az6007_write(d, AZ6007_POWER, 0, 0, NULL, 0); if (ret < 0) return ret; @@ -336,8 +338,8 @@ int az6007_power_ctrl(struct dvb_usb_device *d, int onoff) if (!onoff) return 0; - az6007_write(udev, AZ6007_POWER, 0, 0, NULL, 0); - az6007_write(udev, AZ6007_TS_THROUGH, 0, 0, NULL, 0); + az6007_write(d, AZ6007_POWER, 0, 0, NULL, 0); + az6007_write(d, AZ6007_TS_THROUGH, 0, 0, NULL, 0); return 0; } @@ -355,7 +357,7 @@ static int az6007_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int length; u8 req, addr; - if (mutex_lock_interruptible(&d->i2c_mutex) < 0) + if (mutex_lock_interruptible(&st->mutex) < 0) return -EAGAIN; for (i = 0; i < num; i++) { @@ -379,7 +381,7 @@ static int az6007_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], 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, + ret = __az6007_read(d->udev, req, value, index, st->data, length); if (ret >= len) { for (j = 0; j < len; j++) { @@ -410,7 +412,7 @@ static int az6007_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], if (dvb_usb_az6007_debug & 2) printk(KERN_CONT "0x%02x ", st->data[j]); } - ret = az6007_write(d->udev, req, value, index, st->data, + ret = __az6007_write(d->udev, req, value, index, st->data, length); } else { /* read bytes */ @@ -423,7 +425,7 @@ static int az6007_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], value = addr; length = msgs[i].len + 6; len = msgs[i].len; - ret = az6007_read(d->udev, req, value, index, st->data, + 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]; @@ -438,7 +440,7 @@ static int az6007_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], goto err; } err: - mutex_unlock(&d->i2c_mutex); + mutex_unlock(&st->mutex); if (ret < 0) { info("%s ERROR: %i", __func__, ret); @@ -465,16 +467,16 @@ int az6007_identify_state(struct usb_device *udev, u8 mac[6]; /* Try to read the mac address */ - ret = az6007_read(udev, AZ6007_READ_DATA, 6, 0, mac, 6); + ret = __az6007_read(udev, AZ6007_READ_DATA, 6, 0, mac, 6); if (ret == 6) *cold = 0; else *cold = 1; if (*cold) { - az6007_write(udev, 0x09, 1, 0, NULL, 0); - az6007_write(udev, 0x00, 0, 0, NULL, 0); - az6007_write(udev, 0x00, 0, 0, NULL, 0); + __az6007_write(udev, 0x09, 1, 0, NULL, 0); + __az6007_write(udev, 0x00, 0, 0, NULL, 0); + __az6007_write(udev, 0x00, 0, 0, NULL, 0); } deb_info("Device is on %s state\n", *cold? "warm" : "cold"); @@ -486,7 +488,7 @@ static struct dvb_usb_device_properties az6007_properties; static int az6007_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) { - az6007_led_on_off(intf, 0); + struct usb_device *udev = interface_to_usbdev(intf); return dvb_usb_device_init(intf, &az6007_properties, THIS_MODULE, NULL, adapter_nr); -- cgit v1.2.3 From 711e1398d3131fd83aee0a35d450c6e1a809bfb2 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 21 Jan 2012 11:53:18 -0300 Subject: [media] az6007: Be sure to use kmalloc'ed buffer for transfers USB data transfers may not work if the buffer is allocated at the stack. Be sure to use kmalloc on all places where a buffer is needed. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/az6007.c | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/dvb-usb/az6007.c b/drivers/media/dvb/dvb-usb/az6007.c index 6177332a7a0e..142ef7b0c02e 100644 --- a/drivers/media/dvb/dvb-usb/az6007.c +++ b/drivers/media/dvb/dvb-usb/az6007.c @@ -201,8 +201,8 @@ static struct rc_map_table rc_map_az6007_table[] = { /* remote control stuff (does not work with my box) */ static int az6007_rc_query(struct dvb_usb_device *d, u32 * event, int *state) { + struct az6007_device_state *st = d->priv; struct rc_map_table *keymap = d->props.rc.legacy.rc_map_table; - u8 key[10]; int i; /* @@ -212,9 +212,9 @@ static int az6007_rc_query(struct dvb_usb_device *d, u32 * event, int *state) */ return 0; - az6007_read(d, AZ6007_READ_IR, 0, 0, key, 10); + az6007_read(d, AZ6007_READ_IR, 0, 0, st->data, 10); - if (key[1] == 0x44) { + if (st->data[1] == 0x44) { *state = REMOTE_NO_KEY_PRESSED; return 0; } @@ -228,11 +228,11 @@ static int az6007_rc_query(struct dvb_usb_device *d, u32 * event, int *state) * 88 80 7e 0d f2 ff 00 82 63 82 (another NEC-extended based IR) * I suspect that the IR data is at bytes 1 to 4, and byte 5 is parity */ - deb_rc("remote query key: %x %d\n", key[1], key[1]); - print_hex_dump_bytes("Remote: ", DUMP_PREFIX_NONE, key, 10); + deb_rc("remote query key: %x %d\n", st->data[1], st->data[1]); + print_hex_dump_bytes("Remote: ", DUMP_PREFIX_NONE, st->data, 10); for (i = 0; i < d->props.rc.legacy.rc_map_size; i++) { - if (rc5_custom(&keymap[i]) == key[1]) { + if (rc5_custom(&keymap[i]) == st->data[1]) { *event = keymap[i].keycode; *state = REMOTE_KEY_PRESSED; @@ -244,8 +244,11 @@ static int az6007_rc_query(struct dvb_usb_device *d, u32 * event, int *state) static int az6007_read_mac_addr(struct dvb_usb_device *d, u8 mac[6]) { + struct az6007_device_state *st = d->priv; int ret; - ret = az6007_read(d, AZ6007_READ_DATA, 6, 0, mac, 6); + + ret = az6007_read(d, AZ6007_READ_DATA, 6, 0, st->data, 6); + memcpy(mac, st->data, sizeof(mac)); if (ret > 0) deb_info("%s: mac is %02x:%02x:%02x:%02x:%02x:%02x\n", @@ -464,7 +467,11 @@ int az6007_identify_state(struct usb_device *udev, struct dvb_usb_device_description **desc, int *cold) { int ret; - u8 mac[6]; + u8 *mac; + + mac = kmalloc(6, GFP_ATOMIC); + if (!mac) + return -ENOMEM; /* Try to read the mac address */ ret = __az6007_read(udev, AZ6007_READ_DATA, 6, 0, mac, 6); @@ -473,6 +480,8 @@ int az6007_identify_state(struct usb_device *udev, else *cold = 1; + kfree(mac); + if (*cold) { __az6007_write(udev, 0x09, 1, 0, NULL, 0); __az6007_write(udev, 0x00, 0, 0, NULL, 0); @@ -488,8 +497,6 @@ static struct dvb_usb_device_properties az6007_properties; static int az6007_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) { - struct usb_device *udev = interface_to_usbdev(intf); - return dvb_usb_device_init(intf, &az6007_properties, THIS_MODULE, NULL, adapter_nr); } -- cgit v1.2.3 From 9165144033944a4c650a9914888bf6b6f7328c7a Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 21 Jan 2012 12:14:13 -0300 Subject: [media] az6007: Fix IR handling Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/az6007.c | 31 +++++++++++++------------------ 1 file changed, 13 insertions(+), 18 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/dvb-usb/az6007.c b/drivers/media/dvb/dvb-usb/az6007.c index 142ef7b0c02e..a8aedb87ae69 100644 --- a/drivers/media/dvb/dvb-usb/az6007.c +++ b/drivers/media/dvb/dvb-usb/az6007.c @@ -204,13 +204,7 @@ static int az6007_rc_query(struct dvb_usb_device *d, u32 * event, int *state) struct az6007_device_state *st = d->priv; struct rc_map_table *keymap = d->props.rc.legacy.rc_map_table; int i; - - /* - * FIXME: remove the following return to enabled remote querying - * The driver likely needs proper locking to avoid troubles between - * this call and other concurrent calls. - */ - return 0; + unsigned code = 0; az6007_read(d, AZ6007_READ_IR, 0, 0, st->data, 10); @@ -219,20 +213,21 @@ static int az6007_rc_query(struct dvb_usb_device *d, u32 * event, int *state) return 0; } - /* - * FIXME: need to make something useful with the keycodes and to - * convert it to the non-legacy mode. Yet, it is producing some - * debug info already, like: - * 88 04 eb 02 fd ff 00 82 63 82 (terratec IR) - * 88 04 eb 03 fc 00 00 82 63 82 (terratec IR) - * 88 80 7e 0d f2 ff 00 82 63 82 (another NEC-extended based IR) - * I suspect that the IR data is at bytes 1 to 4, and byte 5 is parity - */ - deb_rc("remote query key: %x %d\n", st->data[1], st->data[1]); + if ((st->data[1] ^ st->data[2]) == 0xff) + code = st->data[1]; + else + code = st->data[1] << 8 | st->data[2]; + + if ((st->data[3] ^ st->data[4]) == 0xff) + code = code << 8 | st->data[3]; + else + code = code << 16 | st->data[3] << 8| st->data[4]; + + printk("remote query key: %04x\n", code); print_hex_dump_bytes("Remote: ", DUMP_PREFIX_NONE, st->data, 10); for (i = 0; i < d->props.rc.legacy.rc_map_size; i++) { - if (rc5_custom(&keymap[i]) == st->data[1]) { + if (rc5_custom(&keymap[i]) == code) { *event = keymap[i].keycode; *state = REMOTE_KEY_PRESSED; -- cgit v1.2.3 From d3d076aaa7d8a028ae4617f57c14727b473f848d Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 21 Jan 2012 12:20:30 -0300 Subject: [media] az6007: Convert IR to use the rc_core logic Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/az6007.c | 30 +++++++----------------------- 1 file changed, 7 insertions(+), 23 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/dvb-usb/az6007.c b/drivers/media/dvb/dvb-usb/az6007.c index a8aedb87ae69..2288916a2a4a 100644 --- a/drivers/media/dvb/dvb-usb/az6007.c +++ b/drivers/media/dvb/dvb-usb/az6007.c @@ -192,26 +192,16 @@ static int az6007_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) return az6007_write(d, 0xbc, onoff, 0, NULL, 0); } -/* keys for the enclosed remote control */ -static struct rc_map_table rc_map_az6007_table[] = { - {0x0001, KEY_1}, - {0x0002, KEY_2}, -}; - /* remote control stuff (does not work with my box) */ -static int az6007_rc_query(struct dvb_usb_device *d, u32 * event, int *state) +static int az6007_rc_query(struct dvb_usb_device *d) { struct az6007_device_state *st = d->priv; - struct rc_map_table *keymap = d->props.rc.legacy.rc_map_table; - int i; unsigned code = 0; az6007_read(d, AZ6007_READ_IR, 0, 0, st->data, 10); - if (st->data[1] == 0x44) { - *state = REMOTE_NO_KEY_PRESSED; + if (st->data[1] == 0x44) return 0; - } if ((st->data[1] ^ st->data[2]) == 0xff) code = st->data[1]; @@ -224,16 +214,9 @@ static int az6007_rc_query(struct dvb_usb_device *d, u32 * event, int *state) code = code << 16 | st->data[3] << 8| st->data[4]; printk("remote query key: %04x\n", code); - print_hex_dump_bytes("Remote: ", DUMP_PREFIX_NONE, st->data, 10); - for (i = 0; i < d->props.rc.legacy.rc_map_size; i++) { - if (rc5_custom(&keymap[i]) == code) { - *event = keymap[i].keycode; - *state = REMOTE_KEY_PRESSED; + rc_keydown(d->rc_dev, code, st->data[5]); - return 0; - } - } return 0; } @@ -536,11 +519,12 @@ static struct dvb_usb_device_properties az6007_properties = { .power_ctrl = az6007_power_ctrl, .read_mac_address = az6007_read_mac_addr, - .rc.legacy = { - .rc_map_table = rc_map_az6007_table, - .rc_map_size = ARRAY_SIZE(rc_map_az6007_table), + .rc.core = { .rc_interval = 400, + .rc_codes = RC_MAP_DIB0700_NEC_TABLE, + .module_name = "az6007", .rc_query = az6007_rc_query, + .allowed_protos = RC_TYPE_NEC, }, .i2c_algo = &az6007_i2c_algo, -- cgit v1.2.3 From 083995477d45ae087d3c4f99cf8ae95b9de84019 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 21 Jan 2012 12:41:21 -0300 Subject: [media] az6007: Use the right keycode for Terratec H7 Instead of using a fake keycode, just for testing, use the right one, for Terratec H7. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/az6007.c | 2 +- .../media/rc/keymaps/rc-nec-terratec-cinergy-xs.c | 52 ++++++++++++++++++++++ 2 files changed, 53 insertions(+), 1 deletion(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/dvb-usb/az6007.c b/drivers/media/dvb/dvb-usb/az6007.c index 2288916a2a4a..14733b84e8b8 100644 --- a/drivers/media/dvb/dvb-usb/az6007.c +++ b/drivers/media/dvb/dvb-usb/az6007.c @@ -521,7 +521,7 @@ static struct dvb_usb_device_properties az6007_properties = { .rc.core = { .rc_interval = 400, - .rc_codes = RC_MAP_DIB0700_NEC_TABLE, + .rc_codes = RC_MAP_NEC_TERRATEC_CINERGY_XS, .module_name = "az6007", .rc_query = az6007_rc_query, .allowed_protos = RC_TYPE_NEC, diff --git a/drivers/media/rc/keymaps/rc-nec-terratec-cinergy-xs.c b/drivers/media/rc/keymaps/rc-nec-terratec-cinergy-xs.c index f3b86c8db679..8d4dae2e2ece 100644 --- a/drivers/media/rc/keymaps/rc-nec-terratec-cinergy-xs.c +++ b/drivers/media/rc/keymaps/rc-nec-terratec-cinergy-xs.c @@ -18,6 +18,8 @@ */ static struct rc_map_table nec_terratec_cinergy_xs[] = { + + /* Terratec Grey IR, with most keys in orange */ { 0x1441, KEY_HOME}, { 0x1401, KEY_POWER2}, @@ -78,6 +80,56 @@ static struct rc_map_table nec_terratec_cinergy_xs[] = { { 0x144e, KEY_REWIND}, { 0x144f, KEY_FASTFORWARD}, { 0x145c, KEY_NEXT}, + + /* Terratec Black IR, with most keys in black */ + { 0x04eb01, KEY_POWER2}, + + { 0x04eb02, KEY_1}, + { 0x04eb03, KEY_2}, + { 0x04eb04, KEY_3}, + { 0x04eb05, KEY_4}, + { 0x04eb06, KEY_5}, + { 0x04eb07, KEY_6}, + { 0x04eb08, KEY_7}, + { 0x04eb09, KEY_8}, + { 0x04eb0a, KEY_9}, + { 0x04eb0c, KEY_0}, + + { 0x04eb0b, KEY_TEXT}, /* TXT */ + { 0x04eb0d, KEY_REFRESH}, /* Refresh */ + + { 0x04eb0e, KEY_HOME}, + { 0x04eb0f, KEY_EPG}, + + { 0x04eb10, KEY_UP}, + { 0x04eb11, KEY_LEFT}, + { 0x04eb12, KEY_OK}, + { 0x04eb13, KEY_RIGHT}, + { 0x04eb14, KEY_DOWN}, + + { 0x04eb15, KEY_BACKSPACE}, + { 0x04eb16, KEY_INFO}, + + { 0x04eb17, KEY_RED}, + { 0x04eb18, KEY_GREEN}, + { 0x04eb19, KEY_YELLOW}, + { 0x04eb1a, KEY_BLUE}, + + { 0x04eb1c, KEY_VOLUMEUP}, + { 0x04eb1e, KEY_VOLUMEDOWN}, + + { 0x04eb1d, KEY_MUTE}, + + { 0x04eb1b, KEY_CHANNELUP}, + { 0x04eb1f, KEY_CHANNELDOWN}, + + { 0x04eb40, KEY_RECORD}, + { 0x04eb4c, KEY_PLAY}, + { 0x04eb58, KEY_PAUSE}, + + { 0x04eb54, KEY_REWIND}, + { 0x04eb48, KEY_STOP}, + { 0x04eb5c, KEY_NEXT}, }; static struct rc_map_list nec_terratec_cinergy_xs_map = { -- cgit v1.2.3 From 44744f9b982049da0f89c560d91bd2549aedf0a0 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 21 Jul 2011 18:33:26 -0300 Subject: [media] az6007: Enable the driver at the building system Add the corresponding entries to allow building this driver. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/Kconfig | 8 ++++++++ drivers/media/dvb/dvb-usb/Makefile | 4 +++- 2 files changed, 11 insertions(+), 1 deletion(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/dvb-usb/Kconfig b/drivers/media/dvb/dvb-usb/Kconfig index 9f203c6767a6..e894bad6538e 100644 --- a/drivers/media/dvb/dvb-usb/Kconfig +++ b/drivers/media/dvb/dvb-usb/Kconfig @@ -361,6 +361,14 @@ config DVB_USB_EC168 help Say Y here to support the E3C EC168 DVB-T USB2.0 receiver. +config DVB_USB_AZ6007 + tristate "AzureWave 6007 and clones DVB-T/C USB2.0 support" + depends on DVB_USB + select DVB_DRXK if !DVB_FE_CUSTOMISE + select MEDIA_TUNER_MT2063 if !DVB_FE_CUSTOMISE + help + Say Y here to support theAfatech AF9005 based DVB-T/DVB-C receivers. + config DVB_USB_AZ6027 tristate "Azurewave DVB-S/S2 USB2.0 AZ6027 support" depends on DVB_USB diff --git a/drivers/media/dvb/dvb-usb/Makefile b/drivers/media/dvb/dvb-usb/Makefile index 26c8b9e57050..d9549cb27698 100644 --- a/drivers/media/dvb/dvb-usb/Makefile +++ b/drivers/media/dvb/dvb-usb/Makefile @@ -54,7 +54,6 @@ obj-$(CONFIG_DVB_USB_DIB0700) += dvb-usb-dib0700.o dvb-usb-opera-objs = opera1.o obj-$(CONFIG_DVB_USB_OPERA1) += dvb-usb-opera.o - dvb-usb-af9005-objs = af9005.o af9005-fe.o obj-$(CONFIG_DVB_USB_AF9005) += dvb-usb-af9005.o @@ -88,6 +87,9 @@ obj-$(CONFIG_DVB_USB_FRIIO) += dvb-usb-friio.o dvb-usb-ec168-objs = ec168.o obj-$(CONFIG_DVB_USB_EC168) += dvb-usb-ec168.o +dvb-usb-az6007-objs = az6007.o +obj-$(CONFIG_DVB_USB_AZ6007) += dvb-usb-az6007.o + dvb-usb-az6027-objs = az6027.o obj-$(CONFIG_DVB_USB_AZ6027) += dvb-usb-az6027.o -- cgit v1.2.3 From 9e5e3097a3febbf317abc6d1b07bc6c33b20c279 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 21 Jan 2012 13:52:39 -0200 Subject: [media] az6007: CodingStyle fixes Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/az6007.c | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/dvb-usb/az6007.c b/drivers/media/dvb/dvb-usb/az6007.c index 14733b84e8b8..02efd94dc72b 100644 --- a/drivers/media/dvb/dvb-usb/az6007.c +++ b/drivers/media/dvb/dvb-usb/az6007.c @@ -211,9 +211,7 @@ static int az6007_rc_query(struct dvb_usb_device *d) if ((st->data[3] ^ st->data[4]) == 0xff) code = code << 8 | st->data[3]; else - code = code << 16 | st->data[3] << 8| st->data[4]; - - printk("remote query key: %04x\n", code); + code = code << 16 | st->data[3] << 8 | st->data[4]; rc_keydown(d->rc_dev, code, st->data[5]); @@ -302,11 +300,11 @@ int az6007_power_ctrl(struct dvb_usb_device *d, int onoff) ret = az6007_write(d, FX2_SCON1, 0, 3, NULL, 0); if (ret < 0) return ret; - msleep (150); + msleep(150); ret = az6007_write(d, FX2_SCON1, 1, 3, NULL, 0); if (ret < 0) return ret; - msleep (430); + msleep(430); ret = az6007_write(d, AZ6007_POWER, 0, 0, NULL, 0); if (ret < 0) return ret; @@ -362,8 +360,8 @@ static int az6007_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], 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); + 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]; @@ -391,10 +389,11 @@ static int az6007_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], for (j = 0; j < len; j++) { st->data[j] = msgs[i].buf[j + 1]; if (dvb_usb_az6007_debug & 2) - printk(KERN_CONT "0x%02x ", st->data[j]); + printk(KERN_CONT "0x%02x ", + st->data[j]); } - ret = __az6007_write(d->udev, req, value, index, st->data, - length); + ret = __az6007_write(d->udev, req, value, index, + st->data, length); } else { /* read bytes */ if (dvb_usb_az6007_debug & 2) @@ -406,8 +405,8 @@ static int az6007_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], value = addr; length = msgs[i].len + 6; len = msgs[i].len; - ret = __az6007_read(d->udev, req, value, index, st->data, - length); + 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 (dvb_usb_az6007_debug & 2) @@ -466,7 +465,7 @@ int az6007_identify_state(struct usb_device *udev, __az6007_write(udev, 0x00, 0, 0, NULL, 0); } - deb_info("Device is on %s state\n", *cold? "warm" : "cold"); + deb_info("Device is on %s state\n", *cold ? "warm" : "cold"); return 0; } @@ -514,7 +513,7 @@ static struct dvb_usb_device_properties az6007_properties = { } } }, - }} + } } } }, .power_ctrl = az6007_power_ctrl, .read_mac_address = az6007_read_mac_addr, -- cgit v1.2.3 From aa104b2fea3ced2a562c480448a2f346c3ab61f4 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 23 Jan 2012 13:15:22 -0200 Subject: [media] cinergyT2-fe: Fix bandwdith settings Changeset 7830bbaff9f mangled the bandwidth field for CinergyT2. Properly fill it. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/cinergyT2-fe.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/dvb-usb/cinergyT2-fe.c b/drivers/media/dvb/dvb-usb/cinergyT2-fe.c index 8a57ed8272de..1efc028a76c9 100644 --- a/drivers/media/dvb/dvb-usb/cinergyT2-fe.c +++ b/drivers/media/dvb/dvb-usb/cinergyT2-fe.c @@ -276,14 +276,15 @@ static int cinergyt2_fe_set_frontend(struct dvb_frontend *fe) param.flags = 0; switch (fep->bandwidth_hz) { + default: case 8000000: - param.bandwidth = 0; + param.bandwidth = 8; break; case 7000000: - param.bandwidth = 1; + param.bandwidth = 7; break; case 6000000: - param.bandwidth = 2; + param.bandwidth = 6; break; } -- cgit v1.2.3 From a8ea0218625699a5c635655a17b565bab5888ea1 Mon Sep 17 00:00:00 2001 From: Malcolm Priestley Date: Fri, 20 Jan 2012 19:07:18 -0300 Subject: [media] it913x v1.23 use it913x_config.chip_ver to select firmware As recommended by Jason at ITE, the chip version should select firmware. However, to continue to support IT9137 firmware with different configuration the driver will use udev->descriptor.idVendor to select the difference between IT9135 and IT9137. Signed-off-by: Malcolm Priestley Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/it913x.c | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/dvb-usb/it913x.c b/drivers/media/dvb/dvb-usb/it913x.c index 9f01cd7a6e3f..50d578c7b8c8 100644 --- a/drivers/media/dvb/dvb-usb/it913x.c +++ b/drivers/media/dvb/dvb-usb/it913x.c @@ -388,19 +388,12 @@ static int ite_firmware_select(struct usb_device *udev, { int sw; /* auto switch */ - if (le16_to_cpu(udev->descriptor.idProduct) == - USB_PID_ITETECH_IT9135) - sw = IT9135_V1_FW; - else if (le16_to_cpu(udev->descriptor.idProduct) == - USB_PID_ITETECH_IT9135_9005) + if (le16_to_cpu(udev->descriptor.idVendor) == USB_VID_KWORLD_2) + sw = IT9137_FW; + else if (it913x_config.chip_ver == 1) sw = IT9135_V1_FW; - else if (le16_to_cpu(udev->descriptor.idProduct) == - USB_PID_ITETECH_IT9135_9006) { + else sw = IT9135_V2_FW; - if (it913x_config.tuner_id_0 == 0) - it913x_config.tuner_id_0 = IT9135_60; - } else - sw = IT9137_FW; /* force switch */ if (dvb_usb_it913x_firmware != IT9135_AUTO) @@ -416,6 +409,8 @@ static int ite_firmware_select(struct usb_device *udev, it913x_config.firmware_ver = 1; it913x_config.adc_x2 = 1; props->firmware = fw_it9135_v2; + if (it913x_config.tuner_id_0 == 0) + it913x_config.tuner_id_0 = IT9135_60; break; case IT9137_FW: default: @@ -823,5 +818,5 @@ module_usb_driver(it913x_driver); MODULE_AUTHOR("Malcolm Priestley "); MODULE_DESCRIPTION("it913x USB 2 Driver"); -MODULE_VERSION("1.22"); +MODULE_VERSION("1.23"); MODULE_LICENSE("GPL"); -- cgit v1.2.3 From cf427952adcee0210e64b77ae7de9c8f256cce5c Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Sat, 21 Jan 2012 11:19:29 -0300 Subject: [media] anysee: repeat failed USB control messages Control message load increased heavily after CI/CAM support due to dvb_ca_en50221. It looks like CI/CAM drops to non-working state easily after error is returned to its callbacks. Due to that, add some logic to avoid errors repeating failed messages. Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/anysee.c | 38 ++++++++++++++++++++++++++++++++------ 1 file changed, 32 insertions(+), 6 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/dvb-usb/anysee.c b/drivers/media/dvb/dvb-usb/anysee.c index cf0c318d6989..03c28655af1b 100644 --- a/drivers/media/dvb/dvb-usb/anysee.c +++ b/drivers/media/dvb/dvb-usb/anysee.c @@ -58,7 +58,7 @@ static int anysee_ctrl_msg(struct dvb_usb_device *d, u8 *sbuf, u8 slen, u8 *rbuf, u8 rlen) { struct anysee_state *state = d->priv; - int act_len, ret; + int act_len, ret, i; u8 buf[64]; memcpy(&buf[0], sbuf, slen); @@ -73,26 +73,52 @@ static int anysee_ctrl_msg(struct dvb_usb_device *d, u8 *sbuf, u8 slen, /* We need receive one message more after dvb_usb_generic_rw due to weird transaction flow, which is 1 x send + 2 x receive. */ ret = dvb_usb_generic_rw(d, buf, sizeof(buf), buf, sizeof(buf), 0); - if (!ret) { + if (ret) + goto error_unlock; + + /* TODO FIXME: dvb_usb_generic_rw() fails rarely with error code -32 + * (EPIPE, Broken pipe). Function supports currently msleep() as a + * parameter but I would not like to use it, since according to + * Documentation/timers/timers-howto.txt it should not be used such + * short, under < 20ms, sleeps. Repeating failed message would be + * better choice as not to add unwanted delays... + * Fixing that correctly is one of those or both; + * 1) use repeat if possible + * 2) add suitable delay + */ + + /* get answer, retry few times if error returned */ + for (i = 0; i < 3; i++) { /* receive 2nd answer */ ret = usb_bulk_msg(d->udev, usb_rcvbulkpipe(d->udev, d->props.generic_bulk_ctrl_endpoint), buf, sizeof(buf), &act_len, 2000); - if (ret) - err("%s: recv bulk message failed: %d", __func__, ret); - else { + + if (ret) { + deb_info("%s: recv bulk message failed: %d", + __func__, ret); + } else { deb_xfer("<<< "); debug_dump(buf, rlen, deb_xfer); if (buf[63] != 0x4f) deb_info("%s: cmd failed\n", __func__); + + break; } } + if (ret) { + /* all retries failed, it is fatal */ + err("%s: recv bulk message failed: %d", __func__, ret); + goto error_unlock; + } + /* read request, copy returned data to return buf */ - if (!ret && rbuf && rlen) + if (rbuf && rlen) memcpy(rbuf, buf, rlen); +error_unlock: mutex_unlock(&anysee_usb_mutex); return ret; -- cgit v1.2.3 From e4b444369c75604ef6e656969039b1c6b4ca61c5 Mon Sep 17 00:00:00 2001 From: Jesper Juhl Date: Mon, 23 Jan 2012 18:45:58 -0300 Subject: [media] drxk_hard: does not need to include linux/version.h This patch removes the unneeded include. Signed-off-by: Jesper Juhl Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/drxk_hard.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/frontends/drxk_hard.c b/drivers/media/dvb/frontends/drxk_hard.c index 5fa192731fcd..47bf16d44bc4 100644 --- a/drivers/media/dvb/frontends/drxk_hard.c +++ b/drivers/media/dvb/frontends/drxk_hard.c @@ -28,7 +28,6 @@ #include #include #include -#include #include #include "dvb_frontend.h" -- cgit v1.2.3 From 260a8f7b06c9f8fba20bea7cd76281a533241076 Mon Sep 17 00:00:00 2001 From: Jose Alberto Reguero Date: Thu, 26 Jan 2012 20:02:52 -0300 Subject: [media] az6007: add another Terratec H7 usb id Signed-off-by: Jose Alberto Reguero Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/az6007.c | 3 ++- drivers/media/dvb/dvb-usb/dvb-usb-ids.h | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/dvb-usb/az6007.c b/drivers/media/dvb/dvb-usb/az6007.c index 02efd94dc72b..df4cbc0ed932 100644 --- a/drivers/media/dvb/dvb-usb/az6007.c +++ b/drivers/media/dvb/dvb-usb/az6007.c @@ -481,6 +481,7 @@ static int az6007_usb_probe(struct usb_interface *intf, static struct usb_device_id az6007_usb_table[] = { {USB_DEVICE(USB_VID_AZUREWAVE, USB_PID_AZUREWAVE_6007)}, {USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_H7)}, + {USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_H7_2)}, {0}, }; @@ -534,7 +535,7 @@ static struct dvb_usb_device_properties az6007_properties = { .warm_ids = { NULL }, }, { .name = "TerraTec DTV StarBox DVB-T/C USB2.0 (az6007)", - .cold_ids = { &az6007_usb_table[1], NULL }, + .cold_ids = { &az6007_usb_table[1], &az6007_usb_table[2], NULL }, .warm_ids = { NULL }, }, { NULL }, diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h index b3e7be4718a6..9c3dae100160 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h +++ b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h @@ -228,6 +228,7 @@ #define USB_PID_TERRATEC_CINERGY_T_XXS 0x0078 #define USB_PID_TERRATEC_CINERGY_T_XXS_2 0x00ab #define USB_PID_TERRATEC_H7 0x10b4 +#define USB_PID_TERRATEC_H7_2 0x10a3 #define USB_PID_TERRATEC_T3 0x10a0 #define USB_PID_TERRATEC_T5 0x10a1 #define USB_PID_PINNACLE_EXPRESSCARD_320CX 0x022e -- cgit v1.2.3 From 0d616ca37108289b59b02191377261d12d3ae3e7 Mon Sep 17 00:00:00 2001 From: Masanari Iida Date: Fri, 27 Jan 2012 09:47:04 -0300 Subject: [media] [trivial] lmedm04: Fix typo Correct spelling "reseting" to "resetting" in drivers/media/dvb/dvb-usb/lmedm04.c Signed-off-by: Masanari Iida Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/lmedm04.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/dvb-usb/lmedm04.c b/drivers/media/dvb/dvb-usb/lmedm04.c index b3fe05bbffc9..291f6b110399 100644 --- a/drivers/media/dvb/dvb-usb/lmedm04.c +++ b/drivers/media/dvb/dvb-usb/lmedm04.c @@ -1054,7 +1054,7 @@ static int dm04_lme2510_tuner(struct dvb_usb_adapter *adap) if (ret) info("TUN Found %s tuner", tun_msg[ret]); else { - info("TUN No tuner found --- reseting device"); + info("TUN No tuner found --- resetting device"); lme_coldreset(adap->dev->udev); return -ENODEV; } -- cgit v1.2.3 From dc66d7f455988310ce2dbd4a0df23af2e5626a89 Mon Sep 17 00:00:00 2001 From: Jose Alberto Reguero Date: Fri, 27 Jan 2012 18:34:49 -0300 Subject: [media] drxk: Fix get_tune_settings for DVB-T DVB-T also use step_size=0. Signed-off-by: Jose Alberto Reguero Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/drxk_hard.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/frontends/drxk_hard.c b/drivers/media/dvb/frontends/drxk_hard.c index 47bf16d44bc4..36d11756492f 100644 --- a/drivers/media/dvb/frontends/drxk_hard.c +++ b/drivers/media/dvb/frontends/drxk_hard.c @@ -6316,15 +6316,12 @@ static int drxk_get_tune_settings(struct dvb_frontend *fe, struct dvb_frontend_t switch (p->delivery_system) { case SYS_DVBC_ANNEX_A: case SYS_DVBC_ANNEX_C: + case SYS_DVBT: sets->min_delay_ms = 3000; sets->max_drift = 0; sets->step_size = 0; return 0; default: - /* - * For DVB-T, let it use the default DVB core way, that is: - * fepriv->step_size = fe->ops.info.frequency_stepsize * 2 - */ return -EINVAL; } } -- cgit v1.2.3 From fc594e3e5196d4cf7ace7735eeca399f7a80868b Mon Sep 17 00:00:00 2001 From: Malcolm Priestley Date: Sat, 28 Jan 2012 18:02:34 -0300 Subject: [media] it913x ver 1.24 Make 0x60 default on version 2 devices Some version 2 devices have different tuner IDs. ID 0x38 appears to have weak signal strength. Apply default 0x60 to unknown IDs. Signed-off-by: Malcolm Priestley Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/it913x.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/dvb-usb/it913x.c b/drivers/media/dvb/dvb-usb/it913x.c index 50d578c7b8c8..c80098ad34ab 100644 --- a/drivers/media/dvb/dvb-usb/it913x.c +++ b/drivers/media/dvb/dvb-usb/it913x.c @@ -409,8 +409,15 @@ static int ite_firmware_select(struct usb_device *udev, it913x_config.firmware_ver = 1; it913x_config.adc_x2 = 1; props->firmware = fw_it9135_v2; - if (it913x_config.tuner_id_0 == 0) + switch (it913x_config.tuner_id_0) { + case IT9135_61: + case IT9135_62: + break; + default: + info("Unknown tuner ID applying default 0x60"); + case IT9135_60: it913x_config.tuner_id_0 = IT9135_60; + } break; case IT9137_FW: default: @@ -818,5 +825,5 @@ module_usb_driver(it913x_driver); MODULE_AUTHOR("Malcolm Priestley "); MODULE_DESCRIPTION("it913x USB 2 Driver"); -MODULE_VERSION("1.23"); +MODULE_VERSION("1.24"); MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 85eeece773a6f0d2ba00958782995cbe68218256 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 15 Dec 2011 10:33:26 -0300 Subject: [media] cx18/ddbridge: remove unused headers The cx18 and ddbridge drivers include linux/dvb/audio.h and video.h without using them. Remove those includes. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/ddbridge/ddbridge.h | 2 -- drivers/media/video/cx18/cx18-driver.h | 2 -- 2 files changed, 4 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/ddbridge/ddbridge.h b/drivers/media/dvb/ddbridge/ddbridge.h index 6d14893218f4..8b1b41d2a52d 100644 --- a/drivers/media/dvb/ddbridge/ddbridge.h +++ b/drivers/media/dvb/ddbridge/ddbridge.h @@ -32,8 +32,6 @@ #include #include #include -#include -#include #include #include "dmxdev.h" diff --git a/drivers/media/video/cx18/cx18-driver.h b/drivers/media/video/cx18/cx18-driver.h index b9a94fc5146d..7a37e0ee136f 100644 --- a/drivers/media/video/cx18/cx18-driver.h +++ b/drivers/media/video/cx18/cx18-driver.h @@ -44,8 +44,6 @@ #include #include -#include -#include #include #include #include -- cgit v1.2.3 From 3691a0dd3a3e53d4b74c7a412f7e58929b65584e Mon Sep 17 00:00:00 2001 From: Malcolm Priestley Date: Wed, 1 Feb 2012 18:27:42 -0300 Subject: [media] it913x v1.25 support different for remotes Support for different types of remote. ITE remotes share common device IDs with differently assigned keys. Two versions of remote maps have been created there are likely to be more. v1 for all other IDs v2 for USB_PID_ITETECH_IT9135_9005. This patch also separates the configuration parts from it913x_identify_state function. TODO remotes for HID interfaces. Signed-off-by: Malcolm Priestley Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/it913x.c | 104 +++++++++++++++++++++++++++++-------- 1 file changed, 82 insertions(+), 22 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/dvb-usb/it913x.c b/drivers/media/dvb/dvb-usb/it913x.c index c80098ad34ab..2560652763cf 100644 --- a/drivers/media/dvb/dvb-usb/it913x.c +++ b/drivers/media/dvb/dvb-usb/it913x.c @@ -429,24 +429,74 @@ static int ite_firmware_select(struct usb_device *udev, return 0; } +static void it913x_select_remote(struct usb_device *udev, + struct dvb_usb_device_properties *props) +{ + switch (le16_to_cpu(udev->descriptor.idProduct)) { + case USB_PID_ITETECH_IT9135_9005: + props->rc.core.rc_codes = RC_MAP_IT913X_V2; + return; + default: + props->rc.core.rc_codes = RC_MAP_IT913X_V1; + } + return; +} + #define TS_MPEG_PKT_SIZE 188 #define EP_LOW 21 #define TS_BUFFER_SIZE_PID (EP_LOW*TS_MPEG_PKT_SIZE) #define EP_HIGH 348 #define TS_BUFFER_SIZE_MAX (EP_HIGH*TS_MPEG_PKT_SIZE) -static int it913x_identify_state(struct usb_device *udev, - struct dvb_usb_device_properties *props, - struct dvb_usb_device_description **desc, - int *cold) +static int it913x_select_config(struct usb_device *udev, + struct dvb_usb_device_properties *props) { - int ret = 0, firm_no; - u8 reg, remote; + int ret = 0, reg; + bool proprietary_ir = false; - firm_no = it913x_return_status(udev); + if (it913x_config.chip_ver == 0x02 + && it913x_config.chip_type == 0x9135) + reg = it913x_read_reg(udev, 0x461d); + else + reg = it913x_read_reg(udev, 0x461b); + + if (reg < 0) + return reg; + + if (reg == 0) { + it913x_config.dual_mode = 0; + it913x_config.tuner_id_0 = IT9135_38; + proprietary_ir = true; + } else { + /* TS mode */ + reg = it913x_read_reg(udev, 0x49c5); + if (reg < 0) + return reg; + it913x_config.dual_mode = reg; + + /* IR mode type */ + reg = it913x_read_reg(udev, 0x49ac); + if (reg < 0) + return reg; + if (reg == 5) { + info("Remote propriety (raw) mode"); + proprietary_ir = true; + } else if (reg == 1) { + info("Remote HID mode NOT SUPPORTED"); + proprietary_ir = false; + props->rc.core.rc_codes = NULL; + } else + props->rc.core.rc_codes = NULL; + + /* Tuner_id */ + reg = it913x_read_reg(udev, 0x49d0); + if (reg < 0) + return reg; + it913x_config.tuner_id_0 = reg; + } - /* checnk for dual mode */ - it913x_config.dual_mode = it913x_read_reg(udev, 0x49c5); + if (proprietary_ir) + it913x_select_remote(udev, props); if (udev->speed != USB_SPEED_HIGH) { props->adapter[0].fe[0].pid_filter_count = 5; @@ -461,17 +511,6 @@ static int it913x_identify_state(struct usb_device *udev, if(props->adapter[0].fe[0].pid_filter_count == 5) props->adapter[0].fe[0].pid_filter_count = 31; - /* TODO different remotes */ - remote = it913x_read_reg(udev, 0x49ac); /* Remote */ - if (remote == 0) - props->rc.core.rc_codes = NULL; - - /* TODO at the moment tuner_id is always assigned to 0x38 */ - it913x_config.tuner_id_0 = it913x_read_reg(udev, 0x49d0); - - info("Dual mode=%x Remote=%x Tuner Type=%x", it913x_config.dual_mode - , remote, it913x_config.tuner_id_0); - /* Select Stream Buffer Size and pid filter option*/ if (pid_filter) { props->adapter[0].fe[0].stream.u.bulk.buffersize = @@ -492,8 +531,29 @@ static int it913x_identify_state(struct usb_device *udev, } else props->num_adapters = 1; + info("Dual mode=%x Tuner Type=%x", it913x_config.dual_mode, + it913x_config.tuner_id_0); + ret = ite_firmware_select(udev, props); + return ret; +} + +static int it913x_identify_state(struct usb_device *udev, + struct dvb_usb_device_properties *props, + struct dvb_usb_device_description **desc, + int *cold) +{ + int ret = 0, firm_no; + u8 reg; + + firm_no = it913x_return_status(udev); + + /* Read and select config */ + ret = it913x_select_config(udev, props); + if (ret < 0) + return ret; + if (firm_no > 0) { *cold = 0; return 0; @@ -791,7 +851,7 @@ static struct dvb_usb_device_properties it913x_properties = { .rc_query = it913x_rc_query, .rc_interval = IT913X_POLL, .allowed_protos = RC_TYPE_NEC, - .rc_codes = RC_MAP_MSI_DIGIVOX_III, + .rc_codes = RC_MAP_IT913X_V1, }, .i2c_algo = &it913x_i2c_algo, .num_device_descs = 5, @@ -825,5 +885,5 @@ module_usb_driver(it913x_driver); MODULE_AUTHOR("Malcolm Priestley "); MODULE_DESCRIPTION("it913x USB 2 Driver"); -MODULE_VERSION("1.24"); +MODULE_VERSION("1.25"); MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 546c9736288e50d29feb204065b71f03c3461f86 Mon Sep 17 00:00:00 2001 From: Masanari Iida Date: Fri, 3 Feb 2012 09:56:59 -0300 Subject: [media] [trivial] frontends: Fix typo in tda1004x.c Correct spelling "alocate" to "allocate" in drivers/media/dvb/frontends/tda1004x.c Signed-off-by: Masanari Iida Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/tda1004x.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/frontends/tda1004x.c b/drivers/media/dvb/frontends/tda1004x.c index ae6f22aae677..35d72b46aa1e 100644 --- a/drivers/media/dvb/frontends/tda1004x.c +++ b/drivers/media/dvb/frontends/tda1004x.c @@ -1272,7 +1272,7 @@ struct dvb_frontend* tda10045_attach(const struct tda1004x_config* config, /* allocate memory for the internal state */ state = kzalloc(sizeof(struct tda1004x_state), GFP_KERNEL); if (!state) { - printk(KERN_ERR "Can't alocate memory for tda10045 state\n"); + printk(KERN_ERR "Can't allocate memory for tda10045 state\n"); return NULL; } @@ -1342,7 +1342,7 @@ struct dvb_frontend* tda10046_attach(const struct tda1004x_config* config, /* allocate memory for the internal state */ state = kzalloc(sizeof(struct tda1004x_state), GFP_KERNEL); if (!state) { - printk(KERN_ERR "Can't alocate memory for tda10046 state\n"); + printk(KERN_ERR "Can't allocate memory for tda10046 state\n"); return NULL; } -- cgit v1.2.3 From 45145b67f5895ff92207cffd74e65460a87920b2 Mon Sep 17 00:00:00 2001 From: Simon Arlott Date: Mon, 6 Feb 2012 17:57:01 -0300 Subject: [media] dvb-core: fix DVBFE_ALGO_HW retune bug Commit 7e07222 breaks DVBFE_ALGO_HW tuning after a retune is requested, which causes bad tuning on my TBS 6920. [ 0.769091] pci 0000:06:00.0: [14f1:8852] type 0 class 0x000400 [ 19.733530] CORE cx23885[0]: subsystem: 6920:8888, board: TurboSight TBS 6920 [card=14,autodetected] [ 762.824912] cx24116_load_firmware: FW version 1.23.86.1 7e0722215a510921cbb73ab4c37477d4dcb91bf8 [media] dvb-core: Don't pass DVBv3 parameters on tune() fops Although re_tune is set to true when FESTATE_RETUNE occurs, it is never set back to false which the old code used to do when !FESTATE_RETUNE. This patch sets re_tune to false if !(state & FESTATE_RETUNE). $ szap-s2 -a 2 "Channel 5" reading channels from file '/home/simon/.szap/channels.conf' zapping to 247 'Channel 5': delivery DVB-S, modulation QPSK sat 0, frequency 10964 MHz H, symbolrate 22000000, coderate 5/6, rolloff 0.35 vpid 0x092a, apid 0x092b, sid 0x092d using '/dev/dvb/adapter2/frontend0' and '/dev/dvb/adapter2/demux0' status 1f | signal cf40 | snr 0000 | ber 00000000 | unc 00000000 | FE_HAS_LOCK status 1f | signal cf40 | snr eccd | ber 00000000 | unc 00000000 | FE_HAS_LOCK status 1f | signal cf40 | snr 0000 | ber 00000000 | unc 00000000 | FE_HAS_LOCK status 1f | signal cf40 | snr 0000 | ber 00000000 | unc 00000000 | FE_HAS_LOCK status 1f | signal cf40 | snr eccd | ber 00000000 | unc 00000000 | FE_HAS_LOCK status 1f | signal cf40 | snr 0000 | ber 00000000 | unc 00000000 | FE_HAS_LOCK status 1f | signal cf40 | snr 0000 | ber 00000000 | unc 00000000 | FE_HAS_LOCK status 1f | signal cf40 | snr eb33 | ber 00000000 | unc 00000000 | FE_HAS_LOCK status 1f | signal cf40 | snr eccd | ber 00000000 | unc 00000000 | FE_HAS_LOCK status 1f | signal cf40 | snr eccd | ber 00000000 | unc 00000000 | FE_HAS_LOCK status 1f | signal cf40 | snr 0000 | ber 00000000 | unc 00000000 | FE_HAS_LOCK status 1f | signal cf40 | snr eccd | ber 00000000 | unc 00000000 | FE_HAS_LOCK status 1f | signal cf40 | snr eccd | ber 00000000 | unc 00000000 | FE_HAS_LOCK status 1f | signal cf40 | snr 0000 | ber 00000000 | unc 00000000 | FE_HAS_LOCK status 1f | signal cec0 | snr eccd | ber 00000000 | unc 00000000 | FE_HAS_LOCK status 1f | signal cec0 | snr 0000 | ber 00000000 | unc 00000000 | FE_HAS_LOCK Signed-off-by: Simon Arlott Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-core/dvb_frontend.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c index fbbe545a74cb..4555baa383b2 100644 --- a/drivers/media/dvb/dvb-core/dvb_frontend.c +++ b/drivers/media/dvb/dvb-core/dvb_frontend.c @@ -655,6 +655,8 @@ restart: dprintk("%s: Retune requested, FESTATE_RETUNE\n", __func__); re_tune = true; fepriv->state = FESTATE_TUNED; + } else { + re_tune = false; } if (fe->ops.tune) -- cgit v1.2.3 From 88495030dc53cd97d4c71937b959e8c67ed27ed7 Mon Sep 17 00:00:00 2001 From: Malcolm Priestley Date: Mon, 6 Feb 2012 19:05:01 -0300 Subject: [media] lmedm04 ver 1.96 Turn off PID filter by default Problems with the PID setting stalling demux on applications like VDR and MythTV. The PID filter is now defaulted to OFF. Signed-off-by: Malcolm Priestley Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/lmedm04.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/dvb-usb/lmedm04.c b/drivers/media/dvb/dvb-usb/lmedm04.c index 291f6b110399..c33134c5d514 100644 --- a/drivers/media/dvb/dvb-usb/lmedm04.c +++ b/drivers/media/dvb/dvb-usb/lmedm04.c @@ -104,8 +104,7 @@ MODULE_PARM_DESC(firmware, "set default firmware 0=Sharp7395 1=LG"); static int pid_filter; module_param_named(pid, pid_filter, int, 0644); -MODULE_PARM_DESC(pid, "set default 0=on 1=off"); - +MODULE_PARM_DESC(pid, "set default 0=default 1=off 2=on"); DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); @@ -653,7 +652,7 @@ static int lme2510_identify_state(struct usb_device *udev, struct dvb_usb_device_description **desc, int *cold) { - if (pid_filter > 0) + if (pid_filter != 2) props->adapter[0].fe[0].caps &= ~DVB_USB_ADAP_NEED_PID_FILTERING; *cold = 0; @@ -1295,5 +1294,5 @@ module_usb_driver(lme2510_driver); MODULE_AUTHOR("Malcolm Priestley "); MODULE_DESCRIPTION("LME2510(C) DVB-S USB2.0"); -MODULE_VERSION("1.91"); +MODULE_VERSION("1.96"); MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 9a56ec5b0327e292a725bec7f6db069ecc72b2db Mon Sep 17 00:00:00 2001 From: Masanari Iida Date: Wed, 8 Feb 2012 07:28:23 -0300 Subject: [media] [trivial] mantis: Fix typo in mantis_hif.c Correct typo "Adater" to "Adapter" in drivers/media/dvb/mantis/mantis_hif.c Signed-off-by: Masanari Iida Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_hif.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/mantis/mantis_hif.c b/drivers/media/dvb/mantis/mantis_hif.c index 672cf4d2462d..10c68df7e16f 100644 --- a/drivers/media/dvb/mantis/mantis_hif.c +++ b/drivers/media/dvb/mantis/mantis_hif.c @@ -76,7 +76,7 @@ static int mantis_hif_write_wait(struct mantis_ca *ca) udelay(500); timeout++; if (timeout > 100) { - dprintk(MANTIS_ERROR, 1, "Adater(%d) Slot(0): Write operation timed out!", mantis->num); + dprintk(MANTIS_ERROR, 1, "Adapter(%d) Slot(0): Write operation timed out!", mantis->num); rc = -ETIMEDOUT; break; } -- cgit v1.2.3 From c0adca734013389ac81513da546947e75d95151a Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Fri, 8 Jul 2011 23:34:09 -0300 Subject: [media] Realtek RTL2830 DVB-T demodulator driver Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/Kconfig | 7 + drivers/media/dvb/frontends/Makefile | 1 + drivers/media/dvb/frontends/rtl2830.c | 514 +++++++++++++++++++++++++++++ drivers/media/dvb/frontends/rtl2830.h | 97 ++++++ drivers/media/dvb/frontends/rtl2830_priv.h | 53 +++ 5 files changed, 672 insertions(+) create mode 100644 drivers/media/dvb/frontends/rtl2830.c create mode 100644 drivers/media/dvb/frontends/rtl2830.h create mode 100644 drivers/media/dvb/frontends/rtl2830_priv.h (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig index ebb5ed7a7783..2995204c3355 100644 --- a/drivers/media/dvb/frontends/Kconfig +++ b/drivers/media/dvb/frontends/Kconfig @@ -425,6 +425,13 @@ config DVB_CXD2820R help Say Y when you want to support this frontend. +config DVB_RTL2830 + tristate "Realtek RTL2830 DVB-T" + depends on DVB_CORE && I2C + default m if DVB_FE_CUSTOMISE + help + Say Y when you want to support this frontend. + comment "DVB-C (cable) frontends" depends on DVB_CORE diff --git a/drivers/media/dvb/frontends/Makefile b/drivers/media/dvb/frontends/Makefile index 00a20636df62..7f85e64cdcb1 100644 --- a/drivers/media/dvb/frontends/Makefile +++ b/drivers/media/dvb/frontends/Makefile @@ -96,4 +96,5 @@ obj-$(CONFIG_DVB_TDA18271C2DD) += tda18271c2dd.o obj-$(CONFIG_DVB_IT913X_FE) += it913x-fe.o obj-$(CONFIG_DVB_A8293) += a8293.o obj-$(CONFIG_DVB_TDA10071) += tda10071.o +obj-$(CONFIG_DVB_RTL2830) += rtl2830.o diff --git a/drivers/media/dvb/frontends/rtl2830.c b/drivers/media/dvb/frontends/rtl2830.c new file mode 100644 index 000000000000..37a9fa29874e --- /dev/null +++ b/drivers/media/dvb/frontends/rtl2830.c @@ -0,0 +1,514 @@ +/* + * Realtek RTL2830 DVB-T demodulator driver + * + * Copyright (C) 2011 Antti Palosaari + * + * 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; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + + +/* + * Driver implements own I2C-adapter for tuner I2C access. That's since chip + * have unusual I2C-gate control which closes gate automatically after each + * I2C transfer. Using own I2C adapter we can workaround that. + */ + +#include "rtl2830_priv.h" + +int rtl2830_debug; +module_param_named(debug, rtl2830_debug, int, 0644); +MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off)."); + +/* write multiple registers */ +static int rtl2830_wr_regs(struct rtl2830_priv *priv, u16 reg, u8 *val, int len) +{ + int ret; + u8 buf[2+len]; + struct i2c_msg msg[1] = { + { + .addr = priv->cfg.i2c_addr, + .flags = 0, + .len = sizeof(buf), + .buf = buf, + } + }; + + buf[0] = (reg >> 8) & 0xff; + buf[1] = (reg >> 0) & 0xff; + memcpy(&buf[2], val, len); + + ret = i2c_transfer(priv->i2c, msg, 1); + if (ret == 1) { + ret = 0; + } else { + warn("i2c wr failed=%d reg=%04x len=%d", ret, reg, len); + ret = -EREMOTEIO; + } + return ret; +} + +/* read multiple registers */ +static int rtl2830_rd_regs(struct rtl2830_priv *priv, u16 reg, u8 *val, int len) +{ + int ret; + u8 buf[2]; + struct i2c_msg msg[2] = { + { + .addr = priv->cfg.i2c_addr, + .flags = 0, + .len = sizeof(buf), + .buf = buf, + }, { + .addr = priv->cfg.i2c_addr, + .flags = I2C_M_RD, + .len = len, + .buf = val, + } + }; + + buf[0] = (reg >> 8) & 0xff; + buf[1] = (reg >> 0) & 0xff; + + ret = i2c_transfer(priv->i2c, msg, 2); + if (ret == 2) { + ret = 0; + } else { + warn("i2c rd failed=%d reg=%04x len=%d", ret, reg, len); + ret = -EREMOTEIO; + } + return ret; +} + +#if 0 /* currently not used */ +/* write single register */ +static int rtl2830_wr_reg(struct rtl2830_priv *priv, u16 reg, u8 val) +{ + return rtl2830_wr_regs(priv, reg, &val, 1); +} +#endif + +/* read single register */ +static int rtl2830_rd_reg(struct rtl2830_priv *priv, u16 reg, u8 *val) +{ + return rtl2830_rd_regs(priv, reg, val, 1); +} + +/* write single register with mask */ +int rtl2830_wr_reg_mask(struct rtl2830_priv *priv, u16 reg, u8 val, u8 mask) +{ + int ret; + u8 tmp; + + /* no need for read if whole reg is written */ + if (mask != 0xff) { + ret = rtl2830_rd_regs(priv, reg, &tmp, 1); + if (ret) + return ret; + + val &= mask; + tmp &= ~mask; + val |= tmp; + } + + return rtl2830_wr_regs(priv, reg, &val, 1); +} + +/* read single register with mask */ +int rtl2830_rd_reg_mask(struct rtl2830_priv *priv, u16 reg, u8 *val, u8 mask) +{ + int ret, i; + u8 tmp; + + ret = rtl2830_rd_regs(priv, reg, &tmp, 1); + if (ret) + return ret; + + tmp &= mask; + + /* find position of the first bit */ + for (i = 0; i < 8; i++) { + if ((mask >> i) & 0x01) + break; + } + *val = tmp >> i; + + return 0; +} + +static int rtl2830_init(struct dvb_frontend *fe) +{ + struct rtl2830_priv *priv = fe->demodulator_priv; + int ret, i; + u64 num; + u8 buf[3], tmp; + u32 if_ctl; + struct rtl2830_reg_val_mask tab[] = { + { 0x00d, 0x01, 0x03 }, + { 0x00d, 0x10, 0x10 }, + { 0x104, 0x00, 0x1e }, + { 0x105, 0x80, 0x80 }, + { 0x110, 0x02, 0x03 }, + { 0x110, 0x08, 0x0c }, + { 0x17b, 0x00, 0x40 }, + { 0x17d, 0x05, 0x0f }, + { 0x17d, 0x50, 0xf0 }, + { 0x18c, 0x08, 0x0f }, + { 0x18d, 0x00, 0xc0 }, + { 0x188, 0x05, 0x0f }, + { 0x189, 0x00, 0xfc }, + { 0x2d5, 0x02, 0x02 }, + { 0x2f1, 0x02, 0x06 }, + { 0x2f1, 0x20, 0xf8 }, + { 0x16d, 0x00, 0x01 }, + { 0x1a6, 0x00, 0x80 }, + { 0x106, priv->cfg.vtop, 0x3f }, + { 0x107, priv->cfg.krf, 0x3f }, + { 0x112, 0x28, 0xff }, + { 0x103, priv->cfg.agc_targ_val, 0xff }, + { 0x00a, 0x02, 0x07 }, + { 0x140, 0x0c, 0x3c }, + { 0x140, 0x40, 0xc0 }, + { 0x15b, 0x05, 0x07 }, + { 0x15b, 0x28, 0x38 }, + { 0x15c, 0x05, 0x07 }, + { 0x15c, 0x28, 0x38 }, + { 0x115, priv->cfg.spec_inv, 0x01 }, + { 0x16f, 0x01, 0x07 }, + { 0x170, 0x18, 0x38 }, + { 0x172, 0x0f, 0x0f }, + { 0x173, 0x08, 0x38 }, + { 0x175, 0x01, 0x07 }, + { 0x176, 0x00, 0xc0 }, + }; + + for (i = 0; i < ARRAY_SIZE(tab); i++) { + ret = rtl2830_wr_reg_mask(priv, tab[i].reg, tab[i].val, + tab[i].mask); + if (ret) + goto err; + } + + ret = rtl2830_wr_regs(priv, 0x18f, "\x28\x00", 2); + if (ret) + goto err; + + ret = rtl2830_wr_regs(priv, 0x195, + "\x04\x06\x0a\x12\x0a\x12\x1e\x28", 8); + if (ret) + goto err; + + num = priv->cfg.if_dvbt % priv->cfg.xtal; + num *= 0x400000; + num /= priv->cfg.xtal; + num = -num; + if_ctl = num & 0x3fffff; + dbg("%s: if_ctl=%08x", __func__, if_ctl); + + ret = rtl2830_rd_reg_mask(priv, 0x119, &tmp, 0xc0); /* b[7:6] */ + if (ret) + goto err; + + buf[0] = tmp << 6; + buf[0] = (if_ctl >> 16) & 0x3f; + buf[1] = (if_ctl >> 8) & 0xff; + buf[2] = (if_ctl >> 0) & 0xff; + + ret = rtl2830_wr_regs(priv, 0x119, buf, 3); + if (ret) + goto err; + + /* TODO: spec init */ + + /* soft reset */ + ret = rtl2830_wr_reg_mask(priv, 0x101, 0x04, 0x04); + if (ret) + goto err; + + ret = rtl2830_wr_reg_mask(priv, 0x101, 0x00, 0x04); + if (ret) + goto err; + + return ret; +err: + dbg("%s: failed=%d", __func__, ret); + return ret; +} + +int rtl2830_get_tune_settings(struct dvb_frontend *fe, + struct dvb_frontend_tune_settings *s) +{ + s->min_delay_ms = 500; + s->step_size = fe->ops.info.frequency_stepsize * 2; + s->max_drift = (fe->ops.info.frequency_stepsize * 2) + 1; + + return 0; +} + +static int rtl2830_set_frontend(struct dvb_frontend *fe) +{ + struct rtl2830_priv *priv = fe->demodulator_priv; + struct dtv_frontend_properties *c = &fe->dtv_property_cache; + int ret, i; + static u8 bw_params1[3][34] = { + { + 0x1f, 0xf0, 0x1f, 0xf0, 0x1f, 0xfa, 0x00, 0x17, 0x00, 0x41, + 0x00, 0x64, 0x00, 0x67, 0x00, 0x38, 0x1f, 0xde, 0x1f, 0x7a, + 0x1f, 0x47, 0x1f, 0x7c, 0x00, 0x30, 0x01, 0x4b, 0x02, 0x82, + 0x03, 0x73, 0x03, 0xcf, /* 6 MHz */ + }, { + 0x1f, 0xfa, 0x1f, 0xda, 0x1f, 0xc1, 0x1f, 0xb3, 0x1f, 0xca, + 0x00, 0x07, 0x00, 0x4d, 0x00, 0x6d, 0x00, 0x40, 0x1f, 0xca, + 0x1f, 0x4d, 0x1f, 0x2a, 0x1f, 0xb2, 0x00, 0xec, 0x02, 0x7e, + 0x03, 0xd0, 0x04, 0x53, /* 7 MHz */ + }, { + 0x00, 0x10, 0x00, 0x0e, 0x1f, 0xf7, 0x1f, 0xc9, 0x1f, 0xa0, + 0x1f, 0xa6, 0x1f, 0xec, 0x00, 0x4e, 0x00, 0x7d, 0x00, 0x3a, + 0x1f, 0x98, 0x1f, 0x10, 0x1f, 0x40, 0x00, 0x75, 0x02, 0x5f, + 0x04, 0x24, 0x04, 0xdb, /* 8 MHz */ + }, + }; + static u8 bw_params2[3][6] = { + {0xc3, 0x0c, 0x44, 0x33, 0x33, 0x30,}, /* 6 MHz */ + {0xb8, 0xe3, 0x93, 0x99, 0x99, 0x98,}, /* 7 MHz */ + {0xae, 0xba, 0xf3, 0x26, 0x66, 0x64,}, /* 8 MHz */ + }; + + + dbg("%s: frequency=%d bandwidth_hz=%d inversion=%d", __func__, + c->frequency, c->bandwidth_hz, c->inversion); + + /* program tuner */ + if (fe->ops.tuner_ops.set_params) + fe->ops.tuner_ops.set_params(fe); + + switch (c->bandwidth_hz) { + case 6000000: + i = 0; + break; + case 7000000: + i = 1; + break; + case 8000000: + i = 2; + break; + default: + dbg("invalid bandwidth"); + return -EINVAL; + } + + ret = rtl2830_wr_reg_mask(priv, 0x008, i << 1, 0x06); + if (ret) + goto err; + + /* 1/2 split I2C write */ + ret = rtl2830_wr_regs(priv, 0x11c, &bw_params1[i][0], 17); + if (ret) + goto err; + + /* 2/2 split I2C write */ + ret = rtl2830_wr_regs(priv, 0x12d, &bw_params1[i][17], 17); + if (ret) + goto err; + + ret = rtl2830_wr_regs(priv, 0x19d, bw_params2[i], 6); + if (ret) + goto err; + + return ret; +err: + dbg("%s: failed=%d", __func__, ret); + return ret; +} + +static int rtl2830_read_status(struct dvb_frontend *fe, fe_status_t *status) +{ + struct rtl2830_priv *priv = fe->demodulator_priv; + int ret; + u8 tmp; + *status = 0; + + ret = rtl2830_rd_reg_mask(priv, 0x351, &tmp, 0x78); /* [6:3] */ + if (ret) + goto err; + + if (tmp == 11) { + *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER | + FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK; + } else if (tmp == 10) { + *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER | + FE_HAS_VITERBI; + } + + return ret; +err: + dbg("%s: failed=%d", __func__, ret); + return ret; +} + +static int rtl2830_read_snr(struct dvb_frontend *fe, u16 *snr) +{ + *snr = 0; + return 0; +} + +static int rtl2830_read_ber(struct dvb_frontend *fe, u32 *ber) +{ + *ber = 0; + return 0; +} + +static int rtl2830_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) +{ + *ucblocks = 0; + return 0; +} + +static int rtl2830_read_signal_strength(struct dvb_frontend *fe, u16 *strength) +{ + *strength = 0; + return 0; +} + +static struct dvb_frontend_ops rtl2830_ops; + +static u32 rtl2830_tuner_i2c_func(struct i2c_adapter *adapter) +{ + return I2C_FUNC_I2C; +} + +static int rtl2830_tuner_i2c_xfer(struct i2c_adapter *i2c_adap, + struct i2c_msg msg[], int num) +{ + struct rtl2830_priv *priv = i2c_get_adapdata(i2c_adap); + int ret; + + /* open i2c-gate */ + ret = rtl2830_wr_reg_mask(priv, 0x101, 0x08, 0x08); + if (ret) + goto err; + + ret = i2c_transfer(priv->i2c, msg, num); + if (ret < 0) + warn("tuner i2c failed=%d", ret); + + return ret; +err: + dbg("%s: failed=%d", __func__, ret); + return ret; +} + +static struct i2c_algorithm rtl2830_tuner_i2c_algo = { + .master_xfer = rtl2830_tuner_i2c_xfer, + .functionality = rtl2830_tuner_i2c_func, +}; + +struct i2c_adapter *rtl2830_get_tuner_i2c_adapter(struct dvb_frontend *fe) +{ + struct rtl2830_priv *priv = fe->demodulator_priv; + return &priv->tuner_i2c_adapter; +} +EXPORT_SYMBOL(rtl2830_get_tuner_i2c_adapter); + +static void rtl2830_release(struct dvb_frontend *fe) +{ + struct rtl2830_priv *priv = fe->demodulator_priv; + + i2c_del_adapter(&priv->tuner_i2c_adapter); + kfree(priv); +} + +struct dvb_frontend *rtl2830_attach(const struct rtl2830_config *cfg, + struct i2c_adapter *i2c) +{ + struct rtl2830_priv *priv = NULL; + int ret = 0; + u8 tmp; + + /* allocate memory for the internal state */ + priv = kzalloc(sizeof(struct rtl2830_priv), GFP_KERNEL); + if (priv == NULL) + goto err; + + /* setup the priv */ + priv->i2c = i2c; + memcpy(&priv->cfg, cfg, sizeof(struct rtl2830_config)); + + /* check if the demod is there */ + ret = rtl2830_rd_reg(priv, 0x000, &tmp); + if (ret) + goto err; + + /* create dvb_frontend */ + memcpy(&priv->fe.ops, &rtl2830_ops, sizeof(struct dvb_frontend_ops)); + priv->fe.demodulator_priv = priv; + + /* create tuner i2c adapter */ + strlcpy(priv->tuner_i2c_adapter.name, "RTL2830 tuner I2C adapter", + sizeof(priv->tuner_i2c_adapter.name)); + priv->tuner_i2c_adapter.algo = &rtl2830_tuner_i2c_algo; + priv->tuner_i2c_adapter.algo_data = NULL; + i2c_set_adapdata(&priv->tuner_i2c_adapter, priv); + if (i2c_add_adapter(&priv->tuner_i2c_adapter) < 0) { + err("tuner I2C bus could not be initialized"); + goto err; + } + + return &priv->fe; +err: + dbg("%s: failed=%d", __func__, ret); + kfree(priv); + return NULL; +} +EXPORT_SYMBOL(rtl2830_attach); + +static struct dvb_frontend_ops rtl2830_ops = { + .delsys = { SYS_DVBT }, + .info = { + .name = "Realtek RTL2830 (DVB-T)", + .caps = FE_CAN_FEC_1_2 | + FE_CAN_FEC_2_3 | + FE_CAN_FEC_3_4 | + FE_CAN_FEC_5_6 | + FE_CAN_FEC_7_8 | + FE_CAN_FEC_AUTO | + FE_CAN_QPSK | + FE_CAN_QAM_16 | + FE_CAN_QAM_64 | + FE_CAN_QAM_AUTO | + FE_CAN_TRANSMISSION_MODE_AUTO | + FE_CAN_GUARD_INTERVAL_AUTO | + FE_CAN_HIERARCHY_AUTO | + FE_CAN_RECOVER | + FE_CAN_MUTE_TS + }, + + .release = rtl2830_release, + + .init = rtl2830_init, + + .get_tune_settings = rtl2830_get_tune_settings, + + .set_frontend = rtl2830_set_frontend, + + .read_status = rtl2830_read_status, + .read_snr = rtl2830_read_snr, + .read_ber = rtl2830_read_ber, + .read_ucblocks = rtl2830_read_ucblocks, + .read_signal_strength = rtl2830_read_signal_strength, +}; + +MODULE_AUTHOR("Antti Palosaari "); +MODULE_DESCRIPTION("Realtek RTL2830 DVB-T demodulator driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/media/dvb/frontends/rtl2830.h b/drivers/media/dvb/frontends/rtl2830.h new file mode 100644 index 000000000000..1c6ee91749c2 --- /dev/null +++ b/drivers/media/dvb/frontends/rtl2830.h @@ -0,0 +1,97 @@ +/* + * Realtek RTL2830 DVB-T demodulator driver + * + * Copyright (C) 2011 Antti Palosaari + * + * 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; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef RTL2830_H +#define RTL2830_H + +#include + +struct rtl2830_config { + /* + * Demodulator I2C address. + */ + u8 i2c_addr; + + /* + * Xtal frequency. + * Hz + * 4000000, 16000000, 25000000, 28800000 + */ + u32 xtal; + + /* + * TS output mode. + */ + u8 ts_mode; + + /* + * Spectrum inversion. + */ + bool spec_inv; + + /* + * IFs for all used modes. + * Hz + * 4570000, 4571429, 36000000, 36125000, 36166667, 44000000 + */ + u32 if_dvbt; + + /* + */ + u8 vtop; + + /* + */ + u8 krf; + + /* + */ + u8 agc_targ_val; +}; + +#if defined(CONFIG_DVB_RTL2830) || \ + (defined(CONFIG_DVB_RTL2830_MODULE) && defined(MODULE)) +extern struct dvb_frontend *rtl2830_attach( + const struct rtl2830_config *config, + struct i2c_adapter *i2c +); + +extern struct i2c_adapter *rtl2830_get_tuner_i2c_adapter( + struct dvb_frontend *fe +); +#else +static inline struct dvb_frontend *rtl2830_attach( + const struct rtl2830_config *config, + struct i2c_adapter *i2c +) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); + return NULL; +} + +static inline struct i2c_adapter *rtl2830_get_tuner_i2c_adapter( + struct dvb_frontend *fe +) +{ + return NULL; +} +#endif + +#endif /* RTL2830_H */ diff --git a/drivers/media/dvb/frontends/rtl2830_priv.h b/drivers/media/dvb/frontends/rtl2830_priv.h new file mode 100644 index 000000000000..2bc662ee87a0 --- /dev/null +++ b/drivers/media/dvb/frontends/rtl2830_priv.h @@ -0,0 +1,53 @@ +/* + * Realtek RTL2830 DVB-T demodulator driver + * + * Copyright (C) 2011 Antti Palosaari + * + * 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; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef RTL2830_PRIV_H +#define RTL2830_PRIV_H + +#include "dvb_frontend.h" +#include "rtl2830.h" + +#define LOG_PREFIX "rtl2830" + +#undef dbg +#define dbg(f, arg...) \ + if (rtl2830_debug) \ + printk(KERN_INFO LOG_PREFIX": " f "\n" , ## arg) +#undef err +#define err(f, arg...) printk(KERN_ERR LOG_PREFIX": " f "\n" , ## arg) +#undef info +#define info(f, arg...) printk(KERN_INFO LOG_PREFIX": " f "\n" , ## arg) +#undef warn +#define warn(f, arg...) printk(KERN_WARNING LOG_PREFIX": " f "\n" , ## arg) + +struct rtl2830_priv { + struct i2c_adapter *i2c; + struct dvb_frontend fe; + struct rtl2830_config cfg; + struct i2c_adapter tuner_i2c_adapter; +}; + +struct rtl2830_reg_val_mask { + u16 reg; + u8 val; + u8 mask; +}; + +#endif /* RTL2830_PRIV_H */ -- cgit v1.2.3 From 831e0b718c8d28afe6c9c9c2fcaebb5a730201ed Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Fri, 8 Jul 2011 23:36:07 -0300 Subject: [media] Realtek RTL28xxU serie DVB USB interface driver For now it supports only Realtek RTL2831U chip. RTL2831U is integrated DVB USB interface and DVB-T demod. DVB-T demod integrated to RTL2831U is Realtek RTL2830. Supported tuners are QT1010, MT2060 and MXL5005S. Signed-off-by: Antti Palosaari [mchehab@redhat.com: fix a small typo] Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/Kconfig | 10 + drivers/media/dvb/dvb-usb/Makefile | 3 + drivers/media/dvb/dvb-usb/rtl28xxu.c | 709 +++++++++++++++++++++++++++++++++++ drivers/media/dvb/dvb-usb/rtl28xxu.h | 210 +++++++++++ 4 files changed, 932 insertions(+) create mode 100644 drivers/media/dvb/dvb-usb/rtl28xxu.c create mode 100644 drivers/media/dvb/dvb-usb/rtl28xxu.h (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/dvb-usb/Kconfig b/drivers/media/dvb/dvb-usb/Kconfig index e894bad6538e..615429274516 100644 --- a/drivers/media/dvb/dvb-usb/Kconfig +++ b/drivers/media/dvb/dvb-usb/Kconfig @@ -411,3 +411,13 @@ config DVB_USB_MXL111SF select VIDEO_TVEEPROM help Say Y here to support the MxL111SF USB2.0 DTV receiver. + +config DVB_USB_RTL28XXU + tristate "Realtek RTL28xxU DVB USB support" + depends on DVB_USB && EXPERIMENTAL + select DVB_RTL2830 + select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMISE + select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMISE + select MEDIA_TUNER_MXL5005S if !MEDIA_TUNER_CUSTOMISE + help + Say Y here to support the Realtek RTL28xxU DVB USB receiver. diff --git a/drivers/media/dvb/dvb-usb/Makefile b/drivers/media/dvb/dvb-usb/Makefile index d9549cb27698..7e476cb49334 100644 --- a/drivers/media/dvb/dvb-usb/Makefile +++ b/drivers/media/dvb/dvb-usb/Makefile @@ -107,6 +107,9 @@ obj-$(CONFIG_DVB_USB_MXL111SF) += dvb-usb-mxl111sf.o obj-$(CONFIG_DVB_USB_MXL111SF) += mxl111sf-demod.o obj-$(CONFIG_DVB_USB_MXL111SF) += mxl111sf-tuner.o +dvb-usb-rtl28xxu-objs = rtl28xxu.o +obj-$(CONFIG_DVB_USB_RTL28XXU) += dvb-usb-rtl28xxu.o + ccflags-y += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/ # due to tuner-xc3028 ccflags-y += -Idrivers/media/common/tuners diff --git a/drivers/media/dvb/dvb-usb/rtl28xxu.c b/drivers/media/dvb/dvb-usb/rtl28xxu.c new file mode 100644 index 000000000000..e7b1811e3567 --- /dev/null +++ b/drivers/media/dvb/dvb-usb/rtl28xxu.c @@ -0,0 +1,709 @@ +/* + * Realtek RTL28xxU DVB USB driver + * + * Copyright (C) 2009 Antti Palosaari + * Copyright (C) 2011 Antti Palosaari + * + * 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; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "rtl28xxu.h" + +#include "rtl2830.h" + +#include "qt1010.h" +#include "mt2060.h" +#include "mxl5005s.h" + +/* debug */ +static int dvb_usb_rtl28xxu_debug; +module_param_named(debug, dvb_usb_rtl28xxu_debug, int, 0644); +MODULE_PARM_DESC(debug, "set debugging level" DVB_USB_DEBUG_STATUS); +DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); + +static int rtl28xxu_ctrl_msg(struct dvb_usb_device *d, struct rtl28xxu_req *req) +{ + int ret; + unsigned int pipe; + u8 requesttype; + u8 *buf; + + buf = kmalloc(req->size, GFP_KERNEL); + if (!buf) { + ret = -ENOMEM; + goto err; + } + + if (req->index & CMD_WR_FLAG) { + /* write */ + memcpy(buf, req->data, req->size); + requesttype = (USB_TYPE_VENDOR | USB_DIR_OUT); + pipe = usb_sndctrlpipe(d->udev, 0); + } else { + /* read */ + requesttype = (USB_TYPE_VENDOR | USB_DIR_IN); + pipe = usb_rcvctrlpipe(d->udev, 0); + } + + ret = usb_control_msg(d->udev, pipe, 0, requesttype, req->value, + req->index, buf, req->size, 1000); + + deb_dump(0, requesttype, req->value, req->index, buf, req->size, + deb_xfer); + + if (ret < 0) + goto err_dealloc; + else + ret = 0; + + /* read request, copy returned data to return buf */ + if (!ret && requesttype == (USB_TYPE_VENDOR | USB_DIR_IN)) + memcpy(req->data, buf, req->size); + + kfree(buf); + return ret; + +err_dealloc: + kfree(buf); +err: + deb_info("%s: failed=%d\n", __func__, ret); + return ret; +} + +static int rtl2831_wr_regs(struct dvb_usb_device *d, u16 reg, u8 *val, int len) +{ + struct rtl28xxu_req req; + + if (reg < 0x3000) + req.index = CMD_USB_WR; + else + req.index = CMD_SYS_WR; + + req.value = reg; + req.size = len; + req.data = val; + + return rtl28xxu_ctrl_msg(d, &req); +} + +static int rtl2831_rd_regs(struct dvb_usb_device *d, u16 reg, u8 *val, int len) +{ + struct rtl28xxu_req req; + + if (reg < 0x3000) + req.index = CMD_USB_RD; + else + req.index = CMD_SYS_RD; + + req.value = reg; + req.size = len; + req.data = val; + + return rtl28xxu_ctrl_msg(d, &req); +} + +static int rtl2831_wr_reg(struct dvb_usb_device *d, u16 reg, u8 val) +{ + return rtl2831_wr_regs(d, reg, &val, 1); +} + +static int rtl2831_rd_reg(struct dvb_usb_device *d, u16 reg, u8 *val) +{ + return rtl2831_rd_regs(d, reg, val, 1); +} + +/* I2C */ +static int rtl28xxu_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], + int num) +{ + int ret; + struct dvb_usb_device *d = i2c_get_adapdata(adap); + struct rtl28xxu_req req; + + /* + * It is not known which are real I2C bus xfer limits, but testing + * with RTL2831U + MT2060 gives max RD 24 and max WR 22 bytes. + */ + + if (mutex_lock_interruptible(&d->i2c_mutex) < 0) + return -EAGAIN; + + if (num == 2 && !(msg[0].flags & I2C_M_RD) && + (msg[1].flags & I2C_M_RD)) { + if (msg[0].len > 2 || msg[1].len > 24) { + ret = -EOPNOTSUPP; + goto err_unlock; + } + if (msg[0].addr == 0x10) { + /* integrated demod */ + req.value = (msg[0].buf[1] << 8) | (msg[0].addr << 1); + req.index = CMD_DEMOD_RD | msg[0].buf[0]; + req.size = msg[1].len; + req.data = &msg[1].buf[0]; + ret = rtl28xxu_ctrl_msg(d, &req); + } else { + /* real I2C */ + req.value = (msg[0].buf[0] << 8) | (msg[0].addr << 1); + req.index = CMD_I2C_RD; + req.size = msg[1].len; + req.data = &msg[1].buf[0]; + ret = rtl28xxu_ctrl_msg(d, &req); + } + } else if (num == 1 && !(msg[0].flags & I2C_M_RD)) { + if (msg[0].len > 22) { + ret = -EOPNOTSUPP; + goto err_unlock; + } + if (msg[0].addr == 0x10) { + /* integrated demod */ + req.value = (msg[0].buf[1] << 8) | (msg[0].addr << 1); + req.index = CMD_DEMOD_WR | msg[0].buf[0]; + req.size = msg[0].len-2; + req.data = &msg[0].buf[2]; + ret = rtl28xxu_ctrl_msg(d, &req); + } else { + /* real I2C */ + req.value = (msg[0].buf[0] << 8) | (msg[0].addr << 1); + req.index = CMD_I2C_WR; + req.size = msg[0].len-1; + req.data = &msg[0].buf[1]; + ret = rtl28xxu_ctrl_msg(d, &req); + } + } else { + ret = -EINVAL; + } + +err_unlock: + mutex_unlock(&d->i2c_mutex); + + return ret ? ret : num; +} + +static u32 rtl28xxu_i2c_func(struct i2c_adapter *adapter) +{ + return I2C_FUNC_I2C; +} + +static struct i2c_algorithm rtl28xxu_i2c_algo = { + .master_xfer = rtl28xxu_i2c_xfer, + .functionality = rtl28xxu_i2c_func, +}; + +static struct rtl2830_config rtl28xxu_rtl2830_mt2060_config = { + .i2c_addr = 0x10, /* 0x20 */ + .xtal = 28800000, + .ts_mode = 0, + .spec_inv = 1, + .if_dvbt = 36150000, + .vtop = 0x20, + .krf = 0x04, + .agc_targ_val = 0x2d, + +}; + +static struct rtl2830_config rtl28xxu_rtl2830_qt1010_config = { + .i2c_addr = 0x10, /* 0x20 */ + .xtal = 28800000, + .ts_mode = 0, + .spec_inv = 1, + .if_dvbt = 36125000, + .vtop = 0x20, + .krf = 0x04, + .agc_targ_val = 0x2d, +}; + +static struct rtl2830_config rtl28xxu_rtl2830_mxl5005s_config = { + .i2c_addr = 0x10, /* 0x20 */ + .xtal = 28800000, + .ts_mode = 0, + .spec_inv = 0, + .if_dvbt = 4570000, + .vtop = 0x3f, + .krf = 0x04, + .agc_targ_val = 0x3e, +}; + +static int rtl28xxu_frontend_attach(struct dvb_usb_adapter *adap) +{ + int ret; + struct rtl28xxu_priv *priv = adap->dev->priv; + u8 buf[1]; + struct rtl2830_config *rtl2830_config; + /* for MT2060 tuner probe */ + struct rtl28xxu_req req_mt2060 = {0x00c0, CMD_I2C_RD, 1, buf}; + /* for QT1010 tuner probe */ + struct rtl28xxu_req req_qt1010 = {0x0fc4, CMD_I2C_RD, 1, buf}; + /* open RTL2831U/RTL2830 I2C gate */ + struct rtl28xxu_req req_gate = {0x0120, 0x0011, 0x0001, "\x08"}; + + deb_info("%s:\n", __func__); + + /* + * RTL2831U GPIOs + * ========================================================= + * GPIO0 | tuner#0 | 0 off | 1 on | MXL5005S (?) + * GPIO2 | LED | 0 off | 1 on | + * GPIO4 | tuner#1 | 0 on | 1 off | MT2060 + */ + + /* GPIO direction */ + ret = rtl2831_wr_reg(adap->dev, SYS_GPIO_DIR, 0x0a); + if (ret) + goto err; + + /* enable as output GPIO0, GPIO2, GPIO4 */ + ret = rtl2831_wr_reg(adap->dev, SYS_GPIO_OUT_EN, 0x15); + if (ret) + goto err; + + /* + * Probe used tuner. We need to know used tuner before demod attach + * since there is some demod params needed to set according to tuner. + */ + + /* open demod I2C gate */ + ret = rtl28xxu_ctrl_msg(adap->dev, &req_gate); + if (ret) + goto err; + + /* check QT1010 ID(?) register; reg=0f val=2c */ + ret = rtl28xxu_ctrl_msg(adap->dev, &req_qt1010); + if (ret == 0 && buf[0] == 0x2c) { + priv->tuner = TUNER_RTL2830_QT1010; + rtl2830_config = &rtl28xxu_rtl2830_qt1010_config; + deb_info("%s: QT1010\n", __func__); + goto found; + } else { + deb_info("%s: QT1010 probe failed=%d - %02x\n", + __func__, ret, buf[0]); + } + + /* open demod I2C gate */ + ret = rtl28xxu_ctrl_msg(adap->dev, &req_gate); + if (ret) + goto err; + + /* check MT2060 ID register; reg=00 val=63 */ + ret = rtl28xxu_ctrl_msg(adap->dev, &req_mt2060); + if (ret == 0 && buf[0] == 0x63) { + priv->tuner = TUNER_RTL2830_MT2060; + rtl2830_config = &rtl28xxu_rtl2830_mt2060_config; + deb_info("%s: MT2060\n", __func__); + goto found; + } else { + deb_info("%s: MT2060 probe failed=%d - %02x\n", + __func__, ret, buf[0]); + } + + /* assume MXL5005S */ + priv->tuner = TUNER_RTL2830_MXL5005S; + rtl2830_config = &rtl28xxu_rtl2830_mxl5005s_config; + deb_info("%s: MXL5005S\n", __func__); + goto found; + +found: + /* attach demodulator */ + adap->fe[0] = dvb_attach(rtl2830_attach, rtl2830_config, + &adap->dev->i2c_adap); + if (adap->fe[0] == NULL) { + ret = -ENODEV; + goto err; + } + + return ret; +err: + deb_info("%s: failed=%d\n", __func__, ret); + return ret; +} + +static struct qt1010_config rtl28xxu_qt1010_config = { + .i2c_address = 0x62, /* 0xc4 */ +}; + +static struct mt2060_config rtl28xxu_mt2060_config = { + .i2c_address = 0x60, /* 0xc0 */ + .clock_out = 0, +}; + +static struct mxl5005s_config rtl28xxu_mxl5005s_config = { + .i2c_address = 0x63, /* 0xc6 */ + .if_freq = IF_FREQ_4570000HZ, + .xtal_freq = CRYSTAL_FREQ_16000000HZ, + .agc_mode = MXL_SINGLE_AGC, + .tracking_filter = MXL_TF_C_H, + .rssi_enable = MXL_RSSI_ENABLE, + .cap_select = MXL_CAP_SEL_ENABLE, + .div_out = MXL_DIV_OUT_4, + .clock_out = MXL_CLOCK_OUT_DISABLE, + .output_load = MXL5005S_IF_OUTPUT_LOAD_200_OHM, + .top = MXL5005S_TOP_25P2, + .mod_mode = MXL_DIGITAL_MODE, + .if_mode = MXL_ZERO_IF, + .AgcMasterByte = 0x00, +}; + +static int rtl28xxu_tuner_attach(struct dvb_usb_adapter *adap) +{ + int ret; + struct rtl28xxu_priv *priv = adap->dev->priv; + struct i2c_adapter *rtl2830_tuner_i2c; + struct dvb_frontend *fe = NULL; + + deb_info("%s:\n", __func__); + + /* use rtl2830 driver I2C adapter, for more info see rtl2830 driver */ + rtl2830_tuner_i2c = rtl2830_get_tuner_i2c_adapter(adap->fe[0]); + + switch (priv->tuner) { + case TUNER_RTL2830_QT1010: + fe = dvb_attach(qt1010_attach, adap->fe[0], rtl2830_tuner_i2c, + &rtl28xxu_qt1010_config); + break; + case TUNER_RTL2830_MT2060: + fe = dvb_attach(mt2060_attach, adap->fe[0], rtl2830_tuner_i2c, + &rtl28xxu_mt2060_config, 1220); + break; + case TUNER_RTL2830_MXL5005S: + fe = dvb_attach(mxl5005s_attach, adap->fe[0], rtl2830_tuner_i2c, + &rtl28xxu_mxl5005s_config); + break; + default: + err("unknown tuner=%d", priv->tuner); + } + + if (fe == NULL) { + ret = -ENODEV; + goto err; + } + + return 0; +err: + deb_info("%s: failed=%d\n", __func__, ret); + return ret; +} + +static int rtl28xxu_streaming_ctrl(struct dvb_usb_adapter *adap , int onoff) +{ + int ret; + u8 buf[2], gpio; + + deb_info("%s: onoff=%d\n", __func__, onoff); + + ret = rtl2831_rd_reg(adap->dev, SYS_GPIO_OUT_VAL, &gpio); + if (ret) + goto err; + + if (onoff) { + buf[0] = 0x00; + buf[1] = 0x00; + gpio |= 0x04; /* LED on */ + } else { + buf[0] = 0x10; /* stall EPA */ + buf[1] = 0x02; /* reset EPA */ + gpio &= (~0x04); /* LED off */ + } + + ret = rtl2831_wr_reg(adap->dev, SYS_GPIO_OUT_VAL, gpio); + if (ret) + goto err; + + ret = rtl2831_wr_regs(adap->dev, USB_EPA_CTL, buf, 2); + if (ret) + goto err; + + return ret; +err: + deb_info("%s: failed=%d\n", __func__, ret); + return ret; +} + +static int rtl28xxu_power_ctrl(struct dvb_usb_device *d, int onoff) +{ + int ret; + u8 gpio, sys0; + + deb_info("%s: onoff=%d\n", __func__, onoff); + + /* demod adc */ + ret = rtl2831_rd_reg(d, SYS_SYS0, &sys0); + if (ret) + goto err; + + /* tuner power, read GPIOs */ + ret = rtl2831_rd_reg(d, SYS_GPIO_OUT_VAL, &gpio); + if (ret) + goto err; + + deb_info("%s: RD SYS0=%02x GPIO_OUT_VAL=%02x\n", __func__, sys0, gpio); + + if (onoff) { + gpio |= 0x01; /* GPIO0 = 1 */ + gpio &= (~0x10); /* GPIO4 = 0 */ + sys0 = sys0 & 0x0f; + sys0 |= 0xe0; + } else { + +#if 0 /* keep */ + /* + * FIXME: Use .fe_ioctl_override() to prevent demod + * IOCTLs in case of device is powered off. + * + * For now we cannot power off device because most FE IOCTLs + * can be performed only when device is powered. + * Using IOCTLs when device is powered off will result errors + * because register access to demod fails. + */ + gpio &= (~0x01); /* GPIO0 = 0 */ + gpio |= 0x10; /* GPIO4 = 1 */ + sys0 = sys0 & (~0xc0); +#endif + } + + deb_info("%s: WR SYS0=%02x GPIO_OUT_VAL=%02x\n", __func__, sys0, gpio); + + /* demod adc */ + ret = rtl2831_wr_reg(d, SYS_SYS0, sys0); + if (ret) + goto err; + + /* tuner power, write GPIOs */ + ret = rtl2831_wr_reg(d, SYS_GPIO_OUT_VAL, gpio); + if (ret) + goto err; + + return ret; +err: + deb_info("%s: failed=%d\n", __func__, ret); + return ret; +} + +static int rtl28xxu_rc_query(struct dvb_usb_device *d) +{ + int ret; + u8 buf[5]; + u32 rc_code; + + ret = rtl2831_rd_regs(d, SYS_IRRC_RP, buf, 5); + if (ret) + goto err; + + if (buf[4] & 0x01) { + if (buf[2] == (u8) ~buf[3]) { + if (buf[0] == (u8) ~buf[1]) { + /* NEC standard (16 bit) */ + rc_code = buf[0] << 8 | buf[2]; + } else { + /* NEC extended (24 bit) */ + rc_code = buf[0] << 16 | + buf[1] << 8 | buf[2]; + } + } else { + /* NEC full (32 bit) */ + rc_code = buf[0] << 24 | buf[1] << 16 | + buf[2] << 8 | buf[3]; + } + + rc_keydown(d->rc_dev, rc_code, 0); + + ret = rtl2831_wr_reg(d, SYS_IRRC_SR, 1); + if (ret) + goto err; + + /* repeated intentionally to avoid extra keypress */ + ret = rtl2831_wr_reg(d, SYS_IRRC_SR, 1); + if (ret) + goto err; + } + + return ret; +err: + deb_info("%s: failed=%d\n", __func__, ret); + return ret; +} + +/* DVB USB Driver stuff */ +#define USB_VID_REALTEK 0x0bda +#define USB_PID_RTL2831U 0x2831 +#define USB_PID_FREECOM 0x0160 + +#define RTL2831U_0BDA_2831 0 +#define RTL2831U_14AA_0160 1 + +static struct usb_device_id rtl28xxu_table[] = { + [RTL2831U_0BDA_2831] = { + USB_DEVICE(USB_VID_REALTEK, USB_PID_RTL2831U)}, + [RTL2831U_14AA_0160] = { + USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_FREECOM)}, + {} /* terminating entry */ +}; + +MODULE_DEVICE_TABLE(usb, rtl28xxu_table); + +static struct dvb_usb_device_properties rtl28xxu_properties[] = { + { + .caps = DVB_USB_IS_AN_I2C_ADAPTER, + + .usb_ctrl = DEVICE_SPECIFIC, + .no_reconnect = 1, + + .size_of_priv = sizeof(struct rtl28xxu_priv), + + .num_adapters = 1, + .adapter = { + { + .frontend_attach = rtl28xxu_frontend_attach, + .tuner_attach = rtl28xxu_tuner_attach, + .streaming_ctrl = rtl28xxu_streaming_ctrl, + .stream = { + .type = USB_BULK, + .count = 6, + .endpoint = 0x81, + .u = { + .bulk = { + .buffersize = 4096, + } + } + }, + } + }, + + .power_ctrl = rtl28xxu_power_ctrl, + + .rc.core = { + .protocol = RC_TYPE_NEC, + .module_name = "rtl28xxu", + .rc_query = rtl28xxu_rc_query, + .rc_interval = 400, + .allowed_protos = RC_TYPE_NEC, + .rc_codes = RC_MAP_EMPTY, + }, + + .i2c_algo = &rtl28xxu_i2c_algo, + + .num_device_descs = 2, + .devices = { + { + .name = "Realtek RTL2831U reference design", + .cold_ids = {NULL}, + .warm_ids = { + &rtl28xxu_table[RTL2831U_0BDA_2831], NULL}, + }, + { + .name = "Freecom USB2.0 DVB-T", + .cold_ids = {NULL}, + .warm_ids = { + &rtl28xxu_table[RTL2831U_14AA_0160], NULL}, + }, + } + }, +}; + +static int rtl28xxu_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + int ret, i; + int properties_count = ARRAY_SIZE(rtl28xxu_properties); + struct dvb_usb_device *d = NULL; + struct rtl28xxu_reg_val rc_nec_tab[] = { + { 0x3033, 0x80 }, + { 0x3020, 0x43 }, + { 0x3021, 0x16 }, + { 0x3022, 0x16 }, + { 0x3023, 0x5a }, + { 0x3024, 0x2d }, + { 0x3025, 0x16 }, + { 0x3026, 0x01 }, + { 0x3028, 0xb0 }, + { 0x3029, 0x04 }, + { 0x302c, 0x88 }, + { 0x302e, 0x13 }, + { 0x3030, 0xdf }, + { 0x3031, 0x05 }, + }; + + deb_info("%s: interface=%d\n", __func__, + intf->cur_altsetting->desc.bInterfaceNumber); + + if (intf->cur_altsetting->desc.bInterfaceNumber != 0) + return 0; + + for (i = 0; i < properties_count; i++) { + ret = dvb_usb_device_init(intf, &rtl28xxu_properties[i], + THIS_MODULE, &d, adapter_nr); + if (ret == 0 || ret != -ENODEV) + break; + } + + if (ret) + goto err; + + /* init USB endpoints */ + ret = rtl2831_wr_reg(d, USB_SYSCTL_0, 0x09); + if (ret) + goto err; + + ret = rtl2831_wr_regs(d, USB_EPA_MAXPKT, "\x00\x02\x00\x00", 4); + if (ret) + goto err; + + ret = rtl2831_wr_regs(d, USB_EPA_FIFO_CFG, "\x14\x00\x00\x00", 4); + if (ret) + goto err; + + /* init remote controller */ + for (i = 0; i < ARRAY_SIZE(rc_nec_tab); i++) { + ret = rtl2831_wr_reg(d, rc_nec_tab[i].reg, rc_nec_tab[i].val); + if (ret) + goto err; + } + + return ret; +err: + deb_info("%s: failed=%d\n", __func__, ret); + return ret; +} + +static struct usb_driver rtl28xxu_driver = { + .name = "dvb_usb_rtl28xxu", + .probe = rtl28xxu_probe, + .disconnect = dvb_usb_device_exit, + .id_table = rtl28xxu_table, +}; + +/* module stuff */ +static int __init rtl28xxu_module_init(void) +{ + int ret; + deb_info("%s:\n", __func__); + ret = usb_register(&rtl28xxu_driver); + if (ret) + err("usb_register failed=%d", ret); + + return ret; +} + +static void __exit rtl28xxu_module_exit(void) +{ + deb_info("%s:\n", __func__); + /* deregister this driver from the USB subsystem */ + usb_deregister(&rtl28xxu_driver); +} + +module_init(rtl28xxu_module_init); +module_exit(rtl28xxu_module_exit); + +MODULE_DESCRIPTION("Realtek RTL28xxU DVB USB driver"); +MODULE_AUTHOR("Antti Palosaari "); +MODULE_LICENSE("GPL"); diff --git a/drivers/media/dvb/dvb-usb/rtl28xxu.h b/drivers/media/dvb/dvb-usb/rtl28xxu.h new file mode 100644 index 000000000000..902cb8b09206 --- /dev/null +++ b/drivers/media/dvb/dvb-usb/rtl28xxu.h @@ -0,0 +1,210 @@ +/* + * Realtek RTL28xxU DVB USB driver + * + * Copyright (C) 2009 Antti Palosaari + * Copyright (C) 2011 Antti Palosaari + * + * 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; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef RTL28XXU_H +#define RTL28XXU_H + +#define DVB_USB_LOG_PREFIX "rtl28xxu" +#include "dvb-usb.h" + +#define deb_info(args...) dprintk(dvb_usb_rtl28xxu_debug, 0x01, args) +#define deb_rc(args...) dprintk(dvb_usb_rtl28xxu_debug, 0x02, args) +#define deb_xfer(args...) dprintk(dvb_usb_rtl28xxu_debug, 0x04, args) +#define deb_reg(args...) dprintk(dvb_usb_rtl28xxu_debug, 0x08, args) +#define deb_i2c(args...) dprintk(dvb_usb_rtl28xxu_debug, 0x10, args) +#define deb_fw(args...) dprintk(dvb_usb_rtl28xxu_debug, 0x20, args) + +#define deb_dump(r, t, v, i, b, l, func) { \ + int loop_; \ + func("%02x %02x %02x %02x %02x %02x %02x %02x", \ + t, r, v & 0xff, v >> 8, i & 0xff, i >> 8, l & 0xff, l >> 8); \ + if (t == (USB_TYPE_VENDOR | USB_DIR_OUT)) \ + func(" >>> "); \ + else \ + func(" <<< "); \ + for (loop_ = 0; loop_ < l; loop_++) \ + func("%02x ", b[loop_]); \ + func("\n");\ +} + +/* + * USB commands + * (usb_control_msg() index parameter) + */ +#define DEMOD (0x00 << 8) +#define USB (0x01 << 8) +#define SYS (0x02 << 8) +#define I2C (0x03 << 8) +#define CMD_WR_FLAG 0x10 +#define CMD_DEMOD_RD (DEMOD) +#define CMD_DEMOD_WR (DEMOD | CMD_WR_FLAG) +#define CMD_USB_RD (USB) +#define CMD_USB_WR (USB | CMD_WR_FLAG) +#define CMD_SYS_RD (SYS) +#define CMD_SYS_WR (SYS | CMD_WR_FLAG) +#define CMD_I2C_RD (I2C) +#define CMD_I2C_WR (I2C | CMD_WR_FLAG) + +struct rtl28xxu_priv { + u8 chip_id; + u8 tuner; +}; + +enum rtl28xxu_chip_id { + CHIP_ID_NONE = 0, + CHIP_ID_RTL2831U, + CHIP_ID_RTL2832U, +}; + +enum rtl28xxu_tuner { + TUNER_NONE = 0, + TUNER_RTL2830_QT1010, + TUNER_RTL2830_MT2060, + TUNER_RTL2830_MXL5005S, +}; + +struct rtl28xxu_req { + u16 value; + u16 index; + u16 size; + u8 *data; +}; + +struct rtl28xxu_reg_val { + u16 reg; + u8 val; +}; + +/* + * memory map + * + * 0x0000 DEMOD : demodulator + * 0x2000 USB : SIE, USB endpoint, debug, DMA + * 0x3000 SYS : system + * 0xfc00 RC : remote controller (not RTL2831U) + */ + +/* + * USB registers + */ +/* SIE Control Registers */ +#define USB_SYSCTL 0x2000 /* USB system control */ +#define USB_SYSCTL_0 0x2000 /* USB system control */ +#define USB_SYSCTL_1 0x2001 /* USB system control */ +#define USB_SYSCTL_2 0x2002 /* USB system control */ +#define USB_SYSCTL_3 0x2003 /* USB system control */ +#define USB_IRQSTAT 0x2008 /* SIE interrupt status */ +#define USB_IRQEN 0x200C /* SIE interrupt enable */ +#define USB_CTRL 0x2010 /* USB control */ +#define USB_STAT 0x2014 /* USB status */ +#define USB_DEVADDR 0x2018 /* USB device address */ +#define USB_TEST 0x201C /* USB test mode */ +#define USB_FRAME_NUMBER 0x2020 /* frame number */ +#define USB_FIFO_ADDR 0x2028 /* address of SIE FIFO RAM */ +#define USB_FIFO_CMD 0x202A /* SIE FIFO RAM access command */ +#define USB_FIFO_DATA 0x2030 /* SIE FIFO RAM data */ +/* Endpoint Registers */ +#define EP0_SETUPA 0x20F8 /* EP 0 setup packet lower byte */ +#define EP0_SETUPB 0x20FC /* EP 0 setup packet higher byte */ +#define USB_EP0_CFG 0x2104 /* EP 0 configure */ +#define USB_EP0_CTL 0x2108 /* EP 0 control */ +#define USB_EP0_STAT 0x210C /* EP 0 status */ +#define USB_EP0_IRQSTAT 0x2110 /* EP 0 interrupt status */ +#define USB_EP0_IRQEN 0x2114 /* EP 0 interrupt enable */ +#define USB_EP0_MAXPKT 0x2118 /* EP 0 max packet size */ +#define USB_EP0_BC 0x2120 /* EP 0 FIFO byte counter */ +#define USB_EPA_CFG 0x2144 /* EP A configure */ +#define USB_EPA_CFG_0 0x2144 /* EP A configure */ +#define USB_EPA_CFG_1 0x2145 /* EP A configure */ +#define USB_EPA_CFG_2 0x2146 /* EP A configure */ +#define USB_EPA_CFG_3 0x2147 /* EP A configure */ +#define USB_EPA_CTL 0x2148 /* EP A control */ +#define USB_EPA_CTL_0 0x2148 /* EP A control */ +#define USB_EPA_CTL_1 0x2149 /* EP A control */ +#define USB_EPA_CTL_2 0x214A /* EP A control */ +#define USB_EPA_CTL_3 0x214B /* EP A control */ +#define USB_EPA_STAT 0x214C /* EP A status */ +#define USB_EPA_IRQSTAT 0x2150 /* EP A interrupt status */ +#define USB_EPA_IRQEN 0x2154 /* EP A interrupt enable */ +#define USB_EPA_MAXPKT 0x2158 /* EP A max packet size */ +#define USB_EPA_MAXPKT_0 0x2158 /* EP A max packet size */ +#define USB_EPA_MAXPKT_1 0x2159 /* EP A max packet size */ +#define USB_EPA_MAXPKT_2 0x215A /* EP A max packet size */ +#define USB_EPA_MAXPKT_3 0x215B /* EP A max packet size */ +#define USB_EPA_FIFO_CFG 0x2160 /* EP A FIFO configure */ +#define USB_EPA_FIFO_CFG_0 0x2160 /* EP A FIFO configure */ +#define USB_EPA_FIFO_CFG_1 0x2161 /* EP A FIFO configure */ +#define USB_EPA_FIFO_CFG_2 0x2162 /* EP A FIFO configure */ +#define USB_EPA_FIFO_CFG_3 0x2163 /* EP A FIFO configure */ +/* Debug Registers */ +#define USB_PHYTSTDIS 0x2F04 /* PHY test disable */ +#define USB_TOUT_VAL 0x2F08 /* USB time-out time */ +#define USB_VDRCTRL 0x2F10 /* UTMI vendor signal control */ +#define USB_VSTAIN 0x2F14 /* UTMI vendor signal status in */ +#define USB_VLOADM 0x2F18 /* UTMI load vendor signal status in */ +#define USB_VSTAOUT 0x2F1C /* UTMI vendor signal status out */ +#define USB_UTMI_TST 0x2F80 /* UTMI test */ +#define USB_UTMI_STATUS 0x2F84 /* UTMI status */ +#define USB_TSTCTL 0x2F88 /* test control */ +#define USB_TSTCTL2 0x2F8C /* test control 2 */ +#define USB_PID_FORCE 0x2F90 /* force PID */ +#define USB_PKTERR_CNT 0x2F94 /* packet error counter */ +#define USB_RXERR_CNT 0x2F98 /* RX error counter */ +#define USB_MEM_BIST 0x2F9C /* MEM BIST test */ +#define USB_SLBBIST 0x2FA0 /* self-loop-back BIST */ +#define USB_CNTTEST 0x2FA4 /* counter test */ +#define USB_PHYTST 0x2FC0 /* USB PHY test */ +#define USB_DBGIDX 0x2FF0 /* select individual block debug signal */ +#define USB_DBGMUX 0x2FF4 /* debug signal module mux */ + +/* + * SYS registers + */ +/* demod control registers */ +#define SYS_SYS0 0x3000 /* include DEMOD_CTL, GPO, GPI, GPOE */ +#define SYS_DEMOD_CTL 0x3000 /* control register for DVB-T demodulator */ +/* GPIO registers */ +#define SYS_GPIO_OUT_VAL 0x3001 /* output value of GPIO */ +#define SYS_GPIO_IN_VAL 0x3002 /* input value of GPIO */ +#define SYS_GPIO_OUT_EN 0x3003 /* output enable of GPIO */ +#define SYS_SYS1 0x3004 /* include GPD, SYSINTE, SYSINTS, GP_CFG0 */ +#define SYS_GPIO_DIR 0x3004 /* direction control for GPIO */ +#define SYS_SYSINTE 0x3005 /* system interrupt enable */ +#define SYS_SYSINTS 0x3006 /* system interrupt status */ +#define SYS_GPIO_CFG0 0x3007 /* PAD configuration for GPIO0-GPIO3 */ +#define SYS_SYS2 0x3008 /* include GP_CFG1 and 3 reserved bytes */ +#define SYS_GPIO_CFG1 0x3008 /* PAD configuration for GPIO4 */ +/* IrDA registers */ +#define SYS_IRRC_PSR 0x3020 /* IR protocol selection */ +#define SYS_IRRC_PER 0x3024 /* IR protocol extension */ +#define SYS_IRRC_SF 0x3028 /* IR sampling frequency */ +#define SYS_IRRC_DPIR 0x302C /* IR data package interval */ +#define SYS_IRRC_CR 0x3030 /* IR control */ +#define SYS_IRRC_RP 0x3034 /* IR read port */ +#define SYS_IRRC_SR 0x3038 /* IR status */ +/* I2C master registers */ +#define SYS_I2CCR 0x3040 /* I2C clock */ +#define SYS_I2CMCR 0x3044 /* I2C master control */ +#define SYS_I2CMSTR 0x3048 /* I2C master SCL timing */ +#define SYS_I2CMSR 0x304C /* I2C master status */ +#define SYS_I2CMFR 0x3050 /* I2C master FIFO */ + +#endif -- cgit v1.2.3 From e9320ece9ea8cae401548bf66955230d513fd93b Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Wed, 3 Aug 2011 04:35:30 -0300 Subject: [media] rtl28xx: fix rtl2831u with tuner mxl5005s Do not return error for demod attach in case of mxl5005s tuner. Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/rtl28xxu.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/dvb-usb/rtl28xxu.c b/drivers/media/dvb/dvb-usb/rtl28xxu.c index e7b1811e3567..c186736ea8f7 100644 --- a/drivers/media/dvb/dvb-usb/rtl28xxu.c +++ b/drivers/media/dvb/dvb-usb/rtl28xxu.c @@ -308,6 +308,7 @@ static int rtl28xxu_frontend_attach(struct dvb_usb_adapter *adap) } /* assume MXL5005S */ + ret = 0; priv->tuner = TUNER_RTL2830_MXL5005S; rtl2830_config = &rtl28xxu_rtl2830_mxl5005s_config; deb_info("%s: MXL5005S\n", __func__); -- cgit v1.2.3 From b5cbaa43a676be6fe4d7e26760e5873969e69341 Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Thu, 4 Aug 2011 13:26:10 -0300 Subject: [media] rtl28xx: initial support for rtl2832u Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/rtl28xxu.c | 323 ++++++++++++++++++++++++++++++----- drivers/media/dvb/dvb-usb/rtl28xxu.h | 47 +++++ 2 files changed, 327 insertions(+), 43 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/dvb-usb/rtl28xxu.c b/drivers/media/dvb/dvb-usb/rtl28xxu.c index c186736ea8f7..8772fe880b34 100644 --- a/drivers/media/dvb/dvb-usb/rtl28xxu.c +++ b/drivers/media/dvb/dvb-usb/rtl28xxu.c @@ -88,8 +88,10 @@ static int rtl2831_wr_regs(struct dvb_usb_device *d, u16 reg, u8 *val, int len) if (reg < 0x3000) req.index = CMD_USB_WR; - else + else if (reg < 0x4000) req.index = CMD_SYS_WR; + else + req.index = CMD_IR_WR; req.value = reg; req.size = len; @@ -104,8 +106,10 @@ static int rtl2831_rd_regs(struct dvb_usb_device *d, u16 reg, u8 *val, int len) if (reg < 0x3000) req.index = CMD_USB_RD; - else + else if (reg < 0x4000) req.index = CMD_SYS_RD; + else + req.index = CMD_IR_RD; req.value = reg; req.size = len; @@ -235,18 +239,18 @@ static struct rtl2830_config rtl28xxu_rtl2830_mxl5005s_config = { .agc_targ_val = 0x3e, }; -static int rtl28xxu_frontend_attach(struct dvb_usb_adapter *adap) +static int rtl2831u_frontend_attach(struct dvb_usb_adapter *adap) { int ret; struct rtl28xxu_priv *priv = adap->dev->priv; u8 buf[1]; struct rtl2830_config *rtl2830_config; + /* open RTL2831U/RTL2830 I2C gate */ + struct rtl28xxu_req req_gate = {0x0120, 0x0011, 0x0001, "\x08"}; /* for MT2060 tuner probe */ struct rtl28xxu_req req_mt2060 = {0x00c0, CMD_I2C_RD, 1, buf}; /* for QT1010 tuner probe */ struct rtl28xxu_req req_qt1010 = {0x0fc4, CMD_I2C_RD, 1, buf}; - /* open RTL2831U/RTL2830 I2C gate */ - struct rtl28xxu_req req_gate = {0x0120, 0x0011, 0x0001, "\x08"}; deb_info("%s:\n", __func__); @@ -329,6 +333,79 @@ err: return ret; } +static int rtl2832u_frontend_attach(struct dvb_usb_adapter *adap) +{ + int ret; + struct rtl28xxu_priv *priv = adap->dev->priv; + u8 buf[1]; + /* open RTL2832U/RTL2832 I2C gate */ + struct rtl28xxu_req req_gate_open = {0x0120, 0x0011, 0x0001, "\x18"}; + /* close RTL2832U/RTL2832 I2C gate */ + struct rtl28xxu_req req_gate_close = {0x0120, 0x0011, 0x0001, "\x10"}; + /* for FC2580 tuner probe */ + struct rtl28xxu_req req_fc2580 = {0x01ac, CMD_I2C_RD, 1, buf}; + + deb_info("%s:\n", __func__); + + /* GPIO direction */ + ret = rtl2831_wr_reg(adap->dev, SYS_GPIO_DIR, 0x0a); + if (ret) + goto err; + + /* enable as output GPIO0, GPIO2, GPIO4 */ + ret = rtl2831_wr_reg(adap->dev, SYS_GPIO_OUT_EN, 0x15); + if (ret) + goto err; + + ret = rtl2831_wr_reg(adap->dev, SYS_DEMOD_CTL, 0xe8); + if (ret) + goto err; + + /* + * Probe used tuner. We need to know used tuner before demod attach + * since there is some demod params needed to set according to tuner. + */ + + /* open demod I2C gate */ + ret = rtl28xxu_ctrl_msg(adap->dev, &req_gate_open); + if (ret) + goto err; + + /* check FC2580 ID register; reg=01 val=56 */ + ret = rtl28xxu_ctrl_msg(adap->dev, &req_fc2580); + if (ret == 0 && buf[0] == 0x56) { + priv->tuner = TUNER_RTL2832_FC2580; + deb_info("%s: FC2580\n", __func__); + goto found; + } else { + deb_info("%s: FC2580 probe failed=%d - %02x\n", + __func__, ret, buf[0]); + } + + /* close demod I2C gate */ + ret = rtl28xxu_ctrl_msg(adap->dev, &req_gate_close); + if (ret) + goto err; + + /* tuner not found */ + ret = -ENODEV; + goto err; + +found: + /* close demod I2C gate */ + ret = rtl28xxu_ctrl_msg(adap->dev, &req_gate_close); + if (ret) + goto err; + + /* attach demodulator */ + /* TODO: */ + + return ret; +err: + deb_info("%s: failed=%d\n", __func__, ret); + return ret; +} + static struct qt1010_config rtl28xxu_qt1010_config = { .i2c_address = 0x62, /* 0xc4 */ }; @@ -355,7 +432,7 @@ static struct mxl5005s_config rtl28xxu_mxl5005s_config = { .AgcMasterByte = 0x00, }; -static int rtl28xxu_tuner_attach(struct dvb_usb_adapter *adap) +static int rtl2831u_tuner_attach(struct dvb_usb_adapter *adap) { int ret; struct rtl28xxu_priv *priv = adap->dev->priv; @@ -395,6 +472,33 @@ err: return ret; } +static int rtl2832u_tuner_attach(struct dvb_usb_adapter *adap) +{ + int ret; + struct rtl28xxu_priv *priv = adap->dev->priv; + struct dvb_frontend *fe = NULL; + + deb_info("%s:\n", __func__); + + switch (priv->tuner) { + case TUNER_RTL2832_FC2580: + /* TODO: */ + break; + default: + err("unknown tuner=%d", priv->tuner); + } + + if (fe == NULL) { + ret = -ENODEV; + goto err; + } + + return 0; +err: + deb_info("%s: failed=%d\n", __func__, ret); + return ret; +} + static int rtl28xxu_streaming_ctrl(struct dvb_usb_adapter *adap , int onoff) { int ret; @@ -455,21 +559,14 @@ static int rtl28xxu_power_ctrl(struct dvb_usb_device *d, int onoff) sys0 = sys0 & 0x0f; sys0 |= 0xe0; } else { - -#if 0 /* keep */ /* * FIXME: Use .fe_ioctl_override() to prevent demod - * IOCTLs in case of device is powered off. - * - * For now we cannot power off device because most FE IOCTLs - * can be performed only when device is powered. - * Using IOCTLs when device is powered off will result errors - * because register access to demod fails. + * IOCTLs in case of device is powered off. Or change + * RTL2830 demod not perform requestesd IOCTL & IO when sleep. */ gpio &= (~0x01); /* GPIO0 = 0 */ gpio |= 0x10; /* GPIO4 = 1 */ sys0 = sys0 & (~0xc0); -#endif } deb_info("%s: WR SYS0=%02x GPIO_OUT_VAL=%02x\n", __func__, sys0, gpio); @@ -490,11 +587,39 @@ err: return ret; } -static int rtl28xxu_rc_query(struct dvb_usb_device *d) +static int rtl2831u_rc_query(struct dvb_usb_device *d) { - int ret; + int ret, i; + struct rtl28xxu_priv *priv = d->priv; u8 buf[5]; u32 rc_code; + struct rtl28xxu_reg_val rc_nec_tab[] = { + { 0x3033, 0x80 }, + { 0x3020, 0x43 }, + { 0x3021, 0x16 }, + { 0x3022, 0x16 }, + { 0x3023, 0x5a }, + { 0x3024, 0x2d }, + { 0x3025, 0x16 }, + { 0x3026, 0x01 }, + { 0x3028, 0xb0 }, + { 0x3029, 0x04 }, + { 0x302c, 0x88 }, + { 0x302e, 0x13 }, + { 0x3030, 0xdf }, + { 0x3031, 0x05 }, + }; + + /* init remote controller */ + if (!priv->rc_active) { + for (i = 0; i < ARRAY_SIZE(rc_nec_tab); i++) { + ret = rtl2831_wr_reg(d, rc_nec_tab[i].reg, + rc_nec_tab[i].val); + if (ret) + goto err; + } + priv->rc_active = true; + } ret = rtl2831_rd_regs(d, SYS_IRRC_RP, buf, 5); if (ret) @@ -534,19 +659,97 @@ err: return ret; } + +static int rtl2832u_rc_query(struct dvb_usb_device *d) +{ + int ret, i; + struct rtl28xxu_priv *priv = d->priv; + u8 buf[128]; + int len; + struct rtl28xxu_reg_val rc_nec_tab[] = { + {IR_RX_CTRL, 0x20}, + {IR_RX_BUF_CTRL, 0x80}, + {IR_RX_IF, 0xff}, + {IR_RX_IE, 0xff}, + {IR_MAX_DURATION0, 0xd0}, + {IR_MAX_DURATION1, 0x07}, + {IR_IDLE_LEN0, 0xc0}, + {IR_IDLE_LEN1, 0x00}, + {IR_GLITCH_LEN, 0x03}, + {IR_RX_CLK, 0x09}, + {IR_RX_CFG, 0x1c}, + {IR_MAX_H_TOL_LEN, 0x1e}, + {IR_MAX_L_TOL_LEN, 0x1e}, + {IR_RX_CTRL, 0x80}, + }; + + /* init remote controller */ + if (!priv->rc_active) { + for (i = 0; i < ARRAY_SIZE(rc_nec_tab); i++) { + ret = rtl2831_wr_reg(d, rc_nec_tab[i].reg, + rc_nec_tab[i].val); + if (ret) + goto err; + } + priv->rc_active = true; + } + + ret = rtl2831_rd_reg(d, IR_RX_IF, &buf[0]); + if (ret) + goto err; + + if (buf[0] != 0x83) + goto exit; + + ret = rtl2831_rd_reg(d, IR_RX_BC, &buf[0]); + if (ret) + goto err; + + len = buf[0]; + ret = rtl2831_rd_regs(d, IR_RX_BUF, buf, len); + + /* TODO: pass raw IR to Kernel IR decoder */ + + ret = rtl2831_wr_reg(d, IR_RX_IF, 0x03); + ret = rtl2831_wr_reg(d, IR_RX_BUF_CTRL, 0x80); + ret = rtl2831_wr_reg(d, IR_RX_CTRL, 0x80); + +exit: + return ret; +err: + deb_info("%s: failed=%d\n", __func__, ret); + return ret; +} + + /* DVB USB Driver stuff */ #define USB_VID_REALTEK 0x0bda +#define USB_VID_DEXATEK 0x1D19 #define USB_PID_RTL2831U 0x2831 +#define USB_PID_RTL2832U 0x2832 #define USB_PID_FREECOM 0x0160 +#define USB_PID_DEXATEK_1101 0x1101 #define RTL2831U_0BDA_2831 0 #define RTL2831U_14AA_0160 1 +#define RTL2832U_1ST_ID (RTL2831U_14AA_0160 + 1) + +#define RTL2832U_0BDA_2832 (0 + RTL2832U_1ST_ID) +#define RTL2832U_1D19_1101 (1 + RTL2832U_1ST_ID) + + static struct usb_device_id rtl28xxu_table[] = { [RTL2831U_0BDA_2831] = { USB_DEVICE(USB_VID_REALTEK, USB_PID_RTL2831U)}, [RTL2831U_14AA_0160] = { USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_FREECOM)}, + + [RTL2832U_0BDA_2832] = { + USB_DEVICE(USB_VID_REALTEK, USB_PID_RTL2832U)}, + [RTL2832U_1D19_1101] = { + USB_DEVICE(USB_VID_DEXATEK, USB_PID_DEXATEK_1101)}, + {} /* terminating entry */ }; @@ -564,8 +767,8 @@ static struct dvb_usb_device_properties rtl28xxu_properties[] = { .num_adapters = 1, .adapter = { { - .frontend_attach = rtl28xxu_frontend_attach, - .tuner_attach = rtl28xxu_tuner_attach, + .frontend_attach = rtl2831u_frontend_attach, + .tuner_attach = rtl2831u_tuner_attach, .streaming_ctrl = rtl28xxu_streaming_ctrl, .stream = { .type = USB_BULK, @@ -585,7 +788,7 @@ static struct dvb_usb_device_properties rtl28xxu_properties[] = { .rc.core = { .protocol = RC_TYPE_NEC, .module_name = "rtl28xxu", - .rc_query = rtl28xxu_rc_query, + .rc_query = rtl2831u_rc_query, .rc_interval = 400, .allowed_protos = RC_TYPE_NEC, .rc_codes = RC_MAP_EMPTY, @@ -609,6 +812,63 @@ static struct dvb_usb_device_properties rtl28xxu_properties[] = { }, } }, + { + .caps = DVB_USB_IS_AN_I2C_ADAPTER, + + .usb_ctrl = DEVICE_SPECIFIC, + .no_reconnect = 1, + + .size_of_priv = sizeof(struct rtl28xxu_priv), + + .num_adapters = 1, + .adapter = { + { + .frontend_attach = rtl2832u_frontend_attach, + .tuner_attach = rtl2832u_tuner_attach, + .streaming_ctrl = rtl28xxu_streaming_ctrl, + .stream = { + .type = USB_BULK, + .count = 6, + .endpoint = 0x81, + .u = { + .bulk = { + .buffersize = 4096, + } + } + }, + } + }, + + .power_ctrl = rtl28xxu_power_ctrl, + + .rc.core = { + .protocol = RC_TYPE_NEC, + .module_name = "rtl28xxu", + .rc_query = rtl2832u_rc_query, + .rc_interval = 400, + .allowed_protos = RC_TYPE_NEC, + .rc_codes = RC_MAP_EMPTY, + }, + + .i2c_algo = &rtl28xxu_i2c_algo, + + .num_device_descs = 2, + .devices = { + { + .name = "Realtek RTL2832U reference design", + .cold_ids = {NULL}, + .warm_ids = { + &rtl28xxu_table[RTL2832U_0BDA_2832], NULL}, + }, + { + .name = "Dexatek dongle", + .cold_ids = {NULL}, + .warm_ids = { + &rtl28xxu_table[RTL2832U_1D19_1101], NULL}, + }, + } + }, + }; static int rtl28xxu_probe(struct usb_interface *intf, @@ -617,22 +877,6 @@ static int rtl28xxu_probe(struct usb_interface *intf, int ret, i; int properties_count = ARRAY_SIZE(rtl28xxu_properties); struct dvb_usb_device *d = NULL; - struct rtl28xxu_reg_val rc_nec_tab[] = { - { 0x3033, 0x80 }, - { 0x3020, 0x43 }, - { 0x3021, 0x16 }, - { 0x3022, 0x16 }, - { 0x3023, 0x5a }, - { 0x3024, 0x2d }, - { 0x3025, 0x16 }, - { 0x3026, 0x01 }, - { 0x3028, 0xb0 }, - { 0x3029, 0x04 }, - { 0x302c, 0x88 }, - { 0x302e, 0x13 }, - { 0x3030, 0xdf }, - { 0x3031, 0x05 }, - }; deb_info("%s: interface=%d\n", __func__, intf->cur_altsetting->desc.bInterfaceNumber); @@ -663,13 +907,6 @@ static int rtl28xxu_probe(struct usb_interface *intf, if (ret) goto err; - /* init remote controller */ - for (i = 0; i < ARRAY_SIZE(rc_nec_tab); i++) { - ret = rtl2831_wr_reg(d, rc_nec_tab[i].reg, rc_nec_tab[i].val); - if (ret) - goto err; - } - return ret; err: deb_info("%s: failed=%d\n", __func__, ret); diff --git a/drivers/media/dvb/dvb-usb/rtl28xxu.h b/drivers/media/dvb/dvb-usb/rtl28xxu.h index 902cb8b09206..dbde378d05e6 100644 --- a/drivers/media/dvb/dvb-usb/rtl28xxu.h +++ b/drivers/media/dvb/dvb-usb/rtl28xxu.h @@ -62,10 +62,13 @@ #define CMD_SYS_WR (SYS | CMD_WR_FLAG) #define CMD_I2C_RD (I2C) #define CMD_I2C_WR (I2C | CMD_WR_FLAG) +#define CMD_IR_RD (CMD_SYS_RD | 0x01) +#define CMD_IR_WR (CMD_SYS_WR | 0x01) struct rtl28xxu_priv { u8 chip_id; u8 tuner; + bool rc_active; }; enum rtl28xxu_chip_id { @@ -76,9 +79,21 @@ enum rtl28xxu_chip_id { enum rtl28xxu_tuner { TUNER_NONE = 0, + TUNER_RTL2830_QT1010, TUNER_RTL2830_MT2060, TUNER_RTL2830_MXL5005S, + + TUNER_RTL2832_MT2266, + TUNER_RTL2832_FC2580, + TUNER_RTL2832_MT2063, + TUNER_RTL2832_MAX3543, + TUNER_RTL2832_TUA9001, + TUNER_RTL2832_MXL5007T, + TUNER_RTL2832_FC0012, + TUNER_RTL2832_E4000, + TUNER_RTL2832_TDA18272, + TUNER_RTL2832_FC0013, }; struct rtl28xxu_req { @@ -192,6 +207,8 @@ struct rtl28xxu_reg_val { #define SYS_GPIO_CFG0 0x3007 /* PAD configuration for GPIO0-GPIO3 */ #define SYS_SYS2 0x3008 /* include GP_CFG1 and 3 reserved bytes */ #define SYS_GPIO_CFG1 0x3008 /* PAD configuration for GPIO4 */ +#define SYS_DEMOD_CTL1 0x300B + /* IrDA registers */ #define SYS_IRRC_PSR 0x3020 /* IR protocol selection */ #define SYS_IRRC_PER 0x3024 /* IR protocol extension */ @@ -207,4 +224,34 @@ struct rtl28xxu_reg_val { #define SYS_I2CMSR 0x304C /* I2C master status */ #define SYS_I2CMFR 0x3050 /* I2C master FIFO */ +/* + * IR registers + */ +#define IR_RX_BUF 0xFC00 +#define IR_RX_IE 0xFD00 +#define IR_RX_IF 0xFD01 +#define IR_RX_CTRL 0xFD02 +#define IR_RX_CFG 0xFD03 +#define IR_MAX_DURATION0 0xFD04 +#define IR_MAX_DURATION1 0xFD05 +#define IR_IDLE_LEN0 0xFD06 +#define IR_IDLE_LEN1 0xFD07 +#define IR_GLITCH_LEN 0xFD08 +#define IR_RX_BUF_CTRL 0xFD09 +#define IR_RX_BUF_DATA 0xFD0A +#define IR_RX_BC 0xFD0B +#define IR_RX_CLK 0xFD0C +#define IR_RX_C_COUNT_L 0xFD0D +#define IR_RX_C_COUNT_H 0xFD0E +#define IR_SUSPEND_CTRL 0xFD10 +#define IR_ERR_TOL_CTRL 0xFD11 +#define IR_UNIT_LEN 0xFD12 +#define IR_ERR_TOL_LEN 0xFD13 +#define IR_MAX_H_TOL_LEN 0xFD14 +#define IR_MAX_L_TOL_LEN 0xFD15 +#define IR_MASK_CTRL 0xFD16 +#define IR_MASK_DATA 0xFD17 +#define IR_RES_MASK_ADDR 0xFD18 +#define IR_RES_MASK_T_LEN 0xFD19 + #endif -- cgit v1.2.3 From 34ec2933485b6b047245ccbb7fa2b3513bed46af Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Thu, 4 Aug 2011 20:21:16 -0300 Subject: [media] rtl28xx: reimplement I2C adapter It is almost perfect now! Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/rtl28xxu.c | 83 ++++++++++++++++++++++++++++-------- drivers/media/dvb/dvb-usb/rtl28xxu.h | 17 +++++--- 2 files changed, 76 insertions(+), 24 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/dvb-usb/rtl28xxu.c b/drivers/media/dvb/dvb-usb/rtl28xxu.c index 8772fe880b34..a6b5c04b3a3b 100644 --- a/drivers/media/dvb/dvb-usb/rtl28xxu.c +++ b/drivers/media/dvb/dvb-usb/rtl28xxu.c @@ -134,11 +134,29 @@ static int rtl28xxu_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], { int ret; struct dvb_usb_device *d = i2c_get_adapdata(adap); + struct rtl28xxu_priv *priv = d->priv; struct rtl28xxu_req req; /* * It is not known which are real I2C bus xfer limits, but testing * with RTL2831U + MT2060 gives max RD 24 and max WR 22 bytes. + * TODO: find out RTL2832U lens + */ + + /* + * I2C adapter logic looks rather complicated due to fact it handles + * three different access methods. Those methods are; + * 1) integrated demod access + * 2) old I2C access + * 3) new I2C access + * + * Used method is selected in order 1, 2, 3. Method 3 can handle all + * requests but there is two reasons why not use it always; + * 1) It is most expensive, usually two USB messages are needed + * 2) At least RTL2831U does not support it + * + * Method 3 is needed in case of I2C write+read (typical register read) + * where write is more than one byte. */ if (mutex_lock_interruptible(&d->i2c_mutex) < 0) @@ -146,44 +164,73 @@ static int rtl28xxu_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], if (num == 2 && !(msg[0].flags & I2C_M_RD) && (msg[1].flags & I2C_M_RD)) { - if (msg[0].len > 2 || msg[1].len > 24) { + if (msg[0].len > 24 || msg[1].len > 24) { + /* TODO: check msg[0].len max */ ret = -EOPNOTSUPP; goto err_unlock; - } - if (msg[0].addr == 0x10) { - /* integrated demod */ - req.value = (msg[0].buf[1] << 8) | (msg[0].addr << 1); - req.index = CMD_DEMOD_RD | msg[0].buf[0]; + } else if (msg[0].addr == 0x10) { + /* method 1 - integrated demod */ + req.value = (msg[0].buf[0] << 8) | (msg[0].addr << 1); + req.index = CMD_DEMOD_RD | priv->page; req.size = msg[1].len; req.data = &msg[1].buf[0]; ret = rtl28xxu_ctrl_msg(d, &req); - } else { - /* real I2C */ + } else if (msg[0].len < 2) { + /* method 2 - old I2C */ req.value = (msg[0].buf[0] << 8) | (msg[0].addr << 1); req.index = CMD_I2C_RD; req.size = msg[1].len; req.data = &msg[1].buf[0]; ret = rtl28xxu_ctrl_msg(d, &req); + } else { + /* method 3 - new I2C */ + req.value = (msg[0].addr << 1); + req.index = CMD_I2C_DA_WR; + req.size = msg[0].len; + req.data = msg[0].buf; + ret = rtl28xxu_ctrl_msg(d, &req); + if (ret) + goto err_unlock; + + req.value = (msg[0].addr << 1); + req.index = CMD_I2C_DA_RD; + req.size = msg[1].len; + req.data = msg[1].buf; + ret = rtl28xxu_ctrl_msg(d, &req); } } else if (num == 1 && !(msg[0].flags & I2C_M_RD)) { if (msg[0].len > 22) { + /* TODO: check msg[0].len max */ ret = -EOPNOTSUPP; goto err_unlock; - } - if (msg[0].addr == 0x10) { - /* integrated demod */ - req.value = (msg[0].buf[1] << 8) | (msg[0].addr << 1); - req.index = CMD_DEMOD_WR | msg[0].buf[0]; - req.size = msg[0].len-2; - req.data = &msg[0].buf[2]; - ret = rtl28xxu_ctrl_msg(d, &req); - } else { - /* real I2C */ + } else if (msg[0].addr == 0x10) { + /* method 1 - integrated demod */ + if (msg[0].buf[0] == 0x00) { + /* save demod page for later demod access */ + priv->page = msg[0].buf[1]; + ret = 0; + } else { + req.value = (msg[0].buf[0] << 8) | + (msg[0].addr << 1); + req.index = CMD_DEMOD_WR | priv->page; + req.size = msg[0].len-1; + req.data = &msg[0].buf[1]; + ret = rtl28xxu_ctrl_msg(d, &req); + } + } else if (msg[0].len < 23) { + /* method 2 - old I2C */ req.value = (msg[0].buf[0] << 8) | (msg[0].addr << 1); req.index = CMD_I2C_WR; req.size = msg[0].len-1; req.data = &msg[0].buf[1]; ret = rtl28xxu_ctrl_msg(d, &req); + } else { + /* method 3 - new I2C */ + req.value = (msg[0].addr << 1); + req.index = CMD_I2C_DA_WR; + req.size = msg[0].len; + req.data = msg[0].buf; + ret = rtl28xxu_ctrl_msg(d, &req); } } else { ret = -EINVAL; diff --git a/drivers/media/dvb/dvb-usb/rtl28xxu.h b/drivers/media/dvb/dvb-usb/rtl28xxu.h index dbde378d05e6..2047b1bb0aa4 100644 --- a/drivers/media/dvb/dvb-usb/rtl28xxu.h +++ b/drivers/media/dvb/dvb-usb/rtl28xxu.h @@ -49,25 +49,30 @@ * USB commands * (usb_control_msg() index parameter) */ -#define DEMOD (0x00 << 8) -#define USB (0x01 << 8) -#define SYS (0x02 << 8) -#define I2C (0x03 << 8) +#define DEMOD (0x00 << 8) +#define USB (0x01 << 8) +#define SYS (0x02 << 8) +#define I2C (0x03 << 8) +#define I2C_DA (0x06 << 8) + #define CMD_WR_FLAG 0x10 #define CMD_DEMOD_RD (DEMOD) #define CMD_DEMOD_WR (DEMOD | CMD_WR_FLAG) #define CMD_USB_RD (USB) #define CMD_USB_WR (USB | CMD_WR_FLAG) #define CMD_SYS_RD (SYS) +#define CMD_IR_RD (CMD_SYS_RD | 0x01) +#define CMD_IR_WR (CMD_SYS_WR | 0x01) #define CMD_SYS_WR (SYS | CMD_WR_FLAG) #define CMD_I2C_RD (I2C) #define CMD_I2C_WR (I2C | CMD_WR_FLAG) -#define CMD_IR_RD (CMD_SYS_RD | 0x01) -#define CMD_IR_WR (CMD_SYS_WR | 0x01) +#define CMD_I2C_DA_RD (I2C_DA) +#define CMD_I2C_DA_WR (I2C_DA | CMD_WR_FLAG) struct rtl28xxu_priv { u8 chip_id; u8 tuner; + u8 page; /* integrated demod active register page */ bool rc_active; }; -- cgit v1.2.3 From 0485a7089b8d6c11fe2db1123a1ed39a2676592f Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Thu, 4 Aug 2011 20:27:19 -0300 Subject: [media] rtl2830: correct I2C functionality Implement I2C functionality according to real RTL2830 demod. Do not send register page in first byte of each I2C write, instead use logic to set page using own write when needed. Page register is physical register 0 as generally used. Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/rtl2830.c | 67 ++++++++++++++++++++++-------- drivers/media/dvb/frontends/rtl2830_priv.h | 2 + 2 files changed, 52 insertions(+), 17 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/frontends/rtl2830.c b/drivers/media/dvb/frontends/rtl2830.c index 37a9fa29874e..f036701c12ee 100644 --- a/drivers/media/dvb/frontends/rtl2830.c +++ b/drivers/media/dvb/frontends/rtl2830.c @@ -31,45 +31,43 @@ int rtl2830_debug; module_param_named(debug, rtl2830_debug, int, 0644); MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off)."); -/* write multiple registers */ -static int rtl2830_wr_regs(struct rtl2830_priv *priv, u16 reg, u8 *val, int len) +/* write multiple hardware registers */ +static int rtl2830_wr(struct rtl2830_priv *priv, u8 reg, u8 *val, int len) { int ret; - u8 buf[2+len]; + u8 buf[1+len]; struct i2c_msg msg[1] = { { .addr = priv->cfg.i2c_addr, .flags = 0, - .len = sizeof(buf), + .len = 1+len, .buf = buf, } }; - buf[0] = (reg >> 8) & 0xff; - buf[1] = (reg >> 0) & 0xff; - memcpy(&buf[2], val, len); + buf[0] = reg; + memcpy(&buf[1], val, len); ret = i2c_transfer(priv->i2c, msg, 1); if (ret == 1) { ret = 0; } else { - warn("i2c wr failed=%d reg=%04x len=%d", ret, reg, len); + warn("i2c wr failed=%d reg=%02x len=%d", ret, reg, len); ret = -EREMOTEIO; } return ret; } -/* read multiple registers */ -static int rtl2830_rd_regs(struct rtl2830_priv *priv, u16 reg, u8 *val, int len) +/* read multiple hardware registers */ +static int rtl2830_rd(struct rtl2830_priv *priv, u8 reg, u8 *val, int len) { int ret; - u8 buf[2]; struct i2c_msg msg[2] = { { .addr = priv->cfg.i2c_addr, .flags = 0, - .len = sizeof(buf), - .buf = buf, + .len = 1, + .buf = ®, }, { .addr = priv->cfg.i2c_addr, .flags = I2C_M_RD, @@ -78,19 +76,54 @@ static int rtl2830_rd_regs(struct rtl2830_priv *priv, u16 reg, u8 *val, int len) } }; - buf[0] = (reg >> 8) & 0xff; - buf[1] = (reg >> 0) & 0xff; - ret = i2c_transfer(priv->i2c, msg, 2); if (ret == 2) { ret = 0; } else { - warn("i2c rd failed=%d reg=%04x len=%d", ret, reg, len); + warn("i2c rd failed=%d reg=%02x len=%d", ret, reg, len); ret = -EREMOTEIO; } return ret; } +/* write multiple registers */ +static int rtl2830_wr_regs(struct rtl2830_priv *priv, u16 reg, u8 *val, int len) +{ + int ret; + u8 reg2 = (reg >> 0) & 0xff; + u8 page = (reg >> 8) & 0xff; + + /* switch bank if needed */ + if (page != priv->page) { + ret = rtl2830_wr(priv, 0x00, &page, 1); + if (ret) + return ret; + + priv->page = page; + } + + return rtl2830_wr(priv, reg2, val, len); +} + +/* read multiple registers */ +static int rtl2830_rd_regs(struct rtl2830_priv *priv, u16 reg, u8 *val, int len) +{ + int ret; + u8 reg2 = (reg >> 0) & 0xff; + u8 page = (reg >> 8) & 0xff; + + /* switch bank if needed */ + if (page != priv->page) { + ret = rtl2830_wr(priv, 0x00, &page, 1); + if (ret) + return ret; + + priv->page = page; + } + + return rtl2830_rd(priv, reg2, val, len); +} + #if 0 /* currently not used */ /* write single register */ static int rtl2830_wr_reg(struct rtl2830_priv *priv, u16 reg, u8 val) diff --git a/drivers/media/dvb/frontends/rtl2830_priv.h b/drivers/media/dvb/frontends/rtl2830_priv.h index 2bc662ee87a0..49de01dd5e83 100644 --- a/drivers/media/dvb/frontends/rtl2830_priv.h +++ b/drivers/media/dvb/frontends/rtl2830_priv.h @@ -42,6 +42,8 @@ struct rtl2830_priv { struct dvb_frontend fe; struct rtl2830_config cfg; struct i2c_adapter tuner_i2c_adapter; + + u8 page; /* active register page */ }; struct rtl2830_reg_val_mask { -- cgit v1.2.3 From fba16b133e6b8dd3dd3f6f34beca1889c9ac731f Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Sat, 21 Jan 2012 20:28:38 -0300 Subject: [media] rtl28xxu: make it compile against current Kernel Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/rtl28xxu.c | 73 +++++++++++++++++++++--------------- 1 file changed, 42 insertions(+), 31 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/dvb-usb/rtl28xxu.c b/drivers/media/dvb/dvb-usb/rtl28xxu.c index a6b5c04b3a3b..101d98e5dcdb 100644 --- a/drivers/media/dvb/dvb-usb/rtl28xxu.c +++ b/drivers/media/dvb/dvb-usb/rtl28xxu.c @@ -367,9 +367,9 @@ static int rtl2831u_frontend_attach(struct dvb_usb_adapter *adap) found: /* attach demodulator */ - adap->fe[0] = dvb_attach(rtl2830_attach, rtl2830_config, + adap->fe_adap[0].fe = dvb_attach(rtl2830_attach, rtl2830_config, &adap->dev->i2c_adap); - if (adap->fe[0] == NULL) { + if (adap->fe_adap[0].fe == NULL) { ret = -ENODEV; goto err; } @@ -489,20 +489,21 @@ static int rtl2831u_tuner_attach(struct dvb_usb_adapter *adap) deb_info("%s:\n", __func__); /* use rtl2830 driver I2C adapter, for more info see rtl2830 driver */ - rtl2830_tuner_i2c = rtl2830_get_tuner_i2c_adapter(adap->fe[0]); + rtl2830_tuner_i2c = rtl2830_get_tuner_i2c_adapter(adap->fe_adap[0].fe); switch (priv->tuner) { case TUNER_RTL2830_QT1010: - fe = dvb_attach(qt1010_attach, adap->fe[0], rtl2830_tuner_i2c, - &rtl28xxu_qt1010_config); + fe = dvb_attach(qt1010_attach, adap->fe_adap[0].fe, + rtl2830_tuner_i2c, &rtl28xxu_qt1010_config); break; case TUNER_RTL2830_MT2060: - fe = dvb_attach(mt2060_attach, adap->fe[0], rtl2830_tuner_i2c, - &rtl28xxu_mt2060_config, 1220); + fe = dvb_attach(mt2060_attach, adap->fe_adap[0].fe, + rtl2830_tuner_i2c, &rtl28xxu_mt2060_config, + 1220); break; case TUNER_RTL2830_MXL5005S: - fe = dvb_attach(mxl5005s_attach, adap->fe[0], rtl2830_tuner_i2c, - &rtl28xxu_mxl5005s_config); + fe = dvb_attach(mxl5005s_attach, adap->fe_adap[0].fe, + rtl2830_tuner_i2c, &rtl28xxu_mxl5005s_config); break; default: err("unknown tuner=%d", priv->tuner); @@ -814,19 +815,24 @@ static struct dvb_usb_device_properties rtl28xxu_properties[] = { .num_adapters = 1, .adapter = { { - .frontend_attach = rtl2831u_frontend_attach, - .tuner_attach = rtl2831u_tuner_attach, - .streaming_ctrl = rtl28xxu_streaming_ctrl, - .stream = { - .type = USB_BULK, - .count = 6, - .endpoint = 0x81, - .u = { - .bulk = { - .buffersize = 4096, + .num_frontends = 1, + .fe = { + { + .frontend_attach = rtl2831u_frontend_attach, + .tuner_attach = rtl2831u_tuner_attach, + .streaming_ctrl = rtl28xxu_streaming_ctrl, + .stream = { + .type = USB_BULK, + .count = 6, + .endpoint = 0x81, + .u = { + .bulk = { + .buffersize = 4096, + } + } } } - }, + } } }, @@ -870,19 +876,24 @@ static struct dvb_usb_device_properties rtl28xxu_properties[] = { .num_adapters = 1, .adapter = { { - .frontend_attach = rtl2832u_frontend_attach, - .tuner_attach = rtl2832u_tuner_attach, - .streaming_ctrl = rtl28xxu_streaming_ctrl, - .stream = { - .type = USB_BULK, - .count = 6, - .endpoint = 0x81, - .u = { - .bulk = { - .buffersize = 4096, + .num_frontends = 1, + .fe = { + { + .frontend_attach = rtl2832u_frontend_attach, + .tuner_attach = rtl2832u_tuner_attach, + .streaming_ctrl = rtl28xxu_streaming_ctrl, + .stream = { + .type = USB_BULK, + .count = 6, + .endpoint = 0x81, + .u = { + .bulk = { + .buffersize = 4096, + } + } } } - }, + } } }, -- cgit v1.2.3 From 9935eea5ac300b84036192af1bd98940a64650de Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Sat, 21 Jan 2012 22:26:52 -0300 Subject: [media] rtl28xxu: many small tweaks * some style issues * remove rtl2832u device IDs * move USB IDs to correct place Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/dvb-usb-ids.h | 4 + drivers/media/dvb/dvb-usb/rtl28xxu.c | 140 ++++++++++++++------------------ drivers/media/dvb/dvb-usb/rtl28xxu.h | 42 +++++----- 3 files changed, 85 insertions(+), 101 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h index 9c3dae100160..bf2826fa591d 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h +++ b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h @@ -51,6 +51,7 @@ #define USB_VID_PINNACLE 0x2304 #define USB_VID_PCTV 0x2013 #define USB_VID_PIXELVIEW 0x1554 +#define USB_VID_REALTEK 0x0bda #define USB_VID_TECHNOTREND 0x0b48 #define USB_VID_TERRATEC 0x0ccd #define USB_VID_TELESTAR 0x10b9 @@ -126,6 +127,7 @@ #define USB_PID_E3C_EC168_3 0xfffb #define USB_PID_E3C_EC168_4 0x1001 #define USB_PID_E3C_EC168_5 0x1002 +#define USB_PID_FREECOM_DVBT 0x0160 #define USB_PID_UNIWILL_STK7700P 0x6003 #define USB_PID_GENIUS_TVGO_DVB_T03 0x4012 #define USB_PID_GRANDTEC_DVBT_USB_COLD 0x0fa0 @@ -252,6 +254,8 @@ #define USB_PID_PCTV_400E 0x020f #define USB_PID_PCTV_450E 0x0222 #define USB_PID_PCTV_452E 0x021f +#define USB_PID_REALTEK_RTL2831U 0x2831 +#define USB_PID_REALTEK_RTL2832U 0x2832 #define USB_PID_TECHNOTREND_CONNECT_S2_3600 0x3007 #define USB_PID_TECHNOTREND_CONNECT_S2_3650_CI 0x300a #define USB_PID_NEBULA_DIGITV 0x0201 diff --git a/drivers/media/dvb/dvb-usb/rtl28xxu.c b/drivers/media/dvb/dvb-usb/rtl28xxu.c index 101d98e5dcdb..b5785fa36220 100644 --- a/drivers/media/dvb/dvb-usb/rtl28xxu.c +++ b/drivers/media/dvb/dvb-usb/rtl28xxu.c @@ -58,25 +58,23 @@ static int rtl28xxu_ctrl_msg(struct dvb_usb_device *d, struct rtl28xxu_req *req) } ret = usb_control_msg(d->udev, pipe, 0, requesttype, req->value, - req->index, buf, req->size, 1000); + req->index, buf, req->size, 1000); + if (ret > 0) + ret = 0; deb_dump(0, requesttype, req->value, req->index, buf, req->size, - deb_xfer); - - if (ret < 0) - goto err_dealloc; - else - ret = 0; + deb_xfer); /* read request, copy returned data to return buf */ if (!ret && requesttype == (USB_TYPE_VENDOR | USB_DIR_IN)) memcpy(req->data, buf, req->size); kfree(buf); - return ret; -err_dealloc: - kfree(buf); + if (ret) + goto err; + + return ret; err: deb_info("%s: failed=%d\n", __func__, ret); return ret; @@ -167,7 +165,7 @@ static int rtl28xxu_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], if (msg[0].len > 24 || msg[1].len > 24) { /* TODO: check msg[0].len max */ ret = -EOPNOTSUPP; - goto err_unlock; + goto err_mutex_unlock; } else if (msg[0].addr == 0x10) { /* method 1 - integrated demod */ req.value = (msg[0].buf[0] << 8) | (msg[0].addr << 1); @@ -190,7 +188,7 @@ static int rtl28xxu_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], req.data = msg[0].buf; ret = rtl28xxu_ctrl_msg(d, &req); if (ret) - goto err_unlock; + goto err_mutex_unlock; req.value = (msg[0].addr << 1); req.index = CMD_I2C_DA_RD; @@ -202,7 +200,7 @@ static int rtl28xxu_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], if (msg[0].len > 22) { /* TODO: check msg[0].len max */ ret = -EOPNOTSUPP; - goto err_unlock; + goto err_mutex_unlock; } else if (msg[0].addr == 0x10) { /* method 1 - integrated demod */ if (msg[0].buf[0] == 0x00) { @@ -236,7 +234,7 @@ static int rtl28xxu_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], ret = -EINVAL; } -err_unlock: +err_mutex_unlock: mutex_unlock(&d->i2c_mutex); return ret ? ret : num; @@ -293,11 +291,11 @@ static int rtl2831u_frontend_attach(struct dvb_usb_adapter *adap) u8 buf[1]; struct rtl2830_config *rtl2830_config; /* open RTL2831U/RTL2830 I2C gate */ - struct rtl28xxu_req req_gate = {0x0120, 0x0011, 0x0001, "\x08"}; + struct rtl28xxu_req req_gate = { 0x0120, 0x0011, 0x0001, "\x08" }; /* for MT2060 tuner probe */ - struct rtl28xxu_req req_mt2060 = {0x00c0, CMD_I2C_RD, 1, buf}; + struct rtl28xxu_req req_mt2060 = { 0x00c0, CMD_I2C_RD, 1, buf }; /* for QT1010 tuner probe */ - struct rtl28xxu_req req_qt1010 = {0x0fc4, CMD_I2C_RD, 1, buf}; + struct rtl28xxu_req req_qt1010 = { 0x0fc4, CMD_I2C_RD, 1, buf }; deb_info("%s:\n", __func__); @@ -484,7 +482,7 @@ static int rtl2831u_tuner_attach(struct dvb_usb_adapter *adap) int ret; struct rtl28xxu_priv *priv = adap->dev->priv; struct i2c_adapter *rtl2830_tuner_i2c; - struct dvb_frontend *fe = NULL; + struct dvb_frontend *fe; deb_info("%s:\n", __func__); @@ -503,9 +501,10 @@ static int rtl2831u_tuner_attach(struct dvb_usb_adapter *adap) break; case TUNER_RTL2830_MXL5005S: fe = dvb_attach(mxl5005s_attach, adap->fe_adap[0].fe, - rtl2830_tuner_i2c, &rtl28xxu_mxl5005s_config); + rtl2830_tuner_i2c, &rtl28xxu_mxl5005s_config); break; default: + fe = NULL; err("unknown tuner=%d", priv->tuner); } @@ -524,15 +523,17 @@ static int rtl2832u_tuner_attach(struct dvb_usb_adapter *adap) { int ret; struct rtl28xxu_priv *priv = adap->dev->priv; - struct dvb_frontend *fe = NULL; + struct dvb_frontend *fe; deb_info("%s:\n", __func__); switch (priv->tuner) { case TUNER_RTL2832_FC2580: /* TODO: */ + fe = NULL; break; default: + fe = NULL; err("unknown tuner=%d", priv->tuner); } @@ -662,7 +663,7 @@ static int rtl2831u_rc_query(struct dvb_usb_device *d) if (!priv->rc_active) { for (i = 0; i < ARRAY_SIZE(rc_nec_tab); i++) { ret = rtl2831_wr_reg(d, rc_nec_tab[i].reg, - rc_nec_tab[i].val); + rc_nec_tab[i].val); if (ret) goto err; } @@ -681,7 +682,7 @@ static int rtl2831u_rc_query(struct dvb_usb_device *d) } else { /* NEC extended (24 bit) */ rc_code = buf[0] << 16 | - buf[1] << 8 | buf[2]; + buf[1] << 8 | buf[2]; } } else { /* NEC full (32 bit) */ @@ -707,7 +708,6 @@ err: return ret; } - static int rtl2832u_rc_query(struct dvb_usb_device *d) { int ret, i; @@ -715,27 +715,27 @@ static int rtl2832u_rc_query(struct dvb_usb_device *d) u8 buf[128]; int len; struct rtl28xxu_reg_val rc_nec_tab[] = { - {IR_RX_CTRL, 0x20}, - {IR_RX_BUF_CTRL, 0x80}, - {IR_RX_IF, 0xff}, - {IR_RX_IE, 0xff}, - {IR_MAX_DURATION0, 0xd0}, - {IR_MAX_DURATION1, 0x07}, - {IR_IDLE_LEN0, 0xc0}, - {IR_IDLE_LEN1, 0x00}, - {IR_GLITCH_LEN, 0x03}, - {IR_RX_CLK, 0x09}, - {IR_RX_CFG, 0x1c}, - {IR_MAX_H_TOL_LEN, 0x1e}, - {IR_MAX_L_TOL_LEN, 0x1e}, - {IR_RX_CTRL, 0x80}, + { IR_RX_CTRL, 0x20 }, + { IR_RX_BUF_CTRL, 0x80 }, + { IR_RX_IF, 0xff }, + { IR_RX_IE, 0xff }, + { IR_MAX_DURATION0, 0xd0 }, + { IR_MAX_DURATION1, 0x07 }, + { IR_IDLE_LEN0, 0xc0 }, + { IR_IDLE_LEN1, 0x00 }, + { IR_GLITCH_LEN, 0x03 }, + { IR_RX_CLK, 0x09 }, + { IR_RX_CFG, 0x1c }, + { IR_MAX_H_TOL_LEN, 0x1e }, + { IR_MAX_L_TOL_LEN, 0x1e }, + { IR_RX_CTRL, 0x80 }, }; /* init remote controller */ if (!priv->rc_active) { for (i = 0; i < ARRAY_SIZE(rc_nec_tab); i++) { ret = rtl2831_wr_reg(d, rc_nec_tab[i].reg, - rc_nec_tab[i].val); + rc_nec_tab[i].val); if (ret) goto err; } @@ -769,35 +769,19 @@ err: return ret; } - -/* DVB USB Driver stuff */ -#define USB_VID_REALTEK 0x0bda -#define USB_VID_DEXATEK 0x1D19 -#define USB_PID_RTL2831U 0x2831 -#define USB_PID_RTL2832U 0x2832 -#define USB_PID_FREECOM 0x0160 -#define USB_PID_DEXATEK_1101 0x1101 - -#define RTL2831U_0BDA_2831 0 -#define RTL2831U_14AA_0160 1 - -#define RTL2832U_1ST_ID (RTL2831U_14AA_0160 + 1) - -#define RTL2832U_0BDA_2832 (0 + RTL2832U_1ST_ID) -#define RTL2832U_1D19_1101 (1 + RTL2832U_1ST_ID) - +enum rtl28xxu_usb_table_entry { + RTL2831U_0BDA_2831, + RTL2831U_14AA_0160, +}; static struct usb_device_id rtl28xxu_table[] = { + /* RTL2831U */ [RTL2831U_0BDA_2831] = { - USB_DEVICE(USB_VID_REALTEK, USB_PID_RTL2831U)}, + USB_DEVICE(USB_VID_REALTEK, USB_PID_REALTEK_RTL2831U)}, [RTL2831U_14AA_0160] = { - USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_FREECOM)}, - - [RTL2832U_0BDA_2832] = { - USB_DEVICE(USB_VID_REALTEK, USB_PID_RTL2832U)}, - [RTL2832U_1D19_1101] = { - USB_DEVICE(USB_VID_DEXATEK, USB_PID_DEXATEK_1101)}, + USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_FREECOM_DVBT)}, + /* RTL2832U */ {} /* terminating entry */ }; @@ -827,7 +811,7 @@ static struct dvb_usb_device_properties rtl28xxu_properties[] = { .endpoint = 0x81, .u = { .bulk = { - .buffersize = 4096, + .buffersize = 8*512, } } } @@ -853,15 +837,15 @@ static struct dvb_usb_device_properties rtl28xxu_properties[] = { .devices = { { .name = "Realtek RTL2831U reference design", - .cold_ids = {NULL}, .warm_ids = { - &rtl28xxu_table[RTL2831U_0BDA_2831], NULL}, + &rtl28xxu_table[RTL2831U_0BDA_2831], + }, }, { .name = "Freecom USB2.0 DVB-T", - .cold_ids = {NULL}, .warm_ids = { - &rtl28xxu_table[RTL2831U_14AA_0160], NULL}, + &rtl28xxu_table[RTL2831U_14AA_0160], + }, }, } }, @@ -888,7 +872,7 @@ static struct dvb_usb_device_properties rtl28xxu_properties[] = { .endpoint = 0x81, .u = { .bulk = { - .buffersize = 4096, + .buffersize = 8*512, } } } @@ -910,19 +894,10 @@ static struct dvb_usb_device_properties rtl28xxu_properties[] = { .i2c_algo = &rtl28xxu_i2c_algo, - .num_device_descs = 2, + .num_device_descs = 0, /* disabled as no support for RTL2832 */ .devices = { { .name = "Realtek RTL2832U reference design", - .cold_ids = {NULL}, - .warm_ids = { - &rtl28xxu_table[RTL2832U_0BDA_2832], NULL}, - }, - { - .name = "Dexatek dongle", - .cold_ids = {NULL}, - .warm_ids = { - &rtl28xxu_table[RTL2832U_1D19_1101], NULL}, }, } }, @@ -930,11 +905,11 @@ static struct dvb_usb_device_properties rtl28xxu_properties[] = { }; static int rtl28xxu_probe(struct usb_interface *intf, - const struct usb_device_id *id) + const struct usb_device_id *id) { int ret, i; int properties_count = ARRAY_SIZE(rtl28xxu_properties); - struct dvb_usb_device *d = NULL; + struct dvb_usb_device *d; deb_info("%s: interface=%d\n", __func__, intf->cur_altsetting->desc.bInterfaceNumber); @@ -944,7 +919,7 @@ static int rtl28xxu_probe(struct usb_interface *intf, for (i = 0; i < properties_count; i++) { ret = dvb_usb_device_init(intf, &rtl28xxu_properties[i], - THIS_MODULE, &d, adapter_nr); + THIS_MODULE, &d, adapter_nr); if (ret == 0 || ret != -ENODEV) break; } @@ -982,7 +957,9 @@ static struct usb_driver rtl28xxu_driver = { static int __init rtl28xxu_module_init(void) { int ret; + deb_info("%s:\n", __func__); + ret = usb_register(&rtl28xxu_driver); if (ret) err("usb_register failed=%d", ret); @@ -993,6 +970,7 @@ static int __init rtl28xxu_module_init(void) static void __exit rtl28xxu_module_exit(void) { deb_info("%s:\n", __func__); + /* deregister this driver from the USB subsystem */ usb_deregister(&rtl28xxu_driver); } diff --git a/drivers/media/dvb/dvb-usb/rtl28xxu.h b/drivers/media/dvb/dvb-usb/rtl28xxu.h index 2047b1bb0aa4..90f3bb4f4c0e 100644 --- a/drivers/media/dvb/dvb-usb/rtl28xxu.h +++ b/drivers/media/dvb/dvb-usb/rtl28xxu.h @@ -49,25 +49,27 @@ * USB commands * (usb_control_msg() index parameter) */ -#define DEMOD (0x00 << 8) -#define USB (0x01 << 8) -#define SYS (0x02 << 8) -#define I2C (0x03 << 8) -#define I2C_DA (0x06 << 8) -#define CMD_WR_FLAG 0x10 -#define CMD_DEMOD_RD (DEMOD) -#define CMD_DEMOD_WR (DEMOD | CMD_WR_FLAG) -#define CMD_USB_RD (USB) -#define CMD_USB_WR (USB | CMD_WR_FLAG) -#define CMD_SYS_RD (SYS) -#define CMD_IR_RD (CMD_SYS_RD | 0x01) -#define CMD_IR_WR (CMD_SYS_WR | 0x01) -#define CMD_SYS_WR (SYS | CMD_WR_FLAG) -#define CMD_I2C_RD (I2C) -#define CMD_I2C_WR (I2C | CMD_WR_FLAG) -#define CMD_I2C_DA_RD (I2C_DA) -#define CMD_I2C_DA_WR (I2C_DA | CMD_WR_FLAG) +#define DEMOD 0x0000 +#define USB 0x0100 +#define SYS 0x0200 +#define I2C 0x0300 +#define I2C_DA 0x0600 + +#define CMD_WR_FLAG 0x0010 +#define CMD_DEMOD_RD 0x0000 +#define CMD_DEMOD_WR 0x0010 +#define CMD_USB_RD 0x0100 +#define CMD_USB_WR 0x0110 +#define CMD_SYS_RD 0x0200 +#define CMD_IR_RD 0x0201 +#define CMD_IR_WR 0x0211 +#define CMD_SYS_WR 0x0210 +#define CMD_I2C_RD 0x0300 +#define CMD_I2C_WR 0x0310 +#define CMD_I2C_DA_RD 0x0600 +#define CMD_I2C_DA_WR 0x0610 + struct rtl28xxu_priv { u8 chip_id; @@ -77,13 +79,13 @@ struct rtl28xxu_priv { }; enum rtl28xxu_chip_id { - CHIP_ID_NONE = 0, + CHIP_ID_NONE, CHIP_ID_RTL2831U, CHIP_ID_RTL2832U, }; enum rtl28xxu_tuner { - TUNER_NONE = 0, + TUNER_NONE, TUNER_RTL2830_QT1010, TUNER_RTL2830_MT2060, -- cgit v1.2.3 From a8567cf22e0efb9faafa6cf33b607ca5aee3c2fa Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Sat, 21 Jan 2012 22:40:58 -0300 Subject: [media] rtl2830: prevent .read_status() when sleeping Hardware is not accessible when device is sleeping. Preventing such IOCTLs when sleep should be job of DVB CORE... Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/rtl28xxu.c | 5 ----- drivers/media/dvb/frontends/rtl2830.c | 15 +++++++++++++++ drivers/media/dvb/frontends/rtl2830_priv.h | 2 ++ 3 files changed, 17 insertions(+), 5 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/dvb-usb/rtl28xxu.c b/drivers/media/dvb/dvb-usb/rtl28xxu.c index b5785fa36220..07597c53d07b 100644 --- a/drivers/media/dvb/dvb-usb/rtl28xxu.c +++ b/drivers/media/dvb/dvb-usb/rtl28xxu.c @@ -608,11 +608,6 @@ static int rtl28xxu_power_ctrl(struct dvb_usb_device *d, int onoff) sys0 = sys0 & 0x0f; sys0 |= 0xe0; } else { - /* - * FIXME: Use .fe_ioctl_override() to prevent demod - * IOCTLs in case of device is powered off. Or change - * RTL2830 demod not perform requestesd IOCTL & IO when sleep. - */ gpio &= (~0x01); /* GPIO0 = 0 */ gpio |= 0x10; /* GPIO4 = 1 */ sys0 = sys0 & (~0xc0); diff --git a/drivers/media/dvb/frontends/rtl2830.c b/drivers/media/dvb/frontends/rtl2830.c index f036701c12ee..f971d949b2af 100644 --- a/drivers/media/dvb/frontends/rtl2830.c +++ b/drivers/media/dvb/frontends/rtl2830.c @@ -273,12 +273,21 @@ static int rtl2830_init(struct dvb_frontend *fe) if (ret) goto err; + priv->sleeping = false; + return ret; err: dbg("%s: failed=%d", __func__, ret); return ret; } +static int rtl2830_sleep(struct dvb_frontend *fe) +{ + struct rtl2830_priv *priv = fe->demodulator_priv; + priv->sleeping = true; + return 0; +} + int rtl2830_get_tune_settings(struct dvb_frontend *fe, struct dvb_frontend_tune_settings *s) { @@ -372,6 +381,9 @@ static int rtl2830_read_status(struct dvb_frontend *fe, fe_status_t *status) u8 tmp; *status = 0; + if (priv->sleeping) + return 0; + ret = rtl2830_rd_reg_mask(priv, 0x351, &tmp, 0x78); /* [6:3] */ if (ret) goto err; @@ -498,6 +510,8 @@ struct dvb_frontend *rtl2830_attach(const struct rtl2830_config *cfg, goto err; } + priv->sleeping = true; + return &priv->fe; err: dbg("%s: failed=%d", __func__, ret); @@ -530,6 +544,7 @@ static struct dvb_frontend_ops rtl2830_ops = { .release = rtl2830_release, .init = rtl2830_init, + .sleep = rtl2830_sleep, .get_tune_settings = rtl2830_get_tune_settings, diff --git a/drivers/media/dvb/frontends/rtl2830_priv.h b/drivers/media/dvb/frontends/rtl2830_priv.h index 49de01dd5e83..4a464761b5b8 100644 --- a/drivers/media/dvb/frontends/rtl2830_priv.h +++ b/drivers/media/dvb/frontends/rtl2830_priv.h @@ -43,6 +43,8 @@ struct rtl2830_priv { struct rtl2830_config cfg; struct i2c_adapter tuner_i2c_adapter; + bool sleeping; + u8 page; /* active register page */ }; -- cgit v1.2.3 From 479e3492a262196631d69a9245a45420a354bec5 Mon Sep 17 00:00:00 2001 From: Gianluca Gennari Date: Sun, 4 Mar 2012 18:19:41 -0300 Subject: [media] rtl2830: __udivdi3 undefined Il 29/02/2012 22:30, Geert Uytterhoeven ha scritto: > http://kisskb.ellerman.id.au/kisskb/buildresult/5759200/ ERROR: > "__udivdi3" [drivers/media/dvb/frontends/rtl2830.ko] undefined! > The following patch fixed the warning on my 32 bit system. Signed-off-by: Gianluca Gennari Acked-by: Geert Uytterhoeven Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/rtl2830.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/frontends/rtl2830.c b/drivers/media/dvb/frontends/rtl2830.c index f971d949b2af..45196c5b0736 100644 --- a/drivers/media/dvb/frontends/rtl2830.c +++ b/drivers/media/dvb/frontends/rtl2830.c @@ -244,7 +244,7 @@ static int rtl2830_init(struct dvb_frontend *fe) num = priv->cfg.if_dvbt % priv->cfg.xtal; num *= 0x400000; - num /= priv->cfg.xtal; + num = div_u64(num, priv->cfg.xtal); num = -num; if_ctl = num & 0x3fffff; dbg("%s: if_ctl=%08x", __func__, if_ctl); -- cgit v1.2.3 From c6e8d86fffd8edf1bfccbd441b1812ee919fe3d5 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Sun, 12 Feb 2012 06:56:32 -0300 Subject: [media] convert drivers/media/* to use module_i2c_driver() This patch converts the drivers in drivers/media/* to use the module_i2_driver() macro which makes the code smaller and a bit simpler. Signed-off-by: Axel Lin Cc: Kyungmin Park Cc: Heungjun Kim Cc: Joonyoung Shim Cc: Andrew Chew Cc: Paul Mundt Cc: Michael Grzeschik Cc: Johannes Obermaier Cc: Steven Toth Acked-by: Laurent Pinchart Acked-by: Sylwester Nawrocki Acked-by: Tomasz Stanislawski Acked-by: Hans Verkuil Acked-by: Guennadi Liakhovetski Acked-by: Mauro Carvalho Chehab Acked-by: Jonathan Corbet Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/au8522_decoder.c | 13 +------------ drivers/media/radio/radio-tea5764.c | 19 +----------------- drivers/media/radio/saa7706h.c | 13 +------------ drivers/media/radio/si470x/radio-si470x-i2c.c | 28 +-------------------------- drivers/media/radio/si4713-i2c.c | 15 +------------- drivers/media/radio/tef6862.c | 14 +------------- drivers/media/video/adp1653.c | 19 +----------------- drivers/media/video/adv7170.c | 13 +------------ drivers/media/video/adv7175.c | 13 +------------ drivers/media/video/adv7180.c | 14 +------------- drivers/media/video/adv7343.c | 13 +------------ drivers/media/video/ak881x.c | 13 +------------ drivers/media/video/as3645a.c | 19 +----------------- drivers/media/video/bt819.c | 13 +------------ drivers/media/video/bt856.c | 13 +------------ drivers/media/video/bt866.c | 13 +------------ drivers/media/video/cs5345.c | 13 +------------ drivers/media/video/cs53l32a.c | 13 +------------ drivers/media/video/cx25840/cx25840-core.c | 13 +------------ drivers/media/video/imx074.c | 13 +------------ drivers/media/video/indycam.c | 13 +------------ drivers/media/video/ir-kbd-i2c.c | 17 +++------------- drivers/media/video/ks0127.c | 13 +------------ drivers/media/video/m52790.c | 13 +------------ drivers/media/video/m5mols/m5mols_core.c | 13 +------------ drivers/media/video/msp3400-driver.c | 13 +------------ drivers/media/video/mt9m001.c | 13 +------------ drivers/media/video/mt9m111.c | 13 +------------ drivers/media/video/mt9p031.c | 13 +------------ drivers/media/video/mt9t001.c | 13 +------------ drivers/media/video/mt9t031.c | 13 +------------ drivers/media/video/mt9t112.c | 16 +-------------- drivers/media/video/mt9v011.c | 13 +------------ drivers/media/video/mt9v022.c | 13 +------------ drivers/media/video/mt9v032.c | 13 +------------ drivers/media/video/noon010pc30.c | 13 +------------ drivers/media/video/ov2640.c | 16 +-------------- drivers/media/video/ov5642.c | 13 +------------ drivers/media/video/ov6650.c | 13 +------------ drivers/media/video/ov7670.c | 13 +------------ drivers/media/video/ov772x.c | 17 +--------------- drivers/media/video/ov9640.c | 13 +------------ drivers/media/video/ov9740.c | 13 +------------ drivers/media/video/rj54n1cb0c.c | 13 +------------ drivers/media/video/s5k6aa.c | 13 +------------ drivers/media/video/s5p-tv/hdmiphy_drv.c | 12 +----------- drivers/media/video/saa6588.c | 13 +------------ drivers/media/video/saa7110.c | 13 +------------ drivers/media/video/saa7115.c | 13 +------------ drivers/media/video/saa7127.c | 13 +------------ drivers/media/video/saa7134/saa6752hs.c | 13 +------------ drivers/media/video/saa717x.c | 13 +------------ drivers/media/video/saa7185.c | 13 +------------ drivers/media/video/saa7191.c | 13 +------------ drivers/media/video/sr030pc30.c | 13 +------------ drivers/media/video/tda7432.c | 13 +------------ drivers/media/video/tda9840.c | 13 +------------ drivers/media/video/tea6415c.c | 13 +------------ drivers/media/video/tea6420.c | 13 +------------ drivers/media/video/ths7303.c | 14 +------------- drivers/media/video/tlv320aic23b.c | 13 +------------ drivers/media/video/tuner-core.c | 13 +------------ drivers/media/video/tvaudio.c | 13 +------------ drivers/media/video/tvp514x.c | 13 +------------ drivers/media/video/tvp5150.c | 13 +------------ drivers/media/video/tvp7002.c | 25 +----------------------- drivers/media/video/tw9910.c | 16 +-------------- drivers/media/video/upd64031a.c | 13 +------------ drivers/media/video/upd64083.c | 13 +------------ drivers/media/video/vp27smpx.c | 13 +------------ drivers/media/video/vpx3220.c | 13 +------------ drivers/media/video/wm8739.c | 13 +------------ drivers/media/video/wm8775.c | 13 +------------ 73 files changed, 75 insertions(+), 940 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/frontends/au8522_decoder.c b/drivers/media/dvb/frontends/au8522_decoder.c index 2b248c12f404..55b6390198e3 100644 --- a/drivers/media/dvb/frontends/au8522_decoder.c +++ b/drivers/media/dvb/frontends/au8522_decoder.c @@ -839,15 +839,4 @@ static struct i2c_driver au8522_driver = { .id_table = au8522_id, }; -static __init int init_au8522(void) -{ - return i2c_add_driver(&au8522_driver); -} - -static __exit void exit_au8522(void) -{ - i2c_del_driver(&au8522_driver); -} - -module_init(init_au8522); -module_exit(exit_au8522); +module_i2c_driver(au8522_driver); diff --git a/drivers/media/radio/radio-tea5764.c b/drivers/media/radio/radio-tea5764.c index db20904d01f0..6b1fae32b483 100644 --- a/drivers/media/radio/radio-tea5764.c +++ b/drivers/media/radio/radio-tea5764.c @@ -575,21 +575,7 @@ static struct i2c_driver tea5764_i2c_driver = { .id_table = tea5764_id, }; -/* init the driver */ -static int __init tea5764_init(void) -{ - int ret = i2c_add_driver(&tea5764_i2c_driver); - - printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ": " - DRIVER_DESC "\n"); - return ret; -} - -/* cleanup the driver */ -static void __exit tea5764_exit(void) -{ - i2c_del_driver(&tea5764_i2c_driver); -} +module_i2c_driver(tea5764_i2c_driver); MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); @@ -600,6 +586,3 @@ module_param(use_xtal, int, 0); MODULE_PARM_DESC(use_xtal, "Chip have a xtal connected in board"); module_param(radio_nr, int, 0); MODULE_PARM_DESC(radio_nr, "video4linux device number to use"); - -module_init(tea5764_init); -module_exit(tea5764_exit); diff --git a/drivers/media/radio/saa7706h.c b/drivers/media/radio/saa7706h.c index b1193dfc5087..9474706350f8 100644 --- a/drivers/media/radio/saa7706h.c +++ b/drivers/media/radio/saa7706h.c @@ -434,18 +434,7 @@ static struct i2c_driver saa7706h_driver = { .id_table = saa7706h_id, }; -static __init int saa7706h_init(void) -{ - return i2c_add_driver(&saa7706h_driver); -} - -static __exit void saa7706h_exit(void) -{ - i2c_del_driver(&saa7706h_driver); -} - -module_init(saa7706h_init); -module_exit(saa7706h_exit); +module_i2c_driver(saa7706h_driver); MODULE_DESCRIPTION("SAA7706H Car Radio DSP driver"); MODULE_AUTHOR("Mocean Laboratories"); diff --git a/drivers/media/radio/si470x/radio-si470x-i2c.c b/drivers/media/radio/si470x/radio-si470x-i2c.c index fd3541b0e91c..9b546a5523f3 100644 --- a/drivers/media/radio/si470x/radio-si470x-i2c.c +++ b/drivers/media/radio/si470x/radio-si470x-i2c.c @@ -539,33 +539,7 @@ static struct i2c_driver si470x_i2c_driver = { .id_table = si470x_i2c_id, }; - - -/************************************************************************** - * Module Interface - **************************************************************************/ - -/* - * si470x_i2c_init - module init - */ -static int __init si470x_i2c_init(void) -{ - printk(KERN_INFO DRIVER_DESC ", Version " DRIVER_VERSION "\n"); - return i2c_add_driver(&si470x_i2c_driver); -} - - -/* - * si470x_i2c_exit - module exit - */ -static void __exit si470x_i2c_exit(void) -{ - i2c_del_driver(&si470x_i2c_driver); -} - - -module_init(si470x_i2c_init); -module_exit(si470x_i2c_exit); +module_i2c_driver(si470x_i2c_driver); MODULE_LICENSE("GPL"); MODULE_AUTHOR(DRIVER_AUTHOR); diff --git a/drivers/media/radio/si4713-i2c.c b/drivers/media/radio/si4713-i2c.c index 27aba936fb2b..b898c8925ab7 100644 --- a/drivers/media/radio/si4713-i2c.c +++ b/drivers/media/radio/si4713-i2c.c @@ -2106,17 +2106,4 @@ static struct i2c_driver si4713_i2c_driver = { .id_table = si4713_id, }; -/* Module Interface */ -static int __init si4713_module_init(void) -{ - return i2c_add_driver(&si4713_i2c_driver); -} - -static void __exit si4713_module_exit(void) -{ - i2c_del_driver(&si4713_i2c_driver); -} - -module_init(si4713_module_init); -module_exit(si4713_module_exit); - +module_i2c_driver(si4713_i2c_driver); diff --git a/drivers/media/radio/tef6862.c b/drivers/media/radio/tef6862.c index 3408685b690c..6418c4c9faf1 100644 --- a/drivers/media/radio/tef6862.c +++ b/drivers/media/radio/tef6862.c @@ -215,20 +215,8 @@ static struct i2c_driver tef6862_driver = { .id_table = tef6862_id, }; -static __init int tef6862_init(void) -{ - return i2c_add_driver(&tef6862_driver); -} - -static __exit void tef6862_exit(void) -{ - i2c_del_driver(&tef6862_driver); -} - -module_init(tef6862_init); -module_exit(tef6862_exit); +module_i2c_driver(tef6862_driver); MODULE_DESCRIPTION("TEF6862 Car Radio Enhanced Selectivity Tuner"); MODULE_AUTHOR("Mocean Laboratories"); MODULE_LICENSE("GPL v2"); - diff --git a/drivers/media/video/adp1653.c b/drivers/media/video/adp1653.c index 12eedf4d515a..0d13f052997e 100644 --- a/drivers/media/video/adp1653.c +++ b/drivers/media/video/adp1653.c @@ -482,24 +482,7 @@ static struct i2c_driver adp1653_i2c_driver = { .id_table = adp1653_id_table, }; -static int __init adp1653_init(void) -{ - int rval; - - rval = i2c_add_driver(&adp1653_i2c_driver); - if (rval) - printk(KERN_ALERT "%s: failed at i2c_add_driver\n", __func__); - - return rval; -} - -static void __exit adp1653_exit(void) -{ - i2c_del_driver(&adp1653_i2c_driver); -} - -module_init(adp1653_init); -module_exit(adp1653_exit); +module_i2c_driver(adp1653_i2c_driver); MODULE_AUTHOR("Sakari Ailus "); MODULE_DESCRIPTION("Analog Devices ADP1653 LED flash driver"); diff --git a/drivers/media/video/adv7170.c b/drivers/media/video/adv7170.c index 879f1d839760..6bc01fb98ff8 100644 --- a/drivers/media/video/adv7170.c +++ b/drivers/media/video/adv7170.c @@ -407,15 +407,4 @@ static struct i2c_driver adv7170_driver = { .id_table = adv7170_id, }; -static __init int init_adv7170(void) -{ - return i2c_add_driver(&adv7170_driver); -} - -static __exit void exit_adv7170(void) -{ - i2c_del_driver(&adv7170_driver); -} - -module_init(init_adv7170); -module_exit(exit_adv7170); +module_i2c_driver(adv7170_driver); diff --git a/drivers/media/video/adv7175.c b/drivers/media/video/adv7175.c index 206078eca853..c7640fab5730 100644 --- a/drivers/media/video/adv7175.c +++ b/drivers/media/video/adv7175.c @@ -457,15 +457,4 @@ static struct i2c_driver adv7175_driver = { .id_table = adv7175_id, }; -static __init int init_adv7175(void) -{ - return i2c_add_driver(&adv7175_driver); -} - -static __exit void exit_adv7175(void) -{ - i2c_del_driver(&adv7175_driver); -} - -module_init(init_adv7175); -module_exit(exit_adv7175); +module_i2c_driver(adv7175_driver); diff --git a/drivers/media/video/adv7180.c b/drivers/media/video/adv7180.c index d2138d06bcad..b8b6c4b0cad4 100644 --- a/drivers/media/video/adv7180.c +++ b/drivers/media/video/adv7180.c @@ -444,20 +444,8 @@ static struct i2c_driver adv7180_driver = { .id_table = adv7180_id, }; -static __init int adv7180_init(void) -{ - return i2c_add_driver(&adv7180_driver); -} - -static __exit void adv7180_exit(void) -{ - i2c_del_driver(&adv7180_driver); -} - -module_init(adv7180_init); -module_exit(adv7180_exit); +module_i2c_driver(adv7180_driver); MODULE_DESCRIPTION("Analog Devices ADV7180 video decoder driver"); MODULE_AUTHOR("Mocean Laboratories"); MODULE_LICENSE("GPL v2"); - diff --git a/drivers/media/video/adv7343.c b/drivers/media/video/adv7343.c index 021fab23070d..119b60401bf3 100644 --- a/drivers/media/video/adv7343.c +++ b/drivers/media/video/adv7343.c @@ -475,15 +475,4 @@ static struct i2c_driver adv7343_driver = { .id_table = adv7343_id, }; -static __init int init_adv7343(void) -{ - return i2c_add_driver(&adv7343_driver); -} - -static __exit void exit_adv7343(void) -{ - i2c_del_driver(&adv7343_driver); -} - -module_init(init_adv7343); -module_exit(exit_adv7343); +module_i2c_driver(adv7343_driver); diff --git a/drivers/media/video/ak881x.c b/drivers/media/video/ak881x.c index 53c496c00fb6..ba674656b10d 100644 --- a/drivers/media/video/ak881x.c +++ b/drivers/media/video/ak881x.c @@ -352,18 +352,7 @@ static struct i2c_driver ak881x_i2c_driver = { .id_table = ak881x_id, }; -static int __init ak881x_module_init(void) -{ - return i2c_add_driver(&ak881x_i2c_driver); -} - -static void __exit ak881x_module_exit(void) -{ - i2c_del_driver(&ak881x_i2c_driver); -} - -module_init(ak881x_module_init); -module_exit(ak881x_module_exit); +module_i2c_driver(ak881x_i2c_driver); MODULE_DESCRIPTION("TV-output driver for ak8813/ak8814"); MODULE_AUTHOR("Guennadi Liakhovetski "); diff --git a/drivers/media/video/as3645a.c b/drivers/media/video/as3645a.c index f241702a0f36..7a3371f044fc 100644 --- a/drivers/media/video/as3645a.c +++ b/drivers/media/video/as3645a.c @@ -881,24 +881,7 @@ static struct i2c_driver as3645a_i2c_driver = { .id_table = as3645a_id_table, }; -static int __init as3645a_init(void) -{ - int rval; - - rval = i2c_add_driver(&as3645a_i2c_driver); - if (rval) - pr_err("%s: Failed to register the driver\n", AS3645A_NAME); - - return rval; -} - -static void __exit as3645a_exit(void) -{ - i2c_del_driver(&as3645a_i2c_driver); -} - -module_init(as3645a_init); -module_exit(as3645a_exit); +module_i2c_driver(as3645a_i2c_driver); MODULE_AUTHOR("Laurent Pinchart "); MODULE_DESCRIPTION("LED flash driver for AS3645A, LM3555 and their clones"); diff --git a/drivers/media/video/bt819.c b/drivers/media/video/bt819.c index 859eabf57978..377bf05b1efd 100644 --- a/drivers/media/video/bt819.c +++ b/drivers/media/video/bt819.c @@ -514,15 +514,4 @@ static struct i2c_driver bt819_driver = { .id_table = bt819_id, }; -static __init int init_bt819(void) -{ - return i2c_add_driver(&bt819_driver); -} - -static __exit void exit_bt819(void) -{ - i2c_del_driver(&bt819_driver); -} - -module_init(init_bt819); -module_exit(exit_bt819); +module_i2c_driver(bt819_driver); diff --git a/drivers/media/video/bt856.c b/drivers/media/video/bt856.c index a43059d4c799..7e5bd365c239 100644 --- a/drivers/media/video/bt856.c +++ b/drivers/media/video/bt856.c @@ -270,15 +270,4 @@ static struct i2c_driver bt856_driver = { .id_table = bt856_id, }; -static __init int init_bt856(void) -{ - return i2c_add_driver(&bt856_driver); -} - -static __exit void exit_bt856(void) -{ - i2c_del_driver(&bt856_driver); -} - -module_init(init_bt856); -module_exit(exit_bt856); +module_i2c_driver(bt856_driver); diff --git a/drivers/media/video/bt866.c b/drivers/media/video/bt866.c index 4e5dcea0501d..905320b67a1c 100644 --- a/drivers/media/video/bt866.c +++ b/drivers/media/video/bt866.c @@ -240,15 +240,4 @@ static struct i2c_driver bt866_driver = { .id_table = bt866_id, }; -static __init int init_bt866(void) -{ - return i2c_add_driver(&bt866_driver); -} - -static __exit void exit_bt866(void) -{ - i2c_del_driver(&bt866_driver); -} - -module_init(init_bt866); -module_exit(exit_bt866); +module_i2c_driver(bt866_driver); diff --git a/drivers/media/video/cs5345.c b/drivers/media/video/cs5345.c index 1d64af9adf71..c8581e26fa9c 100644 --- a/drivers/media/video/cs5345.c +++ b/drivers/media/video/cs5345.c @@ -249,15 +249,4 @@ static struct i2c_driver cs5345_driver = { .id_table = cs5345_id, }; -static __init int init_cs5345(void) -{ - return i2c_add_driver(&cs5345_driver); -} - -static __exit void exit_cs5345(void) -{ - i2c_del_driver(&cs5345_driver); -} - -module_init(init_cs5345); -module_exit(exit_cs5345); +module_i2c_driver(cs5345_driver); diff --git a/drivers/media/video/cs53l32a.c b/drivers/media/video/cs53l32a.c index 51c5b9ad67d8..b293912206eb 100644 --- a/drivers/media/video/cs53l32a.c +++ b/drivers/media/video/cs53l32a.c @@ -248,15 +248,4 @@ static struct i2c_driver cs53l32a_driver = { .id_table = cs53l32a_id, }; -static __init int init_cs53l32a(void) -{ - return i2c_add_driver(&cs53l32a_driver); -} - -static __exit void exit_cs53l32a(void) -{ - i2c_del_driver(&cs53l32a_driver); -} - -module_init(init_cs53l32a); -module_exit(exit_cs53l32a); +module_i2c_driver(cs53l32a_driver); diff --git a/drivers/media/video/cx25840/cx25840-core.c b/drivers/media/video/cx25840/cx25840-core.c index 05247d4c340a..fc1ff69cffd0 100644 --- a/drivers/media/video/cx25840/cx25840-core.c +++ b/drivers/media/video/cx25840/cx25840-core.c @@ -5301,15 +5301,4 @@ static struct i2c_driver cx25840_driver = { .id_table = cx25840_id, }; -static __init int init_cx25840(void) -{ - return i2c_add_driver(&cx25840_driver); -} - -static __exit void exit_cx25840(void) -{ - i2c_del_driver(&cx25840_driver); -} - -module_init(init_cx25840); -module_exit(exit_cx25840); +module_i2c_driver(cx25840_driver); diff --git a/drivers/media/video/imx074.c b/drivers/media/video/imx074.c index eec75bb57203..351e9bafe8fe 100644 --- a/drivers/media/video/imx074.c +++ b/drivers/media/video/imx074.c @@ -468,18 +468,7 @@ static struct i2c_driver imx074_i2c_driver = { .id_table = imx074_id, }; -static int __init imx074_mod_init(void) -{ - return i2c_add_driver(&imx074_i2c_driver); -} - -static void __exit imx074_mod_exit(void) -{ - i2c_del_driver(&imx074_i2c_driver); -} - -module_init(imx074_mod_init); -module_exit(imx074_mod_exit); +module_i2c_driver(imx074_i2c_driver); MODULE_DESCRIPTION("Sony IMX074 Camera driver"); MODULE_AUTHOR("Guennadi Liakhovetski "); diff --git a/drivers/media/video/indycam.c b/drivers/media/video/indycam.c index e5ed4db32e7b..548236333cce 100644 --- a/drivers/media/video/indycam.c +++ b/drivers/media/video/indycam.c @@ -387,15 +387,4 @@ static struct i2c_driver indycam_driver = { .id_table = indycam_id, }; -static __init int init_indycam(void) -{ - return i2c_add_driver(&indycam_driver); -} - -static __exit void exit_indycam(void) -{ - i2c_del_driver(&indycam_driver); -} - -module_init(init_indycam); -module_exit(exit_indycam); +module_i2c_driver(indycam_driver); diff --git a/drivers/media/video/ir-kbd-i2c.c b/drivers/media/video/ir-kbd-i2c.c index a7c41d32f414..04f192a0398a 100644 --- a/drivers/media/video/ir-kbd-i2c.c +++ b/drivers/media/video/ir-kbd-i2c.c @@ -471,7 +471,7 @@ static const struct i2c_device_id ir_kbd_id[] = { { } }; -static struct i2c_driver driver = { +static struct i2c_driver ir_kbd_driver = { .driver = { .name = "ir-kbd-i2c", }, @@ -480,21 +480,10 @@ static struct i2c_driver driver = { .id_table = ir_kbd_id, }; +module_i2c_driver(ir_kbd_driver); + /* ----------------------------------------------------------------------- */ MODULE_AUTHOR("Gerd Knorr, Michal Kochanowicz, Christoph Bartelmus, Ulrich Mueller"); MODULE_DESCRIPTION("input driver for i2c IR remote controls"); MODULE_LICENSE("GPL"); - -static int __init ir_init(void) -{ - return i2c_add_driver(&driver); -} - -static void __exit ir_fini(void) -{ - i2c_del_driver(&driver); -} - -module_init(ir_init); -module_exit(ir_fini); diff --git a/drivers/media/video/ks0127.c b/drivers/media/video/ks0127.c index afa91182b448..ee7ca2dcca2f 100644 --- a/drivers/media/video/ks0127.c +++ b/drivers/media/video/ks0127.c @@ -721,15 +721,4 @@ static struct i2c_driver ks0127_driver = { .id_table = ks0127_id, }; -static __init int init_ks0127(void) -{ - return i2c_add_driver(&ks0127_driver); -} - -static __exit void exit_ks0127(void) -{ - i2c_del_driver(&ks0127_driver); -} - -module_init(init_ks0127); -module_exit(exit_ks0127); +module_i2c_driver(ks0127_driver); diff --git a/drivers/media/video/m52790.c b/drivers/media/video/m52790.c index 303ffa7df4ac..0991576f4c82 100644 --- a/drivers/media/video/m52790.c +++ b/drivers/media/video/m52790.c @@ -213,15 +213,4 @@ static struct i2c_driver m52790_driver = { .id_table = m52790_id, }; -static __init int init_m52790(void) -{ - return i2c_add_driver(&m52790_driver); -} - -static __exit void exit_m52790(void) -{ - i2c_del_driver(&m52790_driver); -} - -module_init(init_m52790); -module_exit(exit_m52790); +module_i2c_driver(m52790_driver); diff --git a/drivers/media/video/m5mols/m5mols_core.c b/drivers/media/video/m5mols/m5mols_core.c index e631d0d77ce1..d718aee01c77 100644 --- a/drivers/media/video/m5mols/m5mols_core.c +++ b/drivers/media/video/m5mols/m5mols_core.c @@ -1057,18 +1057,7 @@ static struct i2c_driver m5mols_i2c_driver = { .id_table = m5mols_id, }; -static int __init m5mols_mod_init(void) -{ - return i2c_add_driver(&m5mols_i2c_driver); -} - -static void __exit m5mols_mod_exit(void) -{ - i2c_del_driver(&m5mols_i2c_driver); -} - -module_init(m5mols_mod_init); -module_exit(m5mols_mod_exit); +module_i2c_driver(m5mols_i2c_driver); MODULE_AUTHOR("HeungJun Kim "); MODULE_AUTHOR("Dongsoo Kim "); diff --git a/drivers/media/video/msp3400-driver.c b/drivers/media/video/msp3400-driver.c index d7cd0f633f63..82ce50721de3 100644 --- a/drivers/media/video/msp3400-driver.c +++ b/drivers/media/video/msp3400-driver.c @@ -881,18 +881,7 @@ static struct i2c_driver msp_driver = { .id_table = msp_id, }; -static __init int init_msp(void) -{ - return i2c_add_driver(&msp_driver); -} - -static __exit void exit_msp(void) -{ - i2c_del_driver(&msp_driver); -} - -module_init(init_msp); -module_exit(exit_msp); +module_i2c_driver(msp_driver); /* * Overrides for Emacs so that we follow Linus's tabbing style. diff --git a/drivers/media/video/mt9m001.c b/drivers/media/video/mt9m001.c index 097c9d3d04a8..7e648183f157 100644 --- a/drivers/media/video/mt9m001.c +++ b/drivers/media/video/mt9m001.c @@ -730,18 +730,7 @@ static struct i2c_driver mt9m001_i2c_driver = { .id_table = mt9m001_id, }; -static int __init mt9m001_mod_init(void) -{ - return i2c_add_driver(&mt9m001_i2c_driver); -} - -static void __exit mt9m001_mod_exit(void) -{ - i2c_del_driver(&mt9m001_i2c_driver); -} - -module_init(mt9m001_mod_init); -module_exit(mt9m001_mod_exit); +module_i2c_driver(mt9m001_i2c_driver); MODULE_DESCRIPTION("Micron MT9M001 Camera driver"); MODULE_AUTHOR("Guennadi Liakhovetski "); diff --git a/drivers/media/video/mt9m111.c b/drivers/media/video/mt9m111.c index bee65bff46e8..b0c529964329 100644 --- a/drivers/media/video/mt9m111.c +++ b/drivers/media/video/mt9m111.c @@ -1008,18 +1008,7 @@ static struct i2c_driver mt9m111_i2c_driver = { .id_table = mt9m111_id, }; -static int __init mt9m111_mod_init(void) -{ - return i2c_add_driver(&mt9m111_i2c_driver); -} - -static void __exit mt9m111_mod_exit(void) -{ - i2c_del_driver(&mt9m111_i2c_driver); -} - -module_init(mt9m111_mod_init); -module_exit(mt9m111_mod_exit); +module_i2c_driver(mt9m111_i2c_driver); MODULE_DESCRIPTION("Micron/Aptina MT9M111/MT9M112/MT9M131 Camera driver"); MODULE_AUTHOR("Robert Jarzmik"); diff --git a/drivers/media/video/mt9p031.c b/drivers/media/video/mt9p031.c index 93c3ec7426e8..dde26105aac7 100644 --- a/drivers/media/video/mt9p031.c +++ b/drivers/media/video/mt9p031.c @@ -945,18 +945,7 @@ static struct i2c_driver mt9p031_i2c_driver = { .id_table = mt9p031_id, }; -static int __init mt9p031_mod_init(void) -{ - return i2c_add_driver(&mt9p031_i2c_driver); -} - -static void __exit mt9p031_mod_exit(void) -{ - i2c_del_driver(&mt9p031_i2c_driver); -} - -module_init(mt9p031_mod_init); -module_exit(mt9p031_mod_exit); +module_i2c_driver(mt9p031_i2c_driver); MODULE_DESCRIPTION("Aptina MT9P031 Camera driver"); MODULE_AUTHOR("Bastian Hecht "); diff --git a/drivers/media/video/mt9t001.c b/drivers/media/video/mt9t001.c index cd81d04a529e..49ca3cbfc6f1 100644 --- a/drivers/media/video/mt9t001.c +++ b/drivers/media/video/mt9t001.c @@ -817,18 +817,7 @@ static struct i2c_driver mt9t001_driver = { .id_table = mt9t001_id, }; -static int __init mt9t001_init(void) -{ - return i2c_add_driver(&mt9t001_driver); -} - -static void __exit mt9t001_exit(void) -{ - i2c_del_driver(&mt9t001_driver); -} - -module_init(mt9t001_init); -module_exit(mt9t001_exit); +module_i2c_driver(mt9t001_driver); MODULE_DESCRIPTION("Aptina (Micron) MT9T001 Camera driver"); MODULE_AUTHOR("Laurent Pinchart "); diff --git a/drivers/media/video/mt9t031.c b/drivers/media/video/mt9t031.c index 84add1aef139..1415074138a5 100644 --- a/drivers/media/video/mt9t031.c +++ b/drivers/media/video/mt9t031.c @@ -850,18 +850,7 @@ static struct i2c_driver mt9t031_i2c_driver = { .id_table = mt9t031_id, }; -static int __init mt9t031_mod_init(void) -{ - return i2c_add_driver(&mt9t031_i2c_driver); -} - -static void __exit mt9t031_mod_exit(void) -{ - i2c_del_driver(&mt9t031_i2c_driver); -} - -module_init(mt9t031_mod_init); -module_exit(mt9t031_mod_exit); +module_i2c_driver(mt9t031_i2c_driver); MODULE_DESCRIPTION("Micron MT9T031 Camera driver"); MODULE_AUTHOR("Guennadi Liakhovetski "); diff --git a/drivers/media/video/mt9t112.c b/drivers/media/video/mt9t112.c index 7b34b11daf24..8d1445f12708 100644 --- a/drivers/media/video/mt9t112.c +++ b/drivers/media/video/mt9t112.c @@ -1117,21 +1117,7 @@ static struct i2c_driver mt9t112_i2c_driver = { .id_table = mt9t112_id, }; -/************************************************************************ - module function -************************************************************************/ -static int __init mt9t112_module_init(void) -{ - return i2c_add_driver(&mt9t112_i2c_driver); -} - -static void __exit mt9t112_module_exit(void) -{ - i2c_del_driver(&mt9t112_i2c_driver); -} - -module_init(mt9t112_module_init); -module_exit(mt9t112_module_exit); +module_i2c_driver(mt9t112_i2c_driver); MODULE_DESCRIPTION("SoC Camera driver for mt9t112"); MODULE_AUTHOR("Kuninori Morimoto"); diff --git a/drivers/media/video/mt9v011.c b/drivers/media/video/mt9v011.c index db74dd27c722..6bf01ad62765 100644 --- a/drivers/media/video/mt9v011.c +++ b/drivers/media/video/mt9v011.c @@ -709,15 +709,4 @@ static struct i2c_driver mt9v011_driver = { .id_table = mt9v011_id, }; -static __init int init_mt9v011(void) -{ - return i2c_add_driver(&mt9v011_driver); -} - -static __exit void exit_mt9v011(void) -{ - i2c_del_driver(&mt9v011_driver); -} - -module_init(init_mt9v011); -module_exit(exit_mt9v011); +module_i2c_driver(mt9v011_driver); diff --git a/drivers/media/video/mt9v022.c b/drivers/media/video/mt9v022.c index 944940758fa3..bf63417adb8f 100644 --- a/drivers/media/video/mt9v022.c +++ b/drivers/media/video/mt9v022.c @@ -872,18 +872,7 @@ static struct i2c_driver mt9v022_i2c_driver = { .id_table = mt9v022_id, }; -static int __init mt9v022_mod_init(void) -{ - return i2c_add_driver(&mt9v022_i2c_driver); -} - -static void __exit mt9v022_mod_exit(void) -{ - i2c_del_driver(&mt9v022_i2c_driver); -} - -module_init(mt9v022_mod_init); -module_exit(mt9v022_mod_exit); +module_i2c_driver(mt9v022_i2c_driver); MODULE_DESCRIPTION("Micron MT9V022 Camera driver"); MODULE_AUTHOR("Guennadi Liakhovetski "); diff --git a/drivers/media/video/mt9v032.c b/drivers/media/video/mt9v032.c index d90b982cc218..75e253a343c5 100644 --- a/drivers/media/video/mt9v032.c +++ b/drivers/media/video/mt9v032.c @@ -756,18 +756,7 @@ static struct i2c_driver mt9v032_driver = { .id_table = mt9v032_id, }; -static int __init mt9v032_init(void) -{ - return i2c_add_driver(&mt9v032_driver); -} - -static void __exit mt9v032_exit(void) -{ - i2c_del_driver(&mt9v032_driver); -} - -module_init(mt9v032_init); -module_exit(mt9v032_exit); +module_i2c_driver(mt9v032_driver); MODULE_DESCRIPTION("Aptina MT9V032 Camera driver"); MODULE_AUTHOR("Laurent Pinchart "); diff --git a/drivers/media/video/noon010pc30.c b/drivers/media/video/noon010pc30.c index d0904c53b972..440c12962bae 100644 --- a/drivers/media/video/noon010pc30.c +++ b/drivers/media/video/noon010pc30.c @@ -844,18 +844,7 @@ static struct i2c_driver noon010_i2c_driver = { .id_table = noon010_id, }; -static int __init noon010_init(void) -{ - return i2c_add_driver(&noon010_i2c_driver); -} - -static void __exit noon010_exit(void) -{ - i2c_del_driver(&noon010_i2c_driver); -} - -module_init(noon010_init); -module_exit(noon010_exit); +module_i2c_driver(noon010_i2c_driver); MODULE_DESCRIPTION("Siliconfile NOON010PC30 camera driver"); MODULE_AUTHOR("Sylwester Nawrocki "); diff --git a/drivers/media/video/ov2640.c b/drivers/media/video/ov2640.c index b5247cb64fde..3c2c5d3bcc6b 100644 --- a/drivers/media/video/ov2640.c +++ b/drivers/media/video/ov2640.c @@ -1103,21 +1103,7 @@ static struct i2c_driver ov2640_i2c_driver = { .id_table = ov2640_id, }; -/* - * Module functions - */ -static int __init ov2640_module_init(void) -{ - return i2c_add_driver(&ov2640_i2c_driver); -} - -static void __exit ov2640_module_exit(void) -{ - i2c_del_driver(&ov2640_i2c_driver); -} - -module_init(ov2640_module_init); -module_exit(ov2640_module_exit); +module_i2c_driver(ov2640_i2c_driver); MODULE_DESCRIPTION("SoC Camera driver for Omni Vision 2640 sensor"); MODULE_AUTHOR("Alberto Panizzo"); diff --git a/drivers/media/video/ov5642.c b/drivers/media/video/ov5642.c index bb37ec80f274..80e07794ac8e 100644 --- a/drivers/media/video/ov5642.c +++ b/drivers/media/video/ov5642.c @@ -1068,18 +1068,7 @@ static struct i2c_driver ov5642_i2c_driver = { .id_table = ov5642_id, }; -static int __init ov5642_mod_init(void) -{ - return i2c_add_driver(&ov5642_i2c_driver); -} - -static void __exit ov5642_mod_exit(void) -{ - i2c_del_driver(&ov5642_i2c_driver); -} - -module_init(ov5642_mod_init); -module_exit(ov5642_mod_exit); +module_i2c_driver(ov5642_i2c_driver); MODULE_DESCRIPTION("Omnivision OV5642 Camera driver"); MODULE_AUTHOR("Bastian Hecht "); diff --git a/drivers/media/video/ov6650.c b/drivers/media/video/ov6650.c index 3627f3225bbb..3e028b1970dd 100644 --- a/drivers/media/video/ov6650.c +++ b/drivers/media/video/ov6650.c @@ -1046,18 +1046,7 @@ static struct i2c_driver ov6650_i2c_driver = { .id_table = ov6650_id, }; -static int __init ov6650_module_init(void) -{ - return i2c_add_driver(&ov6650_i2c_driver); -} - -static void __exit ov6650_module_exit(void) -{ - i2c_del_driver(&ov6650_i2c_driver); -} - -module_init(ov6650_module_init); -module_exit(ov6650_module_exit); +module_i2c_driver(ov6650_i2c_driver); MODULE_DESCRIPTION("SoC Camera driver for OmniVision OV6650"); MODULE_AUTHOR("Janusz Krzysztofik "); diff --git a/drivers/media/video/ov7670.c b/drivers/media/video/ov7670.c index 6a564964853a..e7c82b297514 100644 --- a/drivers/media/video/ov7670.c +++ b/drivers/media/video/ov7670.c @@ -1583,15 +1583,4 @@ static struct i2c_driver ov7670_driver = { .id_table = ov7670_id, }; -static __init int init_ov7670(void) -{ - return i2c_add_driver(&ov7670_driver); -} - -static __exit void exit_ov7670(void) -{ - i2c_del_driver(&ov7670_driver); -} - -module_init(init_ov7670); -module_exit(exit_ov7670); +module_i2c_driver(ov7670_driver); diff --git a/drivers/media/video/ov772x.c b/drivers/media/video/ov772x.c index 9f6ce3d8a29e..74e77d327ed8 100644 --- a/drivers/media/video/ov772x.c +++ b/drivers/media/video/ov772x.c @@ -1123,22 +1123,7 @@ static struct i2c_driver ov772x_i2c_driver = { .id_table = ov772x_id, }; -/* - * module function - */ - -static int __init ov772x_module_init(void) -{ - return i2c_add_driver(&ov772x_i2c_driver); -} - -static void __exit ov772x_module_exit(void) -{ - i2c_del_driver(&ov772x_i2c_driver); -} - -module_init(ov772x_module_init); -module_exit(ov772x_module_exit); +module_i2c_driver(ov772x_i2c_driver); MODULE_DESCRIPTION("SoC Camera driver for ov772x"); MODULE_AUTHOR("Kuninori Morimoto"); diff --git a/drivers/media/video/ov9640.c b/drivers/media/video/ov9640.c index a4f99797eb56..23412debb36b 100644 --- a/drivers/media/video/ov9640.c +++ b/drivers/media/video/ov9640.c @@ -738,18 +738,7 @@ static struct i2c_driver ov9640_i2c_driver = { .id_table = ov9640_id, }; -static int __init ov9640_module_init(void) -{ - return i2c_add_driver(&ov9640_i2c_driver); -} - -static void __exit ov9640_module_exit(void) -{ - i2c_del_driver(&ov9640_i2c_driver); -} - -module_init(ov9640_module_init); -module_exit(ov9640_module_exit); +module_i2c_driver(ov9640_i2c_driver); MODULE_DESCRIPTION("SoC Camera driver for OmniVision OV96xx"); MODULE_AUTHOR("Marek Vasut "); diff --git a/drivers/media/video/ov9740.c b/drivers/media/video/ov9740.c index d9a9f7174f7a..3eb07c22516e 100644 --- a/drivers/media/video/ov9740.c +++ b/drivers/media/video/ov9740.c @@ -998,18 +998,7 @@ static struct i2c_driver ov9740_i2c_driver = { .id_table = ov9740_id, }; -static int __init ov9740_module_init(void) -{ - return i2c_add_driver(&ov9740_i2c_driver); -} - -static void __exit ov9740_module_exit(void) -{ - i2c_del_driver(&ov9740_i2c_driver); -} - -module_init(ov9740_module_init); -module_exit(ov9740_module_exit); +module_i2c_driver(ov9740_i2c_driver); MODULE_DESCRIPTION("SoC Camera driver for OmniVision OV9740"); MODULE_AUTHOR("Andrew Chew "); diff --git a/drivers/media/video/rj54n1cb0c.c b/drivers/media/video/rj54n1cb0c.c index 9937386a3bae..f6419b22c258 100644 --- a/drivers/media/video/rj54n1cb0c.c +++ b/drivers/media/video/rj54n1cb0c.c @@ -1407,18 +1407,7 @@ static struct i2c_driver rj54n1_i2c_driver = { .id_table = rj54n1_id, }; -static int __init rj54n1_mod_init(void) -{ - return i2c_add_driver(&rj54n1_i2c_driver); -} - -static void __exit rj54n1_mod_exit(void) -{ - i2c_del_driver(&rj54n1_i2c_driver); -} - -module_init(rj54n1_mod_init); -module_exit(rj54n1_mod_exit); +module_i2c_driver(rj54n1_i2c_driver); MODULE_DESCRIPTION("Sharp RJ54N1CB0C Camera driver"); MODULE_AUTHOR("Guennadi Liakhovetski "); diff --git a/drivers/media/video/s5k6aa.c b/drivers/media/video/s5k6aa.c index 68df8d5befe2..6625e46a4638 100644 --- a/drivers/media/video/s5k6aa.c +++ b/drivers/media/video/s5k6aa.c @@ -1663,18 +1663,7 @@ static struct i2c_driver s5k6aa_i2c_driver = { .id_table = s5k6aa_id, }; -static int __init s5k6aa_init(void) -{ - return i2c_add_driver(&s5k6aa_i2c_driver); -} - -static void __exit s5k6aa_exit(void) -{ - i2c_del_driver(&s5k6aa_i2c_driver); -} - -module_init(s5k6aa_init); -module_exit(s5k6aa_exit); +module_i2c_driver(s5k6aa_i2c_driver); MODULE_DESCRIPTION("Samsung S5K6AA(FX) SXGA camera driver"); MODULE_AUTHOR("Sylwester Nawrocki "); diff --git a/drivers/media/video/s5p-tv/hdmiphy_drv.c b/drivers/media/video/s5p-tv/hdmiphy_drv.c index 6693f4aff108..0afef77747e5 100644 --- a/drivers/media/video/s5p-tv/hdmiphy_drv.c +++ b/drivers/media/video/s5p-tv/hdmiphy_drv.c @@ -175,14 +175,4 @@ static struct i2c_driver hdmiphy_driver = { .id_table = hdmiphy_id, }; -static int __init hdmiphy_init(void) -{ - return i2c_add_driver(&hdmiphy_driver); -} -module_init(hdmiphy_init); - -static void __exit hdmiphy_exit(void) -{ - i2c_del_driver(&hdmiphy_driver); -} -module_exit(hdmiphy_exit); +module_i2c_driver(hdmiphy_driver); diff --git a/drivers/media/video/saa6588.c b/drivers/media/video/saa6588.c index 99a2ac16f9e5..0caac50d7cf4 100644 --- a/drivers/media/video/saa6588.c +++ b/drivers/media/video/saa6588.c @@ -539,15 +539,4 @@ static struct i2c_driver saa6588_driver = { .id_table = saa6588_id, }; -static __init int init_saa6588(void) -{ - return i2c_add_driver(&saa6588_driver); -} - -static __exit void exit_saa6588(void) -{ - i2c_del_driver(&saa6588_driver); -} - -module_init(init_saa6588); -module_exit(exit_saa6588); +module_i2c_driver(saa6588_driver); diff --git a/drivers/media/video/saa7110.c b/drivers/media/video/saa7110.c index 99664205ef4e..51cd4c8f0520 100644 --- a/drivers/media/video/saa7110.c +++ b/drivers/media/video/saa7110.c @@ -491,15 +491,4 @@ static struct i2c_driver saa7110_driver = { .id_table = saa7110_id, }; -static __init int init_saa7110(void) -{ - return i2c_add_driver(&saa7110_driver); -} - -static __exit void exit_saa7110(void) -{ - i2c_del_driver(&saa7110_driver); -} - -module_init(init_saa7110); -module_exit(exit_saa7110); +module_i2c_driver(saa7110_driver); diff --git a/drivers/media/video/saa7115.c b/drivers/media/video/saa7115.c index 0ef5484696b6..2107336cd836 100644 --- a/drivers/media/video/saa7115.c +++ b/drivers/media/video/saa7115.c @@ -1724,15 +1724,4 @@ static struct i2c_driver saa711x_driver = { .id_table = saa711x_id, }; -static __init int init_saa711x(void) -{ - return i2c_add_driver(&saa711x_driver); -} - -static __exit void exit_saa711x(void) -{ - i2c_del_driver(&saa711x_driver); -} - -module_init(init_saa711x); -module_exit(exit_saa711x); +module_i2c_driver(saa711x_driver); diff --git a/drivers/media/video/saa7127.c b/drivers/media/video/saa7127.c index ad964616c9d2..39c90b08eea8 100644 --- a/drivers/media/video/saa7127.c +++ b/drivers/media/video/saa7127.c @@ -852,15 +852,4 @@ static struct i2c_driver saa7127_driver = { .id_table = saa7127_id, }; -static __init int init_saa7127(void) -{ - return i2c_add_driver(&saa7127_driver); -} - -static __exit void exit_saa7127(void) -{ - i2c_del_driver(&saa7127_driver); -} - -module_init(init_saa7127); -module_exit(exit_saa7127); +module_i2c_driver(saa7127_driver); diff --git a/drivers/media/video/saa7134/saa6752hs.c b/drivers/media/video/saa7134/saa6752hs.c index f9f29cc93a8a..f147b05bd860 100644 --- a/drivers/media/video/saa7134/saa6752hs.c +++ b/drivers/media/video/saa7134/saa6752hs.c @@ -1001,18 +1001,7 @@ static struct i2c_driver saa6752hs_driver = { .id_table = saa6752hs_id, }; -static __init int init_saa6752hs(void) -{ - return i2c_add_driver(&saa6752hs_driver); -} - -static __exit void exit_saa6752hs(void) -{ - i2c_del_driver(&saa6752hs_driver); -} - -module_init(init_saa6752hs); -module_exit(exit_saa6752hs); +module_i2c_driver(saa6752hs_driver); /* * Overrides for Emacs so that we follow Linus's tabbing style. diff --git a/drivers/media/video/saa717x.c b/drivers/media/video/saa717x.c index b6172c2c517e..1e84466515aa 100644 --- a/drivers/media/video/saa717x.c +++ b/drivers/media/video/saa717x.c @@ -1375,15 +1375,4 @@ static struct i2c_driver saa717x_driver = { .id_table = saa717x_id, }; -static __init int init_saa717x(void) -{ - return i2c_add_driver(&saa717x_driver); -} - -static __exit void exit_saa717x(void) -{ - i2c_del_driver(&saa717x_driver); -} - -module_init(init_saa717x); -module_exit(exit_saa717x); +module_i2c_driver(saa717x_driver); diff --git a/drivers/media/video/saa7185.c b/drivers/media/video/saa7185.c index 96f56c2f11f3..2c6b65c76e2b 100644 --- a/drivers/media/video/saa7185.c +++ b/drivers/media/video/saa7185.c @@ -374,15 +374,4 @@ static struct i2c_driver saa7185_driver = { .id_table = saa7185_id, }; -static __init int init_saa7185(void) -{ - return i2c_add_driver(&saa7185_driver); -} - -static __exit void exit_saa7185(void) -{ - i2c_del_driver(&saa7185_driver); -} - -module_init(init_saa7185); -module_exit(exit_saa7185); +module_i2c_driver(saa7185_driver); diff --git a/drivers/media/video/saa7191.c b/drivers/media/video/saa7191.c index 211fa25a1239..d7d1670e0ca3 100644 --- a/drivers/media/video/saa7191.c +++ b/drivers/media/video/saa7191.c @@ -656,15 +656,4 @@ static struct i2c_driver saa7191_driver = { .id_table = saa7191_id, }; -static __init int init_saa7191(void) -{ - return i2c_add_driver(&saa7191_driver); -} - -static __exit void exit_saa7191(void) -{ - i2c_del_driver(&saa7191_driver); -} - -module_init(init_saa7191); -module_exit(exit_saa7191); +module_i2c_driver(saa7191_driver); diff --git a/drivers/media/video/sr030pc30.c b/drivers/media/video/sr030pc30.c index d1b07aceaf94..e9d95bda2ab1 100644 --- a/drivers/media/video/sr030pc30.c +++ b/drivers/media/video/sr030pc30.c @@ -864,18 +864,7 @@ static struct i2c_driver sr030pc30_i2c_driver = { .id_table = sr030pc30_id, }; -static int __init sr030pc30_init(void) -{ - return i2c_add_driver(&sr030pc30_i2c_driver); -} - -static void __exit sr030pc30_exit(void) -{ - i2c_del_driver(&sr030pc30_i2c_driver); -} - -module_init(sr030pc30_init); -module_exit(sr030pc30_exit); +module_i2c_driver(sr030pc30_i2c_driver); MODULE_DESCRIPTION("Siliconfile SR030PC30 camera driver"); MODULE_AUTHOR("Sylwester Nawrocki "); diff --git a/drivers/media/video/tda7432.c b/drivers/media/video/tda7432.c index bd218545da9c..f7707e65761e 100644 --- a/drivers/media/video/tda7432.c +++ b/drivers/media/video/tda7432.c @@ -482,15 +482,4 @@ static struct i2c_driver tda7432_driver = { .id_table = tda7432_id, }; -static __init int init_tda7432(void) -{ - return i2c_add_driver(&tda7432_driver); -} - -static __exit void exit_tda7432(void) -{ - i2c_del_driver(&tda7432_driver); -} - -module_init(init_tda7432); -module_exit(exit_tda7432); +module_i2c_driver(tda7432_driver); diff --git a/drivers/media/video/tda9840.c b/drivers/media/video/tda9840.c index 22fa8202d5ca..465d7086babf 100644 --- a/drivers/media/video/tda9840.c +++ b/drivers/media/video/tda9840.c @@ -208,15 +208,4 @@ static struct i2c_driver tda9840_driver = { .id_table = tda9840_id, }; -static __init int init_tda9840(void) -{ - return i2c_add_driver(&tda9840_driver); -} - -static __exit void exit_tda9840(void) -{ - i2c_del_driver(&tda9840_driver); -} - -module_init(init_tda9840); -module_exit(exit_tda9840); +module_i2c_driver(tda9840_driver); diff --git a/drivers/media/video/tea6415c.c b/drivers/media/video/tea6415c.c index 827425c5b866..d1d6ea1dd273 100644 --- a/drivers/media/video/tea6415c.c +++ b/drivers/media/video/tea6415c.c @@ -184,15 +184,4 @@ static struct i2c_driver tea6415c_driver = { .id_table = tea6415c_id, }; -static __init int init_tea6415c(void) -{ - return i2c_add_driver(&tea6415c_driver); -} - -static __exit void exit_tea6415c(void) -{ - i2c_del_driver(&tea6415c_driver); -} - -module_init(init_tea6415c); -module_exit(exit_tea6415c); +module_i2c_driver(tea6415c_driver); diff --git a/drivers/media/video/tea6420.c b/drivers/media/video/tea6420.c index f350b6c24500..38757217a074 100644 --- a/drivers/media/video/tea6420.c +++ b/drivers/media/video/tea6420.c @@ -166,15 +166,4 @@ static struct i2c_driver tea6420_driver = { .id_table = tea6420_id, }; -static __init int init_tea6420(void) -{ - return i2c_add_driver(&tea6420_driver); -} - -static __exit void exit_tea6420(void) -{ - i2c_del_driver(&tea6420_driver); -} - -module_init(init_tea6420); -module_exit(exit_tea6420); +module_i2c_driver(tea6420_driver); diff --git a/drivers/media/video/ths7303.c b/drivers/media/video/ths7303.c index 61b1dd118364..e5c0eedebc58 100644 --- a/drivers/media/video/ths7303.c +++ b/drivers/media/video/ths7303.c @@ -137,16 +137,4 @@ static struct i2c_driver ths7303_driver = { .id_table = ths7303_id, }; -static int __init ths7303_init(void) -{ - return i2c_add_driver(&ths7303_driver); -} - -static void __exit ths7303_exit(void) -{ - i2c_del_driver(&ths7303_driver); -} - -module_init(ths7303_init); -module_exit(ths7303_exit); - +module_i2c_driver(ths7303_driver); diff --git a/drivers/media/video/tlv320aic23b.c b/drivers/media/video/tlv320aic23b.c index 286ec7e7062a..809a75a558ee 100644 --- a/drivers/media/video/tlv320aic23b.c +++ b/drivers/media/video/tlv320aic23b.c @@ -227,15 +227,4 @@ static struct i2c_driver tlv320aic23b_driver = { .id_table = tlv320aic23b_id, }; -static __init int init_tlv320aic23b(void) -{ - return i2c_add_driver(&tlv320aic23b_driver); -} - -static __exit void exit_tlv320aic23b(void) -{ - i2c_del_driver(&tlv320aic23b_driver); -} - -module_init(init_tlv320aic23b); -module_exit(exit_tlv320aic23b); +module_i2c_driver(tlv320aic23b_driver); diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c index 89a123dee14d..a5c6397ad591 100644 --- a/drivers/media/video/tuner-core.c +++ b/drivers/media/video/tuner-core.c @@ -1329,18 +1329,7 @@ static struct i2c_driver tuner_driver = { .id_table = tuner_id, }; -static __init int init_tuner(void) -{ - return i2c_add_driver(&tuner_driver); -} - -static __exit void exit_tuner(void) -{ - i2c_del_driver(&tuner_driver); -} - -module_init(init_tuner); -module_exit(exit_tuner); +module_i2c_driver(tuner_driver); MODULE_DESCRIPTION("device driver for various TV and TV+FM radio tuners"); MODULE_AUTHOR("Ralph Metzler, Gerd Knorr, Gunther Mayer"); diff --git a/drivers/media/video/tvaudio.c b/drivers/media/video/tvaudio.c index f22dbef9b95b..c5b1a7365e4f 100644 --- a/drivers/media/video/tvaudio.c +++ b/drivers/media/video/tvaudio.c @@ -2078,15 +2078,4 @@ static struct i2c_driver tvaudio_driver = { .id_table = tvaudio_id, }; -static __init int init_tvaudio(void) -{ - return i2c_add_driver(&tvaudio_driver); -} - -static __exit void exit_tvaudio(void) -{ - i2c_del_driver(&tvaudio_driver); -} - -module_init(init_tvaudio); -module_exit(exit_tvaudio); +module_i2c_driver(tvaudio_driver); diff --git a/drivers/media/video/tvp514x.c b/drivers/media/video/tvp514x.c index dd26cacd0556..cd615c1d6011 100644 --- a/drivers/media/video/tvp514x.c +++ b/drivers/media/video/tvp514x.c @@ -1163,15 +1163,4 @@ static struct i2c_driver tvp514x_driver = { .id_table = tvp514x_id, }; -static int __init tvp514x_init(void) -{ - return i2c_add_driver(&tvp514x_driver); -} - -static void __exit tvp514x_exit(void) -{ - i2c_del_driver(&tvp514x_driver); -} - -module_init(tvp514x_init); -module_exit(tvp514x_exit); +module_i2c_driver(tvp514x_driver); diff --git a/drivers/media/video/tvp5150.c b/drivers/media/video/tvp5150.c index 6be9910a6e24..f1fcedd29eb4 100644 --- a/drivers/media/video/tvp5150.c +++ b/drivers/media/video/tvp5150.c @@ -1121,15 +1121,4 @@ static struct i2c_driver tvp5150_driver = { .id_table = tvp5150_id, }; -static __init int init_tvp5150(void) -{ - return i2c_add_driver(&tvp5150_driver); -} - -static __exit void exit_tvp5150(void) -{ - i2c_del_driver(&tvp5150_driver); -} - -module_init(init_tvp5150); -module_exit(exit_tvp5150); +module_i2c_driver(tvp5150_driver); diff --git a/drivers/media/video/tvp7002.c b/drivers/media/video/tvp7002.c index 236c559d5f51..d7676d85c4df 100644 --- a/drivers/media/video/tvp7002.c +++ b/drivers/media/video/tvp7002.c @@ -1069,27 +1069,4 @@ static struct i2c_driver tvp7002_driver = { .id_table = tvp7002_id, }; -/* - * tvp7002_init - Initialize driver via I2C interface - * - * Register the TVP7002 driver. - * Return 0 on success or error code on failure. - */ -static int __init tvp7002_init(void) -{ - return i2c_add_driver(&tvp7002_driver); -} - -/* - * tvp7002_exit - Remove driver via I2C interface - * - * Unregister the TVP7002 driver. - * Returns nothing. - */ -static void __exit tvp7002_exit(void) -{ - i2c_del_driver(&tvp7002_driver); -} - -module_init(tvp7002_init); -module_exit(tvp7002_exit); +module_i2c_driver(tvp7002_driver); diff --git a/drivers/media/video/tw9910.c b/drivers/media/video/tw9910.c index a514fa61116c..8768efb8508a 100644 --- a/drivers/media/video/tw9910.c +++ b/drivers/media/video/tw9910.c @@ -951,21 +951,7 @@ static struct i2c_driver tw9910_i2c_driver = { .id_table = tw9910_id, }; -/* - * module function - */ -static int __init tw9910_module_init(void) -{ - return i2c_add_driver(&tw9910_i2c_driver); -} - -static void __exit tw9910_module_exit(void) -{ - i2c_del_driver(&tw9910_i2c_driver); -} - -module_init(tw9910_module_init); -module_exit(tw9910_module_exit); +module_i2c_driver(tw9910_i2c_driver); MODULE_DESCRIPTION("SoC Camera driver for tw9910"); MODULE_AUTHOR("Kuninori Morimoto"); diff --git a/drivers/media/video/upd64031a.c b/drivers/media/video/upd64031a.c index 1aab96a88203..1e7446542091 100644 --- a/drivers/media/video/upd64031a.c +++ b/drivers/media/video/upd64031a.c @@ -271,15 +271,4 @@ static struct i2c_driver upd64031a_driver = { .id_table = upd64031a_id, }; -static __init int init_upd64031a(void) -{ - return i2c_add_driver(&upd64031a_driver); -} - -static __exit void exit_upd64031a(void) -{ - i2c_del_driver(&upd64031a_driver); -} - -module_init(init_upd64031a); -module_exit(exit_upd64031a); +module_i2c_driver(upd64031a_driver); diff --git a/drivers/media/video/upd64083.c b/drivers/media/video/upd64083.c index 65d065aa6091..75d6acc62018 100644 --- a/drivers/media/video/upd64083.c +++ b/drivers/media/video/upd64083.c @@ -243,15 +243,4 @@ static struct i2c_driver upd64083_driver = { .id_table = upd64083_id, }; -static __init int init_upd64083(void) -{ - return i2c_add_driver(&upd64083_driver); -} - -static __exit void exit_upd64083(void) -{ - i2c_del_driver(&upd64083_driver); -} - -module_init(init_upd64083); -module_exit(exit_upd64083); +module_i2c_driver(upd64083_driver); diff --git a/drivers/media/video/vp27smpx.c b/drivers/media/video/vp27smpx.c index c15efb6e7771..7cfbc9d94a48 100644 --- a/drivers/media/video/vp27smpx.c +++ b/drivers/media/video/vp27smpx.c @@ -208,15 +208,4 @@ static struct i2c_driver vp27smpx_driver = { .id_table = vp27smpx_id, }; -static __init int init_vp27smpx(void) -{ - return i2c_add_driver(&vp27smpx_driver); -} - -static __exit void exit_vp27smpx(void) -{ - i2c_del_driver(&vp27smpx_driver); -} - -module_init(init_vp27smpx); -module_exit(exit_vp27smpx); +module_i2c_driver(vp27smpx_driver); diff --git a/drivers/media/video/vpx3220.c b/drivers/media/video/vpx3220.c index e5cad6ff64a1..2f67b4c5c823 100644 --- a/drivers/media/video/vpx3220.c +++ b/drivers/media/video/vpx3220.c @@ -588,15 +588,4 @@ static struct i2c_driver vpx3220_driver = { .id_table = vpx3220_id, }; -static __init int init_vpx3220(void) -{ - return i2c_add_driver(&vpx3220_driver); -} - -static __exit void exit_vpx3220(void) -{ - i2c_del_driver(&vpx3220_driver); -} - -module_init(init_vpx3220); -module_exit(exit_vpx3220); +module_i2c_driver(vpx3220_driver); diff --git a/drivers/media/video/wm8739.c b/drivers/media/video/wm8739.c index a22f765e968a..3bb99e93febe 100644 --- a/drivers/media/video/wm8739.c +++ b/drivers/media/video/wm8739.c @@ -291,15 +291,4 @@ static struct i2c_driver wm8739_driver = { .id_table = wm8739_id, }; -static __init int init_wm8739(void) -{ - return i2c_add_driver(&wm8739_driver); -} - -static __exit void exit_wm8739(void) -{ - i2c_del_driver(&wm8739_driver); -} - -module_init(init_wm8739); -module_exit(exit_wm8739); +module_i2c_driver(wm8739_driver); diff --git a/drivers/media/video/wm8775.c b/drivers/media/video/wm8775.c index 9cedb1e69b58..bee77ea9f49e 100644 --- a/drivers/media/video/wm8775.c +++ b/drivers/media/video/wm8775.c @@ -339,15 +339,4 @@ static struct i2c_driver wm8775_driver = { .id_table = wm8775_id, }; -static __init int init_wm8775(void) -{ - return i2c_add_driver(&wm8775_driver); -} - -static __exit void exit_wm8775(void) -{ - i2c_del_driver(&wm8775_driver); -} - -module_init(init_wm8775); -module_exit(exit_wm8775); +module_i2c_driver(wm8775_driver); -- cgit v1.2.3 From 46f3da990b8087c95613744a772cab7557b9b180 Mon Sep 17 00:00:00 2001 From: Malcolm Priestley Date: Sun, 12 Feb 2012 07:29:38 -0300 Subject: [media] it913x ver 1.26 change to remove interruptible mutex locks Some virtual I2C commands are missed along some PID filtering commands resulting complete stall of driver. Since dvb-usb cannot handle the -EAGAIN error and commands generally should not be missed mutex_lock is used instead. Signed-off-by: Malcolm Priestley Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/it913x.c | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/dvb-usb/it913x.c b/drivers/media/dvb/dvb-usb/it913x.c index 2560652763cf..bfadf12986ca 100644 --- a/drivers/media/dvb/dvb-usb/it913x.c +++ b/drivers/media/dvb/dvb-usb/it913x.c @@ -263,8 +263,8 @@ static int it913x_pid_filter_ctrl(struct dvb_usb_adapter *adap, int onoff) int ret; u8 pro = (adap->id == 0) ? DEV_0_DMOD : DEV_1_DMOD; - if (mutex_lock_interruptible(&adap->dev->i2c_mutex) < 0) - return -EAGAIN; + mutex_lock(&adap->dev->i2c_mutex); + deb_info(1, "PID_C (%02x)", onoff); ret = it913x_wr_reg(udev, pro, PID_EN, onoff); @@ -280,8 +280,8 @@ static int it913x_pid_filter(struct dvb_usb_adapter *adap, int ret; u8 pro = (adap->id == 0) ? DEV_0_DMOD : DEV_1_DMOD; - if (mutex_lock_interruptible(&adap->dev->i2c_mutex) < 0) - return -EAGAIN; + mutex_lock(&adap->dev->i2c_mutex); + deb_info(1, "PID_F (%02x)", onoff); ret = it913x_wr_reg(udev, pro, PID_LSB, (u8)(pid & 0xff)); @@ -316,8 +316,8 @@ static int it913x_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], int ret; u32 reg; u8 pro; - if (mutex_lock_interruptible(&d->i2c_mutex) < 0) - return -EAGAIN; + + mutex_lock(&d->i2c_mutex); debug_data_snipet(1, "Message out", msg[0].buf); deb_info(2, "num of messages %d address %02x", num, msg[0].addr); @@ -358,8 +358,7 @@ static int it913x_rc_query(struct dvb_usb_device *d) int ret; u32 key; /* Avoid conflict with frontends*/ - if (mutex_lock_interruptible(&d->i2c_mutex) < 0) - return -EAGAIN; + mutex_lock(&d->i2c_mutex); ret = it913x_io(d->udev, READ_LONG, PRO_LINK, CMD_IR_GET, 0, 0, &ibuf[0], sizeof(ibuf)); @@ -603,15 +602,15 @@ static int it913x_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) int ret = 0; u8 pro = (adap->id == 0) ? DEV_0_DMOD : DEV_1_DMOD; - if (mutex_lock_interruptible(&adap->dev->i2c_mutex) < 0) - return -EAGAIN; deb_info(1, "STM (%02x)", onoff); - if (!onoff) - ret = it913x_wr_reg(adap->dev->udev, pro, PID_RST, 0x1); + if (!onoff) { + mutex_lock(&adap->dev->i2c_mutex); + ret = it913x_wr_reg(adap->dev->udev, pro, PID_RST, 0x1); - mutex_unlock(&adap->dev->i2c_mutex); + mutex_unlock(&adap->dev->i2c_mutex); + } return ret; } @@ -885,5 +884,5 @@ module_usb_driver(it913x_driver); MODULE_AUTHOR("Malcolm Priestley "); MODULE_DESCRIPTION("it913x USB 2 Driver"); -MODULE_VERSION("1.25"); +MODULE_VERSION("1.26"); MODULE_LICENSE("GPL"); -- cgit v1.2.3 From aaa589fc5e768eb8df1a7552e37f9c767ce5e384 Mon Sep 17 00:00:00 2001 From: Malcolm Priestley Date: Sun, 12 Feb 2012 07:31:41 -0300 Subject: [media] it913x ver 1.27 Allow PID 8192 to turn PID filter off Allow PID 8192 to turn PID filter off in USB high speed. The PID number is still written to the PID index and will only turn on again if that index is set to 0. Signed-off-by: Malcolm Priestley Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/it913x.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/dvb-usb/it913x.c b/drivers/media/dvb/dvb-usb/it913x.c index bfadf12986ca..cfa415b0816d 100644 --- a/drivers/media/dvb/dvb-usb/it913x.c +++ b/drivers/media/dvb/dvb-usb/it913x.c @@ -64,6 +64,7 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); struct it913x_state { u8 id; struct ite_config it913x_config; + u8 pid_filter_onoff; }; struct ite_config it913x_config; @@ -259,6 +260,7 @@ static u32 it913x_query(struct usb_device *udev, u8 pro) static int it913x_pid_filter_ctrl(struct dvb_usb_adapter *adap, int onoff) { + struct it913x_state *st = adap->dev->priv; struct usb_device *udev = adap->dev->udev; int ret; u8 pro = (adap->id == 0) ? DEV_0_DMOD : DEV_1_DMOD; @@ -267,7 +269,7 @@ static int it913x_pid_filter_ctrl(struct dvb_usb_adapter *adap, int onoff) deb_info(1, "PID_C (%02x)", onoff); - ret = it913x_wr_reg(udev, pro, PID_EN, onoff); + ret = it913x_wr_reg(udev, pro, PID_EN, st->pid_filter_onoff); mutex_unlock(&adap->dev->i2c_mutex); return ret; @@ -276,6 +278,7 @@ static int it913x_pid_filter_ctrl(struct dvb_usb_adapter *adap, int onoff) static int it913x_pid_filter(struct dvb_usb_adapter *adap, int index, u16 pid, int onoff) { + struct it913x_state *st = adap->dev->priv; struct usb_device *udev = adap->dev->udev; int ret; u8 pro = (adap->id == 0) ? DEV_0_DMOD : DEV_1_DMOD; @@ -292,6 +295,13 @@ static int it913x_pid_filter(struct dvb_usb_adapter *adap, ret |= it913x_wr_reg(udev, pro, PID_INX, (u8)(index & 0x1f)); + if (udev->speed == USB_SPEED_HIGH && pid == 0x2000) { + ret |= it913x_wr_reg(udev, pro, PID_EN, !onoff); + st->pid_filter_onoff = !onoff; + } else + st->pid_filter_onoff = + adap->fe_adap[adap->active_fe].pid_filtering; + mutex_unlock(&adap->dev->i2c_mutex); return 0; } @@ -599,6 +609,7 @@ static int it913x_identify_state(struct usb_device *udev, static int it913x_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) { + struct it913x_state *st = adap->dev->priv; int ret = 0; u8 pro = (adap->id == 0) ? DEV_0_DMOD : DEV_1_DMOD; @@ -610,6 +621,9 @@ static int it913x_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) ret = it913x_wr_reg(adap->dev->udev, pro, PID_RST, 0x1); mutex_unlock(&adap->dev->i2c_mutex); + st->pid_filter_onoff = + adap->fe_adap[adap->active_fe].pid_filtering; + } return ret; @@ -884,5 +898,5 @@ module_usb_driver(it913x_driver); MODULE_AUTHOR("Malcolm Priestley "); MODULE_DESCRIPTION("it913x USB 2 Driver"); -MODULE_VERSION("1.26"); +MODULE_VERSION("1.27"); MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 6c5637e4eda58292f7d9ee6ee0b1f9aa4b0a7e7f Mon Sep 17 00:00:00 2001 From: Malcolm Priestley Date: Sun, 12 Feb 2012 09:03:06 -0300 Subject: [media] it913x-fe ver 1.15 read signal strenght using reg VAR_P_INBAND Read signal strength using VAR_P_INBAND and apply FEC preferred values. Note this does not work on IT9137 devices even with dvb-usb-it9135-01.fw firmware. Config read_sl allows switch between read signal strength and signal level. Signed-off-by: Malcolm Priestley Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/it913x.c | 3 + drivers/media/dvb/frontends/it913x-fe-priv.h | 5 ++ drivers/media/dvb/frontends/it913x-fe.c | 91 +++++++++++++++++++++++++--- drivers/media/dvb/frontends/it913x-fe.h | 4 ++ 4 files changed, 93 insertions(+), 10 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/dvb-usb/it913x.c b/drivers/media/dvb/dvb-usb/it913x.c index cfa415b0816d..3b7b102f20ae 100644 --- a/drivers/media/dvb/dvb-usb/it913x.c +++ b/drivers/media/dvb/dvb-usb/it913x.c @@ -412,11 +412,13 @@ static int ite_firmware_select(struct usb_device *udev, case IT9135_V1_FW: it913x_config.firmware_ver = 1; it913x_config.adc_x2 = 1; + it913x_config.read_slevel = false; props->firmware = fw_it9135_v1; break; case IT9135_V2_FW: it913x_config.firmware_ver = 1; it913x_config.adc_x2 = 1; + it913x_config.read_slevel = false; props->firmware = fw_it9135_v2; switch (it913x_config.tuner_id_0) { case IT9135_61: @@ -432,6 +434,7 @@ static int ite_firmware_select(struct usb_device *udev, default: it913x_config.firmware_ver = 0; it913x_config.adc_x2 = 0; + it913x_config.read_slevel = true; props->firmware = fw_it9137; } diff --git a/drivers/media/dvb/frontends/it913x-fe-priv.h b/drivers/media/dvb/frontends/it913x-fe-priv.h index 93b086ea7e1c..eb6fd8aebdb3 100644 --- a/drivers/media/dvb/frontends/it913x-fe-priv.h +++ b/drivers/media/dvb/frontends/it913x-fe-priv.h @@ -201,6 +201,11 @@ fe_modulation_t fe_con[] = { QAM_64, }; +enum { + PRIORITY_HIGH = 0, /* High-priority stream */ + PRIORITY_LOW, /* Low-priority stream */ +}; + /* Standard demodulator functions */ static struct it913xset set_solo_fe[] = { {PRO_LINK, GPIOH5_EN, {0x01}, 0x01}, diff --git a/drivers/media/dvb/frontends/it913x-fe.c b/drivers/media/dvb/frontends/it913x-fe.c index ccc36bf2deb4..84df03c29179 100644 --- a/drivers/media/dvb/frontends/it913x-fe.c +++ b/drivers/media/dvb/frontends/it913x-fe.c @@ -57,6 +57,7 @@ struct it913x_fe_state { u32 frequency; fe_modulation_t constellation; fe_transmit_mode_t transmission_mode; + u8 priority; u32 crystalFrequency; u32 adcFrequency; u8 tuner_type; @@ -500,19 +501,87 @@ static int it913x_fe_read_status(struct dvb_frontend *fe, fe_status_t *status) return 0; } +/* FEC values based on fe_code_rate_t non supported values 0*/ +int it913x_qpsk_pval[] = {0, -93, -91, -90, 0, -89, -88}; +int it913x_16qam_pval[] = {0, -87, -85, -84, 0, -83, -82}; +int it913x_64qam_pval[] = {0, -82, -80, -78, 0, -77, -76}; + +static int it913x_get_signal_strength(struct dvb_frontend *fe) +{ + struct dtv_frontend_properties *p = &fe->dtv_property_cache; + struct it913x_fe_state *state = fe->demodulator_priv; + u8 code_rate; + int ret, temp; + u8 lna_gain_os; + + ret = it913x_read_reg_u8(state, VAR_P_INBAND); + if (ret < 0) + return ret; + + /* VHF/UHF gain offset */ + if (state->frequency < 300000000) + lna_gain_os = 7; + else + lna_gain_os = 14; + + temp = (ret - 100) - lna_gain_os; + + if (state->priority == PRIORITY_HIGH) + code_rate = p->code_rate_HP; + else + code_rate = p->code_rate_LP; + + if (code_rate >= ARRAY_SIZE(it913x_qpsk_pval)) + return -EINVAL; + + deb_info("Reg VAR_P_INBAND:%d Calc Offset Value:%d", ret, temp); + + /* Apply FEC offset values*/ + switch (p->modulation) { + case QPSK: + temp -= it913x_qpsk_pval[code_rate]; + break; + case QAM_16: + temp -= it913x_16qam_pval[code_rate]; + break; + case QAM_64: + temp -= it913x_64qam_pval[code_rate]; + break; + default: + return -EINVAL; + } + + if (temp < -15) + ret = 0; + else if ((-15 <= temp) && (temp < 0)) + ret = (2 * (temp + 15)) / 3; + else if ((0 <= temp) && (temp < 20)) + ret = 4 * temp + 10; + else if ((20 <= temp) && (temp < 35)) + ret = (2 * (temp - 20)) / 3 + 90; + else if (temp >= 35) + ret = 100; + + deb_info("Signal Strength :%d", ret); + + return ret; +} + static int it913x_fe_read_signal_strength(struct dvb_frontend *fe, u16 *strength) { struct it913x_fe_state *state = fe->demodulator_priv; - int ret = it913x_read_reg_u8(state, SIGNAL_LEVEL); - /*SIGNAL_LEVEL always returns 100%! so using FE_HAS_SIGNAL as switch*/ - if (state->it913x_status & FE_HAS_SIGNAL) - ret = (ret * 0xff) / 0x64; - else - ret = 0x0; - ret |= ret << 0x8; - *strength = ret; - return 0; + int ret = 0; + if (state->config->read_slevel) { + if (state->it913x_status & FE_HAS_SIGNAL) + ret = it913x_read_reg_u8(state, SIGNAL_LEVEL); + } else + ret = it913x_get_signal_strength(fe); + + if (ret >= 0) + *strength = (u16)((u32)ret * 0xffff / 0x64); + + return (ret < 0) ? -ENODEV : 0; } static int it913x_fe_read_snr(struct dvb_frontend *fe, u16 *snr) @@ -606,6 +675,8 @@ static int it913x_fe_get_frontend(struct dvb_frontend *fe) if (reg[2] < 4) p->hierarchy = fe_hi[reg[2]]; + state->priority = reg[5]; + p->code_rate_HP = (reg[6] < 6) ? fe_code[reg[6]] : FEC_NONE; p->code_rate_LP = (reg[7] < 6) ? fe_code[reg[7]] : FEC_NONE; @@ -972,5 +1043,5 @@ static struct dvb_frontend_ops it913x_fe_ofdm_ops = { MODULE_DESCRIPTION("it913x Frontend and it9137 tuner"); MODULE_AUTHOR("Malcolm Priestley tvboxspy@gmail.com"); -MODULE_VERSION("1.13"); +MODULE_VERSION("1.15"); MODULE_LICENSE("GPL"); diff --git a/drivers/media/dvb/frontends/it913x-fe.h b/drivers/media/dvb/frontends/it913x-fe.h index c4a908e354e0..07fa4594c12b 100644 --- a/drivers/media/dvb/frontends/it913x-fe.h +++ b/drivers/media/dvb/frontends/it913x-fe.h @@ -34,6 +34,8 @@ struct ite_config { u8 tuner_id_1; u8 dual_mode; u8 adf; + /* option to read SIGNAL_LEVEL */ + u8 read_slevel; }; #if defined(CONFIG_DVB_IT913X_FE) || (defined(CONFIG_DVB_IT913X_FE_MODULE) && \ @@ -168,6 +170,8 @@ static inline struct dvb_frontend *it913x_fe_attach( #define EST_SIGNAL_LEVEL 0x004a #define FREE_BAND 0x004b #define SUSPEND_FLAG 0x004c +#define VAR_P_INBAND 0x00f7 + /* Build in tuner types */ #define IT9137 0x38 #define IT9135_38 0x38 -- cgit v1.2.3 From 06302ffbb470359c8cbcf1ee8b057d6930300f90 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Sun, 12 Feb 2012 15:03:03 -0300 Subject: [media] cx22702: Fix signal strength The signal strength value returned is not quite correct, it decreases when I increase the gain of my antenna, and vice versa. It also doesn't span over the whole 0x0000-0xffff range. Compute a value which at least increases when signal strength increases, and spans the whole allowed range. In practice I get 67% with my antenna fully amplified and 51% with no amplification. This is close enough to what I get on my other DVB-T adapter with the same antenna. Signed-off-by: Jean Delvare Cc: Steven Toth Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/cx22702.c | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/frontends/cx22702.c b/drivers/media/dvb/frontends/cx22702.c index faba82485086..edc8eafc5c09 100644 --- a/drivers/media/dvb/frontends/cx22702.c +++ b/drivers/media/dvb/frontends/cx22702.c @@ -502,10 +502,26 @@ static int cx22702_read_signal_strength(struct dvb_frontend *fe, u16 *signal_strength) { struct cx22702_state *state = fe->demodulator_priv; + u8 reg23; - u16 rs_ber; - rs_ber = cx22702_readreg(state, 0x23); - *signal_strength = (rs_ber << 8) | rs_ber; + /* + * Experience suggests that the strength signal register works as + * follows: + * - In the absence of signal, value is 0xff. + * - In the presence of a weak signal, bit 7 is set, not sure what + * the lower 7 bits mean. + * - In the presence of a strong signal, the register holds a 7-bit + * value (bit 7 is cleared), with greater values standing for + * weaker signals. + */ + reg23 = cx22702_readreg(state, 0x23); + if (reg23 & 0x80) { + *signal_strength = 0; + } else { + reg23 = ~reg23 & 0x7f; + /* Scale to 16 bit */ + *signal_strength = (reg23 << 9) | (reg23 << 2) | (reg23 >> 5); + } return 0; } -- cgit v1.2.3 From 34817174fca0c5512c2d5b6ea0fc37a0337ce1d8 Mon Sep 17 00:00:00 2001 From: Xi Wang Date: Tue, 14 Feb 2012 14:32:41 -0300 Subject: [media] lgdt330x: fix signedness error in i2c_read_demod_bytes() The error handling in lgdt3303_read_status() and lgdt330x_read_ucblocks() doesn't work, because i2c_read_demod_bytes() returns a u8 and (err < 0) is always false. err = i2c_read_demod_bytes(state, 0x58, buf, 1); if (err < 0) return err; Change the return type of i2c_read_demod_bytes() to int. Also change the return value on error to -EIO to make (err < 0) work. Signed-off-by: Xi Wang Cc: stable@vger.kernel.org Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/lgdt330x.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/frontends/lgdt330x.c b/drivers/media/dvb/frontends/lgdt330x.c index c990d35a13dc..e046622df0e4 100644 --- a/drivers/media/dvb/frontends/lgdt330x.c +++ b/drivers/media/dvb/frontends/lgdt330x.c @@ -104,8 +104,8 @@ static int i2c_write_demod_bytes (struct lgdt330x_state* state, * then reads the data returned for (len) bytes. */ -static u8 i2c_read_demod_bytes (struct lgdt330x_state* state, - enum I2C_REG reg, u8* buf, int len) +static int i2c_read_demod_bytes(struct lgdt330x_state *state, + enum I2C_REG reg, u8 *buf, int len) { u8 wr [] = { reg }; struct i2c_msg msg [] = { @@ -118,6 +118,8 @@ static u8 i2c_read_demod_bytes (struct lgdt330x_state* state, ret = i2c_transfer(state->i2c, msg, 2); if (ret != 2) { printk(KERN_WARNING "lgdt330x: %s: addr 0x%02x select 0x%02x error (ret == %i)\n", __func__, state->config->demod_address, reg, ret); + if (ret >= 0) + ret = -EIO; } else { ret = 0; } -- cgit v1.2.3 From 6797e7ad9ca523bdd46b2def7080c31593c5389e Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Fri, 17 Feb 2012 04:57:10 -0300 Subject: [media] media: dvb: append $(srctree) to -I parameters Without this we have got the warnings like following if build with "make W=1 O=/var/tmp": cc1: warning: drivers/media/dvb/dvb-core: No such file or directory [enabled by default] Signed-off-by: Andy Shevchenko Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/Makefile | 7 ++++--- drivers/media/dvb/frontends/Makefile | 4 ++-- 2 files changed, 6 insertions(+), 5 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/dvb-usb/Makefile b/drivers/media/dvb/dvb-usb/Makefile index 7e476cb49334..b76acb5387e6 100644 --- a/drivers/media/dvb/dvb-usb/Makefile +++ b/drivers/media/dvb/dvb-usb/Makefile @@ -110,8 +110,9 @@ obj-$(CONFIG_DVB_USB_MXL111SF) += mxl111sf-tuner.o dvb-usb-rtl28xxu-objs = rtl28xxu.o obj-$(CONFIG_DVB_USB_RTL28XXU) += dvb-usb-rtl28xxu.o -ccflags-y += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/ +ccflags-y += -I$(srctree)/drivers/media/dvb/dvb-core +ccflags-y += -I$(srctree)/drivers/media/dvb/frontends/ # due to tuner-xc3028 -ccflags-y += -Idrivers/media/common/tuners -EXTRA_CFLAGS += -Idrivers/media/dvb/ttpci +ccflags-y += -I$(srctree)/drivers/media/common/tuners +ccflags-y += -I$(srctree)/drivers/media/dvb/ttpci diff --git a/drivers/media/dvb/frontends/Makefile b/drivers/media/dvb/frontends/Makefile index 7f85e64cdcb1..17519dc027d8 100644 --- a/drivers/media/dvb/frontends/Makefile +++ b/drivers/media/dvb/frontends/Makefile @@ -2,8 +2,8 @@ # Makefile for the kernel DVB frontend device drivers. # -ccflags-y += -Idrivers/media/dvb/dvb-core/ -ccflags-y += -Idrivers/media/common/tuners/ +ccflags-y += -I$(srctree)/drivers/media/dvb/dvb-core/ +ccflags-y += -I$(srctree)/drivers/media/common/tuners/ stb0899-objs = stb0899_drv.o stb0899_algo.o stv0900-objs = stv0900_core.o stv0900_sw.o -- cgit v1.2.3 From 9d1760059f29f91ad24cb2dcf75ed2b3f5198dcb Mon Sep 17 00:00:00 2001 From: Paolo Pantò Date: Tue, 21 Feb 2012 12:26:29 -0300 Subject: [media] rtl28xxu: add another Freecom usb id MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Besides sticks with the usb id 14AA:0160, there exists also some with 14AA:0161 - this is the output in /var/log/messages: usb 1-1: new high-speed USB device number 2 using ehci_hcd usb 1-1: New USB device found, idVendor=14aa, idProduct=0161 usb 1-1: New USB device strings: Mfr=1, Product=2, SerialNumber=3 usb 1-1: Product: Freecom DVB-T usb 1-1: Manufacturer: Freecom DVB-T usb 1-1: SerialNumber: 00000000000036742 The patch is based on the code at http://git.linuxtv.org/anttip/media_tree.git/shortlog/refs/heads/realtek Signed-off-by: Paolo Pantò Acked-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/dvb-usb-ids.h | 1 + drivers/media/dvb/dvb-usb/rtl28xxu.c | 4 ++++ 2 files changed, 5 insertions(+) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h index bf2826fa591d..397d8f232731 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h +++ b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h @@ -128,6 +128,7 @@ #define USB_PID_E3C_EC168_4 0x1001 #define USB_PID_E3C_EC168_5 0x1002 #define USB_PID_FREECOM_DVBT 0x0160 +#define USB_PID_FREECOM_DVBT_2 0x0161 #define USB_PID_UNIWILL_STK7700P 0x6003 #define USB_PID_GENIUS_TVGO_DVB_T03 0x4012 #define USB_PID_GRANDTEC_DVBT_USB_COLD 0x0fa0 diff --git a/drivers/media/dvb/dvb-usb/rtl28xxu.c b/drivers/media/dvb/dvb-usb/rtl28xxu.c index 07597c53d07b..8f4736a10fc8 100644 --- a/drivers/media/dvb/dvb-usb/rtl28xxu.c +++ b/drivers/media/dvb/dvb-usb/rtl28xxu.c @@ -767,6 +767,7 @@ err: enum rtl28xxu_usb_table_entry { RTL2831U_0BDA_2831, RTL2831U_14AA_0160, + RTL2831U_14AA_0161, }; static struct usb_device_id rtl28xxu_table[] = { @@ -775,6 +776,8 @@ static struct usb_device_id rtl28xxu_table[] = { USB_DEVICE(USB_VID_REALTEK, USB_PID_REALTEK_RTL2831U)}, [RTL2831U_14AA_0160] = { USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_FREECOM_DVBT)}, + [RTL2831U_14AA_0161] = { + USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_FREECOM_DVBT_2)}, /* RTL2832U */ {} /* terminating entry */ @@ -840,6 +843,7 @@ static struct dvb_usb_device_properties rtl28xxu_properties[] = { .name = "Freecom USB2.0 DVB-T", .warm_ids = { &rtl28xxu_table[RTL2831U_14AA_0160], + &rtl28xxu_table[RTL2831U_14AA_0161], }, }, } -- cgit v1.2.3 From f1ed32194411028e9e2889132c31291c5ed9c699 Mon Sep 17 00:00:00 2001 From: Jesper Juhl Date: Sun, 26 Feb 2012 18:57:13 -0300 Subject: [media] [trivial] DiB0090: remove redundant '; ' from dib0090_fw_identify() One semi-colon is enough. Signed-off-by: Jesper Juhl Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/dib0090.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/frontends/dib0090.c b/drivers/media/dvb/frontends/dib0090.c index 224d81e85091..d9fe60b4be48 100644 --- a/drivers/media/dvb/frontends/dib0090.c +++ b/drivers/media/dvb/frontends/dib0090.c @@ -519,7 +519,7 @@ static int dib0090_fw_identify(struct dvb_frontend *fe) return 0; identification_error: - return -EIO;; + return -EIO; } static void dib0090_reset_digital(struct dvb_frontend *fe, const struct dib0090_config *cfg) -- cgit v1.2.3 From 2b49fad59513b07f976c9711b99f93ae74d081c5 Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Mon, 12 Mar 2012 18:21:20 -0300 Subject: [media] tda10071: fix the delivery system MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit b2a29b578d9c21b2e5c88020f830d3c42115c51d sets accidentally supported delivery systems as DVB-T/T2 whilst it should be DVB-S/S2. Due to that frontend cannot be used at all. Reported-by: Jiří Zelenka Signed-off-by: Antti Palosaari Cc: stable@kernel.org Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/tda10071.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/frontends/tda10071.c b/drivers/media/dvb/frontends/tda10071.c index a99205026751..c21bc92d2811 100644 --- a/drivers/media/dvb/frontends/tda10071.c +++ b/drivers/media/dvb/frontends/tda10071.c @@ -1215,7 +1215,7 @@ error: EXPORT_SYMBOL(tda10071_attach); static struct dvb_frontend_ops tda10071_ops = { - .delsys = { SYS_DVBT, SYS_DVBT2 }, + .delsys = { SYS_DVBS, SYS_DVBS2 }, .info = { .name = "NXP TDA10071", .frequency_min = 950000, -- cgit v1.2.3 From 91caad3195e3b622f2a878869aab40d094106d33 Mon Sep 17 00:00:00 2001 From: Andreas Regel Date: Tue, 28 Feb 2012 14:40:40 -0300 Subject: [media] stb0899: set FE_HAS_SIGNAL flag in read_status In stb0899_read_status the FE_HAS_SIGNAL flag was not set in case of a successful carrier lock. This change fixes that. Signed-off-by: Andreas Regel Acked-by: Klaus Schmidinger Cc: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/stb0899_drv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/frontends/stb0899_drv.c b/drivers/media/dvb/frontends/stb0899_drv.c index 38565beafe23..d38f555a1f15 100644 --- a/drivers/media/dvb/frontends/stb0899_drv.c +++ b/drivers/media/dvb/frontends/stb0899_drv.c @@ -1071,7 +1071,7 @@ static int stb0899_read_status(struct dvb_frontend *fe, enum fe_status *status) reg = stb0899_read_reg(state, STB0899_VSTATUS); if (STB0899_GETFIELD(VSTATUS_LOCKEDVIT, reg)) { dprintk(state->verbose, FE_DEBUG, 1, "--------> FE_HAS_CARRIER | FE_HAS_LOCK"); - *status |= FE_HAS_CARRIER | FE_HAS_LOCK; + *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_LOCK; reg = stb0899_read_reg(state, STB0899_PLPARM); if (STB0899_GETFIELD(VITCURPUN, reg)) { -- cgit v1.2.3 From ef3d23de05254179b7f9e718eae276e5b67e1ba6 Mon Sep 17 00:00:00 2001 From: Andreas Regel Date: Tue, 28 Feb 2012 14:40:44 -0300 Subject: [media] stb0899: fixed reading of IF_AGC_GAIN register When reading IF_AGC_GAIN register a wrong value for the base address register was used (STB0899_DEMOD instead of STB0899_S2DEMOD). That lead to a wrong signal strength value on DVB-S2 transponders. Signed-off-by: Andreas Regel Acked-by: Klaus Schmidinger Cc: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/stb0899_drv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/frontends/stb0899_drv.c b/drivers/media/dvb/frontends/stb0899_drv.c index d38f555a1f15..097e7067f208 100644 --- a/drivers/media/dvb/frontends/stb0899_drv.c +++ b/drivers/media/dvb/frontends/stb0899_drv.c @@ -983,7 +983,7 @@ static int stb0899_read_signal_strength(struct dvb_frontend *fe, u16 *strength) break; case SYS_DVBS2: if (internal->lock) { - reg = STB0899_READ_S2REG(STB0899_DEMOD, IF_AGC_GAIN); + reg = STB0899_READ_S2REG(STB0899_S2DEMOD, IF_AGC_GAIN); val = STB0899_GETFIELD(IF_AGC_GAIN, reg); *strength = stb0899_table_lookup(stb0899_dvbs2rf_tab, ARRAY_SIZE(stb0899_dvbs2rf_tab) - 1, val); -- cgit v1.2.3 From 77768e4b754fdb38d235d8a2384cc8b334367366 Mon Sep 17 00:00:00 2001 From: Malcolm Priestley Date: Fri, 2 Mar 2012 18:15:41 -0300 Subject: [media] STV0288 increase delay between carrier search The current delay of 30uS is too short to recover any carrier. In the lmedm04 driver delays were added to overcome carrier lock problems. The typical delay was 30mS (2 x 15ms register write 0x2c and read 0x24). Other drivers that use STV0288 don't appear to have any delay are likely to have also suffered this problem. Signed-off-by: Malcolm Priestley Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/stv0288.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/frontends/stv0288.c b/drivers/media/dvb/frontends/stv0288.c index fb5548a82208..632b25156e4c 100644 --- a/drivers/media/dvb/frontends/stv0288.c +++ b/drivers/media/dvb/frontends/stv0288.c @@ -506,7 +506,7 @@ static int stv0288_set_frontend(struct dvb_frontend *fe) tda[1] = (unsigned char)tm; stv0288_writeregI(state, 0x2b, tda[1]); stv0288_writeregI(state, 0x2c, tda[2]); - udelay(30); + msleep(30); } state->tuner_frequency = c->frequency; state->fec_inner = FEC_AUTO; -- cgit v1.2.3 From 1a611d8cd078e0059a4a596bcbed0bd8a915e2ef Mon Sep 17 00:00:00 2001 From: Malcolm Priestley Date: Fri, 2 Mar 2012 18:19:30 -0300 Subject: [media] lmedm04 ver 1.97 Remove delays required for STV0288 Remove delays added for STV0288 frontend. This patch significantly speeds up channel change and scan. It requires patch 10161-STV0288 increase delay between carrier search. Signed-off-by: Malcolm Priestley Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/lmedm04.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/dvb-usb/lmedm04.c b/drivers/media/dvb/dvb-usb/lmedm04.c index c33134c5d514..3e6ed2800af2 100644 --- a/drivers/media/dvb/dvb-usb/lmedm04.c +++ b/drivers/media/dvb/dvb-usb/lmedm04.c @@ -181,8 +181,6 @@ static int lme2510_usb_talk(struct dvb_usb_device *d, ret |= lme2510_bulk_write(d->udev, buff, wlen , 0x01); - msleep(10); - ret |= usb_clear_halt(d->udev, usb_rcvbulkpipe(d->udev, 0x01)); ret |= lme2510_bulk_read(d->udev, buff, (rlen < 64) ? @@ -455,8 +453,6 @@ static int lme2510_msg(struct dvb_usb_device *d, st->i2c_talk_onoff = 0; } } - if ((wbuf[3] != 0x6) & (wbuf[3] != 0x5)) - msleep(5); } break; case TUNER_S0194: @@ -1294,5 +1290,5 @@ module_usb_driver(lme2510_driver); MODULE_AUTHOR("Malcolm Priestley "); MODULE_DESCRIPTION("LME2510(C) DVB-S USB2.0"); -MODULE_VERSION("1.96"); +MODULE_VERSION("1.97"); MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 962f8f67e48693d110c26d06089406dd9931474d Mon Sep 17 00:00:00 2001 From: Jose Alberto Reguero Date: Sun, 4 Mar 2012 19:22:05 -0300 Subject: [media] Add CI support to az6007 driver This patch add CI support to az6007 driver. Signed-off-by: Jose Alberto Reguero Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/az6007.c | 377 ++++++++++++++++++++++++++++++++++++- 1 file changed, 376 insertions(+), 1 deletion(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/dvb-usb/az6007.c b/drivers/media/dvb/dvb-usb/az6007.c index df4cbc0ed932..4008b9c50fbd 100644 --- a/drivers/media/dvb/dvb-usb/az6007.c +++ b/drivers/media/dvb/dvb-usb/az6007.c @@ -54,6 +54,7 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); 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); @@ -218,6 +219,371 @@ static int az6007_rc_query(struct dvb_usb_device *d) return 0; } +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 = (struct az6007_device_state *)d->priv; + + 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) { + warn("usb in operation failed. (%d)", ret); + ret = -EINVAL; + } else { + ret = b[0]; + } + + mutex_unlock(&state->ca_mutex); + kfree(b); + return ret; +} + +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 = (struct az6007_device_state *)d->priv; + + int ret; + u8 req; + u16 value1; + u16 index; + int blen; + + deb_info("%s %d", __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) + warn("usb out operation failed. (%d)", ret); + + mutex_unlock(&state->ca_mutex); + return ret; +} + +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 = (struct az6007_device_state *)d->priv; + + 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) { + warn("usb in operation failed. (%d)", ret); + ret = -EINVAL; + } else { + if (b[0] == 0) + warn("Read CI IO error"); + + ret = b[1]; + deb_info("read cam data = %x from 0x%x", b[1], value); + } + + mutex_unlock(&state->ca_mutex); + kfree(b); + return ret; +} + +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 = (struct az6007_device_state *)d->priv; + + 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) { + warn("usb out operation failed. (%d)", ret); + goto failed; + } + +failed: + mutex_unlock(&state->ca_mutex); + return ret; +} + +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) { + warn("usb in operation failed. (%d)", ret); + ret = -EIO; + } else{ + ret = b[0]; + } + kfree(b); + return ret; +} + +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 = (struct az6007_device_state *)d->priv; + + 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) { + warn("usb out operation failed. (%d)", 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) { + warn("usb out operation failed. (%d)", ret); + goto failed; + } + + for (i = 0; i < 15; i++) { + msleep(100); + + if (CI_CamReady(ca, slot)) { + deb_info("CAM Ready"); + break; + } + } + msleep(5000); + +failed: + mutex_unlock(&state->ca_mutex); + return ret; +} + +static int az6007_ci_slot_shutdown(struct dvb_ca_en50221 *ca, int slot) +{ + return 0; +} + +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 = (struct az6007_device_state *)d->priv; + + int ret; + u8 req; + u16 value; + u16 index; + int blen; + + deb_info("%s", __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) { + warn("usb out operation failed. (%d)", ret); + goto failed; + } + +failed: + mutex_unlock(&state->ca_mutex); + return ret; +} + +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 = (struct az6007_device_state *)d->priv; + 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) { + warn("usb in operation failed. (%d)", 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; +} + + +static void az6007_ci_uninit(struct dvb_usb_device *d) +{ + struct az6007_device_state *state; + + deb_info("%s", __func__); + + if (NULL == d) + return; + + state = (struct az6007_device_state *)d->priv; + if (NULL == state) + return; + + if (NULL == state->ca.data) + return; + + dvb_ca_en50221_release(&state->ca); + + memset(&state->ca, 0, sizeof(state->ca)); +} + + +static int az6007_ci_init(struct dvb_usb_adapter *a) +{ + struct dvb_usb_device *d = a->dev; + struct az6007_device_state *state = (struct az6007_device_state *)d->priv; + int ret; + + deb_info("%s", __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(&a->dvb_adap, + &state->ca, + 0, /* flags */ + 1);/* n_slots */ + if (ret != 0) { + err("Cannot initialize CI: Error %d.", ret); + memset(&state->ca, 0, sizeof(state->ca)); + return ret; + } + + deb_info("CI initialized."); + + return 0; +} + static int az6007_read_mac_addr(struct dvb_usb_device *d, u8 mac[6]) { struct az6007_device_state *st = d->priv; @@ -249,6 +615,8 @@ static int az6007_frontend_attach(struct dvb_usb_adapter *adap) st->gate_ctrl = adap->fe_adap[0].fe->ops.i2c_gate_ctrl; adap->fe_adap[0].fe->ops.i2c_gate_ctrl = drxk_gate_ctrl; + az6007_ci_init(adap); + return 0; } @@ -471,6 +839,13 @@ int az6007_identify_state(struct usb_device *udev, static struct dvb_usb_device_properties az6007_properties; +static void az6007_usb_disconnect(struct usb_interface *intf) +{ + struct dvb_usb_device *d = usb_get_intfdata(intf); + az6007_ci_uninit(d); + dvb_usb_device_exit(intf); +} + static int az6007_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) { @@ -546,7 +921,7 @@ static struct dvb_usb_device_properties az6007_properties = { static struct usb_driver az6007_usb_driver = { .name = "dvb_usb_az6007", .probe = az6007_usb_probe, - .disconnect = dvb_usb_device_exit, + .disconnect = az6007_usb_disconnect, .id_table = az6007_usb_table, }; -- cgit v1.2.3 From 9bb24a7e49c33c16c4d9d7d3496f46626e573d02 Mon Sep 17 00:00:00 2001 From: Alexey Khoroshilov Date: Tue, 6 Mar 2012 17:08:16 -0300 Subject: [media] dib9000: fix explicit lock mismatches There are several error paths, where &state->platform.risc.mem_mbx_lock is not unlocked. The patch fixes it. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Alexey Khoroshilov Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/dib9000.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/frontends/dib9000.c b/drivers/media/dvb/frontends/dib9000.c index 863ef3cfab9f..d96b6a1e65d9 100644 --- a/drivers/media/dvb/frontends/dib9000.c +++ b/drivers/media/dvb/frontends/dib9000.c @@ -2208,6 +2208,7 @@ static int dib9000_read_signal_strength(struct dvb_frontend *fe, u16 * strength) DibAcquireLock(&state->platform.risc.mem_mbx_lock); if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) { + DibReleaseLock(&state->platform.risc.mem_mbx_lock); ret = -EIO; goto error; } @@ -2233,8 +2234,10 @@ static u32 dib9000_get_snr(struct dvb_frontend *fe) u16 val; DibAcquireLock(&state->platform.risc.mem_mbx_lock); - if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) + if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) { + DibReleaseLock(&state->platform.risc.mem_mbx_lock); return -EIO; + } dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR, (u8 *) c, 16 * 2); DibReleaseLock(&state->platform.risc.mem_mbx_lock); @@ -2291,6 +2294,7 @@ static int dib9000_read_unc_blocks(struct dvb_frontend *fe, u32 * unc) DibAcquireLock(&state->demod_lock); DibAcquireLock(&state->platform.risc.mem_mbx_lock); if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) { + DibReleaseLock(&state->platform.risc.mem_mbx_lock); ret = -EIO; goto error; } -- cgit v1.2.3 From f3033aecf2341a4e2669c63ed78a190a1c3e7a3a Mon Sep 17 00:00:00 2001 From: Alexey Khoroshilov Date: Tue, 6 Mar 2012 17:08:29 -0300 Subject: [media] dib9000: implement error handling for DibAcquireLock DibAcquireLock() is implemented as mutex_lock_interruptible() but the driver does not handle unsuccessful locking. As a result it may lead to unlock of an unheld mutex. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Alexey Khoroshilov Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/dib9000.c | 115 +++++++++++++++++++++++++++------- 1 file changed, 91 insertions(+), 24 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/frontends/dib9000.c b/drivers/media/dvb/frontends/dib9000.c index d96b6a1e65d9..80848b4c15d4 100644 --- a/drivers/media/dvb/frontends/dib9000.c +++ b/drivers/media/dvb/frontends/dib9000.c @@ -33,7 +33,7 @@ struct i2c_device { /* lock */ #define DIB_LOCK struct mutex -#define DibAcquireLock(lock) do { if (mutex_lock_interruptible(lock) < 0) dprintk("could not get the lock"); } while (0) +#define DibAcquireLock(lock) mutex_lock_interruptible(lock) #define DibReleaseLock(lock) mutex_unlock(lock) #define DibInitLock(lock) mutex_init(lock) #define DibFreeLock(lock) @@ -446,7 +446,10 @@ static int dib9000_risc_mem_read(struct dib9000_state *state, u8 cmd, u8 * b, u1 if (!state->platform.risc.fw_is_running) return -EIO; - DibAcquireLock(&state->platform.risc.mem_lock); + if (DibAcquireLock(&state->platform.risc.mem_lock) < 0) { + dprintk("could not get the lock"); + return -EINTR; + } dib9000_risc_mem_setup(state, cmd | 0x80); dib9000_risc_mem_read_chunks(state, b, len); DibReleaseLock(&state->platform.risc.mem_lock); @@ -459,7 +462,10 @@ static int dib9000_risc_mem_write(struct dib9000_state *state, u8 cmd, const u8 if (!state->platform.risc.fw_is_running) return -EIO; - DibAcquireLock(&state->platform.risc.mem_lock); + if (DibAcquireLock(&state->platform.risc.mem_lock) < 0) { + dprintk("could not get the lock"); + return -EINTR; + } dib9000_risc_mem_setup(state, cmd); dib9000_risc_mem_write_chunks(state, b, m->size); DibReleaseLock(&state->platform.risc.mem_lock); @@ -531,7 +537,10 @@ static int dib9000_mbx_send_attr(struct dib9000_state *state, u8 id, u16 * data, if (!state->platform.risc.fw_is_running) return -EINVAL; - DibAcquireLock(&state->platform.risc.mbx_if_lock); + if (DibAcquireLock(&state->platform.risc.mbx_if_lock) < 0) { + dprintk("could not get the lock"); + return -EINTR; + } tmp = MAX_MAILBOX_TRY; do { size = dib9000_read_word_attr(state, 1043, attr) & 0xff; @@ -593,7 +602,10 @@ static u8 dib9000_mbx_read(struct dib9000_state *state, u16 * data, u8 risc_id, if (!state->platform.risc.fw_is_running) return 0; - DibAcquireLock(&state->platform.risc.mbx_if_lock); + if (DibAcquireLock(&state->platform.risc.mbx_if_lock) < 0) { + dprintk("could not get the lock"); + return 0; + } if (risc_id == 1) mc_base = 16; else @@ -701,7 +713,10 @@ static int dib9000_mbx_process(struct dib9000_state *state, u16 attr) if (!state->platform.risc.fw_is_running) return -1; - DibAcquireLock(&state->platform.risc.mbx_lock); + if (DibAcquireLock(&state->platform.risc.mbx_lock) < 0) { + dprintk("could not get the lock"); + return -1; + } if (dib9000_mbx_count(state, 1, attr)) /* 1=RiscB */ ret = dib9000_mbx_fetch_to_cache(state, attr); @@ -1178,7 +1193,10 @@ static int dib9000_fw_get_channel(struct dvb_frontend *fe) struct dibDVBTChannel *ch; int ret = 0; - DibAcquireLock(&state->platform.risc.mem_mbx_lock); + if (DibAcquireLock(&state->platform.risc.mem_mbx_lock) < 0) { + dprintk("could not get the lock"); + return -EINTR; + } if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) { ret = -EIO; goto error; @@ -1660,7 +1678,10 @@ static int dib9000_fw_component_bus_xfer(struct i2c_adapter *i2c_adap, struct i2 p[12] = 0; } - DibAcquireLock(&state->platform.risc.mem_mbx_lock); + if (DibAcquireLock(&state->platform.risc.mem_mbx_lock) < 0) { + dprintk("could not get the lock"); + return 0; + } dib9000_risc_mem_write(state, FE_MM_W_COMPONENT_ACCESS, p); @@ -1768,7 +1789,10 @@ int dib9000_fw_pid_filter_ctrl(struct dvb_frontend *fe, u8 onoff) return 0; } - DibAcquireLock(&state->demod_lock); + if (DibAcquireLock(&state->demod_lock) < 0) { + dprintk("could not get the lock"); + return -EINTR; + } val = dib9000_read_word(state, 294 + 1) & 0xffef; val |= (onoff & 0x1) << 4; @@ -1800,7 +1824,10 @@ int dib9000_fw_pid_filter(struct dvb_frontend *fe, u8 id, u16 pid, u8 onoff) return 0; } - DibAcquireLock(&state->demod_lock); + if (DibAcquireLock(&state->demod_lock) < 0) { + dprintk("could not get the lock"); + return -EINTR; + } dprintk("Index %x, PID %d, OnOff %d", id, pid, onoff); ret = dib9000_write_word(state, 300 + 1 + id, onoff ? (1 << 13) | pid : 0); @@ -1848,7 +1875,10 @@ static int dib9000_sleep(struct dvb_frontend *fe) u8 index_frontend; int ret = 0; - DibAcquireLock(&state->demod_lock); + if (DibAcquireLock(&state->demod_lock) < 0) { + dprintk("could not get the lock"); + return -EINTR; + } for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) { ret = state->fe[index_frontend]->ops.sleep(state->fe[index_frontend]); if (ret < 0) @@ -1874,8 +1904,12 @@ static int dib9000_get_frontend(struct dvb_frontend *fe) fe_status_t stat; int ret = 0; - if (state->get_frontend_internal == 0) - DibAcquireLock(&state->demod_lock); + if (state->get_frontend_internal == 0) { + if (DibAcquireLock(&state->demod_lock) < 0) { + dprintk("could not get the lock"); + return -EINTR; + } + } for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) { state->fe[index_frontend]->ops.read_status(state->fe[index_frontend], &stat); @@ -1978,7 +2012,10 @@ static int dib9000_set_frontend(struct dvb_frontend *fe) } state->pid_ctrl_index = -1; /* postpone the pid filtering cmd */ - DibAcquireLock(&state->demod_lock); + if (DibAcquireLock(&state->demod_lock) < 0) { + dprintk("could not get the lock"); + return 0; + } fe->dtv_property_cache.delivery_system = SYS_DVBT; @@ -2138,7 +2175,10 @@ static int dib9000_read_status(struct dvb_frontend *fe, fe_status_t * stat) u8 index_frontend; u16 lock = 0, lock_slave = 0; - DibAcquireLock(&state->demod_lock); + if (DibAcquireLock(&state->demod_lock) < 0) { + dprintk("could not get the lock"); + return -EINTR; + } for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) lock_slave |= dib9000_read_lock(state->fe[index_frontend]); @@ -2168,8 +2208,15 @@ static int dib9000_read_ber(struct dvb_frontend *fe, u32 * ber) u16 *c; int ret = 0; - DibAcquireLock(&state->demod_lock); - DibAcquireLock(&state->platform.risc.mem_mbx_lock); + if (DibAcquireLock(&state->demod_lock) < 0) { + dprintk("could not get the lock"); + return -EINTR; + } + if (DibAcquireLock(&state->platform.risc.mem_mbx_lock) < 0) { + dprintk("could not get the lock"); + ret = -EINTR; + goto error; + } if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) { DibReleaseLock(&state->platform.risc.mem_mbx_lock); ret = -EIO; @@ -2196,7 +2243,10 @@ static int dib9000_read_signal_strength(struct dvb_frontend *fe, u16 * strength) u16 val; int ret = 0; - DibAcquireLock(&state->demod_lock); + if (DibAcquireLock(&state->demod_lock) < 0) { + dprintk("could not get the lock"); + return -EINTR; + } *strength = 0; for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) { state->fe[index_frontend]->ops.read_signal_strength(state->fe[index_frontend], &val); @@ -2206,7 +2256,11 @@ static int dib9000_read_signal_strength(struct dvb_frontend *fe, u16 * strength) *strength += val; } - DibAcquireLock(&state->platform.risc.mem_mbx_lock); + if (DibAcquireLock(&state->platform.risc.mem_mbx_lock) < 0) { + dprintk("could not get the lock"); + ret = -EINTR; + goto error; + } if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) { DibReleaseLock(&state->platform.risc.mem_mbx_lock); ret = -EIO; @@ -2233,10 +2287,13 @@ static u32 dib9000_get_snr(struct dvb_frontend *fe) u32 n, s, exp; u16 val; - DibAcquireLock(&state->platform.risc.mem_mbx_lock); + if (DibAcquireLock(&state->platform.risc.mem_mbx_lock) < 0) { + dprintk("could not get the lock"); + return 0; + } if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) { DibReleaseLock(&state->platform.risc.mem_mbx_lock); - return -EIO; + return 0; } dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR, (u8 *) c, 16 * 2); DibReleaseLock(&state->platform.risc.mem_mbx_lock); @@ -2269,7 +2326,10 @@ static int dib9000_read_snr(struct dvb_frontend *fe, u16 * snr) u8 index_frontend; u32 snr_master; - DibAcquireLock(&state->demod_lock); + if (DibAcquireLock(&state->demod_lock) < 0) { + dprintk("could not get the lock"); + return -EINTR; + } snr_master = dib9000_get_snr(fe); for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) snr_master += dib9000_get_snr(state->fe[index_frontend]); @@ -2291,8 +2351,15 @@ static int dib9000_read_unc_blocks(struct dvb_frontend *fe, u32 * unc) u16 *c = (u16 *)state->i2c_read_buffer; int ret = 0; - DibAcquireLock(&state->demod_lock); - DibAcquireLock(&state->platform.risc.mem_mbx_lock); + if (DibAcquireLock(&state->demod_lock) < 0) { + dprintk("could not get the lock"); + return -EINTR; + } + if (DibAcquireLock(&state->platform.risc.mem_mbx_lock) < 0) { + dprintk("could not get the lock"); + ret = -EINTR; + goto error; + } if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) { DibReleaseLock(&state->platform.risc.mem_mbx_lock); ret = -EIO; -- cgit v1.2.3 From 3caaa20121495145cd8fef274d6eea5d90ee7182 Mon Sep 17 00:00:00 2001 From: Santosh Nayak Date: Tue, 6 Mar 2012 23:41:03 -0300 Subject: [media] dvb: negative value assigned to unsigned int in CDRXD() In CDRXD(), Negative number is assigned to unsigned variable 'state->noise_cal.tdCal2. Members of 'SNoiseCal' should be 'signed short'. Signed-off-by: Santosh Nayak Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/drxd_hard.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/frontends/drxd_hard.c b/drivers/media/dvb/frontends/drxd_hard.c index 7bf39cda83c5..f380eb43e9d5 100644 --- a/drivers/media/dvb/frontends/drxd_hard.c +++ b/drivers/media/dvb/frontends/drxd_hard.c @@ -101,9 +101,9 @@ struct SCfgAgc { struct SNoiseCal { int cpOpt; - u16 cpNexpOfs; - u16 tdCal2k; - u16 tdCal8k; + short cpNexpOfs; + short tdCal2k; + short tdCal8k; }; enum app_env { -- cgit v1.2.3 From 77c2402dc6c900a2d60587cd83bc1ee3dd39c460 Mon Sep 17 00:00:00 2001 From: Malcolm Priestley Date: Wed, 7 Mar 2012 18:06:23 -0300 Subject: [media] lmedm04 v1.98 Remove clear halt These were in the original lme2510 device driver. Removing them significantly speeds up the driver. All tuners tested. Signed-off-by: Malcolm Priestley Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/lmedm04.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/dvb-usb/lmedm04.c b/drivers/media/dvb/dvb-usb/lmedm04.c index 3e6ed2800af2..a251583fe292 100644 --- a/drivers/media/dvb/dvb-usb/lmedm04.c +++ b/drivers/media/dvb/dvb-usb/lmedm04.c @@ -177,12 +177,8 @@ static int lme2510_usb_talk(struct dvb_usb_device *d, /* the read/write capped at 64 */ memcpy(buff, wbuf, (wlen < 64) ? wlen : 64); - ret |= usb_clear_halt(d->udev, usb_sndbulkpipe(d->udev, 0x01)); - ret |= lme2510_bulk_write(d->udev, buff, wlen , 0x01); - ret |= usb_clear_halt(d->udev, usb_rcvbulkpipe(d->udev, 0x01)); - ret |= lme2510_bulk_read(d->udev, buff, (rlen < 64) ? rlen : 64 , 0x01); @@ -1290,5 +1286,5 @@ module_usb_driver(lme2510_driver); MODULE_AUTHOR("Malcolm Priestley "); MODULE_DESCRIPTION("LME2510(C) DVB-S USB2.0"); -MODULE_VERSION("1.97"); +MODULE_VERSION("1.98"); MODULE_LICENSE("GPL"); -- cgit v1.2.3 From ae8dc8ee2b84d31306766d87cc5b2bb42e216f57 Mon Sep 17 00:00:00 2001 From: Malcolm Priestley Date: Wed, 7 Mar 2012 18:11:03 -0300 Subject: [media] m88rs2000 1.12 v2 DVB-S frontend and tuner module Support for m88rs2000 chip used in lmedm04 driver. Note there are still lock problems. Slow channel change due to the large block of registers sent in set_frontend. Version 2 differences. Front end is completely shut down when in sleep mode. This allow user to regain control of device. Kaffeine scan problem solved by removing register calls from get_frontend. Kaffeine seems to call get_frontend when updating signal data. This can happen in the middle of a tune stalling the driver. Change calculations to those in the DS3000 driver. Signed-off-by: Malcolm Priestley Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/Kconfig | 8 + drivers/media/dvb/frontends/Makefile | 1 + drivers/media/dvb/frontends/m88rs2000.c | 906 ++++++++++++++++++++++++++++++++ drivers/media/dvb/frontends/m88rs2000.h | 66 +++ 4 files changed, 981 insertions(+) create mode 100644 drivers/media/dvb/frontends/m88rs2000.c create mode 100644 drivers/media/dvb/frontends/m88rs2000.h (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig index 2995204c3355..21246707fbfb 100644 --- a/drivers/media/dvb/frontends/Kconfig +++ b/drivers/media/dvb/frontends/Kconfig @@ -705,6 +705,14 @@ config DVB_IT913X_FE A DVB-T tuner module. Say Y when you want to support this frontend. +config DVB_M88RS2000 + tristate "M88RS2000 DVB-S demodulator and tuner" + depends on DVB_CORE && I2C + default m if DVB_FE_CUSTOMISE + help + A DVB-S tuner module. + Say Y when you want to support this frontend. + comment "Tools to develop new frontends" config DVB_DUMMY_FE diff --git a/drivers/media/dvb/frontends/Makefile b/drivers/media/dvb/frontends/Makefile index 17519dc027d8..86fa808bf589 100644 --- a/drivers/media/dvb/frontends/Makefile +++ b/drivers/media/dvb/frontends/Makefile @@ -97,4 +97,5 @@ obj-$(CONFIG_DVB_IT913X_FE) += it913x-fe.o obj-$(CONFIG_DVB_A8293) += a8293.o obj-$(CONFIG_DVB_TDA10071) += tda10071.o obj-$(CONFIG_DVB_RTL2830) += rtl2830.o +obj-$(CONFIG_DVB_M88RS2000) += m88rs2000.o diff --git a/drivers/media/dvb/frontends/m88rs2000.c b/drivers/media/dvb/frontends/m88rs2000.c new file mode 100644 index 000000000000..c9a34358128b --- /dev/null +++ b/drivers/media/dvb/frontends/m88rs2000.c @@ -0,0 +1,906 @@ +/* + Driver for M88RS2000 demodulator and tuner + + Copyright (C) 2012 Malcolm Priestley (tvboxspy@gmail.com) + Beta Driver + + Include various calculation code from DS3000 driver. + Copyright (C) 2009 Konstantin Dimitrov. + + 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; either version 2 of the License, or + (at your option) any later version. + + 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. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ +#include +#include +#include +#include +#include +#include +#include + + +#include "dvb_frontend.h" +#include "m88rs2000.h" + +struct m88rs2000_state { + struct i2c_adapter *i2c; + const struct m88rs2000_config *config; + struct dvb_frontend frontend; + u8 no_lock_count; + u32 tuner_frequency; + u32 symbol_rate; + fe_code_rate_t fec_inner; + u8 tuner_level; + int errmode; +}; + +static int m88rs2000_debug; + +module_param_named(debug, m88rs2000_debug, int, 0644); +MODULE_PARM_DESC(debug, "set debugging level (1=info (or-able))."); + +#define dprintk(level, args...) do { \ + if (level & m88rs2000_debug) \ + printk(KERN_DEBUG "m88rs2000-fe: " args); \ +} while (0) + +#define deb_info(args...) dprintk(0x01, args) +#define info(format, arg...) \ + printk(KERN_INFO "m88rs2000-fe: " format "\n" , ## arg) + +static int m88rs2000_writereg(struct m88rs2000_state *state, u8 tuner, + u8 reg, u8 data) +{ + int ret; + u8 addr = (tuner == 0) ? state->config->tuner_addr : + state->config->demod_addr; + u8 buf[] = { reg, data }; + struct i2c_msg msg = { + .addr = addr, + .flags = 0, + .buf = buf, + .len = 2 + }; + + ret = i2c_transfer(state->i2c, &msg, 1); + + if (ret != 1) + deb_info("%s: writereg error (reg == 0x%02x, val == 0x%02x, " + "ret == %i)\n", __func__, reg, data, ret); + + return (ret != 1) ? -EREMOTEIO : 0; +} + +static int m88rs2000_demod_write(struct m88rs2000_state *state, u8 reg, u8 data) +{ + return m88rs2000_writereg(state, 1, reg, data); +} + +static int m88rs2000_tuner_write(struct m88rs2000_state *state, u8 reg, u8 data) +{ + m88rs2000_demod_write(state, 0x81, 0x84); + udelay(10); + return m88rs2000_writereg(state, 0, reg, data); + +} + +static int m88rs2000_write(struct dvb_frontend *fe, const u8 buf[], int len) +{ + struct m88rs2000_state *state = fe->demodulator_priv; + + if (len != 2) + return -EINVAL; + + return m88rs2000_writereg(state, 1, buf[0], buf[1]); +} + +static u8 m88rs2000_readreg(struct m88rs2000_state *state, u8 tuner, u8 reg) +{ + int ret; + u8 b0[] = { reg }; + u8 b1[] = { 0 }; + u8 addr = (tuner == 0) ? state->config->tuner_addr : + state->config->demod_addr; + struct i2c_msg msg[] = { + { + .addr = addr, + .flags = 0, + .buf = b0, + .len = 1 + }, { + .addr = addr, + .flags = I2C_M_RD, + .buf = b1, + .len = 1 + } + }; + + ret = i2c_transfer(state->i2c, msg, 2); + + if (ret != 2) + deb_info("%s: readreg error (reg == 0x%02x, ret == %i)\n", + __func__, reg, ret); + + return b1[0]; +} + +static u8 m88rs2000_demod_read(struct m88rs2000_state *state, u8 reg) +{ + return m88rs2000_readreg(state, 1, reg); +} + +static u8 m88rs2000_tuner_read(struct m88rs2000_state *state, u8 reg) +{ + m88rs2000_demod_write(state, 0x81, 0x85); + udelay(10); + return m88rs2000_readreg(state, 0, reg); +} + +static int m88rs2000_set_symbolrate(struct dvb_frontend *fe, u32 srate) +{ + struct m88rs2000_state *state = fe->demodulator_priv; + int ret; + u32 temp; + u8 b[3]; + + if ((srate < 1000000) || (srate > 45000000)) + return -EINVAL; + + temp = srate / 1000; + temp *= 11831; + temp /= 68; + temp -= 3; + + b[0] = (u8) (temp >> 16) & 0xff; + b[1] = (u8) (temp >> 8) & 0xff; + b[2] = (u8) temp & 0xff; + ret = m88rs2000_demod_write(state, 0x93, b[2]); + ret |= m88rs2000_demod_write(state, 0x94, b[1]); + ret |= m88rs2000_demod_write(state, 0x95, b[0]); + + deb_info("m88rs2000: m88rs2000_set_symbolrate\n"); + return ret; +} + +static int m88rs2000_send_diseqc_msg(struct dvb_frontend *fe, + struct dvb_diseqc_master_cmd *m) +{ + struct m88rs2000_state *state = fe->demodulator_priv; + + int i; + u8 reg; + deb_info("%s\n", __func__); + m88rs2000_demod_write(state, 0x9a, 0x30); + reg = m88rs2000_demod_read(state, 0xb2); + reg &= 0x3f; + m88rs2000_demod_write(state, 0xb2, reg); + for (i = 0; i < m->msg_len; i++) + m88rs2000_demod_write(state, 0xb3 + i, m->msg[i]); + + reg = m88rs2000_demod_read(state, 0xb1); + reg &= 0x87; + reg |= ((m->msg_len - 1) << 3) | 0x07; + reg &= 0x7f; + m88rs2000_demod_write(state, 0xb1, reg); + + for (i = 0; i < 15; i++) { + if ((m88rs2000_demod_read(state, 0xb1) & 0x40) == 0x0) + break; + msleep(20); + } + + reg = m88rs2000_demod_read(state, 0xb1); + if ((reg & 0x40) > 0x0) { + reg &= 0x7f; + reg |= 0x40; + m88rs2000_demod_write(state, 0xb1, reg); + } + + reg = m88rs2000_demod_read(state, 0xb2); + reg &= 0x3f; + reg |= 0x80; + m88rs2000_demod_write(state, 0xb2, reg); + m88rs2000_demod_write(state, 0x9a, 0xb0); + + + return 0; +} + +static int m88rs2000_send_diseqc_burst(struct dvb_frontend *fe, + fe_sec_mini_cmd_t burst) +{ + struct m88rs2000_state *state = fe->demodulator_priv; + u8 reg0, reg1; + deb_info("%s\n", __func__); + m88rs2000_demod_write(state, 0x9a, 0x30); + msleep(50); + reg0 = m88rs2000_demod_read(state, 0xb1); + reg1 = m88rs2000_demod_read(state, 0xb2); + if (burst == SEC_MINI_B) + reg1 |= 0x1; + m88rs2000_demod_write(state, 0xb2, reg1); + m88rs2000_demod_write(state, 0xb1, reg0); + m88rs2000_demod_write(state, 0x9a, 0xb0); + + return 0; +} + +static int m88rs2000_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone) +{ + struct m88rs2000_state *state = fe->demodulator_priv; + u8 reg0, reg1; + m88rs2000_demod_write(state, 0x9a, 0x30); + reg0 = m88rs2000_demod_read(state, 0xb1); + reg1 = m88rs2000_demod_read(state, 0xb2); + + reg1 &= 0x3f; + + switch (tone) { + case SEC_TONE_ON: + reg0 |= 0x4; + reg0 &= 0xbc; + break; + case SEC_TONE_OFF: + reg1 |= 0x80; + break; + + default: + return -EINVAL; + } + m88rs2000_demod_write(state, 0xb2, reg1); + m88rs2000_demod_write(state, 0xb1, reg0); + m88rs2000_demod_write(state, 0x9a, 0xb0); + return 0; +} + +struct inittab { + u8 cmd; + u8 reg; + u8 val; +}; + +struct inittab m88rs2000_setup[] = { + {DEMOD_WRITE, 0x9a, 0x30}, + {DEMOD_WRITE, 0x00, 0x01}, + {WRITE_DELAY, 0x19, 0x00}, + {DEMOD_WRITE, 0x00, 0x00}, + {DEMOD_WRITE, 0x9a, 0xb0}, + {DEMOD_WRITE, 0x81, 0xc1}, + {TUNER_WRITE, 0x42, 0x73}, + {TUNER_WRITE, 0x05, 0x07}, + {TUNER_WRITE, 0x20, 0x27}, + {TUNER_WRITE, 0x07, 0x02}, + {TUNER_WRITE, 0x11, 0xff}, + {TUNER_WRITE, 0x60, 0xf9}, + {TUNER_WRITE, 0x08, 0x01}, + {TUNER_WRITE, 0x00, 0x41}, + {DEMOD_WRITE, 0x81, 0x81}, + {DEMOD_WRITE, 0x86, 0xc6}, + {DEMOD_WRITE, 0x9a, 0x30}, + {DEMOD_WRITE, 0xf0, 0x22}, + {DEMOD_WRITE, 0xf1, 0xbf}, + {DEMOD_WRITE, 0xb0, 0x45}, + {DEMOD_WRITE, 0x9a, 0xb0}, + {0xff, 0xaa, 0xff} +}; + +struct inittab m88rs2000_shutdown[] = { + {DEMOD_WRITE, 0x9a, 0x30}, + {DEMOD_WRITE, 0xb0, 0x00}, + {DEMOD_WRITE, 0xf1, 0x89}, + {DEMOD_WRITE, 0x00, 0x01}, + {DEMOD_WRITE, 0x9a, 0xb0}, + {TUNER_WRITE, 0x00, 0x40}, + {DEMOD_WRITE, 0x81, 0x81}, + {0xff, 0xaa, 0xff} +}; + +struct inittab tuner_reset[] = { + {TUNER_WRITE, 0x42, 0x73}, + {TUNER_WRITE, 0x05, 0x07}, + {TUNER_WRITE, 0x20, 0x27}, + {TUNER_WRITE, 0x07, 0x02}, + {TUNER_WRITE, 0x11, 0xff}, + {TUNER_WRITE, 0x60, 0xf9}, + {TUNER_WRITE, 0x08, 0x01}, + {TUNER_WRITE, 0x00, 0x41}, + {0xff, 0xaa, 0xff} +}; + +struct inittab fe_reset[] = { + {DEMOD_WRITE, 0x00, 0x01}, + {DEMOD_WRITE, 0xf1, 0xbf}, + {DEMOD_WRITE, 0x00, 0x01}, + {DEMOD_WRITE, 0x20, 0x81}, + {DEMOD_WRITE, 0x21, 0x80}, + {DEMOD_WRITE, 0x10, 0x33}, + {DEMOD_WRITE, 0x11, 0x44}, + {DEMOD_WRITE, 0x12, 0x07}, + {DEMOD_WRITE, 0x18, 0x20}, + {DEMOD_WRITE, 0x28, 0x04}, + {DEMOD_WRITE, 0x29, 0x8e}, + {DEMOD_WRITE, 0x3b, 0xff}, + {DEMOD_WRITE, 0x32, 0x10}, + {DEMOD_WRITE, 0x33, 0x02}, + {DEMOD_WRITE, 0x34, 0x30}, + {DEMOD_WRITE, 0x35, 0xff}, + {DEMOD_WRITE, 0x38, 0x50}, + {DEMOD_WRITE, 0x39, 0x68}, + {DEMOD_WRITE, 0x3c, 0x7f}, + {DEMOD_WRITE, 0x3d, 0x0f}, + {DEMOD_WRITE, 0x45, 0x20}, + {DEMOD_WRITE, 0x46, 0x24}, + {DEMOD_WRITE, 0x47, 0x7c}, + {DEMOD_WRITE, 0x48, 0x16}, + {DEMOD_WRITE, 0x49, 0x04}, + {DEMOD_WRITE, 0x4a, 0x01}, + {DEMOD_WRITE, 0x4b, 0x78}, + {DEMOD_WRITE, 0X4d, 0xd2}, + {DEMOD_WRITE, 0x4e, 0x6d}, + {DEMOD_WRITE, 0x50, 0x30}, + {DEMOD_WRITE, 0x51, 0x30}, + {DEMOD_WRITE, 0x54, 0x7b}, + {DEMOD_WRITE, 0x56, 0x09}, + {DEMOD_WRITE, 0x58, 0x59}, + {DEMOD_WRITE, 0x59, 0x37}, + {DEMOD_WRITE, 0x63, 0xfa}, + {0xff, 0xaa, 0xff} +}; + +struct inittab fe_trigger[] = { + {DEMOD_WRITE, 0x97, 0x04}, + {DEMOD_WRITE, 0x99, 0x77}, + {DEMOD_WRITE, 0x9b, 0x64}, + {DEMOD_WRITE, 0x9e, 0x00}, + {DEMOD_WRITE, 0x9f, 0xf8}, + {DEMOD_WRITE, 0xa0, 0x20}, + {DEMOD_WRITE, 0xa1, 0xe0}, + {DEMOD_WRITE, 0xa3, 0x38}, + {DEMOD_WRITE, 0x98, 0xff}, + {DEMOD_WRITE, 0xc0, 0x0f}, + {DEMOD_WRITE, 0x89, 0x01}, + {DEMOD_WRITE, 0x00, 0x00}, + {WRITE_DELAY, 0x0a, 0x00}, + {DEMOD_WRITE, 0x00, 0x01}, + {DEMOD_WRITE, 0x00, 0x00}, + {DEMOD_WRITE, 0x9a, 0xb0}, + {0xff, 0xaa, 0xff} +}; + +static int m88rs2000_tab_set(struct m88rs2000_state *state, + struct inittab *tab) +{ + int ret = 0; + u8 i; + if (tab == NULL) + return -EINVAL; + + for (i = 0; i < 255; i++) { + switch (tab[i].cmd) { + case 0x01: + ret = m88rs2000_demod_write(state, tab[i].reg, + tab[i].val); + break; + case 0x02: + ret = m88rs2000_tuner_write(state, tab[i].reg, + tab[i].val); + break; + case 0x10: + if (tab[i].reg > 0) + mdelay(tab[i].reg); + break; + case 0xff: + if (tab[i].reg == 0xaa && tab[i].val == 0xff) + return 0; + case 0x00: + break; + default: + return -EINVAL; + } + if (ret < 0) + return -ENODEV; + } + return 0; +} + +static int m88rs2000_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t volt) +{ + deb_info("%s: %s\n", __func__, + volt == SEC_VOLTAGE_13 ? "SEC_VOLTAGE_13" : + volt == SEC_VOLTAGE_18 ? "SEC_VOLTAGE_18" : "??"); + + return 0; +} + +static int m88rs2000_startup(struct m88rs2000_state *state) +{ + int ret = 0; + u8 reg; + + reg = m88rs2000_tuner_read(state, 0x00); + if ((reg & 0x40) == 0) + ret = -ENODEV; + + return ret; +} + +static int m88rs2000_init(struct dvb_frontend *fe) +{ + struct m88rs2000_state *state = fe->demodulator_priv; + int ret; + + deb_info("m88rs2000: init chip\n"); + /* Setup frontend from shutdown/cold */ + ret = m88rs2000_tab_set(state, m88rs2000_setup); + + return ret; +} + +static int m88rs2000_sleep(struct dvb_frontend *fe) +{ + struct m88rs2000_state *state = fe->demodulator_priv; + int ret; + /* Shutdown the frondend */ + ret = m88rs2000_tab_set(state, m88rs2000_shutdown); + return ret; +} + +static int m88rs2000_read_status(struct dvb_frontend *fe, fe_status_t *status) +{ + struct m88rs2000_state *state = fe->demodulator_priv; + u8 reg = m88rs2000_demod_read(state, 0x8c); + + *status = 0; + + if ((reg & 0x7) == 0x7) { + *status = FE_HAS_CARRIER | FE_HAS_SIGNAL | FE_HAS_VITERBI + | FE_HAS_LOCK; + if (state->config->set_ts_params) + state->config->set_ts_params(fe, CALL_IS_READ); + } + return 0; +} + +/* Extact code for these unknown but lmedm04 driver uses interupt callbacks */ + +static int m88rs2000_read_ber(struct dvb_frontend *fe, u32 *ber) +{ + deb_info("m88rs2000_read_ber %d\n", *ber); + *ber = 0; + return 0; +} + +static int m88rs2000_read_signal_strength(struct dvb_frontend *fe, + u16 *strength) +{ + *strength = 0; + return 0; +} + +static int m88rs2000_read_snr(struct dvb_frontend *fe, u16 *snr) +{ + deb_info("m88rs2000_read_snr %d\n", *snr); + *snr = 0; + return 0; +} + +static int m88rs2000_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) +{ + deb_info("m88rs2000_read_ber %d\n", *ucblocks); + *ucblocks = 0; + return 0; +} + +static int m88rs2000_tuner_gate_ctrl(struct m88rs2000_state *state, u8 offset) +{ + int ret; + ret = m88rs2000_tuner_write(state, 0x51, 0x1f - offset); + ret |= m88rs2000_tuner_write(state, 0x51, 0x1f); + ret |= m88rs2000_tuner_write(state, 0x50, offset); + ret |= m88rs2000_tuner_write(state, 0x50, 0x00); + msleep(20); + return ret; +} + +static int m88rs2000_set_tuner_rf(struct dvb_frontend *fe) +{ + struct m88rs2000_state *state = fe->demodulator_priv; + int reg; + reg = m88rs2000_tuner_read(state, 0x3d); + reg &= 0x7f; + if (reg < 0x17) + reg = 0xa1; + else if (reg < 0x16) + reg = 0x99; + else + reg = 0xf9; + + m88rs2000_tuner_write(state, 0x60, reg); + reg = m88rs2000_tuner_gate_ctrl(state, 0x08); + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); + return reg; +} + +static int m88rs2000_set_tuner(struct dvb_frontend *fe, u16 *offset) +{ + struct dtv_frontend_properties *c = &fe->dtv_property_cache; + struct m88rs2000_state *state = fe->demodulator_priv; + int ret; + u32 frequency = c->frequency; + s32 offset_khz; + s32 tmp; + u32 symbol_rate = (c->symbol_rate / 1000); + u32 f3db, gdiv28; + u16 value, ndiv, lpf_coeff; + u8 lpf_mxdiv, mlpf_max, mlpf_min, nlpf; + u8 lo = 0x01, div4 = 0x0; + + /* Reset Tuner */ + ret = m88rs2000_tab_set(state, tuner_reset); + + /* Calculate frequency divider */ + if (frequency < 1060000) { + lo |= 0x10; + div4 = 0x1; + ndiv = (frequency * 14 * 4) / FE_CRYSTAL_KHZ; + } else + ndiv = (frequency * 14 * 2) / FE_CRYSTAL_KHZ; + ndiv = ndiv + ndiv % 2; + ndiv = ndiv - 1024; + + ret = m88rs2000_tuner_write(state, 0x10, 0x80 | lo); + + /* Set frequency divider */ + ret |= m88rs2000_tuner_write(state, 0x01, (ndiv >> 8) & 0xf); + ret |= m88rs2000_tuner_write(state, 0x02, ndiv & 0xff); + + ret |= m88rs2000_tuner_write(state, 0x03, 0x06); + ret |= m88rs2000_tuner_gate_ctrl(state, 0x10); + if (ret < 0) + return -ENODEV; + + /* Tuner Frequency Range */ + ret = m88rs2000_tuner_write(state, 0x10, lo); + + ret |= m88rs2000_tuner_gate_ctrl(state, 0x08); + + /* Tuner RF */ + ret |= m88rs2000_set_tuner_rf(fe); + + gdiv28 = (FE_CRYSTAL_KHZ / 1000 * 1694 + 500) / 1000; + ret |= m88rs2000_tuner_write(state, 0x04, gdiv28 & 0xff); + ret |= m88rs2000_tuner_gate_ctrl(state, 0x04); + if (ret < 0) + return -ENODEV; + + value = m88rs2000_tuner_read(state, 0x26); + + f3db = (symbol_rate * 135) / 200 + 2000; + f3db += FREQ_OFFSET_LOW_SYM_RATE; + if (f3db < 7000) + f3db = 7000; + if (f3db > 40000) + f3db = 40000; + + gdiv28 = gdiv28 * 207 / (value * 2 + 151); + mlpf_max = gdiv28 * 135 / 100; + mlpf_min = gdiv28 * 78 / 100; + if (mlpf_max > 63) + mlpf_max = 63; + + lpf_coeff = 2766; + + nlpf = (f3db * gdiv28 * 2 / lpf_coeff / + (FE_CRYSTAL_KHZ / 1000) + 1) / 2; + if (nlpf > 23) + nlpf = 23; + if (nlpf < 1) + nlpf = 1; + + lpf_mxdiv = (nlpf * (FE_CRYSTAL_KHZ / 1000) + * lpf_coeff * 2 / f3db + 1) / 2; + + if (lpf_mxdiv < mlpf_min) { + nlpf++; + lpf_mxdiv = (nlpf * (FE_CRYSTAL_KHZ / 1000) + * lpf_coeff * 2 / f3db + 1) / 2; + } + + if (lpf_mxdiv > mlpf_max) + lpf_mxdiv = mlpf_max; + + ret = m88rs2000_tuner_write(state, 0x04, lpf_mxdiv); + ret |= m88rs2000_tuner_write(state, 0x06, nlpf); + + ret |= m88rs2000_tuner_gate_ctrl(state, 0x04); + + ret |= m88rs2000_tuner_gate_ctrl(state, 0x01); + + msleep(80); + /* calculate offset assuming 96000kHz*/ + offset_khz = (ndiv - ndiv % 2 + 1024) * FE_CRYSTAL_KHZ + / 14 / (div4 + 1) / 2; + + offset_khz -= frequency; + + tmp = offset_khz; + tmp *= 65536; + + tmp = (2 * tmp + 96000) / (2 * 96000); + if (tmp < 0) + tmp += 65536; + + *offset = tmp & 0xffff; + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); + + return (ret < 0) ? -EINVAL : 0; +} + +static int m88rs2000_set_fec(struct m88rs2000_state *state, + fe_code_rate_t fec) +{ + int ret; + u16 fec_set; + switch (fec) { + /* This is not confirmed kept for reference */ +/* case FEC_1_2: + fec_set = 0x88; + break; + case FEC_2_3: + fec_set = 0x68; + break; + case FEC_3_4: + fec_set = 0x48; + break; + case FEC_5_6: + fec_set = 0x28; + break; + case FEC_7_8: + fec_set = 0x18; + break; */ + case FEC_AUTO: + default: + fec_set = 0x08; + } + ret = m88rs2000_demod_write(state, 0x76, fec_set); + + return 0; +} + + +static fe_code_rate_t m88rs2000_get_fec(struct m88rs2000_state *state) +{ + u8 reg; + m88rs2000_demod_write(state, 0x9a, 0x30); + reg = m88rs2000_demod_read(state, 0x76); + m88rs2000_demod_write(state, 0x9a, 0xb0); + + switch (reg) { + case 0x88: + return FEC_1_2; + case 0x68: + return FEC_2_3; + case 0x48: + return FEC_3_4; + case 0x28: + return FEC_5_6; + case 0x18: + return FEC_7_8; + case 0x08: + default: + break; + } + + return FEC_AUTO; +} + +static int m88rs2000_set_frontend(struct dvb_frontend *fe) +{ + struct m88rs2000_state *state = fe->demodulator_priv; + struct dtv_frontend_properties *c = &fe->dtv_property_cache; + fe_status_t status; + int i, ret; + u16 offset = 0; + u8 reg; + + state->no_lock_count = 0; + + if (c->delivery_system != SYS_DVBS) { + deb_info("%s: unsupported delivery " + "system selected (%d)\n", + __func__, c->delivery_system); + return -EOPNOTSUPP; + } + + /* Set Tuner */ + ret = m88rs2000_set_tuner(fe, &offset); + if (ret < 0) + return -ENODEV; + + ret = m88rs2000_demod_write(state, 0x9a, 0x30); + /* Unknown usually 0xc6 sometimes 0xc1 */ + reg = m88rs2000_demod_read(state, 0x86); + ret |= m88rs2000_demod_write(state, 0x86, reg); + /* Offset lower nibble always 0 */ + ret |= m88rs2000_demod_write(state, 0x9c, (offset >> 8)); + ret |= m88rs2000_demod_write(state, 0x9d, offset & 0xf0); + + + /* Reset Demod */ + ret = m88rs2000_tab_set(state, fe_reset); + if (ret < 0) + return -ENODEV; + + /* Unknown */ + reg = m88rs2000_demod_read(state, 0x70); + ret = m88rs2000_demod_write(state, 0x70, reg); + + /* Set FEC */ + ret |= m88rs2000_set_fec(state, c->fec_inner); + ret |= m88rs2000_demod_write(state, 0x85, 0x1); + ret |= m88rs2000_demod_write(state, 0x8a, 0xbf); + ret |= m88rs2000_demod_write(state, 0x8d, 0x1e); + ret |= m88rs2000_demod_write(state, 0x90, 0xf1); + ret |= m88rs2000_demod_write(state, 0x91, 0x08); + + if (ret < 0) + return -ENODEV; + + /* Set Symbol Rate */ + ret = m88rs2000_set_symbolrate(fe, c->symbol_rate); + if (ret < 0) + return -ENODEV; + + /* Set up Demod */ + ret = m88rs2000_tab_set(state, fe_trigger); + if (ret < 0) + return -ENODEV; + + for (i = 0; i < 25; i++) { + u8 reg = m88rs2000_demod_read(state, 0x8c); + if ((reg & 0x7) == 0x7) { + status = FE_HAS_LOCK; + break; + } + state->no_lock_count++; + if (state->no_lock_count > 15) { + reg = m88rs2000_demod_read(state, 0x70); + reg ^= 0x4; + m88rs2000_demod_write(state, 0x70, reg); + state->no_lock_count = 0; + } + if (state->no_lock_count == 20) + m88rs2000_set_tuner_rf(fe); + msleep(20); + } + + if (status & FE_HAS_LOCK) { + state->fec_inner = m88rs2000_get_fec(state); + /* Uknown suspect SNR level */ + reg = m88rs2000_demod_read(state, 0x65); + } + + state->tuner_frequency = c->frequency; + state->symbol_rate = c->symbol_rate; + return 0; +} + +static int m88rs2000_get_frontend(struct dvb_frontend *fe) +{ + struct dtv_frontend_properties *c = &fe->dtv_property_cache; + struct m88rs2000_state *state = fe->demodulator_priv; + c->fec_inner = state->fec_inner; + c->frequency = state->tuner_frequency; + c->symbol_rate = state->symbol_rate; + return 0; +} + +static int m88rs2000_i2c_gate_ctrl(struct dvb_frontend *fe, int enable) +{ + struct m88rs2000_state *state = fe->demodulator_priv; + + if (enable) + m88rs2000_demod_write(state, 0x81, 0x84); + else + m88rs2000_demod_write(state, 0x81, 0x81); + udelay(10); + return 0; +} + +static void m88rs2000_release(struct dvb_frontend *fe) +{ + struct m88rs2000_state *state = fe->demodulator_priv; + kfree(state); +} + +static struct dvb_frontend_ops m88rs2000_ops = { + .delsys = { SYS_DVBS }, + .info = { + .name = "M88RS2000 DVB-S", + .type = FE_QPSK, + .frequency_min = 950000, + .frequency_max = 2150000, + .frequency_stepsize = 1000, /* kHz for QPSK frontends */ + .frequency_tolerance = 5000, + .symbol_rate_min = 1000000, + .symbol_rate_max = 45000000, + .symbol_rate_tolerance = 500, /* ppm */ + .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | + FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | + FE_CAN_QPSK | + FE_CAN_FEC_AUTO + }, + + .release = m88rs2000_release, + .init = m88rs2000_init, + .sleep = m88rs2000_sleep, + .write = m88rs2000_write, + .i2c_gate_ctrl = m88rs2000_i2c_gate_ctrl, + .read_status = m88rs2000_read_status, + .read_ber = m88rs2000_read_ber, + .read_signal_strength = m88rs2000_read_signal_strength, + .read_snr = m88rs2000_read_snr, + .read_ucblocks = m88rs2000_read_ucblocks, + .diseqc_send_master_cmd = m88rs2000_send_diseqc_msg, + .diseqc_send_burst = m88rs2000_send_diseqc_burst, + .set_tone = m88rs2000_set_tone, + .set_voltage = m88rs2000_set_voltage, + + .set_frontend = m88rs2000_set_frontend, + .get_frontend = m88rs2000_get_frontend, +}; + +struct dvb_frontend *m88rs2000_attach(const struct m88rs2000_config *config, + struct i2c_adapter *i2c) +{ + struct m88rs2000_state *state = NULL; + + /* allocate memory for the internal state */ + state = kzalloc(sizeof(struct m88rs2000_state), GFP_KERNEL); + if (state == NULL) + goto error; + + /* setup the state */ + state->config = config; + state->i2c = i2c; + state->tuner_frequency = 0; + state->symbol_rate = 0; + state->fec_inner = 0; + + if (m88rs2000_startup(state) < 0) + goto error; + + /* create dvb_frontend */ + memcpy(&state->frontend.ops, &m88rs2000_ops, + sizeof(struct dvb_frontend_ops)); + state->frontend.demodulator_priv = state; + return &state->frontend; + +error: + kfree(state); + + return NULL; +} +EXPORT_SYMBOL(m88rs2000_attach); + +MODULE_DESCRIPTION("M88RS2000 DVB-S Demodulator driver"); +MODULE_AUTHOR("Malcolm Priestley tvboxspy@gmail.com"); +MODULE_LICENSE("GPL"); +MODULE_VERSION("1.12"); + diff --git a/drivers/media/dvb/frontends/m88rs2000.h b/drivers/media/dvb/frontends/m88rs2000.h new file mode 100644 index 000000000000..59acdb696873 --- /dev/null +++ b/drivers/media/dvb/frontends/m88rs2000.h @@ -0,0 +1,66 @@ +/* + Driver for M88RS2000 demodulator + + 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; either version 2 of the License, or + (at your option) any later version. + + 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. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#ifndef M88RS2000_H +#define M88RS2000_H + +#include +#include "dvb_frontend.h" + +struct m88rs2000_config { + /* Demodulator i2c address */ + u8 demod_addr; + /* Tuner address */ + u8 tuner_addr; + + u8 *inittab; + + /* minimum delay before retuning */ + int min_delay_ms; + + int (*set_ts_params)(struct dvb_frontend *, int); +}; + +enum { + CALL_IS_SET_FRONTEND = 0x0, + CALL_IS_READ, +}; + +#if defined(CONFIG_DVB_M88RS2000) || (defined(CONFIG_DVB_M88RS2000_MODULE) && \ + defined(MODULE)) +extern struct dvb_frontend *m88rs2000_attach( + const struct m88rs2000_config *config, struct i2c_adapter *i2c); +#else +static inline struct dvb_frontend *m88rs2000_attach( + const struct m88rs2000_config *config, struct i2c_adapter *i2c) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); + return NULL; +} +#endif /* CONFIG_DVB_M88RS2000 */ + +#define FE_CRYSTAL_KHZ 27000 +#define FREQ_OFFSET_LOW_SYM_RATE 3000 + +enum { + DEMOD_WRITE = 0x1, + TUNER_WRITE, + WRITE_DELAY = 0x10, +}; +#endif /* M88RS2000_H */ -- cgit v1.2.3 From 40841e7469172d60275ad1958f431453c42d836a Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 19 Mar 2012 14:53:48 -0300 Subject: [media] m88rs2000: Don't fill info.type This field is handled internally by the DVB core, with uses the selected delivery system to fill it, when a DVBv3 call is handled. So, drivers should not touch on it. Cc: Malcolm Priestley Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/m88rs2000.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/frontends/m88rs2000.c b/drivers/media/dvb/frontends/m88rs2000.c index c9a34358128b..b0f4b9fcb15d 100644 --- a/drivers/media/dvb/frontends/m88rs2000.c +++ b/drivers/media/dvb/frontends/m88rs2000.c @@ -833,7 +833,6 @@ static struct dvb_frontend_ops m88rs2000_ops = { .delsys = { SYS_DVBS }, .info = { .name = "M88RS2000 DVB-S", - .type = FE_QPSK, .frequency_min = 950000, .frequency_max = 2150000, .frequency_stepsize = 1000, /* kHz for QPSK frontends */ -- cgit v1.2.3 From 4f3b7fed467c23bbc99436d8e8b8e4bdb99a09e1 Mon Sep 17 00:00:00 2001 From: Malcolm Priestley Date: Wed, 7 Mar 2012 18:08:10 -0300 Subject: [media] lmedm04 ver 1.99 support for m88rs2000 v2 Support for m88rs2000 module. The driver also attempts to overcome occasional lock problems. Call backs are now used for read_status, signal level and SNR. Signed-off-by: Malcolm Priestley Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/lmedm04.c | 274 ++++++++++++++++++++++++++---------- drivers/media/dvb/dvb-usb/lmedm04.h | 1 + 2 files changed, 197 insertions(+), 78 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/dvb-usb/lmedm04.c b/drivers/media/dvb/dvb-usb/lmedm04.c index a251583fe292..5dde06d066ff 100644 --- a/drivers/media/dvb/dvb-usb/lmedm04.c +++ b/drivers/media/dvb/dvb-usb/lmedm04.c @@ -77,6 +77,7 @@ #include "stv0299.h" #include "dvb-pll.h" #include "z0194a.h" +#include "m88rs2000.h" @@ -106,12 +107,14 @@ static int pid_filter; module_param_named(pid, pid_filter, int, 0644); MODULE_PARM_DESC(pid, "set default 0=default 1=off 2=on"); + DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); #define TUNER_DEFAULT 0x0 #define TUNER_LG 0x1 #define TUNER_S7395 0x2 #define TUNER_S0194 0x3 +#define TUNER_RS2000 0x4 struct lme2510_state { u8 id; @@ -120,6 +123,8 @@ struct lme2510_state { u8 signal_level; u8 signal_sn; u8 time_key; + u8 last_key; + u8 key_timeout; u8 i2c_talk_onoff; u8 i2c_gate; u8 i2c_tuner_gate_w; @@ -127,6 +132,7 @@ struct lme2510_state { u8 i2c_tuner_addr; u8 stream_on; u8 pid_size; + u8 pid_off; void *buffer; struct urb *lme_urb; void *usb_buffer; @@ -192,9 +198,14 @@ static int lme2510_usb_talk(struct dvb_usb_device *d, static int lme2510_stream_restart(struct dvb_usb_device *d) { - static u8 stream_on[] = LME_ST_ON_W; + struct lme2510_state *st = d->priv; + u8 all_pids[] = LME_ALL_PIDS; + u8 stream_on[] = LME_ST_ON_W; int ret; - u8 rbuff[10]; + u8 rbuff[1]; + if (st->pid_off) + ret = lme2510_usb_talk(d, all_pids, sizeof(all_pids), + rbuff, sizeof(rbuff)); /*Restart Stream Command*/ ret = lme2510_usb_talk(d, stream_on, sizeof(stream_on), rbuff, sizeof(rbuff)); @@ -301,6 +312,14 @@ static void lme2510_int_response(struct urb *lme_urb) ((ibuf[2] & 0x01) << 0x03); } break; + case TUNER_RS2000: + if (ibuf[2] > 0) + st->signal_lock = 0xff; + else + st->signal_lock = 0xf0; + st->signal_level = ibuf[4]; + st->signal_sn = ibuf[5]; + st->time_key = ibuf[7]; default: break; } @@ -352,19 +371,20 @@ static int lme2510_int_read(struct dvb_usb_adapter *adap) static int lme2510_pid_filter_ctrl(struct dvb_usb_adapter *adap, int onoff) { struct lme2510_state *st = adap->dev->priv; - static u8 clear_pid_reg[] = LME_CLEAR_PID; + static u8 clear_pid_reg[] = LME_ALL_PIDS; static u8 rbuf[1]; int ret; deb_info(1, "PID Clearing Filter"); - ret = mutex_lock_interruptible(&adap->dev->i2c_mutex); - if (ret < 0) - return -EAGAIN; + mutex_lock(&adap->dev->i2c_mutex); - if (!onoff) + if (!onoff) { ret |= lme2510_usb_talk(adap->dev, clear_pid_reg, sizeof(clear_pid_reg), rbuf, sizeof(rbuf)); + st->pid_off = true; + } else + st->pid_off = false; st->pid_size = 0; @@ -382,11 +402,9 @@ static int lme2510_pid_filter(struct dvb_usb_adapter *adap, int index, u16 pid, pid, index, onoff); if (onoff) { - ret = mutex_lock_interruptible(&adap->dev->i2c_mutex); - if (ret < 0) - return -EAGAIN; - ret |= lme2510_enable_pid(adap->dev, index, pid); - mutex_unlock(&adap->dev->i2c_mutex); + mutex_lock(&adap->dev->i2c_mutex); + ret |= lme2510_enable_pid(adap->dev, index, pid); + mutex_unlock(&adap->dev->i2c_mutex); } @@ -418,9 +436,6 @@ static int lme2510_msg(struct dvb_usb_device *d, int ret = 0; struct lme2510_state *st = d->priv; - if (mutex_lock_interruptible(&d->i2c_mutex) < 0) - return -EAGAIN; - if (st->i2c_talk_onoff == 1) { ret = lme2510_usb_talk(d, wbuf, wlen, rbuf, rlen); @@ -463,10 +478,12 @@ static int lme2510_msg(struct dvb_usb_device *d, } } break; + case TUNER_RS2000: default: break; } } else { + /* TODO rewrite this section */ switch (st->tuner_config) { case TUNER_LG: switch (wbuf[3]) { @@ -550,6 +567,24 @@ static int lme2510_msg(struct dvb_usb_device *d, break; } break; + case TUNER_RS2000: + switch (wbuf[3]) { + case 0x8c: + rbuf[0] = 0x55; + rbuf[1] = 0xff; + if (st->last_key == st->time_key) { + st->key_timeout++; + if (st->key_timeout > 5) + rbuf[1] = 0; + } else + st->key_timeout = 0; + st->last_key = st->time_key; + break; + default: + lme2510_usb_talk(d, wbuf, wlen, rbuf, rlen); + st->i2c_talk_onoff = 1; + break; + } default: break; } @@ -559,8 +594,6 @@ static int lme2510_msg(struct dvb_usb_device *d, } - mutex_unlock(&d->i2c_mutex); - return ret; } @@ -575,6 +608,8 @@ static int lme2510_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], u16 len; u8 gate = st->i2c_gate; + mutex_lock(&d->i2c_mutex); + if (gate == 0) gate = 5; @@ -613,6 +648,7 @@ static int lme2510_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], if (lme2510_msg(d, obuf, len, ibuf, 64) < 0) { deb_info(1, "i2c transfer failed."); + mutex_unlock(&d->i2c_mutex); return -EAGAIN; } @@ -625,6 +661,8 @@ static int lme2510_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], } } } + + mutex_unlock(&d->i2c_mutex); return i; } @@ -654,7 +692,7 @@ static int lme2510_identify_state(struct usb_device *udev, static int lme2510_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) { struct lme2510_state *st = adap->dev->priv; - static u8 clear_reg_3[] = LME_CLEAR_PID; + static u8 clear_reg_3[] = LME_ALL_PIDS; static u8 rbuf[1]; int ret = 0, rlen = sizeof(rbuf); @@ -666,8 +704,7 @@ static int lme2510_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) else { deb_info(1, "STM Steam Off"); /* mutex is here only to avoid collision with I2C */ - if (mutex_lock_interruptible(&adap->dev->i2c_mutex) < 0) - return -EAGAIN; + mutex_lock(&adap->dev->i2c_mutex); ret = lme2510_usb_talk(adap->dev, clear_reg_3, sizeof(clear_reg_3), rbuf, rlen); @@ -772,16 +809,18 @@ static int lme_firmware_switch(struct usb_device *udev, int cold) const char fw_c_s7395[] = "dvb-usb-lme2510c-s7395.fw"; const char fw_c_lg[] = "dvb-usb-lme2510c-lg.fw"; const char fw_c_s0194[] = "dvb-usb-lme2510c-s0194.fw"; + const char fw_c_rs2000[] = "dvb-usb-lme2510c-rs2000.fw"; const char fw_lg[] = "dvb-usb-lme2510-lg.fw"; const char fw_s0194[] = "dvb-usb-lme2510-s0194.fw"; const char *fw_lme; - int ret, cold_fw; + int ret = 0, cold_fw; cold = (cold > 0) ? (cold & 1) : 0; cold_fw = !cold; - if (le16_to_cpu(udev->descriptor.idProduct) == 0x1122) { + switch (le16_to_cpu(udev->descriptor.idProduct)) { + case 0x1122: switch (dvb_usb_lme2510_firmware) { default: dvb_usb_lme2510_firmware = TUNER_S0194; @@ -804,7 +843,8 @@ static int lme_firmware_switch(struct usb_device *udev, int cold) cold_fw = 0; break; } - } else { + break; + case 0x1120: switch (dvb_usb_lme2510_firmware) { default: dvb_usb_lme2510_firmware = TUNER_S7395; @@ -833,8 +873,17 @@ static int lme_firmware_switch(struct usb_device *udev, int cold) cold_fw = 0; break; } + break; + case 0x22f0: + fw_lme = fw_c_rs2000; + ret = request_firmware(&fw, fw_lme, &udev->dev); + dvb_usb_lme2510_firmware = TUNER_RS2000; + break; + default: + fw_lme = fw_c_s7395; } + if (cold_fw) { info("FRM Loading %s file", fw_lme); ret = lme2510_download_firmware(udev, fw); @@ -897,6 +946,29 @@ static struct stv0299_config sharp_z0194_config = { .set_symbol_rate = sharp_z0194a_set_symbol_rate, }; +static int dm04_rs2000_set_ts_param(struct dvb_frontend *fe, + int caller) +{ + struct dvb_usb_adapter *adap = fe->dvb->priv; + struct dvb_usb_device *d = adap->dev; + struct lme2510_state *st = d->priv; + + mutex_lock(&d->i2c_mutex); + if ((st->i2c_talk_onoff == 1) && (st->stream_on & 1)) { + st->i2c_talk_onoff = 0; + lme2510_stream_restart(d); + } + mutex_unlock(&d->i2c_mutex); + + return 0; +} + +static struct m88rs2000_config m88rs2000_config = { + .demod_addr = 0xd0, + .tuner_addr = 0xc0, + .set_ts_params = dm04_rs2000_set_ts_param, +}; + static int dm04_lme2510_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) { @@ -906,8 +978,7 @@ static int dm04_lme2510_set_voltage(struct dvb_frontend *fe, static u8 rbuf[1]; int ret = 0, len = 3, rlen = 1; - if (mutex_lock_interruptible(&adap->dev->i2c_mutex) < 0) - return -EAGAIN; + mutex_lock(&adap->dev->i2c_mutex); switch (voltage) { case SEC_VOLTAGE_18: @@ -928,12 +999,31 @@ static int dm04_lme2510_set_voltage(struct dvb_frontend *fe, return (ret < 0) ? -ENODEV : 0; } +static int dm04_rs2000_read_signal_strength(struct dvb_frontend *fe, + u16 *strength) +{ + struct dvb_usb_adapter *adap = fe->dvb->priv; + struct lme2510_state *st = adap->dev->priv; + + *strength = (u16)((u32)st->signal_level * 0xffff / 0x7f); + return 0; +} + +static int dm04_rs2000_read_snr(struct dvb_frontend *fe, u16 *snr) +{ + struct dvb_usb_adapter *adap = fe->dvb->priv; + struct lme2510_state *st = adap->dev->priv; + + *snr = (u16)((u32)st->signal_sn * 0xffff / 0xff); + return 0; +} + static int lme_name(struct dvb_usb_adapter *adap) { struct lme2510_state *st = adap->dev->priv; const char *desc = adap->dev->desc->name; char *fe_name[] = {"", " LG TDQY-P001F", " SHARP:BS2F7HZ7395", - " SHARP:BS2F7HZ0194"}; + " SHARP:BS2F7HZ0194", " RS2000"}; char *name = adap->fe_adap[0].fe->ops.info.name; strlcpy(name, desc, 128); @@ -949,60 +1039,82 @@ static int dm04_lme2510_frontend_attach(struct dvb_usb_adapter *adap) int ret = 0; st->i2c_talk_onoff = 1; + switch (le16_to_cpu(adap->dev->udev->descriptor.idProduct)) { + case 0x1122: + case 0x1120: + st->i2c_gate = 4; + adap->fe_adap[0].fe = dvb_attach(tda10086_attach, + &tda10086_config, &adap->dev->i2c_adap); + if (adap->fe_adap[0].fe) { + info("TUN Found Frontend TDA10086"); + st->i2c_tuner_gate_w = 4; + st->i2c_tuner_gate_r = 4; + st->i2c_tuner_addr = 0xc0; + st->tuner_config = TUNER_LG; + if (dvb_usb_lme2510_firmware != TUNER_LG) { + dvb_usb_lme2510_firmware = TUNER_LG; + ret = lme_firmware_switch(adap->dev->udev, 1); + } + break; + } - st->i2c_gate = 4; - adap->fe_adap[0].fe = dvb_attach(tda10086_attach, &tda10086_config, - &adap->dev->i2c_adap); - - if (adap->fe_adap[0].fe) { - info("TUN Found Frontend TDA10086"); - st->i2c_tuner_gate_w = 4; - st->i2c_tuner_gate_r = 4; - st->i2c_tuner_addr = 0xc0; - st->tuner_config = TUNER_LG; - if (dvb_usb_lme2510_firmware != TUNER_LG) { - dvb_usb_lme2510_firmware = TUNER_LG; - ret = lme_firmware_switch(adap->dev->udev, 1); + st->i2c_gate = 4; + adap->fe_adap[0].fe = dvb_attach(stv0299_attach, + &sharp_z0194_config, &adap->dev->i2c_adap); + if (adap->fe_adap[0].fe) { + info("FE Found Stv0299"); + st->i2c_tuner_gate_w = 4; + st->i2c_tuner_gate_r = 5; + st->i2c_tuner_addr = 0xc0; + st->tuner_config = TUNER_S0194; + if (dvb_usb_lme2510_firmware != TUNER_S0194) { + dvb_usb_lme2510_firmware = TUNER_S0194; + ret = lme_firmware_switch(adap->dev->udev, 1); + } + break; } - goto end; - } - st->i2c_gate = 4; - adap->fe_adap[0].fe = dvb_attach(stv0299_attach, &sharp_z0194_config, + st->i2c_gate = 5; + adap->fe_adap[0].fe = dvb_attach(stv0288_attach, &lme_config, &adap->dev->i2c_adap); - if (adap->fe_adap[0].fe) { - info("FE Found Stv0299"); - st->i2c_tuner_gate_w = 4; - st->i2c_tuner_gate_r = 5; - st->i2c_tuner_addr = 0xc0; - st->tuner_config = TUNER_S0194; - if (dvb_usb_lme2510_firmware != TUNER_S0194) { - dvb_usb_lme2510_firmware = TUNER_S0194; - ret = lme_firmware_switch(adap->dev->udev, 1); + + if (adap->fe_adap[0].fe) { + info("FE Found Stv0288"); + st->i2c_tuner_gate_w = 4; + st->i2c_tuner_gate_r = 5; + st->i2c_tuner_addr = 0xc0; + st->tuner_config = TUNER_S7395; + if (dvb_usb_lme2510_firmware != TUNER_S7395) { + dvb_usb_lme2510_firmware = TUNER_S7395; + ret = lme_firmware_switch(adap->dev->udev, 1); + } + break; } - goto end; - } + case 0x22f0: + st->i2c_gate = 5; + adap->fe_adap[0].fe = dvb_attach(m88rs2000_attach, + &m88rs2000_config, &adap->dev->i2c_adap); - st->i2c_gate = 5; - adap->fe_adap[0].fe = dvb_attach(stv0288_attach, &lme_config, - &adap->dev->i2c_adap); - if (adap->fe_adap[0].fe) { - info("FE Found Stv0288"); - st->i2c_tuner_gate_w = 4; - st->i2c_tuner_gate_r = 5; - st->i2c_tuner_addr = 0xc0; - st->tuner_config = TUNER_S7395; - if (dvb_usb_lme2510_firmware != TUNER_S7395) { - dvb_usb_lme2510_firmware = TUNER_S7395; - ret = lme_firmware_switch(adap->dev->udev, 1); + if (adap->fe_adap[0].fe) { + info("FE Found M88RS2000"); + st->i2c_tuner_gate_w = 5; + st->i2c_tuner_gate_r = 5; + st->i2c_tuner_addr = 0xc0; + st->tuner_config = TUNER_RS2000; + adap->fe_adap[0].fe->ops.read_signal_strength = + dm04_rs2000_read_signal_strength; + adap->fe_adap[0].fe->ops.read_snr = + dm04_rs2000_read_snr; } - } else { - info("DM04 Not Supported"); - return -ENODEV; + break; } + if (adap->fe_adap[0].fe == NULL) { + info("DM04/QQBOX Not Powered up or not Supported"); + return -ENODEV; + } -end: if (ret) { + if (ret) { if (adap->fe_adap[0].fe) { dvb_frontend_detach(adap->fe_adap[0].fe); adap->fe_adap[0].fe = NULL; @@ -1019,7 +1131,7 @@ end: if (ret) { static int dm04_lme2510_tuner(struct dvb_usb_adapter *adap) { struct lme2510_state *st = adap->dev->priv; - char *tun_msg[] = {"", "TDA8263", "IX2505V", "DVB_PLL_OPERA"}; + char *tun_msg[] = {"", "TDA8263", "IX2505V", "DVB_PLL_OPERA", "RS2000"}; int ret = 0; switch (st->tuner_config) { @@ -1038,6 +1150,9 @@ static int dm04_lme2510_tuner(struct dvb_usb_adapter *adap) &adap->dev->i2c_adap, DVB_PLL_OPERA1)) ret = st->tuner_config; break; + case TUNER_RS2000: + ret = st->tuner_config; + break; default: break; } @@ -1066,10 +1181,9 @@ static int lme2510_powerup(struct dvb_usb_device *d, int onoff) static u8 lnb_on[] = LNB_ON; static u8 lnb_off[] = LNB_OFF; static u8 rbuf[1]; - int ret, len = 3, rlen = 1; + int ret = 0, len = 3, rlen = 1; - if (mutex_lock_interruptible(&d->i2c_mutex) < 0) - return -EAGAIN; + mutex_lock(&d->i2c_mutex); if (onoff) ret = lme2510_usb_talk(d, lnb_on, len, rbuf, rlen); @@ -1127,6 +1241,7 @@ static int lme2510_probe(struct usb_interface *intf, static struct usb_device_id lme2510_table[] = { { USB_DEVICE(0x3344, 0x1122) }, /* LME2510 */ { USB_DEVICE(0x3344, 0x1120) }, /* LME2510C */ + { USB_DEVICE(0x3344, 0x22f0) }, /* LME2510C RS2000 */ {} /* Terminating entry */ }; @@ -1144,7 +1259,7 @@ static struct dvb_usb_device_properties lme2510_properties = { DVB_USB_ADAP_NEED_PID_FILTERING| DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, .streaming_ctrl = lme2510_streaming_ctrl, - .pid_filter_count = 15, + .pid_filter_count = 32, .pid_filter = lme2510_pid_filter, .pid_filter_ctrl = lme2510_pid_filter_ctrl, .frontend_attach = dm04_lme2510_frontend_attach, @@ -1195,7 +1310,7 @@ static struct dvb_usb_device_properties lme2510c_properties = { DVB_USB_ADAP_NEED_PID_FILTERING| DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, .streaming_ctrl = lme2510_streaming_ctrl, - .pid_filter_count = 15, + .pid_filter_count = 32, .pid_filter = lme2510_pid_filter, .pid_filter_ctrl = lme2510_pid_filter_ctrl, .frontend_attach = dm04_lme2510_frontend_attach, @@ -1225,11 +1340,14 @@ static struct dvb_usb_device_properties lme2510c_properties = { .identify_state = lme2510_identify_state, .i2c_algo = &lme2510_i2c_algo, .generic_bulk_ctrl_endpoint = 0, - .num_device_descs = 1, + .num_device_descs = 2, .devices = { { "DM04_LME2510C_DVB-S", { &lme2510_table[1], NULL }, }, + { "DM04_LME2510C_DVB-S RS2000", + { &lme2510_table[2], NULL }, + }, } }; @@ -1286,5 +1404,5 @@ module_usb_driver(lme2510_driver); MODULE_AUTHOR("Malcolm Priestley "); MODULE_DESCRIPTION("LME2510(C) DVB-S USB2.0"); -MODULE_VERSION("1.98"); +MODULE_VERSION("1.99"); MODULE_LICENSE("GPL"); diff --git a/drivers/media/dvb/dvb-usb/lmedm04.h b/drivers/media/dvb/dvb-usb/lmedm04.h index ab21e2ef53fa..e9c207205c2f 100644 --- a/drivers/media/dvb/dvb-usb/lmedm04.h +++ b/drivers/media/dvb/dvb-usb/lmedm04.h @@ -41,6 +41,7 @@ #define LME_ST_ON_W {0x06, 0x00} #define LME_CLEAR_PID {0x03, 0x02, 0x20, 0xa0} #define LME_ZERO_PID {0x03, 0x06, 0x00, 0x00, 0x01, 0x00, 0x20, 0x9c} +#define LME_ALL_PIDS {0x03, 0x06, 0x00, 0xff, 0x01, 0x1f, 0x20, 0x81} /* LNB Voltage * 07 XX XX -- cgit v1.2.3 From 1d53160111d821d5d924e220f6b5b423f938d617 Mon Sep 17 00:00:00 2001 From: Malcolm Priestley Date: Thu, 8 Mar 2012 15:41:08 -0300 Subject: [media] lmedm04 - support for m88rs2000 missing kconfig option Signed-off-by: Malcolm Priestley Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/dvb-usb/Kconfig b/drivers/media/dvb/dvb-usb/Kconfig index 615429274516..63bf45679f98 100644 --- a/drivers/media/dvb/dvb-usb/Kconfig +++ b/drivers/media/dvb/dvb-usb/Kconfig @@ -386,6 +386,7 @@ config DVB_USB_LME2510 select DVB_IX2505V if !DVB_FE_CUSTOMISE select DVB_STV0299 if !DVB_FE_CUSTOMISE select DVB_PLL if !DVB_FE_CUSTOMISE + select DVB_M88RS2000 if !DVB_FE_CUSTOMISE help Say Y here to support the LME DM04/QQBOX DVB-S USB2.0 . -- cgit v1.2.3 From 847e87659620890bfc80ce7bf682f2a5354543b2 Mon Sep 17 00:00:00 2001 From: Akihiro Tsukada Date: Sat, 10 Mar 2012 11:38:13 -0300 Subject: [media] dvb: earth-pt1: stop polling data when no one accesses the device The driver started a kthread to poll the DMA buffers soon after probing, which relsuleted in 1000/sec sleeps and wakeups of the thread doing nothing useful until someone started feeding. This patch changes the creation and destruction of the kthread depending on the number of users. Signed-off-by: Akihiro Tsukada Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/pt1/pt1.c | 73 +++++++++++++++++++++++++++++++-------------- 1 file changed, 50 insertions(+), 23 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/pt1/pt1.c b/drivers/media/dvb/pt1/pt1.c index b81df5fafe26..463f7849c44c 100644 --- a/drivers/media/dvb/pt1/pt1.c +++ b/drivers/media/dvb/pt1/pt1.c @@ -77,6 +77,8 @@ struct pt1 { struct pt1_adapter *adaps[PT1_NR_ADAPS]; struct pt1_table *tables; struct task_struct *kthread; + int table_index; + int buf_index; struct mutex lock; int power; @@ -303,30 +305,25 @@ static int pt1_filter(struct pt1 *pt1, struct pt1_buffer_page *page) static int pt1_thread(void *data) { struct pt1 *pt1; - int table_index; - int buf_index; struct pt1_buffer_page *page; pt1 = data; set_freezable(); - table_index = 0; - buf_index = 0; - while (!kthread_should_stop()) { try_to_freeze(); - page = pt1->tables[table_index].bufs[buf_index].page; + page = pt1->tables[pt1->table_index].bufs[pt1->buf_index].page; if (!pt1_filter(pt1, page)) { schedule_timeout_interruptible((HZ + 999) / 1000); continue; } - if (++buf_index >= PT1_NR_BUFS) { + if (++pt1->buf_index >= PT1_NR_BUFS) { pt1_increment_table_count(pt1); - buf_index = 0; - if (++table_index >= pt1_nr_tables) - table_index = 0; + pt1->buf_index = 0; + if (++pt1->table_index >= pt1_nr_tables) + pt1->table_index = 0; } } @@ -477,21 +474,60 @@ err: return ret; } +static int pt1_start_polling(struct pt1 *pt1) +{ + int ret = 0; + + mutex_lock(&pt1->lock); + if (!pt1->kthread) { + pt1->kthread = kthread_run(pt1_thread, pt1, "earth-pt1"); + if (IS_ERR(pt1->kthread)) { + ret = PTR_ERR(pt1->kthread); + pt1->kthread = NULL; + } + } + mutex_unlock(&pt1->lock); + return ret; +} + static int pt1_start_feed(struct dvb_demux_feed *feed) { struct pt1_adapter *adap; adap = container_of(feed->demux, struct pt1_adapter, demux); - if (!adap->users++) + if (!adap->users++) { + int ret; + + ret = pt1_start_polling(adap->pt1); + if (ret) + return ret; pt1_set_stream(adap->pt1, adap->index, 1); + } return 0; } +static void pt1_stop_polling(struct pt1 *pt1) +{ + int i, count; + + mutex_lock(&pt1->lock); + for (i = 0, count = 0; i < PT1_NR_ADAPS; i++) + count += pt1->adaps[i]->users; + + if (count == 0 && pt1->kthread) { + kthread_stop(pt1->kthread); + pt1->kthread = NULL; + } + mutex_unlock(&pt1->lock); +} + static int pt1_stop_feed(struct dvb_demux_feed *feed) { struct pt1_adapter *adap; adap = container_of(feed->demux, struct pt1_adapter, demux); - if (!--adap->users) + if (!--adap->users) { pt1_set_stream(adap->pt1, adap->index, 0); + pt1_stop_polling(adap->pt1); + } return 0; } @@ -1020,7 +1056,8 @@ static void __devexit pt1_remove(struct pci_dev *pdev) pt1 = pci_get_drvdata(pdev); regs = pt1->regs; - kthread_stop(pt1->kthread); + if (pt1->kthread) + kthread_stop(pt1->kthread); pt1_cleanup_tables(pt1); pt1_cleanup_frontends(pt1); pt1_disable_ram(pt1); @@ -1043,7 +1080,6 @@ pt1_probe(struct pci_dev *pdev, const struct pci_device_id *ent) void __iomem *regs; struct pt1 *pt1; struct i2c_adapter *i2c_adap; - struct task_struct *kthread; ret = pci_enable_device(pdev); if (ret < 0) @@ -1139,17 +1175,8 @@ pt1_probe(struct pci_dev *pdev, const struct pci_device_id *ent) if (ret < 0) goto err_pt1_cleanup_frontends; - kthread = kthread_run(pt1_thread, pt1, "pt1"); - if (IS_ERR(kthread)) { - ret = PTR_ERR(kthread); - goto err_pt1_cleanup_tables; - } - - pt1->kthread = kthread; return 0; -err_pt1_cleanup_tables: - pt1_cleanup_tables(pt1); err_pt1_cleanup_frontends: pt1_cleanup_frontends(pt1); err_pt1_disable_ram: -- cgit v1.2.3 From 6988111098d643653eca04ebc6dabe9a7f354baa Mon Sep 17 00:00:00 2001 From: Akihiro Tsukada Date: Sat, 10 Mar 2012 11:38:14 -0300 Subject: [media] dvb: earth-pt1: add an error check/report on the incoming data This patch adds a data integrity check using the sequence counter and error flags added by the bridge chip. Signed-off-by: Akihiro Tsukada Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/pt1/pt1.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/pt1/pt1.c b/drivers/media/dvb/pt1/pt1.c index 463f7849c44c..8229a9150c5e 100644 --- a/drivers/media/dvb/pt1/pt1.c +++ b/drivers/media/dvb/pt1/pt1.c @@ -28,6 +28,7 @@ #include #include #include +#include #include "dvbdev.h" #include "dvb_demux.h" @@ -92,6 +93,7 @@ struct pt1_adapter { u8 *buf; int upacket_count; int packet_count; + int st_count; struct dvb_adapter adap; struct dvb_demux demux; @@ -266,6 +268,7 @@ static int pt1_filter(struct pt1 *pt1, struct pt1_buffer_page *page) struct pt1_adapter *adap; int offset; u8 *buf; + int sc; if (!page->upackets[PT1_NR_UPACKETS - 1]) return 0; @@ -282,6 +285,16 @@ static int pt1_filter(struct pt1 *pt1, struct pt1_buffer_page *page) else if (!adap->upacket_count) continue; + if (upacket >> 24 & 1) + printk_ratelimited(KERN_INFO "earth-pt1: device " + "buffer overflowing. table[%d] buf[%d]\n", + pt1->table_index, pt1->buf_index); + sc = upacket >> 26 & 0x7; + if (adap->st_count != -1 && sc != ((adap->st_count + 1) & 0x7)) + printk_ratelimited(KERN_INFO "earth-pt1: data loss" + " in streamID(adapter)[%d]\n", index); + adap->st_count = sc; + buf = adap->buf; offset = adap->packet_count * 188 + adap->upacket_count * 3; buf[offset] = upacket >> 16; @@ -652,6 +665,7 @@ pt1_alloc_adapter(struct pt1 *pt1) adap->buf = buf; adap->upacket_count = 0; adap->packet_count = 0; + adap->st_count = -1; dvb_adap = &adap->adap; dvb_adap->priv = adap; -- cgit v1.2.3 From 7ff04760f737ac9eb2a5f8fc12a762a608c37692 Mon Sep 17 00:00:00 2001 From: Akihiro Tsukada Date: Sat, 10 Mar 2012 11:38:15 -0300 Subject: [media] dvb: earth-pt1: decrease the too large DMA buffer size Current default value of "nr_tables" option corresponds to the DMA buffer of about 10 to 48 seconds long, which is obviously too much. Signed-off-by: Akihiro Tsukada Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/pt1/pt1.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/pt1/pt1.c b/drivers/media/dvb/pt1/pt1.c index 8229a9150c5e..9cd161c409ef 100644 --- a/drivers/media/dvb/pt1/pt1.c +++ b/drivers/media/dvb/pt1/pt1.c @@ -123,7 +123,7 @@ static u32 pt1_read_reg(struct pt1 *pt1, int reg) return readl(pt1->regs + reg * 4); } -static int pt1_nr_tables = 64; +static int pt1_nr_tables = 8; module_param_named(nr_tables, pt1_nr_tables, int, 0); static void pt1_increment_table_count(struct pt1 *pt1) -- cgit v1.2.3 From cd7334d6d6d2cfba7e34ad6605fec61b556bc822 Mon Sep 17 00:00:00 2001 From: Akihiro Tsukada Date: Sat, 10 Mar 2012 11:38:16 -0300 Subject: [media] dvb: earth-pt1: remove unsupported net subdevices PT1 and PT2 do not have net functions. Signed-off-by: Akihiro Tsukada Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/pt1/pt1.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/pt1/pt1.c b/drivers/media/dvb/pt1/pt1.c index 9cd161c409ef..15b35c4725f1 100644 --- a/drivers/media/dvb/pt1/pt1.c +++ b/drivers/media/dvb/pt1/pt1.c @@ -99,7 +99,6 @@ struct pt1_adapter { struct dvb_demux demux; int users; struct dmxdev dmxdev; - struct dvb_net net; struct dvb_frontend *fe; int (*orig_set_voltage)(struct dvb_frontend *fe, fe_sec_voltage_t voltage); @@ -624,7 +623,6 @@ static int pt1_wakeup(struct dvb_frontend *fe) static void pt1_free_adapter(struct pt1_adapter *adap) { - dvb_net_release(&adap->net); adap->demux.dmx.close(&adap->demux.dmx); dvb_dmxdev_release(&adap->dmxdev); dvb_dmx_release(&adap->demux); @@ -694,8 +692,6 @@ pt1_alloc_adapter(struct pt1 *pt1) if (ret < 0) goto err_dmx_release; - dvb_net_init(dvb_adap, &adap->net, &demux->dmx); - return adap; err_dmx_release: -- cgit v1.2.3 From ef3d2dc366c8c32d58dbbf9898cfd4f853ff8fe0 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Mon, 12 Mar 2012 17:07:22 -0300 Subject: [media] au8522: bug-fix: enable modulation AFTER tune (instead of before tuning) The au8522 driver programs the tuner after programming the demodulator, but the tuner should be programmed first. This patch fixes this behavior. EDIT: Apparantly Devin created a similar patch some time ago, but hasn't submitted it for merge. I never saw his patch, but I thank him anyhow for his efforts. In addition, Devin pointed out a flaw in my patch: This newly generated patch takes Devin's comments into account. Thanks-to: Devin Heitmueller Signed-off-by: Michael Krufky Cc: stable@kernel.org Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/au8522_dig.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/frontends/au8522_dig.c b/drivers/media/dvb/frontends/au8522_dig.c index c688b95df486..25f650934c73 100644 --- a/drivers/media/dvb/frontends/au8522_dig.c +++ b/drivers/media/dvb/frontends/au8522_dig.c @@ -588,11 +588,6 @@ static int au8522_set_frontend(struct dvb_frontend *fe) (state->current_modulation == c->modulation)) return 0; - au8522_enable_modulation(fe, c->modulation); - - /* Allow the demod to settle */ - msleep(100); - if (fe->ops.tuner_ops.set_params) { if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 1); @@ -604,6 +599,11 @@ static int au8522_set_frontend(struct dvb_frontend *fe) if (ret < 0) return ret; + /* Allow the tuner to settle */ + msleep(100); + + au8522_enable_modulation(fe, c->modulation); + state->current_frequency = c->frequency; return 0; -- cgit v1.2.3 From 3ef76759484832e498cba381aa1b24b90cf36a26 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Tue, 13 Mar 2012 13:50:37 -0300 Subject: [media] dib0700: Drop useless check when remote key is pressed struct dvb_usb_device *d can never be NULL so don't waste time checking for this. Rationale: the urb's context is set when usb_fill_bulk_urb() is called in dib0700_rc_setup(), and never changes after that. d is dereferenced unconditionally in dib0700_rc_setup() so it can't be NULL or the driver would crash right away. Signed-off-by: Jean Delvare Cc: Mauro Carvalho Chehab Cc: Devin Heitmueller Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/dib0700_core.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/dvb-usb/dib0700_core.c b/drivers/media/dvb/dvb-usb/dib0700_core.c index 070e82aa53f5..ae4f999930fa 100644 --- a/drivers/media/dvb/dvb-usb/dib0700_core.c +++ b/drivers/media/dvb/dvb-usb/dib0700_core.c @@ -677,9 +677,6 @@ static void dib0700_rc_urb_completion(struct urb *purb) u8 toggle; deb_info("%s()\n", __func__); - if (d == NULL) - return; - if (d->rc_dev == NULL) { /* This will occur if disable_rc_polling=1 */ usb_free_urb(purb); -- cgit v1.2.3 From d3db22e10bd4997d244beee6feea5fa39b2e5b82 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Tue, 13 Mar 2012 13:52:50 -0300 Subject: [media] dib0700: Fix memory leak during initialization Reported by kmemleak. Signed-off-by: Jean Delvare Cc: Mauro Carvalho Chehab Cc: Devin Heitmueller Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/dib0700_core.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/dvb-usb/dib0700_core.c b/drivers/media/dvb/dvb-usb/dib0700_core.c index ae4f999930fa..02290c60f72f 100644 --- a/drivers/media/dvb/dvb-usb/dib0700_core.c +++ b/drivers/media/dvb/dvb-usb/dib0700_core.c @@ -679,6 +679,7 @@ static void dib0700_rc_urb_completion(struct urb *purb) deb_info("%s()\n", __func__); if (d->rc_dev == NULL) { /* This will occur if disable_rc_polling=1 */ + kfree(purb->transfer_buffer); usb_free_urb(purb); return; } @@ -687,6 +688,7 @@ static void dib0700_rc_urb_completion(struct urb *purb) if (purb->status < 0) { deb_info("discontinuing polling\n"); + kfree(purb->transfer_buffer); usb_free_urb(purb); return; } @@ -781,8 +783,11 @@ int dib0700_rc_setup(struct dvb_usb_device *d) dib0700_rc_urb_completion, d); ret = usb_submit_urb(purb, GFP_ATOMIC); - if (ret) + if (ret) { err("rc submit urb failed\n"); + kfree(purb->transfer_buffer); + usb_free_urb(purb); + } return ret; } -- cgit v1.2.3 From be4a5e7f0e279b751a23570da583ec41ca32a34f Mon Sep 17 00:00:00 2001 From: Gordon Hecker Date: Wed, 14 Mar 2012 10:27:30 -0300 Subject: [media] af9015: fix i2c failures for dual-tuner devices The i2c failures were caused by enabling both i2c gates at the same time while putting the tuners asleep. This patch removes the init() and sleep() callbacks from the tuner, to prevent frontend.c from calling i2c_gate_ctrl tuner init / sleep i2c_gate_ctrl without holding the lock. tuner init() and sleep() are instead called in frontend init() and sleep(). Signed-off-by: Gordon Hecker Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/af9015.c | 31 +++++++++++++++++++++++++++++++ drivers/media/dvb/dvb-usb/af9015.h | 2 ++ 2 files changed, 33 insertions(+) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/dvb-usb/af9015.c b/drivers/media/dvb/dvb-usb/af9015.c index 282a43d648df..9307b4ca4b77 100644 --- a/drivers/media/dvb/dvb-usb/af9015.c +++ b/drivers/media/dvb/dvb-usb/af9015.c @@ -1141,7 +1141,18 @@ static int af9015_af9013_init(struct dvb_frontend *fe) return -EAGAIN; ret = priv->init[adap->id](fe); + if (ret) + goto err_unlock; + + if (priv->tuner_ops_init[adap->id]) { + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + ret = priv->tuner_ops_init[adap->id](fe); + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); + } +err_unlock: mutex_unlock(&adap->dev->usb_mutex); return ret; @@ -1157,8 +1168,19 @@ static int af9015_af9013_sleep(struct dvb_frontend *fe) if (mutex_lock_interruptible(&adap->dev->usb_mutex)) return -EAGAIN; + if (priv->tuner_ops_sleep[adap->id]) { + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + ret = priv->tuner_ops_sleep[adap->id](fe); + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); + if (ret) + goto err_unlock; + } + ret = priv->sleep[adap->id](fe); +err_unlock: mutex_unlock(&adap->dev->usb_mutex); return ret; @@ -1283,6 +1305,7 @@ static struct mxl5007t_config af9015_mxl5007t_config = { static int af9015_tuner_attach(struct dvb_usb_adapter *adap) { int ret; + struct af9015_state *state = adap->dev->priv; deb_info("%s:\n", __func__); switch (af9015_af9013_config[adap->id].tuner) { @@ -1340,6 +1363,14 @@ static int af9015_tuner_attach(struct dvb_usb_adapter *adap) err("Unknown tuner id:%d", af9015_af9013_config[adap->id].tuner); } + + state->tuner_ops_sleep[adap->id] = + adap->fe_adap[0].fe->ops.tuner_ops.sleep; + adap->fe_adap[0].fe->ops.tuner_ops.sleep = 0; + + state->tuner_ops_init[adap->id] = + adap->fe_adap[0].fe->ops.tuner_ops.init; + adap->fe_adap[0].fe->ops.tuner_ops.init = 0; return ret; } diff --git a/drivers/media/dvb/dvb-usb/af9015.h b/drivers/media/dvb/dvb-usb/af9015.h index f619063fa72f..ee2ec5b8d570 100644 --- a/drivers/media/dvb/dvb-usb/af9015.h +++ b/drivers/media/dvb/dvb-usb/af9015.h @@ -108,6 +108,8 @@ struct af9015_state { int (*read_status[2]) (struct dvb_frontend *fe, fe_status_t *status); int (*init[2]) (struct dvb_frontend *fe); int (*sleep[2]) (struct dvb_frontend *fe); + int (*tuner_ops_init[2]) (struct dvb_frontend *fe); + int (*tuner_ops_sleep[2]) (struct dvb_frontend *fe); }; struct af9015_config { -- cgit v1.2.3 From 6d535bd8829b18c6b5276d65f8f25e57dd0bcbed Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Wed, 14 Mar 2012 10:27:31 -0300 Subject: [media] af9015: fix i2c failures for dual-tuner devices - part 2 Some changes for previous patch I liked to do. Just move tuner init and sleep to own functions from the demod init and sleep functions. Functionality remains still almost the same. Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/af9015.c | 74 +++++++++++++++++++++++--------------- drivers/media/dvb/dvb-usb/af9015.h | 4 +-- 2 files changed, 48 insertions(+), 30 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/dvb-usb/af9015.c b/drivers/media/dvb/dvb-usb/af9015.c index 9307b4ca4b77..7e70ea50ef26 100644 --- a/drivers/media/dvb/dvb-usb/af9015.c +++ b/drivers/media/dvb/dvb-usb/af9015.c @@ -1141,18 +1141,7 @@ static int af9015_af9013_init(struct dvb_frontend *fe) return -EAGAIN; ret = priv->init[adap->id](fe); - if (ret) - goto err_unlock; - - if (priv->tuner_ops_init[adap->id]) { - if (fe->ops.i2c_gate_ctrl) - fe->ops.i2c_gate_ctrl(fe, 1); - ret = priv->tuner_ops_init[adap->id](fe); - if (fe->ops.i2c_gate_ctrl) - fe->ops.i2c_gate_ctrl(fe, 0); - } -err_unlock: mutex_unlock(&adap->dev->usb_mutex); return ret; @@ -1168,24 +1157,48 @@ static int af9015_af9013_sleep(struct dvb_frontend *fe) if (mutex_lock_interruptible(&adap->dev->usb_mutex)) return -EAGAIN; - if (priv->tuner_ops_sleep[adap->id]) { - if (fe->ops.i2c_gate_ctrl) - fe->ops.i2c_gate_ctrl(fe, 1); - ret = priv->tuner_ops_sleep[adap->id](fe); - if (fe->ops.i2c_gate_ctrl) - fe->ops.i2c_gate_ctrl(fe, 0); - if (ret) - goto err_unlock; - } - ret = priv->sleep[adap->id](fe); -err_unlock: mutex_unlock(&adap->dev->usb_mutex); return ret; } +/* override tuner callbacks for resource locking */ +static int af9015_tuner_init(struct dvb_frontend *fe) +{ + int ret; + struct dvb_usb_adapter *adap = fe->dvb->priv; + struct af9015_state *priv = adap->dev->priv; + + if (mutex_lock_interruptible(&adap->dev->usb_mutex)) + return -EAGAIN; + + ret = priv->tuner_init[adap->id](fe); + + mutex_unlock(&adap->dev->usb_mutex); + + return ret; +} + +/* override tuner callbacks for resource locking */ +static int af9015_tuner_sleep(struct dvb_frontend *fe) +{ + int ret; + struct dvb_usb_adapter *adap = fe->dvb->priv; + struct af9015_state *priv = adap->dev->priv; + + if (mutex_lock_interruptible(&adap->dev->usb_mutex)) + return -EAGAIN; + + ret = priv->tuner_sleep[adap->id](fe); + + mutex_unlock(&adap->dev->usb_mutex); + + return ret; +} + + static int af9015_af9013_frontend_attach(struct dvb_usb_adapter *adap) { int ret; @@ -1364,13 +1377,18 @@ static int af9015_tuner_attach(struct dvb_usb_adapter *adap) af9015_af9013_config[adap->id].tuner); } - state->tuner_ops_sleep[adap->id] = - adap->fe_adap[0].fe->ops.tuner_ops.sleep; - adap->fe_adap[0].fe->ops.tuner_ops.sleep = 0; + if (adap->fe_adap[0].fe->ops.tuner_ops.init) { + state->tuner_init[adap->id] = + adap->fe_adap[0].fe->ops.tuner_ops.init; + adap->fe_adap[0].fe->ops.tuner_ops.init = af9015_tuner_init; + } + + if (adap->fe_adap[0].fe->ops.tuner_ops.sleep) { + state->tuner_sleep[adap->id] = + adap->fe_adap[0].fe->ops.tuner_ops.sleep; + adap->fe_adap[0].fe->ops.tuner_ops.sleep = af9015_tuner_sleep; + } - state->tuner_ops_init[adap->id] = - adap->fe_adap[0].fe->ops.tuner_ops.init; - adap->fe_adap[0].fe->ops.tuner_ops.init = 0; return ret; } diff --git a/drivers/media/dvb/dvb-usb/af9015.h b/drivers/media/dvb/dvb-usb/af9015.h index ee2ec5b8d570..2f68419e899b 100644 --- a/drivers/media/dvb/dvb-usb/af9015.h +++ b/drivers/media/dvb/dvb-usb/af9015.h @@ -108,8 +108,8 @@ struct af9015_state { int (*read_status[2]) (struct dvb_frontend *fe, fe_status_t *status); int (*init[2]) (struct dvb_frontend *fe); int (*sleep[2]) (struct dvb_frontend *fe); - int (*tuner_ops_init[2]) (struct dvb_frontend *fe); - int (*tuner_ops_sleep[2]) (struct dvb_frontend *fe); + int (*tuner_init[2]) (struct dvb_frontend *fe); + int (*tuner_sleep[2]) (struct dvb_frontend *fe); }; struct af9015_config { -- cgit v1.2.3 From 593a2ce0ae22188538d27933236a6acab57a0e65 Mon Sep 17 00:00:00 2001 From: Malcolm Priestley Date: Wed, 14 Mar 2012 16:31:26 -0300 Subject: [media] m88rs2000 ver 1.13 Correct deseqc and tuner gain functions Remove incorrect SEC_MINI_B settings-TODO complete this section. Correct break and remove return -EINVAL within set tone. It appears there is a bug that occasionally something other than ON/OFF is sent stalling the driver. Just continue and write back registers. Set register b2 in setup. This is the set voltage pin which isn't used in lmedm04 driver but it is always set to 0x1. Correct the if statements in set_tuner_rf. Signed-off-by: Malcolm Priestley Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/m88rs2000.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/frontends/m88rs2000.c b/drivers/media/dvb/frontends/m88rs2000.c index b0f4b9fcb15d..045ee5a6f7ae 100644 --- a/drivers/media/dvb/frontends/m88rs2000.c +++ b/drivers/media/dvb/frontends/m88rs2000.c @@ -228,8 +228,7 @@ static int m88rs2000_send_diseqc_burst(struct dvb_frontend *fe, msleep(50); reg0 = m88rs2000_demod_read(state, 0xb1); reg1 = m88rs2000_demod_read(state, 0xb2); - if (burst == SEC_MINI_B) - reg1 |= 0x1; + /* TODO complete this section */ m88rs2000_demod_write(state, 0xb2, reg1); m88rs2000_demod_write(state, 0xb1, reg0); m88rs2000_demod_write(state, 0x9a, 0xb0); @@ -251,13 +250,12 @@ static int m88rs2000_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone) case SEC_TONE_ON: reg0 |= 0x4; reg0 &= 0xbc; - break; + break; case SEC_TONE_OFF: reg1 |= 0x80; - break; - + break; default: - return -EINVAL; + break; } m88rs2000_demod_write(state, 0xb2, reg1); m88rs2000_demod_write(state, 0xb1, reg0); @@ -292,6 +290,7 @@ struct inittab m88rs2000_setup[] = { {DEMOD_WRITE, 0xf0, 0x22}, {DEMOD_WRITE, 0xf1, 0xbf}, {DEMOD_WRITE, 0xb0, 0x45}, + {DEMOD_WRITE, 0xb2, 0x01}, /* set voltage pin always set 1*/ {DEMOD_WRITE, 0x9a, 0xb0}, {0xff, 0xaa, 0xff} }; @@ -520,9 +519,9 @@ static int m88rs2000_set_tuner_rf(struct dvb_frontend *fe) int reg; reg = m88rs2000_tuner_read(state, 0x3d); reg &= 0x7f; - if (reg < 0x17) + if (reg < 0x16) reg = 0xa1; - else if (reg < 0x16) + else if (reg == 0x16) reg = 0x99; else reg = 0xf9; @@ -901,5 +900,5 @@ EXPORT_SYMBOL(m88rs2000_attach); MODULE_DESCRIPTION("M88RS2000 DVB-S Demodulator driver"); MODULE_AUTHOR("Malcolm Priestley tvboxspy@gmail.com"); MODULE_LICENSE("GPL"); -MODULE_VERSION("1.12"); +MODULE_VERSION("1.13"); -- cgit v1.2.3 From 3be5bb71fbf18f83cb88b54a62a78e03e5a4f30a Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sun, 18 Mar 2012 14:35:57 -0300 Subject: [media] mxl111sf: fix error on stream stop in mxl111sf_ep6_streaming_ctrl() Remove unnecessary register access in mxl111sf_ep6_streaming_ctrl() This code breaks driver operation in kernel 3.3 and later, although it works properly in 3.2 Disable register access to 0x12 for now. Signed-off-by: Michael Krufky Cc: stable@kernel.org Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/mxl111sf.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/dvb-usb/mxl111sf.c b/drivers/media/dvb/dvb-usb/mxl111sf.c index 38ef0253d3b5..81305de2fea5 100644 --- a/drivers/media/dvb/dvb-usb/mxl111sf.c +++ b/drivers/media/dvb/dvb-usb/mxl111sf.c @@ -351,15 +351,13 @@ static int mxl111sf_ep6_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) adap_state->ep6_clockphase, 0, 0); mxl_fail(ret); +#if 0 } else { ret = mxl111sf_disable_656_port(state); mxl_fail(ret); +#endif } - mxl111sf_read_reg(state, 0x12, &tmp); - tmp &= ~0x04; - mxl111sf_write_reg(state, 0x12, tmp); - return ret; } -- cgit v1.2.3 From 0e377819b99bf2290c94a0eec2be4443b4630ccd Mon Sep 17 00:00:00 2001 From: Klaus Schmidinger Date: Tue, 24 Jan 2012 05:33:53 -0300 Subject: [media] stb0899: fix the limits for signal strength values stb0899: fix the limits for signal strength values stb0899_read_signal_strength() adds an offset to the result of the table lookup. That offset must correspond to the lowest value in the lookup table, to make sure the result doesn't get below 0, which would mean a "very high" value since the parameter is unsigned. 'strength' and 'snr' need to be initialized to 0 to make sure they have a defined result in case there is no "internal->lock". Signed-off-by: Klaus Schmidinger Cc: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/stb0899_drv.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/frontends/stb0899_drv.c b/drivers/media/dvb/frontends/stb0899_drv.c index 097e7067f208..dd08f4ac64a8 100644 --- a/drivers/media/dvb/frontends/stb0899_drv.c +++ b/drivers/media/dvb/frontends/stb0899_drv.c @@ -67,7 +67,7 @@ static const struct stb0899_tab stb0899_cn_tab[] = { * Crude linear extrapolation below -84.8dBm and above -8.0dBm. */ static const struct stb0899_tab stb0899_dvbsrf_tab[] = { - { -950, -128 }, + { -750, -128 }, { -748, -94 }, { -745, -92 }, { -735, -90 }, @@ -131,7 +131,7 @@ static const struct stb0899_tab stb0899_dvbs2rf_tab[] = { { -730, 13645 }, { -750, 13909 }, { -766, 14153 }, - { -999, 16383 } + { -950, 16383 } }; /* DVB-S2 Es/N0 quant in dB/100 vs read value * 100*/ @@ -964,6 +964,7 @@ static int stb0899_read_signal_strength(struct dvb_frontend *fe, u16 *strength) int val; u32 reg; + *strength = 0; switch (state->delsys) { case SYS_DVBS: case SYS_DSS: @@ -987,7 +988,7 @@ static int stb0899_read_signal_strength(struct dvb_frontend *fe, u16 *strength) val = STB0899_GETFIELD(IF_AGC_GAIN, reg); *strength = stb0899_table_lookup(stb0899_dvbs2rf_tab, ARRAY_SIZE(stb0899_dvbs2rf_tab) - 1, val); - *strength += 750; + *strength += 950; dprintk(state->verbose, FE_DEBUG, 1, "IF_AGC_GAIN = 0x%04x, C = %d * 0.1 dBm", val & 0x3fff, *strength); } @@ -1009,6 +1010,7 @@ static int stb0899_read_snr(struct dvb_frontend *fe, u16 *snr) u8 buf[2]; u32 reg; + *snr = 0; reg = stb0899_read_reg(state, STB0899_VSTATUS); switch (state->delsys) { case SYS_DVBS: -- cgit v1.2.3