Commit b7571f8d authored by Patrick Boettcher's avatar Patrick Boettcher Committed by Mauro Carvalho Chehab

V4L/DVB: Complete rewrite of the DiB3000mc-driver

A complete rewrite of the DiB3000MC/P driver has been done. It is now much more
easy to maintain and to get improvements inside.

Additionally the tuning time has been reduced and the usage of the driver is
much more understandable now.
Signed-off-by: default avatarPatrick Boettcher <pboettcher@dibcom.fr>
Signed-off-by: default avatarFrancois KANOUNNIKOFF <fkanounnikoff@dibcom.fr>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@infradead.org>
parent 74340b0a
...@@ -131,9 +131,6 @@ static int dibusb_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num ...@@ -131,9 +131,6 @@ static int dibusb_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num
if (mutex_lock_interruptible(&d->i2c_mutex) < 0) if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
return -EAGAIN; return -EAGAIN;
if (num > 2)
warn("more than 2 i2c messages at a time is not handled yet. TODO.");
for (i = 0; i < num; i++) { for (i = 0; i < num; i++) {
/* write/read request */ /* write/read request */
if (i+1 < num && (msg[i+1].flags & I2C_M_RD)) { if (i+1 < num && (msg[i+1].flags & I2C_M_RD)) {
...@@ -168,31 +165,137 @@ int dibusb_read_eeprom_byte(struct dvb_usb_device *d, u8 offs, u8 *val) ...@@ -168,31 +165,137 @@ int dibusb_read_eeprom_byte(struct dvb_usb_device *d, u8 offs, u8 *val)
} }
EXPORT_SYMBOL(dibusb_read_eeprom_byte); EXPORT_SYMBOL(dibusb_read_eeprom_byte);
static const struct dib3000p_agc_config dib3000p_agc_panasonic_env57h1xd5 = { /* 3000MC/P stuff */
{ 0x51, 0x301d, 0x0, 0x1cc7, 0xdc29, 0x570a, // Config Adjacent channels Perf -cal22
0xbae1, 0x8ccd, 0x3b6d, 0x551d, 0xa, 0x951e } static struct dibx000_agc_config dib3000p_mt2060_agc_config = {
.band_caps = BAND_VHF | BAND_UHF,
.setup = (0 << 15) | (0 << 14) | (1 << 13) | (1 << 12) | (29 << 0),
.agc1_max = 48497,
.agc1_min = 23593,
.agc2_max = 46531,
.agc2_min = 24904,
.agc1_pt1 = 0x65,
.agc1_pt2 = 0x69,
.agc1_slope1 = 0x51,
.agc1_slope2 = 0x27,
.agc2_pt1 = 0,
.agc2_pt2 = 0x33,
.agc2_slope1 = 0x35,
.agc2_slope2 = 0x37,
}; };
static const struct dib3000p_agc_config dib3000p_agc_microtune_mt2060 = { static struct dib3000mc_config stk3000p_dib3000p_config = {
{ 0x196, 0x301d, 0x0, 0x1cc7, 0xffff, 0x5c29, &dib3000p_mt2060_agc_config,
0xa8f6, 0x5eb8, 0x65ff, 0x40ff, 0x8a, 0x1114 }
.max_time = 0x196,
.ln_adc_level = 0x1cc7,
.output_mpeg2_in_188_bytes = 1,
}; };
static struct mt2060_config stk3000p_mt2060_config = { static struct dibx000_agc_config dib3000p_panasonic_agc_config = {
.i2c_address = 0x60, .setup = (0 << 15) | (0 << 14) | (1 << 13) | (1 << 12) | (29 << 0),
.agc1_max = 56361,
.agc1_min = 22282,
.agc2_max = 43254,
.agc2_min = 36045,
.agc1_pt1 = 0x65,
.agc1_pt2 = 0xff,
.agc1_slope1 = 0x40,
.agc1_slope2 = 0xff,
.agc2_pt1 = 0,
.agc2_pt2 = 0x8a,
.agc2_slope1 = 0x11,
.agc2_slope2 = 0x14,
};
static struct dib3000mc_config mod3000p_dib3000p_config = {
&dib3000p_panasonic_agc_config,
.max_time = 0x51,
.ln_adc_level = 0x1cc7,
.output_mpeg2_in_188_bytes = 1,
}; };
int dibusb_dib3000mc_frontend_attach(struct dvb_usb_device *d) int dibusb_dib3000mc_frontend_attach(struct dvb_usb_device *d)
{ {
struct dib3000_config demod_cfg; if (dib3000mc_attach(&d->i2c_adap, 1, DEFAULT_DIB3000P_I2C_ADDRESS, 0, &mod3000p_dib3000p_config, &d->fe) == 0) {
if (d->priv != NULL) {
struct dibusb_state *st = d->priv; struct dibusb_state *st = d->priv;
st->ops.pid_parse = dib3000mc_pid_parse;
st->ops.pid_ctrl = dib3000mc_pid_control;
}
return 0;
}
return -ENODEV; return -ENODEV;
} }
EXPORT_SYMBOL(dibusb_dib3000mc_frontend_attach); EXPORT_SYMBOL(dibusb_dib3000mc_frontend_attach);
static struct mt2060_config stk3000p_mt2060_config = {
0x60
};
int dibusb_dib3000mc_tuner_attach (struct dvb_usb_device *d) int dibusb_dib3000mc_tuner_attach (struct dvb_usb_device *d)
{ {
return -ENODEV; struct dibusb_state *st = d->priv;
int ret;
u8 a,b;
u16 if1 = 1220;
struct i2c_adapter *tun_i2c;
// First IF calibration for Liteon Sticks
if (d->udev->descriptor.idVendor == USB_VID_LITEON &&
d->udev->descriptor.idProduct == USB_PID_LITEON_DVB_T_WARM) {
dibusb_read_eeprom_byte(d,0x7E,&a);
dibusb_read_eeprom_byte(d,0x7F,&b);
if (a == 0x00)
if1 += b;
else if (a == 0x80)
if1 -= b;
else
warn("LITE-ON DVB-T: Strange IF1 calibration :%2X %2X\n", a, b);
} else if (d->udev->descriptor.idVendor == USB_VID_DIBCOM &&
d->udev->descriptor.idProduct == USB_PID_DIBCOM_MOD3001_WARM) {
u8 desc;
dibusb_read_eeprom_byte(d, 7, &desc);
if (desc == 2) {
a = 127;
do {
dibusb_read_eeprom_byte(d, a, &desc);
a--;
} while (a > 7 && (desc == 0xff || desc == 0x00));
if (desc & 0x80)
if1 -= (0xff - desc);
else
if1 += desc;
}
}
tun_i2c = dib3000mc_get_tuner_i2c_master(d->fe, 1);
if ((ret = mt2060_attach(d->fe, tun_i2c, &stk3000p_mt2060_config, if1)) != 0) {
/* not found - use panasonic pll parameters */
if (dvb_pll_attach(d->fe, 0x60, tun_i2c, &dvb_pll_env57h1xd5) == NULL)
return -ENOMEM;
} else {
st->mt2060_present = 1;
/* set the correct parameters for the dib3000p */
dib3000mc_set_config(d->fe, &stk3000p_dib3000p_config);
}
return 0;
} }
EXPORT_SYMBOL(dibusb_dib3000mc_tuner_attach); EXPORT_SYMBOL(dibusb_dib3000mc_tuner_attach);
......
...@@ -20,11 +20,12 @@ static int dibusb_dib3000mb_frontend_attach(struct dvb_usb_device *d) ...@@ -20,11 +20,12 @@ static int dibusb_dib3000mb_frontend_attach(struct dvb_usb_device *d)
struct dibusb_state *st = d->priv; struct dibusb_state *st = d->priv;
demod_cfg.demod_address = 0x8; demod_cfg.demod_address = 0x8;
demod_cfg.pll_set = dvb_usb_pll_set_i2c;
demod_cfg.pll_init = dvb_usb_pll_init_i2c;
if ((d->fe = dib3000mb_attach(&demod_cfg,&d->i2c_adap,&st->ops)) == NULL) if ((d->fe = dib3000mb_attach(&demod_cfg,&d->i2c_adap,&st->ops)) == NULL) {
d->fe->ops.tuner_ops.init = dvb_usb_tuner_init_i2c;
d->fe->ops.tuner_ops.set_params = dvb_usb_tuner_set_params_i2c;
return -ENODEV; return -ENODEV;
}
d->tuner_pass_ctrl = st->ops.tuner_pass_ctrl; d->tuner_pass_ctrl = st->ops.tuner_pass_ctrl;
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include "dvb-usb.h" #include "dvb-usb.h"
#include "dib3000.h" #include "dib3000.h"
#include "dib3000mc.h"
#include "mt2060.h" #include "mt2060.h"
/* /*
......
...@@ -179,16 +179,15 @@ int dvb_usb_fe_init(struct dvb_usb_device* d) ...@@ -179,16 +179,15 @@ int dvb_usb_fe_init(struct dvb_usb_device* d)
return 0; return 0;
} }
d->props.frontend_attach(d);
/* re-assign sleep and wakeup functions */ /* re-assign sleep and wakeup functions */
if (d->fe != NULL) { if (d->props.frontend_attach(d) == 0 && d->fe != NULL) {
d->fe_init = d->fe->ops.init; d->fe->ops.init = dvb_usb_fe_wakeup; d->fe_init = d->fe->ops.init; d->fe->ops.init = dvb_usb_fe_wakeup;
d->fe_sleep = d->fe->ops.sleep; d->fe->ops.sleep = dvb_usb_fe_sleep; d->fe_sleep = d->fe->ops.sleep; d->fe->ops.sleep = dvb_usb_fe_sleep;
if (dvb_register_frontend(&d->dvb_adap, d->fe)) { if (dvb_register_frontend(&d->dvb_adap, d->fe)) {
err("Frontend registration failed."); err("Frontend registration failed.");
dvb_frontend_detach(d->fe); if (d->fe->ops.release)
d->fe->ops.release(d->fe);
d->fe = NULL; d->fe = NULL;
return -ENODEV; return -ENODEV;
} }
...@@ -203,9 +202,7 @@ int dvb_usb_fe_init(struct dvb_usb_device* d) ...@@ -203,9 +202,7 @@ int dvb_usb_fe_init(struct dvb_usb_device* d)
int dvb_usb_fe_exit(struct dvb_usb_device *d) int dvb_usb_fe_exit(struct dvb_usb_device *d)
{ {
if (d->fe != NULL) { if (d->fe != NULL)
dvb_unregister_frontend(d->fe); dvb_unregister_frontend(d->fe);
dvb_frontend_detach(d->fe);
}
return 0; return 0;
} }
...@@ -12,7 +12,7 @@ obj-$(CONFIG_DVB_CX24110) += cx24110.o ...@@ -12,7 +12,7 @@ obj-$(CONFIG_DVB_CX24110) += cx24110.o
obj-$(CONFIG_DVB_TDA8083) += tda8083.o obj-$(CONFIG_DVB_TDA8083) += tda8083.o
obj-$(CONFIG_DVB_L64781) += l64781.o obj-$(CONFIG_DVB_L64781) += l64781.o
obj-$(CONFIG_DVB_DIB3000MB) += dib3000mb.o obj-$(CONFIG_DVB_DIB3000MB) += dib3000mb.o
obj-$(CONFIG_DVB_DIB3000MC) += dib3000mc.o obj-$(CONFIG_DVB_DIB3000MC) += dib3000mc.o dibx000_common.o
obj-$(CONFIG_DVB_MT312) += mt312.o obj-$(CONFIG_DVB_MT312) += mt312.o
obj-$(CONFIG_DVB_VES1820) += ves1820.o obj-$(CONFIG_DVB_VES1820) += ves1820.o
obj-$(CONFIG_DVB_VES1X93) += ves1x93.o obj-$(CONFIG_DVB_VES1X93) += ves1x93.o
...@@ -31,6 +31,8 @@ obj-$(CONFIG_DVB_BCM3510) += bcm3510.o ...@@ -31,6 +31,8 @@ obj-$(CONFIG_DVB_BCM3510) += bcm3510.o
obj-$(CONFIG_DVB_S5H1420) += s5h1420.o obj-$(CONFIG_DVB_S5H1420) += s5h1420.o
obj-$(CONFIG_DVB_LGDT330X) += lgdt330x.o obj-$(CONFIG_DVB_LGDT330X) += lgdt330x.o
obj-$(CONFIG_DVB_CX24123) += cx24123.o obj-$(CONFIG_DVB_CX24123) += cx24123.o
obj-$(CONFIG_DVB_LNBP21) += lnbp21.o
obj-$(CONFIG_DVB_ISL6421) += isl6421.o
obj-$(CONFIG_DVB_TDA10086) += tda10086.o obj-$(CONFIG_DVB_TDA10086) += tda10086.o
obj-$(CONFIG_DVB_TDA826X) += tda826x.o obj-$(CONFIG_DVB_TDA826X) += tda826x.o
obj-$(CONFIG_DVB_TUNER_MT2060) += mt2060.o obj-$(CONFIG_DVB_TUNER_MT2060) += mt2060.o
...@@ -26,20 +26,10 @@ ...@@ -26,20 +26,10 @@
#include <linux/dvb/frontend.h> #include <linux/dvb/frontend.h>
struct dib3000p_agc_config {
u16 val[12];
};
struct dib3000_config struct dib3000_config
{ {
/* the demodulator's i2c address */ /* the demodulator's i2c address */
u8 demod_address; u8 demod_address;
const struct dib3000p_agc_config *agc;
/* PLL maintenance and the i2c address of the PLL */
int (*pll_init)(struct dvb_frontend *fe);
int (*pll_set)(struct dvb_frontend *fe, struct dvb_frontend_parameters* params);
}; };
struct dib_fe_xfer_ops struct dib_fe_xfer_ops
...@@ -51,11 +41,16 @@ struct dib_fe_xfer_ops ...@@ -51,11 +41,16 @@ struct dib_fe_xfer_ops
int (*tuner_pass_ctrl)(struct dvb_frontend *fe, int onoff, u8 pll_ctrl); int (*tuner_pass_ctrl)(struct dvb_frontend *fe, int onoff, u8 pll_ctrl);
}; };
#if defined(CONFIG_DVB_DIB3000MB) || defined(CONFIG_DVB_DIB3000MB_MODULE)
extern struct dvb_frontend* dib3000mb_attach(const struct dib3000_config* config, extern struct dvb_frontend* dib3000mb_attach(const struct dib3000_config* config,
struct i2c_adapter* i2c, struct dib_fe_xfer_ops *xfer_ops); struct i2c_adapter* i2c, struct dib_fe_xfer_ops *xfer_ops);
#else
static inline struct dvb_frontend* dib3000mb_attach(const struct dib3000_config* config,
struct i2c_adapter* i2c, struct dib_fe_xfer_ops *xfer_ops)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
return NULL;
}
#endif // CONFIG_DVB_DIB3000MB
extern struct dvb_frontend* dib3000mc_attach(const struct dib3000_config* config,
struct i2c_adapter* i2c, struct dib_fe_xfer_ops *xfer_ops);
extern int dib3000mc_set_agc_config(struct dvb_frontend *fe, const struct dib3000p_agc_config *agc);
#endif // DIB3000_H #endif // DIB3000_H
...@@ -83,9 +83,6 @@ ...@@ -83,9 +83,6 @@
#define DIB3000_TUNER_WRITE_ENABLE(a) (0xffff & (a << 8)) #define DIB3000_TUNER_WRITE_ENABLE(a) (0xffff & (a << 8))
#define DIB3000_TUNER_WRITE_DISABLE(a) (0xffff & ((a << 8) | (1 << 7))) #define DIB3000_TUNER_WRITE_DISABLE(a) (0xffff & ((a << 8) | (1 << 7)))
/* for auto search */
extern u16 dib3000_seq[2][2][2];
#define DIB3000_REG_MANUFACTOR_ID ( 1025) #define DIB3000_REG_MANUFACTOR_ID ( 1025)
#define DIB3000_I2C_ID_DIBCOM (0x01b3) #define DIB3000_I2C_ID_DIBCOM (0x01b3)
......
This diff is collapsed.
This diff is collapsed.
...@@ -32,7 +32,7 @@ ...@@ -32,7 +32,7 @@
#include "mt2060.h" #include "mt2060.h"
#include "mt2060_priv.h" #include "mt2060_priv.h"
static int debug=0; static int debug;
module_param(debug, int, 0644); module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off)."); MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
...@@ -350,7 +350,7 @@ int mt2060_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct mt206 ...@@ -350,7 +350,7 @@ int mt2060_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct mt206
kfree(priv); kfree(priv);
return -ENODEV; return -ENODEV;
} }
printk(KERN_INFO "MT2060: successfully identified\n"); printk(KERN_INFO "MT2060: successfully identified (IF1 = %d)\n", if1);
memcpy(&fe->ops.tuner_ops, &mt2060_tuner_ops, sizeof(struct dvb_tuner_ops)); memcpy(&fe->ops.tuner_ops, &mt2060_tuner_ops, sizeof(struct dvb_tuner_ops));
fe->tuner_priv = priv; fe->tuner_priv = priv;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment