From: Stefan Ringel <linuxtv@xxxxxxxxxxxxxxx> Signed-off-by: Stefan Ringel <linuxtv@xxxxxxxxxxxxxxx> --- 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 majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html