summaryrefslogtreecommitdiffstats
path: root/drivers/media/dvb/bt8xx
diff options
context:
space:
mode:
authorPaul Mackerras <paulus@samba.org>2005-11-10 11:06:04 +1100
committerPaul Mackerras <paulus@samba.org>2005-11-10 11:06:04 +1100
commit31e7f1ff3c5d39a70da85f7d81a1ab1f4e64fa97 (patch)
treea6cb8f14b1182e5dce55d13e52c1182a8c7e0402 /drivers/media/dvb/bt8xx
parentfca5dcd4835ed09bb1a48a355344aff7a25c76e0 (diff)
parent6730c3c14421b7c924d06e31bb66e0adad225547 (diff)
Merge ../linux-2.6
Diffstat (limited to 'drivers/media/dvb/bt8xx')
-rw-r--r--drivers/media/dvb/bt8xx/Kconfig4
-rw-r--r--drivers/media/dvb/bt8xx/dst.c136
-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
6 files changed, 272 insertions, 111 deletions
diff --git a/drivers/media/dvb/bt8xx/Kconfig b/drivers/media/dvb/bt8xx/Kconfig
index 1e85d16491b..2337b41714e 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 b3c9d7327ac..8977c7a313d 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;
}
/*
diff --git a/drivers/media/dvb/bt8xx/dst_ca.c b/drivers/media/dvb/bt8xx/dst_ca.c
index 6776a592045..e6541aff399 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 3281a6ca368..81557f38fe3 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 c5c7672cd53..2e398090cf6 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 9ec8e5bd6c1..cf035a80361 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;