#define dprintk(level, fmt, arg...) do { \ if (debug >= level) \
printk(KERN_DEBUG "mt2063 %s: " fmt, __func__, ## arg); \
} while (0)
/* positive error codes used internally */
/* Info: Unavoidable LO-related spur may be present in the output */ #define MT2063_SPUR_PRESENT_ERR (0x00800000)
/* Info: Mask of bits used for # of LO-related spurs that were avoided during tuning */ #define MT2063_SPUR_CNT_MASK (0x001f0000) #define MT2063_SPUR_SHIFT (16)
/* Info: Upconverter frequency is out of range (may be reason for MT_UPC_UNLOCK) */ #define MT2063_UPC_RANGE (0x04000000)
/* Info: Downconverter frequency is out of range (may be reason for MT_DPC_UNLOCK) */ #define MT2063_DNC_RANGE (0x08000000)
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 1);
ret = i2c_transfer(state->i2c, &msg, 1); if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 0);
if (ret < 0)
printk(KERN_ERR "%s error ret=%d\n", __func__, ret);
status = mt2063_write(state, reg, &val, 1); if (status < 0) return status;
state->reg[reg] = val;
return0;
}
/* *mt2063_read-ReaddatafromtheI2Cbus
*/ staticint mt2063_read(struct mt2063_state *state,
u8 subAddress, u8 *pData, u32 cnt)
{ int status = 0; /* Status to be returned */ struct dvb_frontend *fe = state->frontend;
u32 i = 0;
/* Check for a node in the free list */ if (pAS_Info->freeZones != NULL) { /* Use one from the free list */
pNode = pAS_Info->freeZones;
pAS_Info->freeZones = pNode->next_;
} else { /* Grab a node from the array */
pNode = &pAS_Info->MT2063_ExclZones[pAS_Info->nZones];
}
if (pPrevNode != NULL) {
pNode->next_ = pPrevNode->next_;
pPrevNode->next_ = pNode;
} else { /* insert at the beginning of the list */
/* See if this zone overlaps the previous */ if ((j > 0) && (tmpMin < zones[j - 1].max_))
zones[j - 1].max_ = tmpMax; else { /* Add new zone */
zones[j].min_ = tmpMin;
zones[j].max_ = tmpMax;
j++;
}
pNode = pNode->next_;
}
/* *Ifthedesiredisokay,returnwithit
*/ if (bDesiredExcluded == 0) return f_Desired;
/* *Ifthedesiredisexcludedandthecenterisokay,returnwithit
*/ if (bZeroExcluded == 0) return f_Center;
/* Find the value closest to 0 (f_Center) */
bestDiff = zones[0].min_; for (i = 0; i < j; i++) { if (abs(zones[i].min_) < abs(bestDiff))
bestDiff = zones[i].min_; if (abs(zones[i].max_) < abs(bestDiff))
bestDiff = zones[i].max_;
}
status |=
((pAS_Info->
nSpursFound << MT2063_SPUR_SHIFT) & MT2063_SPUR_CNT_MASK);
return status;
}
/* *Constantsusedbythetuningalgorithm
*/ #define MT2063_REF_FREQ (16000000UL) /* Reference oscillator Frequency (in Hz) */ #define MT2063_IF1_BW (22000000UL) /* The IF1 filter bandwidth (in Hz) */ #define MT2063_TUNE_STEP_SIZE (50000UL) /* Tune in steps of 50 kHz */ #define MT2063_SPUR_STEP_HZ (250000UL) /* Step size (in Hz) to move IF1 when avoiding spurs */ #define MT2063_ZIF_BW (2000000UL) /* Zero-IF spur-free bandwidth (in Hz) */ #define MT2063_MAX_HARMONICS_1 (15UL) /* Highest intra-tuner LO Spur Harmonic to be avoided */ #define MT2063_MAX_HARMONICS_2 (5UL) /* Highest inter-tuner LO Spur Harmonic to be avoided */ #define MT2063_MIN_LO_SEP (1000000UL) /* Minimum inter-tuner LO frequency separation */ #define MT2063_LO1_FRACN_AVOID (0UL) /* LO1 FracN numerator avoid region (in Hz) */ #define MT2063_LO2_FRACN_AVOID (199999UL) /* LO2 FracN numerator avoid region (in Hz) */ #define MT2063_MIN_FIN_FREQ (44000000UL) /* Minimum input frequency (in Hz) */ #define MT2063_MAX_FIN_FREQ (1100000000UL) /* Maximum input frequency (in Hz) */ #define MT2063_MIN_FOUT_FREQ (36000000UL) /* Minimum output frequency (in Hz) */ #define MT2063_MAX_FOUT_FREQ (57000000UL) /* Maximum output frequency (in Hz) */ #define MT2063_MIN_DNC_FREQ (1293000000UL) /* Minimum LO2 frequency (in Hz) */ #define MT2063_MAX_DNC_FREQ (1614000000UL) /* Maximum LO2 frequency (in Hz) */ #define MT2063_MIN_UPC_FREQ (1396000000UL) /* Minimum LO1 frequency (in Hz) */ #define MT2063_MAX_UPC_FREQ (2750000000UL) /* Maximum LO1 frequency (in Hz) */
if ((state->reg[MT2063_REG_DNC_GAIN] & 0x03) == 0x03) { /* if DNC1 is off */ if ((state->reg[MT2063_REG_VGA_GAIN] & 0x03) == 0x03) /* if DNC2 is off */
*pValue = MT2063_DNC_NONE; else
*pValue = MT2063_DNC_2;
} else { /* DNC1 is on */ if ((state->reg[MT2063_REG_VGA_GAIN] & 0x03) == 0x03) /* if DNC2 is off */
*pValue = MT2063_DNC_1; else
*pValue = MT2063_DNC_BOTH;
} return0;
}
/* *mt2063_set_dnc_output_enable()
*/ static u32 mt2063_set_dnc_output_enable(struct mt2063_state *state, enum MT2063_DNC_Output_Enable nValue)
{ int status = 0; /* Status to be returned */
u8 val = 0;
dprintk(2, "\n");
/* selects, which DNC output is used */ switch (nValue) { case MT2063_DNC_NONE:
val = (state->reg[MT2063_REG_DNC_GAIN] & 0xFC) | 0x03; /* Set DNC1GC=3 */ if (state->reg[MT2063_REG_DNC_GAIN] !=
val)
status |=
mt2063_setreg(state,
MT2063_REG_DNC_GAIN,
val);
val = (state->reg[MT2063_REG_VGA_GAIN] & 0xFC) | 0x03; /* Set DNC2GC=3 */ if (state->reg[MT2063_REG_VGA_GAIN] !=
val)
status |=
mt2063_setreg(state,
MT2063_REG_VGA_GAIN,
val);
val = (state->reg[MT2063_REG_RSVD_20] & ~0x40); /* Set PD2MUX=0 */ if (state->reg[MT2063_REG_RSVD_20] !=
val)
status |=
mt2063_setreg(state,
MT2063_REG_RSVD_20,
val);
break; case MT2063_DNC_1:
val = (state->reg[MT2063_REG_DNC_GAIN] & 0xFC) | (DNC1GC[state->rcvr_mode] & 0x03); /* Set DNC1GC=x */ if (state->reg[MT2063_REG_DNC_GAIN] !=
val)
status |=
mt2063_setreg(state,
MT2063_REG_DNC_GAIN,
val);
val = (state->reg[MT2063_REG_VGA_GAIN] & 0xFC) | 0x03; /* Set DNC2GC=3 */ if (state->reg[MT2063_REG_VGA_GAIN] !=
val)
status |=
mt2063_setreg(state,
MT2063_REG_VGA_GAIN,
val);
val = (state->reg[MT2063_REG_RSVD_20] & ~0x40); /* Set PD2MUX=0 */ if (state->reg[MT2063_REG_RSVD_20] !=
val)
status |=
mt2063_setreg(state,
MT2063_REG_RSVD_20,
val);
break; case MT2063_DNC_2:
val = (state->reg[MT2063_REG_DNC_GAIN] & 0xFC) | 0x03; /* Set DNC1GC=3 */ if (state->reg[MT2063_REG_DNC_GAIN] !=
val)
status |=
mt2063_setreg(state,
MT2063_REG_DNC_GAIN,
val);
val = (state->reg[MT2063_REG_VGA_GAIN] & 0xFC) | (DNC2GC[state->rcvr_mode] & 0x03); /* Set DNC2GC=x */ if (state->reg[MT2063_REG_VGA_GAIN] !=
val)
status |=
mt2063_setreg(state,
MT2063_REG_VGA_GAIN,
val);
val = (state->reg[MT2063_REG_RSVD_20] | 0x40); /* Set PD2MUX=1 */ if (state->reg[MT2063_REG_RSVD_20] !=
val)
status |=
mt2063_setreg(state,
MT2063_REG_RSVD_20,
val);
break; case MT2063_DNC_BOTH:
val = (state->reg[MT2063_REG_DNC_GAIN] & 0xFC) | (DNC1GC[state->rcvr_mode] & 0x03); /* Set DNC1GC=x */ if (state->reg[MT2063_REG_DNC_GAIN] !=
val)
status |=
mt2063_setreg(state,
MT2063_REG_DNC_GAIN,
val);
val = (state->reg[MT2063_REG_VGA_GAIN] & 0xFC) | (DNC2GC[state->rcvr_mode] & 0x03); /* Set DNC2GC=x */ if (state->reg[MT2063_REG_VGA_GAIN] !=
val)
status |=
mt2063_setreg(state,
MT2063_REG_VGA_GAIN,
val);
val = (state->reg[MT2063_REG_RSVD_20] | 0x40); /* Set PD2MUX=1 */ if (state->reg[MT2063_REG_RSVD_20] !=
val)
status |=
mt2063_setreg(state,
MT2063_REG_RSVD_20,
val);
static u32 MT2063_SetReceiverMode(struct mt2063_state *state, enum mt2063_delivery_sys Mode)
{ int status = 0; /* Status to be returned */
u8 val;
u32 longval;
dprintk(2, "\n");
if (Mode >= MT2063_NUM_RCVR_MODES)
status = -ERANGE;
/* RFAGCen */ if (status >= 0) {
val =
(state->
reg[MT2063_REG_PD1_TGT] & ~0x40) | (RFAGCEN[Mode]
? 0x40 : 0x00); if (state->reg[MT2063_REG_PD1_TGT] != val)
status |= mt2063_setreg(state, MT2063_REG_PD1_TGT, val);
}
/* LNARin */ if (status >= 0) {
u8 val = (state->reg[MT2063_REG_CTRL_2C] & ~0x03) |
(LNARIN[Mode] & 0x03); if (state->reg[MT2063_REG_CTRL_2C] != val)
status |= mt2063_setreg(state, MT2063_REG_CTRL_2C, val);
}
/* FIFFQEN and FIFFQ */ if (status >= 0) {
val =
(state->
reg[MT2063_REG_FIFF_CTRL2] & ~0xF0) |
(FIFFQEN[Mode] << 7) | (FIFFQ[Mode] << 4); if (state->reg[MT2063_REG_FIFF_CTRL2] != val) {
status |=
mt2063_setreg(state, MT2063_REG_FIFF_CTRL2, val); /* trigger FIFF calibration, needed after changing FIFFQ */
val =
(state->reg[MT2063_REG_FIFF_CTRL] | 0x01);
status |=
mt2063_setreg(state, MT2063_REG_FIFF_CTRL, val);
val =
(state->
reg[MT2063_REG_FIFF_CTRL] & ~0x01);
status |=
mt2063_setreg(state, MT2063_REG_FIFF_CTRL, val);
}
}
/* DNC1GC & DNC2GC */
status |= mt2063_get_dnc_output_enable(state, &longval);
status |= mt2063_set_dnc_output_enable(state, longval);
/* acLNAmax */ if (status >= 0) {
u8 val = (state->reg[MT2063_REG_LNA_OV] & ~0x1F) |
(ACLNAMAX[Mode] & 0x1F); if (state->reg[MT2063_REG_LNA_OV] != val)
status |= mt2063_setreg(state, MT2063_REG_LNA_OV, val);
}
/* LNATGT */ if (status >= 0) {
u8 val = (state->reg[MT2063_REG_LNA_TGT] & ~0x3F) |
(LNATGT[Mode] & 0x3F); if (state->reg[MT2063_REG_LNA_TGT] != val)
status |= mt2063_setreg(state, MT2063_REG_LNA_TGT, val);
}
/* ACRF */ if (status >= 0) {
u8 val = (state->reg[MT2063_REG_RF_OV] & ~0x1F) |
(ACRFMAX[Mode] & 0x1F); if (state->reg[MT2063_REG_RF_OV] != val)
status |= mt2063_setreg(state, MT2063_REG_RF_OV, val);
}
/* PD1TGT */ if (status >= 0) {
u8 val = (state->reg[MT2063_REG_PD1_TGT] & ~0x3F) |
(PD1TGT[Mode] & 0x3F); if (state->reg[MT2063_REG_PD1_TGT] != val)
status |= mt2063_setreg(state, MT2063_REG_PD1_TGT, val);
}
/* FIFATN */ if (status >= 0) {
u8 val = ACFIFMAX[Mode]; if (state->reg[MT2063_REG_PART_REV] != MT2063_B3 && val > 5)
val = 5;
val = (state->reg[MT2063_REG_FIF_OV] & ~0x1F) |
(val & 0x1F); if (state->reg[MT2063_REG_FIF_OV] != val)
status |= mt2063_setreg(state, MT2063_REG_FIF_OV, val);
}
/* PD2TGT */ if (status >= 0) {
u8 val = (state->reg[MT2063_REG_PD2_TGT] & ~0x3F) |
(PD2TGT[Mode] & 0x3F); if (state->reg[MT2063_REG_PD2_TGT] != val)
status |= mt2063_setreg(state, MT2063_REG_PD2_TGT, val);
}
/* Ignore ATN Overload */ if (status >= 0) {
val = (state->reg[MT2063_REG_LNA_TGT] & ~0x80) |
(RFOVDIS[Mode] ? 0x80 : 0x00); if (state->reg[MT2063_REG_LNA_TGT] != val)
status |= mt2063_setreg(state, MT2063_REG_LNA_TGT, val);
}
/* Ignore FIF Overload */ if (status >= 0) {
val = (state->reg[MT2063_REG_PD1_TGT] & ~0x80) |
(FIFOVDIS[Mode] ? 0x80 : 0x00); if (state->reg[MT2063_REG_PD1_TGT] != val)
status |= mt2063_setreg(state, MT2063_REG_PD1_TGT, val);
}
if (status >= 0) {
state->rcvr_mode = Mode;
dprintk(1, "mt2063 mode changed to %s\n",
mt2063_mode_name[state->rcvr_mode]);
}
/* **FindRFBandsetting
*/
RFBand = 31; /* def when f_in > all */ for (idx = 0; idx < 31; ++idx) { if (state->CTFiltMax[idx] >= f_in) {
RFBand = idx; break;
}
} return RFBand;
}
/* *MT2063_Tune()-Changethetuner'stunedfrequencytoRFin.
*/ static u32 MT2063_Tune(struct mt2063_state *state, u32 f_in)
{ /* RF input center frequency */
int 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;
/* *Checktheupconverteranddownconverterfrequencyranges
*/ 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;
staticconst u8 MT2063B0_defaults[] = { /* Reg, Value */ 0x19, 0x05, 0x1B, 0x1D, 0x1C, 0x1F, 0x1D, 0x0F, 0x1E, 0x3F, 0x1F, 0x0F, 0x20, 0x3F, 0x22, 0x21, 0x23, 0x3F, 0x24, 0x20, 0x25, 0x3F, 0x27, 0xEE, 0x2C, 0x27, /* bit at 0x20 is cleared below */ 0x30, 0x03, 0x2C, 0x07, /* bit at 0x20 is cleared here */ 0x2D, 0x87, 0x2E, 0xAA, 0x28, 0xE1, /* Set the FIFCrst bit here */ 0x28, 0xE0, /* Clear the FIFCrst bit here */ 0x00
};
/* writing 0x05 0xf0 sw-resets all registers, so we write only needed changes */ staticconst u8 MT2063B1_defaults[] = { /* Reg, Value */ 0x05, 0xF0, 0x11, 0x10, /* New Enable AFCsd */ 0x19, 0x05, 0x1A, 0x6C, 0x1B, 0x24, 0x1C, 0x28, 0x1D, 0x8F, 0x1E, 0x14, 0x1F, 0x8F, 0x20, 0x57, 0x22, 0x21, /* New - ver 1.03 */ 0x23, 0x3C, /* New - ver 1.10 */ 0x24, 0x20, /* New - ver 1.03 */ 0x2C, 0x24, /* bit at 0x20 is cleared below */ 0x2D, 0x87, /* FIFFQ=0 */ 0x2F, 0xF3, 0x30, 0x0C, /* New - ver 1.11 */ 0x31, 0x1B, /* New - ver 1.11 */ 0x2C, 0x04, /* bit at 0x20 is cleared here */ 0x28, 0xE1, /* Set the FIFCrst bit here */ 0x28, 0xE0, /* Clear the FIFCrst bit here */ 0x00
};
/* writing 0x05 0xf0 sw-resets all registers, so we write only needed changes */ staticconst u8 MT2063B3_defaults[] = { /* Reg, Value */ 0x05, 0xF0, 0x19, 0x3D, 0x2C, 0x24, /* bit at 0x20 is cleared below */ 0x2C, 0x04, /* bit at 0x20 is cleared here */ 0x28, 0xE1, /* Set the FIFCrst bit here */ 0x28, 0xE0, /* Clear the FIFCrst bit here */ 0x00
};
/* Read the Part/Rev code from the tuner */
status = mt2063_read(state, MT2063_REG_PART_REV,
&state->reg[MT2063_REG_PART_REV], 1); if (status < 0) {
printk(KERN_ERR "Can't read mt2063 part ID\n"); return status;
}
/* Check the part/rev code */ switch (state->reg[MT2063_REG_PART_REV]) { case MT2063_B0:
step = "B0"; break; case MT2063_B1:
step = "B1"; break; case MT2063_B2:
step = "B2"; break; case MT2063_B3:
step = "B3"; break; default:
printk(KERN_ERR "mt2063: Unknown mt2063 device ID (0x%02x)\n",
state->reg[MT2063_REG_PART_REV]); return -ENODEV; /* Wrong tuner Part/Rev code */
}
/* Check the 2nd byte of the Part/Rev code from the tuner */
status = mt2063_read(state, MT2063_REG_RSVD_3B,
&state->reg[MT2063_REG_RSVD_3B], 1);
/* b7 != 0 ==> NOT MT2063 */ if (status < 0 || ((state->reg[MT2063_REG_RSVD_3B] & 0x80) != 0x00)) {
printk(KERN_ERR "mt2063: Unknown part ID (0x%02x%02x)\n",
state->reg[MT2063_REG_PART_REV],
state->reg[MT2063_REG_RSVD_3B]); return -ENODEV; /* Wrong tuner Part/Rev code */
}
printk(KERN_INFO "mt2063: detected a mt2063 %s\n", step);
/* Reset the tuner */
status = mt2063_write(state, MT2063_REG_LO2CQ_3, &all_resets, 1); if (status < 0) return status;
/* change all of the default values that vary from the HW reset values */ /* def = (state->reg[PART_REV] == MT2063_B0) ? MT2063B0_defaults : MT2063B1_defaults; */ switch (state->reg[MT2063_REG_PART_REV]) { case MT2063_B3:
def = MT2063B3_defaults; break;
case MT2063_B1:
def = MT2063B1_defaults; break;
case MT2063_B0:
def = MT2063B0_defaults; break;
default: return -ENODEV;
}
while (status >= 0 && *def) {
u8 reg = *def++;
u8 val = *def++;
status = mt2063_write(state, reg, &val, 1);
} if (status < 0) return status;
status = mt2063_read(state,
MT2063_REG_FIFFC,
&state->reg[MT2063_REG_FIFFC], 1); if (status < 0) return status;
/* Read back all the registers from the tuner */
status = mt2063_read(state,
MT2063_REG_PART_REV,
state->reg, MT2063_REG_END_REGS); if (status < 0) return status;
state->reg[MT2063_REG_CTUNE_CTRL] = 0x0A;
status = mt2063_write(state, MT2063_REG_CTUNE_CTRL,
&state->reg[MT2063_REG_CTUNE_CTRL], 1); if (status < 0) return status;
/* Read the ClearTune filter calibration value */
status = mt2063_read(state, MT2063_REG_FIFFC,
&state->reg[MT2063_REG_FIFFC], 1); if (status < 0) return status;
fcu_osc = state->reg[MT2063_REG_FIFFC];
state->reg[MT2063_REG_CTUNE_CTRL] = 0x00;
status = mt2063_write(state, MT2063_REG_CTUNE_CTRL,
&state->reg[MT2063_REG_CTUNE_CTRL], 1); if (status < 0) return status;
/* Adjust each of the values in the ClearTune filter cross-over table */ for (i = 0; i < 31; i++)
state->CTFiltMax[i] = (state->CTFiltMax[i] / 768) * (fcu_osc + 640);
status = MT2063_SoftwareShutdown(state, 1); if (status < 0) return status;
status = MT2063_ClearPowerMaskBits(state, MT2063_ALL_SD); if (status < 0) return status;
¤ Diese beiden folgenden Angebotsgruppen bietet das Unternehmen0.78Angebot
(Wie Sie bei der Firma Beratungs- und Dienstleistungen beauftragen können 2026-09-30)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.