From: Stefan Ringel <[email protected]>
Signed-off-by: Stefan Ringel <[email protected]>
---
drivers/media/common/tuners/mt2063.c | 225 ++++++++++++----------------------
1 files changed, 76 insertions(+), 149 deletions(-)
diff --git a/drivers/media/common/tuners/mt2063.c
b/drivers/media/common/tuners/mt2063.c
index 8cc58a1..452c517 100644
--- a/drivers/media/common/tuners/mt2063.c
+++ b/drivers/media/common/tuners/mt2063.c
@@ -172,16 +172,91 @@ static int mt2063_set_mode(struct mt2063_state *state,
enum mt2063_delsys Mode)
return 0;
}
+#define MT2063_IF1 1510000
+#define MT2063_OSC 16000
+static int mt2063_tune(struct mt2063_state *state)
+{
+ u32 f_lo1, f_lo2;
+ u32 div1, num1, div2;
+ u32 num2;
+ bool lock = false;
+ dprintk(1, "\n");
/*
+ * it use ClearTune in auto mode, so it doesn't set ClearTune RF Band.
+ *
+ * first IF Filter Center frequency (f_if1) is static setted to 1510 MHz
+ * the reference osc is always 16 MHz
+ *
+ * f_if1 = (f_ref / 8) * (FIFFC + 640)
+ *
+ * f_if2_of = (f_if1 (f_ref / 64)) - ( 8 * FIFFC) - 4992
*
+ * f_lo1 = f_in + f_if1
+ *
+ * f_lo2 = f_lo1 - f_in - f_if2
*
*/
-
+ f_lo1 = state->frequency + MT2063_IF1;
+ /* rounding it to a multiple of 250 kHz */
+ f_lo1 = (f_lo1 / 250) * 250;
+
+ f_lo2 = f_lo1 - state->frequency - state->if2;
+ /* rounding it to a multiple of 50 kHz */
+ f_lo2 = ((f_lo2 + 25) / 50) * 50;
+
+ /* TODO: spuck check */
+
+ /* f_lo1 = 16MHz * (div1 + num1/64) */
+ num1 = f_lo1 / (MT2063_OSC / 64);
+ div1 = num1 / 64;
+ num1 &= 0x3f;
+
+ /* f_lo2 = 16MHz * (div2 + num2/8192) */
+ num2 = f_lo2 * 64 / (MT2063_OSC / 128);
+ div2 = num2 / 8192;
+ num2 &= 0x1fff;
+
+ state->frequency = f_lo1 - f_lo2 - state->if2;
+
+ dprintk(2, "Input frequency: %d kHz\n", state->frequency);
+ dprintk(2, "first IF Filter central frequency: %d kHz\n", 1510000);
+ dprintk(2, "IF Output frequency: %d kHz\n", state->if2);
+ dprintk(2, "LO1 frequency: %d kHz\n", f_lo1);
+ dprintk(2, "LO1 div: %d, 0x%02x\n", div1, div1);
+ dprintk(2, "LO1 num: %d/64, 0x%02x\n", num1, num1);
+ dprintk(2, "LO2 frequency: %d kHz\n", f_lo2);
+ dprintk(2, "LO2 div: %d, 0x%02x\n", div2, div2);
+ dprintk(2, "LO2 num: %d/8192, 0x%04x\n", num2, num2);
+
+ /* set first IF filter center frequency */
+ mt2063_write(state, MT2063_REG_FIFFC, 115);
+
+ /* set LO1 */
+ mt2063_write(state, MT2063_REG_LO1CQ_1, (div1 & 0xff));
+ mt2063_write(state, MT2063_REG_LO1CQ_2, (num1 & 0x3f));
+ /* set LO2, the lastest value with reset */
+ mt2063_write(state, MT2063_REG_LO2CQ_1, (((div2 & 0x7f) << 1) |
+ ((num2 & 0x1000) >> 12)));
+ mt2063_write(state, MT2063_REG_LO2CQ_2, ((num2 & 0x0ff0) >> 4));
+ mt2063_write(state, MT2063_REG_LO2CQ_3, ( 0xe0 | (num2 & 0x000f)));
+
+ /* wait util it's lock */
do {
+ u8 status;
+ /* read LO status bit */
+ mt2063_read(state, MT2063_REG_LO_STATUS, &status);
+
+ if (state->tuner_id == MT2063_B0) {
+ if ((status & 0xc0) == 0xc0)
+ lock = true;
+ } else {
+ if ((status & 0x88) == 0x88)
+ lock = true;
}
+ } while (!lock);
return 0;
}
@@ -207,165 +282,17 @@ static int mt2063_set_mode(struct mt2063_state *state,
enum mt2063_delsys Mode)
{
-/*
- * MT2063_Tune() - Change the tuner's tuned frequency to RFin.
- */
-static u32 MT2063_Tune(struct mt2063_state *state, u32 f_in)
-{ /* RF input center frequency */
-
- u32 status = 0;
- u32 LO1; /* 1st LO register value */
- u32 Num1; /* Numerator for LO1 reg. value */
- u32 f_IF1; /* 1st IF requested */
- u32 LO2; /* 2nd LO register value */
- u32 Num2; /* Numerator for LO2 reg. value */
- u32 ofLO1, ofLO2; /* last time's LO frequencies */
- u8 fiffc = 0x80; /* FIFF center freq from tuner */
- u32 fiffof; /* Offset from FIFF center freq */
- const u8 LO1LK = 0x80; /* Mask for LO1 Lock bit */
- u8 LO2LK = 0x08; /* Mask for LO2 Lock bit */
- u8 val;
- u32 RFBand;
- dprintk(2, "\n");
- /* Check the input and output frequency ranges */
- if ((f_in < MT2063_MIN_FIN_FREQ) || (f_in > MT2063_MAX_FIN_FREQ))
- return -EINVAL;
-
- if ((state->AS_Data.f_out < MT2063_MIN_FOUT_FREQ)
- || (state->AS_Data.f_out > MT2063_MAX_FOUT_FREQ))
- return -EINVAL;
- /*
- * Save original LO1 and LO2 register values
- */
- ofLO1 = state->AS_Data.f_LO1;
- ofLO2 = state->AS_Data.f_LO2;
- /*
- * Find and set RF Band setting
- */
- if (state->ctfilt_sw == 1) {
- val = (state->reg[MT2063_REG_CTUNE_CTRL] | 0x08);
- if (state->reg[MT2063_REG_CTUNE_CTRL] != val) {
- status |=
- mt2063_setreg(state, MT2063_REG_CTUNE_CTRL, val);
- }
- val = state->reg[MT2063_REG_CTUNE_OV];
- state->reg[MT2063_REG_CTUNE_OV] =
- (u8) ((state->reg[MT2063_REG_CTUNE_OV] & ~0x1F)
- | RFBand);
- if (state->reg[MT2063_REG_CTUNE_OV] != val) {
- status |=
- mt2063_setreg(state, MT2063_REG_CTUNE_OV, val);
}
}
- /*
- * Read the FIFF Center Frequency from the tuner
- */
- if (status >= 0) {
- status |=
- mt2063_read(state,
- MT2063_REG_FIFFC,
- &state->reg[MT2063_REG_FIFFC], 1);
- fiffc = state->reg[MT2063_REG_FIFFC];
- }
- /*
- * Assign in the requested values
- */
- state->AS_Data.f_in = f_in;
- /*
- * Check the upconverter and downconverter frequency ranges
- */
- if ((state->AS_Data.f_LO1 < MT2063_MIN_UPC_FREQ)
- || (state->AS_Data.f_LO1 > MT2063_MAX_UPC_FREQ))
- status |= MT2063_UPC_RANGE;
- if ((state->AS_Data.f_LO2 < MT2063_MIN_DNC_FREQ)
- || (state->AS_Data.f_LO2 > MT2063_MAX_DNC_FREQ))
- status |= MT2063_DNC_RANGE;
- /* LO2 Lock bit was in a different place for B0 version */
- if (state->tuner_id == MT2063_B0)
- LO2LK = 0x40;
- /*
- * If we have the same LO frequencies and we're already locked,
- * then skip re-programming the LO registers.
- */
- if ((ofLO1 != state->AS_Data.f_LO1)
- || (ofLO2 != state->AS_Data.f_LO2)
- || ((state->reg[MT2063_REG_LO_STATUS] & (LO1LK | LO2LK)) !=
- (LO1LK | LO2LK))) {
- /*
- * Calculate the FIFFOF register value
- *
- * IF1_Actual
- * FIFFOF = ------------ - 8 * FIFFC - 4992
- * f_ref/64
- */
- fiffof =
- (state->AS_Data.f_LO1 -
- f_in) / (state->AS_Data.f_ref / 64) - 8 * (u32) fiffc -
- 4992;
- if (fiffof > 0xFF)
- fiffof = 0xFF;
-
- /*
- * Place all of the calculated values into the local tuner
- * register fields.
- */
- if (status >= 0) {
- state->reg[MT2063_REG_LO1CQ_1] = (u8) (LO1 & 0xFF);
/* DIV1q */
- state->reg[MT2063_REG_LO1CQ_2] = (u8) (Num1 & 0x3F);
/* NUM1q */
- state->reg[MT2063_REG_LO2CQ_1] = (u8) (((LO2 & 0x7F) <<
1) /* DIV2q */
- |(Num2 >>
12)); /* NUM2q (hi) */
- state->reg[MT2063_REG_LO2CQ_2] = (u8) ((Num2 & 0x0FF0)
>> 4); /* NUM2q (mid) */
- state->reg[MT2063_REG_LO2CQ_3] = (u8) (0xE0 | (Num2 &
0x000F)); /* NUM2q (lo) */
-
- /*
- * Now write out the computed register values
- * IMPORTANT: There is a required order for writing
- * (0x05 must follow all the others).
- */
- status |= mt2063_write(state, MT2063_REG_LO1CQ_1,
&state->reg[MT2063_REG_LO1CQ_1], 5); /* 0x01 - 0x05 */
- if (state->tuner_id == MT2063_B0) {
- /* Re-write the one-shot bits to trigger the
tune operation */
- status |= mt2063_write(state,
MT2063_REG_LO2CQ_3, &state->reg[MT2063_REG_LO2CQ_3], 1); /* 0x05 */
- }
- /* Write out the FIFF offset only if it's changing */
- if (state->reg[MT2063_REG_FIFF_OFFSET] !=
- (u8) fiffof) {
- state->reg[MT2063_REG_FIFF_OFFSET] =
- (u8) fiffof;
- status |=
- mt2063_write(state,
- MT2063_REG_FIFF_OFFSET,
- &state->
- reg[MT2063_REG_FIFF_OFFSET],
- 1);
- }
- }
- /*
- * Check for LO's locking
- */
-
- if (status < 0)
- return status;
- status = mt2063_lockStatus(state);
- if (status < 0)
- return status;
- if (!status)
- return -EINVAL; /* Couldn't lock */
- /*
- * If we locked OK, assign calculated data to mt2063_state
structure
- */
- state->f_IF1_actual = state->AS_Data.f_LO1 - f_in;
- }
- return status;
}
static int mt2063_init(struct dvb_frontend *fe)
--
1.7.7.6
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html