diff options
author | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2008-10-14 20:31:54 -0400 |
---|---|---|
committer | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2008-10-14 20:31:54 -0400 |
commit | 6dc6472581f693b5fc95aebedf67b4960fb85cf0 (patch) | |
tree | 06a5a9a08519950575505273eabced331ed51405 /drivers/media/common/tuners/xc5000.c | |
parent | ee673eaa72d8d185012b1027a05e25aba18c267f (diff) | |
parent | 8acd3a60bcca17c6d89c73cee3ad6057eb83ba1e (diff) |
Merge commit 'origin'
Manual fixup of conflicts on:
arch/powerpc/include/asm/dcr-regs.h
drivers/net/ibm_newemac/core.h
Diffstat (limited to 'drivers/media/common/tuners/xc5000.c')
-rw-r--r-- | drivers/media/common/tuners/xc5000.c | 109 |
1 files changed, 77 insertions, 32 deletions
diff --git a/drivers/media/common/tuners/xc5000.c b/drivers/media/common/tuners/xc5000.c index dcddfa803a75..f9c2bb917f54 100644 --- a/drivers/media/common/tuners/xc5000.c +++ b/drivers/media/common/tuners/xc5000.c | |||
@@ -30,7 +30,7 @@ | |||
30 | #include "dvb_frontend.h" | 30 | #include "dvb_frontend.h" |
31 | 31 | ||
32 | #include "xc5000.h" | 32 | #include "xc5000.h" |
33 | #include "xc5000_priv.h" | 33 | #include "tuner-i2c.h" |
34 | 34 | ||
35 | static int debug; | 35 | static int debug; |
36 | module_param(debug, int, 0644); | 36 | module_param(debug, int, 0644); |
@@ -40,12 +40,26 @@ static int xc5000_load_fw_on_attach; | |||
40 | module_param_named(init_fw, xc5000_load_fw_on_attach, int, 0644); | 40 | module_param_named(init_fw, xc5000_load_fw_on_attach, int, 0644); |
41 | MODULE_PARM_DESC(init_fw, "Load firmware during driver initialization."); | 41 | MODULE_PARM_DESC(init_fw, "Load firmware during driver initialization."); |
42 | 42 | ||
43 | static DEFINE_MUTEX(xc5000_list_mutex); | ||
44 | static LIST_HEAD(hybrid_tuner_instance_list); | ||
45 | |||
43 | #define dprintk(level,fmt, arg...) if (debug >= level) \ | 46 | #define dprintk(level,fmt, arg...) if (debug >= level) \ |
44 | printk(KERN_INFO "%s: " fmt, "xc5000", ## arg) | 47 | printk(KERN_INFO "%s: " fmt, "xc5000", ## arg) |
45 | 48 | ||
46 | #define XC5000_DEFAULT_FIRMWARE "dvb-fe-xc5000-1.1.fw" | 49 | #define XC5000_DEFAULT_FIRMWARE "dvb-fe-xc5000-1.1.fw" |
47 | #define XC5000_DEFAULT_FIRMWARE_SIZE 12332 | 50 | #define XC5000_DEFAULT_FIRMWARE_SIZE 12332 |
48 | 51 | ||
52 | struct xc5000_priv { | ||
53 | struct tuner_i2c_props i2c_props; | ||
54 | struct list_head hybrid_tuner_instance_list; | ||
55 | |||
56 | u32 if_khz; | ||
57 | u32 freq_hz; | ||
58 | u32 bandwidth; | ||
59 | u8 video_standard; | ||
60 | u8 rf_mode; | ||
61 | }; | ||
62 | |||
49 | /* Misc Defines */ | 63 | /* Misc Defines */ |
50 | #define MAX_TV_STANDARD 23 | 64 | #define MAX_TV_STANDARD 23 |
51 | #define XC_MAX_I2C_WRITE_LENGTH 64 | 65 | #define XC_MAX_I2C_WRITE_LENGTH 64 |
@@ -216,9 +230,12 @@ static void xc5000_TunerReset(struct dvb_frontend *fe) | |||
216 | 230 | ||
217 | dprintk(1, "%s()\n", __func__); | 231 | dprintk(1, "%s()\n", __func__); |
218 | 232 | ||
219 | if (priv->cfg->tuner_callback) { | 233 | if (fe->callback) { |
220 | ret = priv->cfg->tuner_callback(priv->devptr, | 234 | ret = fe->callback(((fe->dvb) && (fe->dvb->priv)) ? |
221 | XC5000_TUNER_RESET, 0); | 235 | fe->dvb->priv : |
236 | priv->i2c_props.adap->algo_data, | ||
237 | DVB_FRONTEND_COMPONENT_TUNER, | ||
238 | XC5000_TUNER_RESET, 0); | ||
222 | if (ret) | 239 | if (ret) |
223 | printk(KERN_ERR "xc5000: reset failed\n"); | 240 | printk(KERN_ERR "xc5000: reset failed\n"); |
224 | } else | 241 | } else |
@@ -509,13 +526,13 @@ static int xc5000_readreg(struct xc5000_priv *priv, u16 reg, u16 *val) | |||
509 | u8 buf[2] = { reg >> 8, reg & 0xff }; | 526 | u8 buf[2] = { reg >> 8, reg & 0xff }; |
510 | u8 bval[2] = { 0, 0 }; | 527 | u8 bval[2] = { 0, 0 }; |
511 | struct i2c_msg msg[2] = { | 528 | struct i2c_msg msg[2] = { |
512 | { .addr = priv->cfg->i2c_address, | 529 | { .addr = priv->i2c_props.addr, |
513 | .flags = 0, .buf = &buf[0], .len = 2 }, | 530 | .flags = 0, .buf = &buf[0], .len = 2 }, |
514 | { .addr = priv->cfg->i2c_address, | 531 | { .addr = priv->i2c_props.addr, |
515 | .flags = I2C_M_RD, .buf = &bval[0], .len = 2 }, | 532 | .flags = I2C_M_RD, .buf = &bval[0], .len = 2 }, |
516 | }; | 533 | }; |
517 | 534 | ||
518 | if (i2c_transfer(priv->i2c, msg, 2) != 2) { | 535 | if (i2c_transfer(priv->i2c_props.adap, msg, 2) != 2) { |
519 | printk(KERN_WARNING "xc5000: I2C read failed\n"); | 536 | printk(KERN_WARNING "xc5000: I2C read failed\n"); |
520 | return -EREMOTEIO; | 537 | return -EREMOTEIO; |
521 | } | 538 | } |
@@ -526,10 +543,10 @@ static int xc5000_readreg(struct xc5000_priv *priv, u16 reg, u16 *val) | |||
526 | 543 | ||
527 | static int xc5000_writeregs(struct xc5000_priv *priv, u8 *buf, u8 len) | 544 | static int xc5000_writeregs(struct xc5000_priv *priv, u8 *buf, u8 len) |
528 | { | 545 | { |
529 | struct i2c_msg msg = { .addr = priv->cfg->i2c_address, | 546 | struct i2c_msg msg = { .addr = priv->i2c_props.addr, |
530 | .flags = 0, .buf = buf, .len = len }; | 547 | .flags = 0, .buf = buf, .len = len }; |
531 | 548 | ||
532 | if (i2c_transfer(priv->i2c, &msg, 1) != 1) { | 549 | if (i2c_transfer(priv->i2c_props.adap, &msg, 1) != 1) { |
533 | printk(KERN_ERR "xc5000: I2C write failed (len=%i)\n", | 550 | printk(KERN_ERR "xc5000: I2C write failed (len=%i)\n", |
534 | (int)len); | 551 | (int)len); |
535 | return -EREMOTEIO; | 552 | return -EREMOTEIO; |
@@ -539,10 +556,10 @@ static int xc5000_writeregs(struct xc5000_priv *priv, u8 *buf, u8 len) | |||
539 | 556 | ||
540 | static int xc5000_readregs(struct xc5000_priv *priv, u8 *buf, u8 len) | 557 | static int xc5000_readregs(struct xc5000_priv *priv, u8 *buf, u8 len) |
541 | { | 558 | { |
542 | struct i2c_msg msg = { .addr = priv->cfg->i2c_address, | 559 | struct i2c_msg msg = { .addr = priv->i2c_props.addr, |
543 | .flags = I2C_M_RD, .buf = buf, .len = len }; | 560 | .flags = I2C_M_RD, .buf = buf, .len = len }; |
544 | 561 | ||
545 | if (i2c_transfer(priv->i2c, &msg, 1) != 1) { | 562 | if (i2c_transfer(priv->i2c_props.adap, &msg, 1) != 1) { |
546 | printk(KERN_ERR "xc5000 I2C read failed (len=%i)\n",(int)len); | 563 | printk(KERN_ERR "xc5000 I2C read failed (len=%i)\n",(int)len); |
547 | return -EREMOTEIO; | 564 | return -EREMOTEIO; |
548 | } | 565 | } |
@@ -559,7 +576,7 @@ static int xc5000_fwupload(struct dvb_frontend* fe) | |||
559 | printk(KERN_INFO "xc5000: waiting for firmware upload (%s)...\n", | 576 | printk(KERN_INFO "xc5000: waiting for firmware upload (%s)...\n", |
560 | XC5000_DEFAULT_FIRMWARE); | 577 | XC5000_DEFAULT_FIRMWARE); |
561 | 578 | ||
562 | ret = request_firmware(&fw, XC5000_DEFAULT_FIRMWARE, &priv->i2c->dev); | 579 | ret = request_firmware(&fw, XC5000_DEFAULT_FIRMWARE, &priv->i2c_props.adap->dev); |
563 | if (ret) { | 580 | if (ret) { |
564 | printk(KERN_ERR "xc5000: Upload failed. (file not found?)\n"); | 581 | printk(KERN_ERR "xc5000: Upload failed. (file not found?)\n"); |
565 | ret = XC_RESULT_RESET_FAILURE; | 582 | ret = XC_RESULT_RESET_FAILURE; |
@@ -675,10 +692,10 @@ static int xc5000_set_params(struct dvb_frontend *fe, | |||
675 | return -EREMOTEIO; | 692 | return -EREMOTEIO; |
676 | } | 693 | } |
677 | 694 | ||
678 | ret = xc_set_IF_frequency(priv, priv->cfg->if_khz); | 695 | ret = xc_set_IF_frequency(priv, priv->if_khz); |
679 | if (ret != XC_RESULT_SUCCESS) { | 696 | if (ret != XC_RESULT_SUCCESS) { |
680 | printk(KERN_ERR "xc5000: xc_Set_IF_frequency(%d) failed\n", | 697 | printk(KERN_ERR "xc5000: xc_Set_IF_frequency(%d) failed\n", |
681 | priv->cfg->if_khz); | 698 | priv->if_khz); |
682 | return -EIO; | 699 | return -EIO; |
683 | } | 700 | } |
684 | 701 | ||
@@ -897,9 +914,19 @@ static int xc5000_init(struct dvb_frontend *fe) | |||
897 | 914 | ||
898 | static int xc5000_release(struct dvb_frontend *fe) | 915 | static int xc5000_release(struct dvb_frontend *fe) |
899 | { | 916 | { |
917 | struct xc5000_priv *priv = fe->tuner_priv; | ||
918 | |||
900 | dprintk(1, "%s()\n", __func__); | 919 | dprintk(1, "%s()\n", __func__); |
901 | kfree(fe->tuner_priv); | 920 | |
921 | mutex_lock(&xc5000_list_mutex); | ||
922 | |||
923 | if (priv) | ||
924 | hybrid_tuner_release_state(priv); | ||
925 | |||
926 | mutex_unlock(&xc5000_list_mutex); | ||
927 | |||
902 | fe->tuner_priv = NULL; | 928 | fe->tuner_priv = NULL; |
929 | |||
903 | return 0; | 930 | return 0; |
904 | } | 931 | } |
905 | 932 | ||
@@ -924,29 +951,43 @@ static const struct dvb_tuner_ops xc5000_tuner_ops = { | |||
924 | 951 | ||
925 | struct dvb_frontend *xc5000_attach(struct dvb_frontend *fe, | 952 | struct dvb_frontend *xc5000_attach(struct dvb_frontend *fe, |
926 | struct i2c_adapter *i2c, | 953 | struct i2c_adapter *i2c, |
927 | struct xc5000_config *cfg, void *devptr) | 954 | struct xc5000_config *cfg) |
928 | { | 955 | { |
929 | struct xc5000_priv *priv = NULL; | 956 | struct xc5000_priv *priv = NULL; |
957 | int instance; | ||
930 | u16 id = 0; | 958 | u16 id = 0; |
931 | 959 | ||
932 | dprintk(1, "%s()\n", __func__); | 960 | dprintk(1, "%s(%d-%04x)\n", __func__, |
961 | i2c ? i2c_adapter_id(i2c) : -1, | ||
962 | cfg ? cfg->i2c_address : -1); | ||
933 | 963 | ||
934 | priv = kzalloc(sizeof(struct xc5000_priv), GFP_KERNEL); | 964 | mutex_lock(&xc5000_list_mutex); |
935 | if (priv == NULL) | ||
936 | return NULL; | ||
937 | 965 | ||
938 | priv->cfg = cfg; | 966 | instance = hybrid_tuner_request_state(struct xc5000_priv, priv, |
939 | priv->bandwidth = BANDWIDTH_6_MHZ; | 967 | hybrid_tuner_instance_list, |
940 | priv->i2c = i2c; | 968 | i2c, cfg->i2c_address, "xc5000"); |
941 | priv->devptr = devptr; | 969 | switch (instance) { |
970 | case 0: | ||
971 | goto fail; | ||
972 | break; | ||
973 | case 1: | ||
974 | /* new tuner instance */ | ||
975 | priv->bandwidth = BANDWIDTH_6_MHZ; | ||
976 | priv->if_khz = cfg->if_khz; | ||
977 | |||
978 | fe->tuner_priv = priv; | ||
979 | break; | ||
980 | default: | ||
981 | /* existing tuner instance */ | ||
982 | fe->tuner_priv = priv; | ||
983 | break; | ||
984 | } | ||
942 | 985 | ||
943 | /* Check if firmware has been loaded. It is possible that another | 986 | /* Check if firmware has been loaded. It is possible that another |
944 | instance of the driver has loaded the firmware. | 987 | instance of the driver has loaded the firmware. |
945 | */ | 988 | */ |
946 | if (xc5000_readreg(priv, XREG_PRODUCT_ID, &id) != 0) { | 989 | if (xc5000_readreg(priv, XREG_PRODUCT_ID, &id) != 0) |
947 | kfree(priv); | 990 | goto fail; |
948 | return NULL; | ||
949 | } | ||
950 | 991 | ||
951 | switch(id) { | 992 | switch(id) { |
952 | case XC_PRODUCT_ID_FW_LOADED: | 993 | case XC_PRODUCT_ID_FW_LOADED: |
@@ -967,19 +1008,23 @@ struct dvb_frontend *xc5000_attach(struct dvb_frontend *fe, | |||
967 | printk(KERN_ERR | 1008 | printk(KERN_ERR |
968 | "xc5000: Device not found at addr 0x%02x (0x%x)\n", | 1009 | "xc5000: Device not found at addr 0x%02x (0x%x)\n", |
969 | cfg->i2c_address, id); | 1010 | cfg->i2c_address, id); |
970 | kfree(priv); | 1011 | goto fail; |
971 | return NULL; | ||
972 | } | 1012 | } |
973 | 1013 | ||
1014 | mutex_unlock(&xc5000_list_mutex); | ||
1015 | |||
974 | memcpy(&fe->ops.tuner_ops, &xc5000_tuner_ops, | 1016 | memcpy(&fe->ops.tuner_ops, &xc5000_tuner_ops, |
975 | sizeof(struct dvb_tuner_ops)); | 1017 | sizeof(struct dvb_tuner_ops)); |
976 | 1018 | ||
977 | fe->tuner_priv = priv; | ||
978 | |||
979 | if (xc5000_load_fw_on_attach) | 1019 | if (xc5000_load_fw_on_attach) |
980 | xc5000_init(fe); | 1020 | xc5000_init(fe); |
981 | 1021 | ||
982 | return fe; | 1022 | return fe; |
1023 | fail: | ||
1024 | mutex_unlock(&xc5000_list_mutex); | ||
1025 | |||
1026 | xc5000_release(fe); | ||
1027 | return NULL; | ||
983 | } | 1028 | } |
984 | EXPORT_SYMBOL(xc5000_attach); | 1029 | EXPORT_SYMBOL(xc5000_attach); |
985 | 1030 | ||