aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorMichael Krufky <mkrufky@linuxtv.org>2008-01-06 13:52:56 -0500
committerMauro Carvalho Chehab <mchehab@infradead.org>2008-01-25 16:04:43 -0500
commita4f263b587573f47cc6bc7ad85e5f650169d48f6 (patch)
treed6734ff3a2d7234b34086152fe08c6606973f5b2 /drivers
parentb3d98135aa6e462d7e3f42a86d12483a9003a4da (diff)
V4L/DVB (6986): tda18271: share state between analog and digital tuner instances
Signed-off-by: Michael Krufky <mkrufky@linuxtv.org> Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/media/dvb/frontends/tda18271-fe.c93
-rw-r--r--drivers/media/dvb/frontends/tda18271-priv.h3
-rw-r--r--drivers/media/video/tda8290.c9
3 files changed, 81 insertions, 24 deletions
diff --git a/drivers/media/dvb/frontends/tda18271-fe.c b/drivers/media/dvb/frontends/tda18271-fe.c
index e860f4c009c2..aa93e1550627 100644
--- a/drivers/media/dvb/frontends/tda18271-fe.c
+++ b/drivers/media/dvb/frontends/tda18271-fe.c
@@ -27,6 +27,9 @@ module_param_named(debug, tda18271_debug, int, 0644);
27MODULE_PARM_DESC(debug, "set debug level " 27MODULE_PARM_DESC(debug, "set debug level "
28 "(info=1, map=2, reg=4, adv=8 (or-able))"); 28 "(info=1, map=2, reg=4, adv=8 (or-able))");
29 29
30static LIST_HEAD(tda18271_list);
31static DEFINE_MUTEX(tda18271_list_mutex);
32
30/*---------------------------------------------------------------------*/ 33/*---------------------------------------------------------------------*/
31 34
32static int tda18271_ir_cal_init(struct dvb_frontend *fe) 35static int tda18271_ir_cal_init(struct dvb_frontend *fe)
@@ -936,8 +939,24 @@ fail:
936 939
937static int tda18271_release(struct dvb_frontend *fe) 940static int tda18271_release(struct dvb_frontend *fe)
938{ 941{
939 kfree(fe->tuner_priv); 942 struct tda18271_priv *priv = fe->tuner_priv;
943
944 mutex_lock(&tda18271_list_mutex);
945
946 priv->count--;
947
948 if (!priv->count) {
949 tda_dbg("destroying instance @ %d-%04x\n",
950 i2c_adapter_id(priv->i2c_adap),
951 priv->i2c_addr);
952 list_del(&priv->tda18271_list);
953
954 kfree(priv);
955 }
956 mutex_unlock(&tda18271_list_mutex);
957
940 fe->tuner_priv = NULL; 958 fe->tuner_priv = NULL;
959
941 return 0; 960 return 0;
942} 961}
943 962
@@ -1071,43 +1090,73 @@ struct dvb_frontend *tda18271_attach(struct dvb_frontend *fe, u8 addr,
1071 struct tda18271_config *cfg) 1090 struct tda18271_config *cfg)
1072{ 1091{
1073 struct tda18271_priv *priv = NULL; 1092 struct tda18271_priv *priv = NULL;
1093 int state_found = 0;
1094
1095 mutex_lock(&tda18271_list_mutex);
1096
1097 list_for_each_entry(priv, &tda18271_list, tda18271_list) {
1098 if ((i2c_adapter_id(priv->i2c_adap) == i2c_adapter_id(i2c)) &&
1099 (priv->i2c_addr == addr)) {
1100 tda_dbg("attaching existing tuner @ %d-%04x\n",
1101 i2c_adapter_id(priv->i2c_adap),
1102 priv->i2c_addr);
1103 priv->count++;
1104 fe->tuner_priv = priv;
1105 state_found = 1;
1106 /* allow dvb driver to override i2c gate setting */
1107 if ((cfg) && (cfg->gate != TDA18271_GATE_ANALOG))
1108 priv->gate = cfg->gate;
1109 break;
1110 }
1111 }
1112 if (state_found == 0) {
1113 tda_dbg("creating new tuner instance @ %d-%04x\n",
1114 i2c_adapter_id(i2c), addr);
1115
1116 priv = kzalloc(sizeof(struct tda18271_priv), GFP_KERNEL);
1117 if (priv == NULL) {
1118 mutex_unlock(&tda18271_list_mutex);
1119 return NULL;
1120 }
1074 1121
1075 priv = kzalloc(sizeof(struct tda18271_priv), GFP_KERNEL); 1122 priv->i2c_addr = addr;
1076 if (priv == NULL) 1123 priv->i2c_adap = i2c;
1077 return NULL; 1124 priv->gate = (cfg) ? cfg->gate : TDA18271_GATE_AUTO;
1125 priv->cal_initialized = false;
1126 mutex_init(&priv->lock);
1127 priv->count++;
1078 1128
1079 priv->i2c_addr = addr; 1129 fe->tuner_priv = priv;
1080 priv->i2c_adap = i2c;
1081 priv->gate = (cfg) ? cfg->gate : TDA18271_GATE_AUTO;
1082 priv->cal_initialized = false;
1083 mutex_init(&priv->lock);
1084 1130
1085 fe->tuner_priv = priv; 1131 list_add_tail(&priv->tda18271_list, &tda18271_list);
1086 1132
1087 if (tda18271_get_id(fe) < 0) 1133 if (tda18271_get_id(fe) < 0)
1088 goto fail; 1134 goto fail;
1089 1135
1090 if (tda18271_assign_map_layout(fe) < 0) 1136 if (tda18271_assign_map_layout(fe) < 0)
1091 goto fail; 1137 goto fail;
1092 1138
1093 memcpy(&fe->ops.tuner_ops, &tda18271_tuner_ops, 1139 mutex_lock(&priv->lock);
1094 sizeof(struct dvb_tuner_ops)); 1140 tda18271_init_regs(fe);
1141 mutex_unlock(&priv->lock);
1142 }
1095 1143
1096 /* override default std map with values in config struct */ 1144 /* override default std map with values in config struct */
1097 if ((cfg) && (cfg->std_map)) 1145 if ((cfg) && (cfg->std_map))
1098 tda18271_update_std_map(fe, cfg->std_map); 1146 tda18271_update_std_map(fe, cfg->std_map);
1099 1147
1100 if (tda18271_debug & DBG_MAP) 1148 mutex_unlock(&tda18271_list_mutex);
1101 tda18271_dump_std_map(fe);
1102
1103 mutex_lock(&priv->lock);
1104 1149
1105 tda18271_init_regs(fe); 1150 memcpy(&fe->ops.tuner_ops, &tda18271_tuner_ops,
1151 sizeof(struct dvb_tuner_ops));
1106 1152
1107 mutex_unlock(&priv->lock); 1153 if (tda18271_debug & DBG_MAP)
1154 tda18271_dump_std_map(fe);
1108 1155
1109 return fe; 1156 return fe;
1110fail: 1157fail:
1158 mutex_unlock(&tda18271_list_mutex);
1159
1111 tda18271_release(fe); 1160 tda18271_release(fe);
1112 return NULL; 1161 return NULL;
1113} 1162}
diff --git a/drivers/media/dvb/frontends/tda18271-priv.h b/drivers/media/dvb/frontends/tda18271-priv.h
index af89cfab0066..5c04d63ae849 100644
--- a/drivers/media/dvb/frontends/tda18271-priv.h
+++ b/drivers/media/dvb/frontends/tda18271-priv.h
@@ -102,10 +102,13 @@ struct tda18271_priv {
102 struct i2c_adapter *i2c_adap; 102 struct i2c_adapter *i2c_adap;
103 unsigned char tda18271_regs[TDA18271_NUM_REGS]; 103 unsigned char tda18271_regs[TDA18271_NUM_REGS];
104 104
105 struct list_head tda18271_list;
106
105 enum tda18271_mode mode; 107 enum tda18271_mode mode;
106 enum tda18271_i2c_gate gate; 108 enum tda18271_i2c_gate gate;
107 enum tda18271_ver id; 109 enum tda18271_ver id;
108 110
111 unsigned int count;
109 unsigned int tm_rfcal; 112 unsigned int tm_rfcal;
110 unsigned int cal_initialized:1; 113 unsigned int cal_initialized:1;
111 114
diff --git a/drivers/media/video/tda8290.c b/drivers/media/video/tda8290.c
index eab530708a49..4ac7c0438896 100644
--- a/drivers/media/video/tda8290.c
+++ b/drivers/media/video/tda8290.c
@@ -502,8 +502,13 @@ static void tda8290_init_tuner(struct dvb_frontend *fe)
502 502
503static void tda829x_release(struct dvb_frontend *fe) 503static void tda829x_release(struct dvb_frontend *fe)
504{ 504{
505 if (fe->ops.tuner_ops.release) 505 struct tda8290_priv *priv = fe->analog_demod_priv;
506 fe->ops.tuner_ops.release(fe); 506
507 /* dont try to release the tuner
508 * if we didn't attach it from this module */
509 if ((priv->ver > TDA8290) && (priv->ver > TDA8295))
510 if (fe->ops.tuner_ops.release)
511 fe->ops.tuner_ops.release(fe);
507 512
508 kfree(fe->analog_demod_priv); 513 kfree(fe->analog_demod_priv);
509 fe->analog_demod_priv = NULL; 514 fe->analog_demod_priv = NULL;