V4L/DVB (7262): Add support for xc3028-based boards

This patch adds support for the following saa7134 xc3028 based boards:
132 -> AVerMedia Cardbus TV/Radio (E506R)       [1461:f436]
133 -> AVerMedia Hybrid TV/Radio (A16D)         [1461:f936]
134 -> Avermedia M115                           [1461:a836]
135 -> Compro VideoMate T750                    [185b:c900]

This is based on a original patch thanks to Markus Rechberger that added xc3028
gpio init code for the above boards.

This patch moves saa7134_tuner_callback to saa7134-cards, originally used only
by tda8290 DVB-S boards. The callback was made more generic to support other
tuners.

Currently, it supports both tda8290 and xc2028/xc3028 tuners. Added also the
basis for xc5000 tuner callback.

Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c
index eabc67d..97d9178 100644
--- a/drivers/media/video/saa7134/saa7134-dvb.c
+++ b/drivers/media/video/saa7134/saa7134-dvb.c
@@ -38,6 +38,7 @@
 #include "mt352_priv.h" /* FIXME */
 #include "tda1004x.h"
 #include "nxt200x.h"
+#include "tuner-xc2028.h"
 
 #include "tda10086.h"
 #include "tda826x.h"
@@ -190,6 +191,11 @@
 	.demod_init    = mt352_aver777_init,
 };
 
+static struct mt352_config avermedia_e506r_mt352_dev = {
+	.demod_address   = (0x1e >> 1),
+	.no_tuner        = 1,
+};
+
 /* ==================================================================
  * tda1004x based DVB-T cards, helper functions
  */
@@ -895,6 +901,8 @@
 static int dvb_init(struct saa7134_dev *dev)
 {
 	int ret;
+	int attach_xc3028 = 0;
+
 	/* init struct videobuf_dvb */
 	dev->ts.nr_bufs    = 32;
 	dev->ts.nr_packets = 32*4;
@@ -1142,11 +1150,35 @@
 	case SAA7134_BOARD_MSI_TVANYWHERE_AD11:
 		configure_tda827x_fe(dev, &philips_tiger_s_config);
 		break;
+	case SAA7134_BOARD_AVERMEDIA_CARDBUS_506:
+		dev->dvb.frontend = dvb_attach(mt352_attach,
+					       &avermedia_e506r_mt352_dev,
+					       &dev->i2c_adap);
+		attach_xc3028 = 1;
+		break;
 	default:
 		wprintk("Huh? unknown DVB card?\n");
 		break;
 	}
 
+	if (attach_xc3028) {
+		struct dvb_frontend *fe;
+		struct xc2028_config cfg = {
+			.i2c_adap  = &dev->i2c_adap,
+			.i2c_addr  = 0x61,
+			.video_dev = dev,
+		};
+		fe = dvb_attach(xc2028_attach, dev->dvb.frontend, &cfg);
+		if (!fe) {
+			printk(KERN_ERR "%s/2: xc3028 attach failed\n",
+			       dev->name);
+			dvb_frontend_detach(dev->dvb.frontend);
+			dvb_unregister_frontend(dev->dvb.frontend);
+			dev->dvb.frontend = NULL;
+			return -1;
+		}
+	}
+
 	if (NULL == dev->dvb.frontend) {
 		printk(KERN_ERR "%s/dvb: frontend initialization failed\n", dev->name);
 		return -1;