[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>
diff --git a/drivers/media/dvb/dvb-usb/af9015.c b/drivers/media/dvb/dvb-usb/af9015.c
index 282a43d..9307b4ca 100644
--- a/drivers/media/dvb/dvb-usb/af9015.c
+++ b/drivers/media/dvb/dvb-usb/af9015.c
@@ -1141,7 +1141,18 @@
 		return -EAGAIN;
 
 	ret = priv->init[adap->id](fe);
+	if (ret)
+		goto err_unlock;
 
+	if (priv->tuner_ops_init[adap->id]) {
+		if (fe->ops.i2c_gate_ctrl)
+			fe->ops.i2c_gate_ctrl(fe, 1);
+		ret = priv->tuner_ops_init[adap->id](fe);
+		if (fe->ops.i2c_gate_ctrl)
+			fe->ops.i2c_gate_ctrl(fe, 0);
+	}
+
+err_unlock:
 	mutex_unlock(&adap->dev->usb_mutex);
 
 	return ret;
@@ -1157,8 +1168,19 @@
 	if (mutex_lock_interruptible(&adap->dev->usb_mutex))
 		return -EAGAIN;
 
+	if (priv->tuner_ops_sleep[adap->id]) {
+		if (fe->ops.i2c_gate_ctrl)
+			fe->ops.i2c_gate_ctrl(fe, 1);
+		ret = priv->tuner_ops_sleep[adap->id](fe);
+		if (fe->ops.i2c_gate_ctrl)
+			fe->ops.i2c_gate_ctrl(fe, 0);
+		if (ret)
+			goto err_unlock;
+	}
+
 	ret = priv->sleep[adap->id](fe);
 
+err_unlock:
 	mutex_unlock(&adap->dev->usb_mutex);
 
 	return ret;
@@ -1283,6 +1305,7 @@
 static int af9015_tuner_attach(struct dvb_usb_adapter *adap)
 {
 	int ret;
+	struct af9015_state *state = adap->dev->priv;
 	deb_info("%s:\n", __func__);
 
 	switch (af9015_af9013_config[adap->id].tuner) {
@@ -1340,6 +1363,14 @@
 		err("Unknown tuner id:%d",
 			af9015_af9013_config[adap->id].tuner);
 	}
+
+	state->tuner_ops_sleep[adap->id] =
+				adap->fe_adap[0].fe->ops.tuner_ops.sleep;
+	adap->fe_adap[0].fe->ops.tuner_ops.sleep = 0;
+
+	state->tuner_ops_init[adap->id] =
+				adap->fe_adap[0].fe->ops.tuner_ops.init;
+	adap->fe_adap[0].fe->ops.tuner_ops.init = 0;
 	return ret;
 }