summaryrefslogtreecommitdiff
path: root/linux/drivers/media/dvb/ttusb-dec/ttusb_dec.c
diff options
context:
space:
mode:
authorAlex Woods <devnull@localhost>2003-12-05 00:11:36 +0000
committerAlex Woods <devnull@localhost>2003-12-05 00:11:36 +0000
commit32d1eb26f468bf4d4104f8099f967687d5d1df22 (patch)
tree1d764a1298a360e63a14fe9f1497480713855331 /linux/drivers/media/dvb/ttusb-dec/ttusb_dec.c
parent2b17bc52d2eacffa537f7cbbea626e5a48c2d054 (diff)
downloadmediapointer-dvb-s2-32d1eb26f468bf4d4104f8099f967687d5d1df22.tar.gz
mediapointer-dvb-s2-32d1eb26f468bf4d4104f8099f967687d5d1df22.tar.bz2
Prepare driver for DEC3000-s support.
Add a DEC3000-s frontend with some of FE_SET_FRONTEND implemented (thanks to Pedro GutiƩrrez for USB logs of the DEC3000-s). Prepare bootcode loader for easy transition to firmware loader for 2.6 kernels. Get Makefiles to pull in DEC3000-s bootcode. Turn echo off for ugly bootcode header hacks in 2.4 build Makefile. Note: At this stage, connecting a DEC3000-s will probably just make it reboot over and over.
Diffstat (limited to 'linux/drivers/media/dvb/ttusb-dec/ttusb_dec.c')
-rw-r--r--linux/drivers/media/dvb/ttusb-dec/ttusb_dec.c269
1 files changed, 223 insertions, 46 deletions
diff --git a/linux/drivers/media/dvb/ttusb-dec/ttusb_dec.c b/linux/drivers/media/dvb/ttusb-dec/ttusb_dec.c
index 57fbc2d1f..1cc610c83 100644
--- a/linux/drivers/media/dvb/ttusb-dec/ttusb_dec.c
+++ b/linux/drivers/media/dvb/ttusb-dec/ttusb_dec.c
@@ -35,7 +35,6 @@
#include "dvb_filter.h"
#include "dvb_frontend.h"
#include "dvb_net.h"
-#include "dvb_usb_compat.h"
static int debug = 0;
@@ -56,14 +55,24 @@ static int debug = 0;
#define MAX_AV_PES_LENGTH 6144
+enum ttusb_model {
+ TTUSB_DEC2000T,
+ TTUSB_DEC3000S
+};
+
struct ttusb_dec {
+ enum ttusb_model model;
+ char *model_name;
+
/* DVB bits */
- struct dvb_adapter *adapter;
- struct dmxdev dmxdev;
- struct dvb_demux demux;
- struct dmx_frontend frontend;
- struct dvb_i2c_bus i2c_bus;
- struct dvb_net dvb_net;
+ struct dvb_adapter *adapter;
+ struct dmxdev dmxdev;
+ struct dvb_demux demux;
+ struct dmx_frontend frontend;
+ struct dvb_i2c_bus i2c_bus;
+ struct dvb_net dvb_net;
+ struct dvb_frontend_info *frontend_info;
+ int (*frontend_ioctl) (struct dvb_frontend *, unsigned int, void *);
u16 pid[DMX_PES_OTHER];
@@ -105,8 +114,8 @@ struct urb_frame {
struct list_head urb_frame_list;
};
-static struct dvb_frontend_info dec2000_frontend_info = {
- .name = "TechnoTrend/Hauppauge DEC-2000-t Frontend",
+static struct dvb_frontend_info dec2000t_frontend_info = {
+ .name = "TechnoTrend/Hauppauge DEC2000-t Frontend",
.type = FE_OFDM,
.frequency_min = 51000000,
.frequency_max = 858000000,
@@ -118,6 +127,19 @@ static struct dvb_frontend_info dec2000_frontend_info = {
FE_CAN_HIERARCHY_AUTO,
};
+static struct dvb_frontend_info dec3000s_frontend_info = {
+ .name = "TechnoTrend/Hauppauge DEC3000-s Frontend",
+ .type = FE_QPSK,
+ .frequency_min = 950000,
+ .frequency_max = 2150000,
+ .frequency_stepsize = 125,
+ .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
+ FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
+ FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
+ FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO |
+ FE_CAN_HIERARCHY_AUTO,
+};
+
static int ttusb_dec_send_command(struct ttusb_dec *dec, const u8 command,
int param_length, const u8 params[],
int *result_length, u8 cmd_result[])
@@ -449,7 +471,11 @@ static void ttusb_dec_process_urb(struct urb *urb, struct pt_regs *ptregs)
int i;
for (i = 0; i < FRAMES_PER_ISO_BUF; i++) {
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+ struct iso_packet_descriptor *d;
+#else
struct usb_iso_packet_descriptor *d;
+#endif
u8 *b;
int length;
struct urb_frame *frame;
@@ -484,7 +510,7 @@ static void ttusb_dec_process_urb(struct urb *urb, struct pt_regs *ptregs)
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
if (dec->iso_stream_count)
- usb_submit_urb(urb URB_MEM_FLAG);
+ usb_submit_urb(urb, GFP_ATOMIC);
#endif
}
@@ -502,9 +528,11 @@ static void ttusb_dec_setup_urbs(struct ttusb_dec *dec)
urb->context = dec;
urb->complete = ttusb_dec_process_urb;
urb->pipe = dec->stream_pipe;
- urb->transfer_flags = URB_ISO_ASAP;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+ urb->transfer_flags = URB_ISO_ASAP;
urb->interval = 1;
+#else
+ urb->transfer_flags = USB_ISO_ASAP;
#endif
urb->number_of_packets = FRAMES_PER_ISO_BUF;
urb->transfer_buffer_length = ISO_FRAME_SIZE *
@@ -572,8 +600,12 @@ static int ttusb_dec_start_iso_xfer(struct ttusb_dec *dec)
ttusb_dec_setup_urbs(dec);
for (i = 0; i < ISO_BUF_COUNT; i++) {
- if ((result = usb_submit_urb(dec->iso_urb[i]
- URB_MEM_FLAG))) {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+ if ((result = usb_submit_urb(dec->iso_urb[i],
+ GFP_ATOMIC))) {
+#else
+ if ((result = usb_submit_urb(dec->iso_urb[i]))) {
+#endif
printk("%s: failed urb submission %d: "
"error %d\n", __FUNCTION__, i, result);
@@ -729,7 +761,11 @@ static int ttusb_dec_alloc_iso_urbs(struct ttusb_dec *dec)
for (i = 0; i < ISO_BUF_COUNT; i++) {
struct urb *urb;
- if (!(urb = usb_alloc_urb(FRAMES_PER_ISO_BUF URB_MEM_FLAG))) {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+ if (!(urb = usb_alloc_urb(FRAMES_PER_ISO_BUF, GFP_ATOMIC))) {
+#else
+ if (!(urb = usb_alloc_urb(FRAMES_PER_ISO_BUF))) {
+#endif
ttusb_dec_free_iso_urbs(dec);
return -ENOMEM;
}
@@ -781,20 +817,42 @@ static void ttusb_dec_init_usb(struct ttusb_dec *dec)
ttusb_dec_alloc_iso_urbs(dec);
}
-#include "dsp_dec2000.h"
+#include "dsp_dec2000t.h"
+#include "dsp_dec3000s.h"
static int ttusb_dec_boot_dsp(struct ttusb_dec *dec)
{
int i, j, actual_len, result, size, trans_count;
- u8 b0[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1b, 0xc8, 0x61,
+ u8 b0[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00 };
u8 b1[] = { 0x61 };
u8 b[ARM_PACKET_SIZE];
- u32 dsp_length = htonl(sizeof(dsp_dec2000));
+ u8 *firmware = NULL;
+ size_t firmware_size = 0;
+ u32 firmware_csum = 0;
+ u32 firmware_size_nl;
+ u32 firmware_csum_nl;
dprintk("%s\n", __FUNCTION__);
- memcpy(b0, &dsp_length, 4);
+ switch (dec->model) {
+ case TTUSB_DEC2000T:
+ firmware = &dsp_dec2000t[0];
+ firmware_size = sizeof(dsp_dec2000t);
+ firmware_csum = 0x1bc86100;
+ break;
+
+ case TTUSB_DEC3000S:
+ firmware = &dsp_dec3000s[0];
+ firmware_size = sizeof(dsp_dec3000s);
+ firmware_csum = 0x00000000;
+ break;
+ }
+
+ firmware_size_nl = htonl(firmware_size);
+ memcpy(b0, &firmware_size_nl, 4);
+ firmware_csum_nl = htonl(firmware_csum);
+ memcpy(&b0[6], &firmware_csum_nl, 4);
result = ttusb_dec_send_command(dec, 0x41, sizeof(b0), b0, NULL, NULL);
@@ -804,8 +862,8 @@ static int ttusb_dec_boot_dsp(struct ttusb_dec *dec)
trans_count = 0;
j = 0;
- for (i = 0; i < sizeof(dsp_dec2000); i += COMMAND_PACKET_SIZE) {
- size = sizeof(dsp_dec2000) - i;
+ for (i = 0; i < firmware_size; i += COMMAND_PACKET_SIZE) {
+ size = firmware_size - i;
if (size > COMMAND_PACKET_SIZE)
size = COMMAND_PACKET_SIZE;
@@ -813,7 +871,7 @@ static int ttusb_dec_boot_dsp(struct ttusb_dec *dec)
b[j + 1] = trans_count++;
b[j + 2] = 0xf0;
b[j + 3] = size;
- memcpy(&b[j + 4], &dsp_dec2000[i], size);
+ memcpy(&b[j + 4], &firmware[i], size);
j += COMMAND_PACKET_SIZE + 4;
@@ -855,7 +913,7 @@ static int ttusb_dec_init_dvb(struct ttusb_dec *dec)
dprintk("%s\n", __FUNCTION__);
- if ((result = dvb_register_adapter(&dec->adapter, "dec2000")) < 0) {
+ if ((result = dvb_register_adapter(&dec->adapter, dec->model_name)) < 0) {
printk("%s: dvb_register_adapter failed: error %d\n",
__FUNCTION__, result);
@@ -966,7 +1024,7 @@ static void ttusb_dec_exit_tasklet(struct ttusb_dec *dec)
}
}
-static int dec2000_frontend_ioctl(struct dvb_frontend *fe, unsigned int cmd,
+static int ttusb_dec_2000t_frontend_ioctl(struct dvb_frontend *fe, unsigned int cmd,
void *arg)
{
struct ttusb_dec *dec = fe->data;
@@ -977,7 +1035,7 @@ static int dec2000_frontend_ioctl(struct dvb_frontend *fe, unsigned int cmd,
case FE_GET_INFO:
dprintk("%s: FE_GET_INFO\n", __FUNCTION__);
- memcpy(arg, &dec2000_frontend_info,
+ memcpy(arg, dec->frontend_info,
sizeof (struct dvb_frontend_info));
break;
@@ -1032,8 +1090,112 @@ static int dec2000_frontend_ioctl(struct dvb_frontend *fe, unsigned int cmd,
dprintk(" inversion->%d\n", p->inversion);
freq = htonl(p->frequency / 1000);
- memcpy(&b[4], &freq, sizeof (int));
- ttusb_dec_send_command(dec, 0x71, 20, b, NULL, NULL);
+ memcpy(&b[4], &freq, sizeof (u32));
+ ttusb_dec_send_command(dec, 0x71, sizeof(b), b, NULL, NULL);
+
+ break;
+ }
+
+ case FE_GET_FRONTEND:
+ dprintk("%s: FE_GET_FRONTEND\n", __FUNCTION__);
+ break;
+
+ case FE_SLEEP:
+ dprintk("%s: FE_SLEEP\n", __FUNCTION__);
+ return -ENOSYS;
+ break;
+
+ case FE_INIT:
+ dprintk("%s: FE_INIT\n", __FUNCTION__);
+ break;
+
+ case FE_RESET:
+ dprintk("%s: FE_RESET\n", __FUNCTION__);
+ break;
+
+ default:
+ dprintk("%s: unknown IOCTL (0x%X)\n", __FUNCTION__, cmd);
+ return -EINVAL;
+
+ }
+
+ return 0;
+}
+
+static int ttusb_dec_3000s_frontend_ioctl(struct dvb_frontend *fe, unsigned int cmd,
+ void *arg)
+{
+ struct ttusb_dec *dec = fe->data;
+
+ dprintk("%s\n", __FUNCTION__);
+
+ switch (cmd) {
+
+ case FE_GET_INFO:
+ dprintk("%s: FE_GET_INFO\n", __FUNCTION__);
+ memcpy(arg, dec->frontend_info,
+ sizeof (struct dvb_frontend_info));
+ break;
+
+ case FE_READ_STATUS: {
+ fe_status_t *status = (fe_status_t *)arg;
+ dprintk("%s: FE_READ_STATUS\n", __FUNCTION__);
+ *status = FE_HAS_SIGNAL | FE_HAS_VITERBI |
+ FE_HAS_SYNC | FE_HAS_CARRIER | FE_HAS_LOCK;
+ break;
+ }
+
+ case FE_READ_BER: {
+ u32 *ber = (u32 *)arg;
+ dprintk("%s: FE_READ_BER\n", __FUNCTION__);
+ *ber = 0;
+ return -ENOSYS;
+ break;
+ }
+
+ case FE_READ_SIGNAL_STRENGTH: {
+ dprintk("%s: FE_READ_SIGNAL_STRENGTH\n", __FUNCTION__);
+ *(s32 *)arg = 0xFF;
+ return -ENOSYS;
+ break;
+ }
+
+ case FE_READ_SNR:
+ dprintk("%s: FE_READ_SNR\n", __FUNCTION__);
+ *(s32 *)arg = 0;
+ return -ENOSYS;
+ break;
+
+ case FE_READ_UNCORRECTED_BLOCKS:
+ dprintk("%s: FE_READ_UNCORRECTED_BLOCKS\n", __FUNCTION__);
+ *(u32 *)arg = 0;
+ return -ENOSYS;
+ break;
+
+ case FE_SET_FRONTEND:{
+ struct dvb_frontend_parameters *p =
+ (struct dvb_frontend_parameters *)arg;
+ u8 b[] = { 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
+ 0x00 };
+ u32 freq;
+ u32 sym_rate;
+
+ dprintk("%s: FE_SET_FRONTEND\n", __FUNCTION__);
+
+ dprintk(" frequency->%d\n", p->frequency);
+ dprintk(" symbol_rate->%d\n",
+ p->u.qam.symbol_rate);
+ dprintk(" inversion->%d\n", p->inversion);
+
+ freq = htonl(p->frequency / 1000);
+ memcpy(&b[4], &freq, sizeof(u32));
+ sym_rate = htonl(p->u.qam.symbol_rate);
+ memcpy(&b[12], &sym_rate, sizeof(u32));
+ ttusb_dec_send_command(dec, 0x71, sizeof(b), b, NULL, NULL);
break;
}
@@ -1067,13 +1229,26 @@ static int dec2000_frontend_ioctl(struct dvb_frontend *fe, unsigned int cmd,
static void ttusb_dec_init_frontend(struct ttusb_dec *dec)
{
dec->i2c_bus.adapter = dec->adapter;
- dvb_register_frontend(dec2000_frontend_ioctl, &dec->i2c_bus,
- (void *)dec, &dec2000_frontend_info);
+
+ switch (dec->model) {
+ case TTUSB_DEC2000T:
+ dec->frontend_info = &dec2000t_frontend_info;
+ dec->frontend_ioctl = ttusb_dec_2000t_frontend_ioctl;
+ break;
+
+ case TTUSB_DEC3000S:
+ dec->frontend_info = &dec3000s_frontend_info;
+ dec->frontend_ioctl = ttusb_dec_3000s_frontend_ioctl;
+ break;
+ }
+
+ dvb_register_frontend(dec->frontend_ioctl, &dec->i2c_bus, (void *)dec,
+ dec->frontend_info);
}
static void ttusb_dec_exit_frontend(struct ttusb_dec *dec)
{
- dvb_unregister_frontend(dec2000_frontend_ioctl, &dec->i2c_bus);
+ dvb_unregister_frontend(dec->frontend_ioctl, &dec->i2c_bus);
}
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
@@ -1091,20 +1266,6 @@ static void *ttusb_dec_probe(struct usb_device *udev, unsigned int ifnum,
printk("%s: couldn't allocate memory.\n", __FUNCTION__);
return NULL;
}
-
- memset(dec, 0, sizeof(struct ttusb_dec));
-
- dec->udev = udev;
-
- ttusb_dec_init_usb(dec);
- ttusb_dec_init_stb(dec);
- ttusb_dec_init_dvb(dec);
- ttusb_dec_init_frontend(dec);
- ttusb_dec_init_v_pes(dec);
- ttusb_dec_init_tasklet(dec);
-
- return (void *)dec;
-}
#else
static int ttusb_dec_probe(struct usb_interface *intf,
const struct usb_device_id *id)
@@ -1120,9 +1281,22 @@ static int ttusb_dec_probe(struct usb_interface *intf,
printk("%s: couldn't allocate memory.\n", __FUNCTION__);
return -ENOMEM;
}
+#endif
memset(dec, 0, sizeof(struct ttusb_dec));
+ switch (id->idProduct) {
+ case 0x1007:
+ dec->model = TTUSB_DEC3000S;
+ dec->model_name = "DEC3000-s";
+ break;
+
+ case 0x1008:
+ dec->model = TTUSB_DEC2000T;
+ dec->model_name = "DEC2000-t";
+ break;
+ }
+
dec->udev = udev;
ttusb_dec_init_usb(dec);
@@ -1132,12 +1306,15 @@ static int ttusb_dec_probe(struct usb_interface *intf,
ttusb_dec_init_v_pes(dec);
ttusb_dec_init_tasklet(dec);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+ return (void *)dec;
+#else
usb_set_intfdata(intf, (void *)dec);
ttusb_dec_set_streaming_interface(dec);
return 0;
-}
#endif
+}
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
static void ttusb_dec_disconnect(struct usb_device *udev, void *data)
@@ -1162,7 +1339,7 @@ static void ttusb_dec_disconnect(struct usb_interface *intf)
}
static struct usb_device_id ttusb_dec_table[] = {
- {USB_DEVICE(0x0b48, 0x1006)}, /* Unconfirmed */
+ /*{USB_DEVICE(0x0b48, 0x1006)}, Unconfirmed */
{USB_DEVICE(0x0b48, 0x1007)}, /* DEC3000-s */
{USB_DEVICE(0x0b48, 0x1008)}, /* DEC2000-t */
{}
@@ -1172,7 +1349,7 @@ static struct usb_driver ttusb_dec_driver = {
.name = DRIVER_NAME,
.probe = ttusb_dec_probe,
.disconnect = ttusb_dec_disconnect,
- .id_table = ttusb_dec_table,
+ .id_table = ttusb_dec_table,
};
static int __init ttusb_dec_init(void)