V4L/DVB (7136): tda18271: use hybrid_tuner_request_state to manage tuner instances

Convert tda18271 to use the new 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@infradead.org>
diff --git a/drivers/media/dvb/frontends/tda18271-common.c b/drivers/media/dvb/frontends/tda18271-common.c
index bca5709..3949646 100644
--- a/drivers/media/dvb/frontends/tda18271-common.c
+++ b/drivers/media/dvb/frontends/tda18271-common.c
@@ -125,16 +125,16 @@
 	unsigned char buf = 0x00;
 	int ret;
 	struct i2c_msg msg[] = {
-		{ .addr = priv->i2c_addr, .flags = 0,
+		{ .addr = priv->i2c_props.addr, .flags = 0,
 		  .buf = &buf, .len = 1 },
-		{ .addr = priv->i2c_addr, .flags = I2C_M_RD,
+		{ .addr = priv->i2c_props.addr, .flags = I2C_M_RD,
 		  .buf = regs, .len = 16 }
 	};
 
 	tda18271_i2c_gate_ctrl(fe, 1);
 
 	/* read all registers */
-	ret = i2c_transfer(priv->i2c_adap, msg, 2);
+	ret = i2c_transfer(priv->i2c_props.adap, msg, 2);
 
 	tda18271_i2c_gate_ctrl(fe, 0);
 
@@ -155,16 +155,16 @@
 	unsigned char buf = 0x00;
 	int ret, i;
 	struct i2c_msg msg[] = {
-		{ .addr = priv->i2c_addr, .flags = 0,
+		{ .addr = priv->i2c_props.addr, .flags = 0,
 		  .buf = &buf, .len = 1 },
-		{ .addr = priv->i2c_addr, .flags = I2C_M_RD,
+		{ .addr = priv->i2c_props.addr, .flags = I2C_M_RD,
 		  .buf = regdump, .len = TDA18271_NUM_REGS }
 	};
 
 	tda18271_i2c_gate_ctrl(fe, 1);
 
 	/* read all registers */
-	ret = i2c_transfer(priv->i2c_adap, msg, 2);
+	ret = i2c_transfer(priv->i2c_props.adap, msg, 2);
 
 	tda18271_i2c_gate_ctrl(fe, 0);
 
@@ -192,7 +192,7 @@
 	struct tda18271_priv *priv = fe->tuner_priv;
 	unsigned char *regs = priv->tda18271_regs;
 	unsigned char buf[TDA18271_NUM_REGS + 1];
-	struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0,
+	struct i2c_msg msg = { .addr = priv->i2c_props.addr, .flags = 0,
 			       .buf = buf, .len = len + 1 };
 	int i, ret;
 
@@ -205,7 +205,7 @@
 	tda18271_i2c_gate_ctrl(fe, 1);
 
 	/* write registers */
-	ret = i2c_transfer(priv->i2c_adap, &msg, 1);
+	ret = i2c_transfer(priv->i2c_props.adap, &msg, 1);
 
 	tda18271_i2c_gate_ctrl(fe, 0);
 
@@ -223,7 +223,8 @@
 	unsigned char *regs = priv->tda18271_regs;
 
 	tda_dbg("initializing registers for device @ %d-%04x\n",
-		i2c_adapter_id(priv->i2c_adap), priv->i2c_addr);
+		i2c_adapter_id(priv->i2c_props.adap),
+		priv->i2c_props.addr);
 
 	/* initialize registers */
 	switch (priv->id) {
diff --git a/drivers/media/dvb/frontends/tda18271-fe.c b/drivers/media/dvb/frontends/tda18271-fe.c
index dfe72aa..7f7fab7 100644
--- a/drivers/media/dvb/frontends/tda18271-fe.c
+++ b/drivers/media/dvb/frontends/tda18271-fe.c
@@ -31,8 +31,8 @@
 module_param_named(cal, tda18271_cal_on_startup, int, 0644);
 MODULE_PARM_DESC(cal, "perform RF tracking filter calibration on startup");
 
-static LIST_HEAD(tda18271_list);
 static DEFINE_MUTEX(tda18271_list_mutex);
+static LIST_HEAD(hybrid_tuner_instance_list);
 
 /*---------------------------------------------------------------------*/
 
@@ -986,16 +986,9 @@
 
 	mutex_lock(&tda18271_list_mutex);
 
-	priv->count--;
+	if (priv)
+		hybrid_tuner_release_state(priv);
 
-	if (!priv->count) {
-		tda_dbg("destroying instance @ %d-%04x\n",
-			i2c_adapter_id(priv->i2c_adap),
-			priv->i2c_addr);
-		list_del(&priv->tda18271_list);
-
-		kfree(priv);
-	}
 	mutex_unlock(&tda18271_list_mutex);
 
 	fe->tuner_priv = NULL;
@@ -1109,7 +1102,8 @@
 	}
 
 	tda_info("%s detected @ %d-%04x%s\n", name,
-		 i2c_adapter_id(priv->i2c_adap), priv->i2c_addr,
+		 i2c_adapter_id(priv->i2c_props.adap),
+		 priv->i2c_props.addr,
 		 (0 == ret) ? "" : ", device not supported.");
 
 	return ret;
@@ -1136,46 +1130,25 @@
 				     struct tda18271_config *cfg)
 {
 	struct tda18271_priv *priv = NULL;
-	int state_found = 0;
+	int instance;
 
 	mutex_lock(&tda18271_list_mutex);
 
-	list_for_each_entry(priv, &tda18271_list, tda18271_list) {
-		if ((i2c_adapter_id(priv->i2c_adap) == i2c_adapter_id(i2c)) &&
-		    (priv->i2c_addr == addr)) {
-			tda_dbg("attaching existing tuner @ %d-%04x\n",
-				i2c_adapter_id(priv->i2c_adap),
-				priv->i2c_addr);
-			priv->count++;
-			fe->tuner_priv = priv;
-			state_found = 1;
-			/* allow dvb driver to override i2c gate setting */
-			if ((cfg) && (cfg->gate != TDA18271_GATE_ANALOG))
-				priv->gate = cfg->gate;
-			break;
-		}
-	}
-	if (state_found == 0) {
-		tda_dbg("creating new tuner instance @ %d-%04x\n",
-			i2c_adapter_id(i2c), addr);
-
-		priv = kzalloc(sizeof(struct tda18271_priv), GFP_KERNEL);
-		if (priv == NULL) {
-			mutex_unlock(&tda18271_list_mutex);
-			return NULL;
-		}
-
-		priv->i2c_addr = addr;
-		priv->i2c_adap = i2c;
+	instance = hybrid_tuner_request_state(struct tda18271_priv, priv,
+					      hybrid_tuner_instance_list,
+					      i2c, addr, "tda18271");
+	switch (instance) {
+	case 0:
+		goto fail;
+		break;
+	case 1:
+		/* new tuner instance */
 		priv->gate = (cfg) ? cfg->gate : TDA18271_GATE_AUTO;
 		priv->cal_initialized = false;
 		mutex_init(&priv->lock);
-		priv->count++;
 
 		fe->tuner_priv = priv;
 
-		list_add_tail(&priv->tda18271_list, &tda18271_list);
-
 		if (tda18271_get_id(fe) < 0)
 			goto fail;
 
@@ -1189,6 +1162,15 @@
 			tda18271_rf_cal_init(fe);
 
 		mutex_unlock(&priv->lock);
+		break;
+	default:
+		/* existing tuner instance */
+		fe->tuner_priv = priv;
+
+		/* allow dvb driver to override i2c gate setting */
+		if ((cfg) && (cfg->gate != TDA18271_GATE_ANALOG))
+			priv->gate = cfg->gate;
+		break;
 	}
 
 	/* override default std map with values in config struct */
diff --git a/drivers/media/dvb/frontends/tda18271-priv.h b/drivers/media/dvb/frontends/tda18271-priv.h
index 7b939a5..840b180 100644
--- a/drivers/media/dvb/frontends/tda18271-priv.h
+++ b/drivers/media/dvb/frontends/tda18271-priv.h
@@ -24,6 +24,7 @@
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/mutex.h>
+#include "tuner-i2c.h"
 #include "tda18271.h"
 
 #define R_ID     0x00	/* ID byte                */
@@ -98,17 +99,15 @@
 };
 
 struct tda18271_priv {
-	u8 i2c_addr;
-	struct i2c_adapter *i2c_adap;
 	unsigned char tda18271_regs[TDA18271_NUM_REGS];
 
-	struct list_head tda18271_list;
+	struct list_head	hybrid_tuner_instance_list;
+	struct tuner_i2c_props	i2c_props;
 
 	enum tda18271_mode mode;
 	enum tda18271_i2c_gate gate;
 	enum tda18271_ver id;
 
-	unsigned int count;
 	unsigned int tm_rfcal;
 	unsigned int cal_initialized:1;