aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/common/tuners
diff options
context:
space:
mode:
authorMichael Krufky <mkrufky@linuxtv.org>2008-09-06 10:44:53 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2008-10-12 07:37:01 -0400
commit89fd28545c7390eb6c63d3d9e6faac78942dd1a4 (patch)
tree50e79a8e6eb3cf2384b04e88f716fed4e93fd43c /drivers/media/common/tuners
parentffb412346bcebf143d0f43ab4c6a61c4270a9266 (diff)
V4L/DVB (8949): xc5000: allow multiple driver instances for the same hardware to share state
Convert xc5000 to use the hybrid_tuner_request_state and hybrid_tuner_release_state macros to manage state sharing between hybrid tuner instances. Signed-off-by: Michael Krufky <mkrufky@linuxtv.org> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/common/tuners')
-rw-r--r--drivers/media/common/tuners/xc5000.c87
1 files changed, 61 insertions, 26 deletions
diff --git a/drivers/media/common/tuners/xc5000.c b/drivers/media/common/tuners/xc5000.c
index 50d42c8db4ea..1850f7b7d961 100644
--- a/drivers/media/common/tuners/xc5000.c
+++ b/drivers/media/common/tuners/xc5000.c
@@ -30,6 +30,7 @@
30#include "dvb_frontend.h" 30#include "dvb_frontend.h"
31 31
32#include "xc5000.h" 32#include "xc5000.h"
33#include "tuner-i2c.h"
33 34
34static int debug; 35static int debug;
35module_param(debug, int, 0644); 36module_param(debug, int, 0644);
@@ -39,6 +40,9 @@ static int xc5000_load_fw_on_attach;
39module_param_named(init_fw, xc5000_load_fw_on_attach, int, 0644); 40module_param_named(init_fw, xc5000_load_fw_on_attach, int, 0644);
40MODULE_PARM_DESC(init_fw, "Load firmware during driver initialization."); 41MODULE_PARM_DESC(init_fw, "Load firmware during driver initialization.");
41 42
43static DEFINE_MUTEX(xc5000_list_mutex);
44static LIST_HEAD(hybrid_tuner_instance_list);
45
42#define dprintk(level,fmt, arg...) if (debug >= level) \ 46#define dprintk(level,fmt, arg...) if (debug >= level) \
43 printk(KERN_INFO "%s: " fmt, "xc5000", ## arg) 47 printk(KERN_INFO "%s: " fmt, "xc5000", ## arg)
44 48
@@ -47,7 +51,9 @@ MODULE_PARM_DESC(init_fw, "Load firmware during driver initialization.");
47 51
48struct xc5000_priv { 52struct xc5000_priv {
49 struct xc5000_config *cfg; 53 struct xc5000_config *cfg;
50 struct i2c_adapter *i2c; 54
55 struct tuner_i2c_props i2c_props;
56 struct list_head hybrid_tuner_instance_list;
51 57
52 u32 freq_hz; 58 u32 freq_hz;
53 u32 bandwidth; 59 u32 bandwidth;
@@ -520,13 +526,13 @@ static int xc5000_readreg(struct xc5000_priv *priv, u16 reg, u16 *val)
520 u8 buf[2] = { reg >> 8, reg & 0xff }; 526 u8 buf[2] = { reg >> 8, reg & 0xff };
521 u8 bval[2] = { 0, 0 }; 527 u8 bval[2] = { 0, 0 };
522 struct i2c_msg msg[2] = { 528 struct i2c_msg msg[2] = {
523 { .addr = priv->cfg->i2c_address, 529 { .addr = priv->i2c_props.addr,
524 .flags = 0, .buf = &buf[0], .len = 2 }, 530 .flags = 0, .buf = &buf[0], .len = 2 },
525 { .addr = priv->cfg->i2c_address, 531 { .addr = priv->i2c_props.addr,
526 .flags = I2C_M_RD, .buf = &bval[0], .len = 2 }, 532 .flags = I2C_M_RD, .buf = &bval[0], .len = 2 },
527 }; 533 };
528 534
529 if (i2c_transfer(priv->i2c, msg, 2) != 2) { 535 if (i2c_transfer(priv->i2c_props.adap, msg, 2) != 2) {
530 printk(KERN_WARNING "xc5000: I2C read failed\n"); 536 printk(KERN_WARNING "xc5000: I2C read failed\n");
531 return -EREMOTEIO; 537 return -EREMOTEIO;
532 } 538 }
@@ -537,10 +543,10 @@ static int xc5000_readreg(struct xc5000_priv *priv, u16 reg, u16 *val)
537 543
538static int xc5000_writeregs(struct xc5000_priv *priv, u8 *buf, u8 len) 544static int xc5000_writeregs(struct xc5000_priv *priv, u8 *buf, u8 len)
539{ 545{
540 struct i2c_msg msg = { .addr = priv->cfg->i2c_address, 546 struct i2c_msg msg = { .addr = priv->i2c_props.addr,
541 .flags = 0, .buf = buf, .len = len }; 547 .flags = 0, .buf = buf, .len = len };
542 548
543 if (i2c_transfer(priv->i2c, &msg, 1) != 1) { 549 if (i2c_transfer(priv->i2c_props.adap, &msg, 1) != 1) {
544 printk(KERN_ERR "xc5000: I2C write failed (len=%i)\n", 550 printk(KERN_ERR "xc5000: I2C write failed (len=%i)\n",
545 (int)len); 551 (int)len);
546 return -EREMOTEIO; 552 return -EREMOTEIO;
@@ -550,10 +556,10 @@ static int xc5000_writeregs(struct xc5000_priv *priv, u8 *buf, u8 len)
550 556
551static int xc5000_readregs(struct xc5000_priv *priv, u8 *buf, u8 len) 557static int xc5000_readregs(struct xc5000_priv *priv, u8 *buf, u8 len)
552{ 558{
553 struct i2c_msg msg = { .addr = priv->cfg->i2c_address, 559 struct i2c_msg msg = { .addr = priv->i2c_props.addr,
554 .flags = I2C_M_RD, .buf = buf, .len = len }; 560 .flags = I2C_M_RD, .buf = buf, .len = len };
555 561
556 if (i2c_transfer(priv->i2c, &msg, 1) != 1) { 562 if (i2c_transfer(priv->i2c_props.adap, &msg, 1) != 1) {
557 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);
558 return -EREMOTEIO; 564 return -EREMOTEIO;
559 } 565 }
@@ -570,7 +576,7 @@ static int xc5000_fwupload(struct dvb_frontend* fe)
570 printk(KERN_INFO "xc5000: waiting for firmware upload (%s)...\n", 576 printk(KERN_INFO "xc5000: waiting for firmware upload (%s)...\n",
571 XC5000_DEFAULT_FIRMWARE); 577 XC5000_DEFAULT_FIRMWARE);
572 578
573 ret = request_firmware(&fw, XC5000_DEFAULT_FIRMWARE, &priv->i2c->dev); 579 ret = request_firmware(&fw, XC5000_DEFAULT_FIRMWARE, &priv->i2c_props.adap->dev);
574 if (ret) { 580 if (ret) {
575 printk(KERN_ERR "xc5000: Upload failed. (file not found?)\n"); 581 printk(KERN_ERR "xc5000: Upload failed. (file not found?)\n");
576 ret = XC_RESULT_RESET_FAILURE; 582 ret = XC_RESULT_RESET_FAILURE;
@@ -908,9 +914,19 @@ static int xc5000_init(struct dvb_frontend *fe)
908 914
909static int xc5000_release(struct dvb_frontend *fe) 915static int xc5000_release(struct dvb_frontend *fe)
910{ 916{
917 struct xc5000_priv *priv = fe->tuner_priv;
918
911 dprintk(1, "%s()\n", __func__); 919 dprintk(1, "%s()\n", __func__);
912 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
913 fe->tuner_priv = NULL; 928 fe->tuner_priv = NULL;
929
914 return 0; 930 return 0;
915} 931}
916 932
@@ -938,26 +954,41 @@ struct dvb_frontend *xc5000_attach(struct dvb_frontend *fe,
938 struct xc5000_config *cfg, void *devptr) 954 struct xc5000_config *cfg, void *devptr)
939{ 955{
940 struct xc5000_priv *priv = NULL; 956 struct xc5000_priv *priv = NULL;
957 int instance;
941 u16 id = 0; 958 u16 id = 0;
942 959
943 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);
944 963
945 priv = kzalloc(sizeof(struct xc5000_priv), GFP_KERNEL); 964 mutex_lock(&xc5000_list_mutex);
946 if (priv == NULL)
947 return NULL;
948 965
949 priv->cfg = cfg; 966 instance = hybrid_tuner_request_state(struct xc5000_priv, priv,
950 priv->bandwidth = BANDWIDTH_6_MHZ; 967 hybrid_tuner_instance_list,
951 priv->i2c = i2c; 968 i2c, cfg->i2c_address, "xc5000");
952 priv->devptr = devptr; 969 switch (instance) {
970 case 0:
971 goto fail;
972 break;
973 case 1:
974 /* new tuner instance */
975 priv->cfg = cfg;
976 priv->bandwidth = BANDWIDTH_6_MHZ;
977 priv->devptr = devptr;
978
979 fe->tuner_priv = priv;
980 break;
981 default:
982 /* existing tuner instance */
983 fe->tuner_priv = priv;
984 break;
985 }
953 986
954 /* Check if firmware has been loaded. It is possible that another 987 /* Check if firmware has been loaded. It is possible that another
955 instance of the driver has loaded the firmware. 988 instance of the driver has loaded the firmware.
956 */ 989 */
957 if (xc5000_readreg(priv, XREG_PRODUCT_ID, &id) != 0) { 990 if (xc5000_readreg(priv, XREG_PRODUCT_ID, &id) != 0)
958 kfree(priv); 991 goto fail;
959 return NULL;
960 }
961 992
962 switch(id) { 993 switch(id) {
963 case XC_PRODUCT_ID_FW_LOADED: 994 case XC_PRODUCT_ID_FW_LOADED:
@@ -978,19 +1009,23 @@ struct dvb_frontend *xc5000_attach(struct dvb_frontend *fe,
978 printk(KERN_ERR 1009 printk(KERN_ERR
979 "xc5000: Device not found at addr 0x%02x (0x%x)\n", 1010 "xc5000: Device not found at addr 0x%02x (0x%x)\n",
980 cfg->i2c_address, id); 1011 cfg->i2c_address, id);
981 kfree(priv); 1012 goto fail;
982 return NULL;
983 } 1013 }
984 1014
1015 mutex_unlock(&xc5000_list_mutex);
1016
985 memcpy(&fe->ops.tuner_ops, &xc5000_tuner_ops, 1017 memcpy(&fe->ops.tuner_ops, &xc5000_tuner_ops,
986 sizeof(struct dvb_tuner_ops)); 1018 sizeof(struct dvb_tuner_ops));
987 1019
988 fe->tuner_priv = priv;
989
990 if (xc5000_load_fw_on_attach) 1020 if (xc5000_load_fw_on_attach)
991 xc5000_init(fe); 1021 xc5000_init(fe);
992 1022
993 return fe; 1023 return fe;
1024fail:
1025 mutex_unlock(&xc5000_list_mutex);
1026
1027 xc5000_release(fe);
1028 return NULL;
994} 1029}
995EXPORT_SYMBOL(xc5000_attach); 1030EXPORT_SYMBOL(xc5000_attach);
996 1031