// SPDX-License-Identifier: GPL-2.0-or-later /* tda18271-common.c - driver for the Philips / NXP TDA18271 silicon tuner
Copyright (C) 2007, 2008 Michael Krufky <mkrufky@linuxtv.org>
*/
#include"tda18271-priv.h"
staticint tda18271_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
{ struct tda18271_priv *priv = fe->tuner_priv; enum tda18271_i2c_gate gate; int ret = 0;
switch (priv->gate) { case TDA18271_GATE_DIGITAL: case TDA18271_GATE_ANALOG:
gate = priv->gate; break; case TDA18271_GATE_AUTO: default: switch (priv->mode) { case TDA18271_DIGITAL:
gate = TDA18271_GATE_DIGITAL; break; case TDA18271_ANALOG: default:
gate = TDA18271_GATE_ANALOG; break;
}
}
switch (gate) { case TDA18271_GATE_ANALOG: if (fe->ops.analog_ops.i2c_gate_ctrl)
ret = fe->ops.analog_ops.i2c_gate_ctrl(fe, enable); break; case TDA18271_GATE_DIGITAL: if (fe->ops.i2c_gate_ctrl)
ret = fe->ops.i2c_gate_ctrl(fe, enable); break; default:
ret = -EINVAL; break;
}
/* read all registers */
ret = i2c_transfer(priv->i2c_props.adap, msg, 2);
tda18271_i2c_gate_ctrl(fe, 0);
if (ret != 2)
tda_err("ERROR: i2c_transfer returned: %d\n", ret);
for (i = 0; i < TDA18271_NUM_REGS; i++) { /* don't update write-only registers */ if ((i != R_EB9) &&
(i != R_EB16) &&
(i != R_EB17) &&
(i != R_EB19) &&
(i != R_EB20))
regs[i] = regdump[i];
}
if (tda18271_debug & DBG_REG)
tda18271_dump_regs(fe, 1);
return (ret == 2 ? 0 : ret);
}
staticint __tda18271_write_regs(struct dvb_frontend *fe, int idx, int len, bool lock_i2c)
{ struct tda18271_priv *priv = fe->tuner_priv; unsignedchar *regs = priv->tda18271_regs; unsignedchar buf[TDA18271_NUM_REGS + 1]; struct i2c_msg msg = { .addr = priv->i2c_props.addr, .flags = 0,
.buf = buf }; int i, ret = 1, max;
BUG_ON((len == 0) || (idx + len > sizeof(buf)));
switch (priv->small_i2c) { case TDA18271_03_BYTE_CHUNK_INIT:
max = 3; break; case TDA18271_08_BYTE_CHUNK_INIT:
max = 8; break; case TDA18271_16_BYTE_CHUNK_INIT:
max = 16; break; case TDA18271_39_BYTE_CHUNK_INIT: default:
max = 39;
}
/* * If lock_i2c is true, it will take the I2C bus for tda18271 private * usage during the entire write ops, as otherwise, bad things could * happen. * During device init, several write operations will happen. So, * tda18271_init_regs controls the I2C lock directly, * disabling lock_i2c here.
*/ if (lock_i2c) {
tda18271_i2c_gate_ctrl(fe, 1);
i2c_lock_bus(priv->i2c_props.adap, I2C_LOCK_SEGMENT);
} while (len) { if (max > len)
max = len;
buf[0] = idx; for (i = 1; i <= max; i++)
buf[i] = regs[idx - 1 + i];
msg.len = max + 1;
/* write registers */
ret = __i2c_transfer(priv->i2c_props.adap, &msg, 1); if (ret != 1) break;
idx += max;
len -= max;
} if (lock_i2c) {
i2c_unlock_bus(priv->i2c_props.adap, I2C_LOCK_SEGMENT);
tda18271_i2c_gate_ctrl(fe, 0);
}
if (ret != 1)
tda_err("ERROR: idx = 0x%x, len = %d, i2c_transfer returned: %d\n",
idx, max, ret);
return (ret == 1 ? 0 : ret);
}
int tda18271_write_regs(struct dvb_frontend *fe, int idx, int len)
{ return __tda18271_write_regs(fe, idx, len, true);
}
tda_dbg("initializing registers for device @ %d-%04x\n",
i2c_adapter_id(priv->i2c_props.adap),
priv->i2c_props.addr);
/* * Don't let any other I2C transfer to happen at adapter during init, * as those could cause bad things
*/
tda18271_i2c_gate_ctrl(fe, 1);
i2c_lock_bus(priv->i2c_props.adap, I2C_LOCK_SEGMENT);
/* initialize registers */ switch (priv->id) { case TDA18271HDC1:
regs[R_ID] = 0x83; break; case TDA18271HDC2:
regs[R_ID] = 0x84; break;
}
int tda18271_set_standby_mode(struct dvb_frontend *fe, int sm, int sm_lt, int sm_xt)
{ struct tda18271_priv *priv = fe->tuner_priv; unsignedchar *regs = priv->tda18271_regs;
int tda18271_calc_main_pll(struct dvb_frontend *fe, u32 freq)
{ /* sets main post divider & divider bytes, but does not write them */ struct tda18271_priv *priv = fe->tuner_priv; unsignedchar *regs = priv->tda18271_regs;
u8 d, pd;
u32 div;
int ret = tda18271_lookup_pll_map(fe, MAIN_PLL, &freq, &pd, &d); if (tda_fail(ret)) goto fail;
int tda18271_calc_cal_pll(struct dvb_frontend *fe, u32 freq)
{ /* sets cal post divider & divider bytes, but does not write them */ struct tda18271_priv *priv = fe->tuner_priv; unsignedchar *regs = priv->tda18271_regs;
u8 d, pd;
u32 div;
int ret = tda18271_lookup_pll_map(fe, CAL_PLL, &freq, &pd, &d); if (tda_fail(ret)) goto fail;
int tda18271_calc_bp_filter(struct dvb_frontend *fe, u32 *freq)
{ /* sets bp filter bits, but does not write them */ struct tda18271_priv *priv = fe->tuner_priv; unsignedchar *regs = priv->tda18271_regs;
u8 val;
int ret = tda18271_lookup_map(fe, BP_FILTER, freq, &val); if (tda_fail(ret)) goto fail;
int tda18271_calc_km(struct dvb_frontend *fe, u32 *freq)
{ /* sets K & M bits, but does not write them */ struct tda18271_priv *priv = fe->tuner_priv; unsignedchar *regs = priv->tda18271_regs;
u8 val;
int ret = tda18271_lookup_map(fe, RF_CAL_KMCO, freq, &val); if (tda_fail(ret)) goto fail;
regs[R_EB13] &= ~0x7c; /* clear k & m bits */
regs[R_EB13] |= (0x7c & val);
fail: return ret;
}
int tda18271_calc_rf_band(struct dvb_frontend *fe, u32 *freq)
{ /* sets rf band bits, but does not write them */ struct tda18271_priv *priv = fe->tuner_priv; unsignedchar *regs = priv->tda18271_regs;
u8 val;
int ret = tda18271_lookup_map(fe, RF_BAND, freq, &val); if (tda_fail(ret)) goto fail;
int tda18271_calc_gain_taper(struct dvb_frontend *fe, u32 *freq)
{ /* sets gain taper bits, but does not write them */ struct tda18271_priv *priv = fe->tuner_priv; unsignedchar *regs = priv->tda18271_regs;
u8 val;
int ret = tda18271_lookup_map(fe, GAIN_TAPER, freq, &val); if (tda_fail(ret)) goto fail;
int tda18271_calc_ir_measure(struct dvb_frontend *fe, u32 *freq)
{ /* sets IR Meas bits, but does not write them */ struct tda18271_priv *priv = fe->tuner_priv; unsignedchar *regs = priv->tda18271_regs;
u8 val;
int ret = tda18271_lookup_map(fe, IR_MEASURE, freq, &val); if (tda_fail(ret)) goto fail;
int tda18271_calc_rf_cal(struct dvb_frontend *fe, u32 *freq)
{ /* sets rf cal byte (RFC_Cprog), but does not write it */ struct tda18271_priv *priv = fe->tuner_priv; unsignedchar *regs = priv->tda18271_regs;
u8 val;
int ret = tda18271_lookup_map(fe, RF_CAL, freq, &val); /* The TDA18271HD/C1 rf_cal map lookup is expected to go out of range * for frequencies above 61.1 MHz. In these cases, the internal RF * tracking filters calibration mechanism is used. * * There is no need to warn the user about this.
*/ if (ret < 0) goto fail;
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.