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