diff options
author | Alex Woods <devnull@localhost> | 2003-12-05 00:11:36 +0000 |
---|---|---|
committer | Alex Woods <devnull@localhost> | 2003-12-05 00:11:36 +0000 |
commit | 32d1eb26f468bf4d4104f8099f967687d5d1df22 (patch) | |
tree | 1d764a1298a360e63a14fe9f1497480713855331 /linux/drivers/media/dvb/ttusb-dec/ttusb_dec.c | |
parent | 2b17bc52d2eacffa537f7cbbea626e5a48c2d054 (diff) | |
download | mediapointer-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.c | 269 |
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) |