summaryrefslogtreecommitdiffstats
path: root/drivers/media/dvb
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/dvb')
-rw-r--r--drivers/media/dvb/b2c2/flexcop-fe-tuner.c33
-rw-r--r--drivers/media/dvb/b2c2/flexcop-reg.h4
-rw-r--r--drivers/media/dvb/bt8xx/dst.c52
-rw-r--r--drivers/media/dvb/bt8xx/dst_ca.c3
-rw-r--r--drivers/media/dvb/bt8xx/dvb-bt8xx.c16
-rw-r--r--drivers/media/dvb/cinergyT2/Kconfig20
-rw-r--r--drivers/media/dvb/cinergyT2/cinergyT2.c82
-rw-r--r--drivers/media/dvb/dvb-core/Kconfig2
-rw-r--r--drivers/media/dvb/dvb-core/Makefile2
-rw-r--r--drivers/media/dvb/dvb-core/dvb_ca_en50221.c4
-rw-r--r--drivers/media/dvb/dvb-core/dvb_filter.c16
-rw-r--r--drivers/media/dvb/dvb-core/dvb_frontend.c315
-rw-r--r--drivers/media/dvb/dvb-core/dvb_frontend.h16
-rw-r--r--drivers/media/dvb/dvb-core/dvb_net.c6
-rw-r--r--drivers/media/dvb/dvb-core/dvb_ringbuffer.c32
-rw-r--r--drivers/media/dvb/dvb-core/dvb_ringbuffer.h8
-rw-r--r--drivers/media/dvb/dvb-core/dvbdev.c22
-rw-r--r--drivers/media/dvb/dvb-core/dvbdev.h2
-rw-r--r--drivers/media/dvb/dvb-usb/Kconfig24
-rw-r--r--drivers/media/dvb/dvb-usb/cxusb.c294
-rw-r--r--drivers/media/dvb/dvb-usb/cxusb.h2
-rw-r--r--drivers/media/dvb/dvb-usb/dibusb-mb.c46
-rw-r--r--drivers/media/dvb/dvb-usb/digitv.c2
-rw-r--r--drivers/media/dvb/dvb-usb/dtt200u.c6
-rw-r--r--drivers/media/dvb/dvb-usb/dtt200u.h31
-rw-r--r--drivers/media/dvb/dvb-usb/dvb-usb-common.h2
-rw-r--r--drivers/media/dvb/dvb-usb/dvb-usb-firmware.c154
-rw-r--r--drivers/media/dvb/dvb-usb/dvb-usb-i2c.c8
-rw-r--r--drivers/media/dvb/dvb-usb/dvb-usb-ids.h12
-rw-r--r--drivers/media/dvb/dvb-usb/dvb-usb-init.c59
-rw-r--r--drivers/media/dvb/dvb-usb/dvb-usb.h29
-rw-r--r--drivers/media/dvb/dvb-usb/nova-t-usb2.c7
-rw-r--r--drivers/media/dvb/dvb-usb/vp702x-fe.c2
-rw-r--r--drivers/media/dvb/dvb-usb/vp702x.h43
-rw-r--r--drivers/media/dvb/dvb-usb/vp7045.c2
-rw-r--r--drivers/media/dvb/frontends/Kconfig46
-rw-r--r--drivers/media/dvb/frontends/Makefile1
-rw-r--r--drivers/media/dvb/frontends/bcm3510.c6
-rw-r--r--drivers/media/dvb/frontends/cx22702.c22
-rw-r--r--drivers/media/dvb/frontends/cx24110.c23
-rw-r--r--drivers/media/dvb/frontends/cx24123.c889
-rw-r--r--drivers/media/dvb/frontends/cx24123.h51
-rw-r--r--drivers/media/dvb/frontends/dvb-pll.c15
-rw-r--r--drivers/media/dvb/frontends/dvb-pll.h2
-rw-r--r--drivers/media/dvb/frontends/lgdt330x.c3
-rw-r--r--drivers/media/dvb/frontends/nxt2002.c3
-rw-r--r--drivers/media/dvb/frontends/nxt6000.c10
-rw-r--r--drivers/media/dvb/frontends/or51211.c5
-rw-r--r--drivers/media/dvb/frontends/s5h1420.c4
-rw-r--r--drivers/media/dvb/frontends/sp8870.c3
-rw-r--r--drivers/media/dvb/frontends/sp887x.c5
-rw-r--r--drivers/media/dvb/frontends/stv0299.c12
-rw-r--r--drivers/media/dvb/frontends/stv0299.h1
-rw-r--r--drivers/media/dvb/frontends/tda10021.c4
-rw-r--r--drivers/media/dvb/frontends/tda1004x.c141
-rw-r--r--drivers/media/dvb/pluto2/Kconfig2
-rw-r--r--drivers/media/dvb/ttpci/Kconfig7
-rw-r--r--drivers/media/dvb/ttpci/Makefile2
-rw-r--r--drivers/media/dvb/ttpci/av7110.c133
-rw-r--r--drivers/media/dvb/ttpci/av7110.h17
-rw-r--r--drivers/media/dvb/ttpci/av7110_av.c12
-rw-r--r--drivers/media/dvb/ttpci/av7110_hw.c7
-rw-r--r--drivers/media/dvb/ttpci/av7110_hw.h3
-rw-r--r--drivers/media/dvb/ttpci/av7110_ir.c14
-rw-r--r--drivers/media/dvb/ttpci/av7110_v4l.c118
-rw-r--r--drivers/media/dvb/ttpci/budget-av.c184
-rw-r--r--drivers/media/dvb/ttpci/budget-core.c4
-rw-r--r--drivers/media/dvb/ttpci/budget.c13
-rw-r--r--drivers/media/dvb/ttpci/ttpci-eeprom.c2
-rw-r--r--drivers/media/dvb/ttusb-budget/Kconfig2
-rw-r--r--drivers/media/dvb/ttusb-dec/Kconfig13
-rw-r--r--drivers/media/dvb/ttusb-dec/ttusb_dec.c20
-rw-r--r--drivers/media/dvb/ttusb-dec/ttusbdecfe.c53
73 files changed, 2548 insertions, 662 deletions
diff --git a/drivers/media/dvb/b2c2/flexcop-fe-tuner.c b/drivers/media/dvb/b2c2/flexcop-fe-tuner.c
index 21a9045b3ef6..0b940e152b79 100644
--- a/drivers/media/dvb/b2c2/flexcop-fe-tuner.c
+++ b/drivers/media/dvb/b2c2/flexcop-fe-tuner.c
@@ -298,7 +298,7 @@ static int flexcop_fe_request_firmware(struct dvb_frontend* fe, const struct fir
}
static int lgdt3303_pll_set(struct dvb_frontend* fe,
- struct dvb_frontend_parameters* params)
+ struct dvb_frontend_parameters* params)
{
struct flexcop_device *fc = fe->dvb->priv;
u8 buf[4];
@@ -485,12 +485,16 @@ static struct stv0297_config alps_tdee4_stv0297_config = {
/* try to figure out the frontend, each card/box can have on of the following list */
int flexcop_frontend_init(struct flexcop_device *fc)
{
+ struct dvb_frontend_ops *ops;
+
/* try the sky v2.6 (stv0299/Samsung tbmu24112(sl1935)) */
if ((fc->fe = stv0299_attach(&samsung_tbmu24112_config, &fc->i2c_adap)) != NULL) {
- fc->fe->ops->set_voltage = flexcop_set_voltage;
+ ops = fc->fe->ops;
+
+ ops->set_voltage = flexcop_set_voltage;
- fc->fe_sleep = fc->fe->ops->sleep;
- fc->fe->ops->sleep = flexcop_sleep;
+ fc->fe_sleep = ops->sleep;
+ ops->sleep = flexcop_sleep;
fc->dev_type = FC_SKY;
info("found the stv0299 at i2c address: 0x%02x",samsung_tbmu24112_config.demod_address);
@@ -522,15 +526,17 @@ int flexcop_frontend_init(struct flexcop_device *fc)
} else
/* try the sky v2.3 (vp310/Samsung tbdu18132(tsa5059)) */
if ((fc->fe = vp310_attach(&skystar23_samsung_tbdu18132_config, &fc->i2c_adap)) != NULL) {
- fc->fe->ops->diseqc_send_master_cmd = flexcop_diseqc_send_master_cmd;
- fc->fe->ops->diseqc_send_burst = flexcop_diseqc_send_burst;
- fc->fe->ops->set_tone = flexcop_set_tone;
- fc->fe->ops->set_voltage = flexcop_set_voltage;
+ ops = fc->fe->ops;
+
+ ops->diseqc_send_master_cmd = flexcop_diseqc_send_master_cmd;
+ ops->diseqc_send_burst = flexcop_diseqc_send_burst;
+ ops->set_tone = flexcop_set_tone;
+ ops->set_voltage = flexcop_set_voltage;
- fc->fe_sleep = fc->fe->ops->sleep;
- fc->fe->ops->sleep = flexcop_sleep;
+ fc->fe_sleep = ops->sleep;
+ ops->sleep = flexcop_sleep;
- fc->dev_type = FC_SKY_OLD;
+ fc->dev_type = FC_SKY_OLD;
info("found the vp310 (aka mt312) at i2c address: 0x%02x",skystar23_samsung_tbdu18132_config.demod_address);
}
@@ -540,8 +546,9 @@ int flexcop_frontend_init(struct flexcop_device *fc)
} else {
if (dvb_register_frontend(&fc->dvb_adapter, fc->fe)) {
err("frontend registration failed!");
- if (fc->fe->ops->release != NULL)
- fc->fe->ops->release(fc->fe);
+ ops = fc->fe->ops;
+ if (ops->release != NULL)
+ ops->release(fc->fe);
fc->fe = NULL;
return -EINVAL;
}
diff --git a/drivers/media/dvb/b2c2/flexcop-reg.h b/drivers/media/dvb/b2c2/flexcop-reg.h
index 23cc6431e2b8..3153f9513c63 100644
--- a/drivers/media/dvb/b2c2/flexcop-reg.h
+++ b/drivers/media/dvb/b2c2/flexcop-reg.h
@@ -39,11 +39,13 @@ extern const char *flexcop_device_names[];
/* FlexCop IBI Registers */
#if defined(__LITTLE_ENDIAN)
#include "flexcop_ibi_value_le.h"
-#elif defined(__BIG_ENDIAN)
+#else
+#if defined(__BIG_ENDIAN)
#include "flexcop_ibi_value_be.h"
#else
#error no endian defined
#endif
+#endif
#define fc_data_Tag_ID_DVB 0x3e
#define fc_data_Tag_ID_ATSC 0x3f
diff --git a/drivers/media/dvb/bt8xx/dst.c b/drivers/media/dvb/bt8xx/dst.c
index 8977c7a313df..3a2ff1cc24b7 100644
--- a/drivers/media/dvb/bt8xx/dst.c
+++ b/drivers/media/dvb/bt8xx/dst.c
@@ -1341,30 +1341,40 @@ static int dst_read_snr(struct dvb_frontend *fe, u16 *snr)
return 0;
}
-static int dst_set_frontend(struct dvb_frontend *fe, struct dvb_frontend_parameters *p)
+static int dst_set_frontend(struct dvb_frontend* fe,
+ struct dvb_frontend_parameters* p,
+ unsigned int mode_flags,
+ int *delay,
+ fe_status_t *status)
{
struct dst_state *state = fe->demodulator_priv;
- dst_set_freq(state, p->frequency);
- dprintk(verbose, DST_DEBUG, 1, "Set Frequency=[%d]", p->frequency);
+ if (p != NULL) {
+ dst_set_freq(state, p->frequency);
+ dprintk(verbose, DST_DEBUG, 1, "Set Frequency=[%d]", p->frequency);
- if (state->dst_type == DST_TYPE_IS_SAT) {
- if (state->type_flags & DST_TYPE_HAS_OBS_REGS)
- dst_set_inversion(state, p->inversion);
- dst_set_fec(state, p->u.qpsk.fec_inner);
- dst_set_symbolrate(state, p->u.qpsk.symbol_rate);
- dst_set_polarization(state);
- dprintk(verbose, DST_DEBUG, 1, "Set Symbolrate=[%d]", p->u.qpsk.symbol_rate);
-
- } else if (state->dst_type == DST_TYPE_IS_TERR)
- dst_set_bandwidth(state, p->u.ofdm.bandwidth);
- else if (state->dst_type == DST_TYPE_IS_CABLE) {
- dst_set_fec(state, p->u.qam.fec_inner);
- dst_set_symbolrate(state, p->u.qam.symbol_rate);
- dst_set_modulation(state, p->u.qam.modulation);
+ if (state->dst_type == DST_TYPE_IS_SAT) {
+ if (state->type_flags & DST_TYPE_HAS_OBS_REGS)
+ dst_set_inversion(state, p->inversion);
+ dst_set_fec(state, p->u.qpsk.fec_inner);
+ dst_set_symbolrate(state, p->u.qpsk.symbol_rate);
+ dst_set_polarization(state);
+ dprintk(verbose, DST_DEBUG, 1, "Set Symbolrate=[%d]", p->u.qpsk.symbol_rate);
+
+ } else if (state->dst_type == DST_TYPE_IS_TERR)
+ dst_set_bandwidth(state, p->u.ofdm.bandwidth);
+ else if (state->dst_type == DST_TYPE_IS_CABLE) {
+ dst_set_fec(state, p->u.qam.fec_inner);
+ dst_set_symbolrate(state, p->u.qam.symbol_rate);
+ dst_set_modulation(state, p->u.qam.modulation);
+ }
+ dst_write_tuna(fe);
}
- dst_write_tuna(fe);
+ if (!(mode_flags & FE_TUNE_MODE_ONESHOT))
+ dst_read_status(fe, status);
+
+ *delay = HZ/10;
return 0;
}
@@ -1445,7 +1455,7 @@ static struct dvb_frontend_ops dst_dvbt_ops = {
.release = dst_release,
.init = dst_init,
- .set_frontend = dst_set_frontend,
+ .tune = dst_set_frontend,
.get_frontend = dst_get_frontend,
.read_status = dst_read_status,
.read_signal_strength = dst_read_signal_strength,
@@ -1469,7 +1479,7 @@ static struct dvb_frontend_ops dst_dvbs_ops = {
.release = dst_release,
.init = dst_init,
- .set_frontend = dst_set_frontend,
+ .tune = dst_set_frontend,
.get_frontend = dst_get_frontend,
.read_status = dst_read_status,
.read_signal_strength = dst_read_signal_strength,
@@ -1496,7 +1506,7 @@ static struct dvb_frontend_ops dst_dvbc_ops = {
.release = dst_release,
.init = dst_init,
- .set_frontend = dst_set_frontend,
+ .tune = dst_set_frontend,
.get_frontend = dst_get_frontend,
.read_status = dst_read_status,
.read_signal_strength = dst_read_signal_strength,
diff --git a/drivers/media/dvb/bt8xx/dst_ca.c b/drivers/media/dvb/bt8xx/dst_ca.c
index 2239651969c8..c650b4bf7f5f 100644
--- a/drivers/media/dvb/bt8xx/dst_ca.c
+++ b/drivers/media/dvb/bt8xx/dst_ca.c
@@ -283,16 +283,17 @@ static int handle_dst_tag(struct dst_state *state, struct ca_msg *p_ca_message,
hw_buffer->msg[4] = 0x03;
hw_buffer->msg[5] = length & 0xff;
hw_buffer->msg[6] = 0x00;
+
/*
* Need to compute length for EN50221 section 8.3.2, for the time being
* assuming 8.3.2 is not applicable
*/
memcpy(&hw_buffer->msg[7], &p_ca_message->msg[4], length);
}
+
return 0;
}
-
static int write_to_8820(struct dst_state *state, struct ca_msg *hw_buffer, u8 length, u8 reply)
{
if ((dst_put_ci(state, hw_buffer->msg, length, hw_buffer->msg, reply)) < 0) {
diff --git a/drivers/media/dvb/bt8xx/dvb-bt8xx.c b/drivers/media/dvb/bt8xx/dvb-bt8xx.c
index 77977e9c013e..01b4e0aac049 100644
--- a/drivers/media/dvb/bt8xx/dvb-bt8xx.c
+++ b/drivers/media/dvb/bt8xx/dvb-bt8xx.c
@@ -600,7 +600,6 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type)
struct dst_state* state = NULL;
switch(type) {
-#ifdef BTTV_BOARD_DVICO_DVBT_LITE
case BTTV_BOARD_DVICO_DVBT_LITE:
card->fe = mt352_attach(&thomson_dtt7579_config, card->i2c_adapter);
if (card->fe != NULL) {
@@ -608,22 +607,15 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type)
card->fe->ops->info.frequency_max = 862000000;
}
break;
-#endif
-#ifdef BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE
case BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE:
lgdt330x_reset(card);
card->fe = lgdt330x_attach(&tdvs_tua6034_config, card->i2c_adapter);
if (card->fe != NULL)
dprintk ("dvb_bt8xx: lgdt330x detected\n");
break;
-#endif
-#ifdef BTTV_BOARD_TWINHAN_VP3021
- case BTTV_BOARD_TWINHAN_VP3021:
-#else
case BTTV_BOARD_NEBULA_DIGITV:
-#endif
/*
* It is possible to determine the correct frontend using the I2C bus (see the Nebula SDK);
* this would be a cleaner solution than trying each frontend in turn.
@@ -812,9 +804,7 @@ static int dvb_bt8xx_probe(struct device *dev)
card->irq_err_ignore = 0;
break;
-#ifdef BTTV_BOARD_DVICO_DVBT_LITE
case BTTV_BOARD_DVICO_DVBT_LITE:
-#endif
card->gpio_mode = 0x0400C060;
card->op_sync_orin = 0;
card->irq_err_ignore = 0;
@@ -823,19 +813,13 @@ static int dvb_bt8xx_probe(struct device *dev)
* DA_APP(parallel) */
break;
-#ifdef BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE
case BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE:
-#endif
card->gpio_mode = 0x0400c060;
card->op_sync_orin = BT878_RISC_SYNC_MASK;
card->irq_err_ignore = BT878_AFBUS | BT878_AFDSR;
break;
-#ifdef BTTV_BOARD_TWINHAN_VP3021
- case BTTV_BOARD_TWINHAN_VP3021:
-#else
case BTTV_BOARD_NEBULA_DIGITV:
-#endif
case BTTV_BOARD_AVDVBT_761:
card->gpio_mode = (1 << 26) | (1 << 14) | (1 << 5);
card->op_sync_orin = 0;
diff --git a/drivers/media/dvb/cinergyT2/Kconfig b/drivers/media/dvb/cinergyT2/Kconfig
index 7cf4c4a888ec..6018fcdba1e6 100644
--- a/drivers/media/dvb/cinergyT2/Kconfig
+++ b/drivers/media/dvb/cinergyT2/Kconfig
@@ -21,35 +21,35 @@ config DVB_CINERGYT2_TUNING
config DVB_CINERGYT2_STREAM_URB_COUNT
int "Number of queued USB Request Blocks for Highspeed Stream Transfers"
depends on DVB_CINERGYT2_TUNING
- default "32"
+ default "32"
help
USB Request Blocks for Highspeed Stream transfers are scheduled in
a queue for the Host Controller.
Usually the default value is a safe choice.
- You may increase this number if you are using this device in a
- Server Environment with many high-traffic USB Highspeed devices
+ You may increase this number if you are using this device in a
+ Server Environment with many high-traffic USB Highspeed devices
sharing the same USB bus.
config DVB_CINERGYT2_STREAM_BUF_SIZE
int "Size of URB Stream Buffers for Highspeed Transfers"
depends on DVB_CINERGYT2_TUNING
- default "512"
+ default "512"
help
Should be a multiple of native buffer size of 512 bytes.
Default value is a safe choice.
- You may increase this number if you are using this device in a
- Server Environment with many high-traffic USB Highspeed devices
+ You may increase this number if you are using this device in a
+ Server Environment with many high-traffic USB Highspeed devices
sharing the same USB bus.
config DVB_CINERGYT2_QUERY_INTERVAL
int "Status update interval [milliseconds]"
depends on DVB_CINERGYT2_TUNING
- default "250"
+ default "250"
help
This is the interval for status readouts from the demodulator.
You may try lower values if you need more responsive signal quality
@@ -64,9 +64,9 @@ config DVB_CINERGYT2_QUERY_INTERVAL
config DVB_CINERGYT2_ENABLE_RC_INPUT_DEVICE
bool "Register the onboard IR Remote Control Receiver as Input Device"
depends on DVB_CINERGYT2_TUNING
- default "yes"
+ default "yes"
help
- Enable this option if you want to use the onboard Infrared Remote
+ Enable this option if you want to use the onboard Infrared Remote
Control Receiver as Linux-Input device.
Right now only the keycode table for the default Remote Control
@@ -77,7 +77,7 @@ config DVB_CINERGYT2_ENABLE_RC_INPUT_DEVICE
config DVB_CINERGYT2_RC_QUERY_INTERVAL
int "Infrared Remote Controller update interval [milliseconds]"
depends on DVB_CINERGYT2_TUNING && DVB_CINERGYT2_ENABLE_RC_INPUT_DEVICE
- default "50"
+ default "50"
help
If you have a very fast-repeating remote control you can try lower
values, for normal consumer receivers the default value should be
diff --git a/drivers/media/dvb/cinergyT2/cinergyT2.c b/drivers/media/dvb/cinergyT2/cinergyT2.c
index 1d69bf031fb9..c4b4c5b6b7c8 100644
--- a/drivers/media/dvb/cinergyT2/cinergyT2.c
+++ b/drivers/media/dvb/cinergyT2/cinergyT2.c
@@ -131,6 +131,8 @@ struct cinergyt2 {
wait_queue_head_t poll_wq;
int pending_fe_events;
+ int disconnect_pending;
+ atomic_t inuse;
void *streambuf;
dma_addr_t streambuf_dmahandle;
@@ -343,7 +345,7 @@ static int cinergyt2_start_feed(struct dvb_demux_feed *dvbdmxfeed)
struct dvb_demux *demux = dvbdmxfeed->demux;
struct cinergyt2 *cinergyt2 = demux->priv;
- if (down_interruptible(&cinergyt2->sem))
+ if (cinergyt2->disconnect_pending || down_interruptible(&cinergyt2->sem))
return -ERESTARTSYS;
if (cinergyt2->streaming == 0)
@@ -359,7 +361,7 @@ static int cinergyt2_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
struct dvb_demux *demux = dvbdmxfeed->demux;
struct cinergyt2 *cinergyt2 = demux->priv;
- if (down_interruptible(&cinergyt2->sem))
+ if (cinergyt2->disconnect_pending || down_interruptible(&cinergyt2->sem))
return -ERESTARTSYS;
if (--cinergyt2->streaming == 0)
@@ -479,23 +481,37 @@ static int cinergyt2_open (struct inode *inode, struct file *file)
{
struct dvb_device *dvbdev = file->private_data;
struct cinergyt2 *cinergyt2 = dvbdev->priv;
- int err;
+ int err = -ERESTARTSYS;
- if ((err = dvb_generic_open(inode, file)))
+ if (cinergyt2->disconnect_pending || down_interruptible(&cinergyt2->sem))
+ return -ERESTARTSYS;
+
+ if ((err = dvb_generic_open(inode, file))) {
+ up(&cinergyt2->sem);
return err;
+ }
- if (down_interruptible(&cinergyt2->sem))
- return -ERESTARTSYS;
if ((file->f_flags & O_ACCMODE) != O_RDONLY) {
cinergyt2_sleep(cinergyt2, 0);
schedule_delayed_work(&cinergyt2->query_work, HZ/2);
}
+ atomic_inc(&cinergyt2->inuse);
+
up(&cinergyt2->sem);
return 0;
}
+static void cinergyt2_unregister(struct cinergyt2 *cinergyt2)
+{
+ dvb_unregister_device(cinergyt2->fedev);
+ dvb_unregister_adapter(&cinergyt2->adapter);
+
+ cinergyt2_free_stream_urbs(cinergyt2);
+ kfree(cinergyt2);
+}
+
static int cinergyt2_release (struct inode *inode, struct file *file)
{
struct dvb_device *dvbdev = file->private_data;
@@ -504,7 +520,7 @@ static int cinergyt2_release (struct inode *inode, struct file *file)
if (down_interruptible(&cinergyt2->sem))
return -ERESTARTSYS;
- if ((file->f_flags & O_ACCMODE) != O_RDONLY) {
+ if (!cinergyt2->disconnect_pending && (file->f_flags & O_ACCMODE) != O_RDONLY) {
cancel_delayed_work(&cinergyt2->query_work);
flush_scheduled_work();
cinergyt2_sleep(cinergyt2, 1);
@@ -512,6 +528,11 @@ static int cinergyt2_release (struct inode *inode, struct file *file)
up(&cinergyt2->sem);
+ if (atomic_dec_and_test(&cinergyt2->inuse) && cinergyt2->disconnect_pending) {
+ warn("delayed unregister in release");
+ cinergyt2_unregister(cinergyt2);
+ }
+
return dvb_generic_release(inode, file);
}
@@ -519,7 +540,14 @@ static unsigned int cinergyt2_poll (struct file *file, struct poll_table_struct
{
struct dvb_device *dvbdev = file->private_data;
struct cinergyt2 *cinergyt2 = dvbdev->priv;
+
+ if (cinergyt2->disconnect_pending || down_interruptible(&cinergyt2->sem))
+ return -ERESTARTSYS;
+
poll_wait(file, &cinergyt2->poll_wq, wait);
+
+ up(&cinergyt2->sem);
+
return (POLLIN | POLLRDNORM | POLLPRI);
}
@@ -564,10 +592,15 @@ static int cinergyt2_ioctl (struct inode *inode, struct file *file,
(__u16 __user *) arg);
case FE_READ_UNCORRECTED_BLOCKS:
- /* UNC are already converted to host byte order... */
- return put_user(stat->uncorrected_block_count,
- (__u32 __user *) arg);
+ {
+ uint32_t unc_count;
+
+ unc_count = stat->uncorrected_block_count;
+ stat->uncorrected_block_count = 0;
+ /* UNC are already converted to host byte order... */
+ return put_user(unc_count,(__u32 __user *) arg);
+ }
case FE_SET_FRONTEND:
{
struct dvbt_set_parameters_msg *param = &cinergyt2->param;
@@ -580,7 +613,7 @@ static int cinergyt2_ioctl (struct inode *inode, struct file *file,
if (copy_from_user(&p, (void __user*) arg, sizeof(p)))
return -EFAULT;
- if (down_interruptible(&cinergyt2->sem))
+ if (cinergyt2->disconnect_pending || down_interruptible(&cinergyt2->sem))
return -ERESTARTSYS;
param->cmd = CINERGYT2_EP1_SET_TUNER_PARAMETERS;
@@ -691,7 +724,7 @@ static void cinergyt2_query_rc (void *data)
struct cinergyt2_rc_event rc_events[12];
int n, len, i;
- if (down_interruptible(&cinergyt2->sem))
+ if (cinergyt2->disconnect_pending || down_interruptible(&cinergyt2->sem))
return;
len = cinergyt2_command(cinergyt2, buf, sizeof(buf),
@@ -786,7 +819,6 @@ static int cinergyt2_register_rc(struct cinergyt2 *cinergyt2)
static void cinergyt2_unregister_rc(struct cinergyt2 *cinergyt2)
{
cancel_delayed_work(&cinergyt2->rc_query_work);
- flush_scheduled_work();
input_unregister_device(cinergyt2->rc_input_dev);
}
@@ -817,7 +849,7 @@ static void cinergyt2_query (void *data)
uint8_t lock_bits;
uint32_t unc;
- if (down_interruptible(&cinergyt2->sem))
+ if (cinergyt2->disconnect_pending || down_interruptible(&cinergyt2->sem))
return;
unc = s->uncorrected_block_count;
@@ -917,28 +949,25 @@ static void cinergyt2_disconnect (struct usb_interface *intf)
{
struct cinergyt2 *cinergyt2 = usb_get_intfdata (intf);
- if (down_interruptible(&cinergyt2->sem))
- return;
+ flush_scheduled_work();
cinergyt2_unregister_rc(cinergyt2);
+ cancel_delayed_work(&cinergyt2->query_work);
+ wake_up_interruptible(&cinergyt2->poll_wq);
+
cinergyt2->demux.dmx.close(&cinergyt2->demux.dmx);
- dvb_net_release(&cinergyt2->dvbnet);
- dvb_dmxdev_release(&cinergyt2->dmxdev);
- dvb_dmx_release(&cinergyt2->demux);
- dvb_unregister_device(cinergyt2->fedev);
- dvb_unregister_adapter(&cinergyt2->adapter);
+ cinergyt2->disconnect_pending = 1;
- cinergyt2_free_stream_urbs(cinergyt2);
- up(&cinergyt2->sem);
- kfree(cinergyt2);
+ if (!atomic_read(&cinergyt2->inuse))
+ cinergyt2_unregister(cinergyt2);
}
static int cinergyt2_suspend (struct usb_interface *intf, pm_message_t state)
{
struct cinergyt2 *cinergyt2 = usb_get_intfdata (intf);
- if (down_interruptible(&cinergyt2->sem))
+ if (cinergyt2->disconnect_pending || down_interruptible(&cinergyt2->sem))
return -ERESTARTSYS;
if (state.event > PM_EVENT_ON) {
@@ -961,7 +990,7 @@ static int cinergyt2_resume (struct usb_interface *intf)
struct cinergyt2 *cinergyt2 = usb_get_intfdata (intf);
struct dvbt_set_parameters_msg *param = &cinergyt2->param;
- if (down_interruptible(&cinergyt2->sem))
+ if (cinergyt2->disconnect_pending || down_interruptible(&cinergyt2->sem))
return -ERESTARTSYS;
if (!cinergyt2->sleeping) {
@@ -1014,4 +1043,3 @@ module_exit (cinergyt2_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Holger Waechtler, Daniel Mack");
-
diff --git a/drivers/media/dvb/dvb-core/Kconfig b/drivers/media/dvb/dvb-core/Kconfig
index a9a7b3421048..12ee912a5705 100644
--- a/drivers/media/dvb/dvb-core/Kconfig
+++ b/drivers/media/dvb/dvb-core/Kconfig
@@ -5,7 +5,7 @@ config DVB_CORE
help
DVB core utility functions for device handling, software fallbacks etc.
Say Y when you have a DVB card and want to use it. Say Y if your want
- to build your drivers outside the kernel, but need the DVB core. All
+ to build your drivers outside the kernel, but need the DVB core. All
in-kernel drivers will select this automatically if needed.
If unsure say N.
diff --git a/drivers/media/dvb/dvb-core/Makefile b/drivers/media/dvb/dvb-core/Makefile
index c6baac20f529..7adb50c1e8eb 100644
--- a/drivers/media/dvb/dvb-core/Makefile
+++ b/drivers/media/dvb/dvb-core/Makefile
@@ -3,7 +3,7 @@
#
dvb-core-objs = dvbdev.o dmxdev.o dvb_demux.o dvb_filter.o \
- dvb_ca_en50221.o dvb_frontend.o \
+ dvb_ca_en50221.o dvb_frontend.o \
dvb_net.o dvb_ringbuffer.o
obj-$(CONFIG_DVB_CORE) += dvb-core.o
diff --git a/drivers/media/dvb/dvb-core/dvb_ca_en50221.c b/drivers/media/dvb/dvb-core/dvb_ca_en50221.c
index 5956c35d34ac..4bb779aeff6a 100644
--- a/drivers/media/dvb/dvb-core/dvb_ca_en50221.c
+++ b/drivers/media/dvb/dvb-core/dvb_ca_en50221.c
@@ -1745,9 +1745,7 @@ void dvb_ca_en50221_release(struct dvb_ca_en50221 *pubca)
for (i = 0; i < ca->slot_count; i++) {
dvb_ca_en50221_slot_shutdown(ca, i);
- if (ca->slot_info[i].rx_buffer.data != NULL) {
- vfree(ca->slot_info[i].rx_buffer.data);
- }
+ vfree(ca->slot_info[i].rx_buffer.data);
}
kfree(ca->slot_info);
dvb_unregister_device(ca->dvbdev);
diff --git a/drivers/media/dvb/dvb-core/dvb_filter.c b/drivers/media/dvb/dvb-core/dvb_filter.c
index c49fd0bd7181..772003fb1821 100644
--- a/drivers/media/dvb/dvb-core/dvb_filter.c
+++ b/drivers/media/dvb/dvb-core/dvb_filter.c
@@ -409,16 +409,16 @@ static u8 *skip_pes_header(u8 **bufp)
if ((inbuf[6] & 0xc0) == 0x80){ /* mpeg2 */
if (buf[7] & PTS_ONLY)
- pts = buf+9;
+ pts = buf+9;
else pts = NULL;
buf = inbuf + 9 + inbuf[8];
} else { /* mpeg1 */
for (buf = inbuf + 6; *buf == 0xff; buf++)
- if (buf == inbuf + 6 + 16) {
- break;
- }
+ if (buf == inbuf + 6 + 16) {
+ break;
+ }
if ((*buf & 0xc0) == 0x40)
- buf += 2;
+ buf += 2;
skip = mpeg1_skip_table [*buf >> 4];
if (skip == 5 || skip == 10) pts = buf;
else pts = NULL;
@@ -529,9 +529,9 @@ static void init_mpg_picture( struct mpg_picture *pic, int chan, int32_t field_t
pic->picture_header = 0;
pic->sequence_header_data
= ( INIT_HORIZONTAL_SIZE << 20 )
- | ( INIT_VERTICAL_SIZE << 8 )
- | ( INIT_ASPECT_RATIO << 4 )
- | ( INIT_FRAME_RATE );
+ | ( INIT_VERTICAL_SIZE << 8 )
+ | ( INIT_ASPECT_RATIO << 4 )
+ | ( INIT_FRAME_RATE );
pic->mpeg1_flag = 0;
pic->vinfo.horizontal_size
= INIT_DISP_HORIZONTAL_SIZE;
diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c
index 95ea5095e07e..4a08c4ab6730 100644
--- a/drivers/media/dvb/dvb-core/dvb_frontend.c
+++ b/drivers/media/dvb/dvb-core/dvb_frontend.c
@@ -92,6 +92,7 @@ static DECLARE_MUTEX(frontend_mutex);
struct dvb_frontend_private {
+ /* thread/frontend values */
struct dvb_device *dvbdev;
struct dvb_frontend_parameters parameters;
struct dvb_fe_events events;
@@ -100,20 +101,25 @@ struct dvb_frontend_private {
wait_queue_head_t wait_queue;
pid_t thread_pid;
unsigned long release_jiffies;
- int state;
- int bending;
- int lnb_drift;
- int inversion;
- int auto_step;
- int auto_sub_step;
- int started_auto_step;
- int min_delay;
- int max_drift;
- int step_size;
- int exit;
- int wakeup;
+ unsigned int exit;
+ unsigned int wakeup;
fe_status_t status;
- fe_sec_tone_mode_t tone;
+ unsigned long tune_mode_flags;
+ unsigned int delay;
+
+ /* swzigzag values */
+ unsigned int state;
+ unsigned int bending;
+ int lnb_drift;
+ unsigned int inversion;
+ unsigned int auto_step;
+ unsigned int auto_sub_step;
+ unsigned int started_auto_step;
+ unsigned int min_delay;
+ unsigned int max_drift;
+ unsigned int step_size;
+ int quality;
+ unsigned int check_wrapped;
};
@@ -208,21 +214,21 @@ static void dvb_frontend_init(struct dvb_frontend *fe)
fe->ops->init(fe);
}
-static void update_delay(int *quality, int *delay, int min_delay, int locked)
+static void dvb_frontend_swzigzag_update_delay(struct dvb_frontend_private *fepriv, int locked)
{
- int q2;
+ int q2;
- dprintk ("%s\n", __FUNCTION__);
+ dprintk ("%s\n", __FUNCTION__);
- if (locked)
- (*quality) = (*quality * 220 + 36*256) / 256;
- else
- (*quality) = (*quality * 220 + 0) / 256;
+ if (locked)
+ (fepriv->quality) = (fepriv->quality * 220 + 36*256) / 256;
+ else
+ (fepriv->quality) = (fepriv->quality * 220 + 0) / 256;
- q2 = *quality - 128;
- q2 *= q2;
+ q2 = fepriv->quality - 128;
+ q2 *= q2;
- *delay = min_delay + q2 * HZ / (128*128);
+ fepriv->delay = fepriv->min_delay + q2 * HZ / (128*128);
}
/**
@@ -232,7 +238,7 @@ static void update_delay(int *quality, int *delay, int min_delay, int locked)
* @param check_wrapped Checks if an iteration has completed. DO NOT SET ON THE FIRST ATTEMPT
* @returns Number of complete iterations that have been performed.
*/
-static int dvb_frontend_autotune(struct dvb_frontend *fe, int check_wrapped)
+static int dvb_frontend_swzigzag_autotune(struct dvb_frontend *fe, int check_wrapped)
{
int autoinversion;
int ready = 0;
@@ -321,6 +327,129 @@ static int dvb_frontend_autotune(struct dvb_frontend *fe, int check_wrapped)
return 0;
}
+static void dvb_frontend_swzigzag(struct dvb_frontend *fe)
+{
+ fe_status_t s;
+ struct dvb_frontend_private *fepriv = fe->frontend_priv;
+
+ /* if we've got no parameters, just keep idling */
+ if (fepriv->state & FESTATE_IDLE) {
+ fepriv->delay = 3*HZ;
+ fepriv->quality = 0;
+ return;
+ }
+
+ /* in SCAN mode, we just set the frontend when asked and leave it alone */
+ if (fepriv->tune_mode_flags & FE_TUNE_MODE_ONESHOT) {
+ if (fepriv->state & FESTATE_RETUNE) {
+ if (fe->ops->set_frontend)
+ fe->ops->set_frontend(fe, &fepriv->parameters);
+ fepriv->state = FESTATE_TUNED;
+ }
+ fepriv->delay = 3*HZ;
+ fepriv->quality = 0;
+ return;
+ }
+
+ /* get the frontend status */
+ if (fepriv->state & FESTATE_RETUNE) {
+ s = 0;
+ } else {
+ if (fe->ops->read_status)
+ fe->ops->read_status(fe, &s);
+ if (s != fepriv->status) {
+ dvb_frontend_add_event(fe, s);
+ fepriv->status = s;
+ }
+ }
+
+ /* if we're not tuned, and we have a lock, move to the TUNED state */
+ if ((fepriv->state & FESTATE_WAITFORLOCK) && (s & FE_HAS_LOCK)) {
+ dvb_frontend_swzigzag_update_delay(fepriv, s & FE_HAS_LOCK);
+ fepriv->state = FESTATE_TUNED;
+
+ /* if we're tuned, then we have determined the correct inversion */
+ if ((!(fe->ops->info.caps & FE_CAN_INVERSION_AUTO)) &&
+ (fepriv->parameters.inversion == INVERSION_AUTO)) {
+ fepriv->parameters.inversion = fepriv->inversion;
+ }
+ return;
+ }
+
+ /* if we are tuned already, check we're still locked */
+ if (fepriv->state & FESTATE_TUNED) {
+ dvb_frontend_swzigzag_update_delay(fepriv, s & FE_HAS_LOCK);
+
+ /* we're tuned, and the lock is still good... */
+ if (s & FE_HAS_LOCK) {
+ return;
+ } else { /* if we _WERE_ tuned, but now don't have a lock */
+ fepriv->state = FESTATE_ZIGZAG_FAST;
+ fepriv->started_auto_step = fepriv->auto_step;
+ fepriv->check_wrapped = 0;
+ }
+ }
+
+ /* don't actually do anything if we're in the LOSTLOCK state,
+ * the frontend is set to FE_CAN_RECOVER, and the max_drift is 0 */
+ if ((fepriv->state & FESTATE_LOSTLOCK) &&
+ (fe->ops->info.caps & FE_CAN_RECOVER) && (fepriv->max_drift == 0)) {
+ dvb_frontend_swzigzag_update_delay(fepriv, s & FE_HAS_LOCK);
+ return;
+ }
+
+ /* don't do anything if we're in the DISEQC state, since this
+ * might be someone with a motorized dish controlled by DISEQC.
+ * If its actually a re-tune, there will be a SET_FRONTEND soon enough. */
+ if (fepriv->state & FESTATE_DISEQC) {
+ dvb_frontend_swzigzag_update_delay(fepriv, s & FE_HAS_LOCK);
+ return;
+ }
+
+ /* if we're in the RETUNE state, set everything up for a brand
+ * new scan, keeping the current inversion setting, as the next
+ * tune is _very_ likely to require the same */
+ if (fepriv->state & FESTATE_RETUNE) {
+ fepriv->lnb_drift = 0;
+ fepriv->auto_step = 0;
+ fepriv->auto_sub_step = 0;
+ fepriv->started_auto_step = 0;
+ fepriv->check_wrapped = 0;
+ }
+
+ /* fast zigzag. */
+ if ((fepriv->state & FESTATE_SEARCHING_FAST) || (fepriv->state & FESTATE_RETUNE)) {
+ fepriv->delay = fepriv->min_delay;
+
+ /* peform a tune */
+ if (dvb_frontend_swzigzag_autotune(fe, fepriv->check_wrapped)) {
+ /* OK, if we've run out of trials at the fast speed.
+ * Drop back to slow for the _next_ attempt */
+ fepriv->state = FESTATE_SEARCHING_SLOW;
+ fepriv->started_auto_step = fepriv->auto_step;
+ return;
+ }
+ fepriv->check_wrapped = 1;
+
+ /* if we've just retuned, enter the ZIGZAG_FAST state.
+ * This ensures we cannot return from an
+ * FE_SET_FRONTEND ioctl before the first frontend tune
+ * occurs */
+ if (fepriv->state & FESTATE_RETUNE) {
+ fepriv->state = FESTATE_TUNING_FAST;
+ }
+ }
+
+ /* slow zigzag */
+ if (fepriv->state & FESTATE_SEARCHING_SLOW) {
+ dvb_frontend_swzigzag_update_delay(fepriv, s & FE_HAS_LOCK);
+
+ /* Note: don't bother checking for wrapping; we stay in this
+ * state until we get a lock */
+ dvb_frontend_swzigzag_autotune(fe, 0);
+ }
+}
+
static int dvb_frontend_is_exiting(struct dvb_frontend *fe)
{
struct dvb_frontend_private *fepriv = fe->frontend_priv;
@@ -330,7 +459,7 @@ static int dvb_frontend_is_exiting(struct dvb_frontend *fe)
if (fepriv->dvbdev->writers == 1)
if (time_after(jiffies, fepriv->release_jiffies +
- dvb_shutdown_timeout * HZ))
+ dvb_shutdown_timeout * HZ))
return 1;
return 0;
@@ -355,18 +484,14 @@ static void dvb_frontend_wakeup(struct dvb_frontend *fe)
wake_up_interruptible(&fepriv->wait_queue);
}
-/*
- * FIXME: use linux/kthread.h
- */
static int dvb_frontend_thread(void *data)
{
struct dvb_frontend *fe = data;
struct dvb_frontend_private *fepriv = fe->frontend_priv;
unsigned long timeout;
char name [15];
- int quality = 0, delay = 3*HZ;
fe_status_t s;
- int check_wrapped = 0;
+ struct dvb_frontend_parameters *params;
dprintk("%s\n", __FUNCTION__);
@@ -377,6 +502,9 @@ static int dvb_frontend_thread(void *data)
sigfillset(&current->blocked);
unlock_kernel();
+ fepriv->check_wrapped = 0;
+ fepriv->quality = 0;
+ fepriv->delay = 3*HZ;
fepriv->status = 0;
dvb_frontend_init(fe);
fepriv->wakeup = 0;
@@ -386,7 +514,7 @@ static int dvb_frontend_thread(void *data)
timeout = wait_event_interruptible_timeout(fepriv->wait_queue,
dvb_frontend_should_wakeup(fe),
- delay);
+ fepriv->delay);
if (0 != dvb_frontend_is_exiting(fe)) {
/* got signal or quitting */
break;
@@ -397,108 +525,22 @@ static int dvb_frontend_thread(void *data)
if (down_interruptible(&fepriv->sem))
break;
- /* if we've got no parameters, just keep idling */
- if (fepriv->state & FESTATE_IDLE) {
- delay = 3*HZ;
- quality = 0;
- continue;
- }
+ /* do an iteration of the tuning loop */
+ if (fe->ops->tune) {
+ /* have we been asked to retune? */
+ params = NULL;
+ if (fepriv->state & FESTATE_RETUNE) {
+ params = &fepriv->parameters;
+ fepriv->state = FESTATE_TUNED;
+ }
- /* get the frontend status */
- if (fepriv->state & FESTATE_RETUNE) {
- s = 0;
- } else {
- if (fe->ops->read_status)
- fe->ops->read_status(fe, &s);
+ fe->ops->tune(fe, params, fepriv->tune_mode_flags, &fepriv->delay, &s);
if (s != fepriv->status) {
dvb_frontend_add_event(fe, s);
fepriv->status = s;
}
- }
- /* if we're not tuned, and we have a lock, move to the TUNED state */
- if ((fepriv->state & FESTATE_WAITFORLOCK) && (s & FE_HAS_LOCK)) {
- update_delay(&quality, &delay, fepriv->min_delay, s & FE_HAS_LOCK);
- fepriv->state = FESTATE_TUNED;
-
- /* if we're tuned, then we have determined the correct inversion */
- if ((!(fe->ops->info.caps & FE_CAN_INVERSION_AUTO)) &&
- (fepriv->parameters.inversion == INVERSION_AUTO)) {
- fepriv->parameters.inversion = fepriv->inversion;
- }
- continue;
- }
-
- /* if we are tuned already, check we're still locked */
- if (fepriv->state & FESTATE_TUNED) {
- update_delay(&quality, &delay, fepriv->min_delay, s & FE_HAS_LOCK);
-
- /* we're tuned, and the lock is still good... */
- if (s & FE_HAS_LOCK)
- continue;
- else { /* if we _WERE_ tuned, but now don't have a lock */
- fepriv->state = FESTATE_ZIGZAG_FAST;
- fepriv->started_auto_step = fepriv->auto_step;
- check_wrapped = 0;
- }
- }
-
- /* don't actually do anything if we're in the LOSTLOCK state,
- * the frontend is set to FE_CAN_RECOVER, and the max_drift is 0 */
- if ((fepriv->state & FESTATE_LOSTLOCK) &&
- (fe->ops->info.caps & FE_CAN_RECOVER) && (fepriv->max_drift == 0)) {
- update_delay(&quality, &delay, fepriv->min_delay, s & FE_HAS_LOCK);
- continue;
- }
-
- /* don't do anything if we're in the DISEQC state, since this
- * might be someone with a motorized dish controlled by DISEQC.
- * If its actually a re-tune, there will be a SET_FRONTEND soon enough. */
- if (fepriv->state & FESTATE_DISEQC) {
- update_delay(&quality, &delay, fepriv->min_delay, s & FE_HAS_LOCK);
- continue;
- }
-
- /* if we're in the RETUNE state, set everything up for a brand
- * new scan, keeping the current inversion setting, as the next
- * tune is _very_ likely to require the same */
- if (fepriv->state & FESTATE_RETUNE) {
- fepriv->lnb_drift = 0;
- fepriv->auto_step = 0;
- fepriv->auto_sub_step = 0;
- fepriv->started_auto_step = 0;
- check_wrapped = 0;
- }
-
- /* fast zigzag. */
- if ((fepriv->state & FESTATE_SEARCHING_FAST) || (fepriv->state & FESTATE_RETUNE)) {
- delay = fepriv->min_delay;
-
- /* peform a tune */
- if (dvb_frontend_autotune(fe, check_wrapped)) {
- /* OK, if we've run out of trials at the fast speed.
- * Drop back to slow for the _next_ attempt */
- fepriv->state = FESTATE_SEARCHING_SLOW;
- fepriv->started_auto_step = fepriv->auto_step;
- continue;
- }
- check_wrapped = 1;
-
- /* if we've just retuned, enter the ZIGZAG_FAST state.
- * This ensures we cannot return from an
- * FE_SET_FRONTEND ioctl before the first frontend tune
- * occurs */
- if (fepriv->state & FESTATE_RETUNE) {
- fepriv->state = FESTATE_TUNING_FAST;
- }
- }
-
- /* slow zigzag */
- if (fepriv->state & FESTATE_SEARCHING_SLOW) {
- update_delay(&quality, &delay, fepriv->min_delay, s & FE_HAS_LOCK);
-
- /* Note: don't bother checking for wrapping; we stay in this
- * state until we get a lock */
- dvb_frontend_autotune(fe, 0);
+ } else {
+ dvb_frontend_swzigzag(fe);
}
}
@@ -733,7 +775,6 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
err = fe->ops->set_tone(fe, (fe_sec_tone_mode_t) parg);
fepriv->state = FESTATE_DISEQC;
fepriv->status = 0;
- fepriv->tone = (fe_sec_tone_mode_t) parg;
}
break;
@@ -747,7 +788,7 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
case FE_DISHNETWORK_SEND_LEGACY_CMD:
if (fe->ops->dishnetwork_send_legacy_command) {
- err = fe->ops->dishnetwork_send_legacy_command(fe, (unsigned int) parg);
+ err = fe->ops->dishnetwork_send_legacy_command(fe, (unsigned long) parg);
fepriv->state = FESTATE_DISEQC;
fepriv->status = 0;
} else if (fe->ops->set_voltage) {
@@ -767,13 +808,13 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
* initialization, so parg is 8 bits and does not
* include the initialization or start bit
*/
- unsigned int cmd = ((unsigned int) parg) << 1;
+ unsigned long cmd = ((unsigned long) parg) << 1;
struct timeval nexttime;
struct timeval tv[10];
int i;
u8 last = 1;
if (dvb_frontend_debug)
- printk("%s switch command: 0x%04x\n", __FUNCTION__, cmd);
+ printk("%s switch command: 0x%04lx\n", __FUNCTION__, cmd);
do_gettimeofday(&nexttime);
if (dvb_frontend_debug)
memcpy(&tv[0], &nexttime, sizeof(struct timeval));
@@ -814,7 +855,7 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
case FE_ENABLE_HIGH_LNB_VOLTAGE:
if (fe->ops->enable_high_lnb_voltage)
- err = fe->ops->enable_high_lnb_voltage(fe, (int) parg);
+ err = fe->ops->enable_high_lnb_voltage(fe, (long) parg);
break;
case FE_SET_FRONTEND: {
@@ -891,6 +932,10 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
err = fe->ops->get_frontend(fe, (struct dvb_frontend_parameters*) parg);
}
break;
+
+ case FE_SET_FRONTEND_TUNE_MODE:
+ fepriv->tune_mode_flags = (unsigned long) parg;
+ break;
};
up (&fepriv->sem);
@@ -932,6 +977,9 @@ static int dvb_frontend_open(struct inode *inode, struct file *file)
/* empty event queue */
fepriv->events.eventr = fepriv->events.eventw = 0;
+
+ /* normal tune mode when opened R/W */
+ fepriv->tune_mode_flags &= ~FE_TUNE_MODE_ONESHOT;
}
return ret;
@@ -990,7 +1038,6 @@ int dvb_register_frontend(struct dvb_adapter* dvb,
init_MUTEX (&fepriv->events.sem);
fe->dvb = dvb;
fepriv->inversion = INVERSION_OFF;
- fepriv->tone = SEC_TONE_OFF;
printk ("DVB: registering frontend %i (%s)...\n",
fe->dvb->num,
diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.h b/drivers/media/dvb/dvb-core/dvb_frontend.h
index 1e0840d02f1f..70a6d14efda7 100644
--- a/drivers/media/dvb/dvb-core/dvb_frontend.h
+++ b/drivers/media/dvb/dvb-core/dvb_frontend.h
@@ -58,10 +58,19 @@ struct dvb_frontend_ops {
int (*init)(struct dvb_frontend* fe);
int (*sleep)(struct dvb_frontend* fe);
+ /* if this is set, it overrides the default swzigzag */
+ int (*tune)(struct dvb_frontend* fe,
+ struct dvb_frontend_parameters* params,
+ unsigned int mode_flags,
+ int *delay,
+ fe_status_t *status);
+
+ /* these two are only used for the swzigzag code */
int (*set_frontend)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params);
- int (*get_frontend)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params);
int (*get_tune_settings)(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* settings);
+ int (*get_frontend)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params);
+
int (*read_status)(struct dvb_frontend* fe, fe_status_t* status);
int (*read_ber)(struct dvb_frontend* fe, u32* ber);
int (*read_signal_strength)(struct dvb_frontend* fe, u16* strength);
@@ -74,8 +83,9 @@ struct dvb_frontend_ops {
int (*diseqc_send_burst)(struct dvb_frontend* fe, fe_sec_mini_cmd_t minicmd);
int (*set_tone)(struct dvb_frontend* fe, fe_sec_tone_mode_t tone);
int (*set_voltage)(struct dvb_frontend* fe, fe_sec_voltage_t voltage);
- int (*enable_high_lnb_voltage)(struct dvb_frontend* fe, int arg);
- int (*dishnetwork_send_legacy_command)(struct dvb_frontend* fe, unsigned int cmd);
+ int (*enable_high_lnb_voltage)(struct dvb_frontend* fe, long arg);
+ int (*dishnetwork_send_legacy_command)(struct dvb_frontend* fe, unsigned long cmd);
+ int (*i2c_gate_ctrl)(struct dvb_frontend* fe, int enable);
};
#define MAX_EVENT 8
diff --git a/drivers/media/dvb/dvb-core/dvb_net.c b/drivers/media/dvb/dvb-core/dvb_net.c
index 86bba81e851e..6711eb6a058c 100644
--- a/drivers/media/dvb/dvb-core/dvb_net.c
+++ b/drivers/media/dvb/dvb-core/dvb_net.c
@@ -1222,7 +1222,7 @@ static int dvb_net_add_if(struct dvb_net *dvbnet, u16 pid, u8 feedtype)
return if_num;
}
-static int dvb_net_remove_if(struct dvb_net *dvbnet, unsigned int num)
+static int dvb_net_remove_if(struct dvb_net *dvbnet, unsigned long num)
{
struct net_device *net = dvbnet->device[num];
struct dvb_net_priv *priv;
@@ -1296,9 +1296,9 @@ static int dvb_net_do_ioctl(struct inode *inode, struct file *file,
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
- if ((unsigned int) parg >= DVB_NET_DEVICES_MAX)
+ if ((unsigned long) parg >= DVB_NET_DEVICES_MAX)
return -EINVAL;
- ret = dvb_net_remove_if(dvbnet, (unsigned int) parg);
+ ret = dvb_net_remove_if(dvbnet, (unsigned long) parg);
if (!ret)
module_put(dvbdev->adapter->module);
return ret;
diff --git a/drivers/media/dvb/dvb-core/dvb_ringbuffer.c b/drivers/media/dvb/dvb-core/dvb_ringbuffer.c
index 283c6e9339a4..77ad2410f4d3 100644
--- a/drivers/media/dvb/dvb-core/dvb_ringbuffer.c
+++ b/drivers/media/dvb/dvb-core/dvb_ringbuffer.c
@@ -112,10 +112,10 @@ ssize_t dvb_ringbuffer_read(struct dvb_ringbuffer *rbuf, u8 *buf, size_t len, in
split = (rbuf->pread + len > rbuf->size) ? rbuf->size - rbuf->pread : 0;
if (split > 0) {
if (!usermem)
- memcpy(buf, rbuf->data+rbuf->pread, split);
+ memcpy(buf, rbuf->data+rbuf->pread, split);
else
- if (copy_to_user(buf, rbuf->data+rbuf->pread, split))
- return -EFAULT;
+ if (copy_to_user(buf, rbuf->data+rbuf->pread, split))
+ return -EFAULT;
buf += split;
todo -= split;
rbuf->pread = 0;
@@ -124,7 +124,7 @@ ssize_t dvb_ringbuffer_read(struct dvb_ringbuffer *rbuf, u8 *buf, size_t len, in
memcpy(buf, rbuf->data+rbuf->pread, todo);
else
if (copy_to_user(buf, rbuf->data+rbuf->pread, todo))
- return -EFAULT;
+ return -EFAULT;
rbuf->pread = (rbuf->pread + todo) % rbuf->size;
@@ -167,7 +167,7 @@ ssize_t dvb_ringbuffer_pkt_write(struct dvb_ringbuffer *rbuf, u8* buf, size_t le
}
ssize_t dvb_ringbuffer_pkt_read(struct dvb_ringbuffer *rbuf, size_t idx,
- int offset, u8* buf, size_t len, int usermem)
+ int offset, u8* buf, size_t len, int usermem)
{
size_t todo;
size_t split;
@@ -183,10 +183,10 @@ ssize_t dvb_ringbuffer_pkt_read(struct dvb_ringbuffer *rbuf, size_t idx,
split = ((idx + len) > rbuf->size) ? rbuf->size - idx : 0;
if (split > 0) {
if (!usermem)
- memcpy(buf, rbuf->data+idx, split);
+ memcpy(buf, rbuf->data+idx, split);
else
- if (copy_to_user(buf, rbuf->data+idx, split))
- return -EFAULT;
+ if (copy_to_user(buf, rbuf->data+idx, split))
+ return -EFAULT;
buf += split;
todo -= split;
idx = 0;
@@ -195,7 +195,7 @@ ssize_t dvb_ringbuffer_pkt_read(struct dvb_ringbuffer *rbuf, size_t idx,
memcpy(buf, rbuf->data+idx, todo);
else
if (copy_to_user(buf, rbuf->data+idx, todo))
- return -EFAULT;
+ return -EFAULT;
return len;
}
@@ -209,12 +209,12 @@ void dvb_ringbuffer_pkt_dispose(struct dvb_ringbuffer *rbuf, size_t idx)
// clean up disposed packets
while(dvb_ringbuffer_avail(rbuf) > DVB_RINGBUFFER_PKTHDRSIZE) {
if (DVB_RINGBUFFER_PEEK(rbuf, 2) == PKT_DISPOSED) {
- pktlen = DVB_RINGBUFFER_PEEK(rbuf, 0) << 8;
- pktlen |= DVB_RINGBUFFER_PEEK(rbuf, 1);
- DVB_RINGBUFFER_SKIP(rbuf, pktlen + DVB_RINGBUFFER_PKTHDRSIZE);
+ pktlen = DVB_RINGBUFFER_PEEK(rbuf, 0) << 8;
+ pktlen |= DVB_RINGBUFFER_PEEK(rbuf, 1);
+ DVB_RINGBUFFER_SKIP(rbuf, pktlen + DVB_RINGBUFFER_PKTHDRSIZE);
} else {
- // first packet is not disposed, so we stop cleaning now
- break;
+ // first packet is not disposed, so we stop cleaning now
+ break;
}
}
}
@@ -242,8 +242,8 @@ ssize_t dvb_ringbuffer_pkt_next(struct dvb_ringbuffer *rbuf, size_t idx, size_t*
curpktstatus = rbuf->data[(idx + 2) % rbuf->size];
if (curpktstatus == PKT_READY) {
- *pktlen = curpktlen;
- return idx;
+ *pktlen = curpktlen;
+ return idx;
}
consumed += curpktlen + DVB_RINGBUFFER_PKTHDRSIZE;
diff --git a/drivers/media/dvb/dvb-core/dvb_ringbuffer.h b/drivers/media/dvb/dvb-core/dvb_ringbuffer.h
index fa476f662f82..6d2560972771 100644
--- a/drivers/media/dvb/dvb-core/dvb_ringbuffer.h
+++ b/drivers/media/dvb/dvb-core/dvb_ringbuffer.h
@@ -106,7 +106,7 @@ extern void dvb_ringbuffer_flush_spinlock_wakeup(struct dvb_ringbuffer *rbuf);
** returns number of bytes transferred or -EFAULT
*/
extern ssize_t dvb_ringbuffer_read(struct dvb_ringbuffer *rbuf, u8 *buf,
- size_t len, int usermem);
+ size_t len, int usermem);
/* write routines & macros */
@@ -121,7 +121,7 @@ extern ssize_t dvb_ringbuffer_read(struct dvb_ringbuffer *rbuf, u8 *buf,
** returns number of bytes transferred or -EFAULT
*/
extern ssize_t dvb_ringbuffer_write(struct dvb_ringbuffer *rbuf, const u8 *buf,
- size_t len);
+ size_t len);
/**
@@ -133,7 +133,7 @@ extern ssize_t dvb_ringbuffer_write(struct dvb_ringbuffer *rbuf, const u8 *buf,
* returns Number of bytes written, or -EFAULT, -ENOMEM, -EVINAL.
*/
extern ssize_t dvb_ringbuffer_pkt_write(struct dvb_ringbuffer *rbuf, u8* buf,
- size_t len);
+ size_t len);
/**
* Read from a packet in the ringbuffer. Note: unlike dvb_ringbuffer_read(), this
@@ -149,7 +149,7 @@ extern ssize_t dvb_ringbuffer_pkt_write(struct dvb_ringbuffer *rbuf, u8* buf,
* returns Number of bytes read, or -EFAULT.
*/
extern ssize_t dvb_ringbuffer_pkt_read(struct dvb_ringbuffer *rbuf, size_t idx,
- int offset, u8* buf, size_t len, int usermem);
+ int offset, u8* buf, size_t len, int usermem);
/**
* Dispose of a packet in the ring buffer.
diff --git a/drivers/media/dvb/dvb-core/dvbdev.c b/drivers/media/dvb/dvb-core/dvbdev.c
index a4aee8665854..06b696e9acbd 100644
--- a/drivers/media/dvb/dvb-core/dvbdev.c
+++ b/drivers/media/dvb/dvb-core/dvbdev.c
@@ -92,10 +92,10 @@ static int dvb_device_open(struct inode *inode, struct file *file)
old_fops = file->f_op;
file->f_op = fops_get(dvbdev->fops);
if(file->f_op->open)
- err = file->f_op->open(inode,file);
+ err = file->f_op->open(inode,file);
if (err) {
- fops_put(file->f_op);
- file->f_op = fops_get(old_fops);
+ fops_put(file->f_op);
+ file->f_op = fops_get(old_fops);
}
fops_put(old_fops);
return err;
@@ -356,18 +356,18 @@ int dvb_usercopy(struct inode *inode, struct file *file,
case _IOC_WRITE:
case (_IOC_WRITE | _IOC_READ):
if (_IOC_SIZE(cmd) <= sizeof(sbuf)) {
- parg = sbuf;
+ parg = sbuf;
} else {
- /* too big to allocate from stack */
- mbuf = kmalloc(_IOC_SIZE(cmd),GFP_KERNEL);
- if (NULL == mbuf)
- return -ENOMEM;
- parg = mbuf;
+ /* too big to allocate from stack */
+ mbuf = kmalloc(_IOC_SIZE(cmd),GFP_KERNEL);
+ if (NULL == mbuf)
+ return -ENOMEM;
+ parg = mbuf;
}
err = -EFAULT;
if (copy_from_user(parg, (void __user *)arg, _IOC_SIZE(cmd)))
- goto out;
+ goto out;
break;
}
@@ -384,7 +384,7 @@ int dvb_usercopy(struct inode *inode, struct file *file,
case _IOC_READ:
case (_IOC_WRITE | _IOC_READ):
if (copy_to_user((void __user *)arg, parg, _IOC_SIZE(cmd)))
- err = -EFAULT;
+ err = -EFAULT;
break;
}
diff --git a/drivers/media/dvb/dvb-core/dvbdev.h b/drivers/media/dvb/dvb-core/dvbdev.h
index 0cc6e4a0e27c..74ed5853f0fb 100644
--- a/drivers/media/dvb/dvb-core/dvbdev.h
+++ b/drivers/media/dvb/dvb-core/dvbdev.h
@@ -97,7 +97,7 @@ we simply define out own dvb_usercopy(), which will hopefully become
generic_usercopy() someday... */
extern int dvb_usercopy(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg,
+ unsigned int cmd, unsigned long arg,
int (*func)(struct inode *inode, struct file *file,
unsigned int cmd, void *arg));
diff --git a/drivers/media/dvb/dvb-usb/Kconfig b/drivers/media/dvb/dvb-usb/Kconfig
index 54e2b29076b1..90a69d343b79 100644
--- a/drivers/media/dvb/dvb-usb/Kconfig
+++ b/drivers/media/dvb/dvb-usb/Kconfig
@@ -37,16 +37,16 @@ config DVB_USB_DIBUSB_MB
DiBcom (<http://www.dibcom.fr>) equipped with a DiB3000M-B demodulator.
Devices supported by this driver:
- TwinhanDTV USB-Ter (VP7041)
- TwinhanDTV Magic Box (VP7041e)
- KWorld/JetWay/ADSTech V-Stream XPERT DTV - DVB-T USB1.1 and USB2.0
- Hama DVB-T USB1.1-Box
- DiBcom USB1.1 reference devices (non-public)
- Ultima Electronic/Artec T1 USB TVBOX
+ Artec T1 USB1.1 boxes
+ Avermedia AverTV DVBT USB1.1
Compro Videomate DVB-U2000 - DVB-T USB
+ DiBcom USB1.1 reference devices (non-public)
Grandtec DVB-T USB
- Avermedia AverTV DVBT USB1.1
- Artec T1 USB1.1 boxes
+ Hama DVB-T USB1.1-Box
+ KWorld/JetWay/ADSTech V-Stream XPERT DTV - DVB-T USB1.1 and USB2.0
+ TwinhanDTV Magic Box (VP7041e)
+ TwinhanDTV USB-Ter (VP7041)
+ Ultima Electronic/Artec T1 USB TVBOX
The VP7041 seems to be identical to "CTS Portable" (Chinese
Television System).
@@ -54,6 +54,12 @@ config DVB_USB_DIBUSB_MB
Say Y if you own such a device and want to use it. You should build it as
a module.
+config DVB_USB_DIBUSB_MB_FAULTY
+ bool "Support faulty USB IDs"
+ depends on DVB_USB_DIBUSB_MB
+ help
+ Support for faulty USB IDs due to an invalid EEPROM on some Artec devices.
+
config DVB_USB_DIBUSB_MC
tristate "DiBcom USB DVB-T devices (based on the DiB3000M-C/P) (see help for device list)"
depends on DVB_USB
@@ -63,8 +69,8 @@ config DVB_USB_DIBUSB_MC
DiBcom (<http://www.dibcom.fr>) equipped with a DiB3000M-C/P demodulator.
Devices supported by this driver:
- DiBcom USB2.0 reference devices (non-public)
Artec T1 USB2.0 boxes
+ DiBcom USB2.0 reference devices (non-public)
Say Y if you own such a device and want to use it. You should build it as
a module.
diff --git a/drivers/media/dvb/dvb-usb/cxusb.c b/drivers/media/dvb/dvb-usb/cxusb.c
index d05fab01cccd..358ed153865f 100644
--- a/drivers/media/dvb/dvb-usb/cxusb.c
+++ b/drivers/media/dvb/dvb-usb/cxusb.c
@@ -11,10 +11,11 @@
* design, so it can be reused for the "analogue-only" device (if it will
* appear at all).
*
- * TODO: check if the cx25840-driver (from ivtv) can be used for the analogue
- * part
+ * TODO: Use the cx25840-driver for the analogue part
*
* Copyright (C) 2005 Patrick Boettcher (patrick.boettcher@desy.de)
+ * Copyright (C) 2005 Michael Krufky (mkrufky@m1k.net)
+ * Copyright (C) 2006 Chris Pascoe (c.pascoe@itee.uq.edu.au)
*
* 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
@@ -25,6 +26,9 @@
#include "cxusb.h"
#include "cx22702.h"
+#include "lgdt330x.h"
+#include "mt352.h"
+#include "mt352_priv.h"
/* debug */
int dvb_usb_cxusb_debug;
@@ -156,6 +160,99 @@ static int cxusb_streaming_ctrl(struct dvb_usb_device *d, int onoff)
return 0;
}
+static int cxusb_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
+{
+ struct dvb_usb_rc_key *keymap = d->props.rc_key_map;
+ u8 ircode[4];
+ int i;
+
+ cxusb_ctrl_msg(d, CMD_GET_IR_CODE, NULL, 0, ircode, 4);
+
+ *event = 0;
+ *state = REMOTE_NO_KEY_PRESSED;
+
+ for (i = 0; i < d->props.rc_key_map_size; i++) {
+ if (keymap[i].custom == ircode[2] &&
+ keymap[i].data == ircode[3]) {
+ *event = keymap[i].event;
+ *state = REMOTE_KEY_PRESSED;
+
+ return 0;
+ }
+ }
+
+ return 0;
+}
+
+struct dvb_usb_rc_key dvico_mce_rc_keys[] = {
+ { 0xfe, 0x02, KEY_TV },
+ { 0xfe, 0x0e, KEY_MP3 },
+ { 0xfe, 0x1a, KEY_DVD },
+ { 0xfe, 0x1e, KEY_FAVORITES },
+ { 0xfe, 0x16, KEY_SETUP },
+ { 0xfe, 0x46, KEY_POWER2 },
+ { 0xfe, 0x0a, KEY_EPG },
+ { 0xfe, 0x49, KEY_BACK },
+ { 0xfe, 0x4d, KEY_MENU },
+ { 0xfe, 0x51, KEY_UP },
+ { 0xfe, 0x5b, KEY_LEFT },
+ { 0xfe, 0x5f, KEY_RIGHT },
+ { 0xfe, 0x53, KEY_DOWN },
+ { 0xfe, 0x5e, KEY_OK },
+ { 0xfe, 0x59, KEY_INFO },
+ { 0xfe, 0x55, KEY_TAB },
+ { 0xfe, 0x0f, KEY_PREVIOUSSONG },/* Replay */
+ { 0xfe, 0x12, KEY_NEXTSONG }, /* Skip */
+ { 0xfe, 0x42, KEY_ENTER }, /* Windows/Start */
+ { 0xfe, 0x15, KEY_VOLUMEUP },
+ { 0xfe, 0x05, KEY_VOLUMEDOWN },
+ { 0xfe, 0x11, KEY_CHANNELUP },
+ { 0xfe, 0x09, KEY_CHANNELDOWN },
+ { 0xfe, 0x52, KEY_CAMERA },
+ { 0xfe, 0x5a, KEY_TUNER }, /* Live */
+ { 0xfe, 0x19, KEY_OPEN },
+ { 0xfe, 0x0b, KEY_1 },
+ { 0xfe, 0x17, KEY_2 },
+ { 0xfe, 0x1b, KEY_3 },
+ { 0xfe, 0x07, KEY_4 },
+ { 0xfe, 0x50, KEY_5 },
+ { 0xfe, 0x54, KEY_6 },
+ { 0xfe, 0x48, KEY_7 },
+ { 0xfe, 0x4c, KEY_8 },
+ { 0xfe, 0x58, KEY_9 },
+ { 0xfe, 0x13, KEY_ANGLE }, /* Aspect */
+ { 0xfe, 0x03, KEY_0 },
+ { 0xfe, 0x1f, KEY_ZOOM },
+ { 0xfe, 0x43, KEY_REWIND },
+ { 0xfe, 0x47, KEY_PLAYPAUSE },
+ { 0xfe, 0x4f, KEY_FASTFORWARD },
+ { 0xfe, 0x57, KEY_MUTE },
+ { 0xfe, 0x0d, KEY_STOP },
+ { 0xfe, 0x01, KEY_RECORD },
+ { 0xfe, 0x4e, KEY_POWER },
+};
+
+static int cxusb_dee1601_demod_init(struct dvb_frontend* fe)
+{
+ static u8 clock_config [] = { CLOCK_CTL, 0x38, 0x38 };
+ static u8 reset [] = { RESET, 0x80 };
+ static u8 adc_ctl_1_cfg [] = { ADC_CTL_1, 0x40 };
+ static u8 agc_cfg [] = { AGC_TARGET, 0x28, 0x20 };
+ static u8 gpp_ctl_cfg [] = { GPP_CTL, 0x33 };
+ static u8 capt_range_cfg[] = { CAPT_RANGE, 0x32 };
+
+ mt352_write(fe, clock_config, sizeof(clock_config));
+ udelay(200);
+ mt352_write(fe, reset, sizeof(reset));
+ mt352_write(fe, adc_ctl_1_cfg, sizeof(adc_ctl_1_cfg));
+
+ mt352_write(fe, agc_cfg, sizeof(agc_cfg));
+ mt352_write(fe, gpp_ctl_cfg, sizeof(gpp_ctl_cfg));
+ mt352_write(fe, capt_range_cfg, sizeof(capt_range_cfg));
+
+ return 0;
+}
+
struct cx22702_config cxusb_cx22702_config = {
.demod_address = 0x63,
@@ -165,17 +262,47 @@ struct cx22702_config cxusb_cx22702_config = {
.pll_set = dvb_usb_pll_set_i2c,
};
+struct lgdt330x_config cxusb_lgdt330x_config = {
+ .demod_address = 0x0e,
+ .demod_chip = LGDT3303,
+ .pll_set = dvb_usb_pll_set_i2c,
+};
+
+struct mt352_config cxusb_dee1601_config = {
+ .demod_address = 0x0f,
+ .demod_init = cxusb_dee1601_demod_init,
+ .pll_set = dvb_usb_pll_set,
+};
+
/* Callbacks for DVB USB */
-static int cxusb_tuner_attach(struct dvb_usb_device *d)
+static int cxusb_fmd1216me_tuner_attach(struct dvb_usb_device *d)
{
u8 bpll[4] = { 0x0b, 0xdc, 0x9c, 0xa0 };
d->pll_addr = 0x61;
- memcpy(d->pll_init,bpll,4);
+ memcpy(d->pll_init, bpll, 4);
d->pll_desc = &dvb_pll_fmd1216me;
return 0;
}
-static int cxusb_frontend_attach(struct dvb_usb_device *d)
+static int cxusb_lgh064f_tuner_attach(struct dvb_usb_device *d)
+{
+ u8 bpll[4] = { 0x00, 0x00, 0x18, 0x50 };
+ /* bpll[2] : unset bit 3, set bits 4&5
+ bpll[3] : 0x50 - digital, 0x20 - analog */
+ d->pll_addr = 0x61;
+ memcpy(d->pll_init, bpll, 4);
+ d->pll_desc = &dvb_pll_tdvs_tua6034;
+ return 0;
+}
+
+static int cxusb_dee1601_tuner_attach(struct dvb_usb_device *d)
+{
+ d->pll_addr = 0x61;
+ d->pll_desc = &dvb_pll_thomson_dtt7579;
+ return 0;
+}
+
+static int cxusb_cx22702_frontend_attach(struct dvb_usb_device *d)
{
u8 b;
if (usb_set_interface(d->udev,0,6) < 0)
@@ -189,22 +316,84 @@ static int cxusb_frontend_attach(struct dvb_usb_device *d)
return -EIO;
}
+static int cxusb_lgdt330x_frontend_attach(struct dvb_usb_device *d)
+{
+ if (usb_set_interface(d->udev,0,7) < 0)
+ err("set interface failed");
+
+ cxusb_ctrl_msg(d,CMD_DIGITAL, NULL, 0, NULL, 0);
+
+ if ((d->fe = lgdt330x_attach(&cxusb_lgdt330x_config, &d->i2c_adap)) != NULL)
+ return 0;
+
+ return -EIO;
+}
+
+static int cxusb_dee1601_frontend_attach(struct dvb_usb_device *d)
+{
+ if (usb_set_interface(d->udev,0,0) < 0)
+ err("set interface failed");
+
+ cxusb_ctrl_msg(d,CMD_DIGITAL, NULL, 0, NULL, 0);
+
+ if ((d->fe = mt352_attach(&cxusb_dee1601_config, &d->i2c_adap)) != NULL)
+ return 0;
+
+ return -EIO;
+}
+
+/*
+ * DViCO bluebird firmware needs the "warm" product ID to be patched into the
+ * firmware file before download.
+ */
+
+#define BLUEBIRD_01_ID_OFFSET 6638
+static int bluebird_patch_dvico_firmware_download(struct usb_device *udev, const struct firmware *fw)
+{
+ if (fw->size < BLUEBIRD_01_ID_OFFSET + 4)
+ return -EINVAL;
+
+ if (fw->data[BLUEBIRD_01_ID_OFFSET] == (USB_VID_DVICO & 0xff) &&
+ fw->data[BLUEBIRD_01_ID_OFFSET + 1] == USB_VID_DVICO >> 8) {
+
+ /* FIXME: are we allowed to change the fw-data ? */
+ fw->data[BLUEBIRD_01_ID_OFFSET + 2] = udev->descriptor.idProduct + 1;
+ fw->data[BLUEBIRD_01_ID_OFFSET + 3] = udev->descriptor.idProduct >> 8;
+
+ return usb_cypress_load_firmware(udev,fw,CYPRESS_FX2);
+ }
+
+ return -EINVAL;
+}
+
/* DVB USB Driver stuff */
-static struct dvb_usb_properties cxusb_properties;
+static struct dvb_usb_properties cxusb_medion_properties;
+static struct dvb_usb_properties cxusb_bluebird_lgh064f_properties;
+static struct dvb_usb_properties cxusb_bluebird_dee1601_properties;
static int cxusb_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
- return dvb_usb_device_init(intf,&cxusb_properties,THIS_MODULE,NULL);
+ if (dvb_usb_device_init(intf,&cxusb_medion_properties,THIS_MODULE,NULL) == 0 ||
+ dvb_usb_device_init(intf,&cxusb_bluebird_lgh064f_properties,THIS_MODULE,NULL) == 0 ||
+ dvb_usb_device_init(intf,&cxusb_bluebird_dee1601_properties,THIS_MODULE,NULL) == 0) {
+ return 0;
+ }
+
+ return -EINVAL;
}
static struct usb_device_id cxusb_table [] = {
{ USB_DEVICE(USB_VID_MEDION, USB_PID_MEDION_MD95700) },
+ { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_LG064F_COLD) },
+ { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_LG064F_WARM) },
+ { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DEE1601_COLD) },
+ { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DEE1601_WARM) },
{} /* Terminating entry */
};
MODULE_DEVICE_TABLE (usb, cxusb_table);
-static struct dvb_usb_properties cxusb_properties = {
+static struct dvb_usb_properties cxusb_medion_properties = {
.caps = DVB_USB_IS_AN_I2C_ADAPTER,
.usb_ctrl = CYPRESS_FX2,
@@ -213,8 +402,8 @@ static struct dvb_usb_properties cxusb_properties = {
.streaming_ctrl = cxusb_streaming_ctrl,
.power_ctrl = cxusb_power_ctrl,
- .frontend_attach = cxusb_frontend_attach,
- .tuner_attach = cxusb_tuner_attach,
+ .frontend_attach = cxusb_cx22702_frontend_attach,
+ .tuner_attach = cxusb_fmd1216me_tuner_attach,
.i2c_algo = &cxusb_i2c_algo,
@@ -240,6 +429,91 @@ static struct dvb_usb_properties cxusb_properties = {
}
};
+static struct dvb_usb_properties cxusb_bluebird_lgh064f_properties = {
+ .caps = DVB_USB_IS_AN_I2C_ADAPTER,
+
+ .usb_ctrl = DEVICE_SPECIFIC,
+ .firmware = "dvb-usb-bluebird-01.fw",
+ .download_firmware = bluebird_patch_dvico_firmware_download,
+ /* use usb alt setting 0 for EP4 transfer (dvb-t),
+ use usb alt setting 7 for EP2 transfer (atsc) */
+
+ .size_of_priv = sizeof(struct cxusb_state),
+
+ .streaming_ctrl = cxusb_streaming_ctrl,
+ .power_ctrl = cxusb_power_ctrl,
+ .frontend_attach = cxusb_lgdt330x_frontend_attach,
+ .tuner_attach = cxusb_lgh064f_tuner_attach,
+
+ .i2c_algo = &cxusb_i2c_algo,
+
+ .generic_bulk_ctrl_endpoint = 0x01,
+ /* parameter for the MPEG2-data transfer */
+ .urb = {
+ .type = DVB_USB_BULK,
+ .count = 5,
+ .endpoint = 0x02,
+ .u = {
+ .bulk = {
+ .buffersize = 8192,
+ }
+ }
+ },
+
+ .num_device_descs = 1,
+ .devices = {
+ { "DViCO FusionHDTV5 USB Gold",
+ { &cxusb_table[1], NULL },
+ { &cxusb_table[2], NULL },
+ },
+ }
+};
+
+static struct dvb_usb_properties cxusb_bluebird_dee1601_properties = {
+ .caps = DVB_USB_IS_AN_I2C_ADAPTER,
+
+ .usb_ctrl = DEVICE_SPECIFIC,
+ .firmware = "dvb-usb-bluebird-01.fw",
+ .download_firmware = bluebird_patch_dvico_firmware_download,
+ /* use usb alt setting 0 for EP4 transfer (dvb-t),
+ use usb alt setting 7 for EP2 transfer (atsc) */
+
+ .size_of_priv = sizeof(struct cxusb_state),
+
+ .streaming_ctrl = cxusb_streaming_ctrl,
+ .power_ctrl = cxusb_power_ctrl,
+ .frontend_attach = cxusb_dee1601_frontend_attach,
+ .tuner_attach = cxusb_dee1601_tuner_attach,
+
+ .i2c_algo = &cxusb_i2c_algo,
+
+ .rc_interval = 150,
+ .rc_key_map = dvico_mce_rc_keys,
+ .rc_key_map_size = ARRAY_SIZE(dvico_mce_rc_keys),
+ .rc_query = cxusb_rc_query,
+
+ .generic_bulk_ctrl_endpoint = 0x01,
+ /* parameter for the MPEG2-data transfer */
+ .urb = {
+ .type = DVB_USB_BULK,
+ .count = 5,
+ .endpoint = 0x04,
+ .u = {
+ .bulk = {
+ .buffersize = 8192,
+ }
+ }
+ },
+
+ .num_device_descs = 1,
+ .devices = {
+ { "DViCO FusionHDTV DVB-T Dual USB",
+ { &cxusb_table[3], NULL },
+ { &cxusb_table[4], NULL },
+ },
+ }
+};
+
static struct usb_driver cxusb_driver = {
.name = "dvb_usb_cxusb",
.probe = cxusb_probe,
diff --git a/drivers/media/dvb/dvb-usb/cxusb.h b/drivers/media/dvb/dvb-usb/cxusb.h
index 135c2a81f581..087c99427853 100644
--- a/drivers/media/dvb/dvb-usb/cxusb.h
+++ b/drivers/media/dvb/dvb-usb/cxusb.h
@@ -21,6 +21,8 @@ extern int dvb_usb_cxusb_debug;
#define CMD_STREAMING_ON 0x36
#define CMD_STREAMING_OFF 0x37
+#define CMD_GET_IR_CODE 0x47
+
#define CMD_ANALOG 0x50
#define CMD_DIGITAL 0x51
diff --git a/drivers/media/dvb/dvb-usb/dibusb-mb.c b/drivers/media/dvb/dvb-usb/dibusb-mb.c
index 52ac3e5adf5d..dd5a13195886 100644
--- a/drivers/media/dvb/dvb-usb/dibusb-mb.c
+++ b/drivers/media/dvb/dvb-usb/dibusb-mb.c
@@ -65,11 +65,11 @@ static int dibusb_tuner_probe_and_attach(struct dvb_usb_device *d)
d->tuner_pass_ctrl(d->fe,0,msg[0].addr);
if (b2[0] == 0xfe) {
- info("this device has the Thomson Cable onboard. Which is default.");
+ info("This device has the Thomson Cable onboard. Which is default.");
dibusb_thomson_tuner_attach(d);
} else {
u8 bpll[4] = { 0x0b, 0xf5, 0x85, 0xab };
- info("this device has the Panasonic ENV77H11D5 onboard.");
+ info("This device has the Panasonic ENV77H11D5 onboard.");
d->pll_addr = 0x60;
memcpy(d->pll_init,bpll,4);
d->pll_desc = &dvb_pll_tda665x;
@@ -98,15 +98,15 @@ static int dibusb_probe(struct usb_interface *intf,
/* do not change the order of the ID table */
static struct usb_device_id dibusb_dib3000mb_table [] = {
-/* 00 */ { USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_AVERMEDIA_DVBT_USB_COLD)},
-/* 01 */ { USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_AVERMEDIA_DVBT_USB_WARM)},
+/* 00 */ { USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_AVERMEDIA_DVBT_USB_COLD) },
+/* 01 */ { USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_AVERMEDIA_DVBT_USB_WARM) },
/* 02 */ { USB_DEVICE(USB_VID_COMPRO, USB_PID_COMPRO_DVBU2000_COLD) },
/* 03 */ { USB_DEVICE(USB_VID_COMPRO, USB_PID_COMPRO_DVBU2000_WARM) },
/* 04 */ { USB_DEVICE(USB_VID_COMPRO_UNK, USB_PID_COMPRO_DVBU2000_UNK_COLD) },
/* 05 */ { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_MOD3000_COLD) },
/* 06 */ { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_MOD3000_WARM) },
-/* 07 */ { USB_DEVICE(USB_VID_EMPIA, USB_PID_KWORLD_VSTREAM_COLD) },
-/* 08 */ { USB_DEVICE(USB_VID_EMPIA, USB_PID_KWORLD_VSTREAM_WARM) },
+/* 07 */ { USB_DEVICE(USB_VID_EMPIA, USB_PID_KWORLD_VSTREAM_COLD) },
+/* 08 */ { USB_DEVICE(USB_VID_EMPIA, USB_PID_KWORLD_VSTREAM_WARM) },
/* 09 */ { USB_DEVICE(USB_VID_GRANDTEC, USB_PID_GRANDTEC_DVBT_USB_COLD) },
/* 10 */ { USB_DEVICE(USB_VID_GRANDTEC, USB_PID_GRANDTEC_DVBT_USB_WARM) },
/* 11 */ { USB_DEVICE(USB_VID_GRANDTEC, USB_PID_DIBCOM_MOD3000_COLD) },
@@ -117,27 +117,34 @@ static struct usb_device_id dibusb_dib3000mb_table [] = {
/* 16 */ { USB_DEVICE(USB_VID_VISIONPLUS, USB_PID_TWINHAN_VP7041_WARM) },
/* 17 */ { USB_DEVICE(USB_VID_TWINHAN, USB_PID_TWINHAN_VP7041_COLD) },
/* 18 */ { USB_DEVICE(USB_VID_TWINHAN, USB_PID_TWINHAN_VP7041_WARM) },
-/* 19 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_COLD) },
-/* 20 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_WARM) },
-/* 21 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_AN2235_COLD) },
-/* 22 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_AN2235_WARM) },
+/* 19 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_COLD) },
+/* 20 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_WARM) },
+/* 21 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_AN2235_COLD) },
+/* 22 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_AN2235_WARM) },
/* 23 */ { USB_DEVICE(USB_VID_ADSTECH, USB_PID_ADSTECH_USB2_COLD) },
/* device ID with default DIBUSB2_0-firmware and with the hacked firmware */
/* 24 */ { USB_DEVICE(USB_VID_ADSTECH, USB_PID_ADSTECH_USB2_WARM) },
-/* 25 */ { USB_DEVICE(USB_VID_KYE, USB_PID_KYE_DVB_T_COLD) },
-/* 26 */ { USB_DEVICE(USB_VID_KYE, USB_PID_KYE_DVB_T_WARM) },
+/* 25 */ { USB_DEVICE(USB_VID_KYE, USB_PID_KYE_DVB_T_COLD) },
+/* 26 */ { USB_DEVICE(USB_VID_KYE, USB_PID_KYE_DVB_T_WARM) },
/* 27 */ { USB_DEVICE(USB_VID_KWORLD, USB_PID_KWORLD_VSTREAM_COLD) },
-/* 28 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_USB2_COLD) },
-/* 29 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_USB2_WARM) },
+/* 28 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_USB2_COLD) },
+/* 29 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_USB2_WARM) },
-// #define DVB_USB_DIBUSB_MB_FAULTY_USB_IDs
+/*
+ * XXX: As Artec just 'forgot' to program the EEPROM on some Artec T1 devices
+ * we don't catch these faulty IDs (namely 'Cypress FX1 USB controller') that
+ * have been left on the device. If you don't have such a device but an Artec
+ * device that's supposed to work with this driver but is not detected by it,
+ * free to enable CONFIG_DVB_USB_DIBUSB_MB_FAULTY via your kernel config.
+ */
-#ifdef DVB_USB_DIBUSB_MB_FAULTY_USB_IDs
+#ifdef CONFIG_DVB_USB_DIBUSB_MB_FAULTY
/* 30 */ { USB_DEVICE(USB_VID_ANCHOR, USB_PID_ULTIMA_TVBOX_ANCHOR_COLD) },
#endif
+
{ } /* Terminating entry */
};
MODULE_DEVICE_TABLE (usb, dibusb_dib3000mb_table);
@@ -257,7 +264,7 @@ static struct dvb_usb_properties dibusb1_1_an2235_properties = {
}
},
-#ifdef DVB_USB_DIBUSB_MB_FAULTY_USB_IDs
+#ifdef CONFIG_DVB_USB_DIBUSB_MB_FAULTY
.num_device_descs = 2,
#else
.num_device_descs = 1,
@@ -267,11 +274,12 @@ static struct dvb_usb_properties dibusb1_1_an2235_properties = {
{ &dibusb_dib3000mb_table[20], NULL },
{ &dibusb_dib3000mb_table[21], NULL },
},
-#ifdef DVB_USB_DIBUSB_MB_FAULTY_USB_IDs
+#ifdef CONFIG_DVB_USB_DIBUSB_MB_FAULTY
{ "Artec T1 USB1.1 TVBOX with AN2235 (faulty USB IDs)",
{ &dibusb_dib3000mb_table[30], NULL },
{ NULL },
},
+ { NULL },
#endif
}
};
@@ -323,6 +331,7 @@ static struct dvb_usb_properties dibusb2_0b_properties = {
{ &dibusb_dib3000mb_table[27], NULL },
{ NULL }
},
+ { NULL },
}
};
@@ -369,6 +378,7 @@ static struct dvb_usb_properties artec_t1_usb2_properties = {
{ &dibusb_dib3000mb_table[28], NULL },
{ &dibusb_dib3000mb_table[29], NULL },
},
+ { NULL },
}
};
diff --git a/drivers/media/dvb/dvb-usb/digitv.c b/drivers/media/dvb/dvb-usb/digitv.c
index 450417a9e64b..e6c55c9c9417 100644
--- a/drivers/media/dvb/dvb-usb/digitv.c
+++ b/drivers/media/dvb/dvb-usb/digitv.c
@@ -32,7 +32,7 @@ static int digitv_ctrl_msg(struct dvb_usb_device *d,
sndbuf[1] = vv;
sndbuf[2] = wo ? wlen : rlen;
- if (!wo) {
+ if (wo) {
memcpy(&sndbuf[3],wbuf,wlen);
dvb_usb_generic_write(d,sndbuf,7);
} else {
diff --git a/drivers/media/dvb/dvb-usb/dtt200u.c b/drivers/media/dvb/dvb-usb/dtt200u.c
index 6e2bac873445..130ea7f21f5e 100644
--- a/drivers/media/dvb/dvb-usb/dtt200u.c
+++ b/drivers/media/dvb/dvb-usb/dtt200u.c
@@ -151,7 +151,7 @@ static struct dvb_usb_properties dtt200u_properties = {
.cold_ids = { &dtt200u_usb_table[0], NULL },
.warm_ids = { &dtt200u_usb_table[1], NULL },
},
- { NULL },
+ { 0 },
}
};
@@ -160,7 +160,7 @@ static struct dvb_usb_properties wt220u_properties = {
.pid_filter_count = 15,
.usb_ctrl = CYPRESS_FX2,
- .firmware = "dvb-usb-wt220u-01.fw",
+ .firmware = "dvb-usb-wt220u-02.fw",
.power_ctrl = dtt200u_power_ctrl,
.streaming_ctrl = dtt200u_streaming_ctrl,
@@ -192,7 +192,7 @@ static struct dvb_usb_properties wt220u_properties = {
.cold_ids = { &dtt200u_usb_table[2], NULL },
.warm_ids = { &dtt200u_usb_table[3], NULL },
},
- { NULL },
+ { 0 },
}
};
diff --git a/drivers/media/dvb/dvb-usb/dtt200u.h b/drivers/media/dvb/dvb-usb/dtt200u.h
index 6f1f3042e21a..005b0a7df358 100644
--- a/drivers/media/dvb/dvb-usb/dtt200u.h
+++ b/drivers/media/dvb/dvb-usb/dtt200u.h
@@ -13,6 +13,7 @@
#define _DVB_USB_DTT200U_H_
#define DVB_USB_LOG_PREFIX "dtt200u"
+
#include "dvb-usb.h"
extern int dvb_usb_dtt200u_debug;
@@ -25,15 +26,15 @@ extern int dvb_usb_dtt200u_debug;
* 88 - locking 2 bytes (0x80 0x40 == no signal, 0x89 0x20 == nice signal)
*/
-#define GET_SPEED 0x00
-#define GET_TUNE_STATUS 0x81
-#define GET_RC_CODE 0x84
-#define GET_CONFIGURATION 0x88
-#define GET_AGC 0x89
-#define GET_SNR 0x8a
-#define GET_VIT_ERR_CNT 0x8c
-#define GET_RS_ERR_CNT 0x8d
-#define GET_RS_UNCOR_BLK_CNT 0x8e
+#define GET_SPEED 0x00
+#define GET_TUNE_STATUS 0x81
+#define GET_RC_CODE 0x84
+#define GET_CONFIGURATION 0x88
+#define GET_AGC 0x89
+#define GET_SNR 0x8a
+#define GET_VIT_ERR_CNT 0x8c
+#define GET_RS_ERR_CNT 0x8d
+#define GET_RS_UNCOR_BLK_CNT 0x8e
/* write
* 01 - init
@@ -44,12 +45,12 @@ extern int dvb_usb_dtt200u_debug;
* 08 - transfer switch
*/
-#define SET_INIT 0x01
-#define SET_RF_FREQ 0x02
-#define SET_BANDWIDTH 0x03
-#define SET_PID_FILTER 0x04
-#define RESET_PID_FILTER 0x05
-#define SET_STREAMING 0x08
+#define SET_INIT 0x01
+#define SET_RF_FREQ 0x02
+#define SET_BANDWIDTH 0x03
+#define SET_PID_FILTER 0x04
+#define RESET_PID_FILTER 0x05
+#define SET_STREAMING 0x08
extern struct dvb_frontend * dtt200u_fe_attach(struct dvb_usb_device *d);
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-common.h b/drivers/media/dvb/dvb-usb/dvb-usb-common.h
index 7300489d3e24..a3460bf2d9fa 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb-common.h
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-common.h
@@ -24,7 +24,7 @@ extern int dvb_usb_disable_rc_polling;
#define deb_mem(args...) dprintk(dvb_usb_debug,0x80,args)
/* commonly used methods */
-extern int usb_cypress_load_firmware(struct usb_device *, const char *, int);
+extern int dvb_usb_download_firmware(struct usb_device *, struct dvb_usb_properties *);
extern int dvb_usb_urb_submit(struct dvb_usb_device *);
extern int dvb_usb_urb_kill(struct dvb_usb_device *);
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-firmware.c b/drivers/media/dvb/dvb-usb/dvb-usb-firmware.c
index 5244e39770a0..8535895819fb 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb-firmware.c
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-firmware.c
@@ -9,7 +9,6 @@
*/
#include "dvb-usb-common.h"
-#include <linux/firmware.h>
#include <linux/usb.h>
struct usb_cypress_controller {
@@ -19,9 +18,10 @@ struct usb_cypress_controller {
};
static struct usb_cypress_controller cypress[] = {
- { .id = CYPRESS_AN2135, .name = "Cypress AN2135", .cpu_cs_register = 0x7f92 },
- { .id = CYPRESS_AN2235, .name = "Cypress AN2235", .cpu_cs_register = 0x7f92 },
- { .id = CYPRESS_FX2, .name = "Cypress FX2", .cpu_cs_register = 0xe600 },
+ { .id = DEVICE_SPECIFIC, .name = "Device specific", .cpu_cs_register = 0 },
+ { .id = CYPRESS_AN2135, .name = "Cypress AN2135", .cpu_cs_register = 0x7f92 },
+ { .id = CYPRESS_AN2235, .name = "Cypress AN2235", .cpu_cs_register = 0x7f92 },
+ { .id = CYPRESS_FX2, .name = "Cypress FX2", .cpu_cs_register = 0xe600 },
};
/*
@@ -30,71 +30,117 @@ static struct usb_cypress_controller cypress[] = {
static int usb_cypress_writemem(struct usb_device *udev,u16 addr,u8 *data, u8 len)
{
return usb_control_msg(udev, usb_sndctrlpipe(udev,0),
- 0xa0, USB_TYPE_VENDOR, addr, 0x00, data, len, 5*HZ);
+ 0xa0, USB_TYPE_VENDOR, addr, 0x00, data, len, 5000);
}
-int usb_cypress_load_firmware(struct usb_device *udev, const char *filename, int type)
+int usb_cypress_load_firmware(struct usb_device *udev, const struct firmware *fw, int type)
{
- const struct firmware *fw = NULL;
- u16 addr;
- u8 *b,*p;
- int ret = 0,i;
+ struct hexline hx;
+ u8 reset;
+ int ret,pos=0;
- if ((ret = request_firmware(&fw, filename, &udev->dev)) != 0) {
- err("did not find the firmware file. (%s) "
- "Please see linux/Documentation/dvb/ for more details on firmware-problems.",
- filename);
+ /* stop the CPU */
+ reset = 1;
+ if ((ret = usb_cypress_writemem(udev,cypress[type].cpu_cs_register,&reset,1)) != 1)
+ err("could not stop the USB controller CPU.");
+
+ while ((ret = dvb_usb_get_hexline(fw,&hx,&pos)) > 0) {
+ deb_fw("writing to address 0x%04x (buffer: 0x%02x %02x)\n",hx.addr,hx.len,hx.chk);
+ ret = usb_cypress_writemem(udev,hx.addr,hx.data,hx.len);
+
+ if (ret != hx.len) {
+ err("error while transferring firmware "
+ "(transferred size: %d, block size: %d)",
+ ret,hx.len);
+ ret = -EINVAL;
+ break;
+ }
+ }
+ if (ret < 0) {
+ err("firmware download failed at %d with %d",pos,ret);
return ret;
}
- info("downloading firmware from file '%s' to the '%s'",filename,cypress[type].name);
-
- p = kmalloc(fw->size,GFP_KERNEL);
- if (p != NULL) {
- u8 reset;
- /*
- * you cannot use the fw->data as buffer for
- * usb_control_msg, a new buffer has to be
- * created
- */
- memcpy(p,fw->data,fw->size);
-
- /* stop the CPU */
- reset = 1;
- if ((ret = usb_cypress_writemem(udev,cypress[type].cpu_cs_register,&reset,1)) != 1)
- err("could not stop the USB controller CPU.");
- for(i = 0; p[i+3] == 0 && i < fw->size; ) {
- b = (u8 *) &p[i];
- addr = cpu_to_le16( *((u16 *) &b[1]) );
-
- deb_fw("writing to address 0x%04x (buffer: 0x%02x%02x)\n",addr,b[1],b[2]);
-
- ret = usb_cypress_writemem(udev,addr,&b[4],b[0]);
-
- if (ret != b[0]) {
- err("error while transferring firmware "
- "(transferred size: %d, block size: %d)",
- ret,b[0]);
- ret = -EINVAL;
- break;
- }
- i += 5 + b[0];
- }
- /* length in ret */
- if (ret > 0)
- ret = 0;
+ if (ret == 0) {
/* restart the CPU */
reset = 0;
if (ret || usb_cypress_writemem(udev,cypress[type].cpu_cs_register,&reset,1) != 1) {
err("could not restart the USB controller CPU.");
ret = -EINVAL;
}
+ } else
+ ret = -EIO;
- kfree(p);
- } else {
- ret = -ENOMEM;
+ return ret;
+}
+EXPORT_SYMBOL(usb_cypress_load_firmware);
+
+int dvb_usb_download_firmware(struct usb_device *udev, struct dvb_usb_properties *props)
+{
+ int ret;
+ const struct firmware *fw = NULL;
+
+ if ((ret = request_firmware(&fw, props->firmware, &udev->dev)) != 0) {
+ err("did not find the firmware file. (%s) "
+ "Please see linux/Documentation/dvb/ for more details on firmware-problems. (%d)",
+ props->firmware,ret);
+ return ret;
}
- release_firmware(fw);
+ info("downloading firmware from file '%s'",props->firmware);
+
+ switch (props->usb_ctrl) {
+ case CYPRESS_AN2135:
+ case CYPRESS_AN2235:
+ case CYPRESS_FX2:
+ ret = usb_cypress_load_firmware(udev, fw, props->usb_ctrl);
+ break;
+ case DEVICE_SPECIFIC:
+ if (props->download_firmware)
+ ret = props->download_firmware(udev,fw);
+ else {
+ err("BUG: driver didn't specified a download_firmware-callback, although it claims to have a DEVICE_SPECIFIC one.");
+ ret = -EINVAL;
+ }
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+ release_firmware(fw);
return ret;
}
+
+int dvb_usb_get_hexline(const struct firmware *fw, struct hexline *hx, int *pos)
+{
+ u8 *b = (u8 *) &fw->data[*pos];
+ int data_offs = 4;
+ if (*pos >= fw->size)
+ return 0;
+
+ memset(hx,0,sizeof(struct hexline));
+
+ hx->len = b[0];
+
+ if ((*pos + hx->len + 4) >= fw->size)
+ return -EINVAL;
+
+ hx->addr = le16_to_cpu( *((u16 *) &b[1]) );
+ hx->type = b[3];
+
+ if (hx->type == 0x04) {
+ /* b[4] and b[5] are the Extended linear address record data field */
+ hx->addr |= (b[4] << 24) | (b[5] << 16);
+/* hx->len -= 2;
+ data_offs += 2; */
+ }
+ memcpy(hx->data,&b[data_offs],hx->len);
+ hx->chk = b[hx->len + data_offs];
+
+ *pos += hx->len + 5;
+
+ return *pos;
+}
+EXPORT_SYMBOL(dvb_usb_get_hexline);
+
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-i2c.c b/drivers/media/dvb/dvb-usb/dvb-usb-i2c.c
index da970947dfc7..9b254532af4d 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb-i2c.c
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-i2c.c
@@ -52,9 +52,8 @@ int dvb_usb_pll_init_i2c(struct dvb_frontend *fe)
struct i2c_msg msg = { .addr = d->pll_addr, .flags = 0, .buf = d->pll_init, .len = 4 };
int ret = 0;
- /* if there is nothing to initialize */
- if (d->pll_init[0] == 0x00 && d->pll_init[1] == 0x00 &&
- d->pll_init[2] == 0x00 && d->pll_init[3] == 0x00)
+ /* if pll_desc is not used */
+ if (d->pll_desc == NULL)
return 0;
if (d->tuner_pass_ctrl)
@@ -80,6 +79,9 @@ int dvb_usb_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *fep
{
struct dvb_usb_device *d = fe->dvb->priv;
+ if (d->pll_desc == NULL)
+ return 0;
+
deb_pll("pll addr: %x, freq: %d %p\n",d->pll_addr,fep->frequency,d->pll_desc);
b[0] = d->pll_addr << 1;
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
index 6be99e537e12..d22934383226 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
@@ -86,11 +86,15 @@
#define USB_PID_WINTV_NOVA_T_USB2_COLD 0x9300
#define USB_PID_WINTV_NOVA_T_USB2_WARM 0x9301
#define USB_PID_NEBULA_DIGITV 0x0201
-#define USB_PID_DVICO_BLUEBIRD_LGZ201 0xdb00
-#define USB_PID_DVICO_BLUEBIRD_TH7579 0xdb10
#define USB_PID_DVICO_BLUEBIRD_LGDT 0xd820
-#define USB_PID_DVICO_BLUEBIRD_LGZ201_1 0xdb01
-#define USB_PID_DVICO_BLUEBIRD_TH7579_2 0xdb11
+#define USB_PID_DVICO_BLUEBIRD_LG064F_COLD 0xd500
+#define USB_PID_DVICO_BLUEBIRD_LG064F_WARM 0xd501
+#define USB_PID_DVICO_BLUEBIRD_LGZ201_COLD 0xdb00
+#define USB_PID_DVICO_BLUEBIRD_LGZ201_WARM 0xdb01
+#define USB_PID_DVICO_BLUEBIRD_TH7579_COLD 0xdb10
+#define USB_PID_DVICO_BLUEBIRD_TH7579_WARM 0xdb11
+#define USB_PID_DVICO_BLUEBIRD_DEE1601_COLD 0xdb50
+#define USB_PID_DVICO_BLUEBIRD_DEE1601_WARM 0xdb51
#define USB_PID_MEDION_MD95700 0x0932
#define USB_PID_KYE_DVB_T_COLD 0x701e
#define USB_PID_KYE_DVB_T_WARM 0x701f
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-init.c b/drivers/media/dvb/dvb-usb/dvb-usb-init.c
index dd8e0b94edba..2e23060cbbca 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb-init.c
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-init.c
@@ -138,6 +138,9 @@ int dvb_usb_device_init(struct usb_interface *intf, struct dvb_usb_properties
int ret = -ENOMEM,cold=0;
+ if (du != NULL)
+ *du = NULL;
+
if ((desc = dvb_usb_find_device(udev,props,&cold)) == NULL) {
deb_err("something went very wrong, device was not found in current device list - let's see what comes next.\n");
return -ENODEV;
@@ -145,38 +148,40 @@ int dvb_usb_device_init(struct usb_interface *intf, struct dvb_usb_properties
if (cold) {
info("found a '%s' in cold state, will try to load a firmware",desc->name);
- ret = usb_cypress_load_firmware(udev,props->firmware,props->usb_ctrl);
- } else {
- info("found a '%s' in warm state.",desc->name);
- d = kmalloc(sizeof(struct dvb_usb_device),GFP_KERNEL);
- if (d == NULL) {
- err("no memory for 'struct dvb_usb_device'");
+ ret = dvb_usb_download_firmware(udev,props);
+ if (!props->no_reconnect)
return ret;
+ }
+
+ info("found a '%s' in warm state.",desc->name);
+ d = kmalloc(sizeof(struct dvb_usb_device),GFP_KERNEL);
+ if (d == NULL) {
+ err("no memory for 'struct dvb_usb_device'");
+ return ret;
+ }
+ memset(d,0,sizeof(struct dvb_usb_device));
+
+ d->udev = udev;
+ memcpy(&d->props,props,sizeof(struct dvb_usb_properties));
+ d->desc = desc;
+ d->owner = owner;
+
+ if (d->props.size_of_priv > 0) {
+ d->priv = kmalloc(d->props.size_of_priv,GFP_KERNEL);
+ if (d->priv == NULL) {
+ err("no memory for priv in 'struct dvb_usb_device'");
+ kfree(d);
+ return -ENOMEM;
}
- memset(d,0,sizeof(struct dvb_usb_device));
-
- d->udev = udev;
- memcpy(&d->props,props,sizeof(struct dvb_usb_properties));
- d->desc = desc;
- d->owner = owner;
-
- if (d->props.size_of_priv > 0) {
- d->priv = kmalloc(d->props.size_of_priv,GFP_KERNEL);
- if (d->priv == NULL) {
- err("no memory for priv in 'struct dvb_usb_device'");
- kfree(d);
- return -ENOMEM;
- }
- memset(d->priv,0,d->props.size_of_priv);
- }
+ memset(d->priv,0,d->props.size_of_priv);
+ }
- usb_set_intfdata(intf, d);
+ usb_set_intfdata(intf, d);
- if (du != NULL)
- *du = d;
+ if (du != NULL)
+ *du = d;
- ret = dvb_usb_init(d);
- }
+ ret = dvb_usb_init(d);
if (ret == 0)
info("%s successfully initialized and connected.",desc->name);
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb.h b/drivers/media/dvb/dvb-usb/dvb-usb.h
index b4a1a98006c7..dd568396e594 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb.h
+++ b/drivers/media/dvb/dvb-usb/dvb-usb.h
@@ -10,8 +10,8 @@
#include <linux/config.h>
#include <linux/input.h>
-#include <linux/module.h>
#include <linux/usb.h>
+#include <linux/firmware.h>
#include "dvb_frontend.h"
#include "dvb_demux.h"
@@ -94,7 +94,11 @@ struct dvb_usb_device;
* @usb_ctrl: which USB device-side controller is in use. Needed for firmware
* download.
* @firmware: name of the firmware file.
- *
+ * @download_firmware: called to download the firmware when the usb_ctrl is
+ * DEVICE_SPECIFIC.
+ * @no_reconnect: device doesn't do a reconnect after downloading the firmware,
+ so do the warm initialization right after it
+
* @size_of_priv: how many bytes shall be allocated for the private field
* of struct dvb_usb_device.
*
@@ -142,11 +146,14 @@ struct dvb_usb_properties {
int caps;
int pid_filter_count;
-#define CYPRESS_AN2135 0
-#define CYPRESS_AN2235 1
-#define CYPRESS_FX2 2
+#define DEVICE_SPECIFIC 0
+#define CYPRESS_AN2135 1
+#define CYPRESS_AN2235 2
+#define CYPRESS_FX2 3
int usb_ctrl;
- const char *firmware;
+ const char firmware[FIRMWARE_NAME_MAX];
+ int (*download_firmware) (struct usb_device *, const struct firmware *);
+ int no_reconnect;
int size_of_priv;
@@ -326,5 +333,15 @@ extern int dvb_usb_pll_init_i2c(struct dvb_frontend *);
extern int dvb_usb_pll_set(struct dvb_frontend *, struct dvb_frontend_parameters *, u8[]);
extern int dvb_usb_pll_set_i2c(struct dvb_frontend *, struct dvb_frontend_parameters *);
+/* commonly used firmware download types and function */
+struct hexline {
+ u8 len;
+ u32 addr;
+ u8 type;
+ u8 data[255];
+ u8 chk;
+};
+extern int dvb_usb_get_hexline(const struct firmware *, struct hexline *, int *);
+extern int usb_cypress_load_firmware(struct usb_device *udev, const struct firmware *fw, int type);
#endif
diff --git a/drivers/media/dvb/dvb-usb/nova-t-usb2.c b/drivers/media/dvb/dvb-usb/nova-t-usb2.c
index fac48fc7a4ac..412039d8dbae 100644
--- a/drivers/media/dvb/dvb-usb/nova-t-usb2.c
+++ b/drivers/media/dvb/dvb-usb/nova-t-usb2.c
@@ -129,10 +129,6 @@ static int nova_t_read_mac_address (struct dvb_usb_device *d, u8 mac[6])
dibusb_read_eeprom_byte(d,i, &b);
mac[5 - (i - 136)] = b;
-
-/* deb_ee("%02x ",b);
- if ((i+1) % 16 == 0)
- deb_ee("\n");*/
}
return 0;
@@ -153,7 +149,7 @@ static struct usb_device_id nova_t_table [] = {
/* 01 */ { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_WINTV_NOVA_T_USB2_WARM) },
{ } /* Terminating entry */
};
-MODULE_DEVICE_TABLE (usb, nova_t_table);
+MODULE_DEVICE_TABLE(usb, nova_t_table);
static struct dvb_usb_properties nova_t_properties = {
.caps = DVB_USB_HAS_PID_FILTER | DVB_USB_PID_FILTER_CAN_BE_TURNED_OFF | DVB_USB_IS_AN_I2C_ADAPTER,
@@ -198,6 +194,7 @@ static struct dvb_usb_properties nova_t_properties = {
{ &nova_t_table[0], NULL },
{ &nova_t_table[1], NULL },
},
+ { NULL },
}
};
diff --git a/drivers/media/dvb/dvb-usb/vp702x-fe.c b/drivers/media/dvb/dvb-usb/vp702x-fe.c
index 104b5d016c7b..0885d9fb2bf2 100644
--- a/drivers/media/dvb/dvb-usb/vp702x-fe.c
+++ b/drivers/media/dvb/dvb-usb/vp702x-fe.c
@@ -190,7 +190,7 @@ static int vp702x_fe_get_frontend(struct dvb_frontend* fe,
}
static int vp702x_fe_send_diseqc_msg (struct dvb_frontend* fe,
- struct dvb_diseqc_master_cmd *m)
+ struct dvb_diseqc_master_cmd *m)
{
struct vp702x_fe_state *st = fe->demodulator_priv;
u8 cmd[8],ibuf[10];
diff --git a/drivers/media/dvb/dvb-usb/vp702x.h b/drivers/media/dvb/dvb-usb/vp702x.h
index 4a3e8c7eca2b..a808d48e7bf2 100644
--- a/drivers/media/dvb/dvb-usb/vp702x.h
+++ b/drivers/media/dvb/dvb-usb/vp702x.h
@@ -13,47 +13,47 @@ extern int dvb_usb_vp702x_debug;
/* commands are read and written with USB control messages */
/* consecutive read/write operation */
-#define REQUEST_OUT 0xB2
-#define REQUEST_IN 0xB3
+#define REQUEST_OUT 0xB2
+#define REQUEST_IN 0xB3
/* the out-buffer of these consecutive operations contain sub-commands when b[0] = 0
* request: 0xB2; i: 0; v: 0; b[0] = 0, b[1] = subcmd, additional buffer
* the returning buffer looks as follows
* request: 0xB3; i: 0; v: 0; b[0] = 0xB3, additional buffer */
-#define GET_TUNER_STATUS 0x05
+#define GET_TUNER_STATUS 0x05
/* additional in buffer:
* 0 1 2 3 4 5 6 7 8
* N/A N/A 0x05 signal-quality N/A N/A signal-strength lock==0 N/A */
-#define GET_SYSTEM_STRING 0x06
+#define GET_SYSTEM_STRING 0x06
/* additional in buffer:
* 0 1 2 3 4 5 6 7 8
* N/A 'U' 'S' 'B' '7' '0' '2' 'X' N/A */
-#define SET_DISEQC_CMD 0x08
+#define SET_DISEQC_CMD 0x08
/* additional out buffer:
* 0 1 2 3 4
* len X1 X2 X3 X4
* additional in buffer:
* 0 1 2
- * N/A 0 0 b[1] == b[2] == 0 -> success otherwise not */
+ * N/A 0 0 b[1] == b[2] == 0 -> success, failure otherwise */
-#define SET_LNB_POWER 0x09
+#define SET_LNB_POWER 0x09
/* additional out buffer:
* 0 1 2
* 0x00 0xff 1 = on, 0 = off
* additional in buffer:
* 0 1 2
- * N/A 0 0 b[1] == b[2] == 0 -> success otherwise not */
+ * N/A 0 0 b[1] == b[2] == 0 -> success failure otherwise */
-#define GET_MAC_ADDRESS 0x0A
+#define GET_MAC_ADDRESS 0x0A
/* #define GET_MAC_ADDRESS 0x0B */
/* additional in buffer:
* 0 1 2 3 4 5 6 7 8
* N/A N/A 0x0A or 0x0B MAC0 MAC1 MAC2 MAC3 MAC4 MAC5 */
-#define SET_PID_FILTER 0x11
+#define SET_PID_FILTER 0x11
/* additional in buffer:
* 0 1 ... 14 15 16
* PID0_MSB PID0_LSB ... PID7_MSB PID7_LSB PID_active (bits) */
@@ -64,39 +64,38 @@ extern int dvb_usb_vp702x_debug;
* freq0 freq1 divstep srate0 srate1 srate2 flag chksum
*/
-
/* one direction requests */
-#define READ_REMOTE_REQ 0xB4
+#define READ_REMOTE_REQ 0xB4
/* IN i: 0; v: 0; b[0] == request, b[1] == key */
-#define READ_PID_NUMBER_REQ 0xB5
+#define READ_PID_NUMBER_REQ 0xB5
/* IN i: 0; v: 0; b[0] == request, b[1] == 0, b[2] = pid number */
-#define WRITE_EEPROM_REQ 0xB6
+#define WRITE_EEPROM_REQ 0xB6
/* OUT i: offset; v: value to write; no extra buffer */
-#define READ_EEPROM_REQ 0xB7
+#define READ_EEPROM_REQ 0xB7
/* IN i: bufferlen; v: offset; buffer with bufferlen bytes */
-#define READ_STATUS 0xB8
+#define READ_STATUS 0xB8
/* IN i: 0; v: 0; bufferlen 10 */
-#define READ_TUNER_REG_REQ 0xB9
+#define READ_TUNER_REG_REQ 0xB9
/* IN i: 0; v: register; b[0] = value */
-#define READ_FX2_REG_REQ 0xBA
+#define READ_FX2_REG_REQ 0xBA
/* IN i: offset; v: 0; b[0] = value */
-#define WRITE_FX2_REG_REQ 0xBB
+#define WRITE_FX2_REG_REQ 0xBB
/* OUT i: offset; v: value to write; 1 byte extra buffer */
-#define SET_TUNER_POWER_REQ 0xBC
+#define SET_TUNER_POWER_REQ 0xBC
/* IN i: 0 = power off, 1 = power on */
-#define WRITE_TUNER_REG_REQ 0xBD
+#define WRITE_TUNER_REG_REQ 0xBD
/* IN i: register, v: value to write, no extra buffer */
-#define RESET_TUNER 0xBE
+#define RESET_TUNER 0xBE
/* IN i: 0, v: 0, no extra buffer */
extern struct dvb_frontend * vp702x_fe_attach(struct dvb_usb_device *d);
diff --git a/drivers/media/dvb/dvb-usb/vp7045.c b/drivers/media/dvb/dvb-usb/vp7045.c
index 3835235b68df..028204956bb0 100644
--- a/drivers/media/dvb/dvb-usb/vp7045.c
+++ b/drivers/media/dvb/dvb-usb/vp7045.c
@@ -247,7 +247,7 @@ static struct dvb_usb_properties vp7045_properties = {
.cold_ids = { &vp7045_usb_table[2], NULL },
.warm_ids = { &vp7045_usb_table[3], NULL },
},
- { NULL },
+ { 0 },
}
};
diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig
index 8e269e1c1f9d..db3a8b40031e 100644
--- a/drivers/media/dvb/frontends/Kconfig
+++ b/drivers/media/dvb/frontends/Kconfig
@@ -16,6 +16,12 @@ config DVB_CX24110
help
A DVB-S tuner module. Say Y when you want to support this frontend.
+config DVB_CX24123
+ tristate "Conexant CX24123 based"
+ depends on DVB_CORE
+ help
+ A DVB-S tuner module. Say Y when you want to support this frontend.
+
config DVB_TDA8083
tristate "Philips TDA8083 based"
depends on DVB_CORE
@@ -50,18 +56,19 @@ comment "DVB-T (terrestrial) frontends"
depends on DVB_CORE
config DVB_SP8870
- tristate "Spase sp8870 based"
+ tristate "Spase sp8870 based"
depends on DVB_CORE
select FW_LOADER
help
- A DVB-T tuner module. Say Y when you want to support this frontend.
+ A DVB-T tuner module. Say Y when you want to support this frontend.
This driver needs external firmware. Please use the command
"<kerneldir>/Documentation/dvb/get_dvb_firmware sp8870" to
- download/extract it, and then copy it to /usr/lib/hotplug/firmware.
+ download/extract it, and then copy it to /usr/lib/hotplug/firmware
+ or /lib/firmware (depending on configuration of firmware hotplug).
config DVB_SP887X
- tristate "Spase sp887x based"
+ tristate "Spase sp887x based"
depends on DVB_CORE
select FW_LOADER
help
@@ -69,7 +76,8 @@ config DVB_SP887X
This driver needs external firmware. Please use the command
"<kerneldir>/Documentation/dvb/get_dvb_firmware sp887x" to
- download/extract it, and then copy it to /usr/lib/hotplug/firmware.
+ download/extract it, and then copy it to /usr/lib/hotplug/firmware
+ or /lib/firmware (depending on configuration of firmware hotplug).
config DVB_CX22700
tristate "Conexant CX22700 based"
@@ -78,10 +86,10 @@ config DVB_CX22700
A DVB-T tuner module. Say Y when you want to support this frontend.
config DVB_CX22702
- tristate "Conexant cx22702 demodulator (OFDM)"
- depends on DVB_CORE
- help
- A DVB-T tuner module. Say Y when you want to support this frontend.
+ tristate "Conexant cx22702 demodulator (OFDM)"
+ depends on DVB_CORE
+ help
+ A DVB-T tuner module. Say Y when you want to support this frontend.
config DVB_L64781
tristate "LSI L64781"
@@ -98,8 +106,9 @@ config DVB_TDA1004X
This driver needs external firmware. Please use the commands
"<kerneldir>/Documentation/dvb/get_dvb_firmware tda10045",
- "<kerneldir>/Documentation/dvb/get_dvb_firmware tda10046" to
- download/extract them, and then copy them to /usr/lib/hotplug/firmware.
+ "<kerneldir>/Documentation/dvb/get_dvb_firmware tda10046" to
+ download/extract them, and then copy them to /usr/lib/hotplug/firmware
+ or /lib/firmware (depending on configuration of firmware hotplug).
config DVB_NXT6000
tristate "NxtWave Communications NXT6000 based"
@@ -140,13 +149,13 @@ config DVB_VES1820
tristate "VLSI VES1820 based"
depends on DVB_CORE
help
- A DVB-C tuner module. Say Y when you want to support this frontend.
+ A DVB-C tuner module. Say Y when you want to support this frontend.
config DVB_TDA10021
tristate "Philips TDA10021 based"
depends on DVB_CORE
help
- A DVB-C tuner module. Say Y when you want to support this frontend.
+ A DVB-C tuner module. Say Y when you want to support this frontend.
config DVB_STV0297
tristate "ST STV0297 based"
@@ -164,6 +173,11 @@ config DVB_NXT2002
help
An ATSC 8VSB tuner module. Say Y when you want to support this frontend.
+ This driver needs external firmware. Please use the command
+ "<kerneldir>/Documentation/dvb/get_dvb_firmware nxt2002" to
+ download/extract it, and then copy it to /usr/lib/hotplug/firmware
+ or /lib/firmware (depending on configuration of firmware hotplug).
+
config DVB_NXT200X
tristate "Nextwave NXT2002/NXT2004 based"
depends on DVB_CORE
@@ -172,6 +186,12 @@ config DVB_NXT200X
An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want
to support this frontend.
+ This driver needs external firmware. Please use the commands
+ "<kerneldir>/Documentation/dvb/get_dvb_firmware nxt2002" and
+ "<kerneldir>/Documentation/dvb/get_dvb_firmware nxt2004" to
+ download/extract them, and then copy them to /usr/lib/hotplug/firmware
+ or /lib/firmware (depending on configuration of firmware hotplug).
+
config DVB_OR51211
tristate "or51211 based (pcHDTV HD2000 card)"
depends on DVB_CORE
diff --git a/drivers/media/dvb/frontends/Makefile b/drivers/media/dvb/frontends/Makefile
index a98760fe08a1..615ec830e1c9 100644
--- a/drivers/media/dvb/frontends/Makefile
+++ b/drivers/media/dvb/frontends/Makefile
@@ -32,3 +32,4 @@ obj-$(CONFIG_DVB_OR51132) += or51132.o
obj-$(CONFIG_DVB_BCM3510) += bcm3510.o
obj-$(CONFIG_DVB_S5H1420) += s5h1420.o
obj-$(CONFIG_DVB_LGDT330X) += lgdt330x.o
+obj-$(CONFIG_DVB_CX24123) += cx24123.o
diff --git a/drivers/media/dvb/frontends/bcm3510.c b/drivers/media/dvb/frontends/bcm3510.c
index 8ceb9a33c7af..3b132bafd4de 100644
--- a/drivers/media/dvb/frontends/bcm3510.c
+++ b/drivers/media/dvb/frontends/bcm3510.c
@@ -255,7 +255,7 @@ static int bcm3510_bert_reset(struct bcm3510_state *st)
bcm3510_register_value b;
int ret;
- if ((ret < bcm3510_readB(st,0xfa,&b)) < 0)
+ if ((ret = bcm3510_readB(st,0xfa,&b)) < 0)
return ret;
b.BERCTL_fa.RESYNC = 0; bcm3510_writeB(st,0xfa,b);
@@ -623,13 +623,13 @@ static int bcm3510_download_firmware(struct dvb_frontend* fe)
err("could not load firmware (%s): %d",BCM3510_DEFAULT_FIRMWARE,ret);
return ret;
}
- deb_info("got firmware: %d\n",fw->size);
+ deb_info("got firmware: %zd\n",fw->size);
b = fw->data;
for (i = 0; i < fw->size;) {
addr = le16_to_cpu( *( (u16 *)&b[i] ) );
len = le16_to_cpu( *( (u16 *)&b[i+2] ) );
- deb_info("firmware chunk, addr: 0x%04x, len: 0x%04x, total length: 0x%04x\n",addr,len,fw->size);
+ deb_info("firmware chunk, addr: 0x%04x, len: 0x%04x, total length: 0x%04zx\n",addr,len,fw->size);
if ((ret = bcm3510_write_ram(st,addr,&b[i+4],len)) < 0) {
err("firmware download failed: %d\n",ret);
return ret;
diff --git a/drivers/media/dvb/frontends/cx22702.c b/drivers/media/dvb/frontends/cx22702.c
index 5de0e6d350b1..0fc899f81c5e 100644
--- a/drivers/media/dvb/frontends/cx22702.c
+++ b/drivers/media/dvb/frontends/cx22702.c
@@ -195,6 +195,16 @@ static int cx22702_get_tps (struct cx22702_state *state, struct dvb_ofdm_paramet
return 0;
}
+static int cx22702_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
+{
+ struct cx22702_state* state = fe->demodulator_priv;
+ dprintk ("%s(%d)\n", __FUNCTION__, enable);
+ if (enable)
+ return cx22702_writereg (state, 0x0D, cx22702_readreg(state, 0x0D) & 0xfe);
+ else
+ return cx22702_writereg (state, 0x0D, cx22702_readreg(state, 0x0D) | 1);
+}
+
/* Talk to the demod, set the FEC, GUARD, QAM settings etc */
static int cx22702_set_tps (struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
{
@@ -202,7 +212,7 @@ static int cx22702_set_tps (struct dvb_frontend* fe, struct dvb_frontend_paramet
struct cx22702_state* state = fe->demodulator_priv;
/* set PLL */
- cx22702_writereg (state, 0x0D, cx22702_readreg(state,0x0D) &0xfe);
+ cx22702_i2c_gate_ctrl(fe, 1);
if (state->config->pll_set) {
state->config->pll_set(fe, p);
} else if (state->config->pll_desc) {
@@ -216,7 +226,7 @@ static int cx22702_set_tps (struct dvb_frontend* fe, struct dvb_frontend_paramet
} else {
BUG();
}
- cx22702_writereg (state, 0x0D, cx22702_readreg(state,0x0D) | 1);
+ cx22702_i2c_gate_ctrl(fe, 0);
/* set inversion */
cx22702_set_inversion (state, p->inversion);
@@ -349,11 +359,10 @@ static int cx22702_init (struct dvb_frontend* fe)
cx22702_writereg (state, 0xf8, (state->config->output_mode << 1) & 0x02);
/* init PLL */
- if (state->config->pll_init) {
- cx22702_writereg (state, 0x0D, cx22702_readreg(state,0x0D) & 0xfe);
+ if (state->config->pll_init)
state->config->pll_init(fe);
- cx22702_writereg (state, 0x0D, cx22702_readreg(state,0x0D) | 1);
- }
+
+ cx22702_i2c_gate_ctrl(fe, 0);
return 0;
}
@@ -531,6 +540,7 @@ static struct dvb_frontend_ops cx22702_ops = {
.read_signal_strength = cx22702_read_signal_strength,
.read_snr = cx22702_read_snr,
.read_ucblocks = cx22702_read_ucblocks,
+ .i2c_gate_ctrl = cx22702_i2c_gate_ctrl,
};
module_param(debug, int, 0644);
diff --git a/drivers/media/dvb/frontends/cx24110.c b/drivers/media/dvb/frontends/cx24110.c
index 0c4db80ec332..d15d32c51dc5 100644
--- a/drivers/media/dvb/frontends/cx24110.c
+++ b/drivers/media/dvb/frontends/cx24110.c
@@ -27,7 +27,6 @@
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
-#include <linux/jiffies.h>
#include "dvb_frontend.h"
#include "cx24110.h"
@@ -56,7 +55,7 @@ static int debug;
static struct {u8 reg; u8 data;} cx24110_regdata[]=
/* Comments beginning with @ denote this value should
- be the default */
+ be the default */
{{0x09,0x01}, /* SoftResetAll */
{0x09,0x00}, /* release reset */
{0x01,0xe8}, /* MSB of code rate 27.5MS/s */
@@ -67,26 +66,26 @@ static struct {u8 reg; u8 data;} cx24110_regdata[]=
{0x07,0x01}, /* @ Fclk, i.e. sampling clock, 60MHz */
{0x0a,0x00}, /* @ partial chip disables, do not set */
{0x0b,0x01}, /* set output clock in gapped mode, start signal low
- active for first byte */
+ active for first byte */
{0x0c,0x11}, /* no parity bytes, large hold time, serial data out */
{0x0d,0x6f}, /* @ RS Sync/Unsync thresholds */
{0x10,0x40}, /* chip doc is misleading here: write bit 6 as 1
- to avoid starting the BER counter. Reset the
- CRC test bit. Finite counting selected */
+ to avoid starting the BER counter. Reset the
+ CRC test bit. Finite counting selected */
{0x15,0xff}, /* @ size of the limited time window for RS BER
- estimation. It is <value>*256 RS blocks, this
- gives approx. 2.6 sec at 27.5MS/s, rate 3/4 */
+ estimation. It is <value>*256 RS blocks, this
+ gives approx. 2.6 sec at 27.5MS/s, rate 3/4 */
{0x16,0x00}, /* @ enable all RS output ports */
{0x17,0x04}, /* @ time window allowed for the RS to sync */
{0x18,0xae}, /* @ allow all standard DVB code rates to be scanned
- for automatically */
+ for automatically */
/* leave the current code rate and normalization
- registers as they are after reset... */
+ registers as they are after reset... */
{0x21,0x10}, /* @ during AutoAcq, search each viterbi setting
- only once */
+ only once */
{0x23,0x18}, /* @ size of the limited time window for Viterbi BER
- estimation. It is <value>*65536 channel bits, i.e.
- approx. 38ms at 27.5MS/s, rate 3/4 */
+ estimation. It is <value>*65536 channel bits, i.e.
+ approx. 38ms at 27.5MS/s, rate 3/4 */
{0x24,0x24}, /* do not trigger Viterbi CRC test. Finite count window */
/* leave front-end AGC parameters at default values */
/* leave decimation AGC parameters at default values */
diff --git a/drivers/media/dvb/frontends/cx24123.c b/drivers/media/dvb/frontends/cx24123.c
new file mode 100644
index 000000000000..d661c6f9cbe5
--- /dev/null
+++ b/drivers/media/dvb/frontends/cx24123.c
@@ -0,0 +1,889 @@
+/*
+ Conexant cx24123/cx24109 - DVB QPSK Satellite demod/tuner driver
+
+ Copyright (C) 2005 Steven Toth <stoth@hauppauge.com>
+
+ Support for KWorld DVB-S 100 by Vadim Catana <skystar@moldova.cc>
+
+ 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 <linux/slab.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+
+#include "dvb_frontend.h"
+#include "cx24123.h"
+
+static int debug;
+#define dprintk(args...) \
+ do { \
+ if (debug) printk (KERN_DEBUG "cx24123: " args); \
+ } while (0)
+
+struct cx24123_state
+{
+ struct i2c_adapter* i2c;
+ struct dvb_frontend_ops ops;
+ const struct cx24123_config* config;
+
+ struct dvb_frontend frontend;
+
+ u32 lastber;
+ u16 snr;
+ u8 lnbreg;
+
+ /* Some PLL specifics for tuning */
+ u32 VCAarg;
+ u32 VGAarg;
+ u32 bandselectarg;
+ u32 pllarg;
+
+ /* The Demod/Tuner can't easily provide these, we cache them */
+ u32 currentfreq;
+ u32 currentsymbolrate;
+};
+
+/* Various tuner defaults need to be established for a given symbol rate Sps */
+static struct
+{
+ u32 symbolrate_low;
+ u32 symbolrate_high;
+ u32 VCAslope;
+ u32 VCAoffset;
+ u32 VGA1offset;
+ u32 VGA2offset;
+ u32 VCAprogdata;
+ u32 VGAprogdata;
+} cx24123_AGC_vals[] =
+{
+ {
+ .symbolrate_low = 1000000,
+ .symbolrate_high = 4999999,
+ .VCAslope = 0x07,
+ .VCAoffset = 0x0f,
+ .VGA1offset = 0x1f8,
+ .VGA2offset = 0x1f8,
+ .VGAprogdata = (2 << 18) | (0x1f8 << 9) | 0x1f8,
+ .VCAprogdata = (4 << 18) | (0x07 << 9) | 0x07,
+ },
+ {
+ .symbolrate_low = 5000000,
+ .symbolrate_high = 14999999,
+ .VCAslope = 0x1f,
+ .VCAoffset = 0x1f,
+ .VGA1offset = 0x1e0,
+ .VGA2offset = 0x180,
+ .VGAprogdata = (2 << 18) | (0x180 << 9) | 0x1e0,
+ .VCAprogdata = (4 << 18) | (0x07 << 9) | 0x1f,
+ },
+ {
+ .symbolrate_low = 15000000,
+ .symbolrate_high = 45000000,
+ .VCAslope = 0x3f,
+ .VCAoffset = 0x3f,
+ .VGA1offset = 0x180,
+ .VGA2offset = 0x100,
+ .VGAprogdata = (2 << 18) | (0x100 << 9) | 0x180,
+ .VCAprogdata = (4 << 18) | (0x07 << 9) | 0x3f,
+ },
+};
+
+/*
+ * Various tuner defaults need to be established for a given frequency kHz.
+ * fixme: The bounds on the bands do not match the doc in real life.
+ * fixme: Some of them have been moved, other might need adjustment.
+ */
+static struct
+{
+ u32 freq_low;
+ u32 freq_high;
+ u32 bandselect;
+ u32 VCOdivider;
+ u32 VCOnumber;
+ u32 progdata;
+} cx24123_bandselect_vals[] =
+{
+ {
+ .freq_low = 950000,
+ .freq_high = 1018999,
+ .bandselect = 0x40,
+ .VCOdivider = 4,
+ .VCOnumber = 7,
+ .progdata = (0 << 18) | (0 << 9) | 0x40,
+ },
+ {
+ .freq_low = 1019000,
+ .freq_high = 1074999,
+ .bandselect = 0x80,
+ .VCOdivider = 4,
+ .VCOnumber = 8,
+ .progdata = (0 << 18) | (0 << 9) | 0x80,
+ },
+ {
+ .freq_low = 1075000,
+ .freq_high = 1227999,
+ .bandselect = 0x01,
+ .VCOdivider = 2,
+ .VCOnumber = 1,
+ .progdata = (0 << 18) | (1 << 9) | 0x01,
+ },
+ {
+ .freq_low = 1228000,
+ .freq_high = 1349999,
+ .bandselect = 0x02,
+ .VCOdivider = 2,
+ .VCOnumber = 2,
+ .progdata = (0 << 18) | (1 << 9) | 0x02,
+ },
+ {
+ .freq_low = 1350000,
+ .freq_high = 1481999,
+ .bandselect = 0x04,
+ .VCOdivider = 2,
+ .VCOnumber = 3,
+ .progdata = (0 << 18) | (1 << 9) | 0x04,
+ },
+ {
+ .freq_low = 1482000,
+ .freq_high = 1595999,
+ .bandselect = 0x08,
+ .VCOdivider = 2,
+ .VCOnumber = 4,
+ .progdata = (0 << 18) | (1 << 9) | 0x08,
+ },
+ {
+ .freq_low = 1596000,
+ .freq_high = 1717999,
+ .bandselect = 0x10,
+ .VCOdivider = 2,
+ .VCOnumber = 5,
+ .progdata = (0 << 18) | (1 << 9) | 0x10,
+ },
+ {
+ .freq_low = 1718000,
+ .freq_high = 1855999,
+ .bandselect = 0x20,
+ .VCOdivider = 2,
+ .VCOnumber = 6,
+ .progdata = (0 << 18) | (1 << 9) | 0x20,
+ },
+ {
+ .freq_low = 1856000,
+ .freq_high = 2035999,
+ .bandselect = 0x40,
+ .VCOdivider = 2,
+ .VCOnumber = 7,
+ .progdata = (0 << 18) | (1 << 9) | 0x40,
+ },
+ {
+ .freq_low = 2036000,
+ .freq_high = 2149999,
+ .bandselect = 0x80,
+ .VCOdivider = 2,
+ .VCOnumber = 8,
+ .progdata = (0 << 18) | (1 << 9) | 0x80,
+ },
+};
+
+static struct {
+ u8 reg;
+ u8 data;
+} cx24123_regdata[] =
+{
+ {0x00, 0x03}, /* Reset system */
+ {0x00, 0x00}, /* Clear reset */
+ {0x01, 0x3b}, /* Apply sensible defaults, from an i2c sniffer */
+ {0x03, 0x07},
+ {0x04, 0x10},
+ {0x05, 0x04},
+ {0x06, 0x31},
+ {0x0d, 0x02},
+ {0x0e, 0x03},
+ {0x0f, 0xfe},
+ {0x10, 0x01},
+ {0x14, 0x01},
+ {0x15, 0x98},
+ {0x16, 0x00},
+ {0x17, 0x01},
+ {0x1b, 0x05},
+ {0x1c, 0x80},
+ {0x1d, 0x00},
+ {0x1e, 0x00},
+ {0x20, 0x41},
+ {0x21, 0x15},
+ {0x27, 0x14},
+ {0x28, 0x46},
+ {0x29, 0x00},
+ {0x2a, 0xb0},
+ {0x2b, 0x73},
+ {0x2c, 0x00},
+ {0x2d, 0x00},
+ {0x2e, 0x00},
+ {0x2f, 0x00},
+ {0x30, 0x00},
+ {0x31, 0x00},
+ {0x32, 0x8c},
+ {0x33, 0x00},
+ {0x34, 0x00},
+ {0x35, 0x03},
+ {0x36, 0x02},
+ {0x37, 0x3a},
+ {0x3a, 0x00}, /* Enable AGC accumulator */
+ {0x44, 0x00},
+ {0x45, 0x00},
+ {0x46, 0x05},
+ {0x56, 0x41},
+ {0x57, 0xff},
+ {0x67, 0x83},
+};
+
+static int cx24123_writereg(struct cx24123_state* state, int reg, int data)
+{
+ u8 buf[] = { reg, data };
+ struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = buf, .len = 2 };
+ int err;
+
+ if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) {
+ printk("%s: writereg error(err == %i, reg == 0x%02x,"
+ " data == 0x%02x)\n", __FUNCTION__, err, reg, data);
+ return -EREMOTEIO;
+ }
+
+ return 0;
+}
+
+static int cx24123_writelnbreg(struct cx24123_state* state, int reg, int data)
+{
+ u8 buf[] = { reg, data };
+ /* fixme: put the intersil addr int the config */
+ struct i2c_msg msg = { .addr = 0x08, .flags = 0, .buf = buf, .len = 2 };
+ int err;
+
+ if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) {
+ printk("%s: writelnbreg error (err == %i, reg == 0x%02x,"
+ " data == 0x%02x)\n", __FUNCTION__, err, reg, data);
+ return -EREMOTEIO;
+ }
+
+ /* cache the write, no way to read back */
+ state->lnbreg = data;
+
+ return 0;
+}
+
+static int cx24123_readreg(struct cx24123_state* state, u8 reg)
+{
+ int ret;
+ u8 b0[] = { reg };
+ u8 b1[] = { 0 };
+ struct i2c_msg msg[] = {
+ { .addr = state->config->demod_address, .flags = 0, .buf = b0, .len = 1 },
+ { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b1, .len = 1 }
+ };
+
+ ret = i2c_transfer(state->i2c, msg, 2);
+
+ if (ret != 2) {
+ printk("%s: reg=0x%x (error=%d)\n", __FUNCTION__, reg, ret);
+ return ret;
+ }
+
+ return b1[0];
+}
+
+static int cx24123_readlnbreg(struct cx24123_state* state, u8 reg)
+{
+ return state->lnbreg;
+}
+
+static int cx24123_set_inversion(struct cx24123_state* state, fe_spectral_inversion_t inversion)
+{
+ switch (inversion) {
+ case INVERSION_OFF:
+ cx24123_writereg(state, 0x0e, cx24123_readreg(state, 0x0e) & 0x7f);
+ cx24123_writereg(state, 0x10, cx24123_readreg(state, 0x10) | 0x80);
+ break;
+ case INVERSION_ON:
+ cx24123_writereg(state, 0x0e, cx24123_readreg(state, 0x0e) | 0x80);
+ cx24123_writereg(state, 0x10, cx24123_readreg(state, 0x10) | 0x80);
+ break;
+ case INVERSION_AUTO:
+ cx24123_writereg(state, 0x10, cx24123_readreg(state, 0x10) & 0x7f);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int cx24123_get_inversion(struct cx24123_state* state, fe_spectral_inversion_t *inversion)
+{
+ u8 val;
+
+ val = cx24123_readreg(state, 0x1b) >> 7;
+
+ if (val == 0)
+ *inversion = INVERSION_OFF;
+ else
+ *inversion = INVERSION_ON;
+
+ return 0;
+}
+
+static int cx24123_set_fec(struct cx24123_state* state, fe_code_rate_t fec)
+{
+ if ( (fec < FEC_NONE) || (fec > FEC_AUTO) )
+ fec = FEC_AUTO;
+
+ /* Hardware has 5/11 and 3/5 but are never unused */
+ switch (fec) {
+ case FEC_NONE:
+ return cx24123_writereg(state, 0x0f, 0x01);
+ case FEC_1_2:
+ return cx24123_writereg(state, 0x0f, 0x02);
+ case FEC_2_3:
+ return cx24123_writereg(state, 0x0f, 0x04);
+ case FEC_3_4:
+ return cx24123_writereg(state, 0x0f, 0x08);
+ case FEC_5_6:
+ return cx24123_writereg(state, 0x0f, 0x20);
+ case FEC_7_8:
+ return cx24123_writereg(state, 0x0f, 0x80);
+ case FEC_AUTO:
+ return cx24123_writereg(state, 0x0f, 0xae);
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+static int cx24123_get_fec(struct cx24123_state* state, fe_code_rate_t *fec)
+{
+ int ret;
+ u8 val;
+
+ ret = cx24123_readreg (state, 0x1b);
+ if (ret < 0)
+ return ret;
+ val = ret & 0x07;
+ switch (val) {
+ case 1:
+ *fec = FEC_1_2;
+ break;
+ case 3:
+ *fec = FEC_2_3;
+ break;
+ case 4:
+ *fec = FEC_3_4;
+ break;
+ case 5:
+ *fec = FEC_4_5;
+ break;
+ case 6:
+ *fec = FEC_5_6;
+ break;
+ case 7:
+ *fec = FEC_7_8;
+ break;
+ case 2: /* *fec = FEC_3_5; break; */
+ case 0: /* *fec = FEC_5_11; break; */
+ *fec = FEC_AUTO;
+ break;
+ default:
+ *fec = FEC_NONE; // can't happen
+ }
+
+ return 0;
+}
+
+/* fixme: Symbol rates < 3MSps may not work because of precision loss */
+static int cx24123_set_symbolrate(struct cx24123_state* state, u32 srate)
+{
+ u32 val;
+
+ val = (srate / 1185) * 100;
+
+ /* Compensate for scaling up, by removing 17 symbols per 1Msps */
+ val = val - (17 * (srate / 1000000));
+
+ cx24123_writereg(state, 0x08, (val >> 16) & 0xff );
+ cx24123_writereg(state, 0x09, (val >> 8) & 0xff );
+ cx24123_writereg(state, 0x0a, (val ) & 0xff );
+
+ return 0;
+}
+
+/*
+ * Based on the required frequency and symbolrate, the tuner AGC has to be configured
+ * and the correct band selected. Calculate those values
+ */
+static int cx24123_pll_calculate(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
+{
+ struct cx24123_state *state = fe->demodulator_priv;
+ u32 ndiv = 0, adiv = 0, vco_div = 0;
+ int i = 0;
+
+ /* Defaults for low freq, low rate */
+ state->VCAarg = cx24123_AGC_vals[0].VCAprogdata;
+ state->VGAarg = cx24123_AGC_vals[0].VGAprogdata;
+ state->bandselectarg = cx24123_bandselect_vals[0].progdata;
+ vco_div = cx24123_bandselect_vals[0].VCOdivider;
+
+ /* For the given symbolerate, determine the VCA and VGA programming bits */
+ for (i = 0; i < sizeof(cx24123_AGC_vals) / sizeof(cx24123_AGC_vals[0]); i++)
+ {
+ if ((cx24123_AGC_vals[i].symbolrate_low <= p->u.qpsk.symbol_rate) &&
+ (cx24123_AGC_vals[i].symbolrate_high >= p->u.qpsk.symbol_rate) ) {
+ state->VCAarg = cx24123_AGC_vals[i].VCAprogdata;
+ state->VGAarg = cx24123_AGC_vals[i].VGAprogdata;
+ }
+ }
+
+ /* For the given frequency, determine the bandselect programming bits */
+ for (i = 0; i < sizeof(cx24123_bandselect_vals) / sizeof(cx24123_bandselect_vals[0]); i++)
+ {
+ if ((cx24123_bandselect_vals[i].freq_low <= p->frequency) &&
+ (cx24123_bandselect_vals[i].freq_high >= p->frequency) ) {
+ state->bandselectarg = cx24123_bandselect_vals[i].progdata;
+ vco_div = cx24123_bandselect_vals[i].VCOdivider;
+ }
+ }
+
+ /* Determine the N/A dividers for the requested lband freq (in kHz). */
+ /* Note: 10111 (kHz) is the Crystal Freq and divider of 10. */
+ ndiv = ( ((p->frequency * vco_div) / (10111 / 10) / 2) / 32) & 0x1ff;
+ adiv = ( ((p->frequency * vco_div) / (10111 / 10) / 2) % 32) & 0x1f;
+
+ if (adiv == 0)
+ adiv++;
+
+ /* determine the correct pll frequency values. */
+ /* Command 11, refdiv 11, cpump polarity 1, cpump current 3mA 10. */
+ state->pllarg = (3 << 19) | (3 << 17) | (1 << 16) | (2 << 14);
+ state->pllarg |= (ndiv << 5) | adiv;
+
+ return 0;
+}
+
+/*
+ * Tuner data is 21 bits long, must be left-aligned in data.
+ * Tuner cx24109 is written through a dedicated 3wire interface on the demod chip.
+ */
+static int cx24123_pll_writereg(struct dvb_frontend* fe, struct dvb_frontend_parameters *p, u32 data)
+{
+ struct cx24123_state *state = fe->demodulator_priv;
+ unsigned long timeout;
+
+ /* align the 21 bytes into to bit23 boundary */
+ data = data << 3;
+
+ /* Reset the demod pll word length to 0x15 bits */
+ cx24123_writereg(state, 0x21, 0x15);
+
+ /* write the msb 8 bits, wait for the send to be completed */
+ timeout = jiffies + msecs_to_jiffies(40);
+ cx24123_writereg(state, 0x22, (data >> 16) & 0xff);
+ while ((cx24123_readreg(state, 0x20) & 0x40) == 0) {
+ if (time_after(jiffies, timeout)) {
+ printk("%s: demodulator is not responding, possibly hung, aborting.\n", __FUNCTION__);
+ return -EREMOTEIO;
+ }
+ msleep(10);
+ }
+
+ /* send another 8 bytes, wait for the send to be completed */
+ timeout = jiffies + msecs_to_jiffies(40);
+ cx24123_writereg(state, 0x22, (data>>8) & 0xff );
+ while ((cx24123_readreg(state, 0x20) & 0x40) == 0) {
+ if (time_after(jiffies, timeout)) {
+ printk("%s: demodulator is not responding, possibly hung, aborting.\n", __FUNCTION__);
+ return -EREMOTEIO;
+ }
+ msleep(10);
+ }
+
+ /* send the lower 5 bits of this byte, padded with 3 LBB, wait for the send to be completed */
+ timeout = jiffies + msecs_to_jiffies(40);
+ cx24123_writereg(state, 0x22, (data) & 0xff );
+ while ((cx24123_readreg(state, 0x20) & 0x80)) {
+ if (time_after(jiffies, timeout)) {
+ printk("%s: demodulator is not responding, possibly hung, aborting.\n", __FUNCTION__);
+ return -EREMOTEIO;
+ }
+ msleep(10);
+ }
+
+ /* Trigger the demod to configure the tuner */
+ cx24123_writereg(state, 0x20, cx24123_readreg(state, 0x20) | 2);
+ cx24123_writereg(state, 0x20, cx24123_readreg(state, 0x20) & 0xfd);
+
+ return 0;
+}
+
+static int cx24123_pll_tune(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
+{
+ struct cx24123_state *state = fe->demodulator_priv;
+
+ if (cx24123_pll_calculate(fe, p) != 0) {
+ printk("%s: cx24123_pll_calcutate failed\n",__FUNCTION__);
+ return -EINVAL;
+ }
+
+ /* Write the new VCO/VGA */
+ cx24123_pll_writereg(fe, p, state->VCAarg);
+ cx24123_pll_writereg(fe, p, state->VGAarg);
+
+ /* Write the new bandselect and pll args */
+ cx24123_pll_writereg(fe, p, state->bandselectarg);
+ cx24123_pll_writereg(fe, p, state->pllarg);
+
+ return 0;
+}
+
+static int cx24123_initfe(struct dvb_frontend* fe)
+{
+ struct cx24123_state *state = fe->demodulator_priv;
+ int i;
+
+ /* Configure the demod to a good set of defaults */
+ for (i = 0; i < sizeof(cx24123_regdata) / sizeof(cx24123_regdata[0]); i++)
+ cx24123_writereg(state, cx24123_regdata[i].reg, cx24123_regdata[i].data);
+
+ if (state->config->pll_init)
+ state->config->pll_init(fe);
+
+ /* Configure the LNB for 14V */
+ if (state->config->use_isl6421)
+ cx24123_writelnbreg(state, 0x0, 0x2a);
+
+ return 0;
+}
+
+static int cx24123_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage)
+{
+ struct cx24123_state *state = fe->demodulator_priv;
+ u8 val;
+
+ switch (state->config->use_isl6421) {
+
+ case 1:
+
+ val = cx24123_readlnbreg(state, 0x0);
+
+ switch (voltage) {
+ case SEC_VOLTAGE_13:
+ return cx24123_writelnbreg(state, 0x0, val & 0x32); /* V 13v */
+ case SEC_VOLTAGE_18:
+ return cx24123_writelnbreg(state, 0x0, val | 0x04); /* H 18v */
+ case SEC_VOLTAGE_OFF:
+ return cx24123_writelnbreg(state, 0x0, val & 0x30);
+ default:
+ return -EINVAL;
+ };
+
+ case 0:
+
+ val = cx24123_readreg(state, 0x29);
+
+ switch (voltage) {
+ case SEC_VOLTAGE_13:
+ dprintk("%s: setting voltage 13V\n", __FUNCTION__);
+ if (state->config->enable_lnb_voltage)
+ state->config->enable_lnb_voltage(fe, 1);
+ return cx24123_writereg(state, 0x29, val | 0x80);
+ case SEC_VOLTAGE_18:
+ dprintk("%s: setting voltage 18V\n", __FUNCTION__);
+ if (state->config->enable_lnb_voltage)
+ state->config->enable_lnb_voltage(fe, 1);
+ return cx24123_writereg(state, 0x29, val & 0x7f);
+ case SEC_VOLTAGE_OFF:
+ dprintk("%s: setting voltage off\n", __FUNCTION__);
+ if (state->config->enable_lnb_voltage)
+ state->config->enable_lnb_voltage(fe, 0);
+ return 0;
+ default:
+ return -EINVAL;
+ };
+ }
+
+ return 0;
+}
+
+static int cx24123_send_diseqc_msg(struct dvb_frontend* fe,
+ struct dvb_diseqc_master_cmd *cmd)
+{
+ /* fixme: Implement diseqc */
+ printk("%s: No support yet\n",__FUNCTION__);
+
+ return -ENOTSUPP;
+}
+
+static int cx24123_read_status(struct dvb_frontend* fe, fe_status_t* status)
+{
+ struct cx24123_state *state = fe->demodulator_priv;
+
+ int sync = cx24123_readreg(state, 0x14);
+ int lock = cx24123_readreg(state, 0x20);
+
+ *status = 0;
+ if (lock & 0x01)
+ *status |= FE_HAS_CARRIER | FE_HAS_SIGNAL;
+ if (sync & 0x04)
+ *status |= FE_HAS_VITERBI;
+ if (sync & 0x08)
+ *status |= FE_HAS_CARRIER;
+ if (sync & 0x80)
+ *status |= FE_HAS_SYNC | FE_HAS_LOCK;
+
+ return 0;
+}
+
+/*
+ * Configured to return the measurement of errors in blocks, because no UCBLOCKS value
+ * is available, so this value doubles up to satisfy both measurements
+ */
+static int cx24123_read_ber(struct dvb_frontend* fe, u32* ber)
+{
+ struct cx24123_state *state = fe->demodulator_priv;
+
+ state->lastber =
+ ((cx24123_readreg(state, 0x1c) & 0x3f) << 16) |
+ (cx24123_readreg(state, 0x1d) << 8 |
+ cx24123_readreg(state, 0x1e));
+
+ /* Do the signal quality processing here, it's derived from the BER. */
+ /* Scale the BER from a 24bit to a SNR 16 bit where higher = better */
+ if (state->lastber < 5000)
+ state->snr = 655*100;
+ else if ( (state->lastber >= 5000) && (state->lastber < 55000) )
+ state->snr = 655*90;
+ else if ( (state->lastber >= 55000) && (state->lastber < 150000) )
+ state->snr = 655*80;
+ else if ( (state->lastber >= 150000) && (state->lastber < 250000) )
+ state->snr = 655*70;
+ else if ( (state->lastber >= 250000) && (state->lastber < 450000) )
+ state->snr = 655*65;
+ else
+ state->snr = 0;
+
+ *ber = state->lastber;
+
+ return 0;
+}
+
+static int cx24123_read_signal_strength(struct dvb_frontend* fe, u16* signal_strength)
+{
+ struct cx24123_state *state = fe->demodulator_priv;
+ *signal_strength = cx24123_readreg(state, 0x3b) << 8; /* larger = better */
+
+ return 0;
+}
+
+static int cx24123_read_snr(struct dvb_frontend* fe, u16* snr)
+{
+ struct cx24123_state *state = fe->demodulator_priv;
+ *snr = state->snr;
+
+ return 0;
+}
+
+static int cx24123_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
+{
+ struct cx24123_state *state = fe->demodulator_priv;
+ *ucblocks = state->lastber;
+
+ return 0;
+}
+
+static int cx24123_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
+{
+ struct cx24123_state *state = fe->demodulator_priv;
+
+ if (state->config->set_ts_params)
+ state->config->set_ts_params(fe, 0);
+
+ state->currentfreq=p->frequency;
+ state->currentsymbolrate = p->u.qpsk.symbol_rate;
+
+ cx24123_set_inversion(state, p->inversion);
+ cx24123_set_fec(state, p->u.qpsk.fec_inner);
+ cx24123_set_symbolrate(state, p->u.qpsk.symbol_rate);
+ cx24123_pll_tune(fe, p);
+
+ /* Enable automatic aquisition and reset cycle */
+ cx24123_writereg(state, 0x03, (cx24123_readreg(state, 0x03) | 0x07));
+ cx24123_writereg(state, 0x00, 0x10);
+ cx24123_writereg(state, 0x00, 0);
+
+ return 0;
+}
+
+static int cx24123_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
+{
+ struct cx24123_state *state = fe->demodulator_priv;
+
+ if (cx24123_get_inversion(state, &p->inversion) != 0) {
+ printk("%s: Failed to get inversion status\n",__FUNCTION__);
+ return -EREMOTEIO;
+ }
+ if (cx24123_get_fec(state, &p->u.qpsk.fec_inner) != 0) {
+ printk("%s: Failed to get fec status\n",__FUNCTION__);
+ return -EREMOTEIO;
+ }
+ p->frequency = state->currentfreq;
+ p->u.qpsk.symbol_rate = state->currentsymbolrate;
+
+ return 0;
+}
+
+static int cx24123_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
+{
+ struct cx24123_state *state = fe->demodulator_priv;
+ u8 val;
+
+ switch (state->config->use_isl6421) {
+ case 1:
+
+ val = cx24123_readlnbreg(state, 0x0);
+
+ switch (tone) {
+ case SEC_TONE_ON:
+ return cx24123_writelnbreg(state, 0x0, val | 0x10);
+ case SEC_TONE_OFF:
+ return cx24123_writelnbreg(state, 0x0, val & 0x2f);
+ default:
+ printk("%s: CASE reached default with tone=%d\n", __FUNCTION__, tone);
+ return -EINVAL;
+ }
+
+ case 0:
+
+ val = cx24123_readreg(state, 0x29);
+
+ switch (tone) {
+ case SEC_TONE_ON:
+ dprintk("%s: setting tone on\n", __FUNCTION__);
+ return cx24123_writereg(state, 0x29, val | 0x10);
+ case SEC_TONE_OFF:
+ dprintk("%s: setting tone off\n",__FUNCTION__);
+ return cx24123_writereg(state, 0x29, val & 0xef);
+ default:
+ printk("%s: CASE reached default with tone=%d\n", __FUNCTION__, tone);
+ return -EINVAL;
+ }
+ }
+
+ return 0;
+}
+
+static void cx24123_release(struct dvb_frontend* fe)
+{
+ struct cx24123_state* state = fe->demodulator_priv;
+ dprintk("%s\n",__FUNCTION__);
+ kfree(state);
+}
+
+static struct dvb_frontend_ops cx24123_ops;
+
+struct dvb_frontend* cx24123_attach(const struct cx24123_config* config,
+ struct i2c_adapter* i2c)
+{
+ struct cx24123_state* state = NULL;
+ int ret;
+
+ dprintk("%s\n",__FUNCTION__);
+
+ /* allocate memory for the internal state */
+ state = kmalloc(sizeof(struct cx24123_state), GFP_KERNEL);
+ if (state == NULL) {
+ printk("Unable to kmalloc\n");
+ goto error;
+ }
+
+ /* setup the state */
+ state->config = config;
+ state->i2c = i2c;
+ memcpy(&state->ops, &cx24123_ops, sizeof(struct dvb_frontend_ops));
+ state->lastber = 0;
+ state->snr = 0;
+ state->lnbreg = 0;
+ state->VCAarg = 0;
+ state->VGAarg = 0;
+ state->bandselectarg = 0;
+ state->pllarg = 0;
+ state->currentfreq = 0;
+ state->currentsymbolrate = 0;
+
+ /* check if the demod is there */
+ ret = cx24123_readreg(state, 0x00);
+ if ((ret != 0xd1) && (ret != 0xe1)) {
+ printk("Version != d1 or e1\n");
+ goto error;
+ }
+
+ /* create dvb_frontend */
+ state->frontend.ops = &state->ops;
+ state->frontend.demodulator_priv = state;
+ return &state->frontend;
+
+error:
+ kfree(state);
+
+ return NULL;
+}
+
+static struct dvb_frontend_ops cx24123_ops = {
+
+ .info = {
+ .name = "Conexant CX24123/CX24109",
+ .type = FE_QPSK,
+ .frequency_min = 950000,
+ .frequency_max = 2150000,
+ .frequency_stepsize = 1011, /* kHz for QPSK frontends */
+ .frequency_tolerance = 29500,
+ .symbol_rate_min = 1000000,
+ .symbol_rate_max = 45000000,
+ .caps = FE_CAN_INVERSION_AUTO |
+ 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_RECOVER
+ },
+
+ .release = cx24123_release,
+
+ .init = cx24123_initfe,
+ .set_frontend = cx24123_set_frontend,
+ .get_frontend = cx24123_get_frontend,
+ .read_status = cx24123_read_status,
+ .read_ber = cx24123_read_ber,
+ .read_signal_strength = cx24123_read_signal_strength,
+ .read_snr = cx24123_read_snr,
+ .read_ucblocks = cx24123_read_ucblocks,
+ .diseqc_send_master_cmd = cx24123_send_diseqc_msg,
+ .set_tone = cx24123_set_tone,
+ .set_voltage = cx24123_set_voltage,
+};
+
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
+
+MODULE_DESCRIPTION("DVB Frontend module for Conexant cx24123/cx24109 hardware");
+MODULE_AUTHOR("Steven Toth");
+MODULE_LICENSE("GPL");
+
+EXPORT_SYMBOL(cx24123_attach);
diff --git a/drivers/media/dvb/frontends/cx24123.h b/drivers/media/dvb/frontends/cx24123.h
new file mode 100644
index 000000000000..0c922b5e9263
--- /dev/null
+++ b/drivers/media/dvb/frontends/cx24123.h
@@ -0,0 +1,51 @@
+/*
+ Conexant cx24123/cx24109 - DVB QPSK Satellite demod/tuner driver
+
+ Copyright (C) 2005 Steven Toth <stoth@hauppauge.com>
+
+ 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 CX24123_H
+#define CX24123_H
+
+#include <linux/dvb/frontend.h>
+
+struct cx24123_config
+{
+ /* the demodulator's i2c address */
+ u8 demod_address;
+
+ /*
+ cards like Hauppauge Nova-S Plus/Nova-SE2 use an Intersil ISL6421 chip
+ for LNB control, while KWorld DVB-S 100 use the LNBDC and LNBTone bits
+ from register 0x29 of the CX24123 demodulator
+ */
+ int use_isl6421;
+
+ /* PLL maintenance */
+ int (*pll_init)(struct dvb_frontend* fe);
+ int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params);
+
+ /* Need to set device param for start_dma */
+ int (*set_ts_params)(struct dvb_frontend* fe, int is_punctured);
+
+ void (*enable_lnb_voltage)(struct dvb_frontend* fe, int on);
+};
+
+extern struct dvb_frontend* cx24123_attach(const struct cx24123_config* config,
+ struct i2c_adapter* i2c);
+
+#endif /* CX24123_H */
diff --git a/drivers/media/dvb/frontends/dvb-pll.c b/drivers/media/dvb/frontends/dvb-pll.c
index f857b869616c..a3d57ce9dd12 100644
--- a/drivers/media/dvb/frontends/dvb-pll.c
+++ b/drivers/media/dvb/frontends/dvb-pll.c
@@ -107,18 +107,19 @@ struct dvb_pll_desc dvb_pll_microtune_4042 = {
};
EXPORT_SYMBOL(dvb_pll_microtune_4042);
-struct dvb_pll_desc dvb_pll_thomson_dtt7611 = {
- .name = "Thomson dtt7611",
- .min = 44000000,
- .max = 958000000,
+struct dvb_pll_desc dvb_pll_thomson_dtt761x = {
+ /* DTT 7611 7611A 7612 7613 7613A 7614 7615 7615A */
+ .name = "Thomson dtt761x",
+ .min = 57000000,
+ .max = 863000000,
.count = 3,
.entries = {
- { 157250000, 44000000, 62500, 0x8e, 0x39 },
- { 454000000, 44000000, 62500, 0x8e, 0x3a },
+ { 147000000, 44000000, 62500, 0x8e, 0x39 },
+ { 417000000, 44000000, 62500, 0x8e, 0x3a },
{ 999999999, 44000000, 62500, 0x8e, 0x3c },
},
};
-EXPORT_SYMBOL(dvb_pll_thomson_dtt7611);
+EXPORT_SYMBOL(dvb_pll_thomson_dtt761x);
struct dvb_pll_desc dvb_pll_unknown_1 = {
.name = "unknown 1", /* used by dntv live dvb-t */
diff --git a/drivers/media/dvb/frontends/dvb-pll.h b/drivers/media/dvb/frontends/dvb-pll.h
index 497d31dcf41e..24d4d2e9acd8 100644
--- a/drivers/media/dvb/frontends/dvb-pll.h
+++ b/drivers/media/dvb/frontends/dvb-pll.h
@@ -25,7 +25,7 @@ extern struct dvb_pll_desc dvb_pll_thomson_dtt759x;
extern struct dvb_pll_desc dvb_pll_thomson_dtt7610;
extern struct dvb_pll_desc dvb_pll_lg_z201;
extern struct dvb_pll_desc dvb_pll_microtune_4042;
-extern struct dvb_pll_desc dvb_pll_thomson_dtt7611;
+extern struct dvb_pll_desc dvb_pll_thomson_dtt761x;
extern struct dvb_pll_desc dvb_pll_unknown_1;
extern struct dvb_pll_desc dvb_pll_tua6010xs;
diff --git a/drivers/media/dvb/frontends/lgdt330x.c b/drivers/media/dvb/frontends/lgdt330x.c
index cb5301865d07..9d214643b87a 100644
--- a/drivers/media/dvb/frontends/lgdt330x.c
+++ b/drivers/media/dvb/frontends/lgdt330x.c
@@ -27,6 +27,7 @@
* DViCO FusionHDTV 3 Gold-T
* DViCO FusionHDTV 5 Gold
* DViCO FusionHDTV 5 Lite
+ * DViCO FusionHDTV 5 USB Gold
* Air2PC/AirStar 2 ATSC 3rd generation (HD5000)
*
* TODO:
@@ -402,6 +403,8 @@ static int lgdt330x_set_parameters(struct dvb_frontend* fe,
state->config->pll_set(fe, param);
/* Keep track of the new frequency */
+ /* FIXME this is the wrong way to do this... */
+ /* The tuner is shared with the video4linux analog API */
state->current_frequency = param->frequency;
lgdt330x_SwReset(state);
diff --git a/drivers/media/dvb/frontends/nxt2002.c b/drivers/media/dvb/frontends/nxt2002.c
index 52c416043a62..4f263e65ba14 100644
--- a/drivers/media/dvb/frontends/nxt2002.c
+++ b/drivers/media/dvb/frontends/nxt2002.c
@@ -22,7 +22,8 @@
/*
* This driver needs external firmware. Please use the command
* "<kerneldir>/Documentation/dvb/get_dvb_firmware nxt2002" to
- * download/extract it, and then copy it to /usr/lib/hotplug/firmware.
+ * download/extract it, and then copy it to /usr/lib/hotplug/firmware
+ * or /lib/firmware (depending on configuration of firmware hotplug).
*/
#define NXT2002_DEFAULT_FIRMWARE "dvb-fe-nxt2002.fw"
#define CRC_CCIT_MASK 0x1021
diff --git a/drivers/media/dvb/frontends/nxt6000.c b/drivers/media/dvb/frontends/nxt6000.c
index a458a3bfff70..a16eeba0020d 100644
--- a/drivers/media/dvb/frontends/nxt6000.c
+++ b/drivers/media/dvb/frontends/nxt6000.c
@@ -574,11 +574,11 @@ static struct dvb_frontend_ops nxt6000_ops = {
.symbol_rate_max = 9360000, /* FIXME */
.symbol_rate_tolerance = 4000,
.caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
- FE_CAN_FEC_4_5 | FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 |
- FE_CAN_FEC_7_8 | FE_CAN_FEC_8_9 | FE_CAN_FEC_AUTO |
- 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_FEC_4_5 | FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 |
+ FE_CAN_FEC_7_8 | FE_CAN_FEC_8_9 | FE_CAN_FEC_AUTO |
+ 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,
},
.release = nxt6000_release,
diff --git a/drivers/media/dvb/frontends/or51211.c b/drivers/media/dvb/frontends/or51211.c
index 531f76246e5f..7c3aed1f546b 100644
--- a/drivers/media/dvb/frontends/or51211.c
+++ b/drivers/media/dvb/frontends/or51211.c
@@ -25,7 +25,8 @@
/*
* This driver needs external firmware. Please use the command
* "<kerneldir>/Documentation/dvb/get_dvb_firmware or51211" to
- * download/extract it, and then copy it to /usr/lib/hotplug/firmware.
+ * download/extract it, and then copy it to /usr/lib/hotplug/firmware
+ * or /lib/firmware (depending on configuration of firmware hotplug).
*/
#define OR51211_DEFAULT_FIRMWARE "dvb-fe-or51211.fw"
@@ -112,7 +113,7 @@ static int or51211_load_firmware (struct dvb_frontend* fe,
u8 tudata[585];
int i;
- dprintk("Firmware is %d bytes\n",fw->size);
+ dprintk("Firmware is %zd bytes\n",fw->size);
/* Get eprom data */
tudata[0] = 17;
diff --git a/drivers/media/dvb/frontends/s5h1420.c b/drivers/media/dvb/frontends/s5h1420.c
index 18715091aed8..d69477596921 100644
--- a/drivers/media/dvb/frontends/s5h1420.c
+++ b/drivers/media/dvb/frontends/s5h1420.c
@@ -521,8 +521,8 @@ static void s5h1420_setfec_inversion(struct s5h1420_state* state,
case FEC_3_4:
s5h1420_writereg(state, 0x30, 0x04);
- s5h1420_writereg(state, 0x31, 0x12 | inversion);
- break;
+ s5h1420_writereg(state, 0x31, 0x12 | inversion);
+ break;
case FEC_5_6:
s5h1420_writereg(state, 0x30, 0x08);
diff --git a/drivers/media/dvb/frontends/sp8870.c b/drivers/media/dvb/frontends/sp8870.c
index fc06cd6b46c3..73829e647e50 100644
--- a/drivers/media/dvb/frontends/sp8870.c
+++ b/drivers/media/dvb/frontends/sp8870.c
@@ -22,7 +22,8 @@
/*
* This driver needs external firmware. Please use the command
* "<kerneldir>/Documentation/dvb/get_dvb_firmware alps_tdlb7" to
- * download/extract it, and then copy it to /usr/lib/hotplug/firmware.
+ * download/extract it, and then copy it to /usr/lib/hotplug/firmware
+ * or /lib/firmware (depending on configuration of firmware hotplug).
*/
#define SP8870_DEFAULT_FIRMWARE "dvb-fe-sp8870.fw"
diff --git a/drivers/media/dvb/frontends/sp887x.c b/drivers/media/dvb/frontends/sp887x.c
index e3b665782243..eb8a602198ca 100644
--- a/drivers/media/dvb/frontends/sp887x.c
+++ b/drivers/media/dvb/frontends/sp887x.c
@@ -5,7 +5,8 @@
/*
* This driver needs external firmware. Please use the command
* "<kerneldir>/Documentation/dvb/get_dvb_firmware sp887x" to
- * download/extract it, and then copy it to /usr/lib/hotplug/firmware.
+ * download/extract it, and then copy it to /usr/lib/hotplug/firmware
+ * or /lib/firmware (depending on configuration of firmware hotplug).
*/
#define SP887X_DEFAULT_FIRMWARE "dvb-fe-sp887x.fw"
@@ -581,7 +582,7 @@ static struct dvb_frontend_ops sp887x_ops = {
.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_RECOVER
+ FE_CAN_RECOVER
},
.release = sp887x_release,
diff --git a/drivers/media/dvb/frontends/stv0299.c b/drivers/media/dvb/frontends/stv0299.c
index 177d71d56b67..5bcd00f792e6 100644
--- a/drivers/media/dvb/frontends/stv0299.c
+++ b/drivers/media/dvb/frontends/stv0299.c
@@ -131,6 +131,13 @@ static int stv0299_readregs (struct stv0299_state* state, u8 reg1, u8 *b, u8 len
return ret == 2 ? 0 : ret;
}
+int stv0299_enable_plli2c (struct dvb_frontend* fe)
+{
+ struct stv0299_state* state = fe->demodulator_priv;
+
+ return stv0299_writeregI(state, 0x05, 0xb5); /* enable i2c repeater on stv0299 */
+}
+
static int stv0299_set_FEC (struct stv0299_state* state, fe_code_rate_t fec)
{
dprintk ("%s\n", __FUNCTION__);
@@ -387,7 +394,7 @@ static int stv0299_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t voltag
};
}
-static int stv0299_send_legacy_dish_cmd (struct dvb_frontend* fe, u32 cmd)
+static int stv0299_send_legacy_dish_cmd (struct dvb_frontend* fe, unsigned long cmd)
{
struct stv0299_state* state = fe->demodulator_priv;
u8 reg0x08;
@@ -407,7 +414,7 @@ static int stv0299_send_legacy_dish_cmd (struct dvb_frontend* fe, u32 cmd)
cmd = cmd << 1;
if (debug_legacy_dish_switch)
- printk ("%s switch command: 0x%04x\n",__FUNCTION__, cmd);
+ printk ("%s switch command: 0x%04lx\n",__FUNCTION__, cmd);
do_gettimeofday (&nexttime);
if (debug_legacy_dish_switch)
@@ -717,5 +724,6 @@ MODULE_AUTHOR("Ralph Metzler, Holger Waechtler, Peter Schildmann, Felix Domke, "
"Andreas Oberritter, Andrew de Quincey, Kenneth Aafløy");
MODULE_LICENSE("GPL");
+EXPORT_SYMBOL(stv0299_enable_plli2c);
EXPORT_SYMBOL(stv0299_writereg);
EXPORT_SYMBOL(stv0299_attach);
diff --git a/drivers/media/dvb/frontends/stv0299.h b/drivers/media/dvb/frontends/stv0299.h
index 9af3d71c89db..32c87b4c2f13 100644
--- a/drivers/media/dvb/frontends/stv0299.h
+++ b/drivers/media/dvb/frontends/stv0299.h
@@ -94,6 +94,7 @@ struct stv0299_config
};
extern int stv0299_writereg (struct dvb_frontend* fe, u8 reg, u8 data);
+extern int stv0299_enable_plli2c (struct dvb_frontend* fe);
extern struct dvb_frontend* stv0299_attach(const struct stv0299_config* config,
struct i2c_adapter* i2c);
diff --git a/drivers/media/dvb/frontends/tda10021.c b/drivers/media/dvb/frontends/tda10021.c
index 425cd19136fe..21255cac9793 100644
--- a/drivers/media/dvb/frontends/tda10021.c
+++ b/drivers/media/dvb/frontends/tda10021.c
@@ -95,7 +95,7 @@ static u8 tda10021_readreg (struct tda10021_state* state, u8 reg)
u8 b0 [] = { reg };
u8 b1 [] = { 0 };
struct i2c_msg msg [] = { { .addr = state->config->demod_address, .flags = 0, .buf = b0, .len = 1 },
- { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b1, .len = 1 } };
+ { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b1, .len = 1 } };
int ret;
ret = i2c_transfer (state->i2c, msg, 2);
@@ -434,7 +434,7 @@ static struct dvb_frontend_ops tda10021_ops = {
.frequency_max = 858000000,
.symbol_rate_min = (XIN/2)/64, /* SACLK/64 == (XIN/2)/64 */
.symbol_rate_max = (XIN/2)/4, /* SACLK/4 */
- #if 0
+#if 0
.frequency_tolerance = ???,
.symbol_rate_tolerance = ???, /* ppm */ /* == 8% (spec p. 5) */
#endif
diff --git a/drivers/media/dvb/frontends/tda1004x.c b/drivers/media/dvb/frontends/tda1004x.c
index dd02aff467fe..c63e9a5084eb 100644
--- a/drivers/media/dvb/frontends/tda1004x.c
+++ b/drivers/media/dvb/frontends/tda1004x.c
@@ -23,7 +23,8 @@
* This driver needs external firmware. Please use the commands
* "<kerneldir>/Documentation/dvb/get_dvb_firmware tda10045",
* "<kerneldir>/Documentation/dvb/get_dvb_firmware tda10046" to
- * download/extract them, and then copy them to /usr/lib/hotplug/firmware.
+ * download/extract them, and then copy them to /usr/lib/hotplug/firmware
+ * or /lib/firmware (depending on configuration of firmware hotplug).
*/
#define TDA10045_DEFAULT_FIRMWARE "dvb-fe-tda10045.fw"
#define TDA10046_DEFAULT_FIRMWARE "dvb-fe-tda10046.fw"
@@ -271,32 +272,57 @@ static int tda10045h_set_bandwidth(struct tda1004x_state *state,
static int tda10046h_set_bandwidth(struct tda1004x_state *state,
fe_bandwidth_t bandwidth)
{
- static u8 bandwidth_6mhz[] = { 0x80, 0x15, 0xfe, 0xab, 0x8e };
- static u8 bandwidth_7mhz[] = { 0x6e, 0x02, 0x53, 0xc8, 0x25 };
- static u8 bandwidth_8mhz[] = { 0x60, 0x12, 0xa8, 0xe4, 0xbd };
-
+ static u8 bandwidth_6mhz_53M[] = { 0x7b, 0x2e, 0x11, 0xf0, 0xd2 };
+ static u8 bandwidth_7mhz_53M[] = { 0x6a, 0x02, 0x6a, 0x43, 0x9f };
+ static u8 bandwidth_8mhz_53M[] = { 0x5c, 0x32, 0xc2, 0x96, 0x6d };
+
+ static u8 bandwidth_6mhz_48M[] = { 0x70, 0x02, 0x49, 0x24, 0x92 };
+ static u8 bandwidth_7mhz_48M[] = { 0x60, 0x02, 0xaa, 0xaa, 0xab };
+ static u8 bandwidth_8mhz_48M[] = { 0x54, 0x03, 0x0c, 0x30, 0xc3 };
+ int tda10046_clk53m;
+
+ if ((state->config->if_freq == TDA10046_FREQ_045) ||
+ (state->config->if_freq == TDA10046_FREQ_052))
+ tda10046_clk53m = 0;
+ else
+ tda10046_clk53m = 1;
switch (bandwidth) {
case BANDWIDTH_6_MHZ:
- tda1004x_write_buf(state, TDA10046H_TIME_WREF1, bandwidth_6mhz, sizeof(bandwidth_6mhz));
+ if (tda10046_clk53m)
+ tda1004x_write_buf(state, TDA10046H_TIME_WREF1, bandwidth_6mhz_53M,
+ sizeof(bandwidth_6mhz_53M));
+ else
+ tda1004x_write_buf(state, TDA10046H_TIME_WREF1, bandwidth_6mhz_48M,
+ sizeof(bandwidth_6mhz_48M));
if (state->config->if_freq == TDA10046_FREQ_045) {
- tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_MSB, 0x09);
- tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0x4f);
+ tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_MSB, 0x0a);
+ tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0xab);
}
break;
case BANDWIDTH_7_MHZ:
- tda1004x_write_buf(state, TDA10046H_TIME_WREF1, bandwidth_7mhz, sizeof(bandwidth_7mhz));
+ if (tda10046_clk53m)
+ tda1004x_write_buf(state, TDA10046H_TIME_WREF1, bandwidth_7mhz_53M,
+ sizeof(bandwidth_7mhz_53M));
+ else
+ tda1004x_write_buf(state, TDA10046H_TIME_WREF1, bandwidth_7mhz_48M,
+ sizeof(bandwidth_7mhz_48M));
if (state->config->if_freq == TDA10046_FREQ_045) {
- tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_MSB, 0x0a);
- tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0x79);
+ tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_MSB, 0x0c);
+ tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0x00);
}
break;
case BANDWIDTH_8_MHZ:
- tda1004x_write_buf(state, TDA10046H_TIME_WREF1, bandwidth_8mhz, sizeof(bandwidth_8mhz));
+ if (tda10046_clk53m)
+ tda1004x_write_buf(state, TDA10046H_TIME_WREF1, bandwidth_8mhz_53M,
+ sizeof(bandwidth_8mhz_53M));
+ else
+ tda1004x_write_buf(state, TDA10046H_TIME_WREF1, bandwidth_8mhz_48M,
+ sizeof(bandwidth_8mhz_48M));
if (state->config->if_freq == TDA10046_FREQ_045) {
- tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_MSB, 0x0b);
- tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0xa3);
+ tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_MSB, 0x0d);
+ tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0x55);
}
break;
@@ -418,9 +444,22 @@ static int tda10045_fwupload(struct dvb_frontend* fe)
static void tda10046_init_plls(struct dvb_frontend* fe)
{
struct tda1004x_state* state = fe->demodulator_priv;
+ int tda10046_clk53m;
+
+ if ((state->config->if_freq == TDA10046_FREQ_045) ||
+ (state->config->if_freq == TDA10046_FREQ_052))
+ tda10046_clk53m = 0;
+ else
+ tda10046_clk53m = 1;
tda1004x_write_byteI(state, TDA10046H_CONFPLL1, 0xf0);
- tda1004x_write_byteI(state, TDA10046H_CONFPLL2, 0x0a); // PLL M = 10
+ if(tda10046_clk53m) {
+ printk(KERN_INFO "tda1004x: setting up plls for 53MHz sampling clock\n");
+ tda1004x_write_byteI(state, TDA10046H_CONFPLL2, 0x08); // PLL M = 8
+ } else {
+ printk(KERN_INFO "tda1004x: setting up plls for 48MHz sampling clock\n");
+ tda1004x_write_byteI(state, TDA10046H_CONFPLL2, 0x03); // PLL M = 3
+ }
if (state->config->xtal_freq == TDA10046_XTAL_4M ) {
dprintk("%s: setting up PLLs for a 4 MHz Xtal\n", __FUNCTION__);
tda1004x_write_byteI(state, TDA10046H_CONFPLL3, 0); // PLL P = N = 0
@@ -428,26 +467,32 @@ static void tda10046_init_plls(struct dvb_frontend* fe)
dprintk("%s: setting up PLLs for a 16 MHz Xtal\n", __FUNCTION__);
tda1004x_write_byteI(state, TDA10046H_CONFPLL3, 3); // PLL P = 0, N = 3
}
- tda1004x_write_byteI(state, TDA10046H_FREQ_OFFSET, 99);
+ if(tda10046_clk53m)
+ tda1004x_write_byteI(state, TDA10046H_FREQ_OFFSET, 0x67);
+ else
+ tda1004x_write_byteI(state, TDA10046H_FREQ_OFFSET, 0x72);
+ /* Note clock frequency is handled implicitly */
switch (state->config->if_freq) {
- case TDA10046_FREQ_3617:
- tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_MSB, 0xd4);
- tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0x2c);
- break;
- case TDA10046_FREQ_3613:
- tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_MSB, 0xd4);
- tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0x13);
- break;
case TDA10046_FREQ_045:
- tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_MSB, 0x0b);
- tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0xa3);
+ tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_MSB, 0x0c);
+ tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0x00);
break;
case TDA10046_FREQ_052:
- tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_MSB, 0x0c);
- tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0x06);
+ tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_MSB, 0x0d);
+ tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0xc7);
+ break;
+ case TDA10046_FREQ_3617:
+ tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_MSB, 0xd7);
+ tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0x59);
+ break;
+ case TDA10046_FREQ_3613:
+ tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_MSB, 0xd7);
+ tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0x3f);
break;
}
tda10046h_set_bandwidth(state, BANDWIDTH_8_MHZ); // default bandwidth 8 MHz
+ /* let the PLLs settle */
+ msleep(120);
}
static int tda10046_fwupload(struct dvb_frontend* fe)
@@ -462,13 +507,13 @@ static int tda10046_fwupload(struct dvb_frontend* fe)
/* let the clocks recover from sleep */
msleep(5);
+ /* The PLLs need to be reprogrammed after sleep */
+ tda10046_init_plls(fe);
+
/* don't re-upload unless necessary */
if (tda1004x_check_upload_ok(state) == 0)
return 0;
- /* set parameters */
- tda10046_init_plls(fe);
-
if (state->config->request_firmware != NULL) {
/* request the firmware, this will block until someone uploads it */
printk(KERN_INFO "tda1004x: waiting for firmware upload...\n");
@@ -484,7 +529,6 @@ static int tda10046_fwupload(struct dvb_frontend* fe)
return ret;
} else {
/* boot from firmware eeprom */
- /* Hac Note: we might need to do some GPIO Magic here */
printk(KERN_INFO "tda1004x: booting from eeprom\n");
tda1004x_write_mask(state, TDA1004X_CONFC4, 4, 4);
msleep(300);
@@ -606,10 +650,9 @@ static int tda10046_init(struct dvb_frontend* fe)
// tda setup
tda1004x_write_mask(state, TDA1004X_CONFC4, 0x20, 0); // disable DSP watchdog timer
- tda1004x_write_byteI(state, TDA1004X_AUTO, 7); // select HP stream
- tda1004x_write_byteI(state, TDA1004X_CONFC1, 8); // disable pulse killer
+ tda1004x_write_byteI(state, TDA1004X_AUTO, 0x87); // 100 ppm crystal, select HP stream
+ tda1004x_write_byteI(state, TDA1004X_CONFC1, 8); // disable pulse killer
- tda10046_init_plls(fe);
switch (state->config->agc_config) {
case TDA10046_AGC_DEFAULT:
tda1004x_write_byteI(state, TDA10046H_AGC_CONF, 0x00); // AGC setup
@@ -626,25 +669,22 @@ static int tda10046_init(struct dvb_frontend* fe)
case TDA10046_AGC_TDA827X:
tda1004x_write_byteI(state, TDA10046H_AGC_CONF, 0x02); // AGC setup
tda1004x_write_byteI(state, TDA10046H_AGC_THR, 0x70); // AGC Threshold
- tda1004x_write_byteI(state, TDA10046H_AGC_RENORM, 0x0E); // Gain Renormalize
- tda1004x_write_byteI(state, TDA10046H_CONF_POLARITY, 0x60); // set AGC polarities
+ tda1004x_write_byteI(state, TDA10046H_AGC_RENORM, 0x08); // Gain Renormalize
+ tda1004x_write_byteI(state, TDA10046H_CONF_POLARITY, 0x6a); // set AGC polarities
break;
}
+ tda1004x_write_byteI(state, TDA1004X_CONFADC2, 0x38);
tda1004x_write_byteI(state, TDA10046H_CONF_TRISTATE1, 0x61); // Turn both AGC outputs on
tda1004x_write_byteI(state, TDA10046H_AGC_TUN_MIN, 0); // }
tda1004x_write_byteI(state, TDA10046H_AGC_TUN_MAX, 0xff); // } AGC min/max values
tda1004x_write_byteI(state, TDA10046H_AGC_IF_MIN, 0); // }
tda1004x_write_byteI(state, TDA10046H_AGC_IF_MAX, 0xff); // }
- tda1004x_write_byteI(state, TDA10046H_AGC_GAINS, 1); // IF gain 2, TUN gain 1
+ tda1004x_write_byteI(state, TDA10046H_AGC_GAINS, 0x12); // IF gain 2, TUN gain 1
tda1004x_write_byteI(state, TDA10046H_CVBER_CTRL, 0x1a); // 10^6 VBER measurement bits
tda1004x_write_byteI(state, TDA1004X_CONF_TS1, 7); // MPEG2 interface config
tda1004x_write_byteI(state, TDA1004X_CONF_TS2, 0xc0); // MPEG2 interface config
tda1004x_write_mask(state, 0x3a, 0x80, state->config->invert_oclk << 7);
- tda1004x_write_byteI(state, TDA10046H_CONF_TRISTATE2, 0xe1); // tristate setup
- tda1004x_write_byteI(state, TDA10046H_GPIO_OUT_SEL, 0xcc); // GPIO output config
- tda1004x_write_byteI(state, TDA10046H_GPIO_SELECT, 8); // GPIO select
-
state->initialised = 1;
return 0;
}
@@ -686,9 +726,9 @@ static int tda1004x_set_fe(struct dvb_frontend* fe,
// Set standard params.. or put them to auto
if ((fe_params->u.ofdm.code_rate_HP == FEC_AUTO) ||
- (fe_params->u.ofdm.code_rate_LP == FEC_AUTO) ||
- (fe_params->u.ofdm.constellation == QAM_AUTO) ||
- (fe_params->u.ofdm.hierarchy_information == HIERARCHY_AUTO)) {
+ (fe_params->u.ofdm.code_rate_LP == FEC_AUTO) ||
+ (fe_params->u.ofdm.constellation == QAM_AUTO) ||
+ (fe_params->u.ofdm.hierarchy_information == HIERARCHY_AUTO)) {
tda1004x_write_mask(state, TDA1004X_AUTO, 1, 1); // enable auto
tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x03, 0); // turn off constellation bits
tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x60, 0); // turn off hierarchy bits
@@ -851,6 +891,7 @@ static int tda1004x_set_fe(struct dvb_frontend* fe,
static int tda1004x_get_fe(struct dvb_frontend* fe, struct dvb_frontend_parameters *fe_params)
{
struct tda1004x_state* state = fe->demodulator_priv;
+
dprintk("%s\n", __FUNCTION__);
// inversion status
@@ -875,16 +916,18 @@ static int tda1004x_get_fe(struct dvb_frontend* fe, struct dvb_frontend_paramete
break;
}
break;
-
case TDA1004X_DEMOD_TDA10046:
switch (tda1004x_read_byte(state, TDA10046H_TIME_WREF1)) {
- case 0x60:
+ case 0x5c:
+ case 0x54:
fe_params->u.ofdm.bandwidth = BANDWIDTH_8_MHZ;
break;
- case 0x6e:
+ case 0x6a:
+ case 0x60:
fe_params->u.ofdm.bandwidth = BANDWIDTH_7_MHZ;
break;
- case 0x80:
+ case 0x7b:
+ case 0x70:
fe_params->u.ofdm.bandwidth = BANDWIDTH_6_MHZ;
break;
}
diff --git a/drivers/media/dvb/pluto2/Kconfig b/drivers/media/dvb/pluto2/Kconfig
index f02842be0d60..84f8f9f52869 100644
--- a/drivers/media/dvb/pluto2/Kconfig
+++ b/drivers/media/dvb/pluto2/Kconfig
@@ -8,7 +8,7 @@ config DVB_PLUTO2
Support for PCI cards based on the Pluto2 FPGA like the Satelco
Easywatch Mobile Terrestrial DVB-T Receiver.
- Since these cards have no MPEG decoder onboard, they transmit
+ Since these cards have no MPEG decoder onboard, they transmit
only compressed MPEG data over the PCI bus, so you need
an external software decoder to watch TV on your computer.
diff --git a/drivers/media/dvb/ttpci/Kconfig b/drivers/media/dvb/ttpci/Kconfig
index fa5034a9ecf5..5b2aadb8385c 100644
--- a/drivers/media/dvb/ttpci/Kconfig
+++ b/drivers/media/dvb/ttpci/Kconfig
@@ -18,9 +18,10 @@ config DVB_AV7110
This driver only supports the fullfeatured cards with
onboard MPEG2 decoder.
- This driver needs an external firmware. Please use the script
- "<kerneldir>/Documentation/dvb/get_dvb_firmware av7110" to
- download/extract it, and then copy it to /usr/lib/hotplug/firmware.
+ This driver needs an external firmware. Please use the script
+ "<kerneldir>/Documentation/dvb/get_dvb_firmware av7110" to
+ download/extract it, and then copy it to /usr/lib/hotplug/firmware
+ or /lib/firmware (depending on configuration of firmware hotplug).
Say Y if you own such a card and want to use it.
diff --git a/drivers/media/dvb/ttpci/Makefile b/drivers/media/dvb/ttpci/Makefile
index 825ab1c38a4f..a690730ac39d 100644
--- a/drivers/media/dvb/ttpci/Makefile
+++ b/drivers/media/dvb/ttpci/Makefile
@@ -16,7 +16,7 @@ EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/
hostprogs-y := fdump
ifdef CONFIG_DVB_AV7110_FIRMWARE
-$(obj)/av7110.o: $(obj)/fdump $(obj)/av7110_firm.h
+$(obj)/av7110.o: $(obj)/fdump $(obj)/av7110_firm.h
$(obj)/av7110_firm.h:
$(obj)/fdump $(CONFIG_DVB_AV7110_FIRMWARE_FILE) dvb_ttpci_fw $@
diff --git a/drivers/media/dvb/ttpci/av7110.c b/drivers/media/dvb/ttpci/av7110.c
index 7dae91e5863c..8ce4146f55f1 100644
--- a/drivers/media/dvb/ttpci/av7110.c
+++ b/drivers/media/dvb/ttpci/av7110.c
@@ -133,7 +133,13 @@ static void init_av7110_av(struct av7110 *av7110)
/* remaining inits according to card and frontend type */
av7110->analog_tuner_flags = 0;
av7110->current_input = 0;
- if (i2c_writereg(av7110, 0x20, 0x00, 0x00) == 1) {
+ if (dev->pci->subsystem_vendor == 0x13c2 && dev->pci->subsystem_device == 0x000a) {
+ printk("dvb-ttpci: MSP3415 audio DAC @ card %d\n",
+ av7110->dvb_adapter.num);
+ av7110->adac_type = DVB_ADAC_MSP34x5;
+ av7110_fw_cmd(av7110, COMTYPE_AUDIODAC, ADSwitch, 1, 0); // SPDIF on
+ }
+ else if (i2c_writereg(av7110, 0x20, 0x00, 0x00) == 1) {
printk ("dvb-ttpci: Crystal audio DAC @ card %d detected\n",
av7110->dvb_adapter.num);
av7110->adac_type = DVB_ADAC_CRYSTAL;
@@ -156,10 +162,10 @@ static void init_av7110_av(struct av7110 *av7110)
else {
av7110->adac_type = adac;
printk("dvb-ttpci: adac type set to %d @ card %d\n",
- av7110->dvb_adapter.num, av7110->adac_type);
+ av7110->adac_type, av7110->dvb_adapter.num);
}
- if (av7110->adac_type == DVB_ADAC_NONE || av7110->adac_type == DVB_ADAC_MSP) {
+ if (av7110->adac_type == DVB_ADAC_NONE || av7110->adac_type == DVB_ADAC_MSP34x0) {
// switch DVB SCART on
ret = av7110_fw_cmd(av7110, COMTYPE_AUDIODAC, MainSwitch, 1, 0);
if (ret < 0)
@@ -190,17 +196,15 @@ static void recover_arm(struct av7110 *av7110)
av7110_bootarm(av7110);
msleep(100);
- restart_feeds(av7110);
- av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, SetIR, 1, av7110->ir_config);
-}
-static void arm_error(struct av7110 *av7110)
-{
- dprintk(4, "%p\n",av7110);
+ init_av7110_av(av7110);
+
+ /* card-specific recovery */
+ if (av7110->recover)
+ av7110->recover(av7110);
- av7110->arm_errors++;
- av7110->arm_ready = 0;
- recover_arm(av7110);
+ restart_feeds(av7110);
+ av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, SetIR, 1, av7110->ir_config);
}
static void av7110_arm_sync(struct av7110 *av7110)
@@ -240,26 +244,22 @@ static int arm_thread(void *data)
if (down_interruptible(&av7110->dcomlock))
break;
-
newloops = rdebi(av7110, DEBINOSWAP, STATUS_LOOPS, 0, 2);
up(&av7110->dcomlock);
- if (newloops == av7110->arm_loops) {
+ if (newloops == av7110->arm_loops || av7110->arm_errors > 3) {
printk(KERN_ERR "dvb-ttpci: ARM crashed @ card %d\n",
av7110->dvb_adapter.num);
- arm_error(av7110);
- av7710_set_video_mode(av7110, vidmode);
-
- init_av7110_av(av7110);
+ recover_arm(av7110);
if (down_interruptible(&av7110->dcomlock))
break;
-
newloops = rdebi(av7110, DEBINOSWAP, STATUS_LOOPS, 0, 2) - 1;
up(&av7110->dcomlock);
}
av7110->arm_loops = newloops;
+ av7110->arm_errors = 0;
}
av7110->arm_thread = NULL;
@@ -510,10 +510,6 @@ static void gpioirq(unsigned long data)
iwdebi(av7110, DEBINOSWAP, RX_BUFF, 0, 2);
av7110->video_size.h = h_ar & 0xfff;
- dprintk(8, "GPIO0 irq: DATA_MPEG_VIDEO_EVENT: w/h/ar = %u/%u/%u\n",
- av7110->video_size.w,
- av7110->video_size.h,
- av7110->video_size.aspect_ratio);
event.type = VIDEO_EVENT_SIZE_CHANGED;
event.u.size.w = av7110->video_size.w;
@@ -535,6 +531,11 @@ static void gpioirq(unsigned long data)
event.u.size.aspect_ratio = VIDEO_FORMAT_4_3;
av7110->videostate.video_format = VIDEO_FORMAT_4_3;
}
+
+ dprintk(8, "GPIO0 irq: DATA_MPEG_VIDEO_EVENT: w/h/ar = %u/%u/%u\n",
+ av7110->video_size.w, av7110->video_size.h,
+ av7110->video_size.aspect_ratio);
+
dvb_video_add_event(av7110, &event);
break;
}
@@ -714,6 +715,8 @@ static struct dvb_device dvbdev_osd = {
static inline int SetPIDs(struct av7110 *av7110, u16 vpid, u16 apid, u16 ttpid,
u16 subpid, u16 pcrpid)
{
+ u16 aflags = 0;
+
dprintk(4, "%p\n", av7110);
if (vpid == 0x1fff || apid == 0x1fff ||
@@ -725,8 +728,11 @@ static inline int SetPIDs(struct av7110 *av7110, u16 vpid, u16 apid, u16 ttpid,
av7110->pids[DMX_PES_PCR] = 0;
}
- return av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, MultiPID, 5,
- pcrpid, vpid, apid, ttpid, subpid);
+ if (av7110->audiostate.bypass_mode)
+ aflags |= 0x8000;
+
+ return av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, MultiPID, 6,
+ pcrpid, vpid, apid, ttpid, subpid, aflags);
}
int ChangePIDs(struct av7110 *av7110, u16 vpid, u16 apid, u16 ttpid,
@@ -1043,7 +1049,7 @@ static void restart_feeds(struct av7110 *av7110)
struct dvb_demux *dvbdmx = &av7110->demux;
struct dvb_demux_feed *feed;
int mode;
- int i;
+ int i, j;
dprintk(4, "%p\n", av7110);
@@ -1051,10 +1057,21 @@ static void restart_feeds(struct av7110 *av7110)
av7110->playing = 0;
av7110->rec_mode = 0;
- for (i = 0; i < dvbdmx->filternum; i++) {
+ for (i = 0; i < dvbdmx->feednum; i++) {
feed = &dvbdmx->feed[i];
- if (feed->state == DMX_STATE_GO)
+ if (feed->state == DMX_STATE_GO) {
+ if (feed->type == DMX_TYPE_SEC) {
+ for (j = 0; j < dvbdmx->filternum; j++) {
+ if (dvbdmx->filter[j].type != DMX_TYPE_SEC)
+ continue;
+ if (dvbdmx->filter[j].filter.parent != &feed->feed.sec)
+ continue;
+ if (dvbdmx->filter[j].state == DMX_STATE_GO)
+ dvbdmx->filter[j].state = DMX_STATE_READY;
+ }
+ }
av7110_start_feed(feed);
+ }
}
if (mode)
@@ -1483,9 +1500,9 @@ static int get_firmware(struct av7110* av7110)
if (ret == -ENOENT) {
printk(KERN_ERR "dvb-ttpci: could not load firmware,"
" file not found: dvb-ttpci-01.fw\n");
- printk(KERN_ERR "dvb-ttpci: usually this should be in"
- " /usr/lib/hotplug/firmware\n");
- printk(KERN_ERR "dvb-ttpci: and can be downloaded here"
+ printk(KERN_ERR "dvb-ttpci: usually this should be in "
+ "/usr/lib/hotplug/firmware or /lib/firmware\n");
+ printk(KERN_ERR "dvb-ttpci: and can be downloaded from"
" http://www.linuxtv.org/download/dvb/firmware/\n");
} else
printk(KERN_ERR "dvb-ttpci: cannot request firmware"
@@ -2110,8 +2127,10 @@ static int av7110_fe_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_p
struct av7110* av7110 = fe->dvb->priv;
int ret = av7110_fe_lock_fix(av7110, 0);
- if (!ret)
+ if (!ret) {
+ av7110->saved_fe_params = *params;
ret = av7110->fe_set_frontend(fe, params);
+ }
return ret;
}
@@ -2153,8 +2172,10 @@ static int av7110_fe_diseqc_send_master_cmd(struct dvb_frontend* fe,
struct av7110* av7110 = fe->dvb->priv;
int ret = av7110_fe_lock_fix(av7110, 0);
- if (!ret)
+ if (!ret) {
+ av7110->saved_master_cmd = *cmd;
ret = av7110->fe_diseqc_send_master_cmd(fe, cmd);
+ }
return ret;
}
@@ -2163,8 +2184,10 @@ static int av7110_fe_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_
struct av7110* av7110 = fe->dvb->priv;
int ret = av7110_fe_lock_fix(av7110, 0);
- if (!ret)
+ if (!ret) {
+ av7110->saved_minicmd = minicmd;
ret = av7110->fe_diseqc_send_burst(fe, minicmd);
+ }
return ret;
}
@@ -2173,8 +2196,10 @@ static int av7110_fe_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
struct av7110* av7110 = fe->dvb->priv;
int ret = av7110_fe_lock_fix(av7110, 0);
- if (!ret)
+ if (!ret) {
+ av7110->saved_tone = tone;
ret = av7110->fe_set_tone(fe, tone);
+ }
return ret;
}
@@ -2183,12 +2208,14 @@ static int av7110_fe_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t volta
struct av7110* av7110 = fe->dvb->priv;
int ret = av7110_fe_lock_fix(av7110, 0);
- if (!ret)
+ if (!ret) {
+ av7110->saved_voltage = voltage;
ret = av7110->fe_set_voltage(fe, voltage);
+ }
return ret;
}
-static int av7110_fe_dishnetwork_send_legacy_command(struct dvb_frontend* fe, unsigned int cmd)
+static int av7110_fe_dishnetwork_send_legacy_command(struct dvb_frontend* fe, unsigned long cmd)
{
struct av7110* av7110 = fe->dvb->priv;
@@ -2198,6 +2225,23 @@ static int av7110_fe_dishnetwork_send_legacy_command(struct dvb_frontend* fe, un
return ret;
}
+static void dvb_s_recover(struct av7110* av7110)
+{
+ av7110_fe_init(av7110->fe);
+
+ av7110_fe_set_voltage(av7110->fe, av7110->saved_voltage);
+ if (av7110->saved_master_cmd.msg_len) {
+ msleep(20);
+ av7110_fe_diseqc_send_master_cmd(av7110->fe, &av7110->saved_master_cmd);
+ }
+ msleep(20);
+ av7110_fe_diseqc_send_burst(av7110->fe, av7110->saved_minicmd);
+ msleep(20);
+ av7110_fe_set_tone(av7110->fe, av7110->saved_tone);
+
+ av7110_fe_set_frontend(av7110->fe, &av7110->saved_fe_params);
+}
+
static u8 read_pwm(struct av7110* av7110)
{
u8 b = 0xff;
@@ -2235,6 +2279,7 @@ static int frontend_init(struct av7110 *av7110)
av7110->fe->ops->diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
av7110->fe->ops->diseqc_send_burst = av7110_diseqc_send_burst;
av7110->fe->ops->set_tone = av7110_set_tone;
+ av7110->recover = dvb_s_recover;
break;
}
@@ -2244,15 +2289,17 @@ static int frontend_init(struct av7110 *av7110)
av7110->fe->ops->diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
av7110->fe->ops->diseqc_send_burst = av7110_diseqc_send_burst;
av7110->fe->ops->set_tone = av7110_set_tone;
+ av7110->recover = dvb_s_recover;
break;
}
// Try the grundig 29504-451
- av7110->fe = tda8083_attach(&grundig_29504_451_config, &av7110->i2c_adap);
+ av7110->fe = tda8083_attach(&grundig_29504_451_config, &av7110->i2c_adap);
if (av7110->fe) {
av7110->fe->ops->diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
av7110->fe->ops->diseqc_send_burst = av7110_diseqc_send_burst;
av7110->fe->ops->set_tone = av7110_set_tone;
+ av7110->recover = dvb_s_recover;
break;
}
@@ -2274,12 +2321,12 @@ static int frontend_init(struct av7110 *av7110)
case 0x0001: // Hauppauge/TT Nexus-T premium rev1.X
// ALPS TDLB7
- av7110->fe = sp8870_attach(&alps_tdlb7_config, &av7110->i2c_adap);
+ av7110->fe = sp8870_attach(&alps_tdlb7_config, &av7110->i2c_adap);
break;
case 0x0002: // Hauppauge/TT DVB-C premium rev2.X
- av7110->fe = ves1820_attach(&alps_tdbe2_config, &av7110->i2c_adap, read_pwm(av7110));
+ av7110->fe = ves1820_attach(&alps_tdbe2_config, &av7110->i2c_adap, read_pwm(av7110));
break;
case 0x0006: /* Fujitsu-Siemens DVB-S rev 1.6 */
@@ -2289,6 +2336,7 @@ static int frontend_init(struct av7110 *av7110)
av7110->fe->ops->diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
av7110->fe->ops->diseqc_send_burst = av7110_diseqc_send_burst;
av7110->fe->ops->set_tone = av7110_set_tone;
+ av7110->recover = dvb_s_recover;
}
break;
@@ -2314,8 +2362,11 @@ static int frontend_init(struct av7110 *av7110)
case 0x000E: /* Hauppauge/TT Nexus-S rev 2.3 */
/* ALPS BSBE1 */
av7110->fe = stv0299_attach(&alps_bsbe1_config, &av7110->i2c_adap);
- if (av7110->fe)
+ if (av7110->fe) {
av7110->fe->ops->set_voltage = lnbp21_set_voltage;
+ av7110->fe->ops->dishnetwork_send_legacy_command = NULL;
+ av7110->recover = dvb_s_recover;
+ }
break;
}
}
diff --git a/drivers/media/dvb/ttpci/av7110.h b/drivers/media/dvb/ttpci/av7110.h
index cce00ef293e9..6ea30df2e823 100644
--- a/drivers/media/dvb/ttpci/av7110.h
+++ b/drivers/media/dvb/ttpci/av7110.h
@@ -98,7 +98,8 @@ struct av7110 {
int adac_type; /* audio DAC type */
#define DVB_ADAC_TI 0
#define DVB_ADAC_CRYSTAL 1
-#define DVB_ADAC_MSP 2
+#define DVB_ADAC_MSP34x0 2
+#define DVB_ADAC_MSP34x5 3
#define DVB_ADAC_NONE -1
@@ -228,6 +229,9 @@ struct av7110 {
struct dvb_video_events video_events;
video_size_t video_size;
+ u16 wssMode;
+ u16 wssData;
+
u32 ir_config;
u32 ir_command;
void (*ir_handler)(struct av7110 *av7110, u32 ircom);
@@ -245,6 +249,15 @@ struct av7110 {
struct dvb_frontend* fe;
fe_status_t fe_status;
+
+ /* crash recovery */
+ void (*recover)(struct av7110* av7110);
+ struct dvb_frontend_parameters saved_fe_params;
+ fe_sec_voltage_t saved_voltage;
+ fe_sec_tone_mode_t saved_tone;
+ struct dvb_diseqc_master_cmd saved_master_cmd;
+ fe_sec_mini_cmd_t saved_minicmd;
+
int (*fe_init)(struct dvb_frontend* fe);
int (*fe_read_status)(struct dvb_frontend* fe, fe_status_t* status);
int (*fe_diseqc_reset_overload)(struct dvb_frontend* fe);
@@ -252,7 +265,7 @@ struct av7110 {
int (*fe_diseqc_send_burst)(struct dvb_frontend* fe, fe_sec_mini_cmd_t minicmd);
int (*fe_set_tone)(struct dvb_frontend* fe, fe_sec_tone_mode_t tone);
int (*fe_set_voltage)(struct dvb_frontend* fe, fe_sec_voltage_t voltage);
- int (*fe_dishnetwork_send_legacy_command)(struct dvb_frontend* fe, unsigned int cmd);
+ int (*fe_dishnetwork_send_legacy_command)(struct dvb_frontend* fe, unsigned long cmd);
int (*fe_set_frontend)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params);
};
diff --git a/drivers/media/dvb/ttpci/av7110_av.c b/drivers/media/dvb/ttpci/av7110_av.c
index 0696a5a4f855..400facec7407 100644
--- a/drivers/media/dvb/ttpci/av7110_av.c
+++ b/drivers/media/dvb/ttpci/av7110_av.c
@@ -309,7 +309,7 @@ int av7110_set_volume(struct av7110 *av7110, int volleft, int volright)
i2c_writereg(av7110, 0x20, 0x04, volright);
return 0;
- case DVB_ADAC_MSP:
+ case DVB_ADAC_MSP34x0:
vol = (volleft > volright) ? volleft : volright;
val = (vol * 0x73 / 255) << 8;
if (vol > 0)
@@ -1256,7 +1256,9 @@ static int dvb_audio_ioctl(struct inode *inode, struct file *file,
break;
case AUDIO_SET_BYPASS_MODE:
- ret = -EINVAL;
+ if (FW_VERSION(av7110->arm_app) < 0x2621)
+ ret = -EINVAL;
+ av7110->audiostate.bypass_mode = (int)arg;
break;
case AUDIO_CHANNEL_SELECT:
@@ -1295,7 +1297,11 @@ static int dvb_audio_ioctl(struct inode *inode, struct file *file,
break;
case AUDIO_GET_CAPABILITIES:
- *(int *)parg = AUDIO_CAP_LPCM | AUDIO_CAP_MP1 | AUDIO_CAP_MP2;
+ if (FW_VERSION(av7110->arm_app) < 0x2621)
+ *(unsigned int *)parg = AUDIO_CAP_LPCM | AUDIO_CAP_MP1 | AUDIO_CAP_MP2;
+ else
+ *(unsigned int *)parg = AUDIO_CAP_LPCM | AUDIO_CAP_DTS | AUDIO_CAP_AC3 |
+ AUDIO_CAP_MP1 | AUDIO_CAP_MP2;
break;
case AUDIO_CLEAR_BUFFER:
diff --git a/drivers/media/dvb/ttpci/av7110_hw.c b/drivers/media/dvb/ttpci/av7110_hw.c
index 87106e8bf35b..cb377452b57d 100644
--- a/drivers/media/dvb/ttpci/av7110_hw.c
+++ b/drivers/media/dvb/ttpci/av7110_hw.c
@@ -230,6 +230,8 @@ int av7110_bootarm(struct av7110 *av7110)
dprintk(4, "%p\n", av7110);
+ av7110->arm_ready = 0;
+
saa7146_setgpio(dev, RESET_LINE, SAA7146_GPIO_OUTLO);
/* Disable DEBI and GPIO irq */
@@ -361,6 +363,7 @@ static int __av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length)
break;
if (err) {
printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for COMMAND idle\n", __FUNCTION__);
+ av7110->arm_errors++;
return -ETIMEDOUT;
}
msleep(1);
@@ -1206,9 +1209,9 @@ int av7110_osd_capability(struct av7110 *av7110, osd_cap_t *cap)
switch (cap->cmd) {
case OSD_CAP_MEMSIZE:
if (FW_4M_SDRAM(av7110->arm_app))
- cap->val = 1000000;
+ cap->val = 1000000;
else
- cap->val = 92000;
+ cap->val = 92000;
return 0;
default:
return -EINVAL;
diff --git a/drivers/media/dvb/ttpci/av7110_hw.h b/drivers/media/dvb/ttpci/av7110_hw.h
index 2a5e87ba1052..84b83299b8be 100644
--- a/drivers/media/dvb/ttpci/av7110_hw.h
+++ b/drivers/media/dvb/ttpci/av7110_hw.h
@@ -167,7 +167,8 @@ enum av7110_encoder_command {
LoadVidCode,
SetMonitorType,
SetPanScanType,
- SetFreezeMode
+ SetFreezeMode,
+ SetWSSConfig
};
enum av7110_rec_play_state {
diff --git a/drivers/media/dvb/ttpci/av7110_ir.c b/drivers/media/dvb/ttpci/av7110_ir.c
index f5e59fc924af..9138132ad25f 100644
--- a/drivers/media/dvb/ttpci/av7110_ir.c
+++ b/drivers/media/dvb/ttpci/av7110_ir.c
@@ -17,6 +17,8 @@ static int av_cnt;
static struct av7110 *av_list[4];
static struct input_dev *input_dev;
+static u8 delay_timer_finished;
+
static u16 key_map [256] = {
KEY_0, KEY_1, KEY_2, KEY_3, KEY_4, KEY_5, KEY_6, KEY_7,
KEY_8, KEY_9, KEY_BACK, 0, KEY_POWER, KEY_MUTE, 0, KEY_INFO,
@@ -112,13 +114,16 @@ static void av7110_emit_key(unsigned long parm)
if (timer_pending(&keyup_timer)) {
del_timer(&keyup_timer);
if (keyup_timer.data != keycode || new_toggle != old_toggle) {
+ delay_timer_finished = 0;
input_event(input_dev, EV_KEY, keyup_timer.data, !!0);
input_event(input_dev, EV_KEY, keycode, !0);
} else
- input_event(input_dev, EV_KEY, keycode, 2);
-
- } else
+ if (delay_timer_finished)
+ input_event(input_dev, EV_KEY, keycode, 2);
+ } else {
+ delay_timer_finished = 0;
input_event(input_dev, EV_KEY, keycode, !0);
+ }
keyup_timer.expires = jiffies + UP_TIMEOUT;
keyup_timer.data = keycode;
@@ -145,7 +150,8 @@ static void input_register_keys(void)
static void input_repeat_key(unsigned long data)
{
- /* dummy routine to disable autorepeat in the input driver */
+ /* called by the input driver after rep[REP_DELAY] ms */
+ delay_timer_finished = 1;
}
diff --git a/drivers/media/dvb/ttpci/av7110_v4l.c b/drivers/media/dvb/ttpci/av7110_v4l.c
index b5aea4129fa7..94cf38c7e8a8 100644
--- a/drivers/media/dvb/ttpci/av7110_v4l.c
+++ b/drivers/media/dvb/ttpci/av7110_v4l.c
@@ -490,6 +490,58 @@ static int av7110_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
dprintk(2, "VIDIOC_S_AUDIO: %d\n", a->index);
break;
}
+ case VIDIOC_G_SLICED_VBI_CAP:
+ {
+ struct v4l2_sliced_vbi_cap *cap = arg;
+ dprintk(2, "VIDIOC_G_SLICED_VBI_CAP\n");
+ memset(cap, 0, sizeof *cap);
+ if (FW_VERSION(av7110->arm_app) >= 0x2623) {
+ cap->service_set = V4L2_SLICED_WSS_625;
+ cap->service_lines[0][23] = V4L2_SLICED_WSS_625;
+ }
+ break;
+ }
+ case VIDIOC_G_FMT:
+ {
+ struct v4l2_format *f = arg;
+ dprintk(2, "VIDIOC_G_FMT:\n");
+ if (f->type != V4L2_BUF_TYPE_SLICED_VBI_OUTPUT ||
+ FW_VERSION(av7110->arm_app) < 0x2623)
+ return -EAGAIN; /* handled by core driver */
+ memset(&f->fmt.sliced, 0, sizeof f->fmt.sliced);
+ if (av7110->wssMode) {
+ f->fmt.sliced.service_set = V4L2_SLICED_WSS_625;
+ f->fmt.sliced.service_lines[0][23] = V4L2_SLICED_WSS_625;
+ f->fmt.sliced.io_size = sizeof (struct v4l2_sliced_vbi_data);
+ }
+ break;
+ }
+ case VIDIOC_S_FMT:
+ {
+ struct v4l2_format *f = arg;
+ dprintk(2, "VIDIOC_S_FMT\n");
+ if (f->type != V4L2_BUF_TYPE_SLICED_VBI_OUTPUT ||
+ FW_VERSION(av7110->arm_app) < 0x2623)
+ return -EAGAIN; /* handled by core driver */
+ if (f->fmt.sliced.service_set != V4L2_SLICED_WSS_625 &&
+ f->fmt.sliced.service_lines[0][23] != V4L2_SLICED_WSS_625) {
+ memset(&f->fmt.sliced, 0, sizeof f->fmt.sliced);
+ /* WSS controlled by firmware */
+ av7110->wssMode = 0;
+ av7110->wssData = 0;
+ return av7110_fw_cmd(av7110, COMTYPE_ENCODER,
+ SetWSSConfig, 1, 0);
+ } else {
+ memset(&f->fmt.sliced, 0, sizeof f->fmt.sliced);
+ f->fmt.sliced.service_set = V4L2_SLICED_WSS_625;
+ f->fmt.sliced.service_lines[0][23] = V4L2_SLICED_WSS_625;
+ f->fmt.sliced.io_size = sizeof (struct v4l2_sliced_vbi_data);
+ /* WSS controlled by userspace */
+ av7110->wssMode = 1;
+ av7110->wssData = 0;
+ }
+ break;
+ }
default:
printk("no such ioctl\n");
return -ENOIOCTLCMD;
@@ -497,6 +549,46 @@ static int av7110_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
return 0;
}
+static int av7110_vbi_reset(struct inode *inode, struct file *file)
+{
+ struct saa7146_fh *fh = file->private_data;
+ struct saa7146_dev *dev = fh->dev;
+ struct av7110 *av7110 = (struct av7110*) dev->ext_priv;
+
+ dprintk(2, "%s\n", __FUNCTION__);
+ av7110->wssMode = 0;
+ av7110->wssData = 0;
+ if (FW_VERSION(av7110->arm_app) < 0x2623)
+ return 0;
+ else
+ return av7110_fw_cmd(av7110, COMTYPE_ENCODER, SetWSSConfig, 1, 0);
+}
+
+static ssize_t av7110_vbi_write(struct file *file, const char __user *data, size_t count, loff_t *ppos)
+{
+ struct saa7146_fh *fh = file->private_data;
+ struct saa7146_dev *dev = fh->dev;
+ struct av7110 *av7110 = (struct av7110*) dev->ext_priv;
+ struct v4l2_sliced_vbi_data d;
+ int rc;
+
+ dprintk(2, "%s\n", __FUNCTION__);
+ if (FW_VERSION(av7110->arm_app) < 0x2623 || !av7110->wssMode || count != sizeof d)
+ return -EINVAL;
+ if (copy_from_user(&d, data, count))
+ return -EFAULT;
+ if ((d.id != 0 && d.id != V4L2_SLICED_WSS_625) || d.field != 0 || d.line != 23)
+ return -EINVAL;
+ if (d.id) {
+ av7110->wssData = ((d.data[1] << 8) & 0x3f00) | d.data[0];
+ rc = av7110_fw_cmd(av7110, COMTYPE_ENCODER, SetWSSConfig,
+ 2, 1, av7110->wssData);
+ } else {
+ av7110->wssData = 0;
+ rc = av7110_fw_cmd(av7110, COMTYPE_ENCODER, SetWSSConfig, 1, 0);
+ }
+ return (rc < 0) ? rc : count;
+}
/****************************************************************************
* INITIALIZATION
@@ -512,6 +604,9 @@ static struct saa7146_extension_ioctls ioctls[] = {
{ VIDIOC_S_TUNER, SAA7146_EXCLUSIVE },
{ VIDIOC_G_AUDIO, SAA7146_EXCLUSIVE },
{ VIDIOC_S_AUDIO, SAA7146_EXCLUSIVE },
+ { VIDIOC_G_SLICED_VBI_CAP, SAA7146_EXCLUSIVE },
+ { VIDIOC_G_FMT, SAA7146_BEFORE },
+ { VIDIOC_S_FMT, SAA7146_BEFORE },
{ 0, 0 }
};
@@ -587,7 +682,7 @@ int av7110_init_analog_module(struct av7110 *av7110)
printk("dvb-ttpci: DVB-C analog module @ card %d detected, initializing MSP3400\n",
av7110->dvb_adapter.num);
- av7110->adac_type = DVB_ADAC_MSP;
+ av7110->adac_type = DVB_ADAC_MSP34x0;
msleep(100); // the probing above resets the msp...
msp_readreg(av7110, MSP_RD_DSP, 0x001e, &version1);
msp_readreg(av7110, MSP_RD_DSP, 0x001f, &version2);
@@ -692,12 +787,11 @@ int av7110_init_v4l(struct av7110 *av7110)
saa7146_vv_release(dev);
return -ENODEV;
}
- if (av7110->analog_tuner_flags) {
- if (saa7146_register_device(&av7110->vbi_dev, dev, "av7110", VFL_TYPE_VBI)) {
- ERR(("cannot register vbi v4l2 device. skipping.\n"));
- } else {
+ if (saa7146_register_device(&av7110->vbi_dev, dev, "av7110", VFL_TYPE_VBI)) {
+ ERR(("cannot register vbi v4l2 device. skipping.\n"));
+ } else {
+ if (av7110->analog_tuner_flags)
av7110->analog_tuner_flags |= ANALOG_TUNER_VBI;
- }
}
return 0;
}
@@ -778,7 +872,7 @@ static int std_callback(struct saa7146_dev* dev, struct saa7146_standard *std)
static struct saa7146_ext_vv av7110_vv_data_st = {
.inputs = 1,
.audios = 1,
- .capabilities = 0,
+ .capabilities = V4L2_CAP_SLICED_VBI_OUTPUT,
.flags = 0,
.stds = &standard[0],
@@ -787,12 +881,16 @@ static struct saa7146_ext_vv av7110_vv_data_st = {
.ioctls = &ioctls[0],
.ioctl = av7110_ioctl,
+
+ .vbi_fops.open = av7110_vbi_reset,
+ .vbi_fops.release = av7110_vbi_reset,
+ .vbi_fops.write = av7110_vbi_write,
};
static struct saa7146_ext_vv av7110_vv_data_c = {
.inputs = 1,
.audios = 1,
- .capabilities = V4L2_CAP_TUNER | V4L2_CAP_VBI_CAPTURE,
+ .capabilities = V4L2_CAP_TUNER | V4L2_CAP_VBI_CAPTURE | V4L2_CAP_SLICED_VBI_OUTPUT,
.flags = SAA7146_USE_PORT_B_FOR_VBI,
.stds = &standard[0],
@@ -801,5 +899,9 @@ static struct saa7146_ext_vv av7110_vv_data_c = {
.ioctls = &ioctls[0],
.ioctl = av7110_ioctl,
+
+ .vbi_fops.open = av7110_vbi_reset,
+ .vbi_fops.release = av7110_vbi_reset,
+ .vbi_fops.write = av7110_vbi_write,
};
diff --git a/drivers/media/dvb/ttpci/budget-av.c b/drivers/media/dvb/ttpci/budget-av.c
index 9f51bae7194c..f9d00452e639 100644
--- a/drivers/media/dvb/ttpci/budget-av.c
+++ b/drivers/media/dvb/ttpci/budget-av.c
@@ -127,7 +127,7 @@ static int ciintf_read_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int ad
saa7146_setgpio(budget_av->budget.dev, 1, SAA7146_GPIO_OUTHI);
udelay(1);
- result = ttpci_budget_debiread(&budget_av->budget, DEBICICAM, address & 0xfff, 1, 0, 0);
+ result = ttpci_budget_debiread(&budget_av->budget, DEBICICAM, address & 0xfff, 1, 0, 1);
if (result == -ETIMEDOUT)
budget_av->slot_status = 0;
@@ -145,7 +145,7 @@ static int ciintf_write_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int a
saa7146_setgpio(budget_av->budget.dev, 1, SAA7146_GPIO_OUTHI);
udelay(1);
- result = ttpci_budget_debiwrite(&budget_av->budget, DEBICICAM, address & 0xfff, 1, value, 0, 0);
+ result = ttpci_budget_debiwrite(&budget_av->budget, DEBICICAM, address & 0xfff, 1, value, 0, 1);
if (result == -ETIMEDOUT)
budget_av->slot_status = 0;
@@ -192,7 +192,7 @@ static int ciintf_slot_reset(struct dvb_ca_en50221 *ca, int slot)
{
struct budget_av *budget_av = (struct budget_av *) ca->data;
struct saa7146_dev *saa = budget_av->budget.dev;
- int timeout = 500; // 5 seconds (4.4.6 Ready)
+ int timeout = 50; // 5 seconds (4.4.6 Ready)
if (slot != 0)
return -EINVAL;
@@ -256,19 +256,37 @@ static int ciintf_poll_slot_status(struct dvb_ca_en50221 *ca, int slot, int open
{
struct budget_av *budget_av = (struct budget_av *) ca->data;
struct saa7146_dev *saa = budget_av->budget.dev;
+ int cam_present = 0;
if (slot != 0)
return -EINVAL;
- if (!budget_av->slot_status) {
+ if (!budget_av->slot_status)
+ {
+ // first of all test the card detect line
saa7146_setgpio(saa, 3, SAA7146_GPIO_INPUT);
udelay(1);
if (saa7146_read(saa, PSR) & MASK_06)
{
+ cam_present = 1;
+ }
+ saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTLO);
+
+ // that is unreliable however, so try and read from IO memory
+ if (!cam_present)
+ {
+ saa7146_setgpio(budget_av->budget.dev, 1, SAA7146_GPIO_OUTLO);
+ if (ttpci_budget_debiread(&budget_av->budget, DEBICICAM, 0, 1, 0, 1) != -ETIMEDOUT)
+ {
+ cam_present = 1;
+ }
+ }
+
+ // did we find something?
+ if (cam_present) {
printk(KERN_INFO "budget-av: cam inserted\n");
budget_av->slot_status = 1;
}
- saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTLO);
} else if (!open) {
saa7146_setgpio(budget_av->budget.dev, 1, SAA7146_GPIO_OUTLO);
if (ttpci_budget_debiread(&budget_av->budget, DEBICICAM, 0, 1, 0, 1) == -ETIMEDOUT)
@@ -484,6 +502,140 @@ static int philips_su1278_ty_ci_pll_set(struct dvb_frontend *fe,
return 0;
}
+#define MIN2(a,b) ((a) < (b) ? (a) : (b))
+#define MIN3(a,b,c) MIN2(MIN2(a,b),c)
+
+static int philips_su1278sh2_tua6100_pll_set(struct dvb_frontend *fe,
+ struct i2c_adapter *i2c,
+ struct dvb_frontend_parameters *params)
+{
+ u8 reg0 [2] = { 0x00, 0x00 };
+ u8 reg1 [4] = { 0x01, 0x00, 0x00, 0x00 };
+ u8 reg2 [3] = { 0x02, 0x00, 0x00 };
+ int _fband;
+ int first_ZF;
+ int R, A, N, P, M;
+ struct i2c_msg msg = {.addr = 0x60,.flags = 0,.buf = NULL,.len = 0 };
+ int freq = params->frequency;
+
+ first_ZF = (freq) / 1000;
+
+ if (abs(MIN2(abs(first_ZF-1190),abs(first_ZF-1790))) <
+ abs(MIN3(abs(first_ZF-1202),abs(first_ZF-1542),abs(first_ZF-1890))))
+ _fband = 2;
+ else
+ _fband = 3;
+
+ if (_fband == 2) {
+ if (((first_ZF >= 950) && (first_ZF < 1350)) ||
+ ((first_ZF >= 1430) && (first_ZF < 1950)))
+ reg0[1] = 0x07;
+ else if (((first_ZF >= 1350) && (first_ZF < 1430)) ||
+ ((first_ZF >= 1950) && (first_ZF < 2150)))
+ reg0[1] = 0x0B;
+ }
+
+ if(_fband == 3) {
+ if (((first_ZF >= 950) && (first_ZF < 1350)) ||
+ ((first_ZF >= 1455) && (first_ZF < 1950)))
+ reg0[1] = 0x07;
+ else if (((first_ZF >= 1350) && (first_ZF < 1420)) ||
+ ((first_ZF >= 1950) && (first_ZF < 2150)))
+ reg0[1] = 0x0B;
+ else if ((first_ZF >= 1420) && (first_ZF < 1455))
+ reg0[1] = 0x0F;
+ }
+
+ if (first_ZF > 1525)
+ reg1[1] |= 0x80;
+ else
+ reg1[1] &= 0x7F;
+
+ if (_fband == 2) {
+ if (first_ZF > 1430) { /* 1430MHZ */
+ reg1[1] &= 0xCF; /* N2 */
+ reg2[1] &= 0xCF; /* R2 */
+ reg2[1] |= 0x10;
+ } else {
+ reg1[1] &= 0xCF; /* N2 */
+ reg1[1] |= 0x20;
+ reg2[1] &= 0xCF; /* R2 */
+ reg2[1] |= 0x10;
+ }
+ }
+
+ if (_fband == 3) {
+ if ((first_ZF >= 1455) &&
+ (first_ZF < 1630)) {
+ reg1[1] &= 0xCF; /* N2 */
+ reg1[1] |= 0x20;
+ reg2[1] &= 0xCF; /* R2 */
+ } else {
+ if (first_ZF < 1455) {
+ reg1[1] &= 0xCF; /* N2 */
+ reg1[1] |= 0x20;
+ reg2[1] &= 0xCF; /* R2 */
+ reg2[1] |= 0x10;
+ } else {
+ if (first_ZF >= 1630) {
+ reg1[1] &= 0xCF; /* N2 */
+ reg2[1] &= 0xCF; /* R2 */
+ reg2[1] |= 0x10;
+ }
+ }
+ }
+ }
+
+ /* set ports, enable P0 for symbol rates > 4Ms/s */
+ if (params->u.qpsk.symbol_rate >= 4000000)
+ reg1[1] |= 0x0c;
+ else
+ reg1[1] |= 0x04;
+
+ reg2[1] |= 0x0c;
+
+ R = 64;
+ A = 64;
+ P = 64; //32
+
+ M = (freq * R) / 4; /* in Mhz */
+ N = (M - A * 1000) / (P * 1000);
+
+ reg1[1] |= (N >> 9) & 0x03;
+ reg1[2] = (N >> 1) & 0xff;
+ reg1[3] = (N << 7) & 0x80;
+
+ reg2[1] |= (R >> 8) & 0x03;
+ reg2[2] = R & 0xFF; /* R */
+
+ reg1[3] |= A & 0x7f; /* A */
+
+ if (P == 64)
+ reg1[1] |= 0x40; /* Prescaler 64/65 */
+
+ reg0[1] |= 0x03;
+
+ /* already enabled - do not reenable i2c repeater or TX fails */
+ msg.buf = reg0;
+ msg.len = sizeof(reg0);
+ if (i2c_transfer(i2c, &msg, 1) != 1)
+ return -EIO;
+
+ stv0299_enable_plli2c(fe);
+ msg.buf = reg1;
+ msg.len = sizeof(reg1);
+ if (i2c_transfer(i2c, &msg, 1) != 1)
+ return -EIO;
+
+ stv0299_enable_plli2c(fe);
+ msg.buf = reg2;
+ msg.len = sizeof(reg2);
+ if (i2c_transfer(i2c, &msg, 1) != 1)
+ return -EIO;
+
+ return 0;
+}
+
static u8 typhoon_cinergy1200s_inittab[] = {
0x01, 0x15,
0x02, 0x30,
@@ -553,6 +705,18 @@ static struct stv0299_config cinergy_1200s_config = {
.pll_set = philips_su1278_ty_ci_pll_set,
};
+static struct stv0299_config cinergy_1200s_1894_0010_config = {
+ .demod_address = 0x68,
+ .inittab = typhoon_cinergy1200s_inittab,
+ .mclk = 88000000UL,
+ .invert = 1,
+ .skip_reinit = 0,
+ .lock_output = STV0229_LOCKOUTPUT_1,
+ .volt13_op0_op1 = STV0299_VOLT13_OP0,
+ .min_delay_ms = 100,
+ .set_symbol_rate = philips_su1278_ty_ci_set_symbol_rate,
+ .pll_set = philips_su1278sh2_tua6100_pll_set,
+};
static int philips_cu1216_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
{
@@ -749,6 +913,15 @@ static void frontend_init(struct budget_av *budget_av)
switch (saa->pci->subsystem_device) {
case SUBID_DVBS_KNC1:
+ if (saa->pci->subsystem_vendor == 0x1894) {
+ fe = stv0299_attach(&cinergy_1200s_1894_0010_config,
+ &budget_av->budget.i2c_adap);
+ } else {
+ fe = stv0299_attach(&typhoon_config,
+ &budget_av->budget.i2c_adap);
+ }
+ break;
+
case SUBID_DVBS_KNC1_PLUS:
case SUBID_DVBS_TYPHOON:
fe = stv0299_attach(&typhoon_config,
@@ -1003,6 +1176,7 @@ MAKE_BUDGET_INFO(cin1200t, "Terratec Cinergy 1200 DVB-T", BUDGET_CIN1200T);
static struct pci_device_id pci_tbl[] = {
MAKE_EXTENSION_PCI(knc1s, 0x1131, 0x4f56),
MAKE_EXTENSION_PCI(knc1s, 0x1131, 0x0010),
+ MAKE_EXTENSION_PCI(knc1s, 0x1894, 0x0010),
MAKE_EXTENSION_PCI(knc1sp, 0x1131, 0x0011),
MAKE_EXTENSION_PCI(knc1c, 0x1894, 0x0020),
MAKE_EXTENSION_PCI(knc1cp, 0x1894, 0x0021),
diff --git a/drivers/media/dvb/ttpci/budget-core.c b/drivers/media/dvb/ttpci/budget-core.c
index 017fcbccb8cc..633e68c341c8 100644
--- a/drivers/media/dvb/ttpci/budget-core.c
+++ b/drivers/media/dvb/ttpci/budget-core.c
@@ -404,9 +404,7 @@ int ttpci_budget_init(struct budget *budget, struct saa7146_dev *dev,
tasklet_init(&budget->vpe_tasklet, vpeirq, (unsigned long) budget);
/* frontend power on */
- if (bi->type == BUDGET_FS_ACTIVY)
- saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTHI);
- else
+ if (bi->type != BUDGET_FS_ACTIVY)
saa7146_setgpio(dev, 2, SAA7146_GPIO_OUTHI);
if (budget_register(budget) == 0) {
diff --git a/drivers/media/dvb/ttpci/budget.c b/drivers/media/dvb/ttpci/budget.c
index fafe6407b3d0..238c77b52f89 100644
--- a/drivers/media/dvb/ttpci/budget.c
+++ b/drivers/media/dvb/ttpci/budget.c
@@ -112,6 +112,7 @@ static int SendDiSEqCMsg (struct budget *budget, int len, u8 *msg, unsigned long
* Routines for the Fujitsu Siemens Activy budget card
* 22 kHz tone and DiSEqC are handled by the frontend.
* Voltage must be set here.
+ * GPIO 1: LNBP EN, GPIO 2: LNBP VSEL
*/
static int SetVoltage_Activy (struct budget *budget, fe_sec_voltage_t voltage)
{
@@ -121,11 +122,16 @@ static int SetVoltage_Activy (struct budget *budget, fe_sec_voltage_t voltage)
switch (voltage) {
case SEC_VOLTAGE_13:
+ saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTHI);
saa7146_setgpio(dev, 2, SAA7146_GPIO_OUTLO);
break;
case SEC_VOLTAGE_18:
+ saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTHI);
saa7146_setgpio(dev, 2, SAA7146_GPIO_OUTHI);
break;
+ case SEC_VOLTAGE_OFF:
+ saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTLO);
+ break;
default:
return -EINVAL;
}
@@ -206,7 +212,7 @@ static int lnbp21_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage)
return 0;
}
-static int lnbp21_enable_high_lnb_voltage(struct dvb_frontend* fe, int arg)
+static int lnbp21_enable_high_lnb_voltage(struct dvb_frontend* fe, long arg)
{
struct budget* budget = (struct budget*) fe->dvb->priv;
u8 buf;
@@ -580,6 +586,7 @@ static void frontend_init(struct budget *budget)
if (budget->dvb_frontend) {
budget->dvb_frontend->ops->set_voltage = lnbp21_set_voltage;
budget->dvb_frontend->ops->enable_high_lnb_voltage = lnbp21_enable_high_lnb_voltage;
+ budget->dvb_frontend->ops->dishnetwork_send_legacy_command = NULL;
if (lnbp21_init(budget)) {
printk("%s: No LNBP21 found!\n", __FUNCTION__);
goto error_out;
@@ -624,7 +631,7 @@ static void frontend_init(struct budget *budget)
budget->dvb_frontend = stv0299_attach(&alps_bsru6_config, &budget->i2c_adap);
if (budget->dvb_frontend) {
budget->dvb_frontend->ops->set_voltage = siemens_budget_set_voltage;
- break;
+ budget->dvb_frontend->ops->dishnetwork_send_legacy_command = NULL;
}
break;
@@ -632,7 +639,7 @@ static void frontend_init(struct budget *budget)
budget->dvb_frontend = tda8083_attach(&grundig_29504_451_config, &budget->i2c_adap);
if (budget->dvb_frontend) {
budget->dvb_frontend->ops->set_voltage = siemens_budget_set_voltage;
- break;
+ budget->dvb_frontend->ops->dishnetwork_send_legacy_command = NULL;
}
break;
diff --git a/drivers/media/dvb/ttpci/ttpci-eeprom.c b/drivers/media/dvb/ttpci/ttpci-eeprom.c
index 18aa22b5478d..1f31e91195b0 100644
--- a/drivers/media/dvb/ttpci/ttpci-eeprom.c
+++ b/drivers/media/dvb/ttpci/ttpci-eeprom.c
@@ -13,7 +13,7 @@
Holger Waechtler Convergence
Copyright (C) 2002-2003 Ralph Metzler <rjkm@metzlerbros.de>
- Metzler Brothers Systementwicklung GbR
+ Metzler Brothers Systementwicklung GbR
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
diff --git a/drivers/media/dvb/ttusb-budget/Kconfig b/drivers/media/dvb/ttusb-budget/Kconfig
index c6c1d41a2efb..914587d52b57 100644
--- a/drivers/media/dvb/ttusb-budget/Kconfig
+++ b/drivers/media/dvb/ttusb-budget/Kconfig
@@ -10,7 +10,7 @@ config DVB_TTUSB_BUDGET
Support for external USB adapters designed by Technotrend and
produced by Hauppauge, shipped under the brand name 'Nova-USB'.
- These devices don't have a MPEG decoder built in, so you need
+ These devices don't have a MPEG decoder built in, so you need
an external software decoder to watch TV.
Say Y if you own such a device and want to use it.
diff --git a/drivers/media/dvb/ttusb-dec/Kconfig b/drivers/media/dvb/ttusb-dec/Kconfig
index c334526af66f..83611012ef34 100644
--- a/drivers/media/dvb/ttusb-dec/Kconfig
+++ b/drivers/media/dvb/ttusb-dec/Kconfig
@@ -8,14 +8,15 @@ config DVB_TTUSB_DEC
produced by Hauppauge, shipped under the brand name 'DEC2000-t'
and 'DEC3000-s'.
- Even if these devices have a MPEG decoder built in, they transmit
+ Even if these devices have a MPEG decoder built in, they transmit
only compressed MPEG data over the USB bus, so you need
an external software decoder to watch TV on your computer.
- This driver needs external firmware. Please use the commands
- "<kerneldir>/Documentation/dvb/get_dvb_firmware dec2000t",
- "<kerneldir>/Documentation/dvb/get_dvb_firmware dec2540t",
- "<kerneldir>/Documentation/dvb/get_dvb_firmware dec3000s",
- download/extract them, and then copy them to /usr/lib/hotplug/firmware.
+ This driver needs external firmware. Please use the commands
+ "<kerneldir>/Documentation/dvb/get_dvb_firmware dec2000t",
+ "<kerneldir>/Documentation/dvb/get_dvb_firmware dec2540t",
+ "<kerneldir>/Documentation/dvb/get_dvb_firmware dec3000s",
+ download/extract them, and then copy them to /usr/lib/hotplug/firmware
+ or /lib/firmware (depending on configuration of firmware hotplug).
Say Y if you own such a device and want to use it.
diff --git a/drivers/media/dvb/ttusb-dec/ttusb_dec.c b/drivers/media/dvb/ttusb-dec/ttusb_dec.c
index 8abc21890129..d8966d1d25ee 100644
--- a/drivers/media/dvb/ttusb-dec/ttusb_dec.c
+++ b/drivers/media/dvb/ttusb-dec/ttusb_dec.c
@@ -369,7 +369,7 @@ static int ttusb_dec_get_stb_state (struct ttusb_dec *dec, unsigned int *mode,
static int ttusb_dec_audio_pes2ts_cb(void *priv, unsigned char *data)
{
- struct ttusb_dec *dec = (struct ttusb_dec *)priv;
+ struct ttusb_dec *dec = priv;
dec->audio_filter->feed->cb.ts(data, 188, NULL, 0,
&dec->audio_filter->feed->feed.ts,
@@ -380,7 +380,7 @@ static int ttusb_dec_audio_pes2ts_cb(void *priv, unsigned char *data)
static int ttusb_dec_video_pes2ts_cb(void *priv, unsigned char *data)
{
- struct ttusb_dec *dec = (struct ttusb_dec *)priv;
+ struct ttusb_dec *dec = priv;
dec->video_filter->feed->cb.ts(data, 188, NULL, 0,
&dec->video_filter->feed->feed.ts,
@@ -965,8 +965,8 @@ static int ttusb_dec_start_ts_feed(struct dvb_demux_feed *dvbdmxfeed)
case DMX_TS_PES_TELETEXT:
dec->pid[DMX_PES_TELETEXT] = dvbdmxfeed->pid;
- dprintk(" pes_type: DMX_TS_PES_TELETEXT\n");
- break;
+ dprintk(" pes_type: DMX_TS_PES_TELETEXT(not supported)\n");
+ return -ENOSYS;
case DMX_TS_PES_PCR:
dprintk(" pes_type: DMX_TS_PES_PCR\n");
@@ -975,8 +975,8 @@ static int ttusb_dec_start_ts_feed(struct dvb_demux_feed *dvbdmxfeed)
break;
case DMX_TS_PES_OTHER:
- dprintk(" pes_type: DMX_TS_PES_OTHER\n");
- break;
+ dprintk(" pes_type: DMX_TS_PES_OTHER(not supported)\n");
+ return -ENOSYS;
default:
dprintk(" pes_type: unknown (%d)\n", dvbdmxfeed->pes_type);
@@ -1182,7 +1182,7 @@ static void ttusb_dec_init_tasklet(struct ttusb_dec *dec)
(unsigned long)dec);
}
-static int ttusb_init_rc(struct ttusb_dec *dec)
+static int ttusb_init_rc( struct ttusb_dec *dec)
{
struct input_dev *input_dev;
u8 b[] = { 0x00, 0x01 };
@@ -1203,13 +1203,12 @@ static int ttusb_init_rc(struct ttusb_dec *dec)
input_dev->keycode = rc_keys;
for (i = 0; i < ARRAY_SIZE(rc_keys); i++)
- set_bit(rc_keys[i], input_dev->keybit);
+ set_bit(rc_keys[i], input_dev->keybit);
input_register_device(input_dev);
if (usb_submit_urb(dec->irq_urb, GFP_KERNEL))
printk("%s: usb_submit_urb failed\n",__FUNCTION__);
-
/* enable irq pipe */
ttusb_dec_send_command(dec,0xb0,sizeof(b),b,NULL,NULL);
@@ -1395,6 +1394,7 @@ static int ttusb_dec_init_stb(struct ttusb_dec *dec)
/* We can't trust the USB IDs that some firmwares
give the box */
switch (model) {
+ case 0x00070001:
case 0x00070008:
case 0x0007000c:
ttusb_dec_set_model(dec, TTUSB_DEC3000S);
@@ -1588,7 +1588,7 @@ static int fe_send_command(struct dvb_frontend* fe, const u8 command,
int param_length, const u8 params[],
int *result_length, u8 cmd_result[])
{
- struct ttusb_dec* dec = (struct ttusb_dec*) fe->dvb->priv;
+ struct ttusb_dec* dec = fe->dvb->priv;
return ttusb_dec_send_command(dec, command, param_length, params, result_length, cmd_result);
}
diff --git a/drivers/media/dvb/ttusb-dec/ttusbdecfe.c b/drivers/media/dvb/ttusb-dec/ttusbdecfe.c
index 725af3af5b27..a5a46175fa09 100644
--- a/drivers/media/dvb/ttusb-dec/ttusbdecfe.c
+++ b/drivers/media/dvb/ttusb-dec/ttusbdecfe.c
@@ -42,8 +42,39 @@ struct ttusbdecfe_state {
static int ttusbdecfe_read_status(struct dvb_frontend* fe, fe_status_t* status)
{
- *status = FE_HAS_SIGNAL | FE_HAS_VITERBI |
- FE_HAS_SYNC | FE_HAS_CARRIER | FE_HAS_LOCK;
+ struct ttusbdecfe_state* state = fe->demodulator_priv;
+ u8 b[] = { 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00 };
+ u8 result[4];
+ int len, ret;
+
+ *status=0;
+
+ ret=state->config->send_command(fe, 0x73, sizeof(b), b, &len, result);
+ if(ret)
+ return ret;
+
+ if(len != 4) {
+ printk(KERN_ERR "%s: unexpected reply\n", __FUNCTION__);
+ return -EIO;
+ }
+
+ switch(result[3]) {
+ case 1: /* not tuned yet */
+ case 2: /* no signal/no lock*/
+ break;
+ case 3: /* signal found and locked*/
+ *status = FE_HAS_SIGNAL | FE_HAS_VITERBI |
+ FE_HAS_SYNC | FE_HAS_CARRIER | FE_HAS_LOCK;
+ break;
+ case 4:
+ *status = FE_TIMEDOUT;
+ break;
+ default:
+ pr_info("%s: returned unknown value: %d\n",
+ __FUNCTION__, result[3]);
+ return -EIO;
+ }
return 0;
}
@@ -64,6 +95,16 @@ static int ttusbdecfe_dvbt_set_frontend(struct dvb_frontend* fe, struct dvb_fron
return 0;
}
+static int ttusbdecfe_dvbt_get_tune_settings(struct dvb_frontend* fe,
+ struct dvb_frontend_tune_settings* fesettings)
+{
+ fesettings->min_delay_ms = 1500;
+ /* Drift compensation makes no sense for DVB-T */
+ fesettings->step_size = 0;
+ fesettings->max_drift = 0;
+ return 0;
+}
+
static int ttusbdecfe_dvbs_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
{
struct ttusbdecfe_state* state = (struct ttusbdecfe_state*) fe->demodulator_priv;
@@ -212,6 +253,8 @@ static struct dvb_frontend_ops ttusbdecfe_dvbt_ops = {
.set_frontend = ttusbdecfe_dvbt_set_frontend,
+ .get_tune_settings = ttusbdecfe_dvbt_get_tune_settings,
+
.read_status = ttusbdecfe_read_status,
};
@@ -223,11 +266,11 @@ static struct dvb_frontend_ops ttusbdecfe_dvbs_ops = {
.frequency_min = 950000,
.frequency_max = 2150000,
.frequency_stepsize = 125,
+ .symbol_rate_min = 1000000, /* guessed */
+ .symbol_rate_max = 45000000, /* guessed */
.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_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_QPSK
},
.release = ttusbdecfe_release,
OpenPOWER on IntegriCloud