diff options
Diffstat (limited to 'drivers/media/video/em28xx/em28xx-dvb.c')
-rw-r--r-- | drivers/media/video/em28xx/em28xx-dvb.c | 160 |
1 files changed, 114 insertions, 46 deletions
diff --git a/drivers/media/video/em28xx/em28xx-dvb.c b/drivers/media/video/em28xx/em28xx-dvb.c index c7c04bf712aa..7904ca4b6913 100644 --- a/drivers/media/video/em28xx/em28xx-dvb.c +++ b/drivers/media/video/em28xx/em28xx-dvb.c | |||
@@ -38,6 +38,8 @@ | |||
38 | #include "tda1002x.h" | 38 | #include "tda1002x.h" |
39 | #include "tda18271.h" | 39 | #include "tda18271.h" |
40 | #include "s921.h" | 40 | #include "s921.h" |
41 | #include "drxd.h" | ||
42 | #include "cxd2820r.h" | ||
41 | 43 | ||
42 | MODULE_DESCRIPTION("driver for em28xx based DVB cards"); | 44 | MODULE_DESCRIPTION("driver for em28xx based DVB cards"); |
43 | MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@infradead.org>"); | 45 | MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@infradead.org>"); |
@@ -58,7 +60,7 @@ if (debug >= level) \ | |||
58 | #define EM28XX_DVB_MAX_PACKETS 64 | 60 | #define EM28XX_DVB_MAX_PACKETS 64 |
59 | 61 | ||
60 | struct em28xx_dvb { | 62 | struct em28xx_dvb { |
61 | struct dvb_frontend *frontend; | 63 | struct dvb_frontend *fe[2]; |
62 | 64 | ||
63 | /* feed count management */ | 65 | /* feed count management */ |
64 | struct mutex lock; | 66 | struct mutex lock; |
@@ -285,12 +287,13 @@ static struct zl10353_config em28xx_zl10353_xc3028_no_i2c_gate = { | |||
285 | .if2 = 45600, | 287 | .if2 = 45600, |
286 | }; | 288 | }; |
287 | 289 | ||
288 | #ifdef EM28XX_DRX397XD_SUPPORT | 290 | static struct drxd_config em28xx_drxd = { |
289 | /* [TODO] djh - not sure yet what the device config needs to contain */ | 291 | .index = 0, .demod_address = 0x70, .demod_revision = 0xa2, |
290 | static struct drx397xD_config em28xx_drx397xD_with_xc3028 = { | 292 | .demoda_address = 0x00, .pll_address = 0x00, |
291 | .demod_address = (0xe0 >> 1), | 293 | .pll_type = DRXD_PLL_NONE, .clock = 12000, .insert_rs_byte = 1, |
294 | .pll_set = NULL, .osc_deviation = NULL, .IF = 42800000, | ||
295 | .disable_i2c_gate_ctrl = 1, | ||
292 | }; | 296 | }; |
293 | #endif | ||
294 | 297 | ||
295 | static int mt352_terratec_xs_init(struct dvb_frontend *fe) | 298 | static int mt352_terratec_xs_init(struct dvb_frontend *fe) |
296 | { | 299 | { |
@@ -332,6 +335,26 @@ static struct tda10023_config em28xx_tda10023_config = { | |||
332 | .invert = 1, | 335 | .invert = 1, |
333 | }; | 336 | }; |
334 | 337 | ||
338 | static struct cxd2820r_config em28xx_cxd2820r_config = { | ||
339 | .i2c_address = (0xd8 >> 1), | ||
340 | .ts_mode = CXD2820R_TS_SERIAL, | ||
341 | .if_dvbt_6 = 3300, | ||
342 | .if_dvbt_7 = 3500, | ||
343 | .if_dvbt_8 = 4000, | ||
344 | .if_dvbt2_6 = 3300, | ||
345 | .if_dvbt2_7 = 3500, | ||
346 | .if_dvbt2_8 = 4000, | ||
347 | .if_dvbc = 5000, | ||
348 | |||
349 | /* enable LNA for DVB-T2 and DVB-C */ | ||
350 | .gpio_dvbt2[0] = CXD2820R_GPIO_E | CXD2820R_GPIO_O | CXD2820R_GPIO_L, | ||
351 | .gpio_dvbc[0] = CXD2820R_GPIO_E | CXD2820R_GPIO_O | CXD2820R_GPIO_L, | ||
352 | }; | ||
353 | |||
354 | static struct tda18271_config em28xx_cxd2820r_tda18271_config = { | ||
355 | .output_opt = TDA18271_OUTPUT_LT_OFF, | ||
356 | }; | ||
357 | |||
335 | /* ------------------------------------------------------------------ */ | 358 | /* ------------------------------------------------------------------ */ |
336 | 359 | ||
337 | static int attach_xc3028(u8 addr, struct em28xx *dev) | 360 | static int attach_xc3028(u8 addr, struct em28xx *dev) |
@@ -343,17 +366,17 @@ static int attach_xc3028(u8 addr, struct em28xx *dev) | |||
343 | cfg.i2c_adap = &dev->i2c_adap; | 366 | cfg.i2c_adap = &dev->i2c_adap; |
344 | cfg.i2c_addr = addr; | 367 | cfg.i2c_addr = addr; |
345 | 368 | ||
346 | if (!dev->dvb->frontend) { | 369 | if (!dev->dvb->fe[0]) { |
347 | em28xx_errdev("/2: dvb frontend not attached. " | 370 | em28xx_errdev("/2: dvb frontend not attached. " |
348 | "Can't attach xc3028\n"); | 371 | "Can't attach xc3028\n"); |
349 | return -EINVAL; | 372 | return -EINVAL; |
350 | } | 373 | } |
351 | 374 | ||
352 | fe = dvb_attach(xc2028_attach, dev->dvb->frontend, &cfg); | 375 | fe = dvb_attach(xc2028_attach, dev->dvb->fe[0], &cfg); |
353 | if (!fe) { | 376 | if (!fe) { |
354 | em28xx_errdev("/2: xc3028 attach failed\n"); | 377 | em28xx_errdev("/2: xc3028 attach failed\n"); |
355 | dvb_frontend_detach(dev->dvb->frontend); | 378 | dvb_frontend_detach(dev->dvb->fe[0]); |
356 | dev->dvb->frontend = NULL; | 379 | dev->dvb->fe[0] = NULL; |
357 | return -EINVAL; | 380 | return -EINVAL; |
358 | } | 381 | } |
359 | 382 | ||
@@ -383,16 +406,28 @@ static int register_dvb(struct em28xx_dvb *dvb, | |||
383 | } | 406 | } |
384 | 407 | ||
385 | /* Ensure all frontends negotiate bus access */ | 408 | /* Ensure all frontends negotiate bus access */ |
386 | dvb->frontend->ops.ts_bus_ctrl = em28xx_dvb_bus_ctrl; | 409 | dvb->fe[0]->ops.ts_bus_ctrl = em28xx_dvb_bus_ctrl; |
410 | if (dvb->fe[1]) | ||
411 | dvb->fe[1]->ops.ts_bus_ctrl = em28xx_dvb_bus_ctrl; | ||
387 | 412 | ||
388 | dvb->adapter.priv = dev; | 413 | dvb->adapter.priv = dev; |
389 | 414 | ||
390 | /* register frontend */ | 415 | /* register frontend */ |
391 | result = dvb_register_frontend(&dvb->adapter, dvb->frontend); | 416 | result = dvb_register_frontend(&dvb->adapter, dvb->fe[0]); |
392 | if (result < 0) { | 417 | if (result < 0) { |
393 | printk(KERN_WARNING "%s: dvb_register_frontend failed (errno = %d)\n", | 418 | printk(KERN_WARNING "%s: dvb_register_frontend failed (errno = %d)\n", |
394 | dev->name, result); | 419 | dev->name, result); |
395 | goto fail_frontend; | 420 | goto fail_frontend0; |
421 | } | ||
422 | |||
423 | /* register 2nd frontend */ | ||
424 | if (dvb->fe[1]) { | ||
425 | result = dvb_register_frontend(&dvb->adapter, dvb->fe[1]); | ||
426 | if (result < 0) { | ||
427 | printk(KERN_WARNING "%s: 2nd dvb_register_frontend failed (errno = %d)\n", | ||
428 | dev->name, result); | ||
429 | goto fail_frontend1; | ||
430 | } | ||
396 | } | 431 | } |
397 | 432 | ||
398 | /* register demux stuff */ | 433 | /* register demux stuff */ |
@@ -458,9 +493,14 @@ fail_fe_hw: | |||
458 | fail_dmxdev: | 493 | fail_dmxdev: |
459 | dvb_dmx_release(&dvb->demux); | 494 | dvb_dmx_release(&dvb->demux); |
460 | fail_dmx: | 495 | fail_dmx: |
461 | dvb_unregister_frontend(dvb->frontend); | 496 | if (dvb->fe[1]) |
462 | fail_frontend: | 497 | dvb_unregister_frontend(dvb->fe[1]); |
463 | dvb_frontend_detach(dvb->frontend); | 498 | dvb_unregister_frontend(dvb->fe[0]); |
499 | fail_frontend1: | ||
500 | if (dvb->fe[1]) | ||
501 | dvb_frontend_detach(dvb->fe[1]); | ||
502 | fail_frontend0: | ||
503 | dvb_frontend_detach(dvb->fe[0]); | ||
464 | dvb_unregister_adapter(&dvb->adapter); | 504 | dvb_unregister_adapter(&dvb->adapter); |
465 | fail_adapter: | 505 | fail_adapter: |
466 | return result; | 506 | return result; |
@@ -473,12 +513,15 @@ static void unregister_dvb(struct em28xx_dvb *dvb) | |||
473 | dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_hw); | 513 | dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_hw); |
474 | dvb_dmxdev_release(&dvb->dmxdev); | 514 | dvb_dmxdev_release(&dvb->dmxdev); |
475 | dvb_dmx_release(&dvb->demux); | 515 | dvb_dmx_release(&dvb->demux); |
476 | dvb_unregister_frontend(dvb->frontend); | 516 | if (dvb->fe[1]) |
477 | dvb_frontend_detach(dvb->frontend); | 517 | dvb_unregister_frontend(dvb->fe[1]); |
518 | dvb_unregister_frontend(dvb->fe[0]); | ||
519 | if (dvb->fe[1]) | ||
520 | dvb_frontend_detach(dvb->fe[1]); | ||
521 | dvb_frontend_detach(dvb->fe[0]); | ||
478 | dvb_unregister_adapter(&dvb->adapter); | 522 | dvb_unregister_adapter(&dvb->adapter); |
479 | } | 523 | } |
480 | 524 | ||
481 | |||
482 | static int dvb_init(struct em28xx *dev) | 525 | static int dvb_init(struct em28xx *dev) |
483 | { | 526 | { |
484 | int result = 0; | 527 | int result = 0; |
@@ -497,16 +540,17 @@ static int dvb_init(struct em28xx *dev) | |||
497 | return -ENOMEM; | 540 | return -ENOMEM; |
498 | } | 541 | } |
499 | dev->dvb = dvb; | 542 | dev->dvb = dvb; |
543 | dvb->fe[0] = dvb->fe[1] = NULL; | ||
500 | 544 | ||
501 | mutex_lock(&dev->lock); | 545 | mutex_lock(&dev->lock); |
502 | em28xx_set_mode(dev, EM28XX_DIGITAL_MODE); | 546 | em28xx_set_mode(dev, EM28XX_DIGITAL_MODE); |
503 | /* init frontend */ | 547 | /* init frontend */ |
504 | switch (dev->model) { | 548 | switch (dev->model) { |
505 | case EM2874_LEADERSHIP_ISDBT: | 549 | case EM2874_LEADERSHIP_ISDBT: |
506 | dvb->frontend = dvb_attach(s921_attach, | 550 | dvb->fe[0] = dvb_attach(s921_attach, |
507 | &sharp_isdbt, &dev->i2c_adap); | 551 | &sharp_isdbt, &dev->i2c_adap); |
508 | 552 | ||
509 | if (!dvb->frontend) { | 553 | if (!dvb->fe[0]) { |
510 | result = -EINVAL; | 554 | result = -EINVAL; |
511 | goto out_free; | 555 | goto out_free; |
512 | } | 556 | } |
@@ -516,7 +560,7 @@ static int dvb_init(struct em28xx *dev) | |||
516 | case EM2883_BOARD_HAUPPAUGE_WINTV_HVR_950: | 560 | case EM2883_BOARD_HAUPPAUGE_WINTV_HVR_950: |
517 | case EM2880_BOARD_PINNACLE_PCTV_HD_PRO: | 561 | case EM2880_BOARD_PINNACLE_PCTV_HD_PRO: |
518 | case EM2880_BOARD_AMD_ATI_TV_WONDER_HD_600: | 562 | case EM2880_BOARD_AMD_ATI_TV_WONDER_HD_600: |
519 | dvb->frontend = dvb_attach(lgdt330x_attach, | 563 | dvb->fe[0] = dvb_attach(lgdt330x_attach, |
520 | &em2880_lgdt3303_dev, | 564 | &em2880_lgdt3303_dev, |
521 | &dev->i2c_adap); | 565 | &dev->i2c_adap); |
522 | if (attach_xc3028(0x61, dev) < 0) { | 566 | if (attach_xc3028(0x61, dev) < 0) { |
@@ -525,7 +569,7 @@ static int dvb_init(struct em28xx *dev) | |||
525 | } | 569 | } |
526 | break; | 570 | break; |
527 | case EM2880_BOARD_KWORLD_DVB_310U: | 571 | case EM2880_BOARD_KWORLD_DVB_310U: |
528 | dvb->frontend = dvb_attach(zl10353_attach, | 572 | dvb->fe[0] = dvb_attach(zl10353_attach, |
529 | &em28xx_zl10353_with_xc3028, | 573 | &em28xx_zl10353_with_xc3028, |
530 | &dev->i2c_adap); | 574 | &dev->i2c_adap); |
531 | if (attach_xc3028(0x61, dev) < 0) { | 575 | if (attach_xc3028(0x61, dev) < 0) { |
@@ -536,7 +580,7 @@ static int dvb_init(struct em28xx *dev) | |||
536 | case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900: | 580 | case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900: |
537 | case EM2882_BOARD_TERRATEC_HYBRID_XS: | 581 | case EM2882_BOARD_TERRATEC_HYBRID_XS: |
538 | case EM2880_BOARD_EMPIRE_DUAL_TV: | 582 | case EM2880_BOARD_EMPIRE_DUAL_TV: |
539 | dvb->frontend = dvb_attach(zl10353_attach, | 583 | dvb->fe[0] = dvb_attach(zl10353_attach, |
540 | &em28xx_zl10353_xc3028_no_i2c_gate, | 584 | &em28xx_zl10353_xc3028_no_i2c_gate, |
541 | &dev->i2c_adap); | 585 | &dev->i2c_adap); |
542 | if (attach_xc3028(0x61, dev) < 0) { | 586 | if (attach_xc3028(0x61, dev) < 0) { |
@@ -549,13 +593,13 @@ static int dvb_init(struct em28xx *dev) | |||
549 | case EM2881_BOARD_PINNACLE_HYBRID_PRO: | 593 | case EM2881_BOARD_PINNACLE_HYBRID_PRO: |
550 | case EM2882_BOARD_DIKOM_DK300: | 594 | case EM2882_BOARD_DIKOM_DK300: |
551 | case EM2882_BOARD_KWORLD_VS_DVBT: | 595 | case EM2882_BOARD_KWORLD_VS_DVBT: |
552 | dvb->frontend = dvb_attach(zl10353_attach, | 596 | dvb->fe[0] = dvb_attach(zl10353_attach, |
553 | &em28xx_zl10353_xc3028_no_i2c_gate, | 597 | &em28xx_zl10353_xc3028_no_i2c_gate, |
554 | &dev->i2c_adap); | 598 | &dev->i2c_adap); |
555 | if (dvb->frontend == NULL) { | 599 | if (dvb->fe[0] == NULL) { |
556 | /* This board could have either a zl10353 or a mt352. | 600 | /* This board could have either a zl10353 or a mt352. |
557 | If the chip id isn't for zl10353, try mt352 */ | 601 | If the chip id isn't for zl10353, try mt352 */ |
558 | dvb->frontend = dvb_attach(mt352_attach, | 602 | dvb->fe[0] = dvb_attach(mt352_attach, |
559 | &terratec_xs_mt352_cfg, | 603 | &terratec_xs_mt352_cfg, |
560 | &dev->i2c_adap); | 604 | &dev->i2c_adap); |
561 | } | 605 | } |
@@ -567,7 +611,7 @@ static int dvb_init(struct em28xx *dev) | |||
567 | break; | 611 | break; |
568 | case EM2883_BOARD_KWORLD_HYBRID_330U: | 612 | case EM2883_BOARD_KWORLD_HYBRID_330U: |
569 | case EM2882_BOARD_EVGA_INDTUBE: | 613 | case EM2882_BOARD_EVGA_INDTUBE: |
570 | dvb->frontend = dvb_attach(s5h1409_attach, | 614 | dvb->fe[0] = dvb_attach(s5h1409_attach, |
571 | &em28xx_s5h1409_with_xc3028, | 615 | &em28xx_s5h1409_with_xc3028, |
572 | &dev->i2c_adap); | 616 | &dev->i2c_adap); |
573 | if (attach_xc3028(0x61, dev) < 0) { | 617 | if (attach_xc3028(0x61, dev) < 0) { |
@@ -576,11 +620,11 @@ static int dvb_init(struct em28xx *dev) | |||
576 | } | 620 | } |
577 | break; | 621 | break; |
578 | case EM2882_BOARD_KWORLD_ATSC_315U: | 622 | case EM2882_BOARD_KWORLD_ATSC_315U: |
579 | dvb->frontend = dvb_attach(lgdt330x_attach, | 623 | dvb->fe[0] = dvb_attach(lgdt330x_attach, |
580 | &em2880_lgdt3303_dev, | 624 | &em2880_lgdt3303_dev, |
581 | &dev->i2c_adap); | 625 | &dev->i2c_adap); |
582 | if (dvb->frontend != NULL) { | 626 | if (dvb->fe[0] != NULL) { |
583 | if (!dvb_attach(simple_tuner_attach, dvb->frontend, | 627 | if (!dvb_attach(simple_tuner_attach, dvb->fe[0], |
584 | &dev->i2c_adap, 0x61, TUNER_THOMSON_DTT761X)) { | 628 | &dev->i2c_adap, 0x61, TUNER_THOMSON_DTT761X)) { |
585 | result = -EINVAL; | 629 | result = -EINVAL; |
586 | goto out_free; | 630 | goto out_free; |
@@ -588,25 +632,21 @@ static int dvb_init(struct em28xx *dev) | |||
588 | } | 632 | } |
589 | break; | 633 | break; |
590 | case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900_R2: | 634 | case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900_R2: |
591 | #ifdef EM28XX_DRX397XD_SUPPORT | 635 | case EM2882_BOARD_PINNACLE_HYBRID_PRO_330E: |
592 | /* We don't have the config structure properly populated, so | 636 | dvb->fe[0] = dvb_attach(drxd_attach, &em28xx_drxd, NULL, |
593 | this is commented out for now */ | 637 | &dev->i2c_adap, &dev->udev->dev); |
594 | dvb->frontend = dvb_attach(drx397xD_attach, | ||
595 | &em28xx_drx397xD_with_xc3028, | ||
596 | &dev->i2c_adap); | ||
597 | if (attach_xc3028(0x61, dev) < 0) { | 638 | if (attach_xc3028(0x61, dev) < 0) { |
598 | result = -EINVAL; | 639 | result = -EINVAL; |
599 | goto out_free; | 640 | goto out_free; |
600 | } | 641 | } |
601 | break; | 642 | break; |
602 | #endif | ||
603 | case EM2870_BOARD_REDDO_DVB_C_USB_BOX: | 643 | case EM2870_BOARD_REDDO_DVB_C_USB_BOX: |
604 | /* Philips CU1216L NIM (Philips TDA10023 + Infineon TUA6034) */ | 644 | /* Philips CU1216L NIM (Philips TDA10023 + Infineon TUA6034) */ |
605 | dvb->frontend = dvb_attach(tda10023_attach, | 645 | dvb->fe[0] = dvb_attach(tda10023_attach, |
606 | &em28xx_tda10023_config, | 646 | &em28xx_tda10023_config, |
607 | &dev->i2c_adap, 0x48); | 647 | &dev->i2c_adap, 0x48); |
608 | if (dvb->frontend) { | 648 | if (dvb->fe[0]) { |
609 | if (!dvb_attach(simple_tuner_attach, dvb->frontend, | 649 | if (!dvb_attach(simple_tuner_attach, dvb->fe[0], |
610 | &dev->i2c_adap, 0x60, TUNER_PHILIPS_CU1216L)) { | 650 | &dev->i2c_adap, 0x60, TUNER_PHILIPS_CU1216L)) { |
611 | result = -EINVAL; | 651 | result = -EINVAL; |
612 | goto out_free; | 652 | goto out_free; |
@@ -614,25 +654,53 @@ static int dvb_init(struct em28xx *dev) | |||
614 | } | 654 | } |
615 | break; | 655 | break; |
616 | case EM2870_BOARD_KWORLD_A340: | 656 | case EM2870_BOARD_KWORLD_A340: |
617 | dvb->frontend = dvb_attach(lgdt3305_attach, | 657 | dvb->fe[0] = dvb_attach(lgdt3305_attach, |
618 | &em2870_lgdt3304_dev, | 658 | &em2870_lgdt3304_dev, |
619 | &dev->i2c_adap); | 659 | &dev->i2c_adap); |
620 | if (dvb->frontend != NULL) | 660 | if (dvb->fe[0] != NULL) |
621 | dvb_attach(tda18271_attach, dvb->frontend, 0x60, | 661 | dvb_attach(tda18271_attach, dvb->fe[0], 0x60, |
622 | &dev->i2c_adap, &kworld_a340_config); | 662 | &dev->i2c_adap, &kworld_a340_config); |
623 | break; | 663 | break; |
664 | case EM28174_BOARD_PCTV_290E: | ||
665 | /* MFE | ||
666 | * FE 0 = DVB-T/T2 + FE 1 = DVB-C, both sharing same tuner. */ | ||
667 | /* FE 0 */ | ||
668 | dvb->fe[0] = dvb_attach(cxd2820r_attach, | ||
669 | &em28xx_cxd2820r_config, &dev->i2c_adap, NULL); | ||
670 | if (dvb->fe[0]) { | ||
671 | struct i2c_adapter *i2c_tuner; | ||
672 | i2c_tuner = cxd2820r_get_tuner_i2c_adapter(dvb->fe[0]); | ||
673 | /* FE 0 attach tuner */ | ||
674 | if (!dvb_attach(tda18271_attach, dvb->fe[0], 0x60, | ||
675 | i2c_tuner, &em28xx_cxd2820r_tda18271_config)) { | ||
676 | dvb_frontend_detach(dvb->fe[0]); | ||
677 | result = -EINVAL; | ||
678 | goto out_free; | ||
679 | } | ||
680 | /* FE 1. This dvb_attach() cannot fail. */ | ||
681 | dvb->fe[1] = dvb_attach(cxd2820r_attach, NULL, NULL, | ||
682 | dvb->fe[0]); | ||
683 | dvb->fe[1]->id = 1; | ||
684 | /* FE 1 attach tuner */ | ||
685 | if (!dvb_attach(tda18271_attach, dvb->fe[1], 0x60, | ||
686 | i2c_tuner, &em28xx_cxd2820r_tda18271_config)) { | ||
687 | dvb_frontend_detach(dvb->fe[1]); | ||
688 | /* leave FE 0 still active */ | ||
689 | } | ||
690 | } | ||
691 | break; | ||
624 | default: | 692 | default: |
625 | em28xx_errdev("/2: The frontend of your DVB/ATSC card" | 693 | em28xx_errdev("/2: The frontend of your DVB/ATSC card" |
626 | " isn't supported yet\n"); | 694 | " isn't supported yet\n"); |
627 | break; | 695 | break; |
628 | } | 696 | } |
629 | if (NULL == dvb->frontend) { | 697 | if (NULL == dvb->fe[0]) { |
630 | em28xx_errdev("/2: frontend initialization failed\n"); | 698 | em28xx_errdev("/2: frontend initialization failed\n"); |
631 | result = -EINVAL; | 699 | result = -EINVAL; |
632 | goto out_free; | 700 | goto out_free; |
633 | } | 701 | } |
634 | /* define general-purpose callback pointer */ | 702 | /* define general-purpose callback pointer */ |
635 | dvb->frontend->callback = em28xx_tuner_callback; | 703 | dvb->fe[0]->callback = em28xx_tuner_callback; |
636 | 704 | ||
637 | /* register everything */ | 705 | /* register everything */ |
638 | result = register_dvb(dvb, THIS_MODULE, dev, &dev->udev->dev); | 706 | result = register_dvb(dvb, THIS_MODULE, dev, &dev->udev->dev); |