1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  *  FM Driver for Connectivity chip of Texas Instruments.
4  *  This file provides interfaces to V4L2 subsystem.
5  *
6  *  This module registers with V4L2 subsystem as Radio
7  *  data system interface (/dev/radio). During the registration,
8  *  it will expose two set of function pointers.
9  *
10  *    1) File operation related API (open, close, read, write, poll...etc).
11  *    2) Set of V4L2 IOCTL complaint API.
12  *
13  *  Copyright (C) 2011 Texas Instruments
14  *  Author: Raja Mani <raja_mani@ti.com>
15  *  Author: Manjunatha Halli <manjunatha_halli@ti.com>
16  */
17 
18 #include <linux/export.h>
19 
20 #include "fmdrv.h"
21 #include "fmdrv_v4l2.h"
22 #include "fmdrv_common.h"
23 #include "fmdrv_rx.h"
24 #include "fmdrv_tx.h"
25 
26 static struct video_device gradio_dev;
27 static u8 radio_disconnected;
28 
29 /* -- V4L2 RADIO (/dev/radioX) device file operation interfaces --- */
30 
31 /* Read RX RDS data */
32 static ssize_t fm_v4l2_fops_read(struct file *file, char __user * buf,
33 					size_t count, loff_t *ppos)
34 {
35 	u8 rds_mode;
36 	int ret;
37 	struct fmdev *fmdev;
38 
39 	fmdev = video_drvdata(file);
40 
41 	if (!radio_disconnected) {
42 		fmerr("FM device is already disconnected\n");
43 		return -EIO;
44 	}
45 
46 	if (mutex_lock_interruptible(&fmdev->mutex))
47 		return -ERESTARTSYS;
48 
49 	/* Turn on RDS mode if it is disabled */
50 	ret = fm_rx_get_rds_mode(fmdev, &rds_mode);
51 	if (ret < 0) {
52 		fmerr("Unable to read current rds mode\n");
53 		goto read_unlock;
54 	}
55 
56 	if (rds_mode == FM_RDS_DISABLE) {
57 		ret = fmc_set_rds_mode(fmdev, FM_RDS_ENABLE);
58 		if (ret < 0) {
59 			fmerr("Failed to enable rds mode\n");
60 			goto read_unlock;
61 		}
62 	}
63 
64 	/* Copy RDS data from internal buffer to user buffer */
65 	ret = fmc_transfer_rds_from_internal_buff(fmdev, file, buf, count);
66 read_unlock:
67 	mutex_unlock(&fmdev->mutex);
68 	return ret;
69 }
70 
71 /* Write TX RDS data */
72 static ssize_t fm_v4l2_fops_write(struct file *file, const char __user * buf,
73 		size_t count, loff_t *ppos)
74 {
75 	struct tx_rds rds;
76 	int ret;
77 	struct fmdev *fmdev;
78 
79 	ret = copy_from_user(&rds, buf, sizeof(rds));
80 	rds.text[sizeof(rds.text) - 1] = '\0';
81 	fmdbg("(%d)type: %d, text %s, af %d\n",
82 		   ret, rds.text_type, rds.text, rds.af_freq);
83 	if (ret)
84 		return -EFAULT;
85 
86 	fmdev = video_drvdata(file);
87 	if (mutex_lock_interruptible(&fmdev->mutex))
88 		return -ERESTARTSYS;
89 	fm_tx_set_radio_text(fmdev, rds.text, rds.text_type);
90 	fm_tx_set_af(fmdev, rds.af_freq);
91 	mutex_unlock(&fmdev->mutex);
92 
93 	return sizeof(rds);
94 }
95 
96 static __poll_t fm_v4l2_fops_poll(struct file *file, struct poll_table_struct *pts)
97 {
98 	int ret;
99 	struct fmdev *fmdev;
100 
101 	fmdev = video_drvdata(file);
102 	mutex_lock(&fmdev->mutex);
103 	ret = fmc_is_rds_data_available(fmdev, file, pts);
104 	mutex_unlock(&fmdev->mutex);
105 	if (ret < 0)
106 		return EPOLLIN | EPOLLRDNORM;
107 
108 	return 0;
109 }
110 
111 /*
112  * Handle open request for "/dev/radioX" device.
113  * Start with FM RX mode as default.
114  */
115 static int fm_v4l2_fops_open(struct file *file)
116 {
117 	int ret;
118 	struct fmdev *fmdev = NULL;
119 
120 	/* Don't allow multiple open */
121 	if (radio_disconnected) {
122 		fmerr("FM device is already opened\n");
123 		return -EBUSY;
124 	}
125 
126 	fmdev = video_drvdata(file);
127 
128 	if (mutex_lock_interruptible(&fmdev->mutex))
129 		return -ERESTARTSYS;
130 	ret = fmc_prepare(fmdev);
131 	if (ret < 0) {
132 		fmerr("Unable to prepare FM CORE\n");
133 		goto open_unlock;
134 	}
135 
136 	fmdbg("Load FM RX firmware..\n");
137 
138 	ret = fmc_set_mode(fmdev, FM_MODE_RX);
139 	if (ret < 0) {
140 		fmerr("Unable to load FM RX firmware\n");
141 		goto open_unlock;
142 	}
143 	radio_disconnected = 1;
144 
145 open_unlock:
146 	mutex_unlock(&fmdev->mutex);
147 	return ret;
148 }
149 
150 static int fm_v4l2_fops_release(struct file *file)
151 {
152 	int ret;
153 	struct fmdev *fmdev;
154 
155 	fmdev = video_drvdata(file);
156 	if (!radio_disconnected) {
157 		fmdbg("FM device is already closed\n");
158 		return 0;
159 	}
160 
161 	mutex_lock(&fmdev->mutex);
162 	ret = fmc_set_mode(fmdev, FM_MODE_OFF);
163 	if (ret < 0) {
164 		fmerr("Unable to turn off the chip\n");
165 		goto release_unlock;
166 	}
167 
168 	ret = fmc_release(fmdev);
169 	if (ret < 0) {
170 		fmerr("FM CORE release failed\n");
171 		goto release_unlock;
172 	}
173 	radio_disconnected = 0;
174 
175 release_unlock:
176 	mutex_unlock(&fmdev->mutex);
177 	return ret;
178 }
179 
180 /* V4L2 RADIO (/dev/radioX) device IOCTL interfaces */
181 static int fm_v4l2_vidioc_querycap(struct file *file, void *priv,
182 		struct v4l2_capability *capability)
183 {
184 	strscpy(capability->driver, FM_DRV_NAME, sizeof(capability->driver));
185 	strscpy(capability->card, FM_DRV_CARD_SHORT_NAME,
186 		sizeof(capability->card));
187 	sprintf(capability->bus_info, "UART");
188 	capability->device_caps = V4L2_CAP_HW_FREQ_SEEK | V4L2_CAP_TUNER |
189 		V4L2_CAP_RADIO | V4L2_CAP_MODULATOR |
190 		V4L2_CAP_AUDIO | V4L2_CAP_READWRITE |
191 		V4L2_CAP_RDS_CAPTURE;
192 	capability->capabilities = capability->device_caps |
193 		V4L2_CAP_DEVICE_CAPS;
194 
195 	return 0;
196 }
197 
198 static int fm_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
199 {
200 	struct fmdev *fmdev = container_of(ctrl->handler,
201 			struct fmdev, ctrl_handler);
202 
203 	switch (ctrl->id) {
204 	case  V4L2_CID_TUNE_ANTENNA_CAPACITOR:
205 		ctrl->val = fm_tx_get_tune_cap_val(fmdev);
206 		break;
207 	default:
208 		fmwarn("%s: Unknown IOCTL: %d\n", __func__, ctrl->id);
209 		break;
210 	}
211 
212 	return 0;
213 }
214 
215 static int fm_v4l2_s_ctrl(struct v4l2_ctrl *ctrl)
216 {
217 	struct fmdev *fmdev = container_of(ctrl->handler,
218 			struct fmdev, ctrl_handler);
219 
220 	switch (ctrl->id) {
221 	case V4L2_CID_AUDIO_VOLUME:	/* set volume */
222 		return fm_rx_set_volume(fmdev, (u16)ctrl->val);
223 
224 	case V4L2_CID_AUDIO_MUTE:	/* set mute */
225 		return fmc_set_mute_mode(fmdev, (u8)ctrl->val);
226 
227 	case V4L2_CID_TUNE_POWER_LEVEL:
228 		/* set TX power level - ext control */
229 		return fm_tx_set_pwr_lvl(fmdev, (u8)ctrl->val);
230 
231 	case V4L2_CID_TUNE_PREEMPHASIS:
232 		return fm_tx_set_preemph_filter(fmdev, (u8) ctrl->val);
233 
234 	default:
235 		return -EINVAL;
236 	}
237 }
238 
239 static int fm_v4l2_vidioc_g_audio(struct file *file, void *priv,
240 		struct v4l2_audio *audio)
241 {
242 	memset(audio, 0, sizeof(*audio));
243 	strscpy(audio->name, "Radio", sizeof(audio->name));
244 	audio->capability = V4L2_AUDCAP_STEREO;
245 
246 	return 0;
247 }
248 
249 static int fm_v4l2_vidioc_s_audio(struct file *file, void *priv,
250 		const struct v4l2_audio *audio)
251 {
252 	if (audio->index != 0)
253 		return -EINVAL;
254 
255 	return 0;
256 }
257 
258 /* Get tuner attributes. If current mode is NOT RX, return error */
259 static int fm_v4l2_vidioc_g_tuner(struct file *file, void *priv,
260 		struct v4l2_tuner *tuner)
261 {
262 	struct fmdev *fmdev = video_drvdata(file);
263 	u32 bottom_freq;
264 	u32 top_freq;
265 	u16 stereo_mono_mode;
266 	u16 rssilvl;
267 	int ret;
268 
269 	if (tuner->index != 0)
270 		return -EINVAL;
271 
272 	if (fmdev->curr_fmmode != FM_MODE_RX)
273 		return -EPERM;
274 
275 	ret = fm_rx_get_band_freq_range(fmdev, &bottom_freq, &top_freq);
276 	if (ret != 0)
277 		return ret;
278 
279 	ret = fm_rx_get_stereo_mono(fmdev, &stereo_mono_mode);
280 	if (ret != 0)
281 		return ret;
282 
283 	ret = fm_rx_get_rssi_level(fmdev, &rssilvl);
284 	if (ret != 0)
285 		return ret;
286 
287 	strscpy(tuner->name, "FM", sizeof(tuner->name));
288 	tuner->type = V4L2_TUNER_RADIO;
289 	/* Store rangelow and rangehigh freq in unit of 62.5 Hz */
290 	tuner->rangelow = bottom_freq * 16;
291 	tuner->rangehigh = top_freq * 16;
292 	tuner->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO |
293 	((fmdev->rx.rds.flag == FM_RDS_ENABLE) ? V4L2_TUNER_SUB_RDS : 0);
294 	tuner->capability = V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_RDS |
295 			    V4L2_TUNER_CAP_LOW |
296 			    V4L2_TUNER_CAP_HWSEEK_BOUNDED |
297 			    V4L2_TUNER_CAP_HWSEEK_WRAP;
298 	tuner->audmode = (stereo_mono_mode ?
299 			  V4L2_TUNER_MODE_MONO : V4L2_TUNER_MODE_STEREO);
300 
301 	/*
302 	 * Actual rssi value lies in between -128 to +127.
303 	 * Convert this range from 0 to 255 by adding +128
304 	 */
305 	rssilvl += 128;
306 
307 	/*
308 	 * Return signal strength value should be within 0 to 65535.
309 	 * Find out correct signal radio by multiplying (65535/255) = 257
310 	 */
311 	tuner->signal = rssilvl * 257;
312 	tuner->afc = 0;
313 
314 	return ret;
315 }
316 
317 /*
318  * Set tuner attributes. If current mode is NOT RX, set to RX.
319  * Currently, we set only audio mode (mono/stereo) and RDS state (on/off).
320  * Should we set other tuner attributes, too?
321  */
322 static int fm_v4l2_vidioc_s_tuner(struct file *file, void *priv,
323 		const struct v4l2_tuner *tuner)
324 {
325 	struct fmdev *fmdev = video_drvdata(file);
326 	u16 aud_mode;
327 	u8 rds_mode;
328 	int ret;
329 
330 	if (tuner->index != 0)
331 		return -EINVAL;
332 
333 	aud_mode = (tuner->audmode == V4L2_TUNER_MODE_STEREO) ?
334 			FM_STEREO_MODE : FM_MONO_MODE;
335 	rds_mode = (tuner->rxsubchans & V4L2_TUNER_SUB_RDS) ?
336 			FM_RDS_ENABLE : FM_RDS_DISABLE;
337 
338 	if (fmdev->curr_fmmode != FM_MODE_RX) {
339 		ret = fmc_set_mode(fmdev, FM_MODE_RX);
340 		if (ret < 0) {
341 			fmerr("Failed to set RX mode\n");
342 			return ret;
343 		}
344 	}
345 
346 	ret = fmc_set_stereo_mono(fmdev, aud_mode);
347 	if (ret < 0) {
348 		fmerr("Failed to set RX stereo/mono mode\n");
349 		return ret;
350 	}
351 
352 	ret = fmc_set_rds_mode(fmdev, rds_mode);
353 	if (ret < 0)
354 		fmerr("Failed to set RX RDS mode\n");
355 
356 	return ret;
357 }
358 
359 /* Get tuner or modulator radio frequency */
360 static int fm_v4l2_vidioc_g_freq(struct file *file, void *priv,
361 		struct v4l2_frequency *freq)
362 {
363 	struct fmdev *fmdev = video_drvdata(file);
364 	int ret;
365 
366 	ret = fmc_get_freq(fmdev, &freq->frequency);
367 	if (ret < 0) {
368 		fmerr("Failed to get frequency\n");
369 		return ret;
370 	}
371 
372 	/* Frequency unit of 62.5 Hz*/
373 	freq->frequency = (u32) freq->frequency * 16;
374 
375 	return 0;
376 }
377 
378 /* Set tuner or modulator radio frequency */
379 static int fm_v4l2_vidioc_s_freq(struct file *file, void *priv,
380 		const struct v4l2_frequency *freq)
381 {
382 	struct fmdev *fmdev = video_drvdata(file);
383 
384 	/*
385 	 * As V4L2_TUNER_CAP_LOW is set 1 user sends the frequency
386 	 * in units of 62.5 Hz.
387 	 */
388 	return fmc_set_freq(fmdev, freq->frequency / 16);
389 }
390 
391 /* Set hardware frequency seek. If current mode is NOT RX, set it RX. */
392 static int fm_v4l2_vidioc_s_hw_freq_seek(struct file *file, void *priv,
393 		const struct v4l2_hw_freq_seek *seek)
394 {
395 	struct fmdev *fmdev = video_drvdata(file);
396 	int ret;
397 
398 	if (file->f_flags & O_NONBLOCK)
399 		return -EWOULDBLOCK;
400 
401 	if (fmdev->curr_fmmode != FM_MODE_RX) {
402 		ret = fmc_set_mode(fmdev, FM_MODE_RX);
403 		if (ret != 0) {
404 			fmerr("Failed to set RX mode\n");
405 			return ret;
406 		}
407 	}
408 
409 	ret = fm_rx_seek(fmdev, seek->seek_upward, seek->wrap_around,
410 			seek->spacing);
411 	if (ret < 0)
412 		fmerr("RX seek failed - %d\n", ret);
413 
414 	return ret;
415 }
416 /* Get modulator attributes. If mode is not TX, return no attributes. */
417 static int fm_v4l2_vidioc_g_modulator(struct file *file, void *priv,
418 		struct v4l2_modulator *mod)
419 {
420 	struct fmdev *fmdev = video_drvdata(file);
421 
422 	if (mod->index != 0)
423 		return -EINVAL;
424 
425 	if (fmdev->curr_fmmode != FM_MODE_TX)
426 		return -EPERM;
427 
428 	mod->txsubchans = ((fmdev->tx_data.aud_mode == FM_STEREO_MODE) ?
429 				V4L2_TUNER_SUB_STEREO : V4L2_TUNER_SUB_MONO) |
430 				((fmdev->tx_data.rds.flag == FM_RDS_ENABLE) ?
431 				V4L2_TUNER_SUB_RDS : 0);
432 
433 	mod->capability = V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_RDS |
434 				V4L2_TUNER_CAP_LOW;
435 
436 	return 0;
437 }
438 
439 /* Set modulator attributes. If mode is not TX, set to TX. */
440 static int fm_v4l2_vidioc_s_modulator(struct file *file, void *priv,
441 		const struct v4l2_modulator *mod)
442 {
443 	struct fmdev *fmdev = video_drvdata(file);
444 	u8 rds_mode;
445 	u16 aud_mode;
446 	int ret;
447 
448 	if (mod->index != 0)
449 		return -EINVAL;
450 
451 	if (fmdev->curr_fmmode != FM_MODE_TX) {
452 		ret = fmc_set_mode(fmdev, FM_MODE_TX);
453 		if (ret != 0) {
454 			fmerr("Failed to set TX mode\n");
455 			return ret;
456 		}
457 	}
458 
459 	aud_mode = (mod->txsubchans & V4L2_TUNER_SUB_STEREO) ?
460 			FM_STEREO_MODE : FM_MONO_MODE;
461 	rds_mode = (mod->txsubchans & V4L2_TUNER_SUB_RDS) ?
462 			FM_RDS_ENABLE : FM_RDS_DISABLE;
463 	ret = fm_tx_set_stereo_mono(fmdev, aud_mode);
464 	if (ret < 0) {
465 		fmerr("Failed to set mono/stereo mode for TX\n");
466 		return ret;
467 	}
468 	ret = fm_tx_set_rds_mode(fmdev, rds_mode);
469 	if (ret < 0)
470 		fmerr("Failed to set rds mode for TX\n");
471 
472 	return ret;
473 }
474 
475 static const struct v4l2_file_operations fm_drv_fops = {
476 	.owner = THIS_MODULE,
477 	.read = fm_v4l2_fops_read,
478 	.write = fm_v4l2_fops_write,
479 	.poll = fm_v4l2_fops_poll,
480 	.unlocked_ioctl = video_ioctl2,
481 	.open = fm_v4l2_fops_open,
482 	.release = fm_v4l2_fops_release,
483 };
484 
485 static const struct v4l2_ctrl_ops fm_ctrl_ops = {
486 	.s_ctrl = fm_v4l2_s_ctrl,
487 	.g_volatile_ctrl = fm_g_volatile_ctrl,
488 };
489 static const struct v4l2_ioctl_ops fm_drv_ioctl_ops = {
490 	.vidioc_querycap = fm_v4l2_vidioc_querycap,
491 	.vidioc_g_audio = fm_v4l2_vidioc_g_audio,
492 	.vidioc_s_audio = fm_v4l2_vidioc_s_audio,
493 	.vidioc_g_tuner = fm_v4l2_vidioc_g_tuner,
494 	.vidioc_s_tuner = fm_v4l2_vidioc_s_tuner,
495 	.vidioc_g_frequency = fm_v4l2_vidioc_g_freq,
496 	.vidioc_s_frequency = fm_v4l2_vidioc_s_freq,
497 	.vidioc_s_hw_freq_seek = fm_v4l2_vidioc_s_hw_freq_seek,
498 	.vidioc_g_modulator = fm_v4l2_vidioc_g_modulator,
499 	.vidioc_s_modulator = fm_v4l2_vidioc_s_modulator
500 };
501 
502 /* V4L2 RADIO device parent structure */
503 static const struct video_device fm_viddev_template = {
504 	.fops = &fm_drv_fops,
505 	.ioctl_ops = &fm_drv_ioctl_ops,
506 	.name = FM_DRV_NAME,
507 	.release = video_device_release_empty,
508 	/*
509 	 * To ensure both the tuner and modulator ioctls are accessible we
510 	 * set the vfl_dir to M2M to indicate this.
511 	 *
512 	 * It is not really a mem2mem device of course, but it can both receive
513 	 * and transmit using the same radio device. It's the only radio driver
514 	 * that does this and it should really be split in two radio devices,
515 	 * but that would affect applications using this driver.
516 	 */
517 	.vfl_dir = VFL_DIR_M2M,
518 };
519 
520 int fm_v4l2_init_video_device(struct fmdev *fmdev, int radio_nr)
521 {
522 	struct v4l2_ctrl *ctrl;
523 	int ret;
524 
525 	strscpy(fmdev->v4l2_dev.name, FM_DRV_NAME,
526 		sizeof(fmdev->v4l2_dev.name));
527 	ret = v4l2_device_register(NULL, &fmdev->v4l2_dev);
528 	if (ret < 0)
529 		return ret;
530 
531 	/* Init mutex for core locking */
532 	mutex_init(&fmdev->mutex);
533 
534 	/* Setup FM driver's V4L2 properties */
535 	gradio_dev = fm_viddev_template;
536 
537 	video_set_drvdata(&gradio_dev, fmdev);
538 
539 	gradio_dev.lock = &fmdev->mutex;
540 	gradio_dev.v4l2_dev = &fmdev->v4l2_dev;
541 
542 	/* Register with V4L2 subsystem as RADIO device */
543 	if (video_register_device(&gradio_dev, VFL_TYPE_RADIO, radio_nr)) {
544 		fmerr("Could not register video device\n");
545 		return -ENOMEM;
546 	}
547 
548 	fmdev->radio_dev = &gradio_dev;
549 
550 	/* Register to v4l2 ctrl handler framework */
551 	fmdev->radio_dev->ctrl_handler = &fmdev->ctrl_handler;
552 
553 	ret = v4l2_ctrl_handler_init(&fmdev->ctrl_handler, 5);
554 	if (ret < 0) {
555 		fmerr("(fmdev): Can't init ctrl handler\n");
556 		v4l2_ctrl_handler_free(&fmdev->ctrl_handler);
557 		return -EBUSY;
558 	}
559 
560 	/*
561 	 * Following controls are handled by V4L2 control framework.
562 	 * Added in ascending ID order.
563 	 */
564 	v4l2_ctrl_new_std(&fmdev->ctrl_handler, &fm_ctrl_ops,
565 			V4L2_CID_AUDIO_VOLUME, FM_RX_VOLUME_MIN,
566 			FM_RX_VOLUME_MAX, 1, FM_RX_VOLUME_MAX);
567 
568 	v4l2_ctrl_new_std(&fmdev->ctrl_handler, &fm_ctrl_ops,
569 			V4L2_CID_AUDIO_MUTE, 0, 1, 1, 1);
570 
571 	v4l2_ctrl_new_std_menu(&fmdev->ctrl_handler, &fm_ctrl_ops,
572 			V4L2_CID_TUNE_PREEMPHASIS, V4L2_PREEMPHASIS_75_uS,
573 			0, V4L2_PREEMPHASIS_75_uS);
574 
575 	v4l2_ctrl_new_std(&fmdev->ctrl_handler, &fm_ctrl_ops,
576 			V4L2_CID_TUNE_POWER_LEVEL, FM_PWR_LVL_LOW,
577 			FM_PWR_LVL_HIGH, 1, FM_PWR_LVL_HIGH);
578 
579 	ctrl = v4l2_ctrl_new_std(&fmdev->ctrl_handler, &fm_ctrl_ops,
580 			V4L2_CID_TUNE_ANTENNA_CAPACITOR, 0,
581 			255, 1, 255);
582 
583 	if (ctrl)
584 		ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE;
585 
586 	return 0;
587 }
588 
589 void *fm_v4l2_deinit_video_device(void)
590 {
591 	struct fmdev *fmdev;
592 
593 
594 	fmdev = video_get_drvdata(&gradio_dev);
595 
596 	/* Unregister to v4l2 ctrl handler framework*/
597 	v4l2_ctrl_handler_free(&fmdev->ctrl_handler);
598 
599 	/* Unregister RADIO device from V4L2 subsystem */
600 	video_unregister_device(&gradio_dev);
601 
602 	v4l2_device_unregister(&fmdev->v4l2_dev);
603 
604 	return fmdev;
605 }
606