root/drivers/media/tuners/tda18212.c

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

DEFINITIONS

This source file includes following definitions.
  1. tda18212_set_params
  2. tda18212_get_if_frequency
  3. tda18212_probe
  4. tda18212_remove

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  * NXP TDA18212HN silicon tuner driver
   4  *
   5  * Copyright (C) 2011 Antti Palosaari <crope@iki.fi>
   6  */
   7 
   8 #include "tda18212.h"
   9 #include <linux/regmap.h>
  10 
  11 struct tda18212_dev {
  12         struct tda18212_config cfg;
  13         struct i2c_client *client;
  14         struct regmap *regmap;
  15 
  16         u32 if_frequency;
  17 };
  18 
  19 static int tda18212_set_params(struct dvb_frontend *fe)
  20 {
  21         struct tda18212_dev *dev = fe->tuner_priv;
  22         struct dtv_frontend_properties *c = &fe->dtv_property_cache;
  23         int ret, i;
  24         u32 if_khz;
  25         u8 buf[9];
  26         #define DVBT_6   0
  27         #define DVBT_7   1
  28         #define DVBT_8   2
  29         #define DVBT2_6  3
  30         #define DVBT2_7  4
  31         #define DVBT2_8  5
  32         #define DVBC_6   6
  33         #define DVBC_8   7
  34         #define ATSC_VSB 8
  35         #define ATSC_QAM 9
  36         static const u8 bw_params[][3] = {
  37                      /* reg:   0f    13    23 */
  38                 [DVBT_6]  = { 0xb3, 0x20, 0x03 },
  39                 [DVBT_7]  = { 0xb3, 0x31, 0x01 },
  40                 [DVBT_8]  = { 0xb3, 0x22, 0x01 },
  41                 [DVBT2_6] = { 0xbc, 0x20, 0x03 },
  42                 [DVBT2_7] = { 0xbc, 0x72, 0x03 },
  43                 [DVBT2_8] = { 0xbc, 0x22, 0x01 },
  44                 [DVBC_6]  = { 0x92, 0x50, 0x03 },
  45                 [DVBC_8]  = { 0x92, 0x53, 0x03 },
  46                 [ATSC_VSB] = { 0x7d, 0x20, 0x63 },
  47                 [ATSC_QAM] = { 0x7d, 0x20, 0x63 },
  48         };
  49 
  50         dev_dbg(&dev->client->dev,
  51                         "delivery_system=%d frequency=%d bandwidth_hz=%d\n",
  52                         c->delivery_system, c->frequency,
  53                         c->bandwidth_hz);
  54 
  55         if (fe->ops.i2c_gate_ctrl)
  56                 fe->ops.i2c_gate_ctrl(fe, 1); /* open I2C-gate */
  57 
  58         switch (c->delivery_system) {
  59         case SYS_ATSC:
  60                 if_khz = dev->cfg.if_atsc_vsb;
  61                 i = ATSC_VSB;
  62                 break;
  63         case SYS_DVBC_ANNEX_B:
  64                 if_khz = dev->cfg.if_atsc_qam;
  65                 i = ATSC_QAM;
  66                 break;
  67         case SYS_DVBT:
  68                 switch (c->bandwidth_hz) {
  69                 case 6000000:
  70                         if_khz = dev->cfg.if_dvbt_6;
  71                         i = DVBT_6;
  72                         break;
  73                 case 7000000:
  74                         if_khz = dev->cfg.if_dvbt_7;
  75                         i = DVBT_7;
  76                         break;
  77                 case 8000000:
  78                         if_khz = dev->cfg.if_dvbt_8;
  79                         i = DVBT_8;
  80                         break;
  81                 default:
  82                         ret = -EINVAL;
  83                         goto error;
  84                 }
  85                 break;
  86         case SYS_DVBT2:
  87                 switch (c->bandwidth_hz) {
  88                 case 6000000:
  89                         if_khz = dev->cfg.if_dvbt2_6;
  90                         i = DVBT2_6;
  91                         break;
  92                 case 7000000:
  93                         if_khz = dev->cfg.if_dvbt2_7;
  94                         i = DVBT2_7;
  95                         break;
  96                 case 8000000:
  97                         if_khz = dev->cfg.if_dvbt2_8;
  98                         i = DVBT2_8;
  99                         break;
 100                 default:
 101                         ret = -EINVAL;
 102                         goto error;
 103                 }
 104                 break;
 105         case SYS_DVBC_ANNEX_A:
 106         case SYS_DVBC_ANNEX_C:
 107                 if_khz = dev->cfg.if_dvbc;
 108                 i = DVBC_8;
 109                 break;
 110         default:
 111                 ret = -EINVAL;
 112                 goto error;
 113         }
 114 
 115         ret = regmap_write(dev->regmap, 0x23, bw_params[i][2]);
 116         if (ret)
 117                 goto error;
 118 
 119         ret = regmap_write(dev->regmap, 0x06, 0x00);
 120         if (ret)
 121                 goto error;
 122 
 123         ret = regmap_write(dev->regmap, 0x0f, bw_params[i][0]);
 124         if (ret)
 125                 goto error;
 126 
 127         buf[0] = 0x02;
 128         buf[1] = bw_params[i][1];
 129         buf[2] = 0x03; /* default value */
 130         buf[3] = DIV_ROUND_CLOSEST(if_khz, 50);
 131         buf[4] = ((c->frequency / 1000) >> 16) & 0xff;
 132         buf[5] = ((c->frequency / 1000) >>  8) & 0xff;
 133         buf[6] = ((c->frequency / 1000) >>  0) & 0xff;
 134         buf[7] = 0xc1;
 135         buf[8] = 0x01;
 136         ret = regmap_bulk_write(dev->regmap, 0x12, buf, sizeof(buf));
 137         if (ret)
 138                 goto error;
 139 
 140         /* actual IF rounded as it is on register */
 141         dev->if_frequency = buf[3] * 50 * 1000;
 142 
 143 exit:
 144         if (fe->ops.i2c_gate_ctrl)
 145                 fe->ops.i2c_gate_ctrl(fe, 0); /* close I2C-gate */
 146 
 147         return ret;
 148 
 149 error:
 150         dev_dbg(&dev->client->dev, "failed=%d\n", ret);
 151         goto exit;
 152 }
 153 
 154 static int tda18212_get_if_frequency(struct dvb_frontend *fe, u32 *frequency)
 155 {
 156         struct tda18212_dev *dev = fe->tuner_priv;
 157 
 158         *frequency = dev->if_frequency;
 159 
 160         return 0;
 161 }
 162 
 163 static const struct dvb_tuner_ops tda18212_tuner_ops = {
 164         .info = {
 165                 .name              = "NXP TDA18212",
 166 
 167                 .frequency_min_hz  =  48 * MHz,
 168                 .frequency_max_hz  = 864 * MHz,
 169                 .frequency_step_hz =   1 * kHz,
 170         },
 171 
 172         .set_params    = tda18212_set_params,
 173         .get_if_frequency = tda18212_get_if_frequency,
 174 };
 175 
 176 static int tda18212_probe(struct i2c_client *client,
 177                 const struct i2c_device_id *id)
 178 {
 179         struct tda18212_config *cfg = client->dev.platform_data;
 180         struct dvb_frontend *fe = cfg->fe;
 181         struct tda18212_dev *dev;
 182         int ret;
 183         unsigned int chip_id;
 184         char *version;
 185         static const struct regmap_config regmap_config = {
 186                 .reg_bits = 8,
 187                 .val_bits = 8,
 188         };
 189 
 190         dev = kzalloc(sizeof(*dev), GFP_KERNEL);
 191         if (dev == NULL) {
 192                 ret = -ENOMEM;
 193                 dev_err(&client->dev, "kzalloc() failed\n");
 194                 goto err;
 195         }
 196 
 197         memcpy(&dev->cfg, cfg, sizeof(struct tda18212_config));
 198         dev->client = client;
 199         dev->regmap = devm_regmap_init_i2c(client, &regmap_config);
 200         if (IS_ERR(dev->regmap)) {
 201                 ret = PTR_ERR(dev->regmap);
 202                 goto err;
 203         }
 204 
 205         /* check if the tuner is there */
 206         if (fe->ops.i2c_gate_ctrl)
 207                 fe->ops.i2c_gate_ctrl(fe, 1); /* open I2C-gate */
 208 
 209         ret = regmap_read(dev->regmap, 0x00, &chip_id);
 210         dev_dbg(&dev->client->dev, "chip_id=%02x\n", chip_id);
 211 
 212         if (fe->ops.i2c_gate_ctrl)
 213                 fe->ops.i2c_gate_ctrl(fe, 0); /* close I2C-gate */
 214 
 215         if (ret)
 216                 goto err;
 217 
 218         switch (chip_id) {
 219         case 0xc7:
 220                 version = "M"; /* master */
 221                 break;
 222         case 0x47:
 223                 version = "S"; /* slave */
 224                 break;
 225         default:
 226                 ret = -ENODEV;
 227                 goto err;
 228         }
 229 
 230         dev_info(&dev->client->dev,
 231                         "NXP TDA18212HN/%s successfully identified\n", version);
 232 
 233         fe->tuner_priv = dev;
 234         memcpy(&fe->ops.tuner_ops, &tda18212_tuner_ops,
 235                         sizeof(struct dvb_tuner_ops));
 236         i2c_set_clientdata(client, dev);
 237 
 238         return 0;
 239 err:
 240         dev_dbg(&client->dev, "failed=%d\n", ret);
 241         kfree(dev);
 242         return ret;
 243 }
 244 
 245 static int tda18212_remove(struct i2c_client *client)
 246 {
 247         struct tda18212_dev *dev = i2c_get_clientdata(client);
 248         struct dvb_frontend *fe = dev->cfg.fe;
 249 
 250         dev_dbg(&client->dev, "\n");
 251 
 252         memset(&fe->ops.tuner_ops, 0, sizeof(struct dvb_tuner_ops));
 253         fe->tuner_priv = NULL;
 254         kfree(dev);
 255 
 256         return 0;
 257 }
 258 
 259 static const struct i2c_device_id tda18212_id[] = {
 260         {"tda18212", 0},
 261         {}
 262 };
 263 MODULE_DEVICE_TABLE(i2c, tda18212_id);
 264 
 265 static struct i2c_driver tda18212_driver = {
 266         .driver = {
 267                 .name   = "tda18212",
 268         },
 269         .probe          = tda18212_probe,
 270         .remove         = tda18212_remove,
 271         .id_table       = tda18212_id,
 272 };
 273 
 274 module_i2c_driver(tda18212_driver);
 275 
 276 MODULE_DESCRIPTION("NXP TDA18212HN silicon tuner driver");
 277 MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
 278 MODULE_LICENSE("GPL");

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