summaryrefslogtreecommitdiff
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.c54
-rw-r--r--drivers/media/dvb/b2c2/flexcop-misc.c1
-rw-r--r--drivers/media/dvb/b2c2/flexcop-reg.h1
-rw-r--r--drivers/media/dvb/b2c2/flexcop.c1
-rw-r--r--drivers/media/dvb/bt8xx/Kconfig4
-rw-r--r--drivers/media/dvb/bt8xx/dst.c144
-rw-r--r--drivers/media/dvb/bt8xx/dst_ca.c123
-rw-r--r--drivers/media/dvb/bt8xx/dst_common.h5
-rw-r--r--drivers/media/dvb/bt8xx/dvb-bt8xx.c114
-rw-r--r--drivers/media/dvb/bt8xx/dvb-bt8xx.h1
-rw-r--r--drivers/media/dvb/dvb-core/demux.h5
-rw-r--r--drivers/media/dvb/dvb-core/dvb_demux.c2
-rw-r--r--drivers/media/dvb/dvb-core/dvb_frontend.c118
-rw-r--r--drivers/media/dvb/dvb-core/dvb_frontend.h3
-rw-r--r--drivers/media/dvb/dvb-usb/a800.c4
-rw-r--r--drivers/media/dvb/dvb-usb/dibusb-mb.c59
-rw-r--r--drivers/media/dvb/dvb-usb/dibusb.h4
-rw-r--r--drivers/media/dvb/dvb-usb/dvb-usb-ids.h5
-rw-r--r--drivers/media/dvb/dvb-usb/dvb-usb-urb.c4
-rw-r--r--drivers/media/dvb/frontends/Kconfig8
-rw-r--r--drivers/media/dvb/frontends/Makefile1
-rw-r--r--drivers/media/dvb/frontends/cx24110.c1
-rw-r--r--drivers/media/dvb/frontends/dvb-pll.c54
-rw-r--r--drivers/media/dvb/frontends/dvb-pll.h4
-rw-r--r--drivers/media/dvb/frontends/dvb_dummy_fe.c4
-rw-r--r--drivers/media/dvb/frontends/l64781.c3
-rw-r--r--drivers/media/dvb/frontends/lgdt330x.c29
-rw-r--r--drivers/media/dvb/frontends/lgdt330x.h4
-rw-r--r--drivers/media/dvb/frontends/mt312.c3
-rw-r--r--drivers/media/dvb/frontends/nxt200x.c1205
-rw-r--r--drivers/media/dvb/frontends/nxt200x.h61
-rw-r--r--drivers/media/dvb/frontends/or51132.c10
-rw-r--r--drivers/media/dvb/frontends/or51211.c8
-rw-r--r--drivers/media/dvb/frontends/stv0299.c100
-rw-r--r--drivers/media/dvb/frontends/stv0299.h3
-rw-r--r--drivers/media/dvb/frontends/tda1004x.c21
-rw-r--r--drivers/media/dvb/pluto2/pluto2.c9
-rw-r--r--drivers/media/dvb/ttpci/av7110.c6
-rw-r--r--drivers/media/dvb/ttpci/budget-av.c4
-rw-r--r--drivers/media/dvb/ttpci/budget-ci.c4
-rw-r--r--drivers/media/dvb/ttpci/budget-patch.c3
-rw-r--r--drivers/media/dvb/ttpci/budget.c120
-rw-r--r--drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c5
43 files changed, 2028 insertions, 294 deletions
diff --git a/drivers/media/dvb/b2c2/flexcop-fe-tuner.c b/drivers/media/dvb/b2c2/flexcop-fe-tuner.c
index 47e28b0ee951..a35330315f65 100644
--- a/drivers/media/dvb/b2c2/flexcop-fe-tuner.c
+++ b/drivers/media/dvb/b2c2/flexcop-fe-tuner.c
@@ -13,6 +13,8 @@
#include "bcm3510.h"
#include "stv0297.h"
#include "mt312.h"
+#include "lgdt330x.h"
+#include "dvb-pll.h"
/* lnb control */
@@ -234,7 +236,6 @@ static struct stv0299_config samsung_tbmu24112_config = {
.inittab = samsung_tbmu24112_inittab,
.mclk = 88000000UL,
.invert = 0,
- .enhanced_tuning = 0,
.skip_reinit = 0,
.lock_output = STV0229_LOCKOUTPUT_LK,
.volt13_op0_op1 = STV0299_VOLT13_OP1,
@@ -296,6 +297,52 @@ static int flexcop_fe_request_firmware(struct dvb_frontend* fe, const struct fir
return request_firmware(fw, name, fc->dev);
}
+static int lgdt3303_pll_set(struct dvb_frontend* fe,
+ struct dvb_frontend_parameters* params)
+{
+ struct flexcop_device *fc = fe->dvb->priv;
+ u8 buf[4];
+ struct i2c_msg msg =
+ { .addr = 0x61, .flags = 0, .buf = buf, .len = 4 };
+ int err;
+
+ dvb_pll_configure(&dvb_pll_tdvs_tua6034,buf, params->frequency, 0);
+ dprintk(1, "%s: tuner at 0x%02x bytes: 0x%02x 0x%02x 0x%02x 0x%02x\n",
+ __FUNCTION__, msg.addr, buf[0],buf[1],buf[2],buf[3]);
+ if ((err = i2c_transfer(&fc->i2c_adap, &msg, 1)) != 1) {
+ printk(KERN_WARNING "lgdt3303: %s error "
+ "(addr %02x <- %02x, err = %i)\n",
+ __FUNCTION__, buf[0], buf[1], err);
+ if (err < 0)
+ return err;
+ else
+ return -EREMOTEIO;
+ }
+
+ buf[0] = 0x86 | 0x18;
+ buf[1] = 0x50;
+ msg.len = 2;
+ if ((err = i2c_transfer(&fc->i2c_adap, &msg, 1)) != 1) {
+ printk(KERN_WARNING "lgdt3303: %s error "
+ "(addr %02x <- %02x, err = %i)\n",
+ __FUNCTION__, buf[0], buf[1], err);
+ if (err < 0)
+ return err;
+ else
+ return -EREMOTEIO;
+ }
+
+ return 0;
+}
+
+static struct lgdt330x_config air2pc_atsc_hd5000_config = {
+ .demod_address = 0x59,
+ .demod_chip = LGDT3303,
+ .serial_mpeg = 0x04,
+ .pll_set = lgdt3303_pll_set,
+ .clock_polarity_flip = 1,
+};
+
static struct nxt2002_config samsung_tbmv_config = {
.demod_address = 0x0a,
.request_firmware = flexcop_fe_request_firmware,
@@ -458,6 +505,11 @@ int flexcop_frontend_init(struct flexcop_device *fc)
fc->dev_type = FC_AIR_ATSC2;
info("found the nxt2002 at i2c address: 0x%02x",samsung_tbmv_config.demod_address);
} else
+ /* try the air atsc 3nd generation (lgdt3303) */
+ if ((fc->fe = lgdt330x_attach(&air2pc_atsc_hd5000_config, &fc->i2c_adap)) != NULL) {
+ fc->dev_type = FC_AIR_ATSC3;
+ info("found the lgdt3303 at i2c address: 0x%02x",air2pc_atsc_hd5000_config.demod_address);
+ } else
/* try the air atsc 1nd generation (bcm3510)/panasonic ct10s */
if ((fc->fe = bcm3510_attach(&air2pc_atsc_first_gen_config, &fc->i2c_adap)) != NULL) {
fc->dev_type = FC_AIR_ATSC1;
diff --git a/drivers/media/dvb/b2c2/flexcop-misc.c b/drivers/media/dvb/b2c2/flexcop-misc.c
index 3a08d38b318a..62282d8dbfa8 100644
--- a/drivers/media/dvb/b2c2/flexcop-misc.c
+++ b/drivers/media/dvb/b2c2/flexcop-misc.c
@@ -51,6 +51,7 @@ const char *flexcop_device_names[] = {
"Sky2PC/SkyStar 2 DVB-S",
"Sky2PC/SkyStar 2 DVB-S (old version)",
"Cable2PC/CableStar 2 DVB-C",
+ "Air2PC/AirStar 2 ATSC 3rd generation (HD5000)",
};
const char *flexcop_bus_names[] = {
diff --git a/drivers/media/dvb/b2c2/flexcop-reg.h b/drivers/media/dvb/b2c2/flexcop-reg.h
index 4ae1eb5bfe98..23cc6431e2b8 100644
--- a/drivers/media/dvb/b2c2/flexcop-reg.h
+++ b/drivers/media/dvb/b2c2/flexcop-reg.h
@@ -26,6 +26,7 @@ typedef enum {
FC_SKY,
FC_SKY_OLD,
FC_CABLE,
+ FC_AIR_ATSC3,
} flexcop_device_type_t;
typedef enum {
diff --git a/drivers/media/dvb/b2c2/flexcop.c b/drivers/media/dvb/b2c2/flexcop.c
index 12873d435406..123ed96f6faa 100644
--- a/drivers/media/dvb/b2c2/flexcop.c
+++ b/drivers/media/dvb/b2c2/flexcop.c
@@ -193,6 +193,7 @@ static void flexcop_reset(struct flexcop_device *fc)
v204 = fc->read_ibi_reg(fc,misc_204);
v204.misc_204.Per_reset_sig = 0;
fc->write_ibi_reg(fc,misc_204,v204);
+ msleep(1);
v204.misc_204.Per_reset_sig = 1;
fc->write_ibi_reg(fc,misc_204,v204);
}
diff --git a/drivers/media/dvb/bt8xx/Kconfig b/drivers/media/dvb/bt8xx/Kconfig
index 1e85d16491b0..2337b41714e0 100644
--- a/drivers/media/dvb/bt8xx/Kconfig
+++ b/drivers/media/dvb/bt8xx/Kconfig
@@ -6,10 +6,12 @@ config DVB_BT8XX
select DVB_NXT6000
select DVB_CX24110
select DVB_OR51211
+ select DVB_LGDT330X
help
Support for PCI cards based on the Bt8xx PCI bridge. Examples are
the Nebula cards, the Pinnacle PCTV cards, the Twinhan DST cards,
- the pcHDTV HD2000 cards, and certain AVerMedia cards.
+ the pcHDTV HD2000 cards, the DViCO FusionHDTV Lite cards, and
+ some AVerMedia cards.
Since these cards have no MPEG decoder onboard, they transmit
only compressed MPEG data over the PCI bus, so you need
diff --git a/drivers/media/dvb/bt8xx/dst.c b/drivers/media/dvb/bt8xx/dst.c
index 34a837a1abf4..8977c7a313df 100644
--- a/drivers/media/dvb/bt8xx/dst.c
+++ b/drivers/media/dvb/bt8xx/dst.c
@@ -690,8 +690,8 @@ struct dst_types dst_tlist[] = {
.device_id = "DTT-CI",
.offset = 1,
.dst_type = DST_TYPE_IS_TERR,
- .type_flags = DST_TYPE_HAS_TS204 | DST_TYPE_HAS_FW_2,
- .dst_feature = 0
+ .type_flags = DST_TYPE_HAS_TS204 | DST_TYPE_HAS_NEWTUNE | DST_TYPE_HAS_FW_2 | DST_TYPE_HAS_MULTI_FE,
+ .dst_feature = DST_TYPE_HAS_CA
},
{
@@ -796,6 +796,56 @@ static int dst_get_vendor(struct dst_state *state)
return 0;
}
+static int dst_get_tuner_info(struct dst_state *state)
+{
+ u8 get_tuner_1[] = { 0x00, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+ u8 get_tuner_2[] = { 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+
+ get_tuner_1[7] = dst_check_sum(get_tuner_1, 7);
+ get_tuner_2[7] = dst_check_sum(get_tuner_2, 7);
+ if (state->type_flags & DST_TYPE_HAS_MULTI_FE) {
+ if (dst_command(state, get_tuner_2, 8) < 0) {
+ dprintk(verbose, DST_INFO, 1, "Unsupported Command");
+ return -1;
+ }
+ } else {
+ if (dst_command(state, get_tuner_1, 8) < 0) {
+ dprintk(verbose, DST_INFO, 1, "Unsupported Command");
+ return -1;
+ }
+ }
+ memset(&state->board_info, '\0', 8);
+ memcpy(&state->board_info, &state->rxbuffer, 8);
+ if (state->type_flags & DST_TYPE_HAS_MULTI_FE) {
+ if (state->board_info[1] == 0x0b) {
+ if (state->type_flags & DST_TYPE_HAS_TS204)
+ state->type_flags &= ~DST_TYPE_HAS_TS204;
+ state->type_flags |= DST_TYPE_HAS_NEWTUNE;
+ dprintk(verbose, DST_INFO, 1, "DST type has TS=188");
+ } else {
+ if (state->type_flags & DST_TYPE_HAS_NEWTUNE)
+ state->type_flags &= ~DST_TYPE_HAS_NEWTUNE;
+ state->type_flags |= DST_TYPE_HAS_TS204;
+ dprintk(verbose, DST_INFO, 1, "DST type has TS=204");
+ }
+ } else {
+ if (state->board_info[0] == 0xbc) {
+ if (state->type_flags & DST_TYPE_HAS_TS204)
+ state->type_flags &= ~DST_TYPE_HAS_TS204;
+ state->type_flags |= DST_TYPE_HAS_NEWTUNE;
+ dprintk(verbose, DST_INFO, 1, "DST type has TS=188, Daughterboard=[%d]", state->board_info[1]);
+
+ } else if (state->board_info[0] == 0xcc) {
+ if (state->type_flags & DST_TYPE_HAS_NEWTUNE)
+ state->type_flags &= ~DST_TYPE_HAS_NEWTUNE;
+ state->type_flags |= DST_TYPE_HAS_TS204;
+ dprintk(verbose, DST_INFO, 1, "DST type has TS=204 Daughterboard=[%d]", state->board_info[1]);
+ }
+ }
+
+ return 0;
+}
+
static int dst_get_device_id(struct dst_state *state)
{
u8 reply;
@@ -855,15 +905,12 @@ static int dst_get_device_id(struct dst_state *state)
state->dst_type = use_dst_type;
dst_type_flags_print(state->type_flags);
- if (state->type_flags & DST_TYPE_HAS_TS204) {
- dst_packsize(state, 204);
- }
-
return 0;
}
static int dst_probe(struct dst_state *state)
{
+ sema_init(&state->dst_mutex, 1);
if ((rdc_8820_reset(state)) < 0) {
dprintk(verbose, DST_ERROR, 1, "RDC 8820 RESET Failed.");
return -1;
@@ -886,6 +933,13 @@ static int dst_probe(struct dst_state *state)
dprintk(verbose, DST_INFO, 1, "MAC: Unsupported command");
return 0;
}
+ if ((state->type_flags & DST_TYPE_HAS_MULTI_FE) || (state->type_flags & DST_TYPE_HAS_FW_BUILD)) {
+ if (dst_get_tuner_info(state) < 0)
+ dprintk(verbose, DST_INFO, 1, "Tuner: Unsupported command");
+ }
+ if (state->type_flags & DST_TYPE_HAS_TS204) {
+ dst_packsize(state, 204);
+ }
if (state->type_flags & DST_TYPE_HAS_FW_BUILD) {
if (dst_fw_ver(state) < 0) {
dprintk(verbose, DST_INFO, 1, "FW: Unsupported command");
@@ -907,21 +961,23 @@ static int dst_probe(struct dst_state *state)
int dst_command(struct dst_state *state, u8 *data, u8 len)
{
u8 reply;
+
+ down(&state->dst_mutex);
if ((dst_comm_init(state)) < 0) {
dprintk(verbose, DST_NOTICE, 1, "DST Communication Initialization Failed.");
- return -1;
+ goto error;
}
if (write_dst(state, data, len)) {
dprintk(verbose, DST_INFO, 1, "Tring to recover.. ");
if ((dst_error_recovery(state)) < 0) {
dprintk(verbose, DST_ERROR, 1, "Recovery Failed.");
- return -1;
+ goto error;
}
- return -1;
+ goto error;
}
if ((dst_pio_disable(state)) < 0) {
dprintk(verbose, DST_ERROR, 1, "PIO Disable Failed.");
- return -1;
+ goto error;
}
if (state->type_flags & DST_TYPE_HAS_FW_1)
udelay(3000);
@@ -929,36 +985,41 @@ int dst_command(struct dst_state *state, u8 *data, u8 len)
dprintk(verbose, DST_DEBUG, 1, "Trying to recover.. ");
if ((dst_error_recovery(state)) < 0) {
dprintk(verbose, DST_INFO, 1, "Recovery Failed.");
- return -1;
+ goto error;
}
- return -1;
+ goto error;
}
if (reply != ACK) {
dprintk(verbose, DST_INFO, 1, "write not acknowledged 0x%02x ", reply);
- return -1;
+ goto error;
}
if (len >= 2 && data[0] == 0 && (data[1] == 1 || data[1] == 3))
- return 0;
+ goto error;
if (state->type_flags & DST_TYPE_HAS_FW_1)
udelay(3000);
else
udelay(2000);
if (!dst_wait_dst_ready(state, NO_DELAY))
- return -1;
+ goto error;
if (read_dst(state, state->rxbuffer, FIXED_COMM)) {
dprintk(verbose, DST_DEBUG, 1, "Trying to recover.. ");
if ((dst_error_recovery(state)) < 0) {
dprintk(verbose, DST_INFO, 1, "Recovery failed.");
- return -1;
+ goto error;
}
- return -1;
+ goto error;
}
if (state->rxbuffer[7] != dst_check_sum(state->rxbuffer, 7)) {
dprintk(verbose, DST_INFO, 1, "checksum failure");
- return -1;
+ goto error;
}
-
+ up(&state->dst_mutex);
return 0;
+
+error:
+ up(&state->dst_mutex);
+ return -EIO;
+
}
EXPORT_SYMBOL(dst_command);
@@ -1016,7 +1077,7 @@ static int dst_get_tuna(struct dst_state *state)
return 0;
state->diseq_flags &= ~(HAS_LOCK);
if (!dst_wait_dst_ready(state, NO_DELAY))
- return 0;
+ return -EIO;
if (state->type_flags & DST_TYPE_HAS_NEWTUNE)
/* how to get variable length reply ???? */
retval = read_dst(state, state->rx_tuna, 10);
@@ -1024,22 +1085,27 @@ static int dst_get_tuna(struct dst_state *state)
retval = read_dst(state, &state->rx_tuna[2], FIXED_COMM);
if (retval < 0) {
dprintk(verbose, DST_DEBUG, 1, "read not successful");
- return 0;
+ return retval;
}
if (state->type_flags & DST_TYPE_HAS_NEWTUNE) {
if (state->rx_tuna[9] != dst_check_sum(&state->rx_tuna[0], 9)) {
dprintk(verbose, DST_INFO, 1, "checksum failure ? ");
- return 0;
+ return -EIO;
}
} else {
if (state->rx_tuna[9] != dst_check_sum(&state->rx_tuna[2], 7)) {
dprintk(verbose, DST_INFO, 1, "checksum failure? ");
- return 0;
+ return -EIO;
}
}
if (state->rx_tuna[2] == 0 && state->rx_tuna[3] == 0)
return 0;
- state->decode_freq = ((state->rx_tuna[2] & 0x7f) << 8) + state->rx_tuna[3];
+ if (state->dst_type == DST_TYPE_IS_SAT) {
+ state->decode_freq = ((state->rx_tuna[2] & 0x7f) << 8) + state->rx_tuna[3];
+ } else {
+ state->decode_freq = ((state->rx_tuna[2] & 0x7f) << 16) + (state->rx_tuna[3] << 8) + state->rx_tuna[4];
+ }
+ state->decode_freq = state->decode_freq * 1000;
state->decode_lock = 1;
state->diseq_flags |= HAS_LOCK;
@@ -1062,10 +1128,10 @@ static int dst_write_tuna(struct dvb_frontend *fe)
dst_set_voltage(fe, SEC_VOLTAGE_13);
}
state->diseq_flags &= ~(HAS_LOCK | ATTEMPT_TUNE);
-
+ down(&state->dst_mutex);
if ((dst_comm_init(state)) < 0) {
dprintk(verbose, DST_DEBUG, 1, "DST Communication initialization failed.");
- return -1;
+ goto error;
}
if (state->type_flags & DST_TYPE_HAS_NEWTUNE) {
state->tx_tuna[9] = dst_check_sum(&state->tx_tuna[0], 9);
@@ -1077,23 +1143,29 @@ static int dst_write_tuna(struct dvb_frontend *fe)
if (retval < 0) {
dst_pio_disable(state);
dprintk(verbose, DST_DEBUG, 1, "write not successful");
- return retval;
+ goto werr;
}
if ((dst_pio_disable(state)) < 0) {
dprintk(verbose, DST_DEBUG, 1, "DST PIO disable failed !");
- return -1;
+ goto error;
}
if ((read_dst(state, &reply, GET_ACK) < 0)) {
dprintk(verbose, DST_DEBUG, 1, "read verify not successful.");
- return -1;
+ goto error;
}
if (reply != ACK) {
dprintk(verbose, DST_DEBUG, 1, "write not acknowledged 0x%02x ", reply);
- return 0;
+ goto error;
}
state->diseq_flags |= ATTEMPT_TUNE;
-
- return dst_get_tuna(state);
+ retval = dst_get_tuna(state);
+werr:
+ up(&state->dst_mutex);
+ return retval;
+
+error:
+ up(&state->dst_mutex);
+ return -EIO;
}
/*
@@ -1331,9 +1403,7 @@ struct dst_state *dst_attach(struct dst_state *state, struct dvb_adapter *dvb_ad
{
/* check if the ASIC is there */
if (dst_probe(state) < 0) {
- if (state)
- kfree(state);
-
+ kfree(state);
return NULL;
}
/* determine settings based on type */
@@ -1349,9 +1419,7 @@ struct dst_state *dst_attach(struct dst_state *state, struct dvb_adapter *dvb_ad
break;
default:
dprintk(verbose, DST_ERROR, 1, "unknown DST type. please report to the LinuxTV.org DVB mailinglist.");
- if (state)
- kfree(state);
-
+ kfree(state);
return NULL;
}
diff --git a/drivers/media/dvb/bt8xx/dst_ca.c b/drivers/media/dvb/bt8xx/dst_ca.c
index 6776a592045f..e6541aff3996 100644
--- a/drivers/media/dvb/bt8xx/dst_ca.c
+++ b/drivers/media/dvb/bt8xx/dst_ca.c
@@ -69,62 +69,53 @@ static int ca_set_pid(void)
}
-static int put_checksum(u8 *check_string, int length)
+static void put_checksum(u8 *check_string, int length)
{
- u8 i = 0, checksum = 0;
-
- dprintk(verbose, DST_CA_DEBUG, 1, " ========================= Checksum calculation ===========================");
- dprintk(verbose, DST_CA_DEBUG, 1, " String Length=[0x%02x]", length);
- dprintk(verbose, DST_CA_DEBUG, 1, " String=[");
-
- while (i < length) {
- dprintk(verbose, DST_CA_DEBUG, 0, " %02x", check_string[i]);
- checksum += check_string[i];
- i++;
- }
- dprintk(verbose, DST_CA_DEBUG, 0, " ]\n");
- dprintk(verbose, DST_CA_DEBUG, 1, "Sum=[%02x]\n", checksum);
- check_string[length] = ~checksum + 1;
- dprintk(verbose, DST_CA_DEBUG, 1, " Checksum=[%02x]", check_string[length]);
- dprintk(verbose, DST_CA_DEBUG, 1, " ==========================================================================");
-
- return 0;
+ dprintk(verbose, DST_CA_DEBUG, 1, " Computing string checksum.");
+ dprintk(verbose, DST_CA_DEBUG, 1, " -> string length : 0x%02x", length);
+ check_string[length] = dst_check_sum (check_string, length);
+ dprintk(verbose, DST_CA_DEBUG, 1, " -> checksum : 0x%02x", check_string[length]);
}
static int dst_ci_command(struct dst_state* state, u8 * data, u8 *ca_string, u8 len, int read)
{
u8 reply;
+ down(&state->dst_mutex);
dst_comm_init(state);
msleep(65);
if (write_dst(state, data, len)) {
dprintk(verbose, DST_CA_INFO, 1, " Write not successful, trying to recover");
dst_error_recovery(state);
- return -1;
+ goto error;
}
if ((dst_pio_disable(state)) < 0) {
dprintk(verbose, DST_CA_ERROR, 1, " DST PIO disable failed.");
- return -1;
+ goto error;
}
if (read_dst(state, &reply, GET_ACK) < 0) {
dprintk(verbose, DST_CA_INFO, 1, " Read not successful, trying to recover");
dst_error_recovery(state);
- return -1;
+ goto error;
}
if (read) {
if (! dst_wait_dst_ready(state, LONG_DELAY)) {
dprintk(verbose, DST_CA_NOTICE, 1, " 8820 not ready");
- return -1;
+ goto error;
}
if (read_dst(state, ca_string, 128) < 0) { /* Try to make this dynamic */
dprintk(verbose, DST_CA_INFO, 1, " Read not successful, trying to recover");
dst_error_recovery(state);
- return -1;
+ goto error;
}
}
-
+ up(&state->dst_mutex);
return 0;
+
+error:
+ up(&state->dst_mutex);
+ return -EIO;
}
@@ -166,7 +157,7 @@ static int ca_get_app_info(struct dst_state *state)
return 0;
}
-static int ca_get_slot_caps(struct dst_state *state, struct ca_caps *p_ca_caps, void *arg)
+static int ca_get_slot_caps(struct dst_state *state, struct ca_caps *p_ca_caps, void __user *arg)
{
int i;
u8 slot_cap[256];
@@ -192,25 +183,25 @@ static int ca_get_slot_caps(struct dst_state *state, struct ca_caps *p_ca_caps,
p_ca_caps->descr_num = slot_cap[7];
p_ca_caps->descr_type = 1;
- if (copy_to_user((struct ca_caps *)arg, p_ca_caps, sizeof (struct ca_caps)))
+ if (copy_to_user(arg, p_ca_caps, sizeof (struct ca_caps)))
return -EFAULT;
return 0;
}
/* Need some more work */
-static int ca_get_slot_descr(struct dst_state *state, struct ca_msg *p_ca_message, void *arg)
+static int ca_get_slot_descr(struct dst_state *state, struct ca_msg *p_ca_message, void __user *arg)
{
return -EOPNOTSUPP;
}
-static int ca_get_slot_info(struct dst_state *state, struct ca_slot_info *p_ca_slot_info, void *arg)
+static int ca_get_slot_info(struct dst_state *state, struct ca_slot_info *p_ca_slot_info, void __user *arg)
{
int i;
static u8 slot_command[8] = {0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff};
- u8 *slot_info = state->rxbuffer;
+ u8 *slot_info = state->messages;
put_checksum(&slot_command[0], 7);
if ((dst_put_ci(state, slot_command, sizeof (slot_command), slot_info, GET_REPLY)) < 0) {
@@ -238,19 +229,19 @@ static int ca_get_slot_info(struct dst_state *state, struct ca_slot_info *p_ca_s
} else
p_ca_slot_info->flags = 0;
- if (copy_to_user((struct ca_slot_info *)arg, p_ca_slot_info, sizeof (struct ca_slot_info)))
+ if (copy_to_user(arg, p_ca_slot_info, sizeof (struct ca_slot_info)))
return -EFAULT;
return 0;
}
-static int ca_get_message(struct dst_state *state, struct ca_msg *p_ca_message, void *arg)
+static int ca_get_message(struct dst_state *state, struct ca_msg *p_ca_message, void __user *arg)
{
u8 i = 0;
u32 command = 0;
- if (copy_from_user(p_ca_message, (void *)arg, sizeof (struct ca_msg)))
+ if (copy_from_user(p_ca_message, arg, sizeof (struct ca_msg)))
return -EFAULT;
if (p_ca_message->msg) {
@@ -266,7 +257,7 @@ static int ca_get_message(struct dst_state *state, struct ca_msg *p_ca_message,
switch (command) {
case CA_APP_INFO:
memcpy(p_ca_message->msg, state->messages, 128);
- if (copy_to_user((void *)arg, p_ca_message, sizeof (struct ca_msg)) )
+ if (copy_to_user(arg, p_ca_message, sizeof (struct ca_msg)) )
return -EFAULT;
break;
}
@@ -315,7 +306,7 @@ static int write_to_8820(struct dst_state *state, struct ca_msg *hw_buffer, u8 l
return 0;
}
-u32 asn_1_decode(u8 *asn_1_array)
+static u32 asn_1_decode(u8 *asn_1_array)
{
u8 length_field = 0, word_count = 0, count = 0;
u32 length = 0;
@@ -328,7 +319,8 @@ u32 asn_1_decode(u8 *asn_1_array)
} else {
word_count = length_field & 0x7f;
for (count = 0; count < word_count; count++) {
- length = (length | asn_1_array[count + 1]) << 8;
+ length = length << 8;
+ length += asn_1_array[count + 1];
dprintk(verbose, DST_CA_DEBUG, 1, " Length=[%04x]", length);
}
}
@@ -399,13 +391,14 @@ static int dst_check_ca_pmt(struct dst_state *state, struct ca_msg *p_ca_message
return 0;
}
-static int ca_send_message(struct dst_state *state, struct ca_msg *p_ca_message, void *arg)
+static int ca_send_message(struct dst_state *state, struct ca_msg *p_ca_message, void __user *arg)
{
int i = 0;
unsigned int ca_message_header_len;
u32 command = 0;
struct ca_msg *hw_buffer;
+ int result = 0;
if ((hw_buffer = (struct ca_msg *) kmalloc(sizeof (struct ca_msg), GFP_KERNEL)) == NULL) {
dprintk(verbose, DST_CA_ERROR, 1, " Memory allocation failure");
@@ -413,8 +406,11 @@ static int ca_send_message(struct dst_state *state, struct ca_msg *p_ca_message,
}
dprintk(verbose, DST_CA_DEBUG, 1, " ");
- if (copy_from_user(p_ca_message, (void *)arg, sizeof (struct ca_msg)))
- return -EFAULT;
+ if (copy_from_user(p_ca_message, (void *)arg, sizeof (struct ca_msg))) {
+ result = -EFAULT;
+ goto free_mem_and_exit;
+ }
+
if (p_ca_message->msg) {
ca_message_header_len = p_ca_message->length; /* Restore it back when you are done */
@@ -433,7 +429,8 @@ static int ca_send_message(struct dst_state *state, struct ca_msg *p_ca_message,
dprintk(verbose, DST_CA_DEBUG, 1, "Command = SEND_CA_PMT");
if ((ca_set_pmt(state, p_ca_message, hw_buffer, 0, 0)) < 0) { // code simplification started
dprintk(verbose, DST_CA_ERROR, 1, " -->CA_PMT Failed !");
- return -1;
+ result = -1;
+ goto free_mem_and_exit;
}
dprintk(verbose, DST_CA_INFO, 1, " -->CA_PMT Success !");
break;
@@ -442,7 +439,8 @@ static int ca_send_message(struct dst_state *state, struct ca_msg *p_ca_message,
/* Have to handle the 2 basic types of cards here */
if ((dst_check_ca_pmt(state, p_ca_message, hw_buffer)) < 0) {
dprintk(verbose, DST_CA_ERROR, 1, " -->CA_PMT_REPLY Failed !");
- return -1;
+ result = -1;
+ goto free_mem_and_exit;
}
dprintk(verbose, DST_CA_INFO, 1, " -->CA_PMT_REPLY Success !");
break;
@@ -451,22 +449,28 @@ static int ca_send_message(struct dst_state *state, struct ca_msg *p_ca_message,
if ((ca_get_app_info(state)) < 0) {
dprintk(verbose, DST_CA_ERROR, 1, " -->CA_APP_INFO_ENQUIRY Failed !");
- return -1;
+ result = -1;
+ goto free_mem_and_exit;
}
dprintk(verbose, DST_CA_INFO, 1, " -->CA_APP_INFO_ENQUIRY Success !");
break;
}
}
- return 0;
+free_mem_and_exit:
+ kfree (hw_buffer);
+
+ return result;
}
-static int dst_ca_ioctl(struct inode *inode, struct file *file, unsigned int cmd, void *arg)
+static int dst_ca_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long ioctl_arg)
{
struct dvb_device* dvbdev = (struct dvb_device*) file->private_data;
struct dst_state* state = (struct dst_state*) dvbdev->priv;
struct ca_slot_info *p_ca_slot_info;
struct ca_caps *p_ca_caps;
struct ca_msg *p_ca_message;
+ void __user *arg = (void __user *)ioctl_arg;
+ int result = 0;
if ((p_ca_message = (struct ca_msg *) kmalloc(sizeof (struct ca_msg), GFP_KERNEL)) == NULL) {
dprintk(verbose, DST_CA_ERROR, 1, " Memory allocation failure");
@@ -486,14 +490,16 @@ static int dst_ca_ioctl(struct inode *inode, struct file *file, unsigned int cmd
dprintk(verbose, DST_CA_INFO, 1, " Sending message");
if ((ca_send_message(state, p_ca_message, arg)) < 0) {
dprintk(verbose, DST_CA_ERROR, 1, " -->CA_SEND_MSG Failed !");
- return -1;
+ result = -1;
+ goto free_mem_and_exit;
}
break;
case CA_GET_MSG:
dprintk(verbose, DST_CA_INFO, 1, " Getting message");
if ((ca_get_message(state, p_ca_message, arg)) < 0) {
dprintk(verbose, DST_CA_ERROR, 1, " -->CA_GET_MSG Failed !");
- return -1;
+ result = -1;
+ goto free_mem_and_exit;
}
dprintk(verbose, DST_CA_INFO, 1, " -->CA_GET_MSG Success !");
break;
@@ -506,7 +512,8 @@ static int dst_ca_ioctl(struct inode *inode, struct file *file, unsigned int cmd
dprintk(verbose, DST_CA_INFO, 1, " Getting Slot info");
if ((ca_get_slot_info(state, p_ca_slot_info, arg)) < 0) {
dprintk(verbose, DST_CA_ERROR, 1, " -->CA_GET_SLOT_INFO Failed !");
- return -1;
+ result = -1;
+ goto free_mem_and_exit;
}
dprintk(verbose, DST_CA_INFO, 1, " -->CA_GET_SLOT_INFO Success !");
break;
@@ -514,7 +521,8 @@ static int dst_ca_ioctl(struct inode *inode, struct file *file, unsigned int cmd
dprintk(verbose, DST_CA_INFO, 1, " Getting Slot capabilities");
if ((ca_get_slot_caps(state, p_ca_caps, arg)) < 0) {
dprintk(verbose, DST_CA_ERROR, 1, " -->CA_GET_CAP Failed !");
- return -1;
+ result = -1;
+ goto free_mem_and_exit;
}
dprintk(verbose, DST_CA_INFO, 1, " -->CA_GET_CAP Success !");
break;
@@ -522,7 +530,8 @@ static int dst_ca_ioctl(struct inode *inode, struct file *file, unsigned int cmd
dprintk(verbose, DST_CA_INFO, 1, " Getting descrambler description");
if ((ca_get_slot_descr(state, p_ca_message, arg)) < 0) {
dprintk(verbose, DST_CA_ERROR, 1, " -->CA_GET_DESCR_INFO Failed !");
- return -1;
+ result = -1;
+ goto free_mem_and_exit;
}
dprintk(verbose, DST_CA_INFO, 1, " -->CA_GET_DESCR_INFO Success !");
break;
@@ -530,7 +539,8 @@ static int dst_ca_ioctl(struct inode *inode, struct file *file, unsigned int cmd
dprintk(verbose, DST_CA_INFO, 1, " Setting descrambler");
if ((ca_set_slot_descr()) < 0) {
dprintk(verbose, DST_CA_ERROR, 1, " -->CA_SET_DESCR Failed !");
- return -1;
+ result = -1;
+ goto free_mem_and_exit;
}
dprintk(verbose, DST_CA_INFO, 1, " -->CA_SET_DESCR Success !");
break;
@@ -538,14 +548,19 @@ static int dst_ca_ioctl(struct inode *inode, struct file *file, unsigned int cmd
dprintk(verbose, DST_CA_INFO, 1, " Setting PID");
if ((ca_set_pid()) < 0) {
dprintk(verbose, DST_CA_ERROR, 1, " -->CA_SET_PID Failed !");
- return -1;
+ result = -1;
+ goto free_mem_and_exit;
}
dprintk(verbose, DST_CA_INFO, 1, " -->CA_SET_PID Success !");
default:
- return -EOPNOTSUPP;
+ result = -EOPNOTSUPP;
};
+ free_mem_and_exit:
+ kfree (p_ca_message);
+ kfree (p_ca_slot_info);
+ kfree (p_ca_caps);
- return 0;
+ return result;
}
static int dst_ca_open(struct inode *inode, struct file *file)
@@ -582,7 +597,7 @@ static int dst_ca_write(struct file *file, const char __user *buffer, size_t len
static struct file_operations dst_ca_fops = {
.owner = THIS_MODULE,
- .ioctl = (void *)dst_ca_ioctl,
+ .ioctl = dst_ca_ioctl,
.open = dst_ca_open,
.release = dst_ca_release,
.read = dst_ca_read,
diff --git a/drivers/media/dvb/bt8xx/dst_common.h b/drivers/media/dvb/bt8xx/dst_common.h
index 3281a6ca3685..81557f38fe38 100644
--- a/drivers/media/dvb/bt8xx/dst_common.h
+++ b/drivers/media/dvb/bt8xx/dst_common.h
@@ -22,6 +22,7 @@
#ifndef DST_COMMON_H
#define DST_COMMON_H
+#include <linux/smp_lock.h>
#include <linux/dvb/frontend.h>
#include <linux/device.h>
#include "bt878.h"
@@ -49,6 +50,7 @@
#define DST_TYPE_HAS_FW_BUILD 64
#define DST_TYPE_HAS_OBS_REGS 128
#define DST_TYPE_HAS_INC_COUNT 256
+#define DST_TYPE_HAS_MULTI_FE 512
/* Card capability list */
@@ -117,6 +119,9 @@ struct dst_state {
u8 fw_version[8];
u8 card_info[8];
u8 vendor[8];
+ u8 board_info[8];
+
+ struct semaphore dst_mutex;
};
struct dst_types {
diff --git a/drivers/media/dvb/bt8xx/dvb-bt8xx.c b/drivers/media/dvb/bt8xx/dvb-bt8xx.c
index c5c7672cd538..2e398090cf63 100644
--- a/drivers/media/dvb/bt8xx/dvb-bt8xx.c
+++ b/drivers/media/dvb/bt8xx/dvb-bt8xx.c
@@ -34,6 +34,7 @@
#include "dvb_frontend.h"
#include "dvb-bt8xx.h"
#include "bt878.h"
+#include "dvb-pll.h"
static int debug;
@@ -279,7 +280,7 @@ static int microtune_mt7202dtf_pll_set(struct dvb_frontend* fe, struct dvb_front
data[0] = (div >> 8) & 0x7f;
data[1] = div & 0xff;
data[2] = ((div >> 10) & 0x60) | cfg;
- data[3] = cpump | band_select;
+ data[3] = (cpump << 6) | band_select;
i2c_transfer(card->i2c_adapter, &msg, 1);
return (div * 166666 - 36000000);
@@ -522,9 +523,7 @@ static void digitv_alps_tded4_reset(struct dvb_bt8xx_card *bt)
/*
* Reset the frontend, must be called before trying
* to initialise the MT352 or mt352_attach
- * will fail.
- *
- * Presumably not required for the NXT6000 frontend.
+ * will fail. Same goes for the nxt6000 frontend.
*
*/
@@ -546,14 +545,63 @@ static struct mt352_config digitv_alps_tded4_config = {
.pll_set = digitv_alps_tded4_pll_set,
};
+static int tdvs_tua6034_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
+{
+ struct dvb_bt8xx_card *card = (struct dvb_bt8xx_card *) fe->dvb->priv;
+ u8 buf[4];
+ struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf) };
+ int err;
+
+ dvb_pll_configure(&dvb_pll_tdvs_tua6034, buf, params->frequency, 0);
+ dprintk("%s: tuner at 0x%02x bytes: 0x%02x 0x%02x 0x%02x 0x%02x\n",
+ __FUNCTION__, msg.addr, buf[0],buf[1],buf[2],buf[3]);
+ if ((err = i2c_transfer(card->i2c_adapter, &msg, 1)) != 1) {
+ printk(KERN_WARNING "dvb-bt8xx: %s error "
+ "(addr %02x <- %02x, err = %i)\n",
+ __FUNCTION__, buf[0], buf[1], err);
+ if (err < 0)
+ return err;
+ else
+ return -EREMOTEIO;
+ }
+
+ /* Set the Auxiliary Byte. */
+ buf[2] &= ~0x20;
+ buf[2] |= 0x18;
+ buf[3] = 0x50;
+ i2c_transfer(card->i2c_adapter, &msg, 1);
+
+ return 0;
+}
+
+static struct lgdt330x_config tdvs_tua6034_config = {
+ .demod_address = 0x0e,
+ .demod_chip = LGDT3303,
+ .serial_mpeg = 0x40, /* TPSERIAL for 3303 in TOP_CONTROL */
+ .pll_set = tdvs_tua6034_pll_set,
+};
+
+static void lgdt330x_reset(struct dvb_bt8xx_card *bt)
+{
+ /* Set pin 27 of the lgdt3303 chip high to reset the frontend */
+
+ /* Pulse the reset line */
+ bttv_write_gpio(bt->bttv_nr, 0x00e00007, 0x00000001); /* High */
+ bttv_write_gpio(bt->bttv_nr, 0x00e00007, 0x00000000); /* Low */
+ msleep(100);
+
+ bttv_write_gpio(bt->bttv_nr, 0x00e00007, 0x00000001); /* High */
+ msleep(100);
+}
+
static void frontend_init(struct dvb_bt8xx_card *card, u32 type)
{
int ret;
struct dst_state* state = NULL;
switch(type) {
-#ifdef BTTV_DVICO_DVBT_LITE
- case BTTV_DVICO_DVBT_LITE:
+#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) {
card->fe->ops->info.frequency_min = 174000000;
@@ -562,10 +610,19 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type)
break;
#endif
-#ifdef BTTV_TWINHAN_VP3021
- case BTTV_TWINHAN_VP3021:
+#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_NEBULA_DIGITV:
+ case BTTV_BOARD_NEBULA_DIGITV:
#endif
/*
* It is possible to determine the correct frontend using the I2C bus (see the Nebula SDK);
@@ -573,6 +630,7 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type)
*/
/* Old Nebula (marked (c)2003 on high profile pci card) has nxt6000 demod */
+ digitv_alps_tded4_reset(card);
card->fe = nxt6000_attach(&vp3021_alps_tded4_config, card->i2c_adapter);
if (card->fe != NULL) {
dprintk ("dvb_bt8xx: an nxt6000 was detected on your digitv card\n");
@@ -587,11 +645,11 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type)
dprintk ("dvb_bt8xx: an mt352 was detected on your digitv card\n");
break;
- case BTTV_AVDVBT_761:
+ case BTTV_BOARD_AVDVBT_761:
card->fe = sp887x_attach(&microtune_mt7202dtf_config, card->i2c_adapter);
break;
- case BTTV_AVDVBT_771:
+ case BTTV_BOARD_AVDVBT_771:
card->fe = mt352_attach(&advbt771_samsung_tdtc9251dh0_config, card->i2c_adapter);
if (card->fe != NULL) {
card->fe->ops->info.frequency_min = 174000000;
@@ -599,7 +657,7 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type)
}
break;
- case BTTV_TWINHAN_DST:
+ case BTTV_BOARD_TWINHAN_DST:
/* DST is not a frontend driver !!! */
state = (struct dst_state *) kmalloc(sizeof (struct dst_state), GFP_KERNEL);
/* Setup the Card */
@@ -620,11 +678,11 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type)
ret = dst_ca_attach(state, &card->dvb_adapter);
break;
- case BTTV_PINNACLESAT:
+ case BTTV_BOARD_PINNACLESAT:
card->fe = cx24110_attach(&pctvsat_config, card->i2c_adapter);
break;
- case BTTV_PC_HDTV:
+ case BTTV_BOARD_PC_HDTV:
card->fe = or51211_attach(&or51211_config, card->i2c_adapter);
break;
}
@@ -746,7 +804,7 @@ static int dvb_bt8xx_probe(struct device *dev)
card->i2c_adapter = &sub->core->i2c_adap;
switch(sub->core->type) {
- case BTTV_PINNACLESAT:
+ case BTTV_BOARD_PINNACLESAT:
card->gpio_mode = 0x0400c060;
/* should be: BT878_A_GAIN=0,BT878_A_PWRDN,BT878_DA_DPM,BT878_DA_SBR,
BT878_DA_IOM=1,BT878_DA_APP to enable serial highspeed mode. */
@@ -754,8 +812,8 @@ static int dvb_bt8xx_probe(struct device *dev)
card->irq_err_ignore = 0;
break;
-#ifdef BTTV_DVICO_DVBT_LITE
- case BTTV_DVICO_DVBT_LITE:
+#ifdef BTTV_BOARD_DVICO_DVBT_LITE
+ case BTTV_BOARD_DVICO_DVBT_LITE:
#endif
card->gpio_mode = 0x0400C060;
card->op_sync_orin = 0;
@@ -765,26 +823,34 @@ static int dvb_bt8xx_probe(struct device *dev)
* DA_APP(parallel) */
break;
-#ifdef BTTV_TWINHAN_VP3021
- case BTTV_TWINHAN_VP3021:
+#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_NEBULA_DIGITV:
+ case BTTV_BOARD_NEBULA_DIGITV:
#endif
- case BTTV_AVDVBT_761:
+ case BTTV_BOARD_AVDVBT_761:
card->gpio_mode = (1 << 26) | (1 << 14) | (1 << 5);
card->op_sync_orin = 0;
card->irq_err_ignore = 0;
/* A_PWRDN DA_SBR DA_APP (high speed serial) */
break;
- case BTTV_AVDVBT_771: //case 0x07711461:
+ case BTTV_BOARD_AVDVBT_771: //case 0x07711461:
card->gpio_mode = 0x0400402B;
card->op_sync_orin = BT878_RISC_SYNC_MASK;
card->irq_err_ignore = 0;
/* A_PWRDN DA_SBR DA_APP[0] PKTP=10 RISC_ENABLE FIFO_ENABLE*/
break;
- case BTTV_TWINHAN_DST:
+ case BTTV_BOARD_TWINHAN_DST:
card->gpio_mode = 0x2204f2c;
card->op_sync_orin = BT878_RISC_SYNC_MASK;
card->irq_err_ignore = BT878_APABORT | BT878_ARIPERR |
@@ -802,7 +868,7 @@ static int dvb_bt8xx_probe(struct device *dev)
* RISC+FIFO ENABLE */
break;
- case BTTV_PC_HDTV:
+ case BTTV_BOARD_PC_HDTV:
card->gpio_mode = 0x0100EC7B;
card->op_sync_orin = 0;
card->irq_err_ignore = 0;
diff --git a/drivers/media/dvb/bt8xx/dvb-bt8xx.h b/drivers/media/dvb/bt8xx/dvb-bt8xx.h
index 9ec8e5bd6c1f..cf035a80361c 100644
--- a/drivers/media/dvb/bt8xx/dvb-bt8xx.h
+++ b/drivers/media/dvb/bt8xx/dvb-bt8xx.h
@@ -35,6 +35,7 @@
#include "nxt6000.h"
#include "cx24110.h"
#include "or51211.h"
+#include "lgdt330x.h"
struct dvb_bt8xx_card {
struct semaphore lock;
diff --git a/drivers/media/dvb/dvb-core/demux.h b/drivers/media/dvb/dvb-core/demux.h
index 9719a3b30f78..7d7b0067f228 100644
--- a/drivers/media/dvb/dvb-core/demux.h
+++ b/drivers/media/dvb/dvb-core/demux.h
@@ -48,8 +48,11 @@
* DMX_MAX_SECFEED_SIZE: Maximum length (in bytes) of a private section feed filter.
*/
+#ifndef DMX_MAX_SECTION_SIZE
+#define DMX_MAX_SECTION_SIZE 4096
+#endif
#ifndef DMX_MAX_SECFEED_SIZE
-#define DMX_MAX_SECFEED_SIZE 4096
+#define DMX_MAX_SECFEED_SIZE (DMX_MAX_SECTION_SIZE + 188)
#endif
diff --git a/drivers/media/dvb/dvb-core/dvb_demux.c b/drivers/media/dvb/dvb-core/dvb_demux.c
index dc476dda2b71..b4c899b15959 100644
--- a/drivers/media/dvb/dvb-core/dvb_demux.c
+++ b/drivers/media/dvb/dvb-core/dvb_demux.c
@@ -246,7 +246,7 @@ static int dvb_dmx_swfilter_section_copy_dump(struct dvb_demux_feed *feed,
for (n = 0; sec->secbufp + 2 < limit; n++) {
seclen = section_length(sec->secbuf);
- if (seclen <= 0 || seclen > DMX_MAX_SECFEED_SIZE
+ if (seclen <= 0 || seclen > DMX_MAX_SECTION_SIZE
|| seclen + sec->secbufp > limit)
return 0;
sec->seclen = seclen;
diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c
index a8bc84240b50..6ffa6b216363 100644
--- a/drivers/media/dvb/dvb-core/dvb_frontend.c
+++ b/drivers/media/dvb/dvb-core/dvb_frontend.c
@@ -42,8 +42,6 @@
#include "dvb_frontend.h"
#include "dvbdev.h"
-// #define DEBUG_LOCKLOSS 1
-
static int dvb_frontend_debug;
static int dvb_shutdown_timeout = 5;
static int dvb_force_auto_inversion;
@@ -438,25 +436,6 @@ static int dvb_frontend_thread(void *data)
if (s & FE_HAS_LOCK)
continue;
else { /* if we _WERE_ tuned, but now don't have a lock */
-#ifdef DEBUG_LOCKLOSS
- /* first of all try setting the tone again if it was on - this
- * sometimes works around problems with noisy power supplies */
- if (fe->ops->set_tone && (fepriv->tone == SEC_TONE_ON)) {
- fe->ops->set_tone(fe, fepriv->tone);
- mdelay(100);
- s = 0;
- fe->ops->read_status(fe, &s);
- if (s & FE_HAS_LOCK) {
- printk("DVB%i: Lock was lost, but regained by setting "
- "the tone. This may indicate your power supply "
- "is noisy/slightly incompatable with this DVB-S "
- "adapter\n", fe->dvb->num);
- fepriv->state = FESTATE_TUNED;
- continue;
- }
- }
-#endif
- /* some other reason for losing the lock - start zigzagging */
fepriv->state = FESTATE_ZIGZAG_FAST;
fepriv->started_auto_step = fepriv->auto_step;
check_wrapped = 0;
@@ -577,6 +556,49 @@ static void dvb_frontend_stop(struct dvb_frontend *fe)
fepriv->thread_pid);
}
+s32 timeval_usec_diff(struct timeval lasttime, struct timeval curtime)
+{
+ return ((curtime.tv_usec < lasttime.tv_usec) ?
+ 1000000 - lasttime.tv_usec + curtime.tv_usec :
+ curtime.tv_usec - lasttime.tv_usec);
+}
+EXPORT_SYMBOL(timeval_usec_diff);
+
+static inline void timeval_usec_add(struct timeval *curtime, u32 add_usec)
+{
+ curtime->tv_usec += add_usec;
+ if (curtime->tv_usec >= 1000000) {
+ curtime->tv_usec -= 1000000;
+ curtime->tv_sec++;
+ }
+}
+
+/*
+ * Sleep until gettimeofday() > waketime + add_usec
+ * This needs to be as precise as possible, but as the delay is
+ * usually between 2ms and 32ms, it is done using a scheduled msleep
+ * followed by usleep (normally a busy-wait loop) for the remainder
+ */
+void dvb_frontend_sleep_until(struct timeval *waketime, u32 add_usec)
+{
+ struct timeval lasttime;
+ s32 delta, newdelta;
+
+ timeval_usec_add(waketime, add_usec);
+
+ do_gettimeofday(&lasttime);
+ delta = timeval_usec_diff(lasttime, *waketime);
+ if (delta > 2500) {
+ msleep((delta - 1500) / 1000);
+ do_gettimeofday(&lasttime);
+ newdelta = timeval_usec_diff(lasttime, *waketime);
+ delta = (newdelta > delta) ? 0 : newdelta;
+ }
+ if (delta > 0)
+ udelay(delta);
+}
+EXPORT_SYMBOL(dvb_frontend_sleep_until);
+
static int dvb_frontend_start(struct dvb_frontend *fe)
{
int ret;
@@ -728,6 +750,60 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
err = fe->ops->dishnetwork_send_legacy_command(fe, (unsigned int) parg);
fepriv->state = FESTATE_DISEQC;
fepriv->status = 0;
+ } else if (fe->ops->set_voltage) {
+ /*
+ * NOTE: This is a fallback condition. Some frontends
+ * (stv0299 for instance) take longer than 8msec to
+ * respond to a set_voltage command. Those switches
+ * need custom routines to switch properly. For all
+ * other frontends, the following shoule work ok.
+ * Dish network legacy switches (as used by Dish500)
+ * are controlled by sending 9-bit command words
+ * spaced 8msec apart.
+ * the actual command word is switch/port dependant
+ * so it is up to the userspace application to send
+ * the right command.
+ * The command must always start with a '0' after
+ * initialization, so parg is 8 bits and does not
+ * include the initialization or start bit
+ */
+ unsigned int cmd = ((unsigned int) 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);
+ do_gettimeofday(&nexttime);
+ if (dvb_frontend_debug)
+ memcpy(&tv[0], &nexttime, sizeof(struct timeval));
+ /* before sending a command, initialize by sending
+ * a 32ms 18V to the switch
+ */
+ fe->ops->set_voltage(fe, SEC_VOLTAGE_18);
+ dvb_frontend_sleep_until(&nexttime, 32000);
+
+ for (i = 0; i < 9; i++) {
+ if (dvb_frontend_debug)
+ do_gettimeofday(&tv[i + 1]);
+ if ((cmd & 0x01) != last) {
+ /* set voltage to (last ? 13V : 18V) */
+ fe->ops->set_voltage(fe, (last) ? SEC_VOLTAGE_13 : SEC_VOLTAGE_18);
+ last = (last) ? 0 : 1;
+ }
+ cmd = cmd >> 1;
+ if (i != 8)
+ dvb_frontend_sleep_until(&nexttime, 8000);
+ }
+ if (dvb_frontend_debug) {
+ printk("%s(%d): switch delay (should be 32k followed by all 8k\n",
+ __FUNCTION__, fe->dvb->num);
+ for (i = 1; i < 10; i++)
+ printk("%d: %d\n", i, timeval_usec_diff(tv[i-1] , tv[i]));
+ }
+ err = 0;
+ fepriv->state = FESTATE_DISEQC;
+ fepriv->status = 0;
}
break;
diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.h b/drivers/media/dvb/dvb-core/dvb_frontend.h
index 9c2c1d1136bd..348c9b0b988a 100644
--- a/drivers/media/dvb/dvb-core/dvb_frontend.h
+++ b/drivers/media/dvb/dvb-core/dvb_frontend.h
@@ -101,4 +101,7 @@ extern int dvb_register_frontend(struct dvb_adapter* dvb,
extern int dvb_unregister_frontend(struct dvb_frontend* fe);
+extern void dvb_frontend_sleep_until(struct timeval *waketime, u32 add_usec);
+extern s32 timeval_usec_diff(struct timeval lasttime, struct timeval curtime);
+
#endif
diff --git a/drivers/media/dvb/dvb-usb/a800.c b/drivers/media/dvb/dvb-usb/a800.c
index e55322ef76b3..49f541d9a042 100644
--- a/drivers/media/dvb/dvb-usb/a800.c
+++ b/drivers/media/dvb/dvb-usb/a800.c
@@ -43,11 +43,9 @@ static struct dvb_usb_rc_key a800_rc_keys[] = {
{ 0x02, 0x13, KEY_RIGHT }, /* R / CH RTN */
{ 0x02, 0x17, KEY_PROG2 }, /* SNAP SHOT */
{ 0x02, 0x10, KEY_PROG3 }, /* 16-CH PREV */
- { 0x02, 0x03, KEY_CHANNELUP }, /* CH UP */
{ 0x02, 0x1e, KEY_VOLUMEDOWN }, /* VOL DOWN */
{ 0x02, 0x0c, KEY_ZOOM }, /* FULL SCREEN */
{ 0x02, 0x1f, KEY_VOLUMEUP }, /* VOL UP */
- { 0x02, 0x02, KEY_CHANNELDOWN }, /* CH DOWN */
{ 0x02, 0x14, KEY_MUTE }, /* MUTE */
{ 0x02, 0x08, KEY_AUDIO }, /* AUDIO */
{ 0x02, 0x19, KEY_RECORD }, /* RECORD */
@@ -57,8 +55,6 @@ static struct dvb_usb_rc_key a800_rc_keys[] = {
{ 0x02, 0x1d, KEY_BACK }, /* << / RED */
{ 0x02, 0x1c, KEY_FORWARD }, /* >> / YELLOW */
{ 0x02, 0x03, KEY_TEXT }, /* TELETEXT */
- { 0x02, 0x01, KEY_FIRST }, /* |<< / GREEN */
- { 0x02, 0x00, KEY_LAST }, /* >>| / BLUE */
{ 0x02, 0x04, KEY_EPG }, /* EPG */
{ 0x02, 0x15, KEY_MENU }, /* MENU */
diff --git a/drivers/media/dvb/dvb-usb/dibusb-mb.c b/drivers/media/dvb/dvb-usb/dibusb-mb.c
index 0058505634a0..aa271a2496d5 100644
--- a/drivers/media/dvb/dvb-usb/dibusb-mb.c
+++ b/drivers/media/dvb/dvb-usb/dibusb-mb.c
@@ -82,13 +82,15 @@ static int dibusb_tuner_probe_and_attach(struct dvb_usb_device *d)
static struct dvb_usb_properties dibusb1_1_properties;
static struct dvb_usb_properties dibusb1_1_an2235_properties;
static struct dvb_usb_properties dibusb2_0b_properties;
+static struct dvb_usb_properties artec_t1_usb2_properties;
static int dibusb_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
if (dvb_usb_device_init(intf,&dibusb1_1_properties,THIS_MODULE,NULL) == 0 ||
dvb_usb_device_init(intf,&dibusb1_1_an2235_properties,THIS_MODULE,NULL) == 0 ||
- dvb_usb_device_init(intf,&dibusb2_0b_properties,THIS_MODULE,NULL) == 0)
+ dvb_usb_device_init(intf,&dibusb2_0b_properties,THIS_MODULE,NULL) == 0 ||
+ dvb_usb_device_init(intf,&artec_t1_usb2_properties,THIS_MODULE,NULL) == 0)
return 0;
return -EINVAL;
@@ -128,10 +130,13 @@ static struct usb_device_id dibusb_dib3000mb_table [] = {
/* 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) },
+
// #define DVB_USB_DIBUSB_MB_FAULTY_USB_IDs
#ifdef DVB_USB_DIBUSB_MB_FAULTY_USB_IDs
-/* 28 */ { USB_DEVICE(USB_VID_ANCHOR, USB_PID_ULTIMA_TVBOX_ANCHOR_COLD) },
+/* 30 */ { USB_DEVICE(USB_VID_ANCHOR, USB_PID_ULTIMA_TVBOX_ANCHOR_COLD) },
#endif
{ } /* Terminating entry */
};
@@ -264,7 +269,7 @@ static struct dvb_usb_properties dibusb1_1_an2235_properties = {
},
#ifdef DVB_USB_DIBUSB_MB_FAULTY_USB_IDs
{ "Artec T1 USB1.1 TVBOX with AN2235 (faulty USB IDs)",
- { &dibusb_dib3000mb_table[28], NULL },
+ { &dibusb_dib3000mb_table[30], NULL },
{ NULL },
},
#endif
@@ -273,7 +278,7 @@ static struct dvb_usb_properties dibusb1_1_an2235_properties = {
static struct dvb_usb_properties dibusb2_0b_properties = {
.caps = DVB_USB_HAS_PID_FILTER | DVB_USB_PID_FILTER_CAN_BE_TURNED_OFF | DVB_USB_IS_AN_I2C_ADAPTER,
- .pid_filter_count = 32,
+ .pid_filter_count = 16,
.usb_ctrl = CYPRESS_FX2,
@@ -321,6 +326,52 @@ static struct dvb_usb_properties dibusb2_0b_properties = {
}
};
+static struct dvb_usb_properties artec_t1_usb2_properties = {
+ .caps = DVB_USB_HAS_PID_FILTER | DVB_USB_PID_FILTER_CAN_BE_TURNED_OFF | DVB_USB_IS_AN_I2C_ADAPTER,
+ .pid_filter_count = 16,
+
+ .usb_ctrl = CYPRESS_FX2,
+
+ .firmware = "dvb-usb-dibusb-6.0.0.8.fw",
+
+ .size_of_priv = sizeof(struct dibusb_state),
+
+ .streaming_ctrl = dibusb2_0_streaming_ctrl,
+ .pid_filter = dibusb_pid_filter,
+ .pid_filter_ctrl = dibusb_pid_filter_ctrl,
+ .power_ctrl = dibusb2_0_power_ctrl,
+ .frontend_attach = dibusb_dib3000mb_frontend_attach,
+ .tuner_attach = dibusb_tuner_probe_and_attach,
+
+ .rc_interval = DEFAULT_RC_INTERVAL,
+ .rc_key_map = dibusb_rc_keys,
+ .rc_key_map_size = 63, /* wow, that is ugly ... I want to load it to the driver dynamically */
+ .rc_query = dibusb_rc_query,
+
+ .i2c_algo = &dibusb_i2c_algo,
+
+ .generic_bulk_ctrl_endpoint = 0x01,
+ /* parameter for the MPEG2-data transfer */
+ .urb = {
+ .type = DVB_USB_BULK,
+ .count = 7,
+ .endpoint = 0x06,
+ .u = {
+ .bulk = {
+ .buffersize = 4096,
+ }
+ }
+ },
+
+ .num_device_descs = 1,
+ .devices = {
+ { "Artec T1 USB2.0",
+ { &dibusb_dib3000mb_table[28], NULL },
+ { &dibusb_dib3000mb_table[29], NULL },
+ },
+ }
+};
+
static struct usb_driver dibusb_driver = {
.owner = THIS_MODULE,
.name = "dvb_usb_dibusb_mb",
diff --git a/drivers/media/dvb/dvb-usb/dibusb.h b/drivers/media/dvb/dvb-usb/dibusb.h
index 6611f62977c0..2d99d05c7eab 100644
--- a/drivers/media/dvb/dvb-usb/dibusb.h
+++ b/drivers/media/dvb/dvb-usb/dibusb.h
@@ -11,7 +11,9 @@
#ifndef _DVB_USB_DIBUSB_H_
#define _DVB_USB_DIBUSB_H_
-#define DVB_USB_LOG_PREFIX "dibusb"
+#ifndef DVB_USB_LOG_PREFIX
+ #define DVB_USB_LOG_PREFIX "dibusb"
+#endif
#include "dvb-usb.h"
#include "dib3000.h"
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
index 0818996bf150..6be99e537e12 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
@@ -43,10 +43,14 @@
#define USB_PID_COMPRO_DVBU2000_WARM 0xd001
#define USB_PID_COMPRO_DVBU2000_UNK_COLD 0x010c
#define USB_PID_COMPRO_DVBU2000_UNK_WARM 0x010d
+#define USB_PID_DIBCOM_HOOK_DEFAULT 0x0064
+#define USB_PID_DIBCOM_HOOK_DEFAULT_REENUM 0x0065
#define USB_PID_DIBCOM_MOD3000_COLD 0x0bb8
#define USB_PID_DIBCOM_MOD3000_WARM 0x0bb9
#define USB_PID_DIBCOM_MOD3001_COLD 0x0bc6
#define USB_PID_DIBCOM_MOD3001_WARM 0x0bc7
+#define USB_PID_DIBCOM_STK7700 0x1e14
+#define USB_PID_DIBCOM_STK7700_REENUM 0x1e15
#define USB_PID_DIBCOM_ANCHOR_2135_COLD 0x2131
#define USB_PID_GRANDTEC_DVBT_USB_COLD 0x0fa0
#define USB_PID_GRANDTEC_DVBT_USB_WARM 0x0fa1
@@ -68,6 +72,7 @@
#define USB_PID_ULTIMA_TVBOX_AN2235_WARM 0x8108
#define USB_PID_ULTIMA_TVBOX_ANCHOR_COLD 0x2235
#define USB_PID_ULTIMA_TVBOX_USB2_COLD 0x8109
+#define USB_PID_ULTIMA_TVBOX_USB2_WARM 0x810a
#define USB_PID_ULTIMA_TVBOX_USB2_FX_COLD 0x8613
#define USB_PID_ULTIMA_TVBOX_USB2_FX_WARM 0x1002
#define USB_PID_UNK_HYPER_PALTEK_COLD 0x005e
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-urb.c b/drivers/media/dvb/dvb-usb/dvb-usb-urb.c
index f5799a4c228e..36b7048c02d2 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb-urb.c
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-urb.c
@@ -196,7 +196,9 @@ static int dvb_usb_allocate_stream_buffers(struct dvb_usb_device *d, int num, un
dvb_usb_free_stream_buffers(d);
return -ENOMEM;
}
- deb_mem("buffer %d: %p (dma: %d)\n",d->buf_num,d->buf_list[d->buf_num],d->dma_addr[d->buf_num]);
+ deb_mem("buffer %d: %p (dma: %llu)\n",
+ d->buf_num, d->buf_list[d->buf_num],
+ (unsigned long long)d->dma_addr[d->buf_num]);
memset(d->buf_list[d->buf_num],0,size);
}
deb_mem("allocation successful\n");
diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig
index a50a41f6f79d..8e269e1c1f9d 100644
--- a/drivers/media/dvb/frontends/Kconfig
+++ b/drivers/media/dvb/frontends/Kconfig
@@ -164,6 +164,14 @@ config DVB_NXT2002
help
An ATSC 8VSB tuner module. Say Y when you want to support this frontend.
+config DVB_NXT200X
+ tristate "Nextwave NXT2002/NXT2004 based"
+ depends on DVB_CORE
+ select FW_LOADER
+ help
+ An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want
+ to support this frontend.
+
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 ad8658ffd60a..a98760fe08a1 100644
--- a/drivers/media/dvb/frontends/Makefile
+++ b/drivers/media/dvb/frontends/Makefile
@@ -26,6 +26,7 @@ obj-$(CONFIG_DVB_TDA80XX) += tda80xx.o
obj-$(CONFIG_DVB_TDA10021) += tda10021.o
obj-$(CONFIG_DVB_STV0297) += stv0297.o
obj-$(CONFIG_DVB_NXT2002) += nxt2002.o
+obj-$(CONFIG_DVB_NXT200X) += nxt200x.o
obj-$(CONFIG_DVB_OR51211) += or51211.o
obj-$(CONFIG_DVB_OR51132) += or51132.o
obj-$(CONFIG_DVB_BCM3510) += bcm3510.o
diff --git a/drivers/media/dvb/frontends/cx24110.c b/drivers/media/dvb/frontends/cx24110.c
index d4b97989e3ed..654d7dc879d9 100644
--- a/drivers/media/dvb/frontends/cx24110.c
+++ b/drivers/media/dvb/frontends/cx24110.c
@@ -27,6 +27,7 @@
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
+#include <linux/jiffies.h>
#include "dvb_frontend.h"
#include "cx24110.h"
diff --git a/drivers/media/dvb/frontends/dvb-pll.c b/drivers/media/dvb/frontends/dvb-pll.c
index 536c35d969b7..f857b869616c 100644
--- a/drivers/media/dvb/frontends/dvb-pll.c
+++ b/drivers/media/dvb/frontends/dvb-pll.c
@@ -226,7 +226,7 @@ struct dvb_pll_desc dvb_pll_tua6034 = {
EXPORT_SYMBOL(dvb_pll_tua6034);
/* Infineon TUA6034
- * used in LG Innotek TDVS-H062F
+ * used in LG TDVS H061F and LG TDVS H062F
*/
struct dvb_pll_desc dvb_pll_tdvs_tua6034 = {
.name = "LG/Infineon TUA6034",
@@ -292,6 +292,58 @@ struct dvb_pll_desc dvb_pll_tded4 = {
};
EXPORT_SYMBOL(dvb_pll_tded4);
+/* ALPS TDHU2
+ * used in AverTVHD MCE A180
+ */
+struct dvb_pll_desc dvb_pll_tdhu2 = {
+ .name = "ALPS TDHU2",
+ .min = 54000000,
+ .max = 864000000,
+ .count = 4,
+ .entries = {
+ { 162000000, 44000000, 62500, 0x85, 0x01 },
+ { 426000000, 44000000, 62500, 0x85, 0x02 },
+ { 782000000, 44000000, 62500, 0x85, 0x08 },
+ { 999999999, 44000000, 62500, 0x85, 0x88 },
+ }
+};
+EXPORT_SYMBOL(dvb_pll_tdhu2);
+
+/* Philips TUV1236D
+ * used in ATI HDTV Wonder
+ */
+struct dvb_pll_desc dvb_pll_tuv1236d = {
+ .name = "Philips TUV1236D",
+ .min = 54000000,
+ .max = 864000000,
+ .count = 3,
+ .entries = {
+ { 157250000, 44000000, 62500, 0xc6, 0x41 },
+ { 454000000, 44000000, 62500, 0xc6, 0x42 },
+ { 999999999, 44000000, 62500, 0xc6, 0x44 },
+ },
+};
+EXPORT_SYMBOL(dvb_pll_tuv1236d);
+
+/* Samsung TBMV30111IN
+ * used in Air2PC ATSC - 2nd generation (nxt2002)
+ */
+struct dvb_pll_desc dvb_pll_tbmv30111in = {
+ .name = "Samsung TBMV30111IN",
+ .min = 54000000,
+ .max = 860000000,
+ .count = 4,
+ .entries = {
+ { 172000000, 44000000, 166666, 0xb4, 0x01 },
+ { 214000000, 44000000, 166666, 0xb4, 0x02 },
+ { 467000000, 44000000, 166666, 0xbc, 0x02 },
+ { 721000000, 44000000, 166666, 0xbc, 0x08 },
+ { 841000000, 44000000, 166666, 0xf4, 0x08 },
+ { 999999999, 44000000, 166666, 0xfc, 0x02 },
+ }
+};
+EXPORT_SYMBOL(dvb_pll_tbmv30111in);
+
/* ----------------------------------------------------------- */
/* code */
diff --git a/drivers/media/dvb/frontends/dvb-pll.h b/drivers/media/dvb/frontends/dvb-pll.h
index 205b2d1a8852..497d31dcf41e 100644
--- a/drivers/media/dvb/frontends/dvb-pll.h
+++ b/drivers/media/dvb/frontends/dvb-pll.h
@@ -36,6 +36,10 @@ extern struct dvb_pll_desc dvb_pll_tda665x;
extern struct dvb_pll_desc dvb_pll_fmd1216me;
extern struct dvb_pll_desc dvb_pll_tded4;
+extern struct dvb_pll_desc dvb_pll_tuv1236d;
+extern struct dvb_pll_desc dvb_pll_tdhu2;
+extern struct dvb_pll_desc dvb_pll_tbmv30111in;
+
int dvb_pll_configure(struct dvb_pll_desc *desc, u8 *buf,
u32 freq, int bandwidth);
diff --git a/drivers/media/dvb/frontends/dvb_dummy_fe.c b/drivers/media/dvb/frontends/dvb_dummy_fe.c
index 794be520d590..645946a992d9 100644
--- a/drivers/media/dvb/frontends/dvb_dummy_fe.c
+++ b/drivers/media/dvb/frontends/dvb_dummy_fe.c
@@ -148,7 +148,7 @@ struct dvb_frontend* dvb_dummy_fe_qpsk_attach()
return &state->frontend;
error:
- if (state) kfree(state);
+ kfree(state);
return NULL;
}
@@ -171,7 +171,7 @@ struct dvb_frontend* dvb_dummy_fe_qam_attach()
return &state->frontend;
error:
- if (state) kfree(state);
+ kfree(state);
return NULL;
}
diff --git a/drivers/media/dvb/frontends/l64781.c b/drivers/media/dvb/frontends/l64781.c
index faaad1ae8559..19b4bf7c21a7 100644
--- a/drivers/media/dvb/frontends/l64781.c
+++ b/drivers/media/dvb/frontends/l64781.c
@@ -559,7 +559,8 @@ struct dvb_frontend* l64781_attach(const struct l64781_config* config,
return &state->frontend;
error:
- if (reg0x3e >= 0) l64781_writereg (state, 0x3e, reg0x3e); /* restore reg 0x3e */
+ if (reg0x3e >= 0)
+ l64781_writereg (state, 0x3e, reg0x3e); /* restore reg 0x3e */
kfree(state);
return NULL;
}
diff --git a/drivers/media/dvb/frontends/lgdt330x.c b/drivers/media/dvb/frontends/lgdt330x.c
index 8dde72bd1046..6a33f5a19a8d 100644
--- a/drivers/media/dvb/frontends/lgdt330x.c
+++ b/drivers/media/dvb/frontends/lgdt330x.c
@@ -26,6 +26,8 @@
* DViCO FusionHDTV 3 Gold-Q
* DViCO FusionHDTV 3 Gold-T
* DViCO FusionHDTV 5 Gold
+ * DViCO FusionHDTV 5 Lite
+ * Air2PC/AirStar 2 ATSC 3rd generation (HD5000)
*
* TODO:
* signal strength always returns 0.
@@ -222,6 +224,11 @@ static int lgdt330x_init(struct dvb_frontend* fe)
0x4c, 0x14
};
+ static u8 flip_lgdt3303_init_data[] = {
+ 0x4c, 0x14,
+ 0x87, 0xf3
+ };
+
struct lgdt330x_state* state = fe->demodulator_priv;
char *chip_name;
int err;
@@ -234,8 +241,13 @@ static int lgdt330x_init(struct dvb_frontend* fe)
break;
case LGDT3303:
chip_name = "LGDT3303";
- err = i2c_write_demod_bytes(state, lgdt3303_init_data,
- sizeof(lgdt3303_init_data));
+ if (state->config->clock_polarity_flip) {
+ err = i2c_write_demod_bytes(state, flip_lgdt3303_init_data,
+ sizeof(flip_lgdt3303_init_data));
+ } else {
+ err = i2c_write_demod_bytes(state, lgdt3303_init_data,
+ sizeof(lgdt3303_init_data));
+ }
break;
default:
chip_name = "undefined";
@@ -731,8 +743,7 @@ struct dvb_frontend* lgdt330x_attach(const struct lgdt330x_config* config,
return &state->frontend;
error:
- if (state)
- kfree(state);
+ kfree(state);
dprintk("%s: ERROR\n",__FUNCTION__);
return NULL;
}
@@ -744,9 +755,8 @@ static struct dvb_frontend_ops lgdt3302_ops = {
.frequency_min= 54000000,
.frequency_max= 858000000,
.frequency_stepsize= 62500,
- /* Symbol rate is for all VSB modes need to check QAM */
- .symbol_rate_min = 10762000,
- .symbol_rate_max = 10762000,
+ .symbol_rate_min = 5056941, /* QAM 64 */
+ .symbol_rate_max = 10762000, /* VSB 8 */
.caps = FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_8VSB
},
.init = lgdt330x_init,
@@ -768,9 +778,8 @@ static struct dvb_frontend_ops lgdt3303_ops = {
.frequency_min= 54000000,
.frequency_max= 858000000,
.frequency_stepsize= 62500,
- /* Symbol rate is for all VSB modes need to check QAM */
- .symbol_rate_min = 10762000,
- .symbol_rate_max = 10762000,
+ .symbol_rate_min = 5056941, /* QAM 64 */
+ .symbol_rate_max = 10762000, /* VSB 8 */
.caps = FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_8VSB
},
.init = lgdt330x_init,
diff --git a/drivers/media/dvb/frontends/lgdt330x.h b/drivers/media/dvb/frontends/lgdt330x.h
index e209ba1e47c5..2a6529cccf1a 100644
--- a/drivers/media/dvb/frontends/lgdt330x.h
+++ b/drivers/media/dvb/frontends/lgdt330x.h
@@ -47,6 +47,10 @@ struct lgdt330x_config
/* Need to set device param for start_dma */
int (*set_ts_params)(struct dvb_frontend* fe, int is_punctured);
+
+ /* Flip the polarity of the mpeg data transfer clock using alternate init data
+ * This option applies ONLY to LGDT3303 - 0:disabled (default) 1:enabled */
+ int clock_polarity_flip;
};
extern struct dvb_frontend* lgdt330x_attach(const struct lgdt330x_config* config,
diff --git a/drivers/media/dvb/frontends/mt312.c b/drivers/media/dvb/frontends/mt312.c
index e38454901dd1..9c67f406d581 100644
--- a/drivers/media/dvb/frontends/mt312.c
+++ b/drivers/media/dvb/frontends/mt312.c
@@ -677,8 +677,7 @@ struct dvb_frontend* mt312_attach(const struct mt312_config* config,
return &state->frontend;
error:
- if (state)
- kfree(state);
+ kfree(state);
return NULL;
}
diff --git a/drivers/media/dvb/frontends/nxt200x.c b/drivers/media/dvb/frontends/nxt200x.c
new file mode 100644
index 000000000000..bad0933eb714
--- /dev/null
+++ b/drivers/media/dvb/frontends/nxt200x.c
@@ -0,0 +1,1205 @@
+/*
+ * Support for NXT2002 and NXT2004 - VSB/QAM
+ *
+ * Copyright (C) 2005 Kirk Lapray (kirk.lapray@gmail.com)
+ * based on nxt2002 by Taylor Jacob <rtjacob@earthlink.net>
+ * and nxt2004 by Jean-Francois Thibert (jeanfrancois@sagetv.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.
+ *
+*/
+
+/*
+ * NOTES ABOUT THIS DRIVER
+ *
+ * This Linux driver supports:
+ * B2C2/BBTI Technisat Air2PC - ATSC (NXT2002)
+ * AverTVHD MCE A180 (NXT2004)
+ * ATI HDTV Wonder (NXT2004)
+ *
+ * This driver needs external firmware. Please use the command
+ * "<kerneldir>/Documentation/dvb/get_dvb_firmware nxt2002" or
+ * "<kerneldir>/Documentation/dvb/get_dvb_firmware nxt2004" to
+ * download/extract the appropriate firmware, 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 NXT2004_DEFAULT_FIRMWARE "dvb-fe-nxt2004.fw"
+#define CRC_CCIT_MASK 0x1021
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+
+#include "dvb_frontend.h"
+#include "dvb-pll.h"
+#include "nxt200x.h"
+
+struct nxt200x_state {
+
+ struct i2c_adapter* i2c;
+ struct dvb_frontend_ops ops;
+ const struct nxt200x_config* config;
+ struct dvb_frontend frontend;
+
+ /* demodulator private data */
+ nxt_chip_type demod_chip;
+ u8 initialised:1;
+};
+
+static int debug;
+#define dprintk(args...) \
+ do { \
+ if (debug) printk(KERN_DEBUG "nxt200x: " args); \
+ } while (0)
+
+static int i2c_writebytes (struct nxt200x_state* state, u8 addr, u8 *buf, u8 len)
+{
+ int err;
+ struct i2c_msg msg = { .addr = addr, .flags = 0, .buf = buf, .len = len };
+
+ if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) {
+ printk (KERN_WARNING "nxt200x: %s: i2c write error (addr 0x%02x, err == %i)\n",
+ __FUNCTION__, addr, err);
+ return -EREMOTEIO;
+ }
+ return 0;
+}
+
+static u8 i2c_readbytes (struct nxt200x_state* state, u8 addr, u8* buf, u8 len)
+{
+ int err;
+ struct i2c_msg msg = { .addr = addr, .flags = I2C_M_RD, .buf = buf, .len = len };
+
+ if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) {
+ printk (KERN_WARNING "nxt200x: %s: i2c read error (addr 0x%02x, err == %i)\n",
+ __FUNCTION__, addr, err);
+ return -EREMOTEIO;
+ }
+ return 0;
+}
+
+static int nxt200x_writebytes (struct nxt200x_state* state, u8 reg, u8 *buf, u8 len)
+{
+ u8 buf2 [len+1];
+ int err;
+ struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = buf2, .len = len + 1 };
+
+ buf2[0] = reg;
+ memcpy(&buf2[1], buf, len);
+
+ if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) {
+ printk (KERN_WARNING "nxt200x: %s: i2c write error (addr 0x%02x, err == %i)\n",
+ __FUNCTION__, state->config->demod_address, err);
+ return -EREMOTEIO;
+ }
+ return 0;
+}
+
+static u8 nxt200x_readbytes (struct nxt200x_state* state, u8 reg, u8* buf, u8 len)
+{
+ u8 reg2 [] = { reg };
+
+ struct i2c_msg msg [] = { { .addr = state->config->demod_address, .flags = 0, .buf = reg2, .len = 1 },
+ { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = buf, .len = len } };
+
+ int err;
+
+ if ((err = i2c_transfer (state->i2c, msg, 2)) != 2) {
+ printk (KERN_WARNING "nxt200x: %s: i2c read error (addr 0x%02x, err == %i)\n",
+ __FUNCTION__, state->config->demod_address, err);
+ return -EREMOTEIO;
+ }
+ return 0;
+}
+
+static u16 nxt200x_crc(u16 crc, u8 c)
+{
+ u8 i;
+ u16 input = (u16) c & 0xFF;
+
+ input<<=8;
+ for(i=0; i<8; i++) {
+ if((crc^input) & 0x8000)
+ crc=(crc<<1)^CRC_CCIT_MASK;
+ else
+ crc<<=1;
+ input<<=1;
+ }
+ return crc;
+}
+
+static int nxt200x_writereg_multibyte (struct nxt200x_state* state, u8 reg, u8* data, u8 len)
+{
+ u8 attr, len2, buf;
+ dprintk("%s\n", __FUNCTION__);
+
+ /* set mutli register register */
+ nxt200x_writebytes(state, 0x35, &reg, 1);
+
+ /* send the actual data */
+ nxt200x_writebytes(state, 0x36, data, len);
+
+ switch (state->demod_chip) {
+ case NXT2002:
+ len2 = len;
+ buf = 0x02;
+ break;
+ case NXT2004:
+ /* probably not right, but gives correct values */
+ attr = 0x02;
+ if (reg & 0x80) {
+ attr = attr << 1;
+ if (reg & 0x04)
+ attr = attr >> 1;
+ }
+ /* set write bit */
+ len2 = ((attr << 4) | 0x10) | len;
+ buf = 0x80;
+ break;
+ default:
+ return -EINVAL;
+ break;
+ }
+
+ /* set multi register length */
+ nxt200x_writebytes(state, 0x34, &len2, 1);
+
+ /* toggle the multireg write bit */
+ nxt200x_writebytes(state, 0x21, &buf, 1);
+
+ nxt200x_readbytes(state, 0x21, &buf, 1);
+
+ switch (state->demod_chip) {
+ case NXT2002:
+ if ((buf & 0x02) == 0)
+ return 0;
+ break;
+ case NXT2004:
+ if (buf == 0)
+ return 0;
+ break;
+ default:
+ return -EINVAL;
+ break;
+ }
+
+ printk(KERN_WARNING "nxt200x: Error writing multireg register 0x%02X\n",reg);
+
+ return 0;
+}
+
+static int nxt200x_readreg_multibyte (struct nxt200x_state* state, u8 reg, u8* data, u8 len)
+{
+ int i;
+ u8 buf, len2, attr;
+ dprintk("%s\n", __FUNCTION__);
+
+ /* set mutli register register */
+ nxt200x_writebytes(state, 0x35, &reg, 1);
+
+ switch (state->demod_chip) {
+ case NXT2002:
+ /* set multi register length */
+ len2 = len & 0x80;
+ nxt200x_writebytes(state, 0x34, &len2, 1);
+
+ /* read the actual data */
+ nxt200x_readbytes(state, reg, data, len);
+ return 0;
+ break;
+ case NXT2004:
+ /* probably not right, but gives correct values */
+ attr = 0x02;
+ if (reg & 0x80) {
+ attr = attr << 1;
+ if (reg & 0x04)
+ attr = attr >> 1;
+ }
+
+ /* set multi register length */
+ len2 = (attr << 4) | len;
+ nxt200x_writebytes(state, 0x34, &len2, 1);
+
+ /* toggle the multireg bit*/
+ buf = 0x80;
+ nxt200x_writebytes(state, 0x21, &buf, 1);
+
+ /* read the actual data */
+ for(i = 0; i < len; i++) {
+ nxt200x_readbytes(state, 0x36 + i, &data[i], 1);
+ }
+ return 0;
+ break;
+ default:
+ return -EINVAL;
+ break;
+ }
+}
+
+static void nxt200x_microcontroller_stop (struct nxt200x_state* state)
+{
+ u8 buf, stopval, counter = 0;
+ dprintk("%s\n", __FUNCTION__);
+
+ /* set correct stop value */
+ switch (state->demod_chip) {
+ case NXT2002:
+ stopval = 0x40;
+ break;
+ case NXT2004:
+ stopval = 0x10;
+ break;
+ default:
+ stopval = 0;
+ break;
+ }
+
+ buf = 0x80;
+ nxt200x_writebytes(state, 0x22, &buf, 1);
+
+ while (counter < 20) {
+ nxt200x_readbytes(state, 0x31, &buf, 1);
+ if (buf & stopval)
+ return;
+ msleep(10);
+ counter++;
+ }
+
+ printk(KERN_WARNING "nxt200x: Timeout waiting for nxt200x to stop. This is ok after firmware upload.\n");
+ return;
+}
+
+static void nxt200x_microcontroller_start (struct nxt200x_state* state)
+{
+ u8 buf;
+ dprintk("%s\n", __FUNCTION__);
+
+ buf = 0x00;
+ nxt200x_writebytes(state, 0x22, &buf, 1);
+}
+
+static void nxt2004_microcontroller_init (struct nxt200x_state* state)
+{
+ u8 buf[9];
+ u8 counter = 0;
+ dprintk("%s\n", __FUNCTION__);
+
+ buf[0] = 0x00;
+ nxt200x_writebytes(state, 0x2b, buf, 1);
+ buf[0] = 0x70;
+ nxt200x_writebytes(state, 0x34, buf, 1);
+ buf[0] = 0x04;
+ nxt200x_writebytes(state, 0x35, buf, 1);
+ buf[0] = 0x01; buf[1] = 0x23; buf[2] = 0x45; buf[3] = 0x67; buf[4] = 0x89;
+ buf[5] = 0xAB; buf[6] = 0xCD; buf[7] = 0xEF; buf[8] = 0xC0;
+ nxt200x_writebytes(state, 0x36, buf, 9);
+ buf[0] = 0x80;
+ nxt200x_writebytes(state, 0x21, buf, 1);
+
+ while (counter < 20) {
+ nxt200x_readbytes(state, 0x21, buf, 1);
+ if (buf[0] == 0)
+ return;
+ msleep(10);
+ counter++;
+ }
+
+ printk(KERN_WARNING "nxt200x: Timeout waiting for nxt2004 to init.\n");
+
+ return;
+}
+
+static int nxt200x_writetuner (struct nxt200x_state* state, u8* data)
+{
+ u8 buf, count = 0;
+
+ dprintk("%s\n", __FUNCTION__);
+
+ dprintk("Tuner Bytes: %02X %02X %02X %02X\n", data[0], data[1], data[2], data[3]);
+
+ /* if NXT2004, write directly to tuner. if NXT2002, write through NXT chip.
+ * direct write is required for Philips TUV1236D and ALPS TDHU2 */
+ switch (state->demod_chip) {
+ case NXT2004:
+ if (i2c_writebytes(state, state->config->pll_address, data, 4))
+ printk(KERN_WARNING "nxt200x: error writing to tuner\n");
+ /* wait until we have a lock */
+ while (count < 20) {
+ i2c_readbytes(state, state->config->pll_address, &buf, 1);
+ if (buf & 0x40)
+ return 0;
+ msleep(100);
+ count++;
+ }
+ printk("nxt2004: timeout waiting for tuner lock\n");
+ break;
+ case NXT2002:
+ /* set the i2c transfer speed to the tuner */
+ buf = 0x03;
+ nxt200x_writebytes(state, 0x20, &buf, 1);
+
+ /* setup to transfer 4 bytes via i2c */
+ buf = 0x04;
+ nxt200x_writebytes(state, 0x34, &buf, 1);
+
+ /* write actual tuner bytes */
+ nxt200x_writebytes(state, 0x36, data, 4);
+
+ /* set tuner i2c address */
+ buf = state->config->pll_address;
+ nxt200x_writebytes(state, 0x35, &buf, 1);
+
+ /* write UC Opmode to begin transfer */
+ buf = 0x80;
+ nxt200x_writebytes(state, 0x21, &buf, 1);
+
+ while (count < 20) {
+ nxt200x_readbytes(state, 0x21, &buf, 1);
+ if ((buf & 0x80)== 0x00)
+ return 0;
+ msleep(100);
+ count++;
+ }
+ printk("nxt2002: timeout error writing tuner\n");
+ break;
+ default:
+ return -EINVAL;
+ break;
+ }
+ return 0;
+}
+
+static void nxt200x_agc_reset(struct nxt200x_state* state)
+{
+ u8 buf;
+ dprintk("%s\n", __FUNCTION__);
+
+ switch (state->demod_chip) {
+ case NXT2002:
+ buf = 0x08;
+ nxt200x_writebytes(state, 0x08, &buf, 1);
+ buf = 0x00;
+ nxt200x_writebytes(state, 0x08, &buf, 1);
+ break;
+ case NXT2004:
+ nxt200x_readreg_multibyte(state, 0x08, &buf, 1);
+ buf = 0x08;
+ nxt200x_writereg_multibyte(state, 0x08, &buf, 1);
+ buf = 0x00;
+ nxt200x_writereg_multibyte(state, 0x08, &buf, 1);
+ break;
+ default:
+ break;
+ }
+ return;
+}
+
+static int nxt2002_load_firmware (struct dvb_frontend* fe, const struct firmware *fw)
+{
+
+ struct nxt200x_state* state = fe->demodulator_priv;
+ u8 buf[3], written = 0, chunkpos = 0;
+ u16 rambase, position, crc = 0;
+
+ dprintk("%s\n", __FUNCTION__);
+ dprintk("Firmware is %zu bytes\n", fw->size);
+
+ /* Get the RAM base for this nxt2002 */
+ nxt200x_readbytes(state, 0x10, buf, 1);
+
+ if (buf[0] & 0x10)
+ rambase = 0x1000;
+ else
+ rambase = 0x0000;
+
+ dprintk("rambase on this nxt2002 is %04X\n", rambase);
+
+ /* Hold the micro in reset while loading firmware */
+ buf[0] = 0x80;
+ nxt200x_writebytes(state, 0x2B, buf, 1);
+
+ for (position = 0; position < fw->size; position++) {
+ if (written == 0) {
+ crc = 0;
+ chunkpos = 0x28;
+ buf[0] = ((rambase + position) >> 8);
+ buf[1] = (rambase + position) & 0xFF;
+ buf[2] = 0x81;
+ /* write starting address */
+ nxt200x_writebytes(state, 0x29, buf, 3);
+ }
+ written++;
+ chunkpos++;
+
+ if ((written % 4) == 0)
+ nxt200x_writebytes(state, chunkpos, &fw->data[position-3], 4);
+
+ crc = nxt200x_crc(crc, fw->data[position]);
+
+ if ((written == 255) || (position+1 == fw->size)) {
+ /* write remaining bytes of firmware */
+ nxt200x_writebytes(state, chunkpos+4-(written %4),
+ &fw->data[position-(written %4) + 1],
+ written %4);
+ buf[0] = crc << 8;
+ buf[1] = crc & 0xFF;
+
+ /* write crc */
+ nxt200x_writebytes(state, 0x2C, buf, 2);
+
+ /* do a read to stop things */
+ nxt200x_readbytes(state, 0x2A, buf, 1);
+
+ /* set transfer mode to complete */
+ buf[0] = 0x80;
+ nxt200x_writebytes(state, 0x2B, buf, 1);
+
+ written = 0;
+ }
+ }
+
+ return 0;
+};
+
+static int nxt2004_load_firmware (struct dvb_frontend* fe, const struct firmware *fw)
+{
+
+ struct nxt200x_state* state = fe->demodulator_priv;
+ u8 buf[3];
+ u16 rambase, position, crc=0;
+
+ dprintk("%s\n", __FUNCTION__);
+ dprintk("Firmware is %zu bytes\n", fw->size);
+
+ /* set rambase */
+ rambase = 0x1000;
+
+ /* hold the micro in reset while loading firmware */
+ buf[0] = 0x80;
+ nxt200x_writebytes(state, 0x2B, buf,1);
+
+ /* calculate firmware CRC */
+ for (position = 0; position < fw->size; position++) {
+ crc = nxt200x_crc(crc, fw->data[position]);
+ }
+
+ buf[0] = rambase >> 8;
+ buf[1] = rambase & 0xFF;
+ buf[2] = 0x81;
+ /* write starting address */
+ nxt200x_writebytes(state,0x29,buf,3);
+
+ for (position = 0; position < fw->size;) {
+ nxt200x_writebytes(state, 0x2C, &fw->data[position],
+ fw->size-position > 255 ? 255 : fw->size-position);
+ position += (fw->size-position > 255 ? 255 : fw->size-position);
+ }
+ buf[0] = crc >> 8;
+ buf[1] = crc & 0xFF;
+
+ dprintk("firmware crc is 0x%02X 0x%02X\n", buf[0], buf[1]);
+
+ /* write crc */
+ nxt200x_writebytes(state, 0x2C, buf,2);
+
+ /* do a read to stop things */
+ nxt200x_readbytes(state, 0x2C, buf, 1);
+
+ /* set transfer mode to complete */
+ buf[0] = 0x80;
+ nxt200x_writebytes(state, 0x2B, buf,1);
+
+ return 0;
+};
+
+static int nxt200x_setup_frontend_parameters (struct dvb_frontend* fe,
+ struct dvb_frontend_parameters *p)
+{
+ struct nxt200x_state* state = fe->demodulator_priv;
+ u8 buf[4];
+
+ /* stop the micro first */
+ nxt200x_microcontroller_stop(state);
+
+ if (state->demod_chip == NXT2004) {
+ /* make sure demod is set to digital */
+ buf[0] = 0x04;
+ nxt200x_writebytes(state, 0x14, buf, 1);
+ buf[0] = 0x00;
+ nxt200x_writebytes(state, 0x17, buf, 1);
+ }
+
+ /* get tuning information */
+ dvb_pll_configure(state->config->pll_desc, buf, p->frequency, 0);
+
+ /* set additional params */
+ switch (p->u.vsb.modulation) {
+ case QAM_64:
+ case QAM_256:
+ /* Set punctured clock for QAM */
+ /* This is just a guess since I am unable to test it */
+ if (state->config->set_ts_params)
+ state->config->set_ts_params(fe, 1);
+
+ /* set input */
+ if (state->config->set_pll_input)
+ state->config->set_pll_input(buf, 1);
+ break;
+ case VSB_8:
+ /* Set non-punctured clock for VSB */
+ if (state->config->set_ts_params)
+ state->config->set_ts_params(fe, 0);
+
+ /* set input */
+ if (state->config->set_pll_input)
+ state->config->set_pll_input(buf, 0);
+ break;
+ default:
+ return -EINVAL;
+ break;
+ }
+
+ /* write frequency information */
+ nxt200x_writetuner(state, buf);
+
+ /* reset the agc now that tuning has been completed */
+ nxt200x_agc_reset(state);
+
+ /* set target power level */
+ switch (p->u.vsb.modulation) {
+ case QAM_64:
+ case QAM_256:
+ buf[0] = 0x74;
+ break;
+ case VSB_8:
+ buf[0] = 0x70;
+ break;
+ default:
+ return -EINVAL;
+ break;
+ }
+ nxt200x_writebytes(state, 0x42, buf, 1);
+
+ /* configure sdm */
+ switch (state->demod_chip) {
+ case NXT2002:
+ buf[0] = 0x87;
+ break;
+ case NXT2004:
+ buf[0] = 0x07;
+ break;
+ default:
+ return -EINVAL;
+ break;
+ }
+ nxt200x_writebytes(state, 0x57, buf, 1);
+
+ /* write sdm1 input */
+ buf[0] = 0x10;
+ buf[1] = 0x00;
+ nxt200x_writebytes(state, 0x58, buf, 2);
+
+ /* write sdmx input */
+ switch (p->u.vsb.modulation) {
+ case QAM_64:
+ buf[0] = 0x68;
+ break;
+ case QAM_256:
+ buf[0] = 0x64;
+ break;
+ case VSB_8:
+ buf[0] = 0x60;
+ break;
+ default:
+ return -EINVAL;
+ break;
+ }
+ buf[1] = 0x00;
+ nxt200x_writebytes(state, 0x5C, buf, 2);
+
+ /* write adc power lpf fc */
+ buf[0] = 0x05;
+ nxt200x_writebytes(state, 0x43, buf, 1);
+
+ if (state->demod_chip == NXT2004) {
+ /* write ??? */
+ buf[0] = 0x00;
+ buf[1] = 0x00;
+ nxt200x_writebytes(state, 0x46, buf, 2);
+ }
+
+ /* write accumulator2 input */
+ buf[0] = 0x80;
+ buf[1] = 0x00;
+ nxt200x_writebytes(state, 0x4B, buf, 2);
+
+ /* write kg1 */
+ buf[0] = 0x00;
+ nxt200x_writebytes(state, 0x4D, buf, 1);
+
+ /* write sdm12 lpf fc */
+ buf[0] = 0x44;
+ nxt200x_writebytes(state, 0x55, buf, 1);
+
+ /* write agc control reg */
+ buf[0] = 0x04;
+ nxt200x_writebytes(state, 0x41, buf, 1);
+
+ if (state->demod_chip == NXT2004) {
+ nxt200x_readreg_multibyte(state, 0x80, buf, 1);
+ buf[0] = 0x24;
+ nxt200x_writereg_multibyte(state, 0x80, buf, 1);
+
+ /* soft reset? */
+ nxt200x_readreg_multibyte(state, 0x08, buf, 1);
+ buf[0] = 0x10;
+ nxt200x_writereg_multibyte(state, 0x08, buf, 1);
+ nxt200x_readreg_multibyte(state, 0x08, buf, 1);
+ buf[0] = 0x00;
+ nxt200x_writereg_multibyte(state, 0x08, buf, 1);
+
+ nxt200x_readreg_multibyte(state, 0x80, buf, 1);
+ buf[0] = 0x04;
+ nxt200x_writereg_multibyte(state, 0x80, buf, 1);
+ buf[0] = 0x00;
+ nxt200x_writereg_multibyte(state, 0x81, buf, 1);
+ buf[0] = 0x80; buf[1] = 0x00; buf[2] = 0x00;
+ nxt200x_writereg_multibyte(state, 0x82, buf, 3);
+ nxt200x_readreg_multibyte(state, 0x88, buf, 1);
+ buf[0] = 0x11;
+ nxt200x_writereg_multibyte(state, 0x88, buf, 1);
+ nxt200x_readreg_multibyte(state, 0x80, buf, 1);
+ buf[0] = 0x44;
+ nxt200x_writereg_multibyte(state, 0x80, buf, 1);
+ }
+
+ /* write agc ucgp0 */
+ switch (p->u.vsb.modulation) {
+ case QAM_64:
+ buf[0] = 0x02;
+ break;
+ case QAM_256:
+ buf[0] = 0x03;
+ break;
+ case VSB_8:
+ buf[0] = 0x00;
+ break;
+ default:
+ return -EINVAL;
+ break;
+ }
+ nxt200x_writebytes(state, 0x30, buf, 1);
+
+ /* write agc control reg */
+ buf[0] = 0x00;
+ nxt200x_writebytes(state, 0x41, buf, 1);
+
+ /* write accumulator2 input */
+ buf[0] = 0x80;
+ buf[1] = 0x00;
+ nxt200x_writebytes(state, 0x49, buf,2);
+ nxt200x_writebytes(state, 0x4B, buf,2);
+
+ /* write agc control reg */
+ buf[0] = 0x04;
+ nxt200x_writebytes(state, 0x41, buf, 1);
+
+ nxt200x_microcontroller_start(state);
+
+ if (state->demod_chip == NXT2004) {
+ nxt2004_microcontroller_init(state);
+
+ /* ???? */
+ buf[0] = 0xF0;
+ buf[1] = 0x00;
+ nxt200x_writebytes(state, 0x5C, buf, 2);
+ }
+
+ /* adjacent channel detection should be done here, but I don't
+ have any stations with this need so I cannot test it */
+
+ return 0;
+}
+
+static int nxt200x_read_status(struct dvb_frontend* fe, fe_status_t* status)
+{
+ struct nxt200x_state* state = fe->demodulator_priv;
+ u8 lock;
+ nxt200x_readbytes(state, 0x31, &lock, 1);
+
+ *status = 0;
+ if (lock & 0x20) {
+ *status |= FE_HAS_SIGNAL;
+ *status |= FE_HAS_CARRIER;
+ *status |= FE_HAS_VITERBI;
+ *status |= FE_HAS_SYNC;
+ *status |= FE_HAS_LOCK;
+ }
+ return 0;
+}
+
+static int nxt200x_read_ber(struct dvb_frontend* fe, u32* ber)
+{
+ struct nxt200x_state* state = fe->demodulator_priv;
+ u8 b[3];
+
+ nxt200x_readreg_multibyte(state, 0xE6, b, 3);
+
+ *ber = ((b[0] << 8) + b[1]) * 8;
+
+ return 0;
+}
+
+static int nxt200x_read_signal_strength(struct dvb_frontend* fe, u16* strength)
+{
+ struct nxt200x_state* state = fe->demodulator_priv;
+ u8 b[2];
+ u16 temp = 0;
+
+ /* setup to read cluster variance */
+ b[0] = 0x00;
+ nxt200x_writebytes(state, 0xA1, b, 1);
+
+ /* get multreg val */
+ nxt200x_readreg_multibyte(state, 0xA6, b, 2);
+
+ temp = (b[0] << 8) | b[1];
+ *strength = ((0x7FFF - temp) & 0x0FFF) * 16;
+
+ return 0;
+}
+
+static int nxt200x_read_snr(struct dvb_frontend* fe, u16* snr)
+{
+
+ struct nxt200x_state* state = fe->demodulator_priv;
+ u8 b[2];
+ u16 temp = 0, temp2;
+ u32 snrdb = 0;
+
+ /* setup to read cluster variance */
+ b[0] = 0x00;
+ nxt200x_writebytes(state, 0xA1, b, 1);
+
+ /* get multreg val from 0xA6 */
+ nxt200x_readreg_multibyte(state, 0xA6, b, 2);
+
+ temp = (b[0] << 8) | b[1];
+ temp2 = 0x7FFF - temp;
+
+ /* snr will be in db */
+ if (temp2 > 0x7F00)
+ snrdb = 1000*24 + ( 1000*(30-24) * ( temp2 - 0x7F00 ) / ( 0x7FFF - 0x7F00 ) );
+ else if (temp2 > 0x7EC0)
+ snrdb = 1000*18 + ( 1000*(24-18) * ( temp2 - 0x7EC0 ) / ( 0x7F00 - 0x7EC0 ) );
+ else if (temp2 > 0x7C00)
+ snrdb = 1000*12 + ( 1000*(18-12) * ( temp2 - 0x7C00 ) / ( 0x7EC0 - 0x7C00 ) );
+ else
+ snrdb = 1000*0 + ( 1000*(12-0) * ( temp2 - 0 ) / ( 0x7C00 - 0 ) );
+
+ /* the value reported back from the frontend will be FFFF=32db 0000=0db */
+ *snr = snrdb * (0xFFFF/32000);
+
+ return 0;
+}
+
+static int nxt200x_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
+{
+ struct nxt200x_state* state = fe->demodulator_priv;
+ u8 b[3];
+
+ nxt200x_readreg_multibyte(state, 0xE6, b, 3);
+ *ucblocks = b[2];
+
+ return 0;
+}
+
+static int nxt200x_sleep(struct dvb_frontend* fe)
+{
+ return 0;
+}
+
+static int nxt2002_init(struct dvb_frontend* fe)
+{
+ struct nxt200x_state* state = fe->demodulator_priv;
+ const struct firmware *fw;
+ int ret;
+ u8 buf[2];
+
+ /* request the firmware, this will block until someone uploads it */
+ printk("nxt2002: Waiting for firmware upload (%s)...\n", NXT2002_DEFAULT_FIRMWARE);
+ ret = request_firmware(&fw, NXT2002_DEFAULT_FIRMWARE, &state->i2c->dev);
+ printk("nxt2002: Waiting for firmware upload(2)...\n");
+ if (ret) {
+ printk("nxt2002: No firmware uploaded (timeout or file not found?)\n");
+ return ret;
+ }
+
+ ret = nxt2002_load_firmware(fe, fw);
+ if (ret) {
+ printk("nxt2002: Writing firmware to device failed\n");
+ release_firmware(fw);
+ return ret;
+ }
+ printk("nxt2002: Firmware upload complete\n");
+
+ /* Put the micro into reset */
+ nxt200x_microcontroller_stop(state);
+
+ /* ensure transfer is complete */
+ buf[0]=0x00;
+ nxt200x_writebytes(state, 0x2B, buf, 1);
+
+ /* Put the micro into reset for real this time */
+ nxt200x_microcontroller_stop(state);
+
+ /* soft reset everything (agc,frontend,eq,fec)*/
+ buf[0] = 0x0F;
+ nxt200x_writebytes(state, 0x08, buf, 1);
+ buf[0] = 0x00;
+ nxt200x_writebytes(state, 0x08, buf, 1);
+
+ /* write agc sdm configure */
+ buf[0] = 0xF1;
+ nxt200x_writebytes(state, 0x57, buf, 1);
+
+ /* write mod output format */
+ buf[0] = 0x20;
+ nxt200x_writebytes(state, 0x09, buf, 1);
+
+ /* write fec mpeg mode */
+ buf[0] = 0x7E;
+ buf[1] = 0x00;
+ nxt200x_writebytes(state, 0xE9, buf, 2);
+
+ /* write mux selection */
+ buf[0] = 0x00;
+ nxt200x_writebytes(state, 0xCC, buf, 1);
+
+ return 0;
+}
+
+static int nxt2004_init(struct dvb_frontend* fe)
+{
+ struct nxt200x_state* state = fe->demodulator_priv;
+ const struct firmware *fw;
+ int ret;
+ u8 buf[3];
+
+ /* ??? */
+ buf[0]=0x00;
+ nxt200x_writebytes(state, 0x1E, buf, 1);
+
+ /* request the firmware, this will block until someone uploads it */
+ printk("nxt2004: Waiting for firmware upload (%s)...\n", NXT2004_DEFAULT_FIRMWARE);
+ ret = request_firmware(&fw, NXT2004_DEFAULT_FIRMWARE, &state->i2c->dev);
+ printk("nxt2004: Waiting for firmware upload(2)...\n");
+ if (ret) {
+ printk("nxt2004: No firmware uploaded (timeout or file not found?)\n");
+ return ret;
+ }
+
+ ret = nxt2004_load_firmware(fe, fw);
+ if (ret) {
+ printk("nxt2004: Writing firmware to device failed\n");
+ release_firmware(fw);
+ return ret;
+ }
+ printk("nxt2004: Firmware upload complete\n");
+
+ /* ensure transfer is complete */
+ buf[0] = 0x01;
+ nxt200x_writebytes(state, 0x19, buf, 1);
+
+ nxt2004_microcontroller_init(state);
+ nxt200x_microcontroller_stop(state);
+ nxt200x_microcontroller_stop(state);
+ nxt2004_microcontroller_init(state);
+ nxt200x_microcontroller_stop(state);
+
+ /* soft reset everything (agc,frontend,eq,fec)*/
+ buf[0] = 0xFF;
+ nxt200x_writereg_multibyte(state, 0x08, buf, 1);
+ buf[0] = 0x00;
+ nxt200x_writereg_multibyte(state, 0x08, buf, 1);
+
+ /* write agc sdm configure */
+ buf[0] = 0xD7;
+ nxt200x_writebytes(state, 0x57, buf, 1);
+
+ /* ???*/
+ buf[0] = 0x07;
+ buf[1] = 0xfe;
+ nxt200x_writebytes(state, 0x35, buf, 2);
+ buf[0] = 0x12;
+ nxt200x_writebytes(state, 0x34, buf, 1);
+ buf[0] = 0x80;
+ nxt200x_writebytes(state, 0x21, buf, 1);
+
+ /* ???*/
+ buf[0] = 0x21;
+ nxt200x_writebytes(state, 0x0A, buf, 1);
+
+ /* ???*/
+ buf[0] = 0x01;
+ nxt200x_writereg_multibyte(state, 0x80, buf, 1);
+
+ /* write fec mpeg mode */
+ buf[0] = 0x7E;
+ buf[1] = 0x00;
+ nxt200x_writebytes(state, 0xE9, buf, 2);
+
+ /* write mux selection */
+ buf[0] = 0x00;
+ nxt200x_writebytes(state, 0xCC, buf, 1);
+
+ /* ???*/
+ nxt200x_readreg_multibyte(state, 0x80, buf, 1);
+ buf[0] = 0x00;
+ nxt200x_writereg_multibyte(state, 0x80, buf, 1);
+
+ /* soft reset? */
+ nxt200x_readreg_multibyte(state, 0x08, buf, 1);
+ buf[0] = 0x10;
+ nxt200x_writereg_multibyte(state, 0x08, buf, 1);
+ nxt200x_readreg_multibyte(state, 0x08, buf, 1);
+ buf[0] = 0x00;
+ nxt200x_writereg_multibyte(state, 0x08, buf, 1);
+
+ /* ???*/
+ nxt200x_readreg_multibyte(state, 0x80, buf, 1);
+ buf[0] = 0x01;
+ nxt200x_writereg_multibyte(state, 0x80, buf, 1);
+ buf[0] = 0x70;
+ nxt200x_writereg_multibyte(state, 0x81, buf, 1);
+ buf[0] = 0x31; buf[1] = 0x5E; buf[2] = 0x66;
+ nxt200x_writereg_multibyte(state, 0x82, buf, 3);
+
+ nxt200x_readreg_multibyte(state, 0x88, buf, 1);
+ buf[0] = 0x11;
+ nxt200x_writereg_multibyte(state, 0x88, buf, 1);
+ nxt200x_readreg_multibyte(state, 0x80, buf, 1);
+ buf[0] = 0x40;
+ nxt200x_writereg_multibyte(state, 0x80, buf, 1);
+
+ nxt200x_readbytes(state, 0x10, buf, 1);
+ buf[0] = 0x10;
+ nxt200x_writebytes(state, 0x10, buf, 1);
+ nxt200x_readbytes(state, 0x0A, buf, 1);
+ buf[0] = 0x21;
+ nxt200x_writebytes(state, 0x0A, buf, 1);
+
+ nxt2004_microcontroller_init(state);
+
+ buf[0] = 0x21;
+ nxt200x_writebytes(state, 0x0A, buf, 1);
+ buf[0] = 0x7E;
+ nxt200x_writebytes(state, 0xE9, buf, 1);
+ buf[0] = 0x00;
+ nxt200x_writebytes(state, 0xEA, buf, 1);
+
+ nxt200x_readreg_multibyte(state, 0x80, buf, 1);
+ buf[0] = 0x00;
+ nxt200x_writereg_multibyte(state, 0x80, buf, 1);
+ nxt200x_readreg_multibyte(state, 0x80, buf, 1);
+ buf[0] = 0x00;
+ nxt200x_writereg_multibyte(state, 0x80, buf, 1);
+
+ /* soft reset? */
+ nxt200x_readreg_multibyte(state, 0x08, buf, 1);
+ buf[0] = 0x10;
+ nxt200x_writereg_multibyte(state, 0x08, buf, 1);
+ nxt200x_readreg_multibyte(state, 0x08, buf, 1);
+ buf[0] = 0x00;
+ nxt200x_writereg_multibyte(state, 0x08, buf, 1);
+
+ nxt200x_readreg_multibyte(state, 0x80, buf, 1);
+ buf[0] = 0x04;
+ nxt200x_writereg_multibyte(state, 0x80, buf, 1);
+ buf[0] = 0x00;
+ nxt200x_writereg_multibyte(state, 0x81, buf, 1);
+ buf[0] = 0x80; buf[1] = 0x00; buf[2] = 0x00;
+ nxt200x_writereg_multibyte(state, 0x82, buf, 3);
+
+ nxt200x_readreg_multibyte(state, 0x88, buf, 1);
+ buf[0] = 0x11;
+ nxt200x_writereg_multibyte(state, 0x88, buf, 1);
+
+ nxt200x_readreg_multibyte(state, 0x80, buf, 1);
+ buf[0] = 0x44;
+ nxt200x_writereg_multibyte(state, 0x80, buf, 1);
+
+ /* initialize tuner */
+ nxt200x_readbytes(state, 0x10, buf, 1);
+ buf[0] = 0x12;
+ nxt200x_writebytes(state, 0x10, buf, 1);
+ buf[0] = 0x04;
+ nxt200x_writebytes(state, 0x13, buf, 1);
+ buf[0] = 0x00;
+ nxt200x_writebytes(state, 0x16, buf, 1);
+ buf[0] = 0x04;
+ nxt200x_writebytes(state, 0x14, buf, 1);
+ buf[0] = 0x00;
+ nxt200x_writebytes(state, 0x14, buf, 1);
+ nxt200x_writebytes(state, 0x17, buf, 1);
+ nxt200x_writebytes(state, 0x14, buf, 1);
+ nxt200x_writebytes(state, 0x17, buf, 1);
+
+ return 0;
+}
+
+static int nxt200x_init(struct dvb_frontend* fe)
+{
+ struct nxt200x_state* state = fe->demodulator_priv;
+ int ret = 0;
+
+ if (!state->initialised) {
+ switch (state->demod_chip) {
+ case NXT2002:
+ ret = nxt2002_init(fe);
+ break;
+ case NXT2004:
+ ret = nxt2004_init(fe);
+ break;
+ default:
+ return -EINVAL;
+ break;
+ }
+ state->initialised = 1;
+ }
+ return ret;
+}
+
+static int nxt200x_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fesettings)
+{
+ fesettings->min_delay_ms = 500;
+ fesettings->step_size = 0;
+ fesettings->max_drift = 0;
+ return 0;
+}
+
+static void nxt200x_release(struct dvb_frontend* fe)
+{
+ struct nxt200x_state* state = fe->demodulator_priv;
+ kfree(state);
+}
+
+static struct dvb_frontend_ops nxt200x_ops;
+
+struct dvb_frontend* nxt200x_attach(const struct nxt200x_config* config,
+ struct i2c_adapter* i2c)
+{
+ struct nxt200x_state* state = NULL;
+ u8 buf [] = {0,0,0,0,0};
+
+ /* allocate memory for the internal state */
+ state = (struct nxt200x_state*) kmalloc(sizeof(struct nxt200x_state), GFP_KERNEL);
+ if (state == NULL)
+ goto error;
+ memset(state,0,sizeof(*state));
+
+ /* setup the state */
+ state->config = config;
+ state->i2c = i2c;
+ memcpy(&state->ops, &nxt200x_ops, sizeof(struct dvb_frontend_ops));
+ state->initialised = 0;
+
+ /* read card id */
+ nxt200x_readbytes(state, 0x00, buf, 5);
+ dprintk("NXT info: %02X %02X %02X %02X %02X\n",
+ buf[0], buf[1], buf[2], buf[3], buf[4]);
+
+ /* set demod chip */
+ switch (buf[0]) {
+ case 0x04:
+ state->demod_chip = NXT2002;
+ printk("nxt200x: NXT2002 Detected\n");
+ break;
+ case 0x05:
+ state->demod_chip = NXT2004;
+ printk("nxt200x: NXT2004 Detected\n");
+ break;
+ default:
+ goto error;
+ }
+
+ /* make sure demod chip is supported */
+ switch (state->demod_chip) {
+ case NXT2002:
+ if (buf[0] != 0x04) goto error; /* device id */
+ if (buf[1] != 0x02) goto error; /* fab id */
+ if (buf[2] != 0x11) goto error; /* month */
+ if (buf[3] != 0x20) goto error; /* year msb */
+ if (buf[4] != 0x00) goto error; /* year lsb */
+ break;
+ case NXT2004:
+ if (buf[0] != 0x05) goto error; /* device id */
+ break;
+ default:
+ goto error;
+ }
+
+ /* create dvb_frontend */
+ state->frontend.ops = &state->ops;
+ state->frontend.demodulator_priv = state;
+ return &state->frontend;
+
+error:
+ kfree(state);
+ printk("Unknown/Unsupported NXT chip: %02X %02X %02X %02X %02X\n",
+ buf[0], buf[1], buf[2], buf[3], buf[4]);
+ return NULL;
+}
+
+static struct dvb_frontend_ops nxt200x_ops = {
+
+ .info = {
+ .name = "Nextwave NXT200X VSB/QAM frontend",
+ .type = FE_ATSC,
+ .frequency_min = 54000000,
+ .frequency_max = 860000000,
+ .frequency_stepsize = 166666, /* stepsize is just a guess */
+ .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_8VSB | FE_CAN_QAM_64 | FE_CAN_QAM_256
+ },
+
+ .release = nxt200x_release,
+
+ .init = nxt200x_init,
+ .sleep = nxt200x_sleep,
+
+ .set_frontend = nxt200x_setup_frontend_parameters,
+ .get_tune_settings = nxt200x_get_tune_settings,
+
+ .read_status = nxt200x_read_status,
+ .read_ber = nxt200x_read_ber,
+ .read_signal_strength = nxt200x_read_signal_strength,
+ .read_snr = nxt200x_read_snr,
+ .read_ucblocks = nxt200x_read_ucblocks,
+};
+
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
+
+MODULE_DESCRIPTION("NXT200X (ATSC 8VSB & ITU-T J.83 AnnexB 64/256 QAM) Demodulator Driver");
+MODULE_AUTHOR("Kirk Lapray, Jean-Francois Thibert, and Taylor Jacob");
+MODULE_LICENSE("GPL");
+
+EXPORT_SYMBOL(nxt200x_attach);
+
diff --git a/drivers/media/dvb/frontends/nxt200x.h b/drivers/media/dvb/frontends/nxt200x.h
new file mode 100644
index 000000000000..1d9d70bc37ef
--- /dev/null
+++ b/drivers/media/dvb/frontends/nxt200x.h
@@ -0,0 +1,61 @@
+/*
+ * Support for NXT2002 and NXT2004 - VSB/QAM
+ *
+ * Copyright (C) 2005 Kirk Lapray (kirk.lapray@gmail.com)
+ * based on nxt2002 by Taylor Jacob <rtjacob@earthlink.net>
+ * and nxt2004 by Jean-Francois Thibert (jeanfrancois@sagetv.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 NXT200X_H
+#define NXT200X_H
+
+#include <linux/dvb/frontend.h>
+#include <linux/firmware.h>
+
+typedef enum nxt_chip_t {
+ NXTUNDEFINED,
+ NXT2002,
+ NXT2004
+}nxt_chip_type;
+
+struct nxt200x_config
+{
+ /* the demodulator's i2c address */
+ u8 demod_address;
+
+ /* tuner information */
+ u8 pll_address;
+ struct dvb_pll_desc *pll_desc;
+
+ /* used to set pll input */
+ int (*set_pll_input)(u8* buf, int input);
+
+ /* need to set device param for start_dma */
+ int (*set_ts_params)(struct dvb_frontend* fe, int is_punctured);
+};
+
+extern struct dvb_frontend* nxt200x_attach(const struct nxt200x_config* config,
+ struct i2c_adapter* i2c);
+
+#endif /* NXT200X_H */
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/drivers/media/dvb/frontends/or51132.c b/drivers/media/dvb/frontends/or51132.c
index 817b044c7fd1..78bded861d02 100644
--- a/drivers/media/dvb/frontends/or51132.c
+++ b/drivers/media/dvb/frontends/or51132.c
@@ -468,6 +468,7 @@ static int or51132_read_signal_strength(struct dvb_frontend* fe, u16* strength)
unsigned char snd_buf[2];
u8 rcvr_stat;
u16 snr_equ;
+ u32 signal_strength;
int usK;
snd_buf[0]=0x04;
@@ -503,7 +504,11 @@ static int or51132_read_signal_strength(struct dvb_frontend* fe, u16* strength)
usK = (rcvr_stat & 0x10) ? 3 : 0;
/* The value reported back from the frontend will be FFFF=100% 0000=0% */
- *strength = (((8952 - i20Log10(snr_equ) - usK*100)/3+5)*65535)/1000;
+ signal_strength = (((8952 - i20Log10(snr_equ) - usK*100)/3+5)*65535)/1000;
+ if (signal_strength > 0xffff)
+ *strength = 0xffff;
+ else
+ *strength = signal_strength;
dprintk("read_signal_strength %i\n",*strength);
return 0;
@@ -577,8 +582,7 @@ struct dvb_frontend* or51132_attach(const struct or51132_config* config,
return &state->frontend;
error:
- if (state)
- kfree(state);
+ kfree(state);
return NULL;
}
diff --git a/drivers/media/dvb/frontends/or51211.c b/drivers/media/dvb/frontends/or51211.c
index 8a9db23dd1b7..531f76246e5f 100644
--- a/drivers/media/dvb/frontends/or51211.c
+++ b/drivers/media/dvb/frontends/or51211.c
@@ -339,6 +339,7 @@ static int or51211_read_signal_strength(struct dvb_frontend* fe, u16* strength)
u8 rec_buf[2];
u8 snd_buf[4];
u8 snr_equ;
+ u32 signal_strength;
/* SNR after Equalizer */
snd_buf[0] = 0x04;
@@ -358,8 +359,11 @@ static int or51211_read_signal_strength(struct dvb_frontend* fe, u16* strength)
snr_equ = rec_buf[0] & 0xff;
/* The value reported back from the frontend will be FFFF=100% 0000=0% */
- *strength = (((5334 - i20Log10(snr_equ))/3+5)*65535)/1000;
-
+ signal_strength = (((5334 - i20Log10(snr_equ))/3+5)*65535)/1000;
+ if (signal_strength > 0xffff)
+ *strength = 0xffff;
+ else
+ *strength = signal_strength;
dprintk("read_signal_strength %i\n",*strength);
return 0;
diff --git a/drivers/media/dvb/frontends/stv0299.c b/drivers/media/dvb/frontends/stv0299.c
index 889d9257215d..29c48665e130 100644
--- a/drivers/media/dvb/frontends/stv0299.c
+++ b/drivers/media/dvb/frontends/stv0299.c
@@ -64,8 +64,12 @@ struct stv0299_state {
u32 tuner_frequency;
u32 symbol_rate;
fe_code_rate_t fec_inner;
+ int errmode;
};
+#define STATUS_BER 0
+#define STATUS_UCBLOCKS 1
+
static int debug;
static int debug_legacy_dish_switch;
#define dprintk(args...) \
@@ -383,36 +387,6 @@ static int stv0299_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t voltag
};
}
-static inline s32 stv0299_calc_usec_delay (struct timeval lasttime, struct timeval curtime)
-{
- return ((curtime.tv_usec < lasttime.tv_usec) ?
- 1000000 - lasttime.tv_usec + curtime.tv_usec :
- curtime.tv_usec - lasttime.tv_usec);
-}
-
-static void stv0299_sleep_until (struct timeval *waketime, u32 add_usec)
-{
- struct timeval lasttime;
- s32 delta, newdelta;
-
- waketime->tv_usec += add_usec;
- if (waketime->tv_usec >= 1000000) {
- waketime->tv_usec -= 1000000;
- waketime->tv_sec++;
- }
-
- do_gettimeofday (&lasttime);
- delta = stv0299_calc_usec_delay (lasttime, *waketime);
- if (delta > 2500) {
- msleep ((delta - 1500) / 1000);
- do_gettimeofday (&lasttime);
- newdelta = stv0299_calc_usec_delay (lasttime, *waketime);
- delta = (newdelta > delta) ? 0 : newdelta;
- }
- if (delta > 0)
- udelay (delta);
-}
-
static int stv0299_send_legacy_dish_cmd (struct dvb_frontend* fe, u32 cmd)
{
struct stv0299_state* state = fe->demodulator_priv;
@@ -440,7 +414,7 @@ static int stv0299_send_legacy_dish_cmd (struct dvb_frontend* fe, u32 cmd)
memcpy (&tv[0], &nexttime, sizeof (struct timeval));
stv0299_writeregI (state, 0x0c, reg0x0c | 0x50); /* set LNB to 18V */
- stv0299_sleep_until (&nexttime, 32000);
+ dvb_frontend_sleep_until(&nexttime, 32000);
for (i=0; i<9; i++) {
if (debug_legacy_dish_switch)
@@ -454,13 +428,13 @@ static int stv0299_send_legacy_dish_cmd (struct dvb_frontend* fe, u32 cmd)
cmd = cmd >> 1;
if (i != 8)
- stv0299_sleep_until (&nexttime, 8000);
+ dvb_frontend_sleep_until(&nexttime, 8000);
}
if (debug_legacy_dish_switch) {
printk ("%s(%d): switch delay (should be 32k followed by all 8k\n",
__FUNCTION__, fe->dvb->num);
- for (i=1; i < 10; i++)
- printk ("%d: %d\n", i, stv0299_calc_usec_delay (tv[i-1] , tv[i]));
+ for (i = 1; i < 10; i++)
+ printk ("%d: %d\n", i, timeval_usec_diff(tv[i-1] , tv[i]));
}
return 0;
@@ -517,8 +491,7 @@ static int stv0299_read_ber(struct dvb_frontend* fe, u32* ber)
{
struct stv0299_state* state = fe->demodulator_priv;
- stv0299_writeregI(state, 0x34, (stv0299_readreg(state, 0x34) & 0xcf) | 0x10);
- msleep(100);
+ if (state->errmode != STATUS_BER) return 0;
*ber = (stv0299_readreg (state, 0x1d) << 8) | stv0299_readreg (state, 0x1e);
return 0;
@@ -557,9 +530,8 @@ static int stv0299_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
{
struct stv0299_state* state = fe->demodulator_priv;
- stv0299_writeregI(state, 0x34, (stv0299_readreg(state, 0x34) & 0xcf) | 0x30);
- msleep(100);
- *ucblocks = (stv0299_readreg (state, 0x1d) << 8) | stv0299_readreg (state, 0x1e);
+ if (state->errmode != STATUS_UCBLOCKS) *ucblocks = 0;
+ else *ucblocks = (stv0299_readreg (state, 0x1d) << 8) | stv0299_readreg (state, 0x1e);
return 0;
}
@@ -581,49 +553,14 @@ static int stv0299_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
if (state->config->invert) invval = (~invval) & 1;
stv0299_writeregI(state, 0x0c, (stv0299_readreg(state, 0x0c) & 0xfe) | invval);
- if (state->config->enhanced_tuning) {
- /* check if we should do a finetune */
- int frequency_delta = p->frequency - state->tuner_frequency;
- int minmax = p->u.qpsk.symbol_rate / 2000;
- if (minmax < 5000) minmax = 5000;
-
- if ((frequency_delta > -minmax) && (frequency_delta < minmax) && (frequency_delta != 0) &&
- (state->fec_inner == p->u.qpsk.fec_inner) &&
- (state->symbol_rate == p->u.qpsk.symbol_rate)) {
- int Drot_freq = (frequency_delta << 16) / (state->config->mclk / 1000);
-
- // zap the derotator registers first
- stv0299_writeregI(state, 0x22, 0x00);
- stv0299_writeregI(state, 0x23, 0x00);
-
- // now set them as we want
- stv0299_writeregI(state, 0x22, Drot_freq >> 8);
- stv0299_writeregI(state, 0x23, Drot_freq);
- } else {
- /* A "normal" tune is requested */
- stv0299_writeregI(state, 0x05, 0xb5); /* enable i2c repeater on stv0299 */
- state->config->pll_set(fe, state->i2c, p);
- stv0299_writeregI(state, 0x05, 0x35); /* disable i2c repeater on stv0299 */
-
- stv0299_writeregI(state, 0x32, 0x80);
- stv0299_writeregI(state, 0x22, 0x00);
- stv0299_writeregI(state, 0x23, 0x00);
- stv0299_writeregI(state, 0x32, 0x19);
- stv0299_set_symbolrate (fe, p->u.qpsk.symbol_rate);
- stv0299_set_FEC (state, p->u.qpsk.fec_inner);
- }
- } else {
- stv0299_writeregI(state, 0x05, 0xb5); /* enable i2c repeater on stv0299 */
- state->config->pll_set(fe, state->i2c, p);
- stv0299_writeregI(state, 0x05, 0x35); /* disable i2c repeater on stv0299 */
+ stv0299_writeregI(state, 0x05, 0xb5); /* enable i2c repeater on stv0299 */
+ state->config->pll_set(fe, state->i2c, p);
+ stv0299_writeregI(state, 0x05, 0x35); /* disable i2c repeater on stv0299 */
- stv0299_set_FEC (state, p->u.qpsk.fec_inner);
- stv0299_set_symbolrate (fe, p->u.qpsk.symbol_rate);
- stv0299_writeregI(state, 0x22, 0x00);
- stv0299_writeregI(state, 0x23, 0x00);
- stv0299_readreg (state, 0x23);
- stv0299_writeregI(state, 0x12, 0xb9);
- }
+ stv0299_set_FEC (state, p->u.qpsk.fec_inner);
+ stv0299_set_symbolrate (fe, p->u.qpsk.symbol_rate);
+ stv0299_writeregI(state, 0x22, 0x00);
+ stv0299_writeregI(state, 0x23, 0x00);
state->tuner_frequency = p->frequency;
state->fec_inner = p->u.qpsk.fec_inner;
@@ -708,6 +645,7 @@ struct dvb_frontend* stv0299_attach(const struct stv0299_config* config,
state->tuner_frequency = 0;
state->symbol_rate = 0;
state->fec_inner = 0;
+ state->errmode = STATUS_BER;
/* check if the demod is there */
stv0299_writeregI(state, 0x02, 0x34); /* standby off */
diff --git a/drivers/media/dvb/frontends/stv0299.h b/drivers/media/dvb/frontends/stv0299.h
index d0c4484861e1..9af3d71c89db 100644
--- a/drivers/media/dvb/frontends/stv0299.h
+++ b/drivers/media/dvb/frontends/stv0299.h
@@ -73,9 +73,6 @@ struct stv0299_config
/* does the inversion require inversion? */
u8 invert:1;
- /* Should the enhanced tuning code be used? */
- u8 enhanced_tuning:1;
-
/* Skip reinitialisation? */
u8 skip_reinit:1;
diff --git a/drivers/media/dvb/frontends/tda1004x.c b/drivers/media/dvb/frontends/tda1004x.c
index 3529c618f828..7968743826fc 100644
--- a/drivers/media/dvb/frontends/tda1004x.c
+++ b/drivers/media/dvb/frontends/tda1004x.c
@@ -420,7 +420,7 @@ static void tda10046_init_plls(struct dvb_frontend* fe)
struct tda1004x_state* state = fe->demodulator_priv;
tda1004x_write_byteI(state, TDA10046H_CONFPLL1, 0xf0);
- tda1004x_write_byteI(state, TDA10046H_CONFPLL2, 10); // PLL M = 10
+ tda1004x_write_byteI(state, TDA10046H_CONFPLL2, 0x0a); // PLL M = 10
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
@@ -597,7 +597,10 @@ static int tda10046_init(struct dvb_frontend* fe)
// Init the tuner PLL
if (state->config->pll_init) {
tda1004x_enable_tuner_i2c(state);
- state->config->pll_init(fe);
+ if (state->config->pll_init(fe)) {
+ printk(KERN_ERR "tda1004x: pll init failed\n");
+ return -EIO;
+ }
tda1004x_disable_tuner_i2c(state);
}
@@ -667,7 +670,10 @@ static int tda1004x_set_fe(struct dvb_frontend* fe,
// set frequency
tda1004x_enable_tuner_i2c(state);
- state->config->pll_set(fe, fe_params);
+ if (state->config->pll_set(fe, fe_params)) {
+ printk(KERN_ERR "tda1004x: pll set failed\n");
+ return -EIO;
+ }
tda1004x_disable_tuner_i2c(state);
// Hardcoded to use auto as much as possible on the TDA10045 as it
@@ -832,6 +838,8 @@ static int tda1004x_set_fe(struct dvb_frontend* fe,
case TDA1004X_DEMOD_TDA10046:
tda1004x_write_mask(state, TDA1004X_AUTO, 0x40, 0x40);
+ msleep(1);
+ tda1004x_write_mask(state, TDA10046H_AGC_CONF, 4, 1);
break;
}
@@ -1129,7 +1137,12 @@ static int tda1004x_sleep(struct dvb_frontend* fe)
if (state->config->pll_sleep != NULL) {
tda1004x_enable_tuner_i2c(state);
state->config->pll_sleep(fe);
- tda1004x_disable_tuner_i2c(state);
+ if (state->config->if_freq != TDA10046_FREQ_052) {
+ /* special hack for Philips EUROPA Based boards:
+ * keep the I2c bridge open for tuner access in analog mode
+ */
+ tda1004x_disable_tuner_i2c(state);
+ }
}
tda1004x_write_mask(state, TDA1004X_CONFC4, 1, 1);
break;
diff --git a/drivers/media/dvb/pluto2/pluto2.c b/drivers/media/dvb/pluto2/pluto2.c
index 85b437bbddcd..bbebd1c4caca 100644
--- a/drivers/media/dvb/pluto2/pluto2.c
+++ b/drivers/media/dvb/pluto2/pluto2.c
@@ -286,15 +286,10 @@ static void pluto_dma_end(struct pluto *pluto, unsigned int nbpackets)
* although one packet has been transfered.
*/
if ((nbpackets == 0) || (nbpackets > TS_DMA_PACKETS)) {
- unsigned int i = 0, valid;
+ unsigned int i = 0;
while (pluto->dma_buf[i] == 0x47)
i += 188;
- valid = i / 188;
- if (nbpackets != valid) {
- dev_err(&pluto->pdev->dev, "nbpackets=%u valid=%u\n",
- nbpackets, valid);
- nbpackets = valid;
- }
+ nbpackets = i / 188;
}
dvb_dmx_swfilter_packets(&pluto->demux, pluto->dma_buf, nbpackets);
diff --git a/drivers/media/dvb/ttpci/av7110.c b/drivers/media/dvb/ttpci/av7110.c
index 22b203f8ff27..87ea52757a21 100644
--- a/drivers/media/dvb/ttpci/av7110.c
+++ b/drivers/media/dvb/ttpci/av7110.c
@@ -1566,7 +1566,7 @@ static u8 alps_bsru6_inittab[] = {
0x0e, 0x23, /* alpha_tmg = 2, beta_tmg = 3 */
0x10, 0x3f, // AGC2 0x3d
0x11, 0x84,
- 0x12, 0xb5, // Lock detect: -64 Carrier freq detect:on
+ 0x12, 0xb9,
0x15, 0xc9, // lock detector threshold
0x16, 0x00,
0x17, 0x00,
@@ -1644,7 +1644,6 @@ static struct stv0299_config alps_bsru6_config = {
.inittab = alps_bsru6_inittab,
.mclk = 88000000UL,
.invert = 1,
- .enhanced_tuning = 0,
.skip_reinit = 0,
.lock_output = STV0229_LOCKOUTPUT_1,
.volt13_op0_op1 = STV0299_VOLT13_OP1,
@@ -1669,7 +1668,7 @@ static u8 alps_bsbe1_inittab[] = {
0x0e, 0x23, /* alpha_tmg = 2, beta_tmg = 3 */
0x10, 0x3f, // AGC2 0x3d
0x11, 0x84,
- 0x12, 0xb5, // Lock detect: -64 Carrier freq detect:on
+ 0x12, 0xb9,
0x15, 0xc9, // lock detector threshold
0x16, 0x00,
0x17, 0x00,
@@ -1721,7 +1720,6 @@ static struct stv0299_config alps_bsbe1_config = {
.inittab = alps_bsbe1_inittab,
.mclk = 88000000UL,
.invert = 1,
- .enhanced_tuning = 0,
.skip_reinit = 0,
.min_delay_ms = 100,
.set_symbol_rate = alps_bsru6_set_symbol_rate,
diff --git a/drivers/media/dvb/ttpci/budget-av.c b/drivers/media/dvb/ttpci/budget-av.c
index 7692cd23f839..aa75dc03a0b3 100644
--- a/drivers/media/dvb/ttpci/budget-av.c
+++ b/drivers/media/dvb/ttpci/budget-av.c
@@ -499,7 +499,7 @@ static u8 typhoon_cinergy1200s_inittab[] = {
0x0e, 0x23, /* alpha_tmg = 2, beta_tmg = 3 */
0x10, 0x3f, // AGC2 0x3d
0x11, 0x84,
- 0x12, 0xb5, // Lock detect: -64 Carrier freq detect:on
+ 0x12, 0xb9,
0x15, 0xc9, // lock detector threshold
0x16, 0x00,
0x17, 0x00,
@@ -531,7 +531,6 @@ static struct stv0299_config typhoon_config = {
.inittab = typhoon_cinergy1200s_inittab,
.mclk = 88000000UL,
.invert = 0,
- .enhanced_tuning = 0,
.skip_reinit = 0,
.lock_output = STV0229_LOCKOUTPUT_1,
.volt13_op0_op1 = STV0299_VOLT13_OP0,
@@ -546,7 +545,6 @@ static struct stv0299_config cinergy_1200s_config = {
.inittab = typhoon_cinergy1200s_inittab,
.mclk = 88000000UL,
.invert = 0,
- .enhanced_tuning = 0,
.skip_reinit = 0,
.lock_output = STV0229_LOCKOUTPUT_0,
.volt13_op0_op1 = STV0299_VOLT13_OP0,
diff --git a/drivers/media/dvb/ttpci/budget-ci.c b/drivers/media/dvb/ttpci/budget-ci.c
index 51c30ba68140..75fb92d60998 100644
--- a/drivers/media/dvb/ttpci/budget-ci.c
+++ b/drivers/media/dvb/ttpci/budget-ci.c
@@ -490,7 +490,7 @@ static u8 alps_bsru6_inittab[] = {
0x0e, 0x23, /* alpha_tmg = 2, beta_tmg = 3 */
0x10, 0x3f, // AGC2 0x3d
0x11, 0x84,
- 0x12, 0xb5, // Lock detect: -64 Carrier freq detect:on
+ 0x12, 0xb9,
0x15, 0xc9, // lock detector threshold
0x16, 0x00,
0x17, 0x00,
@@ -580,7 +580,6 @@ static struct stv0299_config alps_bsru6_config = {
.inittab = alps_bsru6_inittab,
.mclk = 88000000UL,
.invert = 1,
- .enhanced_tuning = 0,
.skip_reinit = 0,
.lock_output = STV0229_LOCKOUTPUT_1,
.volt13_op0_op1 = STV0299_VOLT13_OP1,
@@ -710,7 +709,6 @@ static struct stv0299_config philips_su1278_tt_config = {
.inittab = philips_su1278_tt_inittab,
.mclk = 64000000UL,
.invert = 0,
- .enhanced_tuning = 1,
.skip_reinit = 1,
.lock_output = STV0229_LOCKOUTPUT_1,
.volt13_op0_op1 = STV0299_VOLT13_OP1,
diff --git a/drivers/media/dvb/ttpci/budget-patch.c b/drivers/media/dvb/ttpci/budget-patch.c
index b1f21ef0e3b3..755df81cbc49 100644
--- a/drivers/media/dvb/ttpci/budget-patch.c
+++ b/drivers/media/dvb/ttpci/budget-patch.c
@@ -305,7 +305,7 @@ static u8 alps_bsru6_inittab[] = {
0x0e, 0x23, /* alpha_tmg = 2, beta_tmg = 3 */
0x10, 0x3f, // AGC2 0x3d
0x11, 0x84,
- 0x12, 0xb5, // Lock detect: -64 Carrier freq detect:on
+ 0x12, 0xb9,
0x15, 0xc9, // lock detector threshold
0x16, 0x00,
0x17, 0x00,
@@ -379,7 +379,6 @@ static struct stv0299_config alps_bsru6_config = {
.inittab = alps_bsru6_inittab,
.mclk = 88000000UL,
.invert = 1,
- .enhanced_tuning = 0,
.skip_reinit = 0,
.lock_output = STV0229_LOCKOUTPUT_1,
.volt13_op0_op1 = STV0299_VOLT13_OP1,
diff --git a/drivers/media/dvb/ttpci/budget.c b/drivers/media/dvb/ttpci/budget.c
index 43d6c8268642..4fd8bbc47037 100644
--- a/drivers/media/dvb/ttpci/budget.c
+++ b/drivers/media/dvb/ttpci/budget.c
@@ -226,12 +226,14 @@ static int lnbp21_enable_high_lnb_voltage(struct dvb_frontend* fe, int arg)
return 0;
}
-static void lnbp21_init(struct budget* budget)
+static int lnbp21_init(struct budget* budget)
{
u8 buf = 0x00;
struct i2c_msg msg = { .addr = 0x08, .flags = 0, .buf = &buf, .len = sizeof(buf) };
- i2c_transfer (&budget->i2c_adap, &msg, 1);
+ if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1)
+ return -EIO;
+ return 0;
}
static int alps_bsrv2_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
@@ -273,7 +275,7 @@ static u8 alps_bsru6_inittab[] = {
0x01, 0x15,
0x02, 0x00,
0x03, 0x00,
- 0x04, 0x7d, /* F22FR = 0x7d, F22 = f_VCO / 128 / 0x7d = 22 kHz */
+ 0x04, 0x7d, /* F22FR = 0x7d, F22 = f_VCO / 128 / 0x7d = 22 kHz */
0x05, 0x35, /* I2CT = 0, SCLT = 1, SDAT = 1 */
0x06, 0x40, /* DAC not used, set to high impendance mode */
0x07, 0x00, /* DAC LSB */
@@ -284,7 +286,7 @@ static u8 alps_bsru6_inittab[] = {
0x0e, 0x23, /* alpha_tmg = 2, beta_tmg = 3 */
0x10, 0x3f, // AGC2 0x3d
0x11, 0x84,
- 0x12, 0xb5, // Lock detect: -64 Carrier freq detect:on
+ 0x12, 0xb9,
0x15, 0xc9, // lock detector threshold
0x16, 0x00,
0x17, 0x00,
@@ -358,7 +360,6 @@ static struct stv0299_config alps_bsru6_config = {
.inittab = alps_bsru6_inittab,
.mclk = 88000000UL,
.invert = 1,
- .enhanced_tuning = 0,
.skip_reinit = 0,
.lock_output = STV0229_LOCKOUTPUT_1,
.volt13_op0_op1 = STV0299_VOLT13_OP1,
@@ -367,6 +368,79 @@ static struct stv0299_config alps_bsru6_config = {
.pll_set = alps_bsru6_pll_set,
};
+static u8 alps_bsbe1_inittab[] = {
+ 0x01, 0x15,
+ 0x02, 0x30,
+ 0x03, 0x00,
+ 0x04, 0x7d, /* F22FR = 0x7d, F22 = f_VCO / 128 / 0x7d = 22 kHz */
+ 0x05, 0x35, /* I2CT = 0, SCLT = 1, SDAT = 1 */
+ 0x06, 0x40, /* DAC not used, set to high impendance mode */
+ 0x07, 0x00, /* DAC LSB */
+ 0x08, 0x40, /* DiSEqC off, LNB power on OP2/LOCK pin on */
+ 0x09, 0x00, /* FIFO */
+ 0x0c, 0x51, /* OP1 ctl = Normal, OP1 val = 1 (LNB Power ON) */
+ 0x0d, 0x82, /* DC offset compensation = ON, beta_agc1 = 2 */
+ 0x0e, 0x23, /* alpha_tmg = 2, beta_tmg = 3 */
+ 0x10, 0x3f, // AGC2 0x3d
+ 0x11, 0x84,
+ 0x12, 0xb9,
+ 0x15, 0xc9, // lock detector threshold
+ 0x16, 0x00,
+ 0x17, 0x00,
+ 0x18, 0x00,
+ 0x19, 0x00,
+ 0x1a, 0x00,
+ 0x1f, 0x50,
+ 0x20, 0x00,
+ 0x21, 0x00,
+ 0x22, 0x00,
+ 0x23, 0x00,
+ 0x28, 0x00, // out imp: normal out type: parallel FEC mode:0
+ 0x29, 0x1e, // 1/2 threshold
+ 0x2a, 0x14, // 2/3 threshold
+ 0x2b, 0x0f, // 3/4 threshold
+ 0x2c, 0x09, // 5/6 threshold
+ 0x2d, 0x05, // 7/8 threshold
+ 0x2e, 0x01,
+ 0x31, 0x1f, // test all FECs
+ 0x32, 0x19, // viterbi and synchro search
+ 0x33, 0xfc, // rs control
+ 0x34, 0x93, // error control
+ 0x0f, 0x92, // 0x80 = inverse AGC
+ 0xff, 0xff
+};
+
+static int alps_bsbe1_pll_set(struct dvb_frontend* fe, struct i2c_adapter *i2c, struct dvb_frontend_parameters* params)
+{
+ int ret;
+ u8 data[4];
+ u32 div;
+ struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
+
+ if ((params->frequency < 950000) || (params->frequency > 2150000))
+ return -EINVAL;
+
+ div = (params->frequency + (125 - 1)) / 125; // round correctly
+ data[0] = (div >> 8) & 0x7f;
+ data[1] = div & 0xff;
+ data[2] = 0x80 | ((div & 0x18000) >> 10) | 4;
+ data[3] = (params->frequency > 1530000) ? 0xE0 : 0xE4;
+
+ ret = i2c_transfer(i2c, &msg, 1);
+ return (ret != 1) ? -EIO : 0;
+}
+
+static struct stv0299_config alps_bsbe1_config = {
+ .demod_address = 0x68,
+ .inittab = alps_bsbe1_inittab,
+ .mclk = 88000000UL,
+ .invert = 1,
+ .skip_reinit = 0,
+ .min_delay_ms = 100,
+ .set_symbol_rate = alps_bsru6_set_symbol_rate,
+ .pll_set = alps_bsbe1_pll_set,
+};
+
static int alps_tdbe2_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
{
struct budget* budget = (struct budget*) fe->dvb->priv;
@@ -500,6 +574,19 @@ static u8 read_pwm(struct budget* budget)
static void frontend_init(struct budget *budget)
{
switch(budget->dev->pci->subsystem_device) {
+ case 0x1017:
+ // try the ALPS BSBE1 now
+ budget->dvb_frontend = stv0299_attach(&alps_bsbe1_config, &budget->i2c_adap);
+ 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;
+ if (lnbp21_init(budget)) {
+ printk("%s: No LNBP21 found!\n", __FUNCTION__);
+ goto error_out;
+ }
+ }
+
+ break;
case 0x1003: // Hauppauge/TT Nova budget (stv0299/ALPS BSRU6(tsa5059) OR ves1893/ALPS BSRV2(sp5659))
case 0x1013:
// try the ALPS BSRV2 first of all
@@ -554,7 +641,10 @@ 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;
- lnbp21_init(budget);
+ if (lnbp21_init(budget)) {
+ printk("%s: No LNBP21 found!\n", __FUNCTION__);
+ goto error_out;
+ }
break;
}
}
@@ -566,13 +656,17 @@ static void frontend_init(struct budget *budget)
budget->dev->pci->subsystem_vendor,
budget->dev->pci->subsystem_device);
} else {
- if (dvb_register_frontend(&budget->dvb_adapter, budget->dvb_frontend)) {
- printk("budget: Frontend registration failed!\n");
- if (budget->dvb_frontend->ops->release)
- budget->dvb_frontend->ops->release(budget->dvb_frontend);
- budget->dvb_frontend = NULL;
- }
+ if (dvb_register_frontend(&budget->dvb_adapter, budget->dvb_frontend))
+ goto error_out;
}
+ return;
+
+error_out:
+ printk("budget: Frontend registration failed!\n");
+ if (budget->dvb_frontend->ops->release)
+ budget->dvb_frontend->ops->release(budget->dvb_frontend);
+ budget->dvb_frontend = NULL;
+ return;
}
static int budget_attach (struct saa7146_dev* dev, struct saa7146_pci_extension_data *info)
@@ -618,6 +712,7 @@ static int budget_detach (struct saa7146_dev* dev)
static struct saa7146_extension budget_extension;
+MAKE_BUDGET_INFO(ttbs2, "TT-Budget/WinTV-NOVA-S PCI (rev AL/alps bsbe1 lnbp21 frontend)", BUDGET_TT);
MAKE_BUDGET_INFO(ttbs, "TT-Budget/WinTV-NOVA-S PCI", BUDGET_TT);
MAKE_BUDGET_INFO(ttbc, "TT-Budget/WinTV-NOVA-C PCI", BUDGET_TT);
MAKE_BUDGET_INFO(ttbt, "TT-Budget/WinTV-NOVA-T PCI", BUDGET_TT);
@@ -630,6 +725,7 @@ static struct pci_device_id pci_tbl[] = {
MAKE_EXTENSION_PCI(ttbc, 0x13c2, 0x1004),
MAKE_EXTENSION_PCI(ttbt, 0x13c2, 0x1005),
MAKE_EXTENSION_PCI(satel, 0x13c2, 0x1013),
+ MAKE_EXTENSION_PCI(ttbs2, 0x13c2, 0x1017),
MAKE_EXTENSION_PCI(ttbs, 0x13c2, 0x1016),
MAKE_EXTENSION_PCI(fsacs1,0x1131, 0x4f60),
MAKE_EXTENSION_PCI(fsacs0,0x1131, 0x4f61),
diff --git a/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c b/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c
index d200ab0ad9e7..fd53d6010502 100644
--- a/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c
+++ b/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c
@@ -1198,7 +1198,7 @@ static u8 alps_bsbe1_inittab[] = {
0x0e, 0x23, /* alpha_tmg = 2, beta_tmg = 3 */
0x10, 0x3f, // AGC2 0x3d
0x11, 0x84,
- 0x12, 0xb5, // Lock detect: -64 Carrier freq detect:on
+ 0x12, 0xb9,
0x15, 0xc9, // lock detector threshold
0x16, 0x00,
0x17, 0x00,
@@ -1240,7 +1240,7 @@ static u8 alps_bsru6_inittab[] = {
0x0e, 0x23, /* alpha_tmg = 2, beta_tmg = 3 */
0x10, 0x3f, // AGC2 0x3d
0x11, 0x84,
- 0x12, 0xb5, // Lock detect: -64 Carrier freq detect:on
+ 0x12, 0xb9,
0x15, 0xc9, // lock detector threshold
0x16, 0x00,
0x17, 0x00,
@@ -1335,7 +1335,6 @@ static struct stv0299_config alps_stv0299_config = {
.inittab = alps_bsru6_inittab,
.mclk = 88000000UL,
.invert = 1,
- .enhanced_tuning = 0,
.skip_reinit = 0,
.lock_output = STV0229_LOCKOUTPUT_1,
.volt13_op0_op1 = STV0299_VOLT13_OP1,