[media] cx18: Make RF analog TV work for newer HVR-1600 models with silicon tuners

A previous changes which added the newer model HVR-1600's and DTV support for
them, neglected to add RF analog TV for them.  Fix RF analog TV for the newer
HVR-1600's which have a worldwide analog tuner assembly with a TDA18271 tuner
and TDA8295 demodulator.

Thanks go to Jeff Campbell and Mike Bradley for reproting the problem, and
also to Mike Bradley for doing a lot of the legwork to figure out the tuner
reset GPIO line, the demodulator I2C address, and that the GPIOs have to be
reinitialized after a cardtype switch.

Reported-by: Jeff Campbell <jac1dlists@gmail.com>
Tested-by: Andy Walls <awalls@md.metrocast.net>
Signed-off-by: Andy Walls <awalls@md.metrocast.net>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
diff --git a/drivers/media/video/cx18/Kconfig b/drivers/media/video/cx18/Kconfig
index d9d2f6a..d788ad6 100644
--- a/drivers/media/video/cx18/Kconfig
+++ b/drivers/media/video/cx18/Kconfig
@@ -9,6 +9,9 @@
 	select VIDEO_CS5345
 	select DVB_S5H1409 if !DVB_FE_CUSTOMISE
 	select MEDIA_TUNER_MXL5005S if !MEDIA_TUNER_CUSTOMISE
+	select DVB_S5H1411 if !DVB_FE_CUSTOMISE
+	select MEDIA_TUNER_TDA18271 if !MEDIA_TUNER_CUSTOMISE
+	select MEDIA_TUNER_TDA8290 if !MEDIA_TUNER_CUSTOMISE
 	---help---
 	  This is a video4linux driver for Conexant cx23418 based
 	  PCI combo video recorder devices.
diff --git a/drivers/media/video/cx18/cx18-cards.c b/drivers/media/video/cx18/cx18-cards.c
index 68ad196..c07c849 100644
--- a/drivers/media/video/cx18/cx18-cards.c
+++ b/drivers/media/video/cx18/cx18-cards.c
@@ -39,6 +39,16 @@
 	.tv    = { 0x61, 0x60, I2C_CLIENT_END },
 };
 
+/*
+ * usual i2c tuner addresses to probe with additional demod address for
+ * an NXP TDA8295 at 0x42 (N.B. it can possibly be at 0x4b or 0x4c too).
+ */
+static struct cx18_card_tuner_i2c cx18_i2c_nxp = {
+	.radio = { I2C_CLIENT_END },
+	.demod = { 0x42, 0x43, I2C_CLIENT_END },
+	.tv    = { 0x61, 0x60, I2C_CLIENT_END },
+};
+
 /* Please add new PCI IDs to: http://pci-ids.ucw.cz/
    This keeps the PCI ID database up to date. Note that the entries
    must be added under vendor 0x4444 (Conexant) as subsystem IDs.
@@ -131,15 +141,15 @@
 		.tune_lane = 0,
 		.initial_emrs = 0,
 	},
-	.gpio_init.initial_value = 0x3001,
-	.gpio_init.direction = 0x3001,
+	.gpio_init.initial_value = 0x3801,
+	.gpio_init.direction = 0x3801,
 	.gpio_i2c_slave_reset = {
-		.active_lo_mask = 0x3001,
+		.active_lo_mask = 0x3801,
 		.msecs_asserted = 10,
 		.msecs_recovery = 40,
 		.ir_reset_mask  = 0x0001,
 	},
-	.i2c = &cx18_i2c_std,
+	.i2c = &cx18_i2c_nxp,
 };
 
 static const struct cx18_card cx18_card_hvr1600_samsung = {
diff --git a/drivers/media/video/cx18/cx18-cards.h b/drivers/media/video/cx18/cx18-cards.h
index 3e75006..add7391e 100644
--- a/drivers/media/video/cx18/cx18-cards.h
+++ b/drivers/media/video/cx18/cx18-cards.h
@@ -109,7 +109,7 @@
 
 struct cx18_card_tuner_i2c {
 	unsigned short radio[2];/* radio tuner i2c address to probe */
-	unsigned short demod[2];/* demodulator i2c address to probe */
+	unsigned short demod[3];/* demodulator i2c address to probe */
 	unsigned short tv[4];	/* tv tuner i2c addresses to probe */
 };
 
diff --git a/drivers/media/video/cx18/cx18-driver.c b/drivers/media/video/cx18/cx18-driver.c
index 841ea4e..9e2f870 100644
--- a/drivers/media/video/cx18/cx18-driver.c
+++ b/drivers/media/video/cx18/cx18-driver.c
@@ -423,7 +423,16 @@
 		return;
 
 	/* autodetect tuner standard */
-	if (tv.tuner_formats & V4L2_STD_PAL) {
+#define TVEEPROM_TUNER_FORMAT_ALL (V4L2_STD_B  | V4L2_STD_GH | \
+				   V4L2_STD_MN | \
+				   V4L2_STD_PAL_I | \
+				   V4L2_STD_SECAM_L | V4L2_STD_SECAM_LC | \
+				   V4L2_STD_DK)
+	if ((tv.tuner_formats & TVEEPROM_TUNER_FORMAT_ALL)
+					== TVEEPROM_TUNER_FORMAT_ALL) {
+		CX18_DEBUG_INFO("Worldwide tuner detected\n");
+		cx->std = V4L2_STD_ALL;
+	} else if (tv.tuner_formats & V4L2_STD_PAL) {
 		CX18_DEBUG_INFO("PAL tuner detected\n");
 		cx->std |= V4L2_STD_PAL_BG | V4L2_STD_PAL_H;
 	} else if (tv.tuner_formats & V4L2_STD_NTSC) {
@@ -1001,7 +1010,15 @@
 	if (cx->card->hw_all & CX18_HW_TVEEPROM) {
 		/* Based on the model number the cardtype may be changed.
 		   The PCI IDs are not always reliable. */
+		const struct cx18_card *orig_card = cx->card;
 		cx18_process_eeprom(cx);
+
+		if (cx->card != orig_card) {
+			/* Changed the cardtype; re-reset the I2C chips */
+			cx18_gpio_init(cx);
+			cx18_call_hw(cx, CX18_HW_GPIO_RESET_CTRL,
+					core, reset, (u32) CX18_GPIO_RESET_I2C);
+		}
 	}
 	if (cx->card->comment)
 		CX18_INFO("%s", cx->card->comment);
@@ -1087,6 +1104,8 @@
 	/* The tuner is fixed to the standard. The other inputs (e.g. S-Video)
 	   are not. */
 	cx->tuner_std = cx->std;
+	if (cx->std == V4L2_STD_ALL)
+		cx->std = V4L2_STD_NTSC_M;
 
 	retval = cx18_streams_setup(cx);
 	if (retval) {
@@ -1133,6 +1152,7 @@
 	int fw_retry_count = 3;
 	struct v4l2_frequency vf;
 	struct cx18_open_id fh;
+	v4l2_std_id std;
 
 	fh.cx = cx;
 
@@ -1220,7 +1240,8 @@
 	/* Let the VIDIOC_S_STD ioctl do all the work, keeps the code
 	   in one place. */
 	cx->std++;		/* Force full standard initialization */
-	cx18_s_std(NULL, &fh, &cx->tuner_std);
+	std = (cx->tuner_std == V4L2_STD_ALL) ? V4L2_STD_NTSC_M : cx->tuner_std;
+	cx18_s_std(NULL, &fh, &std);
 	cx18_s_frequency(NULL, &fh, &vf);
 	return 0;
 }