0001
0002
0003
0004
0005
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;
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, ®map_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");