aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGordon Hecker <ghecker@gmx.de>2012-03-14 09:27:30 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2012-03-19 18:40:58 -0400
commitbe4a5e7f0e279b751a23570da583ec41ca32a34f (patch)
tree440ce7e2adbf8b8fb41db5cbad8d654f2eaebe91
parentd3db22e10bd4997d244beee6feea5fa39b2e5b82 (diff)
[media] af9015: fix i2c failures for dual-tuner devices
The i2c failures were caused by enabling both i2c gates at the same time while putting the tuners asleep. This patch removes the init() and sleep() callbacks from the tuner, to prevent frontend.c from calling i2c_gate_ctrl tuner init / sleep i2c_gate_ctrl without holding the lock. tuner init() and sleep() are instead called in frontend init() and sleep(). Signed-off-by: Gordon Hecker <ghecker@gmx.de> Signed-off-by: Antti Palosaari <crope@iki.fi> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
-rw-r--r--drivers/media/dvb/dvb-usb/af9015.c31
-rw-r--r--drivers/media/dvb/dvb-usb/af9015.h2
2 files changed, 33 insertions, 0 deletions
diff --git a/drivers/media/dvb/dvb-usb/af9015.c b/drivers/media/dvb/dvb-usb/af9015.c
index 282a43d648df..9307b4ca4b77 100644
--- a/drivers/media/dvb/dvb-usb/af9015.c
+++ b/drivers/media/dvb/dvb-usb/af9015.c
@@ -1141,7 +1141,18 @@ static int af9015_af9013_init(struct dvb_frontend *fe)
1141 return -EAGAIN; 1141 return -EAGAIN;
1142 1142
1143 ret = priv->init[adap->id](fe); 1143 ret = priv->init[adap->id](fe);
1144 if (ret)
1145 goto err_unlock;
1146
1147 if (priv->tuner_ops_init[adap->id]) {
1148 if (fe->ops.i2c_gate_ctrl)
1149 fe->ops.i2c_gate_ctrl(fe, 1);
1150 ret = priv->tuner_ops_init[adap->id](fe);
1151 if (fe->ops.i2c_gate_ctrl)
1152 fe->ops.i2c_gate_ctrl(fe, 0);
1153 }
1144 1154
1155err_unlock:
1145 mutex_unlock(&adap->dev->usb_mutex); 1156 mutex_unlock(&adap->dev->usb_mutex);
1146 1157
1147 return ret; 1158 return ret;
@@ -1157,8 +1168,19 @@ static int af9015_af9013_sleep(struct dvb_frontend *fe)
1157 if (mutex_lock_interruptible(&adap->dev->usb_mutex)) 1168 if (mutex_lock_interruptible(&adap->dev->usb_mutex))
1158 return -EAGAIN; 1169 return -EAGAIN;
1159 1170
1171 if (priv->tuner_ops_sleep[adap->id]) {
1172 if (fe->ops.i2c_gate_ctrl)
1173 fe->ops.i2c_gate_ctrl(fe, 1);
1174 ret = priv->tuner_ops_sleep[adap->id](fe);
1175 if (fe->ops.i2c_gate_ctrl)
1176 fe->ops.i2c_gate_ctrl(fe, 0);
1177 if (ret)
1178 goto err_unlock;
1179 }
1180
1160 ret = priv->sleep[adap->id](fe); 1181 ret = priv->sleep[adap->id](fe);
1161 1182
1183err_unlock:
1162 mutex_unlock(&adap->dev->usb_mutex); 1184 mutex_unlock(&adap->dev->usb_mutex);
1163 1185
1164 return ret; 1186 return ret;
@@ -1283,6 +1305,7 @@ static struct mxl5007t_config af9015_mxl5007t_config = {
1283static int af9015_tuner_attach(struct dvb_usb_adapter *adap) 1305static int af9015_tuner_attach(struct dvb_usb_adapter *adap)
1284{ 1306{
1285 int ret; 1307 int ret;
1308 struct af9015_state *state = adap->dev->priv;
1286 deb_info("%s:\n", __func__); 1309 deb_info("%s:\n", __func__);
1287 1310
1288 switch (af9015_af9013_config[adap->id].tuner) { 1311 switch (af9015_af9013_config[adap->id].tuner) {
@@ -1340,6 +1363,14 @@ static int af9015_tuner_attach(struct dvb_usb_adapter *adap)
1340 err("Unknown tuner id:%d", 1363 err("Unknown tuner id:%d",
1341 af9015_af9013_config[adap->id].tuner); 1364 af9015_af9013_config[adap->id].tuner);
1342 } 1365 }
1366
1367 state->tuner_ops_sleep[adap->id] =
1368 adap->fe_adap[0].fe->ops.tuner_ops.sleep;
1369 adap->fe_adap[0].fe->ops.tuner_ops.sleep = 0;
1370
1371 state->tuner_ops_init[adap->id] =
1372 adap->fe_adap[0].fe->ops.tuner_ops.init;
1373 adap->fe_adap[0].fe->ops.tuner_ops.init = 0;
1343 return ret; 1374 return ret;
1344} 1375}
1345 1376
diff --git a/drivers/media/dvb/dvb-usb/af9015.h b/drivers/media/dvb/dvb-usb/af9015.h
index f619063fa72f..ee2ec5b8d570 100644
--- a/drivers/media/dvb/dvb-usb/af9015.h
+++ b/drivers/media/dvb/dvb-usb/af9015.h
@@ -108,6 +108,8 @@ struct af9015_state {
108 int (*read_status[2]) (struct dvb_frontend *fe, fe_status_t *status); 108 int (*read_status[2]) (struct dvb_frontend *fe, fe_status_t *status);
109 int (*init[2]) (struct dvb_frontend *fe); 109 int (*init[2]) (struct dvb_frontend *fe);
110 int (*sleep[2]) (struct dvb_frontend *fe); 110 int (*sleep[2]) (struct dvb_frontend *fe);
111 int (*tuner_ops_init[2]) (struct dvb_frontend *fe);
112 int (*tuner_ops_sleep[2]) (struct dvb_frontend *fe);
111}; 113};
112 114
113struct af9015_config { 115struct af9015_config {