aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/cx88/cx88-dvb.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/cx88/cx88-dvb.c')
-rw-r--r--drivers/media/video/cx88/cx88-dvb.c260
1 files changed, 225 insertions, 35 deletions
diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c
index f7b41eb1bb5a..f1251b844e08 100644
--- a/drivers/media/video/cx88/cx88-dvb.c
+++ b/drivers/media/video/cx88/cx88-dvb.c
@@ -45,16 +45,20 @@
45#include "nxt200x.h" 45#include "nxt200x.h"
46#include "cx24123.h" 46#include "cx24123.h"
47#include "isl6421.h" 47#include "isl6421.h"
48#include "tuner-simple.h"
49#include "tda9887.h"
48 50
49MODULE_DESCRIPTION("driver for cx2388x based DVB cards"); 51MODULE_DESCRIPTION("driver for cx2388x based DVB cards");
50MODULE_AUTHOR("Chris Pascoe <c.pascoe@itee.uq.edu.au>"); 52MODULE_AUTHOR("Chris Pascoe <c.pascoe@itee.uq.edu.au>");
51MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]"); 53MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
52MODULE_LICENSE("GPL"); 54MODULE_LICENSE("GPL");
53 55
54static unsigned int debug = 0; 56static unsigned int debug;
55module_param(debug, int, 0644); 57module_param(debug, int, 0644);
56MODULE_PARM_DESC(debug,"enable debug messages [dvb]"); 58MODULE_PARM_DESC(debug,"enable debug messages [dvb]");
57 59
60DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
61
58#define dprintk(level,fmt, arg...) if (debug >= level) \ 62#define dprintk(level,fmt, arg...) if (debug >= level) \
59 printk(KERN_DEBUG "%s/2-dvb: " fmt, core->name, ## arg) 63 printk(KERN_DEBUG "%s/2-dvb: " fmt, core->name, ## arg)
60 64
@@ -235,6 +239,19 @@ static struct zl10353_config dvico_fusionhdtv_hybrid = {
235 .no_tuner = 1, 239 .no_tuner = 1,
236}; 240};
237 241
242static struct zl10353_config dvico_fusionhdtv_xc3028 = {
243 .demod_address = 0x0f,
244 .if2 = 45600,
245 .no_tuner = 1,
246};
247
248static struct mt352_config dvico_fusionhdtv_mt352_xc3028 = {
249 .demod_address = 0x0f,
250 .if2 = 4560,
251 .no_tuner = 1,
252 .demod_init = dvico_fusionhdtv_demod_init,
253};
254
238static struct zl10353_config dvico_fusionhdtv_plus_v1_1 = { 255static struct zl10353_config dvico_fusionhdtv_plus_v1_1 = {
239 .demod_address = 0x0f, 256 .demod_address = 0x0f,
240}; 257};
@@ -266,7 +283,7 @@ static int lgdt330x_pll_rf_set(struct dvb_frontend* fe, int index)
266 struct cx8802_dev *dev= fe->dvb->priv; 283 struct cx8802_dev *dev= fe->dvb->priv;
267 struct cx88_core *core = dev->core; 284 struct cx88_core *core = dev->core;
268 285
269 dprintk(1, "%s: index = %d\n", __FUNCTION__, index); 286 dprintk(1, "%s: index = %d\n", __func__, index);
270 if (index == 0) 287 if (index == 0)
271 cx_clear(MO_GP0_IO, 8); 288 cx_clear(MO_GP0_IO, 8);
272 else 289 else
@@ -357,6 +374,40 @@ static int geniatech_dvbs_set_voltage(struct dvb_frontend *fe,
357 return 0; 374 return 0;
358} 375}
359 376
377static int cx88_pci_nano_callback(void *ptr, int command, int arg)
378{
379 struct cx88_core *core = ptr;
380
381 switch (command) {
382 case XC2028_TUNER_RESET:
383 /* Send the tuner in then out of reset */
384 dprintk(1, "%s: XC2028_TUNER_RESET %d\n", __func__, arg);
385
386 switch (core->boardnr) {
387 case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO:
388 /* GPIO-4 xc3028 tuner */
389
390 cx_set(MO_GP0_IO, 0x00001000);
391 cx_clear(MO_GP0_IO, 0x00000010);
392 msleep(100);
393 cx_set(MO_GP0_IO, 0x00000010);
394 msleep(100);
395 break;
396 }
397
398 break;
399 case XC2028_RESET_CLK:
400 dprintk(1, "%s: XC2028_RESET_CLK %d\n", __func__, arg);
401 break;
402 default:
403 dprintk(1, "%s: unknown command %d, arg %d\n", __func__,
404 command, arg);
405 return -EINVAL;
406 }
407
408 return 0;
409}
410
360static struct cx24123_config geniatech_dvbs_config = { 411static struct cx24123_config geniatech_dvbs_config = {
361 .demod_address = 0x55, 412 .demod_address = 0x55,
362 .set_ts_params = cx24123_set_ts_param, 413 .set_ts_params = cx24123_set_ts_param,
@@ -383,12 +434,76 @@ static struct s5h1409_config pinnacle_pctv_hd_800i_config = {
383 .mpeg_timing = S5H1409_MPEGTIMING_NONCONTINOUS_NONINVERTING_CLOCK, 434 .mpeg_timing = S5H1409_MPEGTIMING_NONCONTINOUS_NONINVERTING_CLOCK,
384}; 435};
385 436
437static struct s5h1409_config dvico_hdtv5_pci_nano_config = {
438 .demod_address = 0x32 >> 1,
439 .output_mode = S5H1409_SERIAL_OUTPUT,
440 .gpio = S5H1409_GPIO_OFF,
441 .inversion = S5H1409_INVERSION_OFF,
442 .status_mode = S5H1409_DEMODLOCKING,
443 .mpeg_timing = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK,
444};
445
446static struct s5h1409_config kworld_atsc_120_config = {
447 .demod_address = 0x32 >> 1,
448 .output_mode = S5H1409_SERIAL_OUTPUT,
449 .gpio = S5H1409_GPIO_OFF,
450 .inversion = S5H1409_INVERSION_OFF,
451 .status_mode = S5H1409_DEMODLOCKING,
452 .mpeg_timing = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK,
453};
454
386static struct xc5000_config pinnacle_pctv_hd_800i_tuner_config = { 455static struct xc5000_config pinnacle_pctv_hd_800i_tuner_config = {
387 .i2c_address = 0x64, 456 .i2c_address = 0x64,
388 .if_khz = 5380, 457 .if_khz = 5380,
389 .tuner_callback = cx88_tuner_callback, 458 .tuner_callback = cx88_tuner_callback,
390}; 459};
391 460
461static struct zl10353_config cx88_geniatech_x8000_mt = {
462 .demod_address = (0x1e >> 1),
463 .no_tuner = 1,
464};
465
466static int attach_xc3028(u8 addr, struct cx8802_dev *dev)
467{
468 struct dvb_frontend *fe;
469 struct xc2028_ctrl ctl;
470 struct xc2028_config cfg = {
471 .i2c_adap = &dev->core->i2c_adap,
472 .i2c_addr = addr,
473 .ctrl = &ctl,
474 .callback = cx88_tuner_callback,
475 };
476
477 if (!dev->dvb.frontend) {
478 printk(KERN_ERR "%s/2: dvb frontend not attached. "
479 "Can't attach xc3028\n",
480 dev->core->name);
481 return -EINVAL;
482 }
483
484 /*
485 * Some xc3028 devices may be hidden by an I2C gate. This is known
486 * to happen with some s5h1409-based devices.
487 * Now that I2C gate is open, sets up xc3028 configuration
488 */
489 cx88_setup_xc3028(dev->core, &ctl);
490
491 fe = dvb_attach(xc2028_attach, dev->dvb.frontend, &cfg);
492 if (!fe) {
493 printk(KERN_ERR "%s/2: xc3028 attach failed\n",
494 dev->core->name);
495 dvb_frontend_detach(dev->dvb.frontend);
496 dvb_unregister_frontend(dev->dvb.frontend);
497 dev->dvb.frontend = NULL;
498 return -EINVAL;
499 }
500
501 printk(KERN_INFO "%s/2: xc3028 attached\n",
502 dev->core->name);
503
504 return 0;
505}
506
392static int dvb_register(struct cx8802_dev *dev) 507static int dvb_register(struct cx8802_dev *dev)
393{ 508{
394 /* init struct videobuf_dvb */ 509 /* init struct videobuf_dvb */
@@ -429,8 +544,9 @@ static int dvb_register(struct cx8802_dev *dev)
429 &hauppauge_hvr_config, 544 &hauppauge_hvr_config,
430 &dev->core->i2c_adap); 545 &dev->core->i2c_adap);
431 if (dev->dvb.frontend != NULL) { 546 if (dev->dvb.frontend != NULL) {
432 dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, 547 dvb_attach(simple_tuner_attach, dev->dvb.frontend,
433 &dev->core->i2c_adap, DVB_PLL_FMD1216ME); 548 &dev->core->i2c_adap, 0x61,
549 TUNER_PHILIPS_FMD1216ME_MK3);
434 } 550 }
435 break; 551 break;
436 case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS: 552 case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS:
@@ -497,8 +613,9 @@ static int dvb_register(struct cx8802_dev *dev)
497 dev->dvb.frontend = dvb_attach(mt352_attach, &dntv_live_dvbt_pro_config, 613 dev->dvb.frontend = dvb_attach(mt352_attach, &dntv_live_dvbt_pro_config,
498 &dev->vp3054->adap); 614 &dev->vp3054->adap);
499 if (dev->dvb.frontend != NULL) { 615 if (dev->dvb.frontend != NULL) {
500 dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, 616 dvb_attach(simple_tuner_attach, dev->dvb.frontend,
501 &dev->core->i2c_adap, DVB_PLL_FMD1216ME); 617 &dev->core->i2c_adap, 0x61,
618 TUNER_PHILIPS_FMD1216ME_MK3);
502 } 619 }
503#else 620#else
504 printk(KERN_ERR "%s/2: built without vp3054 support\n", dev->core->name); 621 printk(KERN_ERR "%s/2: built without vp3054 support\n", dev->core->name);
@@ -509,18 +626,36 @@ static int dvb_register(struct cx8802_dev *dev)
509 &dvico_fusionhdtv_hybrid, 626 &dvico_fusionhdtv_hybrid,
510 &dev->core->i2c_adap); 627 &dev->core->i2c_adap);
511 if (dev->dvb.frontend != NULL) { 628 if (dev->dvb.frontend != NULL) {
512 dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, 629 dvb_attach(simple_tuner_attach, dev->dvb.frontend,
513 &dev->core->i2c_adap, 630 &dev->core->i2c_adap, 0x61,
514 DVB_PLL_THOMSON_FE6600); 631 TUNER_THOMSON_FE6600);
515 } 632 }
516 break; 633 break;
634 case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO:
635 dev->dvb.frontend = dvb_attach(zl10353_attach,
636 &dvico_fusionhdtv_xc3028,
637 &dev->core->i2c_adap);
638 if (dev->dvb.frontend == NULL)
639 dev->dvb.frontend = dvb_attach(mt352_attach,
640 &dvico_fusionhdtv_mt352_xc3028,
641 &dev->core->i2c_adap);
642 /*
643 * On this board, the demod provides the I2C bus pullup.
644 * We must not permit gate_ctrl to be performed, or
645 * the xc3028 cannot communicate on the bus.
646 */
647 if (dev->dvb.frontend)
648 dev->dvb.frontend->ops.i2c_gate_ctrl = NULL;
649 if (attach_xc3028(0x61, dev) < 0)
650 return -EINVAL;
651 break;
517 case CX88_BOARD_PCHDTV_HD3000: 652 case CX88_BOARD_PCHDTV_HD3000:
518 dev->dvb.frontend = dvb_attach(or51132_attach, &pchdtv_hd3000, 653 dev->dvb.frontend = dvb_attach(or51132_attach, &pchdtv_hd3000,
519 &dev->core->i2c_adap); 654 &dev->core->i2c_adap);
520 if (dev->dvb.frontend != NULL) { 655 if (dev->dvb.frontend != NULL) {
521 dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, 656 dvb_attach(simple_tuner_attach, dev->dvb.frontend,
522 &dev->core->i2c_adap, 657 &dev->core->i2c_adap, 0x61,
523 DVB_PLL_THOMSON_DTT761X); 658 TUNER_THOMSON_DTT761X);
524 } 659 }
525 break; 660 break;
526 case CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_Q: 661 case CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_Q:
@@ -540,9 +675,9 @@ static int dvb_register(struct cx8802_dev *dev)
540 &fusionhdtv_3_gold, 675 &fusionhdtv_3_gold,
541 &dev->core->i2c_adap); 676 &dev->core->i2c_adap);
542 if (dev->dvb.frontend != NULL) { 677 if (dev->dvb.frontend != NULL) {
543 dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, 678 dvb_attach(simple_tuner_attach, dev->dvb.frontend,
544 &dev->core->i2c_adap, 679 &dev->core->i2c_adap, 0x61,
545 DVB_PLL_MICROTUNE_4042); 680 TUNER_MICROTUNE_4042FI5);
546 } 681 }
547 } 682 }
548 break; 683 break;
@@ -560,9 +695,9 @@ static int dvb_register(struct cx8802_dev *dev)
560 &fusionhdtv_3_gold, 695 &fusionhdtv_3_gold,
561 &dev->core->i2c_adap); 696 &dev->core->i2c_adap);
562 if (dev->dvb.frontend != NULL) { 697 if (dev->dvb.frontend != NULL) {
563 dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, 698 dvb_attach(simple_tuner_attach, dev->dvb.frontend,
564 &dev->core->i2c_adap, 699 &dev->core->i2c_adap, 0x61,
565 DVB_PLL_THOMSON_DTT761X); 700 TUNER_THOMSON_DTT761X);
566 } 701 }
567 } 702 }
568 break; 703 break;
@@ -580,9 +715,11 @@ static int dvb_register(struct cx8802_dev *dev)
580 &fusionhdtv_5_gold, 715 &fusionhdtv_5_gold,
581 &dev->core->i2c_adap); 716 &dev->core->i2c_adap);
582 if (dev->dvb.frontend != NULL) { 717 if (dev->dvb.frontend != NULL) {
583 dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, 718 dvb_attach(simple_tuner_attach, dev->dvb.frontend,
584 &dev->core->i2c_adap, 719 &dev->core->i2c_adap, 0x61,
585 DVB_PLL_LG_TDVS_H06XF); 720 TUNER_LG_TDVS_H06XF);
721 dvb_attach(tda9887_attach, dev->dvb.frontend,
722 &dev->core->i2c_adap, 0x43);
586 } 723 }
587 } 724 }
588 break; 725 break;
@@ -600,9 +737,11 @@ static int dvb_register(struct cx8802_dev *dev)
600 &pchdtv_hd5500, 737 &pchdtv_hd5500,
601 &dev->core->i2c_adap); 738 &dev->core->i2c_adap);
602 if (dev->dvb.frontend != NULL) { 739 if (dev->dvb.frontend != NULL) {
603 dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, 740 dvb_attach(simple_tuner_attach, dev->dvb.frontend,
604 &dev->core->i2c_adap, 741 &dev->core->i2c_adap, 0x61,
605 DVB_PLL_LG_TDVS_H06XF); 742 TUNER_LG_TDVS_H06XF);
743 dvb_attach(tda9887_attach, dev->dvb.frontend,
744 &dev->core->i2c_adap, 0x43);
606 } 745 }
607 } 746 }
608 break; 747 break;
@@ -611,8 +750,9 @@ static int dvb_register(struct cx8802_dev *dev)
611 &ati_hdtvwonder, 750 &ati_hdtvwonder,
612 &dev->core->i2c_adap); 751 &dev->core->i2c_adap);
613 if (dev->dvb.frontend != NULL) { 752 if (dev->dvb.frontend != NULL) {
614 dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, 753 dvb_attach(simple_tuner_attach, dev->dvb.frontend,
615 NULL, DVB_PLL_TUV1236D); 754 &dev->core->i2c_adap, 0x61,
755 TUNER_PHILIPS_TUV1236D);
616 } 756 }
617 break; 757 break;
618 case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1: 758 case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1:
@@ -658,14 +798,62 @@ static int dvb_register(struct cx8802_dev *dev)
658 &pinnacle_pctv_hd_800i_tuner_config); 798 &pinnacle_pctv_hd_800i_tuner_config);
659 } 799 }
660 break; 800 break;
801 case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO:
802 dev->dvb.frontend = dvb_attach(s5h1409_attach,
803 &dvico_hdtv5_pci_nano_config,
804 &dev->core->i2c_adap);
805 if (dev->dvb.frontend != NULL) {
806 struct dvb_frontend *fe;
807 struct xc2028_config cfg = {
808 .i2c_adap = &dev->core->i2c_adap,
809 .i2c_addr = 0x61,
810 .callback = cx88_pci_nano_callback,
811 };
812 static struct xc2028_ctrl ctl = {
813 .fname = "xc3028-v27.fw",
814 .max_len = 64,
815 .scode_table = XC3028_FE_OREN538,
816 };
817
818 fe = dvb_attach(xc2028_attach,
819 dev->dvb.frontend, &cfg);
820 if (fe != NULL && fe->ops.tuner_ops.set_config != NULL)
821 fe->ops.tuner_ops.set_config(fe, &ctl);
822 }
823 break;
824 case CX88_BOARD_PINNACLE_HYBRID_PCTV:
825 dev->dvb.frontend = dvb_attach(zl10353_attach,
826 &cx88_geniatech_x8000_mt,
827 &dev->core->i2c_adap);
828 if (attach_xc3028(0x61, dev) < 0)
829 return -EINVAL;
830 break;
831 case CX88_BOARD_GENIATECH_X8000_MT:
832 dev->ts_gen_cntrl = 0x00;
833
834 dev->dvb.frontend = dvb_attach(zl10353_attach,
835 &cx88_geniatech_x8000_mt,
836 &dev->core->i2c_adap);
837 if (attach_xc3028(0x61, dev) < 0)
838 return -EINVAL;
839 break;
840 case CX88_BOARD_KWORLD_ATSC_120:
841 dev->dvb.frontend = dvb_attach(s5h1409_attach,
842 &kworld_atsc_120_config,
843 &dev->core->i2c_adap);
844 if (attach_xc3028(0x61, dev) < 0)
845 return -EINVAL;
846 break;
661 default: 847 default:
662 printk(KERN_ERR "%s/2: The frontend of your DVB/ATSC card isn't supported yet\n", 848 printk(KERN_ERR "%s/2: The frontend of your DVB/ATSC card isn't supported yet\n",
663 dev->core->name); 849 dev->core->name);
664 break; 850 break;
665 } 851 }
666 if (NULL == dev->dvb.frontend) { 852 if (NULL == dev->dvb.frontend) {
667 printk(KERN_ERR "%s/2: frontend initialization failed\n", dev->core->name); 853 printk(KERN_ERR
668 return -1; 854 "%s/2: frontend initialization failed\n",
855 dev->core->name);
856 return -EINVAL;
669 } 857 }
670 858
671 /* Ensure all frontends negotiate bus access */ 859 /* Ensure all frontends negotiate bus access */
@@ -675,7 +863,8 @@ static int dvb_register(struct cx8802_dev *dev)
675 cx88_call_i2c_clients (dev->core, TUNER_SET_STANDBY, NULL); 863 cx88_call_i2c_clients (dev->core, TUNER_SET_STANDBY, NULL);
676 864
677 /* register everything */ 865 /* register everything */
678 return videobuf_dvb_register(&dev->dvb, THIS_MODULE, dev, &dev->pci->dev); 866 return videobuf_dvb_register(&dev->dvb, THIS_MODULE, dev,
867 &dev->pci->dev, adapter_nr);
679} 868}
680 869
681/* ----------------------------------------------------------- */ 870/* ----------------------------------------------------------- */
@@ -685,7 +874,7 @@ static int cx8802_dvb_advise_acquire(struct cx8802_driver *drv)
685{ 874{
686 struct cx88_core *core = drv->core; 875 struct cx88_core *core = drv->core;
687 int err = 0; 876 int err = 0;
688 dprintk( 1, "%s\n", __FUNCTION__); 877 dprintk( 1, "%s\n", __func__);
689 878
690 switch (core->boardnr) { 879 switch (core->boardnr) {
691 case CX88_BOARD_HAUPPAUGE_HVR1300: 880 case CX88_BOARD_HAUPPAUGE_HVR1300:
@@ -708,7 +897,7 @@ static int cx8802_dvb_advise_release(struct cx8802_driver *drv)
708{ 897{
709 struct cx88_core *core = drv->core; 898 struct cx88_core *core = drv->core;
710 int err = 0; 899 int err = 0;
711 dprintk( 1, "%s\n", __FUNCTION__); 900 dprintk( 1, "%s\n", __func__);
712 901
713 switch (core->boardnr) { 902 switch (core->boardnr) {
714 case CX88_BOARD_HAUPPAUGE_HVR1300: 903 case CX88_BOARD_HAUPPAUGE_HVR1300:
@@ -726,7 +915,7 @@ static int cx8802_dvb_probe(struct cx8802_driver *drv)
726 struct cx8802_dev *dev = drv->core->dvbdev; 915 struct cx8802_dev *dev = drv->core->dvbdev;
727 int err; 916 int err;
728 917
729 dprintk( 1, "%s\n", __FUNCTION__); 918 dprintk( 1, "%s\n", __func__);
730 dprintk( 1, " ->being probed by Card=%d Name=%s, PCI %02x:%02x\n", 919 dprintk( 1, " ->being probed by Card=%d Name=%s, PCI %02x:%02x\n",
731 core->boardnr, 920 core->boardnr,
732 core->name, 921 core->name,
@@ -744,8 +933,8 @@ static int cx8802_dvb_probe(struct cx8802_driver *drv)
744 933
745 /* dvb stuff */ 934 /* dvb stuff */
746 printk(KERN_INFO "%s/2: cx2388x based DVB/ATSC card\n", core->name); 935 printk(KERN_INFO "%s/2: cx2388x based DVB/ATSC card\n", core->name);
747 videobuf_queue_pci_init(&dev->dvb.dvbq, &dvb_qops, 936 videobuf_queue_sg_init(&dev->dvb.dvbq, &dvb_qops,
748 dev->pci, &dev->slock, 937 &dev->pci->dev, &dev->slock,
749 V4L2_BUF_TYPE_VIDEO_CAPTURE, 938 V4L2_BUF_TYPE_VIDEO_CAPTURE,
750 V4L2_FIELD_TOP, 939 V4L2_FIELD_TOP,
751 sizeof(struct cx88_buffer), 940 sizeof(struct cx88_buffer),
@@ -764,7 +953,8 @@ static int cx8802_dvb_remove(struct cx8802_driver *drv)
764 struct cx8802_dev *dev = drv->core->dvbdev; 953 struct cx8802_dev *dev = drv->core->dvbdev;
765 954
766 /* dvb */ 955 /* dvb */
767 videobuf_dvb_unregister(&dev->dvb); 956 if (dev->dvb.frontend)
957 videobuf_dvb_unregister(&dev->dvb);
768 958
769 vp3054_i2c_remove(dev); 959 vp3054_i2c_remove(dev);
770 960