aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/tda9887.c
diff options
context:
space:
mode:
authorMichael Krufky <mkrufky@linuxtv.org>2008-04-22 13:45:51 -0400
committerMauro Carvalho Chehab <mchehab@infradead.org>2008-04-24 13:07:49 -0400
commitac8b63b30a320699e602a18af6101528b408d41d (patch)
tree9a304127c8630cdd471b3cb5ab4169cc378888f1 /drivers/media/video/tda9887.c
parent081b496a75fec134657f036f585738a1ca869047 (diff)
V4L/DVB (7346): tda9887: allow multiple driver instances for the same hardware to share state
Convert tda9887 to use the new hybrid_tuner_request_state and hybrid_tuner_release_state macros to manage state sharing between hybrid tuner instances. Some ATSC/DVB cards need to put the analog demodulator into standby before tuning digital. This patch allows us to attach the tda9887 driver to the digital side of the bridge driver and be able to put it into standby without jeopardizing the analog demod driver's state. Signed-off-by: Michael Krufky <mkrufky@linuxtv.org> Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Diffstat (limited to 'drivers/media/video/tda9887.c')
-rw-r--r--drivers/media/video/tda9887.c43
1 files changed, 33 insertions, 10 deletions
diff --git a/drivers/media/video/tda9887.c b/drivers/media/video/tda9887.c
index 75d08404d238..a0545ba957b0 100644
--- a/drivers/media/video/tda9887.c
+++ b/drivers/media/video/tda9887.c
@@ -25,8 +25,12 @@ static int debug;
25module_param(debug, int, 0644); 25module_param(debug, int, 0644);
26MODULE_PARM_DESC(debug, "enable verbose debug messages"); 26MODULE_PARM_DESC(debug, "enable verbose debug messages");
27 27
28static DEFINE_MUTEX(tda9887_list_mutex);
29static LIST_HEAD(hybrid_tuner_instance_list);
30
28struct tda9887_priv { 31struct tda9887_priv {
29 struct tuner_i2c_props i2c_props; 32 struct tuner_i2c_props i2c_props;
33 struct list_head hybrid_tuner_instance_list;
30 34
31 unsigned char data[4]; 35 unsigned char data[4];
32 unsigned int config; 36 unsigned int config;
@@ -642,7 +646,15 @@ static int tda9887_set_config(struct dvb_frontend *fe, void *priv_cfg)
642 646
643static void tda9887_release(struct dvb_frontend *fe) 647static void tda9887_release(struct dvb_frontend *fe)
644{ 648{
645 kfree(fe->analog_demod_priv); 649 struct tda9887_priv *priv = fe->analog_demod_priv;
650
651 mutex_lock(&tda9887_list_mutex);
652
653 if (priv)
654 hybrid_tuner_release_state(priv);
655
656 mutex_unlock(&tda9887_list_mutex);
657
646 fe->analog_demod_priv = NULL; 658 fe->analog_demod_priv = NULL;
647} 659}
648 660
@@ -663,18 +675,29 @@ struct dvb_frontend *tda9887_attach(struct dvb_frontend *fe,
663 u8 i2c_addr) 675 u8 i2c_addr)
664{ 676{
665 struct tda9887_priv *priv = NULL; 677 struct tda9887_priv *priv = NULL;
678 int instance;
666 679
667 priv = kzalloc(sizeof(struct tda9887_priv), GFP_KERNEL); 680 mutex_lock(&tda9887_list_mutex);
668 if (priv == NULL)
669 return NULL;
670 fe->analog_demod_priv = priv;
671 681
672 priv->i2c_props.addr = i2c_addr; 682 instance = hybrid_tuner_request_state(struct tda9887_priv, priv,
673 priv->i2c_props.adap = i2c_adap; 683 hybrid_tuner_instance_list,
674 priv->i2c_props.name = "tda9887"; 684 i2c_adap, i2c_addr, "tda9887");
675 priv->mode = T_STANDBY; 685 switch (instance) {
686 case 0:
687 mutex_unlock(&tda9887_list_mutex);
688 return NULL;
689 break;
690 case 1:
691 fe->analog_demod_priv = priv;
692 priv->mode = T_STANDBY;
693 tuner_info("tda988[5/6/7] found\n");
694 break;
695 default:
696 fe->analog_demod_priv = priv;
697 break;
698 }
676 699
677 tuner_info("tda988[5/6/7] found\n"); 700 mutex_unlock(&tda9887_list_mutex);
678 701
679 memcpy(&fe->ops.analog_ops, &tda9887_ops, 702 memcpy(&fe->ops.analog_ops, &tda9887_ops,
680 sizeof(struct analog_demod_ops)); 703 sizeof(struct analog_demod_ops));