root/drivers/media/tuners/tda18218.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. tda18218_wr_regs
  2. tda18218_rd_regs
  3. tda18218_wr_reg
  4. tda18218_rd_reg
  5. tda18218_set_params
  6. tda18218_get_if_frequency
  7. tda18218_sleep
  8. tda18218_init
  9. tda18218_release
  10. tda18218_attach

   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 */
  14 static 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 */
  60 static 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 */
  99 static 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 
 106 static int tda18218_rd_reg(struct tda18218_priv *priv, u8 reg, u8 *val)
 107 {
 108         return tda18218_rd_regs(priv, reg, val, 1);
 109 }
 110 
 111 static 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 
 196 error:
 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 
 206 static 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 
 214 static 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 
 234 static 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 
 255 static void tda18218_release(struct dvb_frontend *fe)
 256 {
 257         kfree(fe->tuner_priv);
 258         fe->tuner_priv = NULL;
 259 }
 260 
 261 static 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 
 279 struct 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 }
 339 EXPORT_SYMBOL(tda18218_attach);
 340 
 341 MODULE_DESCRIPTION("NXP TDA18218HN silicon tuner driver");
 342 MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
 343 MODULE_LICENSE("GPL");

/* [<][>][^][v][top][bottom][index][help] */