aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAntti Palosaari <crope@iki.fi>2011-04-07 14:51:52 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2011-05-20 08:30:07 -0400
commitf71095be6645aee0828623701e35e7e7d52910d8 (patch)
treec8e0f073d203d0a4c8c8525a12d8e0a3b166a57d
parentf9d0bc1c08d205008e9414a0853e4aca8b07168a (diff)
[media] em28xx: Multi Frontend (MFE) support
Register multiple FEs for same adapter. After that it is possible to register two FEs for same adapter. For example one for DVB-T and one for DVB-C. Signed-off-by: Antti Palosaari <crope@iki.fi> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
-rw-r--r--drivers/media/video/em28xx/em28xx-dvb.c91
1 files changed, 56 insertions, 35 deletions
diff --git a/drivers/media/video/em28xx/em28xx-dvb.c b/drivers/media/video/em28xx/em28xx-dvb.c
index 84120596d0e3..0766bc6be14b 100644
--- a/drivers/media/video/em28xx/em28xx-dvb.c
+++ b/drivers/media/video/em28xx/em28xx-dvb.c
@@ -59,7 +59,7 @@ if (debug >= level) \
59#define EM28XX_DVB_MAX_PACKETS 64 59#define EM28XX_DVB_MAX_PACKETS 64
60 60
61struct em28xx_dvb { 61struct em28xx_dvb {
62 struct dvb_frontend *frontend; 62 struct dvb_frontend *fe[2];
63 63
64 /* feed count management */ 64 /* feed count management */
65 struct mutex lock; 65 struct mutex lock;
@@ -345,17 +345,17 @@ static int attach_xc3028(u8 addr, struct em28xx *dev)
345 cfg.i2c_adap = &dev->i2c_adap; 345 cfg.i2c_adap = &dev->i2c_adap;
346 cfg.i2c_addr = addr; 346 cfg.i2c_addr = addr;
347 347
348 if (!dev->dvb->frontend) { 348 if (!dev->dvb->fe[0]) {
349 em28xx_errdev("/2: dvb frontend not attached. " 349 em28xx_errdev("/2: dvb frontend not attached. "
350 "Can't attach xc3028\n"); 350 "Can't attach xc3028\n");
351 return -EINVAL; 351 return -EINVAL;
352 } 352 }
353 353
354 fe = dvb_attach(xc2028_attach, dev->dvb->frontend, &cfg); 354 fe = dvb_attach(xc2028_attach, dev->dvb->fe[0], &cfg);
355 if (!fe) { 355 if (!fe) {
356 em28xx_errdev("/2: xc3028 attach failed\n"); 356 em28xx_errdev("/2: xc3028 attach failed\n");
357 dvb_frontend_detach(dev->dvb->frontend); 357 dvb_frontend_detach(dev->dvb->fe[0]);
358 dev->dvb->frontend = NULL; 358 dev->dvb->fe[0] = NULL;
359 return -EINVAL; 359 return -EINVAL;
360 } 360 }
361 361
@@ -385,16 +385,28 @@ static int register_dvb(struct em28xx_dvb *dvb,
385 } 385 }
386 386
387 /* Ensure all frontends negotiate bus access */ 387 /* Ensure all frontends negotiate bus access */
388 dvb->frontend->ops.ts_bus_ctrl = em28xx_dvb_bus_ctrl; 388 dvb->fe[0]->ops.ts_bus_ctrl = em28xx_dvb_bus_ctrl;
389 if (dvb->fe[1])
390 dvb->fe[1]->ops.ts_bus_ctrl = em28xx_dvb_bus_ctrl;
389 391
390 dvb->adapter.priv = dev; 392 dvb->adapter.priv = dev;
391 393
392 /* register frontend */ 394 /* register frontend */
393 result = dvb_register_frontend(&dvb->adapter, dvb->frontend); 395 result = dvb_register_frontend(&dvb->adapter, dvb->fe[0]);
394 if (result < 0) { 396 if (result < 0) {
395 printk(KERN_WARNING "%s: dvb_register_frontend failed (errno = %d)\n", 397 printk(KERN_WARNING "%s: dvb_register_frontend failed (errno = %d)\n",
396 dev->name, result); 398 dev->name, result);
397 goto fail_frontend; 399 goto fail_frontend0;
400 }
401
402 /* register 2nd frontend */
403 if (dvb->fe[1]) {
404 result = dvb_register_frontend(&dvb->adapter, dvb->fe[1]);
405 if (result < 0) {
406 printk(KERN_WARNING "%s: 2nd dvb_register_frontend failed (errno = %d)\n",
407 dev->name, result);
408 goto fail_frontend1;
409 }
398 } 410 }
399 411
400 /* register demux stuff */ 412 /* register demux stuff */
@@ -460,9 +472,14 @@ fail_fe_hw:
460fail_dmxdev: 472fail_dmxdev:
461 dvb_dmx_release(&dvb->demux); 473 dvb_dmx_release(&dvb->demux);
462fail_dmx: 474fail_dmx:
463 dvb_unregister_frontend(dvb->frontend); 475 if (dvb->fe[1])
464fail_frontend: 476 dvb_unregister_frontend(dvb->fe[1]);
465 dvb_frontend_detach(dvb->frontend); 477 dvb_unregister_frontend(dvb->fe[0]);
478fail_frontend1:
479 if (dvb->fe[1])
480 dvb_frontend_detach(dvb->fe[1]);
481fail_frontend0:
482 dvb_frontend_detach(dvb->fe[0]);
466 dvb_unregister_adapter(&dvb->adapter); 483 dvb_unregister_adapter(&dvb->adapter);
467fail_adapter: 484fail_adapter:
468 return result; 485 return result;
@@ -475,12 +492,15 @@ static void unregister_dvb(struct em28xx_dvb *dvb)
475 dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_hw); 492 dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_hw);
476 dvb_dmxdev_release(&dvb->dmxdev); 493 dvb_dmxdev_release(&dvb->dmxdev);
477 dvb_dmx_release(&dvb->demux); 494 dvb_dmx_release(&dvb->demux);
478 dvb_unregister_frontend(dvb->frontend); 495 if (dvb->fe[1])
479 dvb_frontend_detach(dvb->frontend); 496 dvb_unregister_frontend(dvb->fe[1]);
497 dvb_unregister_frontend(dvb->fe[0]);
498 if (dvb->fe[1])
499 dvb_frontend_detach(dvb->fe[1]);
500 dvb_frontend_detach(dvb->fe[0]);
480 dvb_unregister_adapter(&dvb->adapter); 501 dvb_unregister_adapter(&dvb->adapter);
481} 502}
482 503
483
484static int dvb_init(struct em28xx *dev) 504static int dvb_init(struct em28xx *dev)
485{ 505{
486 int result = 0; 506 int result = 0;
@@ -499,16 +519,17 @@ static int dvb_init(struct em28xx *dev)
499 return -ENOMEM; 519 return -ENOMEM;
500 } 520 }
501 dev->dvb = dvb; 521 dev->dvb = dvb;
522 dvb->fe[0] = dvb->fe[1] = NULL;
502 523
503 mutex_lock(&dev->lock); 524 mutex_lock(&dev->lock);
504 em28xx_set_mode(dev, EM28XX_DIGITAL_MODE); 525 em28xx_set_mode(dev, EM28XX_DIGITAL_MODE);
505 /* init frontend */ 526 /* init frontend */
506 switch (dev->model) { 527 switch (dev->model) {
507 case EM2874_LEADERSHIP_ISDBT: 528 case EM2874_LEADERSHIP_ISDBT:
508 dvb->frontend = dvb_attach(s921_attach, 529 dvb->fe[0] = dvb_attach(s921_attach,
509 &sharp_isdbt, &dev->i2c_adap); 530 &sharp_isdbt, &dev->i2c_adap);
510 531
511 if (!dvb->frontend) { 532 if (!dvb->fe[0]) {
512 result = -EINVAL; 533 result = -EINVAL;
513 goto out_free; 534 goto out_free;
514 } 535 }
@@ -518,7 +539,7 @@ static int dvb_init(struct em28xx *dev)
518 case EM2883_BOARD_HAUPPAUGE_WINTV_HVR_950: 539 case EM2883_BOARD_HAUPPAUGE_WINTV_HVR_950:
519 case EM2880_BOARD_PINNACLE_PCTV_HD_PRO: 540 case EM2880_BOARD_PINNACLE_PCTV_HD_PRO:
520 case EM2880_BOARD_AMD_ATI_TV_WONDER_HD_600: 541 case EM2880_BOARD_AMD_ATI_TV_WONDER_HD_600:
521 dvb->frontend = dvb_attach(lgdt330x_attach, 542 dvb->fe[0] = dvb_attach(lgdt330x_attach,
522 &em2880_lgdt3303_dev, 543 &em2880_lgdt3303_dev,
523 &dev->i2c_adap); 544 &dev->i2c_adap);
524 if (attach_xc3028(0x61, dev) < 0) { 545 if (attach_xc3028(0x61, dev) < 0) {
@@ -527,7 +548,7 @@ static int dvb_init(struct em28xx *dev)
527 } 548 }
528 break; 549 break;
529 case EM2880_BOARD_KWORLD_DVB_310U: 550 case EM2880_BOARD_KWORLD_DVB_310U:
530 dvb->frontend = dvb_attach(zl10353_attach, 551 dvb->fe[0] = dvb_attach(zl10353_attach,
531 &em28xx_zl10353_with_xc3028, 552 &em28xx_zl10353_with_xc3028,
532 &dev->i2c_adap); 553 &dev->i2c_adap);
533 if (attach_xc3028(0x61, dev) < 0) { 554 if (attach_xc3028(0x61, dev) < 0) {
@@ -538,7 +559,7 @@ static int dvb_init(struct em28xx *dev)
538 case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900: 559 case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900:
539 case EM2882_BOARD_TERRATEC_HYBRID_XS: 560 case EM2882_BOARD_TERRATEC_HYBRID_XS:
540 case EM2880_BOARD_EMPIRE_DUAL_TV: 561 case EM2880_BOARD_EMPIRE_DUAL_TV:
541 dvb->frontend = dvb_attach(zl10353_attach, 562 dvb->fe[0] = dvb_attach(zl10353_attach,
542 &em28xx_zl10353_xc3028_no_i2c_gate, 563 &em28xx_zl10353_xc3028_no_i2c_gate,
543 &dev->i2c_adap); 564 &dev->i2c_adap);
544 if (attach_xc3028(0x61, dev) < 0) { 565 if (attach_xc3028(0x61, dev) < 0) {
@@ -551,13 +572,13 @@ static int dvb_init(struct em28xx *dev)
551 case EM2881_BOARD_PINNACLE_HYBRID_PRO: 572 case EM2881_BOARD_PINNACLE_HYBRID_PRO:
552 case EM2882_BOARD_DIKOM_DK300: 573 case EM2882_BOARD_DIKOM_DK300:
553 case EM2882_BOARD_KWORLD_VS_DVBT: 574 case EM2882_BOARD_KWORLD_VS_DVBT:
554 dvb->frontend = dvb_attach(zl10353_attach, 575 dvb->fe[0] = dvb_attach(zl10353_attach,
555 &em28xx_zl10353_xc3028_no_i2c_gate, 576 &em28xx_zl10353_xc3028_no_i2c_gate,
556 &dev->i2c_adap); 577 &dev->i2c_adap);
557 if (dvb->frontend == NULL) { 578 if (dvb->fe[0] == NULL) {
558 /* This board could have either a zl10353 or a mt352. 579 /* This board could have either a zl10353 or a mt352.
559 If the chip id isn't for zl10353, try mt352 */ 580 If the chip id isn't for zl10353, try mt352 */
560 dvb->frontend = dvb_attach(mt352_attach, 581 dvb->fe[0] = dvb_attach(mt352_attach,
561 &terratec_xs_mt352_cfg, 582 &terratec_xs_mt352_cfg,
562 &dev->i2c_adap); 583 &dev->i2c_adap);
563 } 584 }
@@ -569,7 +590,7 @@ static int dvb_init(struct em28xx *dev)
569 break; 590 break;
570 case EM2883_BOARD_KWORLD_HYBRID_330U: 591 case EM2883_BOARD_KWORLD_HYBRID_330U:
571 case EM2882_BOARD_EVGA_INDTUBE: 592 case EM2882_BOARD_EVGA_INDTUBE:
572 dvb->frontend = dvb_attach(s5h1409_attach, 593 dvb->fe[0] = dvb_attach(s5h1409_attach,
573 &em28xx_s5h1409_with_xc3028, 594 &em28xx_s5h1409_with_xc3028,
574 &dev->i2c_adap); 595 &dev->i2c_adap);
575 if (attach_xc3028(0x61, dev) < 0) { 596 if (attach_xc3028(0x61, dev) < 0) {
@@ -578,11 +599,11 @@ static int dvb_init(struct em28xx *dev)
578 } 599 }
579 break; 600 break;
580 case EM2882_BOARD_KWORLD_ATSC_315U: 601 case EM2882_BOARD_KWORLD_ATSC_315U:
581 dvb->frontend = dvb_attach(lgdt330x_attach, 602 dvb->fe[0] = dvb_attach(lgdt330x_attach,
582 &em2880_lgdt3303_dev, 603 &em2880_lgdt3303_dev,
583 &dev->i2c_adap); 604 &dev->i2c_adap);
584 if (dvb->frontend != NULL) { 605 if (dvb->fe[0] != NULL) {
585 if (!dvb_attach(simple_tuner_attach, dvb->frontend, 606 if (!dvb_attach(simple_tuner_attach, dvb->fe[0],
586 &dev->i2c_adap, 0x61, TUNER_THOMSON_DTT761X)) { 607 &dev->i2c_adap, 0x61, TUNER_THOMSON_DTT761X)) {
587 result = -EINVAL; 608 result = -EINVAL;
588 goto out_free; 609 goto out_free;
@@ -591,7 +612,7 @@ static int dvb_init(struct em28xx *dev)
591 break; 612 break;
592 case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900_R2: 613 case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900_R2:
593 case EM2882_BOARD_PINNACLE_HYBRID_PRO_330E: 614 case EM2882_BOARD_PINNACLE_HYBRID_PRO_330E:
594 dvb->frontend = dvb_attach(drxd_attach, &em28xx_drxd, NULL, 615 dvb->fe[0] = dvb_attach(drxd_attach, &em28xx_drxd, NULL,
595 &dev->i2c_adap, &dev->udev->dev); 616 &dev->i2c_adap, &dev->udev->dev);
596 if (attach_xc3028(0x61, dev) < 0) { 617 if (attach_xc3028(0x61, dev) < 0) {
597 result = -EINVAL; 618 result = -EINVAL;
@@ -600,11 +621,11 @@ static int dvb_init(struct em28xx *dev)
600 break; 621 break;
601 case EM2870_BOARD_REDDO_DVB_C_USB_BOX: 622 case EM2870_BOARD_REDDO_DVB_C_USB_BOX:
602 /* Philips CU1216L NIM (Philips TDA10023 + Infineon TUA6034) */ 623 /* Philips CU1216L NIM (Philips TDA10023 + Infineon TUA6034) */
603 dvb->frontend = dvb_attach(tda10023_attach, 624 dvb->fe[0] = dvb_attach(tda10023_attach,
604 &em28xx_tda10023_config, 625 &em28xx_tda10023_config,
605 &dev->i2c_adap, 0x48); 626 &dev->i2c_adap, 0x48);
606 if (dvb->frontend) { 627 if (dvb->fe[0]) {
607 if (!dvb_attach(simple_tuner_attach, dvb->frontend, 628 if (!dvb_attach(simple_tuner_attach, dvb->fe[0],
608 &dev->i2c_adap, 0x60, TUNER_PHILIPS_CU1216L)) { 629 &dev->i2c_adap, 0x60, TUNER_PHILIPS_CU1216L)) {
609 result = -EINVAL; 630 result = -EINVAL;
610 goto out_free; 631 goto out_free;
@@ -612,11 +633,11 @@ static int dvb_init(struct em28xx *dev)
612 } 633 }
613 break; 634 break;
614 case EM2870_BOARD_KWORLD_A340: 635 case EM2870_BOARD_KWORLD_A340:
615 dvb->frontend = dvb_attach(lgdt3305_attach, 636 dvb->fe[0] = dvb_attach(lgdt3305_attach,
616 &em2870_lgdt3304_dev, 637 &em2870_lgdt3304_dev,
617 &dev->i2c_adap); 638 &dev->i2c_adap);
618 if (dvb->frontend != NULL) 639 if (dvb->fe[0] != NULL)
619 dvb_attach(tda18271_attach, dvb->frontend, 0x60, 640 dvb_attach(tda18271_attach, dvb->fe[0], 0x60,
620 &dev->i2c_adap, &kworld_a340_config); 641 &dev->i2c_adap, &kworld_a340_config);
621 break; 642 break;
622 default: 643 default:
@@ -624,13 +645,13 @@ static int dvb_init(struct em28xx *dev)
624 " isn't supported yet\n"); 645 " isn't supported yet\n");
625 break; 646 break;
626 } 647 }
627 if (NULL == dvb->frontend) { 648 if (NULL == dvb->fe[0]) {
628 em28xx_errdev("/2: frontend initialization failed\n"); 649 em28xx_errdev("/2: frontend initialization failed\n");
629 result = -EINVAL; 650 result = -EINVAL;
630 goto out_free; 651 goto out_free;
631 } 652 }
632 /* define general-purpose callback pointer */ 653 /* define general-purpose callback pointer */
633 dvb->frontend->callback = em28xx_tuner_callback; 654 dvb->fe[0]->callback = em28xx_tuner_callback;
634 655
635 /* register everything */ 656 /* register everything */
636 result = register_dvb(dvb, THIS_MODULE, dev, &dev->udev->dev); 657 result = register_dvb(dvb, THIS_MODULE, dev, &dev->udev->dev);