Merge master.kernel.org:/pub/scm/linux/kernel/git/mchehab/v4l-dvb
[linux-2.6.git] / drivers / media / dvb / ttusb-dec / ttusb_dec.c
index 64e771b..de077a7 100644 (file)
@@ -20,7 +20,8 @@
  *
  */
 
-#include <asm/semaphore.h>
+#include <linux/mutex.h>
+
 #include <linux/list.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
@@ -28,7 +29,6 @@
 #include <linux/slab.h>
 #include <linux/spinlock.h>
 #include <linux/usb.h>
-#include <linux/version.h>
 #include <linux/interrupt.h>
 #include <linux/firmware.h>
 #include <linux/crc32.h>
@@ -98,7 +98,7 @@ struct ttusb_dec {
        int                             can_playback;
 
        /* DVB bits */
-       struct dvb_adapter              *adapter;
+       struct dvb_adapter              adapter;
        struct dmxdev                   dmxdev;
        struct dvb_demux                demux;
        struct dmx_frontend             frontend;
@@ -116,7 +116,7 @@ struct ttusb_dec {
        unsigned int                    out_pipe;
        unsigned int                    irq_pipe;
        enum ttusb_dec_interface        interface;
-       struct semaphore                usb_sem;
+       struct mutex                    usb_mutex;
 
        void                    *irq_buffer;
        struct urb              *irq_urb;
@@ -125,7 +125,7 @@ struct ttusb_dec {
        dma_addr_t              iso_dma_handle;
        struct urb              *iso_urb[ISO_BUF_COUNT];
        int                     iso_stream_count;
-       struct semaphore        iso_sem;
+       struct mutex            iso_mutex;
 
        u8                              packet[MAX_PVA_LENGTH + 4];
        enum ttusb_dec_packet_type      packet_type;
@@ -153,7 +153,8 @@ struct ttusb_dec {
        struct list_head        filter_info_list;
        spinlock_t              filter_info_list_lock;
 
-       struct input_dev        rc_input_dev;
+       struct input_dev        *rc_input_dev;
+       char                    rc_phys[64];
 
        int                     active; /* Loaded successfully */
 };
@@ -214,7 +215,7 @@ static void ttusb_dec_handle_irq( struct urb *urb, struct pt_regs *regs)
                case -ECONNRESET:
                case -ENOENT:
                case -ESHUTDOWN:
-               case -ETIMEDOUT:
+               case -ETIME:
                        /* this urb is dead, cleanup */
                        dprintk("%s:urb shutting down with status: %d\n",
                                        __FUNCTION__, urb->status);
@@ -236,9 +237,9 @@ static void ttusb_dec_handle_irq( struct urb *urb, struct pt_regs *regs)
                 * this should/could be added later ...
                 * for now lets report each signal as a key down and up*/
                dprintk("%s:rc signal:%d\n", __FUNCTION__, buffer[4]);
-               input_report_key(&dec->rc_input_dev,rc_keys[buffer[4]-1],1);
-               input_report_key(&dec->rc_input_dev,rc_keys[buffer[4]-1],0);
-               input_sync(&dec->rc_input_dev);
+               input_report_key(dec->rc_input_dev, rc_keys[buffer[4] - 1], 1);
+               input_report_key(dec->rc_input_dev, rc_keys[buffer[4] - 1], 0);
+               input_sync(dec->rc_input_dev);
        }
 
 exit:  retval = usb_submit_urb(urb, GFP_ATOMIC);
@@ -273,9 +274,9 @@ static int ttusb_dec_send_command(struct ttusb_dec *dec, const u8 command,
        if (!b)
                return -ENOMEM;
 
-       if ((result = down_interruptible(&dec->usb_sem))) {
+       if ((result = mutex_lock_interruptible(&dec->usb_mutex))) {
                kfree(b);
-               printk("%s: Failed to down usb semaphore.\n", __FUNCTION__);
+               printk("%s: Failed to lock usb mutex.\n", __FUNCTION__);
                return result;
        }
 
@@ -300,7 +301,7 @@ static int ttusb_dec_send_command(struct ttusb_dec *dec, const u8 command,
        if (result) {
                printk("%s: command bulk message failed: error %d\n",
                       __FUNCTION__, result);
-               up(&dec->usb_sem);
+               mutex_unlock(&dec->usb_mutex);
                kfree(b);
                return result;
        }
@@ -311,7 +312,7 @@ static int ttusb_dec_send_command(struct ttusb_dec *dec, const u8 command,
        if (result) {
                printk("%s: result bulk message failed: error %d\n",
                       __FUNCTION__, result);
-               up(&dec->usb_sem);
+               mutex_unlock(&dec->usb_mutex);
                kfree(b);
                return result;
        } else {
@@ -327,7 +328,7 @@ static int ttusb_dec_send_command(struct ttusb_dec *dec, const u8 command,
                if (cmd_result && b[3] > 0)
                        memcpy(cmd_result, &b[4], b[3]);
 
-               up(&dec->usb_sem);
+               mutex_unlock(&dec->usb_mutex);
 
                kfree(b);
                return 0;
@@ -369,7 +370,7 @@ static int ttusb_dec_get_stb_state (struct ttusb_dec *dec, unsigned int *mode,
 
 static int ttusb_dec_audio_pes2ts_cb(void *priv, unsigned char *data)
 {
-       struct ttusb_dec *dec = (struct ttusb_dec *)priv;
+       struct ttusb_dec *dec = priv;
 
        dec->audio_filter->feed->cb.ts(data, 188, NULL, 0,
                                       &dec->audio_filter->feed->feed.ts,
@@ -380,7 +381,7 @@ static int ttusb_dec_audio_pes2ts_cb(void *priv, unsigned char *data)
 
 static int ttusb_dec_video_pes2ts_cb(void *priv, unsigned char *data)
 {
-       struct ttusb_dec *dec = (struct ttusb_dec *)priv;
+       struct ttusb_dec *dec = priv;
 
        dec->video_filter->feed->cb.ts(data, 188, NULL, 0,
                                       &dec->video_filter->feed->feed.ts,
@@ -835,7 +836,7 @@ static void ttusb_dec_stop_iso_xfer(struct ttusb_dec *dec)
 
        dprintk("%s\n", __FUNCTION__);
 
-       if (down_interruptible(&dec->iso_sem))
+       if (mutex_lock_interruptible(&dec->iso_mutex))
                return;
 
        dec->iso_stream_count--;
@@ -845,7 +846,7 @@ static void ttusb_dec_stop_iso_xfer(struct ttusb_dec *dec)
                        usb_kill_urb(dec->iso_urb[i]);
        }
 
-       up(&dec->iso_sem);
+       mutex_unlock(&dec->iso_mutex);
 }
 
 /* Setting the interface of the DEC tends to take down the USB communications
@@ -890,7 +891,7 @@ static int ttusb_dec_start_iso_xfer(struct ttusb_dec *dec)
 
        dprintk("%s\n", __FUNCTION__);
 
-       if (down_interruptible(&dec->iso_sem))
+       if (mutex_lock_interruptible(&dec->iso_mutex))
                return -EAGAIN;
 
        if (!dec->iso_stream_count) {
@@ -911,7 +912,7 @@ static int ttusb_dec_start_iso_xfer(struct ttusb_dec *dec)
                                        i--;
                                }
 
-                               up(&dec->iso_sem);
+                               mutex_unlock(&dec->iso_mutex);
                                return result;
                        }
                }
@@ -919,7 +920,7 @@ static int ttusb_dec_start_iso_xfer(struct ttusb_dec *dec)
 
        dec->iso_stream_count++;
 
-       up(&dec->iso_sem);
+       mutex_unlock(&dec->iso_mutex);
 
        return 0;
 }
@@ -965,8 +966,8 @@ static int ttusb_dec_start_ts_feed(struct dvb_demux_feed *dvbdmxfeed)
 
        case DMX_TS_PES_TELETEXT:
                dec->pid[DMX_PES_TELETEXT] = dvbdmxfeed->pid;
-               dprintk("  pes_type: DMX_TS_PES_TELETEXT\n");
-               break;
+               dprintk("  pes_type: DMX_TS_PES_TELETEXT(not supported)\n");
+               return -ENOSYS;
 
        case DMX_TS_PES_PCR:
                dprintk("  pes_type: DMX_TS_PES_PCR\n");
@@ -975,8 +976,8 @@ static int ttusb_dec_start_ts_feed(struct dvb_demux_feed *dvbdmxfeed)
                break;
 
        case DMX_TS_PES_OTHER:
-               dprintk("  pes_type: DMX_TS_PES_OTHER\n");
-               break;
+               dprintk("  pes_type: DMX_TS_PES_OTHER(not supported)\n");
+               return -ENOSYS;
 
        default:
                dprintk("  pes_type: unknown (%d)\n", dvbdmxfeed->pes_type);
@@ -1182,29 +1183,37 @@ static void ttusb_dec_init_tasklet(struct ttusb_dec *dec)
                     (unsigned long)dec);
 }
 
-static void ttusb_init_rc( struct ttusb_dec *dec)
+static int ttusb_init_rc( struct ttusb_dec *dec)
 {
+       struct input_dev *input_dev;
        u8 b[] = { 0x00, 0x01 };
        int i;
 
-       init_input_dev(&dec->rc_input_dev);
+       usb_make_path(dec->udev, dec->rc_phys, sizeof(dec->rc_phys));
+       strlcpy(dec->rc_phys, "/input0", sizeof(dec->rc_phys));
+
+       dec->rc_input_dev = input_dev = input_allocate_device();
+       if (!input_dev)
+               return -ENOMEM;
 
-       dec->rc_input_dev.name = "ttusb_dec remote control";
-       dec->rc_input_dev.evbit[0] = BIT(EV_KEY);
-       dec->rc_input_dev.keycodesize = sizeof(u16);
-       dec->rc_input_dev.keycodemax = 0x1a;
-       dec->rc_input_dev.keycode = rc_keys;
+       input_dev->name = "ttusb_dec remote control";
+       input_dev->phys = dec->rc_phys;
+       input_dev->evbit[0] = BIT(EV_KEY);
+       input_dev->keycodesize = sizeof(u16);
+       input_dev->keycodemax = 0x1a;
+       input_dev->keycode = rc_keys;
 
-        for (i = 0; i < sizeof(rc_keys)/sizeof(rc_keys[0]); i++)
-                set_bit(rc_keys[i], dec->rc_input_dev.keybit);
+       for (i = 0; i < ARRAY_SIZE(rc_keys); i++)
+                 set_bit(rc_keys[i], input_dev->keybit);
 
-       input_register_device(&dec->rc_input_dev);
+       input_register_device(input_dev);
 
-       if(usb_submit_urb(dec->irq_urb,GFP_KERNEL)) {
+       if (usb_submit_urb(dec->irq_urb, GFP_KERNEL))
                printk("%s: usb_submit_urb failed\n",__FUNCTION__);
-       }
        /* enable irq pipe */
        ttusb_dec_send_command(dec,0xb0,sizeof(b),b,NULL,NULL);
+
+       return 0;
 }
 
 static void ttusb_dec_init_v_pes(struct ttusb_dec *dec)
@@ -1221,8 +1230,8 @@ static int ttusb_dec_init_usb(struct ttusb_dec *dec)
 {
        dprintk("%s\n", __FUNCTION__);
 
-       sema_init(&dec->usb_sem, 1);
-       sema_init(&dec->iso_sem, 1);
+       mutex_init(&dec->usb_mutex);
+       mutex_init(&dec->iso_mutex);
 
        dec->command_pipe = usb_sndbulkpipe(dec->udev, COMMAND_PIPE);
        dec->result_pipe = usb_rcvbulkpipe(dec->udev, RESULT_PIPE);
@@ -1281,6 +1290,7 @@ static int ttusb_dec_boot_dsp(struct ttusb_dec *dec)
        if (firmware_size < 60) {
                printk("%s: firmware size too small for DSP code (%zu < 60).\n",
                        __FUNCTION__, firmware_size);
+               release_firmware(fw_entry);
                return -1;
        }
 
@@ -1294,6 +1304,7 @@ static int ttusb_dec_boot_dsp(struct ttusb_dec *dec)
                printk("%s: crc32 check of DSP code failed (calculated "
                       "0x%08x != 0x%08x in file), file invalid.\n",
                        __FUNCTION__, crc32_csum, crc32_check);
+               release_firmware(fw_entry);
                return -1;
        }
        memcpy(idstring, &firmware[36], 20);
@@ -1308,15 +1319,19 @@ static int ttusb_dec_boot_dsp(struct ttusb_dec *dec)
 
        result = ttusb_dec_send_command(dec, 0x41, sizeof(b0), b0, NULL, NULL);
 
-       if (result)
+       if (result) {
+               release_firmware(fw_entry);
                return result;
+       }
 
        trans_count = 0;
        j = 0;
 
        b = kmalloc(ARM_PACKET_SIZE, GFP_KERNEL);
-       if (b == NULL)
+       if (b == NULL) {
+               release_firmware(fw_entry);
                return -ENOMEM;
+       }
 
        for (i = 0; i < firmware_size; i += COMMAND_PACKET_SIZE) {
                size = firmware_size - i;
@@ -1345,6 +1360,7 @@ static int ttusb_dec_boot_dsp(struct ttusb_dec *dec)
 
        result = ttusb_dec_send_command(dec, 0x43, sizeof(b1), b1, NULL, NULL);
 
+       release_firmware(fw_entry);
        kfree(b);
 
        return result;
@@ -1379,6 +1395,7 @@ static int ttusb_dec_init_stb(struct ttusb_dec *dec)
                        /* We can't trust the USB IDs that some firmwares
                           give the box */
                        switch (model) {
+                       case 0x00070001:
                        case 0x00070008:
                        case 0x0007000c:
                                ttusb_dec_set_model(dec, TTUSB_DEC3000S);
@@ -1415,7 +1432,7 @@ static int ttusb_dec_init_dvb(struct ttusb_dec *dec)
        dprintk("%s\n", __FUNCTION__);
 
        if ((result = dvb_register_adapter(&dec->adapter,
-                                          dec->model_name, THIS_MODULE)) < 0) {
+                                          dec->model_name, THIS_MODULE, &dec->udev->dev)) < 0) {
                printk("%s: dvb_register_adapter failed: error %d\n",
                       __FUNCTION__, result);
 
@@ -1435,7 +1452,7 @@ static int ttusb_dec_init_dvb(struct ttusb_dec *dec)
                printk("%s: dvb_dmx_init failed: error %d\n", __FUNCTION__,
                       result);
 
-               dvb_unregister_adapter(dec->adapter);
+               dvb_unregister_adapter(&dec->adapter);
 
                return result;
        }
@@ -1444,12 +1461,12 @@ static int ttusb_dec_init_dvb(struct ttusb_dec *dec)
        dec->dmxdev.demux = &dec->demux.dmx;
        dec->dmxdev.capabilities = 0;
 
-       if ((result = dvb_dmxdev_init(&dec->dmxdev, dec->adapter)) < 0) {
+       if ((result = dvb_dmxdev_init(&dec->dmxdev, &dec->adapter)) < 0) {
                printk("%s: dvb_dmxdev_init failed: error %d\n",
                       __FUNCTION__, result);
 
                dvb_dmx_release(&dec->demux);
-               dvb_unregister_adapter(dec->adapter);
+               dvb_unregister_adapter(&dec->adapter);
 
                return result;
        }
@@ -1463,7 +1480,7 @@ static int ttusb_dec_init_dvb(struct ttusb_dec *dec)
 
                dvb_dmxdev_release(&dec->dmxdev);
                dvb_dmx_release(&dec->demux);
-               dvb_unregister_adapter(dec->adapter);
+               dvb_unregister_adapter(&dec->adapter);
 
                return result;
        }
@@ -1476,12 +1493,12 @@ static int ttusb_dec_init_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);
-               dvb_unregister_adapter(dec->adapter);
+               dvb_unregister_adapter(&dec->adapter);
 
                return result;
        }
 
-       dvb_net_init(dec->adapter, &dec->dvb_net, &dec->demux.dmx);
+       dvb_net_init(&dec->adapter, &dec->dvb_net, &dec->demux.dmx);
 
        return 0;
 }
@@ -1495,8 +1512,12 @@ 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);
+       if (dec->fe) {
+               dvb_unregister_frontend(dec->fe);
+               if (dec->fe->ops.release)
+                       dec->fe->ops.release(dec->fe);
+       }
+       dvb_unregister_adapter(&dec->adapter);
 }
 
 static void ttusb_dec_exit_rc(struct ttusb_dec *dec)
@@ -1507,15 +1528,18 @@ static void ttusb_dec_exit_rc(struct ttusb_dec *dec)
          * As the irq is submitted after the interface is changed,
          * this is the best method i figured out.
          * Any others?*/
-       if(dec->interface == TTUSB_DEC_INTERFACE_IN)
+       if (dec->interface == TTUSB_DEC_INTERFACE_IN)
                usb_kill_urb(dec->irq_urb);
 
        usb_free_urb(dec->irq_urb);
 
        usb_buffer_free(dec->udev,IRQ_PACKET_SIZE,
-                          dec->irq_buffer, dec->irq_dma_handle);
+                          dec->irq_buffer, dec->irq_dma_handle);
 
-       input_unregister_device(&dec->rc_input_dev);
+       if (dec->rc_input_dev) {
+               input_unregister_device(dec->rc_input_dev);
+               dec->rc_input_dev = NULL;
+       }
 }
 
 
@@ -1565,15 +1589,15 @@ 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[])
+static 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;
+       struct ttusb_dec* dec = fe->dvb->priv;
        return ttusb_dec_send_command(dec, command, param_length, params, result_length, cmd_result);
 }
 
-struct ttusbdecfe_config fe_config = {
+static struct ttusbdecfe_config fe_config = {
        .send_command = fe_send_command
 };
 
@@ -1587,15 +1611,13 @@ static int ttusb_dec_probe(struct usb_interface *intf,
 
        udev = interface_to_usbdev(intf);
 
-       if (!(dec = kmalloc(sizeof(struct ttusb_dec), GFP_KERNEL))) {
+       if (!(dec = kzalloc(sizeof(struct ttusb_dec), GFP_KERNEL))) {
                printk("%s: couldn't allocate memory.\n", __FUNCTION__);
                return -ENOMEM;
        }
 
        usb_set_intfdata(intf, (void *)dec);
 
-       memset(dec, 0, sizeof(struct ttusb_dec));
-
        switch (le16_to_cpu(id->idProduct)) {
        case 0x1006:
                ttusb_dec_set_model(dec, TTUSB_DEC3000S);
@@ -1620,7 +1642,7 @@ static int ttusb_dec_probe(struct usb_interface *intf,
        }
        ttusb_dec_init_dvb(dec);
 
-       dec->adapter->priv = dec;
+       dec->adapter.priv = dec;
        switch (le16_to_cpu(id->idProduct)) {
        case 0x1006:
                dec->fe = ttusbdecfe_dvbs_attach(&fe_config);
@@ -1637,10 +1659,10 @@ static int ttusb_dec_probe(struct usb_interface *intf,
                       le16_to_cpu(dec->udev->descriptor.idVendor),
                       le16_to_cpu(dec->udev->descriptor.idProduct));
        } else {
-               if (dvb_register_frontend(dec->adapter, dec->fe)) {
+               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);
+                       if (dec->fe->ops.release)
+                               dec->fe->ops.release(dec->fe);
                        dec->fe = NULL;
                }
        }
@@ -1653,7 +1675,7 @@ static int ttusb_dec_probe(struct usb_interface *intf,
 
        ttusb_dec_set_interface(dec, TTUSB_DEC_INTERFACE_IN);
 
-       if(enable_rc)
+       if (enable_rc)
                ttusb_init_rc(dec);
 
        return 0;