V4L/DVB (7574): mt312: Add support for zl10313 demod

Add zl10313 support to mt312 driver.
zl10313 uses 10.111MHz xtal.

Signed-off-by: Matthias Schwarzott <zzam@gentoo.org>
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
diff --git a/drivers/media/dvb/frontends/mt312.c b/drivers/media/dvb/frontends/mt312.c
index 1f478c8..e17a361 100644
--- a/drivers/media/dvb/frontends/mt312.c
+++ b/drivers/media/dvb/frontends/mt312.c
@@ -1,7 +1,8 @@
 /*
-    Driver for Zarlink VP310/MT312 Satellite Channel Decoder
+    Driver for Zarlink VP310/MT312/ZL10313 Satellite Channel Decoder
 
     Copyright (C) 2003 Andreas Oberritter <obi@linuxtv.org>
+    Copyright (C) 2008 Matthias Schwarzott <zzam@gentoo.org>
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
@@ -55,6 +56,7 @@
 	} while (0)
 
 #define MT312_PLL_CLK		10000000UL	/* 10 MHz */
+#define MT312_PLL_CLK_10_111	10111000UL	/* 10.111 MHz */
 
 static int mt312_read(struct mt312_state *state, const enum mt312_reg_addr reg,
 		      u8 *buf, const size_t count)
@@ -264,6 +266,32 @@
 			return ret;
 	}
 
+	switch (state->id) {
+	case ID_ZL10313:
+		/* enable ADC */
+		ret = mt312_writereg(state, GPP_CTRL, 0x80);
+		if (ret < 0)
+			return ret;
+
+		/* configure ZL10313 for optimal ADC performance */
+		buf[0] = 0x80;
+		buf[1] = 0xB0;
+		ret = mt312_write(state, HW_CTRL, buf, 2);
+		if (ret < 0)
+			return ret;
+
+		/* enable MPEG output and ADCs */
+		ret = mt312_writereg(state, HW_CTRL, 0x00);
+		if (ret < 0)
+			return ret;
+
+		ret = mt312_writereg(state, MPEG_CTRL, 0x00);
+		if (ret < 0)
+			return ret;
+
+		break;
+	}
+
 	/* SYS_CLK */
 	buf[0] = mt312_div(state->xtal * state->freq_mult * 2, 1000000);
 
@@ -278,7 +306,17 @@
 	if (ret < 0)
 		return ret;
 
-	ret = mt312_writereg(state, OP_CTRL, 0x53);
+	/* different MOCLK polarity */
+	switch (state->id) {
+	case ID_ZL10313:
+		buf[0] = 0x33;
+		break;
+	default:
+		buf[0] = 0x53;
+		break;
+	}
+
+	ret = mt312_writereg(state, OP_CTRL, buf[0]);
 	if (ret < 0)
 		return ret;
 
@@ -552,6 +590,7 @@
 		break;
 
 	case ID_MT312:
+	case ID_ZL10313:
 		break;
 
 	default:
@@ -617,11 +656,29 @@
 {
 	struct mt312_state *state = fe->demodulator_priv;
 
-	if (enable) {
-		return mt312_writereg(state, GPP_CTRL, 0x40);
-	} else {
-		return mt312_writereg(state, GPP_CTRL, 0x00);
+	u8 val = 0x00;
+	int ret;
+
+	switch (state->id) {
+	case ID_ZL10313:
+		ret = mt312_readreg(state, GPP_CTRL, &val);
+		if (ret < 0)
+			goto error;
+
+		/* preserve this bit to not accidently shutdown ADC */
+		val &= 0x80;
+		break;
 	}
+
+	if (enable)
+		val |= 0x40;
+	else
+		val &= ~0x40;
+
+	ret = mt312_writereg(state, GPP_CTRL, val);
+
+error:
+	return ret;
 }
 
 static int mt312_sleep(struct dvb_frontend *fe)
@@ -635,6 +692,18 @@
 	if (ret < 0)
 		return ret;
 
+	if (state->id == ID_ZL10313) {
+		/* reset ADC */
+		ret = mt312_writereg(state, GPP_CTRL, 0x00);
+		if (ret < 0)
+			return ret;
+
+		/* full shutdown of ADCs, mpeg bus tristated */
+		ret = mt312_writereg(state, HW_CTRL, 0x0d);
+		if (ret < 0)
+			return ret;
+	}
+
 	ret = mt312_readreg(state, CONFIG, &config);
 	if (ret < 0)
 		return ret;
@@ -736,8 +805,13 @@
 		state->xtal = MT312_PLL_CLK;
 		state->freq_mult = 6;
 		break;
+	case ID_ZL10313:
+		strcpy(state->frontend.ops.info.name, "Zarlink ZL10313 DVB-S");
+		state->xtal = MT312_PLL_CLK_10_111;
+		state->freq_mult = 9;
+		break;
 	default:
-		printk(KERN_WARNING "Only Zarlink VP310/MT312"
+		printk(KERN_WARNING "Only Zarlink VP310/MT312/ZL10313"
 			" are supported chips.\n");
 		goto error;
 	}
@@ -753,7 +827,7 @@
 module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
 
-MODULE_DESCRIPTION("Zarlink VP310/MT312 DVB-S Demodulator driver");
+MODULE_DESCRIPTION("Zarlink VP310/MT312/ZL10313 DVB-S Demodulator driver");
 MODULE_AUTHOR("Andreas Oberritter <obi@linuxtv.org>");
 MODULE_LICENSE("GPL");
 
diff --git a/drivers/media/dvb/frontends/mt312_priv.h b/drivers/media/dvb/frontends/mt312_priv.h
index 5e0b95b..a3959f9 100644
--- a/drivers/media/dvb/frontends/mt312_priv.h
+++ b/drivers/media/dvb/frontends/mt312_priv.h
@@ -110,6 +110,8 @@
 	VIT_ERRPER_H = 83,
 	VIT_ERRPER_M = 84,
 	VIT_ERRPER_L = 85,
+	HW_CTRL = 84,	/* ZL10313 only */
+	MPEG_CTRL = 85,	/* ZL10313 only */
 	VIT_SETUP = 86,
 	VIT_REF0 = 87,
 	VIT_REF1 = 88,
@@ -156,7 +158,8 @@
 
 enum mt312_model_id {
 	ID_VP310 = 1,
-	ID_MT312 = 3
+	ID_MT312 = 3,
+	ID_ZL10313 = 5,
 };
 
 #endif				/* DVB_FRONTENDS_MT312_PRIV */