Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * Infineon TUA9001 silicon tuner driver
0004  *
0005  * Copyright (C) 2009 Antti Palosaari <crope@iki.fi>
0006  */
0007 
0008 #include "tua9001_priv.h"
0009 
0010 static int tua9001_init(struct dvb_frontend *fe)
0011 {
0012     struct tua9001_dev *dev = fe->tuner_priv;
0013     struct i2c_client *client = dev->client;
0014     int ret, i;
0015     static const struct tua9001_reg_val data[] = {
0016         {0x1e, 0x6512},
0017         {0x25, 0xb888},
0018         {0x39, 0x5460},
0019         {0x3b, 0x00c0},
0020         {0x3a, 0xf000},
0021         {0x08, 0x0000},
0022         {0x32, 0x0030},
0023         {0x41, 0x703a},
0024         {0x40, 0x1c78},
0025         {0x2c, 0x1c00},
0026         {0x36, 0xc013},
0027         {0x37, 0x6f18},
0028         {0x27, 0x0008},
0029         {0x2a, 0x0001},
0030         {0x34, 0x0a40},
0031     };
0032 
0033     dev_dbg(&client->dev, "\n");
0034 
0035     if (fe->callback) {
0036         ret = fe->callback(client->adapter,
0037                    DVB_FRONTEND_COMPONENT_TUNER,
0038                    TUA9001_CMD_RESETN, 0);
0039         if (ret)
0040             goto err;
0041     }
0042 
0043     for (i = 0; i < ARRAY_SIZE(data); i++) {
0044         ret = regmap_write(dev->regmap, data[i].reg, data[i].val);
0045         if (ret)
0046             goto err;
0047     }
0048     return 0;
0049 err:
0050     dev_dbg(&client->dev, "failed=%d\n", ret);
0051     return ret;
0052 }
0053 
0054 static int tua9001_sleep(struct dvb_frontend *fe)
0055 {
0056     struct tua9001_dev *dev = fe->tuner_priv;
0057     struct i2c_client *client = dev->client;
0058     int ret;
0059 
0060     dev_dbg(&client->dev, "\n");
0061 
0062     if (fe->callback) {
0063         ret = fe->callback(client->adapter,
0064                    DVB_FRONTEND_COMPONENT_TUNER,
0065                    TUA9001_CMD_RESETN, 1);
0066         if (ret)
0067             goto err;
0068     }
0069     return 0;
0070 err:
0071     dev_dbg(&client->dev, "failed=%d\n", ret);
0072     return ret;
0073 }
0074 
0075 static int tua9001_set_params(struct dvb_frontend *fe)
0076 {
0077     struct tua9001_dev *dev = fe->tuner_priv;
0078     struct i2c_client *client = dev->client;
0079     struct dtv_frontend_properties *c = &fe->dtv_property_cache;
0080     int ret, i;
0081     u16 val;
0082     struct tua9001_reg_val data[2];
0083 
0084     dev_dbg(&client->dev,
0085         "delivery_system=%u frequency=%u bandwidth_hz=%u\n",
0086         c->delivery_system, c->frequency, c->bandwidth_hz);
0087 
0088     switch (c->delivery_system) {
0089     case SYS_DVBT:
0090         switch (c->bandwidth_hz) {
0091         case 8000000:
0092             val  = 0x0000;
0093             break;
0094         case 7000000:
0095             val  = 0x1000;
0096             break;
0097         case 6000000:
0098             val  = 0x2000;
0099             break;
0100         case 5000000:
0101             val  = 0x3000;
0102             break;
0103         default:
0104             ret = -EINVAL;
0105             goto err;
0106         }
0107         break;
0108     default:
0109         ret = -EINVAL;
0110         goto err;
0111     }
0112 
0113     data[0].reg = 0x04;
0114     data[0].val = val;
0115     data[1].reg = 0x1f;
0116     data[1].val = div_u64((u64) (c->frequency - 150000000) * 48, 1000000);
0117 
0118     if (fe->callback) {
0119         ret = fe->callback(client->adapter,
0120                    DVB_FRONTEND_COMPONENT_TUNER,
0121                    TUA9001_CMD_RXEN, 0);
0122         if (ret)
0123             goto err;
0124     }
0125 
0126     for (i = 0; i < ARRAY_SIZE(data); i++) {
0127         ret = regmap_write(dev->regmap, data[i].reg, data[i].val);
0128         if (ret)
0129             goto err;
0130     }
0131 
0132     if (fe->callback) {
0133         ret = fe->callback(client->adapter,
0134                    DVB_FRONTEND_COMPONENT_TUNER,
0135                    TUA9001_CMD_RXEN, 1);
0136         if (ret)
0137             goto err;
0138     }
0139     return 0;
0140 err:
0141     dev_dbg(&client->dev, "failed=%d\n", ret);
0142     return ret;
0143 }
0144 
0145 static int tua9001_get_if_frequency(struct dvb_frontend *fe, u32 *frequency)
0146 {
0147     struct tua9001_dev *dev = fe->tuner_priv;
0148     struct i2c_client *client = dev->client;
0149 
0150     dev_dbg(&client->dev, "\n");
0151 
0152     *frequency = 0; /* Zero-IF */
0153     return 0;
0154 }
0155 
0156 static const struct dvb_tuner_ops tua9001_tuner_ops = {
0157     .info = {
0158         .name             = "Infineon TUA9001",
0159         .frequency_min_hz = 170 * MHz,
0160         .frequency_max_hz = 862 * MHz,
0161     },
0162 
0163     .init = tua9001_init,
0164     .sleep = tua9001_sleep,
0165     .set_params = tua9001_set_params,
0166 
0167     .get_if_frequency = tua9001_get_if_frequency,
0168 };
0169 
0170 static int tua9001_probe(struct i2c_client *client,
0171             const struct i2c_device_id *id)
0172 {
0173     struct tua9001_dev *dev;
0174     struct tua9001_platform_data *pdata = client->dev.platform_data;
0175     struct dvb_frontend *fe = pdata->dvb_frontend;
0176     int ret;
0177     static const struct regmap_config regmap_config = {
0178         .reg_bits =  8,
0179         .val_bits = 16,
0180     };
0181 
0182     dev = kzalloc(sizeof(*dev), GFP_KERNEL);
0183     if (!dev) {
0184         ret = -ENOMEM;
0185         goto err;
0186     }
0187 
0188     dev->fe = pdata->dvb_frontend;
0189     dev->client = client;
0190     dev->regmap = devm_regmap_init_i2c(client, &regmap_config);
0191     if (IS_ERR(dev->regmap)) {
0192         ret = PTR_ERR(dev->regmap);
0193         goto err_kfree;
0194     }
0195 
0196     if (fe->callback) {
0197         ret = fe->callback(client->adapter,
0198                    DVB_FRONTEND_COMPONENT_TUNER,
0199                    TUA9001_CMD_CEN, 1);
0200         if (ret)
0201             goto err_kfree;
0202 
0203         ret = fe->callback(client->adapter,
0204                    DVB_FRONTEND_COMPONENT_TUNER,
0205                    TUA9001_CMD_RXEN, 0);
0206         if (ret)
0207             goto err_kfree;
0208 
0209         ret = fe->callback(client->adapter,
0210                    DVB_FRONTEND_COMPONENT_TUNER,
0211                    TUA9001_CMD_RESETN, 1);
0212         if (ret)
0213             goto err_kfree;
0214     }
0215 
0216     fe->tuner_priv = dev;
0217     memcpy(&fe->ops.tuner_ops, &tua9001_tuner_ops,
0218             sizeof(struct dvb_tuner_ops));
0219     i2c_set_clientdata(client, dev);
0220 
0221     dev_info(&client->dev, "Infineon TUA9001 successfully attached\n");
0222     return 0;
0223 err_kfree:
0224     kfree(dev);
0225 err:
0226     dev_dbg(&client->dev, "failed=%d\n", ret);
0227     return ret;
0228 }
0229 
0230 static int tua9001_remove(struct i2c_client *client)
0231 {
0232     struct tua9001_dev *dev = i2c_get_clientdata(client);
0233     struct dvb_frontend *fe = dev->fe;
0234     int ret;
0235 
0236     dev_dbg(&client->dev, "\n");
0237 
0238     if (fe->callback) {
0239         ret = fe->callback(client->adapter,
0240                    DVB_FRONTEND_COMPONENT_TUNER,
0241                    TUA9001_CMD_CEN, 0);
0242         if (ret)
0243             dev_err(&client->dev, "Tuner disable failed (%pe)\n", ERR_PTR(ret));
0244     }
0245     kfree(dev);
0246     return 0;
0247 }
0248 
0249 static const struct i2c_device_id tua9001_id_table[] = {
0250     {"tua9001", 0},
0251     {}
0252 };
0253 MODULE_DEVICE_TABLE(i2c, tua9001_id_table);
0254 
0255 static struct i2c_driver tua9001_driver = {
0256     .driver = {
0257         .name   = "tua9001",
0258         .suppress_bind_attrs = true,
0259     },
0260     .probe      = tua9001_probe,
0261     .remove     = tua9001_remove,
0262     .id_table   = tua9001_id_table,
0263 };
0264 
0265 module_i2c_driver(tua9001_driver);
0266 
0267 MODULE_DESCRIPTION("Infineon TUA9001 silicon tuner driver");
0268 MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
0269 MODULE_LICENSE("GPL");