0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <linux/module.h>
0010 #include <linux/gcd.h>
0011 #include <media/v4l2-device.h>
0012 #include <media/v4l2-ctrls.h>
0013
0014 static const struct v4l2_frequency_band bands[] = {
0015 {
0016 .type = V4L2_TUNER_RF,
0017 .index = 0,
0018 .capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS,
0019 .rangelow = 49000000,
0020 .rangehigh = 263000000,
0021 }, {
0022 .type = V4L2_TUNER_RF,
0023 .index = 1,
0024 .capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS,
0025 .rangelow = 390000000,
0026 .rangehigh = 960000000,
0027 },
0028 };
0029
0030 struct msi001_dev {
0031 struct spi_device *spi;
0032 struct v4l2_subdev sd;
0033
0034
0035 struct v4l2_ctrl_handler hdl;
0036 struct v4l2_ctrl *bandwidth_auto;
0037 struct v4l2_ctrl *bandwidth;
0038 struct v4l2_ctrl *lna_gain;
0039 struct v4l2_ctrl *mixer_gain;
0040 struct v4l2_ctrl *if_gain;
0041
0042 unsigned int f_tuner;
0043 };
0044
0045 static inline struct msi001_dev *sd_to_msi001_dev(struct v4l2_subdev *sd)
0046 {
0047 return container_of(sd, struct msi001_dev, sd);
0048 }
0049
0050 static int msi001_wreg(struct msi001_dev *dev, u32 data)
0051 {
0052
0053 return spi_write(dev->spi, &data, 3);
0054 };
0055
0056 static int msi001_set_gain(struct msi001_dev *dev, int lna_gain, int mixer_gain,
0057 int if_gain)
0058 {
0059 struct spi_device *spi = dev->spi;
0060 int ret;
0061 u32 reg;
0062
0063 dev_dbg(&spi->dev, "lna=%d mixer=%d if=%d\n",
0064 lna_gain, mixer_gain, if_gain);
0065
0066 reg = 1 << 0;
0067 reg |= (59 - if_gain) << 4;
0068 reg |= 0 << 10;
0069 reg |= (1 - mixer_gain) << 12;
0070 reg |= (1 - lna_gain) << 13;
0071 reg |= 4 << 14;
0072 reg |= 0 << 17;
0073 ret = msi001_wreg(dev, reg);
0074 if (ret)
0075 goto err;
0076
0077 return 0;
0078 err:
0079 dev_dbg(&spi->dev, "failed %d\n", ret);
0080 return ret;
0081 };
0082
0083 static int msi001_set_tuner(struct msi001_dev *dev)
0084 {
0085 struct spi_device *spi = dev->spi;
0086 int ret, i;
0087 unsigned int uitmp, div_n, k, k_thresh, k_frac, div_lo, f_if1;
0088 u32 reg;
0089 u64 f_vco;
0090 u8 mode, filter_mode;
0091
0092 static const struct {
0093 u32 rf;
0094 u8 mode;
0095 u8 div_lo;
0096 } band_lut[] = {
0097 { 50000000, 0xe1, 16},
0098 {108000000, 0x42, 32},
0099 {330000000, 0x44, 16},
0100 {960000000, 0x48, 4},
0101 { ~0U, 0x50, 2},
0102 };
0103 static const struct {
0104 u32 freq;
0105 u8 filter_mode;
0106 } if_freq_lut[] = {
0107 { 0, 0x03},
0108 { 450000, 0x02},
0109 {1620000, 0x01},
0110 {2048000, 0x00},
0111 };
0112 static const struct {
0113 u32 freq;
0114 u8 val;
0115 } bandwidth_lut[] = {
0116 { 200000, 0x00},
0117 { 300000, 0x01},
0118 { 600000, 0x02},
0119 {1536000, 0x03},
0120 {5000000, 0x04},
0121 {6000000, 0x05},
0122 {7000000, 0x06},
0123 {8000000, 0x07},
0124 };
0125
0126 unsigned int f_rf = dev->f_tuner;
0127
0128
0129
0130
0131
0132 unsigned int bandwidth;
0133
0134
0135
0136
0137
0138 unsigned int f_if = 0;
0139 #define F_REF 24000000
0140 #define DIV_PRE_N 4
0141 #define F_VCO_STEP div_lo
0142
0143 dev_dbg(&spi->dev, "f_rf=%d f_if=%d\n", f_rf, f_if);
0144
0145 for (i = 0; i < ARRAY_SIZE(band_lut); i++) {
0146 if (f_rf <= band_lut[i].rf) {
0147 mode = band_lut[i].mode;
0148 div_lo = band_lut[i].div_lo;
0149 break;
0150 }
0151 }
0152 if (i == ARRAY_SIZE(band_lut)) {
0153 ret = -EINVAL;
0154 goto err;
0155 }
0156
0157
0158 if ((mode >> 0) & 0x1)
0159 f_if1 = 5 * F_REF;
0160 else
0161 f_if1 = 0;
0162
0163 for (i = 0; i < ARRAY_SIZE(if_freq_lut); i++) {
0164 if (f_if == if_freq_lut[i].freq) {
0165 filter_mode = if_freq_lut[i].filter_mode;
0166 break;
0167 }
0168 }
0169 if (i == ARRAY_SIZE(if_freq_lut)) {
0170 ret = -EINVAL;
0171 goto err;
0172 }
0173
0174
0175 bandwidth = dev->bandwidth->val;
0176 bandwidth = clamp(bandwidth, 200000U, 8000000U);
0177
0178 for (i = 0; i < ARRAY_SIZE(bandwidth_lut); i++) {
0179 if (bandwidth <= bandwidth_lut[i].freq) {
0180 bandwidth = bandwidth_lut[i].val;
0181 break;
0182 }
0183 }
0184 if (i == ARRAY_SIZE(bandwidth_lut)) {
0185 ret = -EINVAL;
0186 goto err;
0187 }
0188
0189 dev->bandwidth->val = bandwidth_lut[i].freq;
0190
0191 dev_dbg(&spi->dev, "bandwidth selected=%d\n", bandwidth_lut[i].freq);
0192
0193
0194
0195
0196
0197
0198
0199
0200
0201
0202
0203
0204
0205
0206
0207
0208
0209
0210 f_vco = (u64) (f_rf + f_if + f_if1) * div_lo;
0211 div_n = div_u64_rem(f_vco, DIV_PRE_N * F_REF, &k);
0212 k_thresh = (DIV_PRE_N * F_REF) / F_VCO_STEP;
0213 k_frac = div_u64((u64) k * k_thresh, (DIV_PRE_N * F_REF));
0214
0215
0216 uitmp = gcd(k_thresh, k_frac);
0217 k_thresh /= uitmp;
0218 k_frac /= uitmp;
0219
0220
0221 uitmp = DIV_ROUND_UP(k_thresh, 4095);
0222 k_thresh = DIV_ROUND_CLOSEST(k_thresh, uitmp);
0223 k_frac = DIV_ROUND_CLOSEST(k_frac, uitmp);
0224
0225
0226 uitmp = (unsigned int) F_REF * DIV_PRE_N * div_n;
0227 uitmp += (unsigned int) F_REF * DIV_PRE_N * k_frac / k_thresh;
0228 uitmp /= div_lo;
0229
0230 dev_dbg(&spi->dev,
0231 "f_rf=%u:%u f_vco=%llu div_n=%u k_thresh=%u k_frac=%u div_lo=%u\n",
0232 f_rf, uitmp, f_vco, div_n, k_thresh, k_frac, div_lo);
0233
0234 ret = msi001_wreg(dev, 0x00000e);
0235 if (ret)
0236 goto err;
0237
0238 ret = msi001_wreg(dev, 0x000003);
0239 if (ret)
0240 goto err;
0241
0242 reg = 0 << 0;
0243 reg |= mode << 4;
0244 reg |= filter_mode << 12;
0245 reg |= bandwidth << 14;
0246 reg |= 0x02 << 17;
0247 reg |= 0x00 << 20;
0248 ret = msi001_wreg(dev, reg);
0249 if (ret)
0250 goto err;
0251
0252 reg = 5 << 0;
0253 reg |= k_thresh << 4;
0254 reg |= 1 << 19;
0255 reg |= 1 << 21;
0256 ret = msi001_wreg(dev, reg);
0257 if (ret)
0258 goto err;
0259
0260 reg = 2 << 0;
0261 reg |= k_frac << 4;
0262 reg |= div_n << 16;
0263 ret = msi001_wreg(dev, reg);
0264 if (ret)
0265 goto err;
0266
0267 ret = msi001_set_gain(dev, dev->lna_gain->cur.val,
0268 dev->mixer_gain->cur.val, dev->if_gain->cur.val);
0269 if (ret)
0270 goto err;
0271
0272 reg = 6 << 0;
0273 reg |= 63 << 4;
0274 reg |= 4095 << 10;
0275 ret = msi001_wreg(dev, reg);
0276 if (ret)
0277 goto err;
0278
0279 return 0;
0280 err:
0281 dev_dbg(&spi->dev, "failed %d\n", ret);
0282 return ret;
0283 }
0284
0285 static int msi001_standby(struct v4l2_subdev *sd)
0286 {
0287 struct msi001_dev *dev = sd_to_msi001_dev(sd);
0288
0289 return msi001_wreg(dev, 0x000000);
0290 }
0291
0292 static int msi001_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *v)
0293 {
0294 struct msi001_dev *dev = sd_to_msi001_dev(sd);
0295 struct spi_device *spi = dev->spi;
0296
0297 dev_dbg(&spi->dev, "index=%d\n", v->index);
0298
0299 strscpy(v->name, "Mirics MSi001", sizeof(v->name));
0300 v->type = V4L2_TUNER_RF;
0301 v->capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS;
0302 v->rangelow = 49000000;
0303 v->rangehigh = 960000000;
0304
0305 return 0;
0306 }
0307
0308 static int msi001_s_tuner(struct v4l2_subdev *sd, const struct v4l2_tuner *v)
0309 {
0310 struct msi001_dev *dev = sd_to_msi001_dev(sd);
0311 struct spi_device *spi = dev->spi;
0312
0313 dev_dbg(&spi->dev, "index=%d\n", v->index);
0314 return 0;
0315 }
0316
0317 static int msi001_g_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *f)
0318 {
0319 struct msi001_dev *dev = sd_to_msi001_dev(sd);
0320 struct spi_device *spi = dev->spi;
0321
0322 dev_dbg(&spi->dev, "tuner=%d\n", f->tuner);
0323 f->frequency = dev->f_tuner;
0324 return 0;
0325 }
0326
0327 static int msi001_s_frequency(struct v4l2_subdev *sd,
0328 const struct v4l2_frequency *f)
0329 {
0330 struct msi001_dev *dev = sd_to_msi001_dev(sd);
0331 struct spi_device *spi = dev->spi;
0332 unsigned int band;
0333
0334 dev_dbg(&spi->dev, "tuner=%d type=%d frequency=%u\n",
0335 f->tuner, f->type, f->frequency);
0336
0337 if (f->frequency < ((bands[0].rangehigh + bands[1].rangelow) / 2))
0338 band = 0;
0339 else
0340 band = 1;
0341 dev->f_tuner = clamp_t(unsigned int, f->frequency,
0342 bands[band].rangelow, bands[band].rangehigh);
0343
0344 return msi001_set_tuner(dev);
0345 }
0346
0347 static int msi001_enum_freq_bands(struct v4l2_subdev *sd,
0348 struct v4l2_frequency_band *band)
0349 {
0350 struct msi001_dev *dev = sd_to_msi001_dev(sd);
0351 struct spi_device *spi = dev->spi;
0352
0353 dev_dbg(&spi->dev, "tuner=%d type=%d index=%d\n",
0354 band->tuner, band->type, band->index);
0355
0356 if (band->index >= ARRAY_SIZE(bands))
0357 return -EINVAL;
0358
0359 band->capability = bands[band->index].capability;
0360 band->rangelow = bands[band->index].rangelow;
0361 band->rangehigh = bands[band->index].rangehigh;
0362
0363 return 0;
0364 }
0365
0366 static const struct v4l2_subdev_tuner_ops msi001_tuner_ops = {
0367 .standby = msi001_standby,
0368 .g_tuner = msi001_g_tuner,
0369 .s_tuner = msi001_s_tuner,
0370 .g_frequency = msi001_g_frequency,
0371 .s_frequency = msi001_s_frequency,
0372 .enum_freq_bands = msi001_enum_freq_bands,
0373 };
0374
0375 static const struct v4l2_subdev_ops msi001_ops = {
0376 .tuner = &msi001_tuner_ops,
0377 };
0378
0379 static int msi001_s_ctrl(struct v4l2_ctrl *ctrl)
0380 {
0381 struct msi001_dev *dev = container_of(ctrl->handler, struct msi001_dev, hdl);
0382 struct spi_device *spi = dev->spi;
0383
0384 int ret;
0385
0386 dev_dbg(&spi->dev, "id=%d name=%s val=%d min=%lld max=%lld step=%lld\n",
0387 ctrl->id, ctrl->name, ctrl->val, ctrl->minimum, ctrl->maximum,
0388 ctrl->step);
0389
0390 switch (ctrl->id) {
0391 case V4L2_CID_RF_TUNER_BANDWIDTH_AUTO:
0392 case V4L2_CID_RF_TUNER_BANDWIDTH:
0393 ret = msi001_set_tuner(dev);
0394 break;
0395 case V4L2_CID_RF_TUNER_LNA_GAIN:
0396 ret = msi001_set_gain(dev, dev->lna_gain->val,
0397 dev->mixer_gain->cur.val,
0398 dev->if_gain->cur.val);
0399 break;
0400 case V4L2_CID_RF_TUNER_MIXER_GAIN:
0401 ret = msi001_set_gain(dev, dev->lna_gain->cur.val,
0402 dev->mixer_gain->val,
0403 dev->if_gain->cur.val);
0404 break;
0405 case V4L2_CID_RF_TUNER_IF_GAIN:
0406 ret = msi001_set_gain(dev, dev->lna_gain->cur.val,
0407 dev->mixer_gain->cur.val,
0408 dev->if_gain->val);
0409 break;
0410 default:
0411 dev_dbg(&spi->dev, "unknown control %d\n", ctrl->id);
0412 ret = -EINVAL;
0413 }
0414
0415 return ret;
0416 }
0417
0418 static const struct v4l2_ctrl_ops msi001_ctrl_ops = {
0419 .s_ctrl = msi001_s_ctrl,
0420 };
0421
0422 static int msi001_probe(struct spi_device *spi)
0423 {
0424 struct msi001_dev *dev;
0425 int ret;
0426
0427 dev_dbg(&spi->dev, "\n");
0428
0429 dev = kzalloc(sizeof(*dev), GFP_KERNEL);
0430 if (!dev) {
0431 ret = -ENOMEM;
0432 goto err;
0433 }
0434
0435 dev->spi = spi;
0436 dev->f_tuner = bands[0].rangelow;
0437 v4l2_spi_subdev_init(&dev->sd, spi, &msi001_ops);
0438
0439
0440 v4l2_ctrl_handler_init(&dev->hdl, 5);
0441 dev->bandwidth_auto = v4l2_ctrl_new_std(&dev->hdl, &msi001_ctrl_ops,
0442 V4L2_CID_RF_TUNER_BANDWIDTH_AUTO, 0, 1, 1, 1);
0443 dev->bandwidth = v4l2_ctrl_new_std(&dev->hdl, &msi001_ctrl_ops,
0444 V4L2_CID_RF_TUNER_BANDWIDTH, 200000, 8000000, 1, 200000);
0445 if (dev->hdl.error) {
0446 ret = dev->hdl.error;
0447 dev_err(&spi->dev, "Could not initialize controls\n");
0448
0449 goto err_ctrl_handler_free;
0450 }
0451
0452 v4l2_ctrl_auto_cluster(2, &dev->bandwidth_auto, 0, false);
0453 dev->lna_gain = v4l2_ctrl_new_std(&dev->hdl, &msi001_ctrl_ops,
0454 V4L2_CID_RF_TUNER_LNA_GAIN, 0, 1, 1, 1);
0455 dev->mixer_gain = v4l2_ctrl_new_std(&dev->hdl, &msi001_ctrl_ops,
0456 V4L2_CID_RF_TUNER_MIXER_GAIN, 0, 1, 1, 1);
0457 dev->if_gain = v4l2_ctrl_new_std(&dev->hdl, &msi001_ctrl_ops,
0458 V4L2_CID_RF_TUNER_IF_GAIN, 0, 59, 1, 0);
0459 if (dev->hdl.error) {
0460 ret = dev->hdl.error;
0461 dev_err(&spi->dev, "Could not initialize controls\n");
0462
0463 goto err_ctrl_handler_free;
0464 }
0465
0466 dev->sd.ctrl_handler = &dev->hdl;
0467 return 0;
0468 err_ctrl_handler_free:
0469 v4l2_ctrl_handler_free(&dev->hdl);
0470 kfree(dev);
0471 err:
0472 return ret;
0473 }
0474
0475 static void msi001_remove(struct spi_device *spi)
0476 {
0477 struct v4l2_subdev *sd = spi_get_drvdata(spi);
0478 struct msi001_dev *dev = sd_to_msi001_dev(sd);
0479
0480 dev_dbg(&spi->dev, "\n");
0481
0482
0483
0484
0485
0486 v4l2_device_unregister_subdev(&dev->sd);
0487 v4l2_ctrl_handler_free(&dev->hdl);
0488 kfree(dev);
0489 }
0490
0491 static const struct spi_device_id msi001_id_table[] = {
0492 {"msi001", 0},
0493 {}
0494 };
0495 MODULE_DEVICE_TABLE(spi, msi001_id_table);
0496
0497 static struct spi_driver msi001_driver = {
0498 .driver = {
0499 .name = "msi001",
0500 .suppress_bind_attrs = true,
0501 },
0502 .probe = msi001_probe,
0503 .remove = msi001_remove,
0504 .id_table = msi001_id_table,
0505 };
0506 module_spi_driver(msi001_driver);
0507
0508 MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
0509 MODULE_DESCRIPTION("Mirics MSi001");
0510 MODULE_LICENSE("GPL");