^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * NXP TDA18218HN silicon tuner driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2010 Antti Palosaari <crope@iki.fi>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include "tda18218_priv.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) /* Max transfer size done by I2C transfer functions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #define MAX_XFER_SIZE 64
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) /* write multiple registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) static int tda18218_wr_regs(struct tda18218_priv *priv, u8 reg, u8 *val, u8 len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) int ret = 0, len2, remaining;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) u8 buf[MAX_XFER_SIZE];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) struct i2c_msg msg[1] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) .addr = priv->cfg->i2c_address,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) .flags = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) .buf = buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) if (1 + len > sizeof(buf)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) dev_warn(&priv->i2c->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) "%s: i2c wr reg=%04x: len=%d is too big!\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) KBUILD_MODNAME, reg, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) for (remaining = len; remaining > 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) remaining -= (priv->cfg->i2c_wr_max - 1)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) len2 = remaining;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) if (len2 > (priv->cfg->i2c_wr_max - 1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) len2 = (priv->cfg->i2c_wr_max - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) msg[0].len = 1 + len2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) buf[0] = reg + len - remaining;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) memcpy(&buf[1], &val[len - remaining], len2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) ret = i2c_transfer(priv->i2c, msg, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) if (ret != 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) if (ret == 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) dev_warn(&priv->i2c->dev, "%s: i2c wr failed=%d reg=%02x " \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) "len=%d\n", KBUILD_MODNAME, ret, reg, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) ret = -EREMOTEIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) /* read multiple registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) static int tda18218_rd_regs(struct tda18218_priv *priv, u8 reg, u8 *val, u8 len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) u8 buf[MAX_XFER_SIZE]; /* we must start read always from reg 0x00 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) struct i2c_msg msg[2] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) .addr = priv->cfg->i2c_address,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) .flags = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) .len = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) .buf = "\x00",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) .addr = priv->cfg->i2c_address,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) .flags = I2C_M_RD,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) .len = reg + len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) .buf = buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) if (reg + len > sizeof(buf)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) dev_warn(&priv->i2c->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) "%s: i2c wr reg=%04x: len=%d is too big!\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) KBUILD_MODNAME, reg, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) ret = i2c_transfer(priv->i2c, msg, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) if (ret == 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) memcpy(val, &buf[reg], len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) dev_warn(&priv->i2c->dev, "%s: i2c rd failed=%d reg=%02x " \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) "len=%d\n", KBUILD_MODNAME, ret, reg, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) ret = -EREMOTEIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) /* write single register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) static int tda18218_wr_reg(struct tda18218_priv *priv, u8 reg, u8 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) return tda18218_wr_regs(priv, reg, &val, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) /* read single register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) static int tda18218_rd_reg(struct tda18218_priv *priv, u8 reg, u8 *val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) return tda18218_rd_regs(priv, reg, val, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) static int tda18218_set_params(struct dvb_frontend *fe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) struct tda18218_priv *priv = fe->tuner_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) struct dtv_frontend_properties *c = &fe->dtv_property_cache;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) u32 bw = c->bandwidth_hz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) u8 buf[3], i, BP_Filter, LP_Fc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) u32 LO_Frac;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) /* TODO: find out correct AGC algorithm */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) u8 agc[][2] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) { R20_AGC11, 0x60 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) { R23_AGC21, 0x02 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) { R20_AGC11, 0xa0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) { R23_AGC21, 0x09 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) { R20_AGC11, 0xe0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) { R23_AGC21, 0x0c },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) { R20_AGC11, 0x40 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) { R23_AGC21, 0x01 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) { R20_AGC11, 0x80 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) { R23_AGC21, 0x08 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) { R20_AGC11, 0xc0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) { R23_AGC21, 0x0b },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) { R24_AGC22, 0x1c },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) { R24_AGC22, 0x0c },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) if (fe->ops.i2c_gate_ctrl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) fe->ops.i2c_gate_ctrl(fe, 1); /* open I2C-gate */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) /* low-pass filter cut-off frequency */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) if (bw <= 6000000) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) LP_Fc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) priv->if_frequency = 3000000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) } else if (bw <= 7000000) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) LP_Fc = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) priv->if_frequency = 3500000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) LP_Fc = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) priv->if_frequency = 4000000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) LO_Frac = c->frequency + priv->if_frequency;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) /* band-pass filter */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) if (LO_Frac < 188000000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) BP_Filter = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) else if (LO_Frac < 253000000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) BP_Filter = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) else if (LO_Frac < 343000000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) BP_Filter = 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) BP_Filter = 6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) buf[0] = (priv->regs[R1A_IF1] & ~7) | BP_Filter; /* BP_Filter */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) buf[1] = (priv->regs[R1B_IF2] & ~3) | LP_Fc; /* LP_Fc */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) buf[2] = priv->regs[R1C_AGC2B];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) ret = tda18218_wr_regs(priv, R1A_IF1, buf, 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) buf[0] = (LO_Frac / 1000) >> 12; /* LO_Frac_0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) buf[1] = (LO_Frac / 1000) >> 4; /* LO_Frac_1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) buf[2] = (LO_Frac / 1000) << 4 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) (priv->regs[R0C_MD5] & 0x0f); /* LO_Frac_2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) ret = tda18218_wr_regs(priv, R0A_MD3, buf, 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) buf[0] = priv->regs[R0F_MD8] | (1 << 6); /* Freq_prog_Start */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) ret = tda18218_wr_regs(priv, R0F_MD8, buf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) buf[0] = priv->regs[R0F_MD8] & ~(1 << 6); /* Freq_prog_Start */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) ret = tda18218_wr_regs(priv, R0F_MD8, buf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) /* trigger AGC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) for (i = 0; i < ARRAY_SIZE(agc); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) ret = tda18218_wr_reg(priv, agc[i][0], agc[i][1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) if (fe->ops.i2c_gate_ctrl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) fe->ops.i2c_gate_ctrl(fe, 0); /* close I2C-gate */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) static int tda18218_get_if_frequency(struct dvb_frontend *fe, u32 *frequency)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) struct tda18218_priv *priv = fe->tuner_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) *frequency = priv->if_frequency;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) dev_dbg(&priv->i2c->dev, "%s: if_frequency=%d\n", __func__, *frequency);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) static int tda18218_sleep(struct dvb_frontend *fe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) struct tda18218_priv *priv = fe->tuner_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) if (fe->ops.i2c_gate_ctrl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) fe->ops.i2c_gate_ctrl(fe, 1); /* open I2C-gate */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) /* standby */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) ret = tda18218_wr_reg(priv, R17_PD1, priv->regs[R17_PD1] | (1 << 0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) if (fe->ops.i2c_gate_ctrl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) fe->ops.i2c_gate_ctrl(fe, 0); /* close I2C-gate */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) static int tda18218_init(struct dvb_frontend *fe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) struct tda18218_priv *priv = fe->tuner_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) /* TODO: calibrations */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) if (fe->ops.i2c_gate_ctrl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) fe->ops.i2c_gate_ctrl(fe, 1); /* open I2C-gate */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) ret = tda18218_wr_regs(priv, R00_ID, priv->regs, TDA18218_NUM_REGS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) if (fe->ops.i2c_gate_ctrl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) fe->ops.i2c_gate_ctrl(fe, 0); /* close I2C-gate */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) static void tda18218_release(struct dvb_frontend *fe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) kfree(fe->tuner_priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) fe->tuner_priv = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) static const struct dvb_tuner_ops tda18218_tuner_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) .info = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) .name = "NXP TDA18218",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) .frequency_min_hz = 174 * MHz,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) .frequency_max_hz = 864 * MHz,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) .frequency_step_hz = 1 * kHz,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) .release = tda18218_release,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) .init = tda18218_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) .sleep = tda18218_sleep,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) .set_params = tda18218_set_params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) .get_if_frequency = tda18218_get_if_frequency,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) struct dvb_frontend *tda18218_attach(struct dvb_frontend *fe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) struct i2c_adapter *i2c, struct tda18218_config *cfg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) struct tda18218_priv *priv = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) u8 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) /* chip default registers values */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) static u8 def_regs[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) 0xc0, 0x88, 0x00, 0x8e, 0x03, 0x00, 0x00, 0xd0, 0x00, 0x40,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) 0x00, 0x00, 0x07, 0xff, 0x84, 0x09, 0x00, 0x13, 0x00, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) 0x01, 0x84, 0x09, 0xf0, 0x19, 0x0a, 0x8e, 0x69, 0x98, 0x01,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) 0x00, 0x58, 0x10, 0x40, 0x8c, 0x00, 0x0c, 0x48, 0x85, 0xc9,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) 0xa7, 0x00, 0x00, 0x00, 0x30, 0x81, 0x80, 0x00, 0x39, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) 0x8a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf6, 0xf6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) priv = kzalloc(sizeof(struct tda18218_priv), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) if (priv == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) priv->cfg = cfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) priv->i2c = i2c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) fe->tuner_priv = priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) if (fe->ops.i2c_gate_ctrl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) fe->ops.i2c_gate_ctrl(fe, 1); /* open I2C-gate */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) /* check if the tuner is there */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) ret = tda18218_rd_reg(priv, R00_ID, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) if (!ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) dev_dbg(&priv->i2c->dev, "%s: chip id=%02x\n", __func__, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) if (ret || val != def_regs[R00_ID]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) kfree(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) dev_info(&priv->i2c->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) "%s: NXP TDA18218HN successfully identified\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) KBUILD_MODNAME);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) memcpy(&fe->ops.tuner_ops, &tda18218_tuner_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) sizeof(struct dvb_tuner_ops));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) memcpy(priv->regs, def_regs, sizeof(def_regs));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) /* loop-through enabled chip default register values */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) if (priv->cfg->loop_through) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) priv->regs[R17_PD1] = 0xb0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) priv->regs[R18_PD2] = 0x59;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) /* standby */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) ret = tda18218_wr_reg(priv, R17_PD1, priv->regs[R17_PD1] | (1 << 0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) if (fe->ops.i2c_gate_ctrl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) fe->ops.i2c_gate_ctrl(fe, 0); /* close I2C-gate */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) return fe;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) EXPORT_SYMBOL(tda18218_attach);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) MODULE_DESCRIPTION("NXP TDA18218HN silicon tuner driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) MODULE_LICENSE("GPL");