V4L/DVB (7258): Support DVB-T tuning on the DViCO FusionHDTV DVB-T Pro

Add support for tuning DVB-T channels on DViCO's FusionHDTV DVB-T Pro board.

The IR remote and analog tuner are not supported at this time.

Some changes made by Mauro Chehab to allow merging it with some other xc3028
patches.

Signed-off-by: Chris Pascoe <c.pascoe@itee.uq.edu.au>
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c
index d07286f..1dc70f2 100644
--- a/drivers/media/video/cx88/cx88-cards.c
+++ b/drivers/media/video/cx88/cx88-cards.c
@@ -1543,7 +1543,24 @@
 		       .gpio3  = 0x00000000,
 	       },
 	       .mpeg           = CX88_MPEG_DVB,
-       }
+       },
+       [CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO] = {
+	       .name           = "DViCO FusionHDTV DVB-T PRO",
+	       .tuner_type     = TUNER_ABSENT, /* XXX: Has XC3028 */
+	       .radio_type     = UNSET,
+	       .tuner_addr     = ADDR_UNSET,
+	       .radio_addr     = ADDR_UNSET,
+	       .input          = { {
+		       .type   = CX88_VMUX_COMPOSITE1,
+		       .vmux   = 1,
+		       .gpio0  = 0x000067df,
+		}, {
+		       .type   = CX88_VMUX_SVIDEO,
+		       .vmux   = 2,
+		       .gpio0  = 0x000067df,
+	       } },
+	       .mpeg           = CX88_MPEG_DVB,
+       },
 };
 
 /* ------------------------------------------------------------------ */
@@ -1748,7 +1765,11 @@
 		.subdevice = 0xdb11,
 		.card      = CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS,
 		/* Re-branded DViCO: UltraView DVB-T Plus */
-	},{
+	}, {
+		.subvendor = 0x18ac,
+		.subdevice = 0xdb30,
+		.card      = CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO,
+	}, {
 		.subvendor = 0x17de,
 		.subdevice = 0x0840,
 		.card      = CX88_BOARD_KWORLD_HARDWARE_MPEG_TV_XPERT,
@@ -2009,6 +2030,28 @@
 		CX88_RADIO : 0;
 }
 
+/* ------------------------------------------------------------------- */
+/* some Divco specific stuff                                           */
+static int cx88_dvico_xc2028_callback(void *ptr, int command, int arg)
+{
+	struct cx88_core *core = ptr;
+
+	switch (command) {
+	case XC2028_TUNER_RESET:
+		cx_set(MO_GP0_IO, 0x0200);
+		cx_clear(MO_GP0_IO, 0x02);
+		mdelay(100);
+		cx_set(MO_GP0_IO, 0x02);
+		mdelay(100);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+
 /* ----------------------------------------------------------------------- */
 /* some Geniatech specific stuff                                           */
 
@@ -2098,6 +2141,8 @@
 	case CX88_BOARD_POWERCOLOR_REAL_ANGEL:
 	case CX88_BOARD_GENIATECH_X8000_MT:
 		return cx88_xc3028_geniatech_tuner_callback(priv, command, arg);
+	case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO:
+		return cx88_dvico_xc2028_callback(priv, command, arg);
 	}
 
 	switch (command) {
@@ -2267,6 +2312,7 @@
 	case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1:
 	case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS:
 	case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID:
+	case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO:
 		/* GPIO0:0 is hooked to mt352 reset pin */
 		cx_set(MO_GP0_IO, 0x00000101);
 		cx_clear(MO_GP0_IO, 0x00000001);
@@ -2338,9 +2384,18 @@
 
 		ctl.fname   = XC2028_DEFAULT_FIRMWARE;
 		ctl.max_len = 64;
-		/* FIXME: Those should be device-dependent */
-		ctl.demod = XC3028_FE_OREN538;
-		ctl.mts = 1;
+
+		switch (core->boardnr) {
+		case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO:
+			ctl.scode_table = XC3028_FE_ZARLINK456;
+			break;
+		case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO:
+			ctl.demod = XC3028_FE_OREN538;
+			break;
+		default:
+			ctl.demod = XC3028_FE_OREN538;
+			ctl.mts = 1;
+		}
 
 		xc2028_cfg.tuner = TUNER_XC2028;
 		xc2028_cfg.priv  = &ctl;
diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c
index c786d95..591037d 100644
--- a/drivers/media/video/cx88/cx88-dvb.c
+++ b/drivers/media/video/cx88/cx88-dvb.c
@@ -237,6 +237,19 @@
 	.no_tuner      = 1,
 };
 
+static struct zl10353_config dvico_fusionhdtv_xc3028 = {
+	.demod_address = 0x0f,
+	.if2           = 45600,
+	.no_tuner      = 1,
+};
+
+static struct mt352_config dvico_fusionhdtv_mt352_xc3028 = {
+	.demod_address = 0x0f,
+	.if2 = 4560,
+	.no_tuner = 1,
+	.demod_init = dvico_fusionhdtv_demod_init,
+};
+
 static struct zl10353_config dvico_fusionhdtv_plus_v1_1 = {
 	.demod_address = 0x0f,
 };
@@ -567,6 +580,16 @@
 				   DVB_PLL_THOMSON_FE6600);
 		}
 		break;
+	case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO:
+		dev->dvb.frontend = dvb_attach(zl10353_attach,
+					       &dvico_fusionhdtv_xc3028,
+					       &dev->core->i2c_adap);
+		if (dev->dvb.frontend == NULL)
+			dev->dvb.frontend = dvb_attach(mt352_attach,
+						&dvico_fusionhdtv_mt352_xc3028,
+						&dev->core->i2c_adap);
+		attach_xc3028 = 1;
+		break;
 	case CX88_BOARD_PCHDTV_HD3000:
 		dev->dvb.frontend = dvb_attach(or51132_attach, &pchdtv_hd3000,
 					       &dev->core->i2c_adap);
diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h
index 5145bf2..9df3f19 100644
--- a/drivers/media/video/cx88/cx88.h
+++ b/drivers/media/video/cx88/cx88.h
@@ -216,6 +216,7 @@
 #define CX88_BOARD_WINFAST_TV2000_XP_GLOBAL 61
 #define CX88_BOARD_POWERCOLOR_REAL_ANGEL   62
 #define CX88_BOARD_GENIATECH_X8000_MT      63
+#define CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO 64
 
 enum cx88_itype {
 	CX88_VMUX_COMPOSITE1 = 1,