^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) * Fitipower FC0011 tuner driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2012 Michael Buesch <m@bues.ch>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Derived from FC0012 tuner driver:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Copyright (C) 2012 Hans-Frieder Vogt <hfvogt@gmx.net>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include "fc0011.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) /* Tuner registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) enum {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) FC11_REG_0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) FC11_REG_FA, /* FA */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) FC11_REG_FP, /* FP */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) FC11_REG_XINHI, /* XIN high 8 bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) FC11_REG_XINLO, /* XIN low 8 bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) FC11_REG_VCO, /* VCO */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) FC11_REG_VCOSEL, /* VCO select */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) FC11_REG_7, /* Unknown tuner reg 7 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) FC11_REG_8, /* Unknown tuner reg 8 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) FC11_REG_9,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) FC11_REG_10, /* Unknown tuner reg 10 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) FC11_REG_11, /* Unknown tuner reg 11 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) FC11_REG_12,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) FC11_REG_RCCAL, /* RC calibrate */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) FC11_REG_VCOCAL, /* VCO calibrate */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) FC11_REG_15,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) FC11_REG_16, /* Unknown tuner reg 16 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) FC11_REG_17,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) FC11_NR_REGS, /* Number of registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) enum FC11_REG_VCOSEL_bits {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) FC11_VCOSEL_2 = 0x08, /* VCO select 2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) FC11_VCOSEL_1 = 0x10, /* VCO select 1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) FC11_VCOSEL_CLKOUT = 0x20, /* Fix clock out */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) FC11_VCOSEL_BW7M = 0x40, /* 7MHz bw */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) FC11_VCOSEL_BW6M = 0x80, /* 6MHz bw */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) enum FC11_REG_RCCAL_bits {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) FC11_RCCAL_FORCE = 0x10, /* force */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) enum FC11_REG_VCOCAL_bits {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) FC11_VCOCAL_RUN = 0, /* VCO calibration run */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) FC11_VCOCAL_VALUEMASK = 0x3F, /* VCO calibration value mask */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) FC11_VCOCAL_OK = 0x40, /* VCO calibration Ok */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) FC11_VCOCAL_RESET = 0x80, /* VCO calibration reset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) struct fc0011_priv {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) struct i2c_adapter *i2c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) u8 addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) u32 frequency;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) u32 bandwidth;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) static int fc0011_writereg(struct fc0011_priv *priv, u8 reg, u8 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) u8 buf[2] = { reg, val };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) struct i2c_msg msg = { .addr = priv->addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) .flags = 0, .buf = buf, .len = 2 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) if (i2c_transfer(priv->i2c, &msg, 1) != 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) dev_err(&priv->i2c->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) "I2C write reg failed, reg: %02x, val: %02x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) reg, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) static int fc0011_readreg(struct fc0011_priv *priv, u8 reg, u8 *val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) u8 dummy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) struct i2c_msg msg[2] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) { .addr = priv->addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) .flags = 0, .buf = ®, .len = 1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) { .addr = priv->addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) .flags = I2C_M_RD, .buf = val ? : &dummy, .len = 1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) if (i2c_transfer(priv->i2c, msg, 2) != 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) dev_err(&priv->i2c->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) "I2C read failed, reg: %02x\n", reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) static void fc0011_release(struct dvb_frontend *fe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) kfree(fe->tuner_priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) fe->tuner_priv = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) static int fc0011_init(struct dvb_frontend *fe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) struct fc0011_priv *priv = fe->tuner_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) if (WARN_ON(!fe->callback))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) err = fe->callback(priv->i2c, DVB_FRONTEND_COMPONENT_TUNER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) FC0011_FE_CALLBACK_POWER, priv->addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) dev_err(&priv->i2c->dev, "Power-on callback failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) err = fe->callback(priv->i2c, DVB_FRONTEND_COMPONENT_TUNER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) FC0011_FE_CALLBACK_RESET, priv->addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) dev_err(&priv->i2c->dev, "Reset callback failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) /* Initiate VCO calibration */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) static int fc0011_vcocal_trigger(struct fc0011_priv *priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) err = fc0011_writereg(priv, FC11_REG_VCOCAL, FC11_VCOCAL_RESET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) err = fc0011_writereg(priv, FC11_REG_VCOCAL, FC11_VCOCAL_RUN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) /* Read VCO calibration value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) static int fc0011_vcocal_read(struct fc0011_priv *priv, u8 *value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) err = fc0011_writereg(priv, FC11_REG_VCOCAL, FC11_VCOCAL_RUN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) usleep_range(10000, 20000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) err = fc0011_readreg(priv, FC11_REG_VCOCAL, value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) static int fc0011_set_params(struct dvb_frontend *fe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) struct dtv_frontend_properties *p = &fe->dtv_property_cache;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) struct fc0011_priv *priv = fe->tuner_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) unsigned int i, vco_retries;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) u32 freq = p->frequency / 1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) u32 bandwidth = p->bandwidth_hz / 1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) u32 fvco, xin, frac, xdiv, xdivr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) u8 fa, fp, vco_sel, vco_cal;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) u8 regs[FC11_NR_REGS] = { };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) regs[FC11_REG_7] = 0x0F;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) regs[FC11_REG_8] = 0x3E;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) regs[FC11_REG_10] = 0xB8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) regs[FC11_REG_11] = 0x80;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) regs[FC11_REG_RCCAL] = 0x04;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) err = fc0011_writereg(priv, FC11_REG_7, regs[FC11_REG_7]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) err |= fc0011_writereg(priv, FC11_REG_8, regs[FC11_REG_8]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) err |= fc0011_writereg(priv, FC11_REG_10, regs[FC11_REG_10]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) err |= fc0011_writereg(priv, FC11_REG_11, regs[FC11_REG_11]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) err |= fc0011_writereg(priv, FC11_REG_RCCAL, regs[FC11_REG_RCCAL]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) /* Set VCO freq and VCO div */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) if (freq < 54000) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) fvco = freq * 64;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) regs[FC11_REG_VCO] = 0x82;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) } else if (freq < 108000) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) fvco = freq * 32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) regs[FC11_REG_VCO] = 0x42;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) } else if (freq < 216000) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) fvco = freq * 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) regs[FC11_REG_VCO] = 0x22;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) } else if (freq < 432000) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) fvco = freq * 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) regs[FC11_REG_VCO] = 0x12;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) fvco = freq * 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) regs[FC11_REG_VCO] = 0x0A;
^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) /* Calc XIN. The PLL reference frequency is 18 MHz. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) xdiv = fvco / 18000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) WARN_ON(xdiv > 0xFF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) frac = fvco - xdiv * 18000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) frac = (frac << 15) / 18000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) if (frac >= 16384)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) frac += 32786;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) if (!frac)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) xin = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) xin = clamp_t(u32, frac, 512, 65024);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) regs[FC11_REG_XINHI] = xin >> 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) regs[FC11_REG_XINLO] = xin;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) /* Calc FP and FA */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) xdivr = xdiv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) if (fvco - xdiv * 18000 >= 9000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) xdivr += 1; /* round */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) fp = xdivr / 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) fa = xdivr - fp * 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) if (fa < 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) fp -= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) fa += 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) if (fp > 0x1F) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) fp = 0x1F;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) fa = 0xF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) if (fa >= fp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) dev_warn(&priv->i2c->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) "fa %02X >= fp %02X, but trying to continue\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) (unsigned int)(u8)fa, (unsigned int)(u8)fp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) regs[FC11_REG_FA] = fa;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) regs[FC11_REG_FP] = fp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) /* Select bandwidth */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) switch (bandwidth) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) case 8000:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) case 7000:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) regs[FC11_REG_VCOSEL] |= FC11_VCOSEL_BW7M;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) dev_warn(&priv->i2c->dev, "Unsupported bandwidth %u kHz. Using 6000 kHz.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) bandwidth);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) bandwidth = 6000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) case 6000:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) regs[FC11_REG_VCOSEL] |= FC11_VCOSEL_BW6M;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) /* Pre VCO select */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) if (fvco < 2320000) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) vco_sel = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) regs[FC11_REG_VCOSEL] &= ~(FC11_VCOSEL_1 | FC11_VCOSEL_2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) } else if (fvco < 3080000) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) vco_sel = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) regs[FC11_REG_VCOSEL] &= ~(FC11_VCOSEL_1 | FC11_VCOSEL_2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) regs[FC11_REG_VCOSEL] |= FC11_VCOSEL_1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) vco_sel = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) regs[FC11_REG_VCOSEL] &= ~(FC11_VCOSEL_1 | FC11_VCOSEL_2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) regs[FC11_REG_VCOSEL] |= FC11_VCOSEL_2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) /* Fix for low freqs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) if (freq < 45000) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) regs[FC11_REG_FA] = 0x6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) regs[FC11_REG_FP] = 0x11;
^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) /* Clock out fix */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) regs[FC11_REG_VCOSEL] |= FC11_VCOSEL_CLKOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) /* Write the cached registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) for (i = FC11_REG_FA; i <= FC11_REG_VCOSEL; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) err = fc0011_writereg(priv, i, regs[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) /* VCO calibration */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) err = fc0011_vcocal_trigger(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) err = fc0011_vcocal_read(priv, &vco_cal);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) vco_retries = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) while (!(vco_cal & FC11_VCOCAL_OK) && vco_retries < 3) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) /* Reset the tuner and try again */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) err = fe->callback(priv->i2c, DVB_FRONTEND_COMPONENT_TUNER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) FC0011_FE_CALLBACK_RESET, priv->addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) dev_err(&priv->i2c->dev, "Failed to reset tuner\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) /* Reinit tuner config */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) for (i = FC11_REG_FA; i <= FC11_REG_VCOSEL; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) err |= fc0011_writereg(priv, i, regs[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) err |= fc0011_writereg(priv, FC11_REG_7, regs[FC11_REG_7]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) err |= fc0011_writereg(priv, FC11_REG_8, regs[FC11_REG_8]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) err |= fc0011_writereg(priv, FC11_REG_10, regs[FC11_REG_10]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) err |= fc0011_writereg(priv, FC11_REG_11, regs[FC11_REG_11]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) err |= fc0011_writereg(priv, FC11_REG_RCCAL, regs[FC11_REG_RCCAL]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) /* VCO calibration */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) err = fc0011_vcocal_trigger(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) err = fc0011_vcocal_read(priv, &vco_cal);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) vco_retries++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) if (!(vco_cal & FC11_VCOCAL_OK)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) dev_err(&priv->i2c->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) "Failed to read VCO calibration value (got %02X)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) (unsigned int)vco_cal);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) vco_cal &= FC11_VCOCAL_VALUEMASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) switch (vco_sel) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) WARN_ON(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) if (vco_cal < 8) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) regs[FC11_REG_VCOSEL] &= ~(FC11_VCOSEL_1 | FC11_VCOSEL_2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) regs[FC11_REG_VCOSEL] |= FC11_VCOSEL_1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) err = fc0011_writereg(priv, FC11_REG_VCOSEL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) regs[FC11_REG_VCOSEL]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) err = fc0011_vcocal_trigger(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) regs[FC11_REG_VCOSEL] &= ~(FC11_VCOSEL_1 | FC11_VCOSEL_2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) err = fc0011_writereg(priv, FC11_REG_VCOSEL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) regs[FC11_REG_VCOSEL]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) if (vco_cal < 5) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) regs[FC11_REG_VCOSEL] &= ~(FC11_VCOSEL_1 | FC11_VCOSEL_2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) regs[FC11_REG_VCOSEL] |= FC11_VCOSEL_2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) err = fc0011_writereg(priv, FC11_REG_VCOSEL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) regs[FC11_REG_VCOSEL]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) err = fc0011_vcocal_trigger(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) } else if (vco_cal <= 48) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) regs[FC11_REG_VCOSEL] &= ~(FC11_VCOSEL_1 | FC11_VCOSEL_2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) regs[FC11_REG_VCOSEL] |= FC11_VCOSEL_1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) err = fc0011_writereg(priv, FC11_REG_VCOSEL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) regs[FC11_REG_VCOSEL]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) regs[FC11_REG_VCOSEL] &= ~(FC11_VCOSEL_1 | FC11_VCOSEL_2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) err = fc0011_writereg(priv, FC11_REG_VCOSEL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) regs[FC11_REG_VCOSEL]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) err = fc0011_vcocal_trigger(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) if (vco_cal > 53) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) regs[FC11_REG_VCOSEL] &= ~(FC11_VCOSEL_1 | FC11_VCOSEL_2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) regs[FC11_REG_VCOSEL] |= FC11_VCOSEL_1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) err = fc0011_writereg(priv, FC11_REG_VCOSEL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) regs[FC11_REG_VCOSEL]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) err = fc0011_vcocal_trigger(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) regs[FC11_REG_VCOSEL] &= ~(FC11_VCOSEL_1 | FC11_VCOSEL_2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) regs[FC11_REG_VCOSEL] |= FC11_VCOSEL_2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) err = fc0011_writereg(priv, FC11_REG_VCOSEL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) regs[FC11_REG_VCOSEL]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) err = fc0011_vcocal_read(priv, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) usleep_range(10000, 50000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) err = fc0011_readreg(priv, FC11_REG_RCCAL, ®s[FC11_REG_RCCAL]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) regs[FC11_REG_RCCAL] |= FC11_RCCAL_FORCE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) err = fc0011_writereg(priv, FC11_REG_RCCAL, regs[FC11_REG_RCCAL]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) regs[FC11_REG_16] = 0xB;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) err = fc0011_writereg(priv, FC11_REG_16, regs[FC11_REG_16]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) dev_dbg(&priv->i2c->dev, "Tuned to fa=%02X fp=%02X xin=%02X%02X vco=%02X vcosel=%02X vcocal=%02X(%u) bw=%u\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) (unsigned int)regs[FC11_REG_FA],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) (unsigned int)regs[FC11_REG_FP],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) (unsigned int)regs[FC11_REG_XINHI],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) (unsigned int)regs[FC11_REG_XINLO],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) (unsigned int)regs[FC11_REG_VCO],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) (unsigned int)regs[FC11_REG_VCOSEL],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) (unsigned int)vco_cal, vco_retries,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) (unsigned int)bandwidth);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) priv->frequency = p->frequency;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) priv->bandwidth = p->bandwidth_hz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) static int fc0011_get_frequency(struct dvb_frontend *fe, u32 *frequency)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) struct fc0011_priv *priv = fe->tuner_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) *frequency = priv->frequency;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) static int fc0011_get_if_frequency(struct dvb_frontend *fe, u32 *frequency)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) *frequency = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) static int fc0011_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) struct fc0011_priv *priv = fe->tuner_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) *bandwidth = priv->bandwidth;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) static const struct dvb_tuner_ops fc0011_tuner_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) .info = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) .name = "Fitipower FC0011",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) .frequency_min_hz = 45 * MHz,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) .frequency_max_hz = 1000 * MHz,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) .release = fc0011_release,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) .init = fc0011_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) .set_params = fc0011_set_params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) .get_frequency = fc0011_get_frequency,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) .get_if_frequency = fc0011_get_if_frequency,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) .get_bandwidth = fc0011_get_bandwidth,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) struct dvb_frontend *fc0011_attach(struct dvb_frontend *fe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) struct i2c_adapter *i2c,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) const struct fc0011_config *config)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) struct fc0011_priv *priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) priv = kzalloc(sizeof(struct fc0011_priv), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) if (!priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) priv->i2c = i2c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) priv->addr = config->i2c_address;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) fe->tuner_priv = priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) fe->ops.tuner_ops = fc0011_tuner_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) dev_info(&priv->i2c->dev, "Fitipower FC0011 tuner attached\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) return fe;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) EXPORT_SYMBOL(fc0011_attach);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) MODULE_DESCRIPTION("Fitipower FC0011 silicon tuner driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) MODULE_AUTHOR("Michael Buesch <m@bues.ch>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) MODULE_LICENSE("GPL");