1 /*
2  *  drivers/media/radio/si470x/radio-si470x-common.c
3  *
4  *  Driver for radios with Silicon Labs Si470x FM Radio Receivers
5  *
6  *  Copyright (c) 2009 Tobias Lorenz <tobias.lorenz@gmx.net>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21  */
22 
23 
24 /*
25  * History:
26  * 2008-01-12	Tobias Lorenz <tobias.lorenz@gmx.net>
27  *		Version 1.0.0
28  *		- First working version
29  * 2008-01-13	Tobias Lorenz <tobias.lorenz@gmx.net>
30  *		Version 1.0.1
31  *		- Improved error handling, every function now returns errno
32  *		- Improved multi user access (start/mute/stop)
33  *		- Channel doesn't get lost anymore after start/mute/stop
34  *		- RDS support added (polling mode via interrupt EP 1)
35  *		- marked default module parameters with *value*
36  *		- switched from bit structs to bit masks
37  *		- header file cleaned and integrated
38  * 2008-01-14	Tobias Lorenz <tobias.lorenz@gmx.net>
39  * 		Version 1.0.2
40  * 		- hex values are now lower case
41  * 		- commented USB ID for ADS/Tech moved on todo list
42  * 		- blacklisted si470x in hid-quirks.c
43  * 		- rds buffer handling functions integrated into *_work, *_read
44  * 		- rds_command in si470x_poll exchanged against simple retval
45  * 		- check for firmware version 15
46  * 		- code order and prototypes still remain the same
47  * 		- spacing and bottom of band codes remain the same
48  * 2008-01-16	Tobias Lorenz <tobias.lorenz@gmx.net>
49  *		Version 1.0.3
50  * 		- code reordered to avoid function prototypes
51  *		- switch/case defaults are now more user-friendly
52  *		- unified comment style
53  *		- applied all checkpatch.pl v1.12 suggestions
54  *		  except the warning about the too long lines with bit comments
55  *		- renamed FMRADIO to RADIO to cut line length (checkpatch.pl)
56  * 2008-01-22	Tobias Lorenz <tobias.lorenz@gmx.net>
57  *		Version 1.0.4
58  *		- avoid poss. locking when doing copy_to_user which may sleep
59  *		- RDS is automatically activated on read now
60  *		- code cleaned of unnecessary rds_commands
61  *		- USB Vendor/Product ID for ADS/Tech FM Radio Receiver verified
62  *		  (thanks to Guillaume RAMOUSSE)
63  * 2008-01-27	Tobias Lorenz <tobias.lorenz@gmx.net>
64  *		Version 1.0.5
65  *		- number of seek_retries changed to tune_timeout
66  *		- fixed problem with incomplete tune operations by own buffers
67  *		- optimization of variables and printf types
68  *		- improved error logging
69  * 2008-01-31	Tobias Lorenz <tobias.lorenz@gmx.net>
70  *		Oliver Neukum <oliver@neukum.org>
71  *		Version 1.0.6
72  *		- fixed coverity checker warnings in *_usb_driver_disconnect
73  *		- probe()/open() race by correct ordering in probe()
74  *		- DMA coherency rules by separate allocation of all buffers
75  *		- use of endianness macros
76  *		- abuse of spinlock, replaced by mutex
77  *		- racy handling of timer in disconnect,
78  *		  replaced by delayed_work
79  *		- racy interruptible_sleep_on(),
80  *		  replaced with wait_event_interruptible()
81  *		- handle signals in read()
82  * 2008-02-08	Tobias Lorenz <tobias.lorenz@gmx.net>
83  *		Oliver Neukum <oliver@neukum.org>
84  *		Version 1.0.7
85  *		- usb autosuspend support
86  *		- unplugging fixed
87  * 2008-05-07	Tobias Lorenz <tobias.lorenz@gmx.net>
88  *		Version 1.0.8
89  *		- hardware frequency seek support
90  *		- afc indication
91  *		- more safety checks, let si470x_get_freq return errno
92  *		- vidioc behavior corrected according to v4l2 spec
93  * 2008-10-20	Alexey Klimov <klimov.linux@gmail.com>
94  * 		- add support for KWorld USB FM Radio FM700
95  * 		- blacklisted KWorld radio in hid-core.c and hid-ids.h
96  * 2008-12-03	Mark Lord <mlord@pobox.com>
97  *		- add support for DealExtreme USB Radio
98  * 2009-01-31	Bob Ross <pigiron@gmx.com>
99  *		- correction of stereo detection/setting
100  *		- correction of signal strength indicator scaling
101  * 2009-01-31	Rick Bronson <rick@efn.org>
102  *		Tobias Lorenz <tobias.lorenz@gmx.net>
103  *		- add LED status output
104  *		- get HW/SW version from scratchpad
105  * 2009-06-16   Edouard Lafargue <edouard@lafargue.name>
106  *		Version 1.0.10
107  *		- add support for interrupt mode for RDS endpoint,
108  *                instead of polling.
109  *                Improves RDS reception significantly
110  */
111 
112 
113 /* kernel includes */
114 #include "radio-si470x.h"
115 
116 
117 
118 /**************************************************************************
119  * Module Parameters
120  **************************************************************************/
121 
122 /* Spacing (kHz) */
123 /* 0: 200 kHz (USA, Australia) */
124 /* 1: 100 kHz (Europe, Japan) */
125 /* 2:  50 kHz */
126 static unsigned short space = 2;
127 module_param(space, ushort, 0444);
128 MODULE_PARM_DESC(space, "Spacing: 0=200kHz 1=100kHz *2=50kHz*");
129 
130 /* Bottom of Band (MHz) */
131 /* 0: 87.5 - 108 MHz (USA, Europe)*/
132 /* 1: 76   - 108 MHz (Japan wide band) */
133 /* 2: 76   -  90 MHz (Japan) */
134 static unsigned short band = 1;
135 module_param(band, ushort, 0444);
136 MODULE_PARM_DESC(band, "Band: 0=87.5..108MHz *1=76..108MHz* 2=76..90MHz");
137 
138 /* De-emphasis */
139 /* 0: 75 us (USA) */
140 /* 1: 50 us (Europe, Australia, Japan) */
141 static unsigned short de = 1;
142 module_param(de, ushort, 0444);
143 MODULE_PARM_DESC(de, "De-emphasis: 0=75us *1=50us*");
144 
145 /* Tune timeout */
146 static unsigned int tune_timeout = 3000;
147 module_param(tune_timeout, uint, 0644);
148 MODULE_PARM_DESC(tune_timeout, "Tune timeout: *3000*");
149 
150 /* Seek timeout */
151 static unsigned int seek_timeout = 5000;
152 module_param(seek_timeout, uint, 0644);
153 MODULE_PARM_DESC(seek_timeout, "Seek timeout: *5000*");
154 
155 
156 
157 /**************************************************************************
158  * Generic Functions
159  **************************************************************************/
160 
161 /*
162  * si470x_set_chan - set the channel
163  */
si470x_set_chan(struct si470x_device * radio,unsigned short chan)164 static int si470x_set_chan(struct si470x_device *radio, unsigned short chan)
165 {
166 	int retval;
167 	unsigned long timeout;
168 	bool timed_out = 0;
169 
170 	/* start tuning */
171 	radio->registers[CHANNEL] &= ~CHANNEL_CHAN;
172 	radio->registers[CHANNEL] |= CHANNEL_TUNE | chan;
173 	retval = si470x_set_register(radio, CHANNEL);
174 	if (retval < 0)
175 		goto done;
176 
177 	/* currently I2C driver only uses interrupt way to tune */
178 	if (radio->stci_enabled) {
179 		INIT_COMPLETION(radio->completion);
180 
181 		/* wait till tune operation has completed */
182 		retval = wait_for_completion_timeout(&radio->completion,
183 				msecs_to_jiffies(tune_timeout));
184 		if (!retval)
185 			timed_out = true;
186 	} else {
187 		/* wait till tune operation has completed */
188 		timeout = jiffies + msecs_to_jiffies(tune_timeout);
189 		do {
190 			retval = si470x_get_register(radio, STATUSRSSI);
191 			if (retval < 0)
192 				goto stop;
193 			timed_out = time_after(jiffies, timeout);
194 		} while (((radio->registers[STATUSRSSI] & STATUSRSSI_STC) == 0)
195 				&& (!timed_out));
196 	}
197 
198 	if ((radio->registers[STATUSRSSI] & STATUSRSSI_STC) == 0)
199 		dev_warn(&radio->videodev->dev, "tune does not complete\n");
200 	if (timed_out)
201 		dev_warn(&radio->videodev->dev,
202 			"tune timed out after %u ms\n", tune_timeout);
203 
204 stop:
205 	/* stop tuning */
206 	radio->registers[CHANNEL] &= ~CHANNEL_TUNE;
207 	retval = si470x_set_register(radio, CHANNEL);
208 
209 done:
210 	return retval;
211 }
212 
213 
214 /*
215  * si470x_get_freq - get the frequency
216  */
si470x_get_freq(struct si470x_device * radio,unsigned int * freq)217 static int si470x_get_freq(struct si470x_device *radio, unsigned int *freq)
218 {
219 	unsigned int spacing, band_bottom;
220 	unsigned short chan;
221 	int retval;
222 
223 	/* Spacing (kHz) */
224 	switch ((radio->registers[SYSCONFIG2] & SYSCONFIG2_SPACE) >> 4) {
225 	/* 0: 200 kHz (USA, Australia) */
226 	case 0:
227 		spacing = 0.200 * FREQ_MUL; break;
228 	/* 1: 100 kHz (Europe, Japan) */
229 	case 1:
230 		spacing = 0.100 * FREQ_MUL; break;
231 	/* 2:  50 kHz */
232 	default:
233 		spacing = 0.050 * FREQ_MUL; break;
234 	};
235 
236 	/* Bottom of Band (MHz) */
237 	switch ((radio->registers[SYSCONFIG2] & SYSCONFIG2_BAND) >> 6) {
238 	/* 0: 87.5 - 108 MHz (USA, Europe) */
239 	case 0:
240 		band_bottom = 87.5 * FREQ_MUL; break;
241 	/* 1: 76   - 108 MHz (Japan wide band) */
242 	default:
243 		band_bottom = 76   * FREQ_MUL; break;
244 	/* 2: 76   -  90 MHz (Japan) */
245 	case 2:
246 		band_bottom = 76   * FREQ_MUL; break;
247 	};
248 
249 	/* read channel */
250 	retval = si470x_get_register(radio, READCHAN);
251 	chan = radio->registers[READCHAN] & READCHAN_READCHAN;
252 
253 	/* Frequency (MHz) = Spacing (kHz) x Channel + Bottom of Band (MHz) */
254 	*freq = chan * spacing + band_bottom;
255 
256 	return retval;
257 }
258 
259 
260 /*
261  * si470x_set_freq - set the frequency
262  */
si470x_set_freq(struct si470x_device * radio,unsigned int freq)263 int si470x_set_freq(struct si470x_device *radio, unsigned int freq)
264 {
265 	unsigned int spacing, band_bottom;
266 	unsigned short chan;
267 
268 	/* Spacing (kHz) */
269 	switch ((radio->registers[SYSCONFIG2] & SYSCONFIG2_SPACE) >> 4) {
270 	/* 0: 200 kHz (USA, Australia) */
271 	case 0:
272 		spacing = 0.200 * FREQ_MUL; break;
273 	/* 1: 100 kHz (Europe, Japan) */
274 	case 1:
275 		spacing = 0.100 * FREQ_MUL; break;
276 	/* 2:  50 kHz */
277 	default:
278 		spacing = 0.050 * FREQ_MUL; break;
279 	};
280 
281 	/* Bottom of Band (MHz) */
282 	switch ((radio->registers[SYSCONFIG2] & SYSCONFIG2_BAND) >> 6) {
283 	/* 0: 87.5 - 108 MHz (USA, Europe) */
284 	case 0:
285 		band_bottom = 87.5 * FREQ_MUL; break;
286 	/* 1: 76   - 108 MHz (Japan wide band) */
287 	default:
288 		band_bottom = 76   * FREQ_MUL; break;
289 	/* 2: 76   -  90 MHz (Japan) */
290 	case 2:
291 		band_bottom = 76   * FREQ_MUL; break;
292 	};
293 
294 	/* Chan = [ Freq (Mhz) - Bottom of Band (MHz) ] / Spacing (kHz) */
295 	chan = (freq - band_bottom) / spacing;
296 
297 	return si470x_set_chan(radio, chan);
298 }
299 
300 
301 /*
302  * si470x_set_seek - set seek
303  */
si470x_set_seek(struct si470x_device * radio,unsigned int wrap_around,unsigned int seek_upward)304 static int si470x_set_seek(struct si470x_device *radio,
305 		unsigned int wrap_around, unsigned int seek_upward)
306 {
307 	int retval = 0;
308 	unsigned long timeout;
309 	bool timed_out = 0;
310 
311 	/* start seeking */
312 	radio->registers[POWERCFG] |= POWERCFG_SEEK;
313 	if (wrap_around == 1)
314 		radio->registers[POWERCFG] &= ~POWERCFG_SKMODE;
315 	else
316 		radio->registers[POWERCFG] |= POWERCFG_SKMODE;
317 	if (seek_upward == 1)
318 		radio->registers[POWERCFG] |= POWERCFG_SEEKUP;
319 	else
320 		radio->registers[POWERCFG] &= ~POWERCFG_SEEKUP;
321 	retval = si470x_set_register(radio, POWERCFG);
322 	if (retval < 0)
323 		goto done;
324 
325 	/* currently I2C driver only uses interrupt way to seek */
326 	if (radio->stci_enabled) {
327 		INIT_COMPLETION(radio->completion);
328 
329 		/* wait till seek operation has completed */
330 		retval = wait_for_completion_timeout(&radio->completion,
331 				msecs_to_jiffies(seek_timeout));
332 		if (!retval)
333 			timed_out = true;
334 	} else {
335 		/* wait till seek operation has completed */
336 		timeout = jiffies + msecs_to_jiffies(seek_timeout);
337 		do {
338 			retval = si470x_get_register(radio, STATUSRSSI);
339 			if (retval < 0)
340 				goto stop;
341 			timed_out = time_after(jiffies, timeout);
342 		} while (((radio->registers[STATUSRSSI] & STATUSRSSI_STC) == 0)
343 				&& (!timed_out));
344 	}
345 
346 	if ((radio->registers[STATUSRSSI] & STATUSRSSI_STC) == 0)
347 		dev_warn(&radio->videodev->dev, "seek does not complete\n");
348 	if (radio->registers[STATUSRSSI] & STATUSRSSI_SF)
349 		dev_warn(&radio->videodev->dev,
350 			"seek failed / band limit reached\n");
351 	if (timed_out)
352 		dev_warn(&radio->videodev->dev,
353 			"seek timed out after %u ms\n", seek_timeout);
354 
355 stop:
356 	/* stop seeking */
357 	radio->registers[POWERCFG] &= ~POWERCFG_SEEK;
358 	retval = si470x_set_register(radio, POWERCFG);
359 
360 done:
361 	/* try again, if timed out */
362 	if ((retval == 0) && timed_out)
363 		retval = -EAGAIN;
364 
365 	return retval;
366 }
367 
368 
369 /*
370  * si470x_start - switch on radio
371  */
si470x_start(struct si470x_device * radio)372 int si470x_start(struct si470x_device *radio)
373 {
374 	int retval;
375 
376 	/* powercfg */
377 	radio->registers[POWERCFG] =
378 		POWERCFG_DMUTE | POWERCFG_ENABLE | POWERCFG_RDSM;
379 	retval = si470x_set_register(radio, POWERCFG);
380 	if (retval < 0)
381 		goto done;
382 
383 	/* sysconfig 1 */
384 	radio->registers[SYSCONFIG1] =
385 		(de << 11) & SYSCONFIG1_DE;		/* DE*/
386 	retval = si470x_set_register(radio, SYSCONFIG1);
387 	if (retval < 0)
388 		goto done;
389 
390 	/* sysconfig 2 */
391 	radio->registers[SYSCONFIG2] =
392 		(0x3f  << 8) |				/* SEEKTH */
393 		((band  << 6) & SYSCONFIG2_BAND)  |	/* BAND */
394 		((space << 4) & SYSCONFIG2_SPACE) |	/* SPACE */
395 		15;					/* VOLUME (max) */
396 	retval = si470x_set_register(radio, SYSCONFIG2);
397 	if (retval < 0)
398 		goto done;
399 
400 	/* reset last channel */
401 	retval = si470x_set_chan(radio,
402 		radio->registers[CHANNEL] & CHANNEL_CHAN);
403 
404 done:
405 	return retval;
406 }
407 
408 
409 /*
410  * si470x_stop - switch off radio
411  */
si470x_stop(struct si470x_device * radio)412 int si470x_stop(struct si470x_device *radio)
413 {
414 	int retval;
415 
416 	/* sysconfig 1 */
417 	radio->registers[SYSCONFIG1] &= ~SYSCONFIG1_RDS;
418 	retval = si470x_set_register(radio, SYSCONFIG1);
419 	if (retval < 0)
420 		goto done;
421 
422 	/* powercfg */
423 	radio->registers[POWERCFG] &= ~POWERCFG_DMUTE;
424 	/* POWERCFG_ENABLE has to automatically go low */
425 	radio->registers[POWERCFG] |= POWERCFG_ENABLE |	POWERCFG_DISABLE;
426 	retval = si470x_set_register(radio, POWERCFG);
427 
428 done:
429 	return retval;
430 }
431 
432 
433 /*
434  * si470x_rds_on - switch on rds reception
435  */
si470x_rds_on(struct si470x_device * radio)436 static int si470x_rds_on(struct si470x_device *radio)
437 {
438 	int retval;
439 
440 	/* sysconfig 1 */
441 	radio->registers[SYSCONFIG1] |= SYSCONFIG1_RDS;
442 	retval = si470x_set_register(radio, SYSCONFIG1);
443 	if (retval < 0)
444 		radio->registers[SYSCONFIG1] &= ~SYSCONFIG1_RDS;
445 
446 	return retval;
447 }
448 
449 
450 
451 /**************************************************************************
452  * File Operations Interface
453  **************************************************************************/
454 
455 /*
456  * si470x_fops_read - read RDS data
457  */
si470x_fops_read(struct file * file,char __user * buf,size_t count,loff_t * ppos)458 static ssize_t si470x_fops_read(struct file *file, char __user *buf,
459 		size_t count, loff_t *ppos)
460 {
461 	struct si470x_device *radio = video_drvdata(file);
462 	int retval = 0;
463 	unsigned int block_count = 0;
464 
465 	/* switch on rds reception */
466 	mutex_lock(&radio->lock);
467 	if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0)
468 		si470x_rds_on(radio);
469 
470 	/* block if no new data available */
471 	while (radio->wr_index == radio->rd_index) {
472 		if (file->f_flags & O_NONBLOCK) {
473 			retval = -EWOULDBLOCK;
474 			goto done;
475 		}
476 		if (wait_event_interruptible(radio->read_queue,
477 			radio->wr_index != radio->rd_index) < 0) {
478 			retval = -EINTR;
479 			goto done;
480 		}
481 	}
482 
483 	/* calculate block count from byte count */
484 	count /= 3;
485 
486 	/* copy RDS block out of internal buffer and to user buffer */
487 	while (block_count < count) {
488 		if (radio->rd_index == radio->wr_index)
489 			break;
490 
491 		/* always transfer rds complete blocks */
492 		if (copy_to_user(buf, &radio->buffer[radio->rd_index], 3))
493 			/* retval = -EFAULT; */
494 			break;
495 
496 		/* increment and wrap read pointer */
497 		radio->rd_index += 3;
498 		if (radio->rd_index >= radio->buf_size)
499 			radio->rd_index = 0;
500 
501 		/* increment counters */
502 		block_count++;
503 		buf += 3;
504 		retval += 3;
505 	}
506 
507 done:
508 	mutex_unlock(&radio->lock);
509 	return retval;
510 }
511 
512 
513 /*
514  * si470x_fops_poll - poll RDS data
515  */
si470x_fops_poll(struct file * file,struct poll_table_struct * pts)516 static unsigned int si470x_fops_poll(struct file *file,
517 		struct poll_table_struct *pts)
518 {
519 	struct si470x_device *radio = video_drvdata(file);
520 	int retval = 0;
521 
522 	/* switch on rds reception */
523 
524 	mutex_lock(&radio->lock);
525 	if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0)
526 		si470x_rds_on(radio);
527 	mutex_unlock(&radio->lock);
528 
529 	poll_wait(file, &radio->read_queue, pts);
530 
531 	if (radio->rd_index != radio->wr_index)
532 		retval = POLLIN | POLLRDNORM;
533 
534 	return retval;
535 }
536 
537 
538 /*
539  * si470x_fops - file operations interface
540  */
541 static const struct v4l2_file_operations si470x_fops = {
542 	.owner			= THIS_MODULE,
543 	.read			= si470x_fops_read,
544 	.poll			= si470x_fops_poll,
545 	.unlocked_ioctl		= video_ioctl2,
546 	.open			= si470x_fops_open,
547 	.release		= si470x_fops_release,
548 };
549 
550 
551 
552 /**************************************************************************
553  * Video4Linux Interface
554  **************************************************************************/
555 
556 /*
557  * si470x_vidioc_queryctrl - enumerate control items
558  */
si470x_vidioc_queryctrl(struct file * file,void * priv,struct v4l2_queryctrl * qc)559 static int si470x_vidioc_queryctrl(struct file *file, void *priv,
560 		struct v4l2_queryctrl *qc)
561 {
562 	struct si470x_device *radio = video_drvdata(file);
563 	int retval = -EINVAL;
564 
565 	/* abort if qc->id is below V4L2_CID_BASE */
566 	if (qc->id < V4L2_CID_BASE)
567 		goto done;
568 
569 	/* search video control */
570 	switch (qc->id) {
571 	case V4L2_CID_AUDIO_VOLUME:
572 		return v4l2_ctrl_query_fill(qc, 0, 15, 1, 15);
573 	case V4L2_CID_AUDIO_MUTE:
574 		return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1);
575 	}
576 
577 	/* disable unsupported base controls */
578 	/* to satisfy kradio and such apps */
579 	if ((retval == -EINVAL) && (qc->id < V4L2_CID_LASTP1)) {
580 		qc->flags = V4L2_CTRL_FLAG_DISABLED;
581 		retval = 0;
582 	}
583 
584 done:
585 	if (retval < 0)
586 		dev_warn(&radio->videodev->dev,
587 			"query controls failed with %d\n", retval);
588 	return retval;
589 }
590 
591 
592 /*
593  * si470x_vidioc_g_ctrl - get the value of a control
594  */
si470x_vidioc_g_ctrl(struct file * file,void * priv,struct v4l2_control * ctrl)595 static int si470x_vidioc_g_ctrl(struct file *file, void *priv,
596 		struct v4l2_control *ctrl)
597 {
598 	struct si470x_device *radio = video_drvdata(file);
599 	int retval = 0;
600 
601 	mutex_lock(&radio->lock);
602 	/* safety checks */
603 	retval = si470x_disconnect_check(radio);
604 	if (retval)
605 		goto done;
606 
607 	switch (ctrl->id) {
608 	case V4L2_CID_AUDIO_VOLUME:
609 		ctrl->value = radio->registers[SYSCONFIG2] &
610 				SYSCONFIG2_VOLUME;
611 		break;
612 	case V4L2_CID_AUDIO_MUTE:
613 		ctrl->value = ((radio->registers[POWERCFG] &
614 				POWERCFG_DMUTE) == 0) ? 1 : 0;
615 		break;
616 	default:
617 		retval = -EINVAL;
618 	}
619 
620 done:
621 	if (retval < 0)
622 		dev_warn(&radio->videodev->dev,
623 			"get control failed with %d\n", retval);
624 
625 	mutex_unlock(&radio->lock);
626 	return retval;
627 }
628 
629 
630 /*
631  * si470x_vidioc_s_ctrl - set the value of a control
632  */
si470x_vidioc_s_ctrl(struct file * file,void * priv,struct v4l2_control * ctrl)633 static int si470x_vidioc_s_ctrl(struct file *file, void *priv,
634 		struct v4l2_control *ctrl)
635 {
636 	struct si470x_device *radio = video_drvdata(file);
637 	int retval = 0;
638 
639 	mutex_lock(&radio->lock);
640 	/* safety checks */
641 	retval = si470x_disconnect_check(radio);
642 	if (retval)
643 		goto done;
644 
645 	switch (ctrl->id) {
646 	case V4L2_CID_AUDIO_VOLUME:
647 		radio->registers[SYSCONFIG2] &= ~SYSCONFIG2_VOLUME;
648 		radio->registers[SYSCONFIG2] |= ctrl->value;
649 		retval = si470x_set_register(radio, SYSCONFIG2);
650 		break;
651 	case V4L2_CID_AUDIO_MUTE:
652 		if (ctrl->value == 1)
653 			radio->registers[POWERCFG] &= ~POWERCFG_DMUTE;
654 		else
655 			radio->registers[POWERCFG] |= POWERCFG_DMUTE;
656 		retval = si470x_set_register(radio, POWERCFG);
657 		break;
658 	default:
659 		retval = -EINVAL;
660 	}
661 
662 done:
663 	if (retval < 0)
664 		dev_warn(&radio->videodev->dev,
665 			"set control failed with %d\n", retval);
666 	mutex_unlock(&radio->lock);
667 	return retval;
668 }
669 
670 
671 /*
672  * si470x_vidioc_g_audio - get audio attributes
673  */
si470x_vidioc_g_audio(struct file * file,void * priv,struct v4l2_audio * audio)674 static int si470x_vidioc_g_audio(struct file *file, void *priv,
675 		struct v4l2_audio *audio)
676 {
677 	/* driver constants */
678 	audio->index = 0;
679 	strcpy(audio->name, "Radio");
680 	audio->capability = V4L2_AUDCAP_STEREO;
681 	audio->mode = 0;
682 
683 	return 0;
684 }
685 
686 
687 /*
688  * si470x_vidioc_g_tuner - get tuner attributes
689  */
si470x_vidioc_g_tuner(struct file * file,void * priv,struct v4l2_tuner * tuner)690 static int si470x_vidioc_g_tuner(struct file *file, void *priv,
691 		struct v4l2_tuner *tuner)
692 {
693 	struct si470x_device *radio = video_drvdata(file);
694 	int retval = 0;
695 
696 	mutex_lock(&radio->lock);
697 	/* safety checks */
698 	retval = si470x_disconnect_check(radio);
699 	if (retval)
700 		goto done;
701 
702 	if (tuner->index != 0) {
703 		retval = -EINVAL;
704 		goto done;
705 	}
706 
707 	retval = si470x_get_register(radio, STATUSRSSI);
708 	if (retval < 0)
709 		goto done;
710 
711 	/* driver constants */
712 	strcpy(tuner->name, "FM");
713 	tuner->type = V4L2_TUNER_RADIO;
714 	tuner->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO |
715 			    V4L2_TUNER_CAP_RDS | V4L2_TUNER_CAP_RDS_BLOCK_IO;
716 
717 	/* range limits */
718 	switch ((radio->registers[SYSCONFIG2] & SYSCONFIG2_BAND) >> 6) {
719 	/* 0: 87.5 - 108 MHz (USA, Europe, default) */
720 	default:
721 		tuner->rangelow  =  87.5 * FREQ_MUL;
722 		tuner->rangehigh = 108   * FREQ_MUL;
723 		break;
724 	/* 1: 76   - 108 MHz (Japan wide band) */
725 	case 1:
726 		tuner->rangelow  =  76   * FREQ_MUL;
727 		tuner->rangehigh = 108   * FREQ_MUL;
728 		break;
729 	/* 2: 76   -  90 MHz (Japan) */
730 	case 2:
731 		tuner->rangelow  =  76   * FREQ_MUL;
732 		tuner->rangehigh =  90   * FREQ_MUL;
733 		break;
734 	};
735 
736 	/* stereo indicator == stereo (instead of mono) */
737 	if ((radio->registers[STATUSRSSI] & STATUSRSSI_ST) == 0)
738 		tuner->rxsubchans = V4L2_TUNER_SUB_MONO;
739 	else
740 		tuner->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO;
741 	/* If there is a reliable method of detecting an RDS channel,
742 	   then this code should check for that before setting this
743 	   RDS subchannel. */
744 	tuner->rxsubchans |= V4L2_TUNER_SUB_RDS;
745 
746 	/* mono/stereo selector */
747 	if ((radio->registers[POWERCFG] & POWERCFG_MONO) == 0)
748 		tuner->audmode = V4L2_TUNER_MODE_STEREO;
749 	else
750 		tuner->audmode = V4L2_TUNER_MODE_MONO;
751 
752 	/* min is worst, max is best; signal:0..0xffff; rssi: 0..0xff */
753 	/* measured in units of dbµV in 1 db increments (max at ~75 dbµV) */
754 	tuner->signal = (radio->registers[STATUSRSSI] & STATUSRSSI_RSSI);
755 	/* the ideal factor is 0xffff/75 = 873,8 */
756 	tuner->signal = (tuner->signal * 873) + (8 * tuner->signal / 10);
757 
758 	/* automatic frequency control: -1: freq to low, 1 freq to high */
759 	/* AFCRL does only indicate that freq. differs, not if too low/high */
760 	tuner->afc = (radio->registers[STATUSRSSI] & STATUSRSSI_AFCRL) ? 1 : 0;
761 
762 done:
763 	if (retval < 0)
764 		dev_warn(&radio->videodev->dev,
765 			"get tuner failed with %d\n", retval);
766 	mutex_unlock(&radio->lock);
767 	return retval;
768 }
769 
770 
771 /*
772  * si470x_vidioc_s_tuner - set tuner attributes
773  */
si470x_vidioc_s_tuner(struct file * file,void * priv,struct v4l2_tuner * tuner)774 static int si470x_vidioc_s_tuner(struct file *file, void *priv,
775 		struct v4l2_tuner *tuner)
776 {
777 	struct si470x_device *radio = video_drvdata(file);
778 	int retval = 0;
779 
780 	mutex_lock(&radio->lock);
781 	/* safety checks */
782 	retval = si470x_disconnect_check(radio);
783 	if (retval)
784 		goto done;
785 
786 	if (tuner->index != 0)
787 		goto done;
788 
789 	/* mono/stereo selector */
790 	switch (tuner->audmode) {
791 	case V4L2_TUNER_MODE_MONO:
792 		radio->registers[POWERCFG] |= POWERCFG_MONO;  /* force mono */
793 		break;
794 	case V4L2_TUNER_MODE_STEREO:
795 		radio->registers[POWERCFG] &= ~POWERCFG_MONO; /* try stereo */
796 		break;
797 	default:
798 		goto done;
799 	}
800 
801 	retval = si470x_set_register(radio, POWERCFG);
802 
803 done:
804 	if (retval < 0)
805 		dev_warn(&radio->videodev->dev,
806 			"set tuner failed with %d\n", retval);
807 	mutex_unlock(&radio->lock);
808 	return retval;
809 }
810 
811 
812 /*
813  * si470x_vidioc_g_frequency - get tuner or modulator radio frequency
814  */
si470x_vidioc_g_frequency(struct file * file,void * priv,struct v4l2_frequency * freq)815 static int si470x_vidioc_g_frequency(struct file *file, void *priv,
816 		struct v4l2_frequency *freq)
817 {
818 	struct si470x_device *radio = video_drvdata(file);
819 	int retval = 0;
820 
821 	/* safety checks */
822 	mutex_lock(&radio->lock);
823 	retval = si470x_disconnect_check(radio);
824 	if (retval)
825 		goto done;
826 
827 	if (freq->tuner != 0) {
828 		retval = -EINVAL;
829 		goto done;
830 	}
831 
832 	freq->type = V4L2_TUNER_RADIO;
833 	retval = si470x_get_freq(radio, &freq->frequency);
834 
835 done:
836 	if (retval < 0)
837 		dev_warn(&radio->videodev->dev,
838 			"get frequency failed with %d\n", retval);
839 	mutex_unlock(&radio->lock);
840 	return retval;
841 }
842 
843 
844 /*
845  * si470x_vidioc_s_frequency - set tuner or modulator radio frequency
846  */
si470x_vidioc_s_frequency(struct file * file,void * priv,struct v4l2_frequency * freq)847 static int si470x_vidioc_s_frequency(struct file *file, void *priv,
848 		struct v4l2_frequency *freq)
849 {
850 	struct si470x_device *radio = video_drvdata(file);
851 	int retval = 0;
852 
853 	mutex_lock(&radio->lock);
854 	/* safety checks */
855 	retval = si470x_disconnect_check(radio);
856 	if (retval)
857 		goto done;
858 
859 	if (freq->tuner != 0) {
860 		retval = -EINVAL;
861 		goto done;
862 	}
863 
864 	retval = si470x_set_freq(radio, freq->frequency);
865 
866 done:
867 	if (retval < 0)
868 		dev_warn(&radio->videodev->dev,
869 			"set frequency failed with %d\n", retval);
870 	mutex_unlock(&radio->lock);
871 	return retval;
872 }
873 
874 
875 /*
876  * si470x_vidioc_s_hw_freq_seek - set hardware frequency seek
877  */
si470x_vidioc_s_hw_freq_seek(struct file * file,void * priv,struct v4l2_hw_freq_seek * seek)878 static int si470x_vidioc_s_hw_freq_seek(struct file *file, void *priv,
879 		struct v4l2_hw_freq_seek *seek)
880 {
881 	struct si470x_device *radio = video_drvdata(file);
882 	int retval = 0;
883 
884 	mutex_lock(&radio->lock);
885 	/* safety checks */
886 	retval = si470x_disconnect_check(radio);
887 	if (retval)
888 		goto done;
889 
890 	if (seek->tuner != 0) {
891 		retval = -EINVAL;
892 		goto done;
893 	}
894 
895 	retval = si470x_set_seek(radio, seek->wrap_around, seek->seek_upward);
896 
897 done:
898 	if (retval < 0)
899 		dev_warn(&radio->videodev->dev,
900 			"set hardware frequency seek failed with %d\n", retval);
901 	mutex_unlock(&radio->lock);
902 	return retval;
903 }
904 
905 
906 /*
907  * si470x_ioctl_ops - video device ioctl operations
908  */
909 static const struct v4l2_ioctl_ops si470x_ioctl_ops = {
910 	.vidioc_querycap	= si470x_vidioc_querycap,
911 	.vidioc_queryctrl	= si470x_vidioc_queryctrl,
912 	.vidioc_g_ctrl		= si470x_vidioc_g_ctrl,
913 	.vidioc_s_ctrl		= si470x_vidioc_s_ctrl,
914 	.vidioc_g_audio		= si470x_vidioc_g_audio,
915 	.vidioc_g_tuner		= si470x_vidioc_g_tuner,
916 	.vidioc_s_tuner		= si470x_vidioc_s_tuner,
917 	.vidioc_g_frequency	= si470x_vidioc_g_frequency,
918 	.vidioc_s_frequency	= si470x_vidioc_s_frequency,
919 	.vidioc_s_hw_freq_seek	= si470x_vidioc_s_hw_freq_seek,
920 };
921 
922 
923 /*
924  * si470x_viddev_template - video device interface
925  */
926 struct video_device si470x_viddev_template = {
927 	.fops			= &si470x_fops,
928 	.name			= DRIVER_NAME,
929 	.release		= video_device_release,
930 	.ioctl_ops		= &si470x_ioctl_ops,
931 };
932