diff options
| -rw-r--r-- | Documentation/video4linux/CARDLIST.tuner | 1 | ||||
| -rw-r--r-- | drivers/media/dvb/frontends/xc5000.c | 213 | ||||
| -rw-r--r-- | drivers/media/dvb/frontends/xc5000.h | 12 | ||||
| -rw-r--r-- | drivers/media/video/tuner-core.c | 20 | ||||
| -rw-r--r-- | drivers/media/video/tuner-types.c | 4 | ||||
| -rw-r--r-- | include/media/tuner.h | 1 |
6 files changed, 213 insertions, 38 deletions
diff --git a/Documentation/video4linux/CARDLIST.tuner b/Documentation/video4linux/CARDLIST.tuner index 2211c8eac64..0e2394695bb 100644 --- a/Documentation/video4linux/CARDLIST.tuner +++ b/Documentation/video4linux/CARDLIST.tuner | |||
| @@ -73,3 +73,4 @@ tuner=71 - Xceive xc2028/xc3028 tuner | |||
| 73 | tuner=72 - Thomson FE6600 | 73 | tuner=72 - Thomson FE6600 |
| 74 | tuner=73 - Samsung TCPG 6121P30A | 74 | tuner=73 - Samsung TCPG 6121P30A |
| 75 | tuner=75 - Philips TEA5761 FM Radio | 75 | tuner=75 - Philips TEA5761 FM Radio |
| 76 | tuner=76 - Xceive 5000 tuner | ||
diff --git a/drivers/media/dvb/frontends/xc5000.c b/drivers/media/dvb/frontends/xc5000.c index a036530ee4b..28048d5307a 100644 --- a/drivers/media/dvb/frontends/xc5000.c +++ b/drivers/media/dvb/frontends/xc5000.c | |||
| @@ -22,6 +22,7 @@ | |||
| 22 | 22 | ||
| 23 | #include <linux/module.h> | 23 | #include <linux/module.h> |
| 24 | #include <linux/moduleparam.h> | 24 | #include <linux/moduleparam.h> |
| 25 | #include <linux/videodev2.h> | ||
| 25 | #include <linux/delay.h> | 26 | #include <linux/delay.h> |
| 26 | #include <linux/dvb/frontend.h> | 27 | #include <linux/dvb/frontend.h> |
| 27 | #include <linux/i2c.h> | 28 | #include <linux/i2c.h> |
| @@ -56,6 +57,10 @@ MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off)."); | |||
| 56 | #define XC_RESULT_I2C_READ_FAILURE 3 | 57 | #define XC_RESULT_I2C_READ_FAILURE 3 |
| 57 | #define XC_RESULT_OUT_OF_RANGE 5 | 58 | #define XC_RESULT_OUT_OF_RANGE 5 |
| 58 | 59 | ||
| 60 | /* Product id */ | ||
| 61 | #define XC_PRODUCT_ID_FW_NOT_LOADED 0x2000 | ||
| 62 | #define XC_PRODUCT_ID_FW_LOADED 0x1388 | ||
| 63 | |||
| 59 | /* Registers */ | 64 | /* Registers */ |
| 60 | #define XREG_INIT 0x00 | 65 | #define XREG_INIT 0x00 |
| 61 | #define XREG_VIDEO_MODE 0x01 | 66 | #define XREG_VIDEO_MODE 0x01 |
| @@ -122,7 +127,29 @@ typedef struct { | |||
| 122 | } XC_TV_STANDARD; | 127 | } XC_TV_STANDARD; |
| 123 | 128 | ||
| 124 | /* Tuner standards */ | 129 | /* Tuner standards */ |
| 125 | #define DTV6 17 | 130 | #define MN_NTSC_PAL_BTSC 0 |
| 131 | #define MN_NTSC_PAL_A2 1 | ||
| 132 | #define MN_NTSC_PAL_EIAJ 2 | ||
| 133 | #define MN_NTSC_PAL_Mono 3 | ||
| 134 | #define BG_PAL_A2 4 | ||
| 135 | #define BG_PAL_NICAM 5 | ||
| 136 | #define BG_PAL_MONO 6 | ||
| 137 | #define I_PAL_NICAM 7 | ||
| 138 | #define I_PAL_NICAM_MONO 8 | ||
| 139 | #define DK_PAL_A2 9 | ||
| 140 | #define DK_PAL_NICAM 10 | ||
| 141 | #define DK_PAL_MONO 11 | ||
| 142 | #define DK_SECAM_A2DK1 12 | ||
| 143 | #define DK_SECAM_A2LDK3 13 | ||
| 144 | #define DK_SECAM_A2MONO 14 | ||
| 145 | #define L_SECAM_NICAM 15 | ||
| 146 | #define LC_SECAM_NICAM 16 | ||
| 147 | #define DTV6 17 | ||
| 148 | #define DTV8 18 | ||
| 149 | #define DTV7_8 19 | ||
| 150 | #define DTV7 20 | ||
| 151 | #define FM_Radio_INPUT2 21 | ||
| 152 | #define FM_Radio_INPUT1 22 | ||
| 126 | 153 | ||
| 127 | XC_TV_STANDARD XC5000_Standard[MAX_TV_STANDARD] = { | 154 | XC_TV_STANDARD XC5000_Standard[MAX_TV_STANDARD] = { |
| 128 | {"M/N-NTSC/PAL-BTSC", 0x0400, 0x8020}, | 155 | {"M/N-NTSC/PAL-BTSC", 0x0400, 0x8020}, |
| @@ -184,12 +211,13 @@ static void xc5000_TunerReset(struct dvb_frontend *fe) | |||
| 184 | 211 | ||
| 185 | dprintk(1, "%s()\n", __FUNCTION__); | 212 | dprintk(1, "%s()\n", __FUNCTION__); |
| 186 | 213 | ||
| 187 | if (priv->cfg->tuner_reset) { | 214 | if (priv->cfg->tuner_callback) { |
| 188 | ret = priv->cfg->tuner_reset(fe); | 215 | ret = priv->cfg->tuner_callback(priv->cfg->video_dev, |
| 216 | XC5000_TUNER_RESET, 0); | ||
| 189 | if (ret) | 217 | if (ret) |
| 190 | printk(KERN_ERR "xc5000: reset failed\n"); | 218 | printk(KERN_ERR "xc5000: reset failed\n"); |
| 191 | } else | 219 | } else |
| 192 | printk(KERN_ERR "xc5000: no tuner reset function, fatal\n"); | 220 | printk(KERN_ERR "xc5000: no tuner reset callback function, fatal\n"); |
| 193 | } | 221 | } |
| 194 | 222 | ||
| 195 | static int xc_write_reg(struct xc5000_priv *priv, u16 regAddr, u16 i2cData) | 223 | static int xc_write_reg(struct xc5000_priv *priv, u16 regAddr, u16 i2cData) |
| @@ -259,7 +287,6 @@ static int xc_load_i2c_sequence(struct dvb_frontend *fe, u8 i2c_sequence[]) | |||
| 259 | 287 | ||
| 260 | index=0; | 288 | index=0; |
| 261 | while ((i2c_sequence[index]!=0xFF) || (i2c_sequence[index+1]!=0xFF)) { | 289 | while ((i2c_sequence[index]!=0xFF) || (i2c_sequence[index+1]!=0xFF)) { |
| 262 | |||
| 263 | len = i2c_sequence[index]* 256 + i2c_sequence[index+1]; | 290 | len = i2c_sequence[index]* 256 + i2c_sequence[index+1]; |
| 264 | if (len == 0x0000) { | 291 | if (len == 0x0000) { |
| 265 | /* RESET command */ | 292 | /* RESET command */ |
| @@ -311,7 +338,7 @@ static int xc_SetTVStandard(struct xc5000_priv *priv, | |||
| 311 | u16 VideoMode, u16 AudioMode) | 338 | u16 VideoMode, u16 AudioMode) |
| 312 | { | 339 | { |
| 313 | int ret; | 340 | int ret; |
| 314 | dprintk(1, "%s(%d,%d)\n", __FUNCTION__, VideoMode, AudioMode); | 341 | dprintk(1, "%s(0x%04x,0x%04x)\n", __FUNCTION__, VideoMode, AudioMode); |
| 315 | dprintk(1, "%s() Standard = %s\n", | 342 | dprintk(1, "%s() Standard = %s\n", |
| 316 | __FUNCTION__, | 343 | __FUNCTION__, |
| 317 | XC5000_Standard[priv->video_standard].Name); | 344 | XC5000_Standard[priv->video_standard].Name); |
| @@ -325,7 +352,11 @@ static int xc_SetTVStandard(struct xc5000_priv *priv, | |||
| 325 | 352 | ||
| 326 | static int xc_shutdown(struct xc5000_priv *priv) | 353 | static int xc_shutdown(struct xc5000_priv *priv) |
| 327 | { | 354 | { |
| 328 | return xc_write_reg(priv, XREG_POWER_DOWN, 0); | 355 | return 0; |
| 356 | /* Fixme: cannot bring tuner back alive once shutdown | ||
| 357 | * without reloading the driver modules. | ||
| 358 | * return xc_write_reg(priv, XREG_POWER_DOWN, 0); | ||
| 359 | */ | ||
| 329 | } | 360 | } |
| 330 | 361 | ||
| 331 | static int xc_SetSignalSource(struct xc5000_priv *priv, u16 rf_mode) | 362 | static int xc_SetSignalSource(struct xc5000_priv *priv, u16 rf_mode) |
| @@ -349,7 +380,7 @@ static int xc_set_RF_frequency(struct xc5000_priv *priv, u32 freq_hz) | |||
| 349 | { | 380 | { |
| 350 | u16 freq_code; | 381 | u16 freq_code; |
| 351 | 382 | ||
| 352 | dprintk(1, "%s(%d)\n", __FUNCTION__, freq_hz); | 383 | dprintk(1, "%s(%u)\n", __FUNCTION__, freq_hz); |
| 353 | 384 | ||
| 354 | if ((freq_hz > xc5000_tuner_ops.info.frequency_max) || | 385 | if ((freq_hz > xc5000_tuner_ops.info.frequency_max) || |
| 355 | (freq_hz < xc5000_tuner_ops.info.frequency_min)) | 386 | (freq_hz < xc5000_tuner_ops.info.frequency_min)) |
| @@ -457,7 +488,7 @@ static int xc_tune_channel(struct xc5000_priv *priv, u32 freq_hz) | |||
| 457 | { | 488 | { |
| 458 | int found = 0; | 489 | int found = 0; |
| 459 | 490 | ||
| 460 | dprintk(1, "%s(%d)\n", __FUNCTION__, freq_hz); | 491 | dprintk(1, "%s(%u)\n", __FUNCTION__, freq_hz); |
| 461 | 492 | ||
| 462 | if (xc_set_RF_frequency(priv, freq_hz) != XC_RESULT_SUCCESS) | 493 | if (xc_set_RF_frequency(priv, freq_hz) != XC_RESULT_SUCCESS) |
| 463 | return 0; | 494 | return 0; |
| @@ -480,7 +511,7 @@ static int xc5000_readreg(struct xc5000_priv *priv, u16 reg, u16 *val) | |||
| 480 | }; | 511 | }; |
| 481 | 512 | ||
| 482 | if (i2c_transfer(priv->i2c, msg, 2) != 2) { | 513 | if (i2c_transfer(priv->i2c, msg, 2) != 2) { |
| 483 | printk(KERN_WARNING "xc5000 I2C read failed\n"); | 514 | printk(KERN_WARNING "xc5000: I2C read failed\n"); |
| 484 | return -EREMOTEIO; | 515 | return -EREMOTEIO; |
| 485 | } | 516 | } |
| 486 | 517 | ||
| @@ -494,7 +525,7 @@ static int xc5000_writeregs(struct xc5000_priv *priv, u8 *buf, u8 len) | |||
| 494 | .flags = 0, .buf = buf, .len = len }; | 525 | .flags = 0, .buf = buf, .len = len }; |
| 495 | 526 | ||
| 496 | if (i2c_transfer(priv->i2c, &msg, 1) != 1) { | 527 | if (i2c_transfer(priv->i2c, &msg, 1) != 1) { |
| 497 | printk(KERN_ERR "xc5000 I2C write failed (len=%i)\n", | 528 | printk(KERN_ERR "xc5000: I2C write failed (len=%i)\n", |
| 498 | (int)len); | 529 | (int)len); |
| 499 | return -EREMOTEIO; | 530 | return -EREMOTEIO; |
| 500 | } | 531 | } |
| @@ -519,16 +550,11 @@ static int xc5000_fwupload(struct dvb_frontend* fe) | |||
| 519 | const struct firmware *fw; | 550 | const struct firmware *fw; |
| 520 | int ret; | 551 | int ret; |
| 521 | 552 | ||
| 522 | if (!priv->cfg->request_firmware) { | ||
| 523 | printk(KERN_ERR "xc5000: no firmware callback, fatal\n"); | ||
| 524 | return -EIO; | ||
| 525 | } | ||
| 526 | |||
| 527 | /* request the firmware, this will block and timeout */ | 553 | /* request the firmware, this will block and timeout */ |
| 528 | printk(KERN_INFO "xc5000: waiting for firmware upload (%s)...\n", | 554 | printk(KERN_INFO "xc5000: waiting for firmware upload (%s)...\n", |
| 529 | XC5000_DEFAULT_FIRMWARE); | 555 | XC5000_DEFAULT_FIRMWARE); |
| 530 | 556 | ||
| 531 | ret = priv->cfg->request_firmware(fe, &fw, XC5000_DEFAULT_FIRMWARE); | 557 | ret = request_firmware(&fw, XC5000_DEFAULT_FIRMWARE, &priv->i2c->dev); |
| 532 | if (ret) { | 558 | if (ret) { |
| 533 | printk(KERN_ERR "xc5000: Upload failed. (file not found?)\n"); | 559 | printk(KERN_ERR "xc5000: Upload failed. (file not found?)\n"); |
| 534 | ret = XC_RESULT_RESET_FAILURE; | 560 | ret = XC_RESULT_RESET_FAILURE; |
| @@ -601,7 +627,6 @@ static int xc5000_set_params(struct dvb_frontend *fe, | |||
| 601 | 627 | ||
| 602 | dprintk(1, "%s() frequency=%d (Hz)\n", __FUNCTION__, params->frequency); | 628 | dprintk(1, "%s() frequency=%d (Hz)\n", __FUNCTION__, params->frequency); |
| 603 | 629 | ||
| 604 | |||
| 605 | switch(params->u.vsb.modulation) { | 630 | switch(params->u.vsb.modulation) { |
| 606 | case VSB_8: | 631 | case VSB_8: |
| 607 | case VSB_16: | 632 | case VSB_16: |
| @@ -658,6 +683,93 @@ static int xc5000_set_params(struct dvb_frontend *fe, | |||
| 658 | return 0; | 683 | return 0; |
| 659 | } | 684 | } |
| 660 | 685 | ||
| 686 | static int xc_load_fw_and_init_tuner(struct dvb_frontend *fe); | ||
| 687 | |||
| 688 | static int xc5000_set_analog_params(struct dvb_frontend *fe, | ||
| 689 | struct analog_parameters *params) | ||
| 690 | { | ||
| 691 | struct xc5000_priv *priv = fe->tuner_priv; | ||
| 692 | int ret; | ||
| 693 | |||
| 694 | if(priv->fwloaded == 0) | ||
| 695 | xc_load_fw_and_init_tuner(fe); | ||
| 696 | |||
| 697 | dprintk(1, "%s() frequency=%d (in units of 62.5khz)\n", | ||
| 698 | __FUNCTION__, params->frequency); | ||
| 699 | |||
| 700 | priv->rf_mode = XC_RF_MODE_CABLE; /* Fix me: it could be air. */ | ||
| 701 | |||
| 702 | /* params->frequency is in units of 62.5khz */ | ||
| 703 | priv->freq_hz = params->frequency * 62500; | ||
| 704 | |||
| 705 | /* FIX ME: Some video standards may have several possible audio | ||
| 706 | standards. We simply default to one of them here. | ||
| 707 | */ | ||
| 708 | if(params->std & V4L2_STD_MN) { | ||
| 709 | /* default to BTSC audio standard */ | ||
| 710 | priv->video_standard = MN_NTSC_PAL_BTSC; | ||
| 711 | goto tune_channel; | ||
| 712 | } | ||
| 713 | |||
| 714 | if(params->std & V4L2_STD_PAL_BG) { | ||
| 715 | /* default to NICAM audio standard */ | ||
| 716 | priv->video_standard = BG_PAL_NICAM; | ||
| 717 | goto tune_channel; | ||
| 718 | } | ||
| 719 | |||
| 720 | if(params->std & V4L2_STD_PAL_I) { | ||
| 721 | /* default to NICAM audio standard */ | ||
| 722 | priv->video_standard = I_PAL_NICAM; | ||
| 723 | goto tune_channel; | ||
| 724 | } | ||
| 725 | |||
| 726 | if(params->std & V4L2_STD_PAL_DK) { | ||
| 727 | /* default to NICAM audio standard */ | ||
| 728 | priv->video_standard = DK_PAL_NICAM; | ||
| 729 | goto tune_channel; | ||
| 730 | } | ||
| 731 | |||
| 732 | if(params->std & V4L2_STD_SECAM_DK) { | ||
| 733 | /* default to A2 DK1 audio standard */ | ||
| 734 | priv->video_standard = DK_SECAM_A2DK1; | ||
| 735 | goto tune_channel; | ||
| 736 | } | ||
| 737 | |||
| 738 | if(params->std & V4L2_STD_SECAM_L) { | ||
| 739 | priv->video_standard = L_SECAM_NICAM; | ||
| 740 | goto tune_channel; | ||
| 741 | } | ||
| 742 | |||
| 743 | if(params->std & V4L2_STD_SECAM_LC) { | ||
| 744 | priv->video_standard = LC_SECAM_NICAM; | ||
| 745 | goto tune_channel; | ||
| 746 | } | ||
| 747 | |||
| 748 | tune_channel: | ||
| 749 | ret = xc_SetSignalSource(priv, priv->rf_mode); | ||
| 750 | if (ret != XC_RESULT_SUCCESS) { | ||
| 751 | printk(KERN_ERR | ||
| 752 | "xc5000: xc_SetSignalSource(%d) failed\n", | ||
| 753 | priv->rf_mode); | ||
| 754 | return -EREMOTEIO; | ||
| 755 | } | ||
| 756 | |||
| 757 | ret = xc_SetTVStandard(priv, | ||
| 758 | XC5000_Standard[priv->video_standard].VideoMode, | ||
| 759 | XC5000_Standard[priv->video_standard].AudioMode); | ||
| 760 | if (ret != XC_RESULT_SUCCESS) { | ||
| 761 | printk(KERN_ERR "xc5000: xc_SetTVStandard failed\n"); | ||
| 762 | return -EREMOTEIO; | ||
| 763 | } | ||
| 764 | |||
| 765 | xc_tune_channel(priv, priv->freq_hz); | ||
| 766 | |||
| 767 | if (debug) | ||
| 768 | xc_debug_dump(priv); | ||
| 769 | |||
| 770 | return 0; | ||
| 771 | } | ||
| 772 | |||
| 661 | static int xc5000_get_frequency(struct dvb_frontend *fe, u32 *freq) | 773 | static int xc5000_get_frequency(struct dvb_frontend *fe, u32 *freq) |
| 662 | { | 774 | { |
| 663 | struct xc5000_priv *priv = fe->tuner_priv; | 775 | struct xc5000_priv *priv = fe->tuner_priv; |
| @@ -670,6 +782,7 @@ static int xc5000_get_bandwidth(struct dvb_frontend *fe, u32 *bw) | |||
| 670 | { | 782 | { |
| 671 | struct xc5000_priv *priv = fe->tuner_priv; | 783 | struct xc5000_priv *priv = fe->tuner_priv; |
| 672 | dprintk(1, "%s()\n", __FUNCTION__); | 784 | dprintk(1, "%s()\n", __FUNCTION__); |
| 785 | |||
| 673 | *bw = priv->bandwidth; | 786 | *bw = priv->bandwidth; |
| 674 | return 0; | 787 | return 0; |
| 675 | } | 788 | } |
| @@ -691,13 +804,12 @@ static int xc5000_get_status(struct dvb_frontend *fe, u32 *status) | |||
| 691 | static int xc_load_fw_and_init_tuner(struct dvb_frontend *fe) | 804 | static int xc_load_fw_and_init_tuner(struct dvb_frontend *fe) |
| 692 | { | 805 | { |
| 693 | struct xc5000_priv *priv = fe->tuner_priv; | 806 | struct xc5000_priv *priv = fe->tuner_priv; |
| 694 | int ret; | 807 | int ret = 0; |
| 695 | 808 | ||
| 696 | if (priv->fwloaded == 0) { | 809 | if (priv->fwloaded == 0) { |
| 697 | ret = xc5000_fwupload(fe); | 810 | ret = xc5000_fwupload(fe); |
| 698 | if (ret != XC_RESULT_SUCCESS) | 811 | if (ret != XC_RESULT_SUCCESS) |
| 699 | return ret; | 812 | return ret; |
| 700 | |||
| 701 | priv->fwloaded = 1; | 813 | priv->fwloaded = 1; |
| 702 | } | 814 | } |
| 703 | 815 | ||
| @@ -720,9 +832,27 @@ static int xc_load_fw_and_init_tuner(struct dvb_frontend *fe) | |||
| 720 | static int xc5000_sleep(struct dvb_frontend *fe) | 832 | static int xc5000_sleep(struct dvb_frontend *fe) |
| 721 | { | 833 | { |
| 722 | struct xc5000_priv *priv = fe->tuner_priv; | 834 | struct xc5000_priv *priv = fe->tuner_priv; |
| 835 | int ret; | ||
| 836 | |||
| 723 | dprintk(1, "%s()\n", __FUNCTION__); | 837 | dprintk(1, "%s()\n", __FUNCTION__); |
| 724 | 838 | ||
| 725 | return xc_shutdown(priv); | 839 | /* On Pinnacle PCTV HD 800i, the tuner cannot be reinitialized |
| 840 | * once shutdown without reloading the driver. Maybe I am not | ||
| 841 | * doing something right. | ||
| 842 | * | ||
| 843 | */ | ||
| 844 | |||
| 845 | ret = xc_shutdown(priv); | ||
| 846 | if(ret != XC_RESULT_SUCCESS) { | ||
| 847 | printk(KERN_ERR | ||
| 848 | "xc5000: %s() unable to shutdown tuner\n", | ||
| 849 | __FUNCTION__); | ||
| 850 | return -EREMOTEIO; | ||
| 851 | } | ||
| 852 | else { | ||
| 853 | /* priv->fwloaded = 0; */ | ||
| 854 | return XC_RESULT_SUCCESS; | ||
| 855 | } | ||
| 726 | } | 856 | } |
| 727 | 857 | ||
| 728 | static int xc5000_init(struct dvb_frontend *fe) | 858 | static int xc5000_init(struct dvb_frontend *fe) |
| @@ -757,14 +887,15 @@ static const struct dvb_tuner_ops xc5000_tuner_ops = { | |||
| 757 | .frequency_step = 50000, | 887 | .frequency_step = 50000, |
| 758 | }, | 888 | }, |
| 759 | 889 | ||
| 760 | .release = xc5000_release, | 890 | .release = xc5000_release, |
| 761 | .init = xc5000_init, | 891 | .init = xc5000_init, |
| 762 | .sleep = xc5000_sleep, | 892 | .sleep = xc5000_sleep, |
| 763 | 893 | ||
| 764 | .set_params = xc5000_set_params, | 894 | .set_params = xc5000_set_params, |
| 765 | .get_frequency = xc5000_get_frequency, | 895 | .set_analog_params = xc5000_set_analog_params, |
| 766 | .get_bandwidth = xc5000_get_bandwidth, | 896 | .get_frequency = xc5000_get_frequency, |
| 767 | .get_status = xc5000_get_status | 897 | .get_bandwidth = xc5000_get_bandwidth, |
| 898 | .get_status = xc5000_get_status | ||
| 768 | }; | 899 | }; |
| 769 | 900 | ||
| 770 | struct dvb_frontend * xc5000_attach(struct dvb_frontend *fe, | 901 | struct dvb_frontend * xc5000_attach(struct dvb_frontend *fe, |
| @@ -783,14 +914,33 @@ struct dvb_frontend * xc5000_attach(struct dvb_frontend *fe, | |||
| 783 | priv->cfg = cfg; | 914 | priv->cfg = cfg; |
| 784 | priv->bandwidth = BANDWIDTH_6_MHZ; | 915 | priv->bandwidth = BANDWIDTH_6_MHZ; |
| 785 | priv->i2c = i2c; | 916 | priv->i2c = i2c; |
| 786 | priv->fwloaded = 0; | ||
| 787 | 917 | ||
| 918 | /* Check if firmware has been loaded. It is possible that another | ||
| 919 | instance of the driver has loaded the firmware. | ||
| 920 | */ | ||
| 788 | if (xc5000_readreg(priv, XREG_PRODUCT_ID, &id) != 0) { | 921 | if (xc5000_readreg(priv, XREG_PRODUCT_ID, &id) != 0) { |
| 789 | kfree(priv); | 922 | kfree(priv); |
| 790 | return NULL; | 923 | return NULL; |
| 791 | } | 924 | } |
| 792 | 925 | ||
| 793 | if ((id != 0x2000) && (id != 0x1388)) { | 926 | switch(id) { |
| 927 | case XC_PRODUCT_ID_FW_LOADED: | ||
| 928 | printk(KERN_INFO | ||
| 929 | "xc5000: Successfully identified at address 0x%02x\n", | ||
| 930 | cfg->i2c_address); | ||
| 931 | printk(KERN_INFO | ||
| 932 | "xc5000: Firmware has been loaded previously\n"); | ||
| 933 | priv->fwloaded = 1; | ||
| 934 | break; | ||
| 935 | case XC_PRODUCT_ID_FW_NOT_LOADED: | ||
| 936 | printk(KERN_INFO | ||
| 937 | "xc5000: Successfully identified at address 0x%02x\n", | ||
| 938 | cfg->i2c_address); | ||
| 939 | printk(KERN_INFO | ||
| 940 | "xc5000: Firmware has not been loaded previously\n"); | ||
| 941 | priv->fwloaded = 0; | ||
| 942 | break; | ||
| 943 | default: | ||
| 794 | printk(KERN_ERR | 944 | printk(KERN_ERR |
| 795 | "xc5000: Device not found at addr 0x%02x (0x%x)\n", | 945 | "xc5000: Device not found at addr 0x%02x (0x%x)\n", |
| 796 | cfg->i2c_address, id); | 946 | cfg->i2c_address, id); |
| @@ -798,9 +948,6 @@ struct dvb_frontend * xc5000_attach(struct dvb_frontend *fe, | |||
| 798 | return NULL; | 948 | return NULL; |
| 799 | } | 949 | } |
| 800 | 950 | ||
| 801 | printk(KERN_INFO "xc5000: successfully identified at address 0x%02x\n", | ||
| 802 | cfg->i2c_address); | ||
| 803 | |||
| 804 | memcpy(&fe->ops.tuner_ops, &xc5000_tuner_ops, | 951 | memcpy(&fe->ops.tuner_ops, &xc5000_tuner_ops, |
| 805 | sizeof(struct dvb_tuner_ops)); | 952 | sizeof(struct dvb_tuner_ops)); |
| 806 | 953 | ||
diff --git a/drivers/media/dvb/frontends/xc5000.h b/drivers/media/dvb/frontends/xc5000.h index 941b3194813..85b2d438fa4 100644 --- a/drivers/media/dvb/frontends/xc5000.h +++ b/drivers/media/dvb/frontends/xc5000.h | |||
| @@ -28,13 +28,15 @@ struct dvb_frontend; | |||
| 28 | struct i2c_adapter; | 28 | struct i2c_adapter; |
| 29 | 29 | ||
| 30 | struct xc5000_config { | 30 | struct xc5000_config { |
| 31 | u8 i2c_address; | 31 | u8 i2c_address; |
| 32 | u32 if_khz; | 32 | u32 if_khz; |
| 33 | int (*request_firmware)(struct dvb_frontend *fe, | 33 | void *video_dev; |
| 34 | const struct firmware **fw, char *name); | 34 | int (*tuner_callback) (void *dev, int command, int arg); |
| 35 | int (*tuner_reset)(struct dvb_frontend* fe); | ||
| 36 | }; | 35 | }; |
| 37 | 36 | ||
| 37 | /* xc5000 callback command */ | ||
| 38 | #define XC5000_TUNER_RESET 0 | ||
| 39 | |||
| 38 | #if defined(CONFIG_DVB_TUNER_XC5000) || defined(CONFIG_DVB_TUNER_XC5000_MODULE) | 40 | #if defined(CONFIG_DVB_TUNER_XC5000) || defined(CONFIG_DVB_TUNER_XC5000_MODULE) |
| 39 | extern struct dvb_frontend* xc5000_attach(struct dvb_frontend *fe, | 41 | extern struct dvb_frontend* xc5000_attach(struct dvb_frontend *fe, |
| 40 | struct i2c_adapter *i2c, | 42 | struct i2c_adapter *i2c, |
diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c index 35976e6cb1b..16cdeeafeb6 100644 --- a/drivers/media/video/tuner-core.c +++ b/drivers/media/video/tuner-core.c | |||
| @@ -27,6 +27,7 @@ | |||
| 27 | #include "tuner-xc2028.h" | 27 | #include "tuner-xc2028.h" |
| 28 | #include "tuner-simple.h" | 28 | #include "tuner-simple.h" |
| 29 | #include "tda9887.h" | 29 | #include "tda9887.h" |
| 30 | #include "xc5000.h" | ||
| 30 | 31 | ||
| 31 | #define UNSET (-1U) | 32 | #define UNSET (-1U) |
| 32 | 33 | ||
| @@ -329,6 +330,8 @@ static void attach_tda829x(struct tuner *t) | |||
| 329 | tda829x_attach(&t->fe, t->i2c->adapter, t->i2c->addr, &cfg); | 330 | tda829x_attach(&t->fe, t->i2c->adapter, t->i2c->addr, &cfg); |
| 330 | } | 331 | } |
| 331 | 332 | ||
| 333 | static struct xc5000_config xc5000_cfg; | ||
| 334 | |||
| 332 | static void set_type(struct i2c_client *c, unsigned int type, | 335 | static void set_type(struct i2c_client *c, unsigned int type, |
| 333 | unsigned int new_mode_mask, unsigned int new_config, | 336 | unsigned int new_mode_mask, unsigned int new_config, |
| 334 | int (*tuner_callback) (void *dev, int command,int arg)) | 337 | int (*tuner_callback) (void *dev, int command,int arg)) |
| @@ -428,6 +431,23 @@ static void set_type(struct i2c_client *c, unsigned int type, | |||
| 428 | case TUNER_TDA9887: | 431 | case TUNER_TDA9887: |
| 429 | tda9887_attach(&t->fe, t->i2c->adapter, t->i2c->addr); | 432 | tda9887_attach(&t->fe, t->i2c->adapter, t->i2c->addr); |
| 430 | break; | 433 | break; |
| 434 | case TUNER_XC5000: | ||
| 435 | xc5000_cfg.i2c_address = t->i2c->addr; | ||
| 436 | xc5000_cfg.if_khz = 5380; | ||
| 437 | xc5000_cfg.video_dev = c->adapter->algo_data; | ||
| 438 | xc5000_cfg.tuner_callback = t->tuner_callback; | ||
| 439 | if (!xc5000_attach(&t->fe, t->i2c->adapter, &xc5000_cfg)) { | ||
| 440 | t->type = TUNER_ABSENT; | ||
| 441 | t->mode_mask = T_UNINITIALIZED; | ||
| 442 | return; | ||
| 443 | } | ||
| 444 | { | ||
| 445 | struct dvb_tuner_ops *xc_tuner_ops; | ||
| 446 | xc_tuner_ops = &t->fe.ops.tuner_ops; | ||
| 447 | if(xc_tuner_ops->init != NULL) | ||
| 448 | xc_tuner_ops->init(&t->fe); | ||
| 449 | } | ||
| 450 | break; | ||
| 431 | default: | 451 | default: |
| 432 | attach_simple_tuner(t); | 452 | attach_simple_tuner(t); |
| 433 | break; | 453 | break; |
diff --git a/drivers/media/video/tuner-types.c b/drivers/media/video/tuner-types.c index e2cd05a0580..883047f9c28 100644 --- a/drivers/media/video/tuner-types.c +++ b/drivers/media/video/tuner-types.c | |||
| @@ -1475,6 +1475,10 @@ struct tunertype tuners[] = { | |||
| 1475 | .name = "Philips TEA5761 FM Radio", | 1475 | .name = "Philips TEA5761 FM Radio", |
| 1476 | /* see tea5767.c for details */ | 1476 | /* see tea5767.c for details */ |
| 1477 | }, | 1477 | }, |
| 1478 | [TUNER_XC5000] = { /* Xceive 5000 */ | ||
| 1479 | .name = "Xceive 5000 tuner", | ||
| 1480 | /* see xc5000.c for details */ | ||
| 1481 | }, | ||
| 1478 | }; | 1482 | }; |
| 1479 | 1483 | ||
| 1480 | unsigned const int tuner_count = ARRAY_SIZE(tuners); | 1484 | unsigned const int tuner_count = ARRAY_SIZE(tuners); |
diff --git a/include/media/tuner.h b/include/media/tuner.h index 97be269afbe..1bf24a6ed8f 100644 --- a/include/media/tuner.h +++ b/include/media/tuner.h | |||
| @@ -121,6 +121,7 @@ | |||
| 121 | #define TUNER_SAMSUNG_TCPG_6121P30A 73 /* Hauppauge PVR-500 PAL */ | 121 | #define TUNER_SAMSUNG_TCPG_6121P30A 73 /* Hauppauge PVR-500 PAL */ |
| 122 | #define TUNER_TDA9887 74 /* This tuner should be used only internally */ | 122 | #define TUNER_TDA9887 74 /* This tuner should be used only internally */ |
| 123 | #define TUNER_TEA5761 75 /* Only FM Radio Tuner */ | 123 | #define TUNER_TEA5761 75 /* Only FM Radio Tuner */ |
| 124 | #define TUNER_XC5000 76 /* Xceive Silicon Tuner */ | ||
| 124 | 125 | ||
| 125 | /* tv card specific */ | 126 | /* tv card specific */ |
| 126 | #define TDA9887_PRESENT (1<<0) | 127 | #define TDA9887_PRESENT (1<<0) |
