18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci    tda18271-common.c - driver for the Philips / NXP TDA18271 silicon tuner
48c2ecf20Sopenharmony_ci
58c2ecf20Sopenharmony_ci    Copyright (C) 2007, 2008 Michael Krufky <mkrufky@linuxtv.org>
68c2ecf20Sopenharmony_ci
78c2ecf20Sopenharmony_ci*/
88c2ecf20Sopenharmony_ci
98c2ecf20Sopenharmony_ci#include "tda18271-priv.h"
108c2ecf20Sopenharmony_ci
118c2ecf20Sopenharmony_cistatic int tda18271_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
128c2ecf20Sopenharmony_ci{
138c2ecf20Sopenharmony_ci	struct tda18271_priv *priv = fe->tuner_priv;
148c2ecf20Sopenharmony_ci	enum tda18271_i2c_gate gate;
158c2ecf20Sopenharmony_ci	int ret = 0;
168c2ecf20Sopenharmony_ci
178c2ecf20Sopenharmony_ci	switch (priv->gate) {
188c2ecf20Sopenharmony_ci	case TDA18271_GATE_DIGITAL:
198c2ecf20Sopenharmony_ci	case TDA18271_GATE_ANALOG:
208c2ecf20Sopenharmony_ci		gate = priv->gate;
218c2ecf20Sopenharmony_ci		break;
228c2ecf20Sopenharmony_ci	case TDA18271_GATE_AUTO:
238c2ecf20Sopenharmony_ci	default:
248c2ecf20Sopenharmony_ci		switch (priv->mode) {
258c2ecf20Sopenharmony_ci		case TDA18271_DIGITAL:
268c2ecf20Sopenharmony_ci			gate = TDA18271_GATE_DIGITAL;
278c2ecf20Sopenharmony_ci			break;
288c2ecf20Sopenharmony_ci		case TDA18271_ANALOG:
298c2ecf20Sopenharmony_ci		default:
308c2ecf20Sopenharmony_ci			gate = TDA18271_GATE_ANALOG;
318c2ecf20Sopenharmony_ci			break;
328c2ecf20Sopenharmony_ci		}
338c2ecf20Sopenharmony_ci	}
348c2ecf20Sopenharmony_ci
358c2ecf20Sopenharmony_ci	switch (gate) {
368c2ecf20Sopenharmony_ci	case TDA18271_GATE_ANALOG:
378c2ecf20Sopenharmony_ci		if (fe->ops.analog_ops.i2c_gate_ctrl)
388c2ecf20Sopenharmony_ci			ret = fe->ops.analog_ops.i2c_gate_ctrl(fe, enable);
398c2ecf20Sopenharmony_ci		break;
408c2ecf20Sopenharmony_ci	case TDA18271_GATE_DIGITAL:
418c2ecf20Sopenharmony_ci		if (fe->ops.i2c_gate_ctrl)
428c2ecf20Sopenharmony_ci			ret = fe->ops.i2c_gate_ctrl(fe, enable);
438c2ecf20Sopenharmony_ci		break;
448c2ecf20Sopenharmony_ci	default:
458c2ecf20Sopenharmony_ci		ret = -EINVAL;
468c2ecf20Sopenharmony_ci		break;
478c2ecf20Sopenharmony_ci	}
488c2ecf20Sopenharmony_ci
498c2ecf20Sopenharmony_ci	return ret;
508c2ecf20Sopenharmony_ci};
518c2ecf20Sopenharmony_ci
528c2ecf20Sopenharmony_ci/*---------------------------------------------------------------------*/
538c2ecf20Sopenharmony_ci
548c2ecf20Sopenharmony_cistatic void tda18271_dump_regs(struct dvb_frontend *fe, int extended)
558c2ecf20Sopenharmony_ci{
568c2ecf20Sopenharmony_ci	struct tda18271_priv *priv = fe->tuner_priv;
578c2ecf20Sopenharmony_ci	unsigned char *regs = priv->tda18271_regs;
588c2ecf20Sopenharmony_ci
598c2ecf20Sopenharmony_ci	tda_reg("=== TDA18271 REG DUMP ===\n");
608c2ecf20Sopenharmony_ci	tda_reg("ID_BYTE            = 0x%02x\n", 0xff & regs[R_ID]);
618c2ecf20Sopenharmony_ci	tda_reg("THERMO_BYTE        = 0x%02x\n", 0xff & regs[R_TM]);
628c2ecf20Sopenharmony_ci	tda_reg("POWER_LEVEL_BYTE   = 0x%02x\n", 0xff & regs[R_PL]);
638c2ecf20Sopenharmony_ci	tda_reg("EASY_PROG_BYTE_1   = 0x%02x\n", 0xff & regs[R_EP1]);
648c2ecf20Sopenharmony_ci	tda_reg("EASY_PROG_BYTE_2   = 0x%02x\n", 0xff & regs[R_EP2]);
658c2ecf20Sopenharmony_ci	tda_reg("EASY_PROG_BYTE_3   = 0x%02x\n", 0xff & regs[R_EP3]);
668c2ecf20Sopenharmony_ci	tda_reg("EASY_PROG_BYTE_4   = 0x%02x\n", 0xff & regs[R_EP4]);
678c2ecf20Sopenharmony_ci	tda_reg("EASY_PROG_BYTE_5   = 0x%02x\n", 0xff & regs[R_EP5]);
688c2ecf20Sopenharmony_ci	tda_reg("CAL_POST_DIV_BYTE  = 0x%02x\n", 0xff & regs[R_CPD]);
698c2ecf20Sopenharmony_ci	tda_reg("CAL_DIV_BYTE_1     = 0x%02x\n", 0xff & regs[R_CD1]);
708c2ecf20Sopenharmony_ci	tda_reg("CAL_DIV_BYTE_2     = 0x%02x\n", 0xff & regs[R_CD2]);
718c2ecf20Sopenharmony_ci	tda_reg("CAL_DIV_BYTE_3     = 0x%02x\n", 0xff & regs[R_CD3]);
728c2ecf20Sopenharmony_ci	tda_reg("MAIN_POST_DIV_BYTE = 0x%02x\n", 0xff & regs[R_MPD]);
738c2ecf20Sopenharmony_ci	tda_reg("MAIN_DIV_BYTE_1    = 0x%02x\n", 0xff & regs[R_MD1]);
748c2ecf20Sopenharmony_ci	tda_reg("MAIN_DIV_BYTE_2    = 0x%02x\n", 0xff & regs[R_MD2]);
758c2ecf20Sopenharmony_ci	tda_reg("MAIN_DIV_BYTE_3    = 0x%02x\n", 0xff & regs[R_MD3]);
768c2ecf20Sopenharmony_ci
778c2ecf20Sopenharmony_ci	/* only dump extended regs if DBG_ADV is set */
788c2ecf20Sopenharmony_ci	if (!(tda18271_debug & DBG_ADV))
798c2ecf20Sopenharmony_ci		return;
808c2ecf20Sopenharmony_ci
818c2ecf20Sopenharmony_ci	/* W indicates write-only registers.
828c2ecf20Sopenharmony_ci	 * Register dump for write-only registers shows last value written. */
838c2ecf20Sopenharmony_ci
848c2ecf20Sopenharmony_ci	tda_reg("EXTENDED_BYTE_1    = 0x%02x\n", 0xff & regs[R_EB1]);
858c2ecf20Sopenharmony_ci	tda_reg("EXTENDED_BYTE_2    = 0x%02x\n", 0xff & regs[R_EB2]);
868c2ecf20Sopenharmony_ci	tda_reg("EXTENDED_BYTE_3    = 0x%02x\n", 0xff & regs[R_EB3]);
878c2ecf20Sopenharmony_ci	tda_reg("EXTENDED_BYTE_4    = 0x%02x\n", 0xff & regs[R_EB4]);
888c2ecf20Sopenharmony_ci	tda_reg("EXTENDED_BYTE_5    = 0x%02x\n", 0xff & regs[R_EB5]);
898c2ecf20Sopenharmony_ci	tda_reg("EXTENDED_BYTE_6    = 0x%02x\n", 0xff & regs[R_EB6]);
908c2ecf20Sopenharmony_ci	tda_reg("EXTENDED_BYTE_7    = 0x%02x\n", 0xff & regs[R_EB7]);
918c2ecf20Sopenharmony_ci	tda_reg("EXTENDED_BYTE_8    = 0x%02x\n", 0xff & regs[R_EB8]);
928c2ecf20Sopenharmony_ci	tda_reg("EXTENDED_BYTE_9  W = 0x%02x\n", 0xff & regs[R_EB9]);
938c2ecf20Sopenharmony_ci	tda_reg("EXTENDED_BYTE_10   = 0x%02x\n", 0xff & regs[R_EB10]);
948c2ecf20Sopenharmony_ci	tda_reg("EXTENDED_BYTE_11   = 0x%02x\n", 0xff & regs[R_EB11]);
958c2ecf20Sopenharmony_ci	tda_reg("EXTENDED_BYTE_12   = 0x%02x\n", 0xff & regs[R_EB12]);
968c2ecf20Sopenharmony_ci	tda_reg("EXTENDED_BYTE_13   = 0x%02x\n", 0xff & regs[R_EB13]);
978c2ecf20Sopenharmony_ci	tda_reg("EXTENDED_BYTE_14   = 0x%02x\n", 0xff & regs[R_EB14]);
988c2ecf20Sopenharmony_ci	tda_reg("EXTENDED_BYTE_15   = 0x%02x\n", 0xff & regs[R_EB15]);
998c2ecf20Sopenharmony_ci	tda_reg("EXTENDED_BYTE_16 W = 0x%02x\n", 0xff & regs[R_EB16]);
1008c2ecf20Sopenharmony_ci	tda_reg("EXTENDED_BYTE_17 W = 0x%02x\n", 0xff & regs[R_EB17]);
1018c2ecf20Sopenharmony_ci	tda_reg("EXTENDED_BYTE_18   = 0x%02x\n", 0xff & regs[R_EB18]);
1028c2ecf20Sopenharmony_ci	tda_reg("EXTENDED_BYTE_19 W = 0x%02x\n", 0xff & regs[R_EB19]);
1038c2ecf20Sopenharmony_ci	tda_reg("EXTENDED_BYTE_20 W = 0x%02x\n", 0xff & regs[R_EB20]);
1048c2ecf20Sopenharmony_ci	tda_reg("EXTENDED_BYTE_21   = 0x%02x\n", 0xff & regs[R_EB21]);
1058c2ecf20Sopenharmony_ci	tda_reg("EXTENDED_BYTE_22   = 0x%02x\n", 0xff & regs[R_EB22]);
1068c2ecf20Sopenharmony_ci	tda_reg("EXTENDED_BYTE_23   = 0x%02x\n", 0xff & regs[R_EB23]);
1078c2ecf20Sopenharmony_ci}
1088c2ecf20Sopenharmony_ci
1098c2ecf20Sopenharmony_ciint tda18271_read_regs(struct dvb_frontend *fe)
1108c2ecf20Sopenharmony_ci{
1118c2ecf20Sopenharmony_ci	struct tda18271_priv *priv = fe->tuner_priv;
1128c2ecf20Sopenharmony_ci	unsigned char *regs = priv->tda18271_regs;
1138c2ecf20Sopenharmony_ci	unsigned char buf = 0x00;
1148c2ecf20Sopenharmony_ci	int ret;
1158c2ecf20Sopenharmony_ci	struct i2c_msg msg[] = {
1168c2ecf20Sopenharmony_ci		{ .addr = priv->i2c_props.addr, .flags = 0,
1178c2ecf20Sopenharmony_ci		  .buf = &buf, .len = 1 },
1188c2ecf20Sopenharmony_ci		{ .addr = priv->i2c_props.addr, .flags = I2C_M_RD,
1198c2ecf20Sopenharmony_ci		  .buf = regs, .len = 16 }
1208c2ecf20Sopenharmony_ci	};
1218c2ecf20Sopenharmony_ci
1228c2ecf20Sopenharmony_ci	tda18271_i2c_gate_ctrl(fe, 1);
1238c2ecf20Sopenharmony_ci
1248c2ecf20Sopenharmony_ci	/* read all registers */
1258c2ecf20Sopenharmony_ci	ret = i2c_transfer(priv->i2c_props.adap, msg, 2);
1268c2ecf20Sopenharmony_ci
1278c2ecf20Sopenharmony_ci	tda18271_i2c_gate_ctrl(fe, 0);
1288c2ecf20Sopenharmony_ci
1298c2ecf20Sopenharmony_ci	if (ret != 2)
1308c2ecf20Sopenharmony_ci		tda_err("ERROR: i2c_transfer returned: %d\n", ret);
1318c2ecf20Sopenharmony_ci
1328c2ecf20Sopenharmony_ci	if (tda18271_debug & DBG_REG)
1338c2ecf20Sopenharmony_ci		tda18271_dump_regs(fe, 0);
1348c2ecf20Sopenharmony_ci
1358c2ecf20Sopenharmony_ci	return (ret == 2 ? 0 : ret);
1368c2ecf20Sopenharmony_ci}
1378c2ecf20Sopenharmony_ci
1388c2ecf20Sopenharmony_ciint tda18271_read_extended(struct dvb_frontend *fe)
1398c2ecf20Sopenharmony_ci{
1408c2ecf20Sopenharmony_ci	struct tda18271_priv *priv = fe->tuner_priv;
1418c2ecf20Sopenharmony_ci	unsigned char *regs = priv->tda18271_regs;
1428c2ecf20Sopenharmony_ci	unsigned char regdump[TDA18271_NUM_REGS];
1438c2ecf20Sopenharmony_ci	unsigned char buf = 0x00;
1448c2ecf20Sopenharmony_ci	int ret, i;
1458c2ecf20Sopenharmony_ci	struct i2c_msg msg[] = {
1468c2ecf20Sopenharmony_ci		{ .addr = priv->i2c_props.addr, .flags = 0,
1478c2ecf20Sopenharmony_ci		  .buf = &buf, .len = 1 },
1488c2ecf20Sopenharmony_ci		{ .addr = priv->i2c_props.addr, .flags = I2C_M_RD,
1498c2ecf20Sopenharmony_ci		  .buf = regdump, .len = TDA18271_NUM_REGS }
1508c2ecf20Sopenharmony_ci	};
1518c2ecf20Sopenharmony_ci
1528c2ecf20Sopenharmony_ci	tda18271_i2c_gate_ctrl(fe, 1);
1538c2ecf20Sopenharmony_ci
1548c2ecf20Sopenharmony_ci	/* read all registers */
1558c2ecf20Sopenharmony_ci	ret = i2c_transfer(priv->i2c_props.adap, msg, 2);
1568c2ecf20Sopenharmony_ci
1578c2ecf20Sopenharmony_ci	tda18271_i2c_gate_ctrl(fe, 0);
1588c2ecf20Sopenharmony_ci
1598c2ecf20Sopenharmony_ci	if (ret != 2)
1608c2ecf20Sopenharmony_ci		tda_err("ERROR: i2c_transfer returned: %d\n", ret);
1618c2ecf20Sopenharmony_ci
1628c2ecf20Sopenharmony_ci	for (i = 0; i < TDA18271_NUM_REGS; i++) {
1638c2ecf20Sopenharmony_ci		/* don't update write-only registers */
1648c2ecf20Sopenharmony_ci		if ((i != R_EB9)  &&
1658c2ecf20Sopenharmony_ci		    (i != R_EB16) &&
1668c2ecf20Sopenharmony_ci		    (i != R_EB17) &&
1678c2ecf20Sopenharmony_ci		    (i != R_EB19) &&
1688c2ecf20Sopenharmony_ci		    (i != R_EB20))
1698c2ecf20Sopenharmony_ci			regs[i] = regdump[i];
1708c2ecf20Sopenharmony_ci	}
1718c2ecf20Sopenharmony_ci
1728c2ecf20Sopenharmony_ci	if (tda18271_debug & DBG_REG)
1738c2ecf20Sopenharmony_ci		tda18271_dump_regs(fe, 1);
1748c2ecf20Sopenharmony_ci
1758c2ecf20Sopenharmony_ci	return (ret == 2 ? 0 : ret);
1768c2ecf20Sopenharmony_ci}
1778c2ecf20Sopenharmony_ci
1788c2ecf20Sopenharmony_cistatic int __tda18271_write_regs(struct dvb_frontend *fe, int idx, int len,
1798c2ecf20Sopenharmony_ci			bool lock_i2c)
1808c2ecf20Sopenharmony_ci{
1818c2ecf20Sopenharmony_ci	struct tda18271_priv *priv = fe->tuner_priv;
1828c2ecf20Sopenharmony_ci	unsigned char *regs = priv->tda18271_regs;
1838c2ecf20Sopenharmony_ci	unsigned char buf[TDA18271_NUM_REGS + 1];
1848c2ecf20Sopenharmony_ci	struct i2c_msg msg = { .addr = priv->i2c_props.addr, .flags = 0,
1858c2ecf20Sopenharmony_ci			       .buf = buf };
1868c2ecf20Sopenharmony_ci	int i, ret = 1, max;
1878c2ecf20Sopenharmony_ci
1888c2ecf20Sopenharmony_ci	BUG_ON((len == 0) || (idx + len > sizeof(buf)));
1898c2ecf20Sopenharmony_ci
1908c2ecf20Sopenharmony_ci	switch (priv->small_i2c) {
1918c2ecf20Sopenharmony_ci	case TDA18271_03_BYTE_CHUNK_INIT:
1928c2ecf20Sopenharmony_ci		max = 3;
1938c2ecf20Sopenharmony_ci		break;
1948c2ecf20Sopenharmony_ci	case TDA18271_08_BYTE_CHUNK_INIT:
1958c2ecf20Sopenharmony_ci		max = 8;
1968c2ecf20Sopenharmony_ci		break;
1978c2ecf20Sopenharmony_ci	case TDA18271_16_BYTE_CHUNK_INIT:
1988c2ecf20Sopenharmony_ci		max = 16;
1998c2ecf20Sopenharmony_ci		break;
2008c2ecf20Sopenharmony_ci	case TDA18271_39_BYTE_CHUNK_INIT:
2018c2ecf20Sopenharmony_ci	default:
2028c2ecf20Sopenharmony_ci		max = 39;
2038c2ecf20Sopenharmony_ci	}
2048c2ecf20Sopenharmony_ci
2058c2ecf20Sopenharmony_ci
2068c2ecf20Sopenharmony_ci	/*
2078c2ecf20Sopenharmony_ci	 * If lock_i2c is true, it will take the I2C bus for tda18271 private
2088c2ecf20Sopenharmony_ci	 * usage during the entire write ops, as otherwise, bad things could
2098c2ecf20Sopenharmony_ci	 * happen.
2108c2ecf20Sopenharmony_ci	 * During device init, several write operations will happen. So,
2118c2ecf20Sopenharmony_ci	 * tda18271_init_regs controls the I2C lock directly,
2128c2ecf20Sopenharmony_ci	 * disabling lock_i2c here.
2138c2ecf20Sopenharmony_ci	 */
2148c2ecf20Sopenharmony_ci	if (lock_i2c) {
2158c2ecf20Sopenharmony_ci		tda18271_i2c_gate_ctrl(fe, 1);
2168c2ecf20Sopenharmony_ci		i2c_lock_bus(priv->i2c_props.adap, I2C_LOCK_SEGMENT);
2178c2ecf20Sopenharmony_ci	}
2188c2ecf20Sopenharmony_ci	while (len) {
2198c2ecf20Sopenharmony_ci		if (max > len)
2208c2ecf20Sopenharmony_ci			max = len;
2218c2ecf20Sopenharmony_ci
2228c2ecf20Sopenharmony_ci		buf[0] = idx;
2238c2ecf20Sopenharmony_ci		for (i = 1; i <= max; i++)
2248c2ecf20Sopenharmony_ci			buf[i] = regs[idx - 1 + i];
2258c2ecf20Sopenharmony_ci
2268c2ecf20Sopenharmony_ci		msg.len = max + 1;
2278c2ecf20Sopenharmony_ci
2288c2ecf20Sopenharmony_ci		/* write registers */
2298c2ecf20Sopenharmony_ci		ret = __i2c_transfer(priv->i2c_props.adap, &msg, 1);
2308c2ecf20Sopenharmony_ci		if (ret != 1)
2318c2ecf20Sopenharmony_ci			break;
2328c2ecf20Sopenharmony_ci
2338c2ecf20Sopenharmony_ci		idx += max;
2348c2ecf20Sopenharmony_ci		len -= max;
2358c2ecf20Sopenharmony_ci	}
2368c2ecf20Sopenharmony_ci	if (lock_i2c) {
2378c2ecf20Sopenharmony_ci		i2c_unlock_bus(priv->i2c_props.adap, I2C_LOCK_SEGMENT);
2388c2ecf20Sopenharmony_ci		tda18271_i2c_gate_ctrl(fe, 0);
2398c2ecf20Sopenharmony_ci	}
2408c2ecf20Sopenharmony_ci
2418c2ecf20Sopenharmony_ci	if (ret != 1)
2428c2ecf20Sopenharmony_ci		tda_err("ERROR: idx = 0x%x, len = %d, i2c_transfer returned: %d\n",
2438c2ecf20Sopenharmony_ci			idx, max, ret);
2448c2ecf20Sopenharmony_ci
2458c2ecf20Sopenharmony_ci	return (ret == 1 ? 0 : ret);
2468c2ecf20Sopenharmony_ci}
2478c2ecf20Sopenharmony_ci
2488c2ecf20Sopenharmony_ciint tda18271_write_regs(struct dvb_frontend *fe, int idx, int len)
2498c2ecf20Sopenharmony_ci{
2508c2ecf20Sopenharmony_ci	return __tda18271_write_regs(fe, idx, len, true);
2518c2ecf20Sopenharmony_ci}
2528c2ecf20Sopenharmony_ci
2538c2ecf20Sopenharmony_ci/*---------------------------------------------------------------------*/
2548c2ecf20Sopenharmony_ci
2558c2ecf20Sopenharmony_cistatic int __tda18271_charge_pump_source(struct dvb_frontend *fe,
2568c2ecf20Sopenharmony_ci					 enum tda18271_pll pll, int force,
2578c2ecf20Sopenharmony_ci					 bool lock_i2c)
2588c2ecf20Sopenharmony_ci{
2598c2ecf20Sopenharmony_ci	struct tda18271_priv *priv = fe->tuner_priv;
2608c2ecf20Sopenharmony_ci	unsigned char *regs = priv->tda18271_regs;
2618c2ecf20Sopenharmony_ci
2628c2ecf20Sopenharmony_ci	int r_cp = (pll == TDA18271_CAL_PLL) ? R_EB7 : R_EB4;
2638c2ecf20Sopenharmony_ci
2648c2ecf20Sopenharmony_ci	regs[r_cp] &= ~0x20;
2658c2ecf20Sopenharmony_ci	regs[r_cp] |= ((force & 1) << 5);
2668c2ecf20Sopenharmony_ci
2678c2ecf20Sopenharmony_ci	return __tda18271_write_regs(fe, r_cp, 1, lock_i2c);
2688c2ecf20Sopenharmony_ci}
2698c2ecf20Sopenharmony_ci
2708c2ecf20Sopenharmony_ciint tda18271_charge_pump_source(struct dvb_frontend *fe,
2718c2ecf20Sopenharmony_ci				enum tda18271_pll pll, int force)
2728c2ecf20Sopenharmony_ci{
2738c2ecf20Sopenharmony_ci	return __tda18271_charge_pump_source(fe, pll, force, true);
2748c2ecf20Sopenharmony_ci}
2758c2ecf20Sopenharmony_ci
2768c2ecf20Sopenharmony_ci
2778c2ecf20Sopenharmony_ciint tda18271_init_regs(struct dvb_frontend *fe)
2788c2ecf20Sopenharmony_ci{
2798c2ecf20Sopenharmony_ci	struct tda18271_priv *priv = fe->tuner_priv;
2808c2ecf20Sopenharmony_ci	unsigned char *regs = priv->tda18271_regs;
2818c2ecf20Sopenharmony_ci
2828c2ecf20Sopenharmony_ci	tda_dbg("initializing registers for device @ %d-%04x\n",
2838c2ecf20Sopenharmony_ci		i2c_adapter_id(priv->i2c_props.adap),
2848c2ecf20Sopenharmony_ci		priv->i2c_props.addr);
2858c2ecf20Sopenharmony_ci
2868c2ecf20Sopenharmony_ci	/*
2878c2ecf20Sopenharmony_ci	 * Don't let any other I2C transfer to happen at adapter during init,
2888c2ecf20Sopenharmony_ci	 * as those could cause bad things
2898c2ecf20Sopenharmony_ci	 */
2908c2ecf20Sopenharmony_ci	tda18271_i2c_gate_ctrl(fe, 1);
2918c2ecf20Sopenharmony_ci	i2c_lock_bus(priv->i2c_props.adap, I2C_LOCK_SEGMENT);
2928c2ecf20Sopenharmony_ci
2938c2ecf20Sopenharmony_ci	/* initialize registers */
2948c2ecf20Sopenharmony_ci	switch (priv->id) {
2958c2ecf20Sopenharmony_ci	case TDA18271HDC1:
2968c2ecf20Sopenharmony_ci		regs[R_ID]   = 0x83;
2978c2ecf20Sopenharmony_ci		break;
2988c2ecf20Sopenharmony_ci	case TDA18271HDC2:
2998c2ecf20Sopenharmony_ci		regs[R_ID]   = 0x84;
3008c2ecf20Sopenharmony_ci		break;
3018c2ecf20Sopenharmony_ci	}
3028c2ecf20Sopenharmony_ci
3038c2ecf20Sopenharmony_ci	regs[R_TM]   = 0x08;
3048c2ecf20Sopenharmony_ci	regs[R_PL]   = 0x80;
3058c2ecf20Sopenharmony_ci	regs[R_EP1]  = 0xc6;
3068c2ecf20Sopenharmony_ci	regs[R_EP2]  = 0xdf;
3078c2ecf20Sopenharmony_ci	regs[R_EP3]  = 0x16;
3088c2ecf20Sopenharmony_ci	regs[R_EP4]  = 0x60;
3098c2ecf20Sopenharmony_ci	regs[R_EP5]  = 0x80;
3108c2ecf20Sopenharmony_ci	regs[R_CPD]  = 0x80;
3118c2ecf20Sopenharmony_ci	regs[R_CD1]  = 0x00;
3128c2ecf20Sopenharmony_ci	regs[R_CD2]  = 0x00;
3138c2ecf20Sopenharmony_ci	regs[R_CD3]  = 0x00;
3148c2ecf20Sopenharmony_ci	regs[R_MPD]  = 0x00;
3158c2ecf20Sopenharmony_ci	regs[R_MD1]  = 0x00;
3168c2ecf20Sopenharmony_ci	regs[R_MD2]  = 0x00;
3178c2ecf20Sopenharmony_ci	regs[R_MD3]  = 0x00;
3188c2ecf20Sopenharmony_ci
3198c2ecf20Sopenharmony_ci	switch (priv->id) {
3208c2ecf20Sopenharmony_ci	case TDA18271HDC1:
3218c2ecf20Sopenharmony_ci		regs[R_EB1]  = 0xff;
3228c2ecf20Sopenharmony_ci		break;
3238c2ecf20Sopenharmony_ci	case TDA18271HDC2:
3248c2ecf20Sopenharmony_ci		regs[R_EB1]  = 0xfc;
3258c2ecf20Sopenharmony_ci		break;
3268c2ecf20Sopenharmony_ci	}
3278c2ecf20Sopenharmony_ci
3288c2ecf20Sopenharmony_ci	regs[R_EB2]  = 0x01;
3298c2ecf20Sopenharmony_ci	regs[R_EB3]  = 0x84;
3308c2ecf20Sopenharmony_ci	regs[R_EB4]  = 0x41;
3318c2ecf20Sopenharmony_ci	regs[R_EB5]  = 0x01;
3328c2ecf20Sopenharmony_ci	regs[R_EB6]  = 0x84;
3338c2ecf20Sopenharmony_ci	regs[R_EB7]  = 0x40;
3348c2ecf20Sopenharmony_ci	regs[R_EB8]  = 0x07;
3358c2ecf20Sopenharmony_ci	regs[R_EB9]  = 0x00;
3368c2ecf20Sopenharmony_ci	regs[R_EB10] = 0x00;
3378c2ecf20Sopenharmony_ci	regs[R_EB11] = 0x96;
3388c2ecf20Sopenharmony_ci
3398c2ecf20Sopenharmony_ci	switch (priv->id) {
3408c2ecf20Sopenharmony_ci	case TDA18271HDC1:
3418c2ecf20Sopenharmony_ci		regs[R_EB12] = 0x0f;
3428c2ecf20Sopenharmony_ci		break;
3438c2ecf20Sopenharmony_ci	case TDA18271HDC2:
3448c2ecf20Sopenharmony_ci		regs[R_EB12] = 0x33;
3458c2ecf20Sopenharmony_ci		break;
3468c2ecf20Sopenharmony_ci	}
3478c2ecf20Sopenharmony_ci
3488c2ecf20Sopenharmony_ci	regs[R_EB13] = 0xc1;
3498c2ecf20Sopenharmony_ci	regs[R_EB14] = 0x00;
3508c2ecf20Sopenharmony_ci	regs[R_EB15] = 0x8f;
3518c2ecf20Sopenharmony_ci	regs[R_EB16] = 0x00;
3528c2ecf20Sopenharmony_ci	regs[R_EB17] = 0x00;
3538c2ecf20Sopenharmony_ci
3548c2ecf20Sopenharmony_ci	switch (priv->id) {
3558c2ecf20Sopenharmony_ci	case TDA18271HDC1:
3568c2ecf20Sopenharmony_ci		regs[R_EB18] = 0x00;
3578c2ecf20Sopenharmony_ci		break;
3588c2ecf20Sopenharmony_ci	case TDA18271HDC2:
3598c2ecf20Sopenharmony_ci		regs[R_EB18] = 0x8c;
3608c2ecf20Sopenharmony_ci		break;
3618c2ecf20Sopenharmony_ci	}
3628c2ecf20Sopenharmony_ci
3638c2ecf20Sopenharmony_ci	regs[R_EB19] = 0x00;
3648c2ecf20Sopenharmony_ci	regs[R_EB20] = 0x20;
3658c2ecf20Sopenharmony_ci
3668c2ecf20Sopenharmony_ci	switch (priv->id) {
3678c2ecf20Sopenharmony_ci	case TDA18271HDC1:
3688c2ecf20Sopenharmony_ci		regs[R_EB21] = 0x33;
3698c2ecf20Sopenharmony_ci		break;
3708c2ecf20Sopenharmony_ci	case TDA18271HDC2:
3718c2ecf20Sopenharmony_ci		regs[R_EB21] = 0xb3;
3728c2ecf20Sopenharmony_ci		break;
3738c2ecf20Sopenharmony_ci	}
3748c2ecf20Sopenharmony_ci
3758c2ecf20Sopenharmony_ci	regs[R_EB22] = 0x48;
3768c2ecf20Sopenharmony_ci	regs[R_EB23] = 0xb0;
3778c2ecf20Sopenharmony_ci
3788c2ecf20Sopenharmony_ci	__tda18271_write_regs(fe, 0x00, TDA18271_NUM_REGS, false);
3798c2ecf20Sopenharmony_ci
3808c2ecf20Sopenharmony_ci	/* setup agc1 gain */
3818c2ecf20Sopenharmony_ci	regs[R_EB17] = 0x00;
3828c2ecf20Sopenharmony_ci	__tda18271_write_regs(fe, R_EB17, 1, false);
3838c2ecf20Sopenharmony_ci	regs[R_EB17] = 0x03;
3848c2ecf20Sopenharmony_ci	__tda18271_write_regs(fe, R_EB17, 1, false);
3858c2ecf20Sopenharmony_ci	regs[R_EB17] = 0x43;
3868c2ecf20Sopenharmony_ci	__tda18271_write_regs(fe, R_EB17, 1, false);
3878c2ecf20Sopenharmony_ci	regs[R_EB17] = 0x4c;
3888c2ecf20Sopenharmony_ci	__tda18271_write_regs(fe, R_EB17, 1, false);
3898c2ecf20Sopenharmony_ci
3908c2ecf20Sopenharmony_ci	/* setup agc2 gain */
3918c2ecf20Sopenharmony_ci	if ((priv->id) == TDA18271HDC1) {
3928c2ecf20Sopenharmony_ci		regs[R_EB20] = 0xa0;
3938c2ecf20Sopenharmony_ci		__tda18271_write_regs(fe, R_EB20, 1, false);
3948c2ecf20Sopenharmony_ci		regs[R_EB20] = 0xa7;
3958c2ecf20Sopenharmony_ci		__tda18271_write_regs(fe, R_EB20, 1, false);
3968c2ecf20Sopenharmony_ci		regs[R_EB20] = 0xe7;
3978c2ecf20Sopenharmony_ci		__tda18271_write_regs(fe, R_EB20, 1, false);
3988c2ecf20Sopenharmony_ci		regs[R_EB20] = 0xec;
3998c2ecf20Sopenharmony_ci		__tda18271_write_regs(fe, R_EB20, 1, false);
4008c2ecf20Sopenharmony_ci	}
4018c2ecf20Sopenharmony_ci
4028c2ecf20Sopenharmony_ci	/* image rejection calibration */
4038c2ecf20Sopenharmony_ci
4048c2ecf20Sopenharmony_ci	/* low-band */
4058c2ecf20Sopenharmony_ci	regs[R_EP3] = 0x1f;
4068c2ecf20Sopenharmony_ci	regs[R_EP4] = 0x66;
4078c2ecf20Sopenharmony_ci	regs[R_EP5] = 0x81;
4088c2ecf20Sopenharmony_ci	regs[R_CPD] = 0xcc;
4098c2ecf20Sopenharmony_ci	regs[R_CD1] = 0x6c;
4108c2ecf20Sopenharmony_ci	regs[R_CD2] = 0x00;
4118c2ecf20Sopenharmony_ci	regs[R_CD3] = 0x00;
4128c2ecf20Sopenharmony_ci	regs[R_MPD] = 0xcd;
4138c2ecf20Sopenharmony_ci	regs[R_MD1] = 0x77;
4148c2ecf20Sopenharmony_ci	regs[R_MD2] = 0x08;
4158c2ecf20Sopenharmony_ci	regs[R_MD3] = 0x00;
4168c2ecf20Sopenharmony_ci
4178c2ecf20Sopenharmony_ci	__tda18271_write_regs(fe, R_EP3, 11, false);
4188c2ecf20Sopenharmony_ci
4198c2ecf20Sopenharmony_ci	if ((priv->id) == TDA18271HDC2) {
4208c2ecf20Sopenharmony_ci		/* main pll cp source on */
4218c2ecf20Sopenharmony_ci		__tda18271_charge_pump_source(fe, TDA18271_MAIN_PLL, 1, false);
4228c2ecf20Sopenharmony_ci		msleep(1);
4238c2ecf20Sopenharmony_ci
4248c2ecf20Sopenharmony_ci		/* main pll cp source off */
4258c2ecf20Sopenharmony_ci		__tda18271_charge_pump_source(fe, TDA18271_MAIN_PLL, 0, false);
4268c2ecf20Sopenharmony_ci	}
4278c2ecf20Sopenharmony_ci
4288c2ecf20Sopenharmony_ci	msleep(5); /* pll locking */
4298c2ecf20Sopenharmony_ci
4308c2ecf20Sopenharmony_ci	/* launch detector */
4318c2ecf20Sopenharmony_ci	__tda18271_write_regs(fe, R_EP1, 1, false);
4328c2ecf20Sopenharmony_ci	msleep(5); /* wanted low measurement */
4338c2ecf20Sopenharmony_ci
4348c2ecf20Sopenharmony_ci	regs[R_EP5] = 0x85;
4358c2ecf20Sopenharmony_ci	regs[R_CPD] = 0xcb;
4368c2ecf20Sopenharmony_ci	regs[R_CD1] = 0x66;
4378c2ecf20Sopenharmony_ci	regs[R_CD2] = 0x70;
4388c2ecf20Sopenharmony_ci
4398c2ecf20Sopenharmony_ci	__tda18271_write_regs(fe, R_EP3, 7, false);
4408c2ecf20Sopenharmony_ci	msleep(5); /* pll locking */
4418c2ecf20Sopenharmony_ci
4428c2ecf20Sopenharmony_ci	/* launch optimization algorithm */
4438c2ecf20Sopenharmony_ci	__tda18271_write_regs(fe, R_EP2, 1, false);
4448c2ecf20Sopenharmony_ci	msleep(30); /* image low optimization completion */
4458c2ecf20Sopenharmony_ci
4468c2ecf20Sopenharmony_ci	/* mid-band */
4478c2ecf20Sopenharmony_ci	regs[R_EP5] = 0x82;
4488c2ecf20Sopenharmony_ci	regs[R_CPD] = 0xa8;
4498c2ecf20Sopenharmony_ci	regs[R_CD2] = 0x00;
4508c2ecf20Sopenharmony_ci	regs[R_MPD] = 0xa9;
4518c2ecf20Sopenharmony_ci	regs[R_MD1] = 0x73;
4528c2ecf20Sopenharmony_ci	regs[R_MD2] = 0x1a;
4538c2ecf20Sopenharmony_ci
4548c2ecf20Sopenharmony_ci	__tda18271_write_regs(fe, R_EP3, 11, false);
4558c2ecf20Sopenharmony_ci	msleep(5); /* pll locking */
4568c2ecf20Sopenharmony_ci
4578c2ecf20Sopenharmony_ci	/* launch detector */
4588c2ecf20Sopenharmony_ci	__tda18271_write_regs(fe, R_EP1, 1, false);
4598c2ecf20Sopenharmony_ci	msleep(5); /* wanted mid measurement */
4608c2ecf20Sopenharmony_ci
4618c2ecf20Sopenharmony_ci	regs[R_EP5] = 0x86;
4628c2ecf20Sopenharmony_ci	regs[R_CPD] = 0xa8;
4638c2ecf20Sopenharmony_ci	regs[R_CD1] = 0x66;
4648c2ecf20Sopenharmony_ci	regs[R_CD2] = 0xa0;
4658c2ecf20Sopenharmony_ci
4668c2ecf20Sopenharmony_ci	__tda18271_write_regs(fe, R_EP3, 7, false);
4678c2ecf20Sopenharmony_ci	msleep(5); /* pll locking */
4688c2ecf20Sopenharmony_ci
4698c2ecf20Sopenharmony_ci	/* launch optimization algorithm */
4708c2ecf20Sopenharmony_ci	__tda18271_write_regs(fe, R_EP2, 1, false);
4718c2ecf20Sopenharmony_ci	msleep(30); /* image mid optimization completion */
4728c2ecf20Sopenharmony_ci
4738c2ecf20Sopenharmony_ci	/* high-band */
4748c2ecf20Sopenharmony_ci	regs[R_EP5] = 0x83;
4758c2ecf20Sopenharmony_ci	regs[R_CPD] = 0x98;
4768c2ecf20Sopenharmony_ci	regs[R_CD1] = 0x65;
4778c2ecf20Sopenharmony_ci	regs[R_CD2] = 0x00;
4788c2ecf20Sopenharmony_ci	regs[R_MPD] = 0x99;
4798c2ecf20Sopenharmony_ci	regs[R_MD1] = 0x71;
4808c2ecf20Sopenharmony_ci	regs[R_MD2] = 0xcd;
4818c2ecf20Sopenharmony_ci
4828c2ecf20Sopenharmony_ci	__tda18271_write_regs(fe, R_EP3, 11, false);
4838c2ecf20Sopenharmony_ci	msleep(5); /* pll locking */
4848c2ecf20Sopenharmony_ci
4858c2ecf20Sopenharmony_ci	/* launch detector */
4868c2ecf20Sopenharmony_ci	__tda18271_write_regs(fe, R_EP1, 1, false);
4878c2ecf20Sopenharmony_ci	msleep(5); /* wanted high measurement */
4888c2ecf20Sopenharmony_ci
4898c2ecf20Sopenharmony_ci	regs[R_EP5] = 0x87;
4908c2ecf20Sopenharmony_ci	regs[R_CD1] = 0x65;
4918c2ecf20Sopenharmony_ci	regs[R_CD2] = 0x50;
4928c2ecf20Sopenharmony_ci
4938c2ecf20Sopenharmony_ci	__tda18271_write_regs(fe, R_EP3, 7, false);
4948c2ecf20Sopenharmony_ci	msleep(5); /* pll locking */
4958c2ecf20Sopenharmony_ci
4968c2ecf20Sopenharmony_ci	/* launch optimization algorithm */
4978c2ecf20Sopenharmony_ci	__tda18271_write_regs(fe, R_EP2, 1, false);
4988c2ecf20Sopenharmony_ci	msleep(30); /* image high optimization completion */
4998c2ecf20Sopenharmony_ci
5008c2ecf20Sopenharmony_ci	/* return to normal mode */
5018c2ecf20Sopenharmony_ci	regs[R_EP4] = 0x64;
5028c2ecf20Sopenharmony_ci	__tda18271_write_regs(fe, R_EP4, 1, false);
5038c2ecf20Sopenharmony_ci
5048c2ecf20Sopenharmony_ci	/* synchronize */
5058c2ecf20Sopenharmony_ci	__tda18271_write_regs(fe, R_EP1, 1, false);
5068c2ecf20Sopenharmony_ci
5078c2ecf20Sopenharmony_ci	i2c_unlock_bus(priv->i2c_props.adap, I2C_LOCK_SEGMENT);
5088c2ecf20Sopenharmony_ci	tda18271_i2c_gate_ctrl(fe, 0);
5098c2ecf20Sopenharmony_ci
5108c2ecf20Sopenharmony_ci	return 0;
5118c2ecf20Sopenharmony_ci}
5128c2ecf20Sopenharmony_ci
5138c2ecf20Sopenharmony_ci/*---------------------------------------------------------------------*/
5148c2ecf20Sopenharmony_ci
5158c2ecf20Sopenharmony_ci/*
5168c2ecf20Sopenharmony_ci *  Standby modes, EP3 [7:5]
5178c2ecf20Sopenharmony_ci *
5188c2ecf20Sopenharmony_ci *  | SM  || SM_LT || SM_XT || mode description
5198c2ecf20Sopenharmony_ci *  |=====\\=======\\=======\\====================================
5208c2ecf20Sopenharmony_ci *  |  0  ||   0   ||   0   || normal mode
5218c2ecf20Sopenharmony_ci *  |-----||-------||-------||------------------------------------
5228c2ecf20Sopenharmony_ci *  |     ||       ||       || standby mode w/ slave tuner output
5238c2ecf20Sopenharmony_ci *  |  1  ||   0   ||   0   || & loop through & xtal oscillator on
5248c2ecf20Sopenharmony_ci *  |-----||-------||-------||------------------------------------
5258c2ecf20Sopenharmony_ci *  |  1  ||   1   ||   0   || standby mode w/ xtal oscillator on
5268c2ecf20Sopenharmony_ci *  |-----||-------||-------||------------------------------------
5278c2ecf20Sopenharmony_ci *  |  1  ||   1   ||   1   || power off
5288c2ecf20Sopenharmony_ci *
5298c2ecf20Sopenharmony_ci */
5308c2ecf20Sopenharmony_ci
5318c2ecf20Sopenharmony_ciint tda18271_set_standby_mode(struct dvb_frontend *fe,
5328c2ecf20Sopenharmony_ci			      int sm, int sm_lt, int sm_xt)
5338c2ecf20Sopenharmony_ci{
5348c2ecf20Sopenharmony_ci	struct tda18271_priv *priv = fe->tuner_priv;
5358c2ecf20Sopenharmony_ci	unsigned char *regs = priv->tda18271_regs;
5368c2ecf20Sopenharmony_ci
5378c2ecf20Sopenharmony_ci	if (tda18271_debug & DBG_ADV)
5388c2ecf20Sopenharmony_ci		tda_dbg("sm = %d, sm_lt = %d, sm_xt = %d\n", sm, sm_lt, sm_xt);
5398c2ecf20Sopenharmony_ci
5408c2ecf20Sopenharmony_ci	regs[R_EP3]  &= ~0xe0; /* clear sm, sm_lt, sm_xt */
5418c2ecf20Sopenharmony_ci	regs[R_EP3]  |= (sm    ? (1 << 7) : 0) |
5428c2ecf20Sopenharmony_ci			(sm_lt ? (1 << 6) : 0) |
5438c2ecf20Sopenharmony_ci			(sm_xt ? (1 << 5) : 0);
5448c2ecf20Sopenharmony_ci
5458c2ecf20Sopenharmony_ci	return tda18271_write_regs(fe, R_EP3, 1);
5468c2ecf20Sopenharmony_ci}
5478c2ecf20Sopenharmony_ci
5488c2ecf20Sopenharmony_ci/*---------------------------------------------------------------------*/
5498c2ecf20Sopenharmony_ci
5508c2ecf20Sopenharmony_ciint tda18271_calc_main_pll(struct dvb_frontend *fe, u32 freq)
5518c2ecf20Sopenharmony_ci{
5528c2ecf20Sopenharmony_ci	/* sets main post divider & divider bytes, but does not write them */
5538c2ecf20Sopenharmony_ci	struct tda18271_priv *priv = fe->tuner_priv;
5548c2ecf20Sopenharmony_ci	unsigned char *regs = priv->tda18271_regs;
5558c2ecf20Sopenharmony_ci	u8 d, pd;
5568c2ecf20Sopenharmony_ci	u32 div;
5578c2ecf20Sopenharmony_ci
5588c2ecf20Sopenharmony_ci	int ret = tda18271_lookup_pll_map(fe, MAIN_PLL, &freq, &pd, &d);
5598c2ecf20Sopenharmony_ci	if (tda_fail(ret))
5608c2ecf20Sopenharmony_ci		goto fail;
5618c2ecf20Sopenharmony_ci
5628c2ecf20Sopenharmony_ci	regs[R_MPD]   = (0x7f & pd);
5638c2ecf20Sopenharmony_ci
5648c2ecf20Sopenharmony_ci	div =  ((d * (freq / 1000)) << 7) / 125;
5658c2ecf20Sopenharmony_ci
5668c2ecf20Sopenharmony_ci	regs[R_MD1]   = 0x7f & (div >> 16);
5678c2ecf20Sopenharmony_ci	regs[R_MD2]   = 0xff & (div >> 8);
5688c2ecf20Sopenharmony_ci	regs[R_MD3]   = 0xff & div;
5698c2ecf20Sopenharmony_cifail:
5708c2ecf20Sopenharmony_ci	return ret;
5718c2ecf20Sopenharmony_ci}
5728c2ecf20Sopenharmony_ci
5738c2ecf20Sopenharmony_ciint tda18271_calc_cal_pll(struct dvb_frontend *fe, u32 freq)
5748c2ecf20Sopenharmony_ci{
5758c2ecf20Sopenharmony_ci	/* sets cal post divider & divider bytes, but does not write them */
5768c2ecf20Sopenharmony_ci	struct tda18271_priv *priv = fe->tuner_priv;
5778c2ecf20Sopenharmony_ci	unsigned char *regs = priv->tda18271_regs;
5788c2ecf20Sopenharmony_ci	u8 d, pd;
5798c2ecf20Sopenharmony_ci	u32 div;
5808c2ecf20Sopenharmony_ci
5818c2ecf20Sopenharmony_ci	int ret = tda18271_lookup_pll_map(fe, CAL_PLL, &freq, &pd, &d);
5828c2ecf20Sopenharmony_ci	if (tda_fail(ret))
5838c2ecf20Sopenharmony_ci		goto fail;
5848c2ecf20Sopenharmony_ci
5858c2ecf20Sopenharmony_ci	regs[R_CPD]   = pd;
5868c2ecf20Sopenharmony_ci
5878c2ecf20Sopenharmony_ci	div =  ((d * (freq / 1000)) << 7) / 125;
5888c2ecf20Sopenharmony_ci
5898c2ecf20Sopenharmony_ci	regs[R_CD1]   = 0x7f & (div >> 16);
5908c2ecf20Sopenharmony_ci	regs[R_CD2]   = 0xff & (div >> 8);
5918c2ecf20Sopenharmony_ci	regs[R_CD3]   = 0xff & div;
5928c2ecf20Sopenharmony_cifail:
5938c2ecf20Sopenharmony_ci	return ret;
5948c2ecf20Sopenharmony_ci}
5958c2ecf20Sopenharmony_ci
5968c2ecf20Sopenharmony_ci/*---------------------------------------------------------------------*/
5978c2ecf20Sopenharmony_ci
5988c2ecf20Sopenharmony_ciint tda18271_calc_bp_filter(struct dvb_frontend *fe, u32 *freq)
5998c2ecf20Sopenharmony_ci{
6008c2ecf20Sopenharmony_ci	/* sets bp filter bits, but does not write them */
6018c2ecf20Sopenharmony_ci	struct tda18271_priv *priv = fe->tuner_priv;
6028c2ecf20Sopenharmony_ci	unsigned char *regs = priv->tda18271_regs;
6038c2ecf20Sopenharmony_ci	u8 val;
6048c2ecf20Sopenharmony_ci
6058c2ecf20Sopenharmony_ci	int ret = tda18271_lookup_map(fe, BP_FILTER, freq, &val);
6068c2ecf20Sopenharmony_ci	if (tda_fail(ret))
6078c2ecf20Sopenharmony_ci		goto fail;
6088c2ecf20Sopenharmony_ci
6098c2ecf20Sopenharmony_ci	regs[R_EP1]  &= ~0x07; /* clear bp filter bits */
6108c2ecf20Sopenharmony_ci	regs[R_EP1]  |= (0x07 & val);
6118c2ecf20Sopenharmony_cifail:
6128c2ecf20Sopenharmony_ci	return ret;
6138c2ecf20Sopenharmony_ci}
6148c2ecf20Sopenharmony_ci
6158c2ecf20Sopenharmony_ciint tda18271_calc_km(struct dvb_frontend *fe, u32 *freq)
6168c2ecf20Sopenharmony_ci{
6178c2ecf20Sopenharmony_ci	/* sets K & M bits, but does not write them */
6188c2ecf20Sopenharmony_ci	struct tda18271_priv *priv = fe->tuner_priv;
6198c2ecf20Sopenharmony_ci	unsigned char *regs = priv->tda18271_regs;
6208c2ecf20Sopenharmony_ci	u8 val;
6218c2ecf20Sopenharmony_ci
6228c2ecf20Sopenharmony_ci	int ret = tda18271_lookup_map(fe, RF_CAL_KMCO, freq, &val);
6238c2ecf20Sopenharmony_ci	if (tda_fail(ret))
6248c2ecf20Sopenharmony_ci		goto fail;
6258c2ecf20Sopenharmony_ci
6268c2ecf20Sopenharmony_ci	regs[R_EB13] &= ~0x7c; /* clear k & m bits */
6278c2ecf20Sopenharmony_ci	regs[R_EB13] |= (0x7c & val);
6288c2ecf20Sopenharmony_cifail:
6298c2ecf20Sopenharmony_ci	return ret;
6308c2ecf20Sopenharmony_ci}
6318c2ecf20Sopenharmony_ci
6328c2ecf20Sopenharmony_ciint tda18271_calc_rf_band(struct dvb_frontend *fe, u32 *freq)
6338c2ecf20Sopenharmony_ci{
6348c2ecf20Sopenharmony_ci	/* sets rf band bits, but does not write them */
6358c2ecf20Sopenharmony_ci	struct tda18271_priv *priv = fe->tuner_priv;
6368c2ecf20Sopenharmony_ci	unsigned char *regs = priv->tda18271_regs;
6378c2ecf20Sopenharmony_ci	u8 val;
6388c2ecf20Sopenharmony_ci
6398c2ecf20Sopenharmony_ci	int ret = tda18271_lookup_map(fe, RF_BAND, freq, &val);
6408c2ecf20Sopenharmony_ci	if (tda_fail(ret))
6418c2ecf20Sopenharmony_ci		goto fail;
6428c2ecf20Sopenharmony_ci
6438c2ecf20Sopenharmony_ci	regs[R_EP2]  &= ~0xe0; /* clear rf band bits */
6448c2ecf20Sopenharmony_ci	regs[R_EP2]  |= (0xe0 & (val << 5));
6458c2ecf20Sopenharmony_cifail:
6468c2ecf20Sopenharmony_ci	return ret;
6478c2ecf20Sopenharmony_ci}
6488c2ecf20Sopenharmony_ci
6498c2ecf20Sopenharmony_ciint tda18271_calc_gain_taper(struct dvb_frontend *fe, u32 *freq)
6508c2ecf20Sopenharmony_ci{
6518c2ecf20Sopenharmony_ci	/* sets gain taper bits, but does not write them */
6528c2ecf20Sopenharmony_ci	struct tda18271_priv *priv = fe->tuner_priv;
6538c2ecf20Sopenharmony_ci	unsigned char *regs = priv->tda18271_regs;
6548c2ecf20Sopenharmony_ci	u8 val;
6558c2ecf20Sopenharmony_ci
6568c2ecf20Sopenharmony_ci	int ret = tda18271_lookup_map(fe, GAIN_TAPER, freq, &val);
6578c2ecf20Sopenharmony_ci	if (tda_fail(ret))
6588c2ecf20Sopenharmony_ci		goto fail;
6598c2ecf20Sopenharmony_ci
6608c2ecf20Sopenharmony_ci	regs[R_EP2]  &= ~0x1f; /* clear gain taper bits */
6618c2ecf20Sopenharmony_ci	regs[R_EP2]  |= (0x1f & val);
6628c2ecf20Sopenharmony_cifail:
6638c2ecf20Sopenharmony_ci	return ret;
6648c2ecf20Sopenharmony_ci}
6658c2ecf20Sopenharmony_ci
6668c2ecf20Sopenharmony_ciint tda18271_calc_ir_measure(struct dvb_frontend *fe, u32 *freq)
6678c2ecf20Sopenharmony_ci{
6688c2ecf20Sopenharmony_ci	/* sets IR Meas bits, but does not write them */
6698c2ecf20Sopenharmony_ci	struct tda18271_priv *priv = fe->tuner_priv;
6708c2ecf20Sopenharmony_ci	unsigned char *regs = priv->tda18271_regs;
6718c2ecf20Sopenharmony_ci	u8 val;
6728c2ecf20Sopenharmony_ci
6738c2ecf20Sopenharmony_ci	int ret = tda18271_lookup_map(fe, IR_MEASURE, freq, &val);
6748c2ecf20Sopenharmony_ci	if (tda_fail(ret))
6758c2ecf20Sopenharmony_ci		goto fail;
6768c2ecf20Sopenharmony_ci
6778c2ecf20Sopenharmony_ci	regs[R_EP5] &= ~0x07;
6788c2ecf20Sopenharmony_ci	regs[R_EP5] |= (0x07 & val);
6798c2ecf20Sopenharmony_cifail:
6808c2ecf20Sopenharmony_ci	return ret;
6818c2ecf20Sopenharmony_ci}
6828c2ecf20Sopenharmony_ci
6838c2ecf20Sopenharmony_ciint tda18271_calc_rf_cal(struct dvb_frontend *fe, u32 *freq)
6848c2ecf20Sopenharmony_ci{
6858c2ecf20Sopenharmony_ci	/* sets rf cal byte (RFC_Cprog), but does not write it */
6868c2ecf20Sopenharmony_ci	struct tda18271_priv *priv = fe->tuner_priv;
6878c2ecf20Sopenharmony_ci	unsigned char *regs = priv->tda18271_regs;
6888c2ecf20Sopenharmony_ci	u8 val;
6898c2ecf20Sopenharmony_ci
6908c2ecf20Sopenharmony_ci	int ret = tda18271_lookup_map(fe, RF_CAL, freq, &val);
6918c2ecf20Sopenharmony_ci	/* The TDA18271HD/C1 rf_cal map lookup is expected to go out of range
6928c2ecf20Sopenharmony_ci	 * for frequencies above 61.1 MHz.  In these cases, the internal RF
6938c2ecf20Sopenharmony_ci	 * tracking filters calibration mechanism is used.
6948c2ecf20Sopenharmony_ci	 *
6958c2ecf20Sopenharmony_ci	 * There is no need to warn the user about this.
6968c2ecf20Sopenharmony_ci	 */
6978c2ecf20Sopenharmony_ci	if (ret < 0)
6988c2ecf20Sopenharmony_ci		goto fail;
6998c2ecf20Sopenharmony_ci
7008c2ecf20Sopenharmony_ci	regs[R_EB14] = val;
7018c2ecf20Sopenharmony_cifail:
7028c2ecf20Sopenharmony_ci	return ret;
7038c2ecf20Sopenharmony_ci}
7048c2ecf20Sopenharmony_ci
7058c2ecf20Sopenharmony_civoid _tda_printk(struct tda18271_priv *state, const char *level,
7068c2ecf20Sopenharmony_ci		 const char *func, const char *fmt, ...)
7078c2ecf20Sopenharmony_ci{
7088c2ecf20Sopenharmony_ci	struct va_format vaf;
7098c2ecf20Sopenharmony_ci	va_list args;
7108c2ecf20Sopenharmony_ci
7118c2ecf20Sopenharmony_ci	va_start(args, fmt);
7128c2ecf20Sopenharmony_ci
7138c2ecf20Sopenharmony_ci	vaf.fmt = fmt;
7148c2ecf20Sopenharmony_ci	vaf.va = &args;
7158c2ecf20Sopenharmony_ci
7168c2ecf20Sopenharmony_ci	if (state)
7178c2ecf20Sopenharmony_ci		printk("%s%s: [%d-%04x|%c] %pV",
7188c2ecf20Sopenharmony_ci		       level, func, i2c_adapter_id(state->i2c_props.adap),
7198c2ecf20Sopenharmony_ci		       state->i2c_props.addr,
7208c2ecf20Sopenharmony_ci		       (state->role == TDA18271_MASTER) ? 'M' : 'S',
7218c2ecf20Sopenharmony_ci		       &vaf);
7228c2ecf20Sopenharmony_ci	else
7238c2ecf20Sopenharmony_ci		printk("%s%s: %pV", level, func, &vaf);
7248c2ecf20Sopenharmony_ci
7258c2ecf20Sopenharmony_ci	va_end(args);
7268c2ecf20Sopenharmony_ci}
727