xref: /openbmc/linux/drivers/media/tuners/msi001.c (revision 7d545e77)
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Mirics MSi001 silicon tuner driver
4  *
5  * Copyright (C) 2013 Antti Palosaari <crope@iki.fi>
6  * Copyright (C) 2014 Antti Palosaari <crope@iki.fi>
7  */
8 
9 #include <linux/module.h>
10 #include <linux/gcd.h>
11 #include <media/v4l2-device.h>
12 #include <media/v4l2-ctrls.h>
13 
14 static const struct v4l2_frequency_band bands[] = {
15 	{
16 		.type = V4L2_TUNER_RF,
17 		.index = 0,
18 		.capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS,
19 		.rangelow   =   49000000,
20 		.rangehigh  =  263000000,
21 	}, {
22 		.type = V4L2_TUNER_RF,
23 		.index = 1,
24 		.capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS,
25 		.rangelow   =  390000000,
26 		.rangehigh  =  960000000,
27 	},
28 };
29 
30 struct msi001_dev {
31 	struct spi_device *spi;
32 	struct v4l2_subdev sd;
33 
34 	/* Controls */
35 	struct v4l2_ctrl_handler hdl;
36 	struct v4l2_ctrl *bandwidth_auto;
37 	struct v4l2_ctrl *bandwidth;
38 	struct v4l2_ctrl *lna_gain;
39 	struct v4l2_ctrl *mixer_gain;
40 	struct v4l2_ctrl *if_gain;
41 
42 	unsigned int f_tuner;
43 };
44 
45 static inline struct msi001_dev *sd_to_msi001_dev(struct v4l2_subdev *sd)
46 {
47 	return container_of(sd, struct msi001_dev, sd);
48 }
49 
50 static int msi001_wreg(struct msi001_dev *dev, u32 data)
51 {
52 	/* Register format: 4 bits addr + 20 bits value */
53 	return spi_write(dev->spi, &data, 3);
54 };
55 
56 static int msi001_set_gain(struct msi001_dev *dev, int lna_gain, int mixer_gain,
57 			   int if_gain)
58 {
59 	struct spi_device *spi = dev->spi;
60 	int ret;
61 	u32 reg;
62 
63 	dev_dbg(&spi->dev, "lna=%d mixer=%d if=%d\n",
64 		lna_gain, mixer_gain, if_gain);
65 
66 	reg = 1 << 0;
67 	reg |= (59 - if_gain) << 4;
68 	reg |= 0 << 10;
69 	reg |= (1 - mixer_gain) << 12;
70 	reg |= (1 - lna_gain) << 13;
71 	reg |= 4 << 14;
72 	reg |= 0 << 17;
73 	ret = msi001_wreg(dev, reg);
74 	if (ret)
75 		goto err;
76 
77 	return 0;
78 err:
79 	dev_dbg(&spi->dev, "failed %d\n", ret);
80 	return ret;
81 };
82 
83 static int msi001_set_tuner(struct msi001_dev *dev)
84 {
85 	struct spi_device *spi = dev->spi;
86 	int ret, i;
87 	unsigned int uitmp, div_n, k, k_thresh, k_frac, div_lo, f_if1;
88 	u32 reg;
89 	u64 f_vco;
90 	u8 mode, filter_mode;
91 
92 	static const struct {
93 		u32 rf;
94 		u8 mode;
95 		u8 div_lo;
96 	} band_lut[] = {
97 		{ 50000000, 0xe1, 16}, /* AM_MODE2, antenna 2 */
98 		{108000000, 0x42, 32}, /* VHF_MODE */
99 		{330000000, 0x44, 16}, /* B3_MODE */
100 		{960000000, 0x48,  4}, /* B45_MODE */
101 		{      ~0U, 0x50,  2}, /* BL_MODE */
102 	};
103 	static const struct {
104 		u32 freq;
105 		u8 filter_mode;
106 	} if_freq_lut[] = {
107 		{      0, 0x03}, /* Zero IF */
108 		{ 450000, 0x02}, /* 450 kHz IF */
109 		{1620000, 0x01}, /* 1.62 MHz IF */
110 		{2048000, 0x00}, /* 2.048 MHz IF */
111 	};
112 	static const struct {
113 		u32 freq;
114 		u8 val;
115 	} bandwidth_lut[] = {
116 		{ 200000, 0x00}, /* 200 kHz */
117 		{ 300000, 0x01}, /* 300 kHz */
118 		{ 600000, 0x02}, /* 600 kHz */
119 		{1536000, 0x03}, /* 1.536 MHz */
120 		{5000000, 0x04}, /* 5 MHz */
121 		{6000000, 0x05}, /* 6 MHz */
122 		{7000000, 0x06}, /* 7 MHz */
123 		{8000000, 0x07}, /* 8 MHz */
124 	};
125 
126 	unsigned int f_rf = dev->f_tuner;
127 
128 	/*
129 	 * bandwidth (Hz)
130 	 * 200000, 300000, 600000, 1536000, 5000000, 6000000, 7000000, 8000000
131 	 */
132 	unsigned int bandwidth;
133 
134 	/*
135 	 * intermediate frequency (Hz)
136 	 * 0, 450000, 1620000, 2048000
137 	 */
138 	unsigned int f_if = 0;
139 	#define F_REF 24000000
140 	#define DIV_PRE_N 4
141 	#define	F_VCO_STEP div_lo
142 
143 	dev_dbg(&spi->dev, "f_rf=%d f_if=%d\n", f_rf, f_if);
144 
145 	for (i = 0; i < ARRAY_SIZE(band_lut); i++) {
146 		if (f_rf <= band_lut[i].rf) {
147 			mode = band_lut[i].mode;
148 			div_lo = band_lut[i].div_lo;
149 			break;
150 		}
151 	}
152 	if (i == ARRAY_SIZE(band_lut)) {
153 		ret = -EINVAL;
154 		goto err;
155 	}
156 
157 	/* AM_MODE is upconverted */
158 	if ((mode >> 0) & 0x1)
159 		f_if1 =  5 * F_REF;
160 	else
161 		f_if1 =  0;
162 
163 	for (i = 0; i < ARRAY_SIZE(if_freq_lut); i++) {
164 		if (f_if == if_freq_lut[i].freq) {
165 			filter_mode = if_freq_lut[i].filter_mode;
166 			break;
167 		}
168 	}
169 	if (i == ARRAY_SIZE(if_freq_lut)) {
170 		ret = -EINVAL;
171 		goto err;
172 	}
173 
174 	/* filters */
175 	bandwidth = dev->bandwidth->val;
176 	bandwidth = clamp(bandwidth, 200000U, 8000000U);
177 
178 	for (i = 0; i < ARRAY_SIZE(bandwidth_lut); i++) {
179 		if (bandwidth <= bandwidth_lut[i].freq) {
180 			bandwidth = bandwidth_lut[i].val;
181 			break;
182 		}
183 	}
184 	if (i == ARRAY_SIZE(bandwidth_lut)) {
185 		ret = -EINVAL;
186 		goto err;
187 	}
188 
189 	dev->bandwidth->val = bandwidth_lut[i].freq;
190 
191 	dev_dbg(&spi->dev, "bandwidth selected=%d\n", bandwidth_lut[i].freq);
192 
193 	/*
194 	 * Fractional-N synthesizer
195 	 *
196 	 *           +---------------------------------------+
197 	 *           v                                       |
198 	 *  Fref   +----+     +-------+         +----+     +------+     +---+
199 	 * ------> | PD | --> |  VCO  | ------> | /4 | --> | /N.F | <-- | K |
200 	 *         +----+     +-------+         +----+     +------+     +---+
201 	 *                      |
202 	 *                      |
203 	 *                      v
204 	 *                    +-------+  Fout
205 	 *                    | /Rout | ------>
206 	 *                    +-------+
207 	 */
208 
209 	/* Calculate PLL integer and fractional control word. */
210 	f_vco = (u64) (f_rf + f_if + f_if1) * div_lo;
211 	div_n = div_u64_rem(f_vco, DIV_PRE_N * F_REF, &k);
212 	k_thresh = (DIV_PRE_N * F_REF) / F_VCO_STEP;
213 	k_frac = div_u64((u64) k * k_thresh, (DIV_PRE_N * F_REF));
214 
215 	/* Find out greatest common divisor and divide to smaller. */
216 	uitmp = gcd(k_thresh, k_frac);
217 	k_thresh /= uitmp;
218 	k_frac /= uitmp;
219 
220 	/* Force divide to reg max. Resolution will be reduced. */
221 	uitmp = DIV_ROUND_UP(k_thresh, 4095);
222 	k_thresh = DIV_ROUND_CLOSEST(k_thresh, uitmp);
223 	k_frac = DIV_ROUND_CLOSEST(k_frac, uitmp);
224 
225 	/* Calculate real RF set. */
226 	uitmp = (unsigned int) F_REF * DIV_PRE_N * div_n;
227 	uitmp += (unsigned int) F_REF * DIV_PRE_N * k_frac / k_thresh;
228 	uitmp /= div_lo;
229 
230 	dev_dbg(&spi->dev,
231 		"f_rf=%u:%u f_vco=%llu div_n=%u k_thresh=%u k_frac=%u div_lo=%u\n",
232 		f_rf, uitmp, f_vco, div_n, k_thresh, k_frac, div_lo);
233 
234 	ret = msi001_wreg(dev, 0x00000e);
235 	if (ret)
236 		goto err;
237 
238 	ret = msi001_wreg(dev, 0x000003);
239 	if (ret)
240 		goto err;
241 
242 	reg = 0 << 0;
243 	reg |= mode << 4;
244 	reg |= filter_mode << 12;
245 	reg |= bandwidth << 14;
246 	reg |= 0x02 << 17;
247 	reg |= 0x00 << 20;
248 	ret = msi001_wreg(dev, reg);
249 	if (ret)
250 		goto err;
251 
252 	reg = 5 << 0;
253 	reg |= k_thresh << 4;
254 	reg |= 1 << 19;
255 	reg |= 1 << 21;
256 	ret = msi001_wreg(dev, reg);
257 	if (ret)
258 		goto err;
259 
260 	reg = 2 << 0;
261 	reg |= k_frac << 4;
262 	reg |= div_n << 16;
263 	ret = msi001_wreg(dev, reg);
264 	if (ret)
265 		goto err;
266 
267 	ret = msi001_set_gain(dev, dev->lna_gain->cur.val,
268 			      dev->mixer_gain->cur.val, dev->if_gain->cur.val);
269 	if (ret)
270 		goto err;
271 
272 	reg = 6 << 0;
273 	reg |= 63 << 4;
274 	reg |= 4095 << 10;
275 	ret = msi001_wreg(dev, reg);
276 	if (ret)
277 		goto err;
278 
279 	return 0;
280 err:
281 	dev_dbg(&spi->dev, "failed %d\n", ret);
282 	return ret;
283 }
284 
285 static int msi001_standby(struct v4l2_subdev *sd)
286 {
287 	struct msi001_dev *dev = sd_to_msi001_dev(sd);
288 
289 	return msi001_wreg(dev, 0x000000);
290 }
291 
292 static int msi001_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *v)
293 {
294 	struct msi001_dev *dev = sd_to_msi001_dev(sd);
295 	struct spi_device *spi = dev->spi;
296 
297 	dev_dbg(&spi->dev, "index=%d\n", v->index);
298 
299 	strscpy(v->name, "Mirics MSi001", sizeof(v->name));
300 	v->type = V4L2_TUNER_RF;
301 	v->capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS;
302 	v->rangelow =    49000000;
303 	v->rangehigh =  960000000;
304 
305 	return 0;
306 }
307 
308 static int msi001_s_tuner(struct v4l2_subdev *sd, const struct v4l2_tuner *v)
309 {
310 	struct msi001_dev *dev = sd_to_msi001_dev(sd);
311 	struct spi_device *spi = dev->spi;
312 
313 	dev_dbg(&spi->dev, "index=%d\n", v->index);
314 	return 0;
315 }
316 
317 static int msi001_g_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *f)
318 {
319 	struct msi001_dev *dev = sd_to_msi001_dev(sd);
320 	struct spi_device *spi = dev->spi;
321 
322 	dev_dbg(&spi->dev, "tuner=%d\n", f->tuner);
323 	f->frequency = dev->f_tuner;
324 	return 0;
325 }
326 
327 static int msi001_s_frequency(struct v4l2_subdev *sd,
328 			      const struct v4l2_frequency *f)
329 {
330 	struct msi001_dev *dev = sd_to_msi001_dev(sd);
331 	struct spi_device *spi = dev->spi;
332 	unsigned int band;
333 
334 	dev_dbg(&spi->dev, "tuner=%d type=%d frequency=%u\n",
335 		f->tuner, f->type, f->frequency);
336 
337 	if (f->frequency < ((bands[0].rangehigh + bands[1].rangelow) / 2))
338 		band = 0;
339 	else
340 		band = 1;
341 	dev->f_tuner = clamp_t(unsigned int, f->frequency,
342 			       bands[band].rangelow, bands[band].rangehigh);
343 
344 	return msi001_set_tuner(dev);
345 }
346 
347 static int msi001_enum_freq_bands(struct v4l2_subdev *sd,
348 				  struct v4l2_frequency_band *band)
349 {
350 	struct msi001_dev *dev = sd_to_msi001_dev(sd);
351 	struct spi_device *spi = dev->spi;
352 
353 	dev_dbg(&spi->dev, "tuner=%d type=%d index=%d\n",
354 		band->tuner, band->type, band->index);
355 
356 	if (band->index >= ARRAY_SIZE(bands))
357 		return -EINVAL;
358 
359 	band->capability = bands[band->index].capability;
360 	band->rangelow = bands[band->index].rangelow;
361 	band->rangehigh = bands[band->index].rangehigh;
362 
363 	return 0;
364 }
365 
366 static const struct v4l2_subdev_tuner_ops msi001_tuner_ops = {
367 	.standby                  = msi001_standby,
368 	.g_tuner                  = msi001_g_tuner,
369 	.s_tuner                  = msi001_s_tuner,
370 	.g_frequency              = msi001_g_frequency,
371 	.s_frequency              = msi001_s_frequency,
372 	.enum_freq_bands          = msi001_enum_freq_bands,
373 };
374 
375 static const struct v4l2_subdev_ops msi001_ops = {
376 	.tuner                    = &msi001_tuner_ops,
377 };
378 
379 static int msi001_s_ctrl(struct v4l2_ctrl *ctrl)
380 {
381 	struct msi001_dev *dev = container_of(ctrl->handler, struct msi001_dev, hdl);
382 	struct spi_device *spi = dev->spi;
383 
384 	int ret;
385 
386 	dev_dbg(&spi->dev, "id=%d name=%s val=%d min=%lld max=%lld step=%lld\n",
387 		ctrl->id, ctrl->name, ctrl->val, ctrl->minimum, ctrl->maximum,
388 		ctrl->step);
389 
390 	switch (ctrl->id) {
391 	case V4L2_CID_RF_TUNER_BANDWIDTH_AUTO:
392 	case V4L2_CID_RF_TUNER_BANDWIDTH:
393 		ret = msi001_set_tuner(dev);
394 		break;
395 	case  V4L2_CID_RF_TUNER_LNA_GAIN:
396 		ret = msi001_set_gain(dev, dev->lna_gain->val,
397 				      dev->mixer_gain->cur.val,
398 				      dev->if_gain->cur.val);
399 		break;
400 	case  V4L2_CID_RF_TUNER_MIXER_GAIN:
401 		ret = msi001_set_gain(dev, dev->lna_gain->cur.val,
402 				      dev->mixer_gain->val,
403 				      dev->if_gain->cur.val);
404 		break;
405 	case  V4L2_CID_RF_TUNER_IF_GAIN:
406 		ret = msi001_set_gain(dev, dev->lna_gain->cur.val,
407 				      dev->mixer_gain->cur.val,
408 				      dev->if_gain->val);
409 		break;
410 	default:
411 		dev_dbg(&spi->dev, "unknown control %d\n", ctrl->id);
412 		ret = -EINVAL;
413 	}
414 
415 	return ret;
416 }
417 
418 static const struct v4l2_ctrl_ops msi001_ctrl_ops = {
419 	.s_ctrl                   = msi001_s_ctrl,
420 };
421 
422 static int msi001_probe(struct spi_device *spi)
423 {
424 	struct msi001_dev *dev;
425 	int ret;
426 
427 	dev_dbg(&spi->dev, "\n");
428 
429 	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
430 	if (!dev) {
431 		ret = -ENOMEM;
432 		goto err;
433 	}
434 
435 	dev->spi = spi;
436 	dev->f_tuner = bands[0].rangelow;
437 	v4l2_spi_subdev_init(&dev->sd, spi, &msi001_ops);
438 
439 	/* Register controls */
440 	v4l2_ctrl_handler_init(&dev->hdl, 5);
441 	dev->bandwidth_auto = v4l2_ctrl_new_std(&dev->hdl, &msi001_ctrl_ops,
442 			V4L2_CID_RF_TUNER_BANDWIDTH_AUTO, 0, 1, 1, 1);
443 	dev->bandwidth = v4l2_ctrl_new_std(&dev->hdl, &msi001_ctrl_ops,
444 			V4L2_CID_RF_TUNER_BANDWIDTH, 200000, 8000000, 1, 200000);
445 	v4l2_ctrl_auto_cluster(2, &dev->bandwidth_auto, 0, false);
446 	dev->lna_gain = v4l2_ctrl_new_std(&dev->hdl, &msi001_ctrl_ops,
447 			V4L2_CID_RF_TUNER_LNA_GAIN, 0, 1, 1, 1);
448 	dev->mixer_gain = v4l2_ctrl_new_std(&dev->hdl, &msi001_ctrl_ops,
449 			V4L2_CID_RF_TUNER_MIXER_GAIN, 0, 1, 1, 1);
450 	dev->if_gain = v4l2_ctrl_new_std(&dev->hdl, &msi001_ctrl_ops,
451 			V4L2_CID_RF_TUNER_IF_GAIN, 0, 59, 1, 0);
452 	if (dev->hdl.error) {
453 		ret = dev->hdl.error;
454 		dev_err(&spi->dev, "Could not initialize controls\n");
455 		/* control init failed, free handler */
456 		goto err_ctrl_handler_free;
457 	}
458 
459 	dev->sd.ctrl_handler = &dev->hdl;
460 	return 0;
461 err_ctrl_handler_free:
462 	v4l2_ctrl_handler_free(&dev->hdl);
463 	kfree(dev);
464 err:
465 	return ret;
466 }
467 
468 static int msi001_remove(struct spi_device *spi)
469 {
470 	struct v4l2_subdev *sd = spi_get_drvdata(spi);
471 	struct msi001_dev *dev = sd_to_msi001_dev(sd);
472 
473 	dev_dbg(&spi->dev, "\n");
474 
475 	/*
476 	 * Registered by v4l2_spi_new_subdev() from master driver, but we must
477 	 * unregister it from here. Weird.
478 	 */
479 	v4l2_device_unregister_subdev(&dev->sd);
480 	v4l2_ctrl_handler_free(&dev->hdl);
481 	kfree(dev);
482 	return 0;
483 }
484 
485 static const struct spi_device_id msi001_id_table[] = {
486 	{"msi001", 0},
487 	{}
488 };
489 MODULE_DEVICE_TABLE(spi, msi001_id_table);
490 
491 static struct spi_driver msi001_driver = {
492 	.driver = {
493 		.name	= "msi001",
494 		.suppress_bind_attrs = true,
495 	},
496 	.probe		= msi001_probe,
497 	.remove		= msi001_remove,
498 	.id_table	= msi001_id_table,
499 };
500 module_spi_driver(msi001_driver);
501 
502 MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
503 MODULE_DESCRIPTION("Mirics MSi001");
504 MODULE_LICENSE("GPL");
505