vserver 1.9.5.x5
[linux-2.6.git] / drivers / media / dvb / ttusb-dec / ttusb_dec.c
index cc48a65..f85069f 100644 (file)
 #include <asm/semaphore.h>
 #include <linux/list.h>
 #include <linux/module.h>
+#include <linux/moduleparam.h>
 #include <linux/pci.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
 #include <linux/usb.h>
+#include <linux/version.h>
 #include <linux/interrupt.h>
 #include <linux/firmware.h>
-#if defined(CONFIG_CRC32) || defined(CONFIG_CRC32_MODULE)
 #include <linux/crc32.h>
-#else
-#warning "CRC checking of firmware not available"
-#endif
 #include <linux/init.h>
 
 #include "dmxdev.h"
 #include "dvb_demux.h"
-#include "dvb_i2c.h"
 #include "dvb_filter.h"
 #include "dvb_frontend.h"
 #include "dvb_net.h"
+#include "ttusbdecfe.h"
 
-static int debug = 0;
-static int output_pva = 0;
+static int debug;
+static int output_pva;
+
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
+module_param(output_pva, int, 0444);
+MODULE_PARM_DESC(output_pva, "Output PVA from dvr device (default:off)");
 
 #define dprintk        if (debug) printk
 
@@ -63,9 +66,6 @@ static int output_pva = 0;
 
 #define        MAX_PVA_LENGTH          6144
 
-#define LOF_HI                 10600000
-#define LOF_LO                 9750000
-
 enum ttusb_dec_model {
        TTUSB_DEC2000T,
        TTUSB_DEC2540T,
@@ -95,14 +95,10 @@ struct ttusb_dec {
        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 *);
+       struct dvb_frontend*            fe;
 
        u16                     pid[DMX_PES_OTHER];
-       int                     hi_band;
-       int                     voltage;
 
        /* USB bits */
        struct usb_device       *udev;
@@ -161,32 +157,6 @@ struct filter_info {
        struct list_head        filter_info_list;
 };
 
-static struct dvb_frontend_info dec2000t_frontend_info = {
-       .name                   = "TechnoTrend/Hauppauge DEC2000-t Frontend",
-       .type                   = FE_OFDM,
-       .frequency_min          = 51000000,
-       .frequency_max          = 858000000,
-       .frequency_stepsize     = 62500,
-       .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 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 void ttusb_dec_set_model(struct ttusb_dec *dec,
                                enum ttusb_dec_model model);
 
@@ -786,7 +756,7 @@ static void ttusb_dec_stop_iso_xfer(struct ttusb_dec *dec)
 
        if (!dec->iso_stream_count) {
                for (i = 0; i < ISO_BUF_COUNT; i++)
-                       usb_unlink_urb(dec->iso_urb[i]);
+                       usb_kill_urb(dec->iso_urb[i]);
        }
 
        up(&dec->iso_sem);
@@ -851,7 +821,7 @@ static int ttusb_dec_start_iso_xfer(struct ttusb_dec *dec)
                                       "error %d\n", __FUNCTION__, i, result);
 
                                while (i) {
-                                       usb_unlink_urb(dec->iso_urb[i - 1]);
+                                       usb_kill_urb(dec->iso_urb[i - 1]);
                                        i--;
                                }
 
@@ -1100,7 +1070,7 @@ static int ttusb_dec_alloc_iso_urbs(struct ttusb_dec *dec)
                                               &dec->iso_dma_handle);
 
        memset(dec->iso_buffer, 0,
-              sizeof(ISO_FRAME_SIZE * (FRAMES_PER_ISO_BUF * ISO_BUF_COUNT)));
+              ISO_FRAME_SIZE * (FRAMES_PER_ISO_BUF * ISO_BUF_COUNT));
 
        for (i = 0; i < ISO_BUF_COUNT; i++) {
                struct urb *urb;
@@ -1120,7 +1090,7 @@ static int ttusb_dec_alloc_iso_urbs(struct ttusb_dec *dec)
 
 static void ttusb_dec_init_tasklet(struct ttusb_dec *dec)
 {
-       dec->urb_frame_list_lock = SPIN_LOCK_UNLOCKED;
+       spin_lock_init(&dec->urb_frame_list_lock);
        INIT_LIST_HEAD(&dec->urb_frame_list);
        tasklet_init(&dec->urb_tasklet, ttusb_dec_process_urb_frame_list,
                     (unsigned long)dec);
@@ -1165,10 +1135,9 @@ static int ttusb_dec_boot_dsp(struct ttusb_dec *dec)
        u16 firmware_csum = 0;
        u16 firmware_csum_ns;
        u32 firmware_size_nl;
-#if defined(CONFIG_CRC32) || defined(CONFIG_CRC32_MODULE)
        u32 crc32_csum, crc32_check, tmp;
-#endif
        const struct firmware *fw_entry = NULL;
+
        dprintk("%s\n", __FUNCTION__);
 
        if (request_firmware(&fw_entry, dec->firmware_name, &dec->udev->dev)) {
@@ -1189,7 +1158,6 @@ static int ttusb_dec_boot_dsp(struct ttusb_dec *dec)
        /* a 32 bit checksum over the first 56 bytes of the DSP Code is stored
           at offset 56 of file, so use it to check if the firmware file is
           valid. */
-#if defined(CONFIG_CRC32) || defined(CONFIG_CRC32_MODULE)
        crc32_csum = crc32(~0L, firmware, 56) ^ ~0L;
        memcpy(&tmp, &firmware[56], 4);
        crc32_check = htonl(tmp);
@@ -1199,7 +1167,6 @@ static int ttusb_dec_boot_dsp(struct ttusb_dec *dec)
                        __FUNCTION__, crc32_csum, crc32_check);
                return -1;
        }
-#endif
        memcpy(idstring, &firmware[36], 20);
        idstring[20] = '\0';
        printk(KERN_INFO "ttusb_dec: found DSP code \"%s\".\n", idstring);
@@ -1288,6 +1255,7 @@ static int ttusb_dec_init_stb(struct ttusb_dec *dec)
                                ttusb_dec_set_model(dec, TTUSB_DEC3000S);
                                break;
                        case 0x00070009:
+                       case 0x00070013:
                                ttusb_dec_set_model(dec, TTUSB_DEC2000T);
                                break;
                        case 0x00070011:
@@ -1398,6 +1366,7 @@ static void ttusb_dec_exit_dvb(struct ttusb_dec *dec)
        dec->demux.dmx.remove_frontend(&dec->demux.dmx, &dec->frontend);
        dvb_dmxdev_release(&dec->dmxdev);
        dvb_dmx_release(&dec->demux);
+       if (dec->fe) dvb_unregister_frontend(dec->fe);
        dvb_unregister_adapter(dec->adapter);
 }
 
@@ -1410,7 +1379,7 @@ static void ttusb_dec_exit_usb(struct ttusb_dec *dec)
        dec->iso_stream_count = 0;
 
        for (i = 0; i < ISO_BUF_COUNT; i++)
-               usb_unlink_urb(dec->iso_urb[i]);
+               usb_kill_urb(dec->iso_urb[i]);
 
        ttusb_dec_free_iso_urbs(dec);
 }
@@ -1429,261 +1398,10 @@ static void ttusb_dec_exit_tasklet(struct ttusb_dec *dec)
        }
 }
 
-static int ttusb_dec_2000t_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, 0x03,
-                          0x00, 0x00, 0x00, 0x00,
-                          0x00, 0x00, 0x00, 0x01,
-                          0x00, 0x00, 0x00, 0xff,
-                          0x00, 0x00, 0x00, 0xff };
-                       u32 freq;
-
-                       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));
-                       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;
-
-       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, 0x00,
-                          0x00, 0x00, 0x00, 0x00,
-                          0x00, 0x00, 0x00, 0x00 };
-                       u32 freq;
-                       u32 sym_rate;
-                       u32 band;
-               u32 lnb_voltage;
-
-                       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 +
-                      (dec->hi_band ? LOF_HI : LOF_LO));
-                       memcpy(&b[4], &freq, sizeof(u32));
-                       sym_rate = htonl(p->u.qam.symbol_rate);
-                       memcpy(&b[12], &sym_rate, sizeof(u32));
-                       band = htonl(dec->hi_band ? LOF_HI : LOF_LO);
-                       memcpy(&b[24], &band, sizeof(u32));
-               lnb_voltage = htonl(dec->voltage);
-               memcpy(&b[28], &lnb_voltage, 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_DISEQC_SEND_MASTER_CMD:
-               dprintk("%s: FE_DISEQC_SEND_MASTER_CMD\n", __FUNCTION__);
-               break;
-
-       case FE_DISEQC_SEND_BURST:
-               dprintk("%s: FE_DISEQC_SEND_BURST\n", __FUNCTION__);
-               break;
-
-       case FE_SET_TONE: {
-                       fe_sec_tone_mode_t tone = (fe_sec_tone_mode_t)arg;
-                       dprintk("%s: FE_SET_TONE\n", __FUNCTION__);
-                       dec->hi_band = (SEC_TONE_ON == tone);
-                       break;
-               }
-
-       case FE_SET_VOLTAGE:
-               dprintk("%s: FE_SET_VOLTAGE\n", __FUNCTION__);
-               switch ((fe_sec_voltage_t) arg) {
-               case SEC_VOLTAGE_13:
-                       dec->voltage = 13;
-                       break;
-               case SEC_VOLTAGE_18:
-                       dec->voltage = 18;
-                       break;
-               default:
-                       return -EINVAL;
-                       break;
-               }
-               break;
-
-       default:
-               dprintk("%s: unknown IOCTL (0x%X)\n", __FUNCTION__, cmd);
-               return -EINVAL;
-
-       }
-
-       return 0;
-}
-
-static void ttusb_dec_init_frontend(struct ttusb_dec *dec)
-{
-       dec->i2c_bus.adapter = dec->adapter;
-
-       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(dec->frontend_ioctl, &dec->i2c_bus);
-}
-
 static void ttusb_dec_init_filters(struct ttusb_dec *dec)
 {
        INIT_LIST_HEAD(&dec->filter_info_list);
-       dec->filter_info_list_lock = SPIN_LOCK_UNLOCKED;
+       spin_lock_init(&dec->filter_info_list_lock);
 }
 
 static void ttusb_dec_exit_filters(struct ttusb_dec *dec)
@@ -1698,6 +1416,18 @@ static void ttusb_dec_exit_filters(struct ttusb_dec *dec)
        }
 }
 
+int fe_send_command(struct dvb_frontend* fe, const u8 command,
+                   int param_length, const u8 params[],
+                   int *result_length, u8 cmd_result[])
+{
+       struct ttusb_dec* dec = (struct ttusb_dec*) fe->dvb->priv;
+       return ttusb_dec_send_command(dec, command, param_length, params, result_length, cmd_result);
+}
+
+struct ttusbdecfe_config fe_config = {
+       .send_command = fe_send_command
+};
+
 static int ttusb_dec_probe(struct usb_interface *intf,
                           const struct usb_device_id *id)
 {
@@ -1717,7 +1447,7 @@ static int ttusb_dec_probe(struct usb_interface *intf,
 
        memset(dec, 0, sizeof(struct ttusb_dec));
 
-       switch (id->idProduct) {
+       switch (le16_to_cpu(id->idProduct)) {
                case 0x1006:
                ttusb_dec_set_model(dec, TTUSB_DEC3000S);
                        break;
@@ -1739,7 +1469,32 @@ static int ttusb_dec_probe(struct usb_interface *intf,
                return 0;
        }
        ttusb_dec_init_dvb(dec);
-       ttusb_dec_init_frontend(dec);
+
+       dec->adapter->priv = dec;
+       switch (le16_to_cpu(id->idProduct)) {
+       case 0x1006:
+               dec->fe = ttusbdecfe_dvbs_attach(&fe_config);
+               break;
+
+       case 0x1008:
+       case 0x1009:
+               dec->fe = ttusbdecfe_dvbt_attach(&fe_config);
+               break;
+       }
+
+       if (dec->fe == NULL) {
+               printk("dvb-ttusb-dec: A frontend driver was not found for device %04x/%04x\n",
+                      le16_to_cpu(dec->udev->descriptor.idVendor),
+                      le16_to_cpu(dec->udev->descriptor.idProduct));
+       } else {
+               if (dvb_register_frontend(dec->adapter, dec->fe)) {
+                       printk("budget-ci: Frontend registration failed!\n");
+                       if (dec->fe->ops->release)
+                               dec->fe->ops->release(dec->fe);
+                       dec->fe = NULL;
+               }
+       }
+
        ttusb_dec_init_v_pes(dec);
        ttusb_dec_init_filters(dec);
        ttusb_dec_init_tasklet(dec);
@@ -1763,7 +1518,6 @@ static void ttusb_dec_disconnect(struct usb_interface *intf)
        ttusb_dec_exit_tasklet(dec);
                ttusb_dec_exit_filters(dec);
        ttusb_dec_exit_usb(dec);
-               ttusb_dec_exit_frontend(dec);
        ttusb_dec_exit_dvb(dec);
        }
 
@@ -1779,22 +1533,16 @@ static void ttusb_dec_set_model(struct ttusb_dec *dec,
        case TTUSB_DEC2000T:
                dec->model_name = "DEC2000-t";
                dec->firmware_name = "dvb-ttusb-dec-2000t.fw";
-               dec->frontend_info = &dec2000t_frontend_info;
-               dec->frontend_ioctl = ttusb_dec_2000t_frontend_ioctl;
                break;
 
        case TTUSB_DEC2540T:
                dec->model_name = "DEC2540-t";
                dec->firmware_name = "dvb-ttusb-dec-2540t.fw";
-               dec->frontend_info = &dec2000t_frontend_info;
-               dec->frontend_ioctl = ttusb_dec_2000t_frontend_ioctl;
                break;
 
        case TTUSB_DEC3000S:
                dec->model_name = "DEC3000-s";
                dec->firmware_name = "dvb-ttusb-dec-3000s.fw";
-               dec->frontend_info = &dec3000s_frontend_info;
-               dec->frontend_ioctl = ttusb_dec_3000s_frontend_ioctl;
                break;
        }
 }
@@ -1840,7 +1588,3 @@ MODULE_DESCRIPTION(DRIVER_NAME);
 MODULE_LICENSE("GPL");
 MODULE_DEVICE_TABLE(usb, ttusb_dec_table);
 
-MODULE_PARM(debug, "i");
-MODULE_PARM_DESC(debug, "Debug level");
-MODULE_PARM(output_pva, "i");
-MODULE_PARM_DESC(output_pva, "Output PVA from dvr device");