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  */
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 	/* wait till tune operation has completed */
178 	timeout = jiffies + msecs_to_jiffies(tune_timeout);
179 	do {
180 		retval = si470x_get_register(radio, STATUSRSSI);
181 		if (retval < 0)
182 			goto stop;
183 		timed_out = time_after(jiffies, timeout);
184 	} while (((radio->registers[STATUSRSSI] & STATUSRSSI_STC) == 0) &&
185 		(!timed_out));
186 	if ((radio->registers[STATUSRSSI] & STATUSRSSI_STC) == 0)
187 		dev_warn(&radio->videodev->dev, "tune does not complete\n");
188 	if (timed_out)
189 		dev_warn(&radio->videodev->dev,
190 			"tune timed out after %u ms\n", tune_timeout);
191 
192 stop:
193 	/* stop tuning */
194 	radio->registers[CHANNEL] &= ~CHANNEL_TUNE;
195 	retval = si470x_set_register(radio, CHANNEL);
196 
197 done:
198 	return retval;
199 }
200 
201 
202 /*
203  * si470x_get_freq - get the frequency
204  */
205 static int si470x_get_freq(struct si470x_device *radio, unsigned int *freq)
206 {
207 	unsigned int spacing, band_bottom;
208 	unsigned short chan;
209 	int retval;
210 
211 	/* Spacing (kHz) */
212 	switch ((radio->registers[SYSCONFIG2] & SYSCONFIG2_SPACE) >> 4) {
213 	/* 0: 200 kHz (USA, Australia) */
214 	case 0:
215 		spacing = 0.200 * FREQ_MUL; break;
216 	/* 1: 100 kHz (Europe, Japan) */
217 	case 1:
218 		spacing = 0.100 * FREQ_MUL; break;
219 	/* 2:  50 kHz */
220 	default:
221 		spacing = 0.050 * FREQ_MUL; break;
222 	};
223 
224 	/* Bottom of Band (MHz) */
225 	switch ((radio->registers[SYSCONFIG2] & SYSCONFIG2_BAND) >> 6) {
226 	/* 0: 87.5 - 108 MHz (USA, Europe) */
227 	case 0:
228 		band_bottom = 87.5 * FREQ_MUL; break;
229 	/* 1: 76   - 108 MHz (Japan wide band) */
230 	default:
231 		band_bottom = 76   * FREQ_MUL; break;
232 	/* 2: 76   -  90 MHz (Japan) */
233 	case 2:
234 		band_bottom = 76   * FREQ_MUL; break;
235 	};
236 
237 	/* read channel */
238 	retval = si470x_get_register(radio, READCHAN);
239 	chan = radio->registers[READCHAN] & READCHAN_READCHAN;
240 
241 	/* Frequency (MHz) = Spacing (kHz) x Channel + Bottom of Band (MHz) */
242 	*freq = chan * spacing + band_bottom;
243 
244 	return retval;
245 }
246 
247 
248 /*
249  * si470x_set_freq - set the frequency
250  */
251 int si470x_set_freq(struct si470x_device *radio, unsigned int freq)
252 {
253 	unsigned int spacing, band_bottom;
254 	unsigned short chan;
255 
256 	/* Spacing (kHz) */
257 	switch ((radio->registers[SYSCONFIG2] & SYSCONFIG2_SPACE) >> 4) {
258 	/* 0: 200 kHz (USA, Australia) */
259 	case 0:
260 		spacing = 0.200 * FREQ_MUL; break;
261 	/* 1: 100 kHz (Europe, Japan) */
262 	case 1:
263 		spacing = 0.100 * FREQ_MUL; break;
264 	/* 2:  50 kHz */
265 	default:
266 		spacing = 0.050 * FREQ_MUL; break;
267 	};
268 
269 	/* Bottom of Band (MHz) */
270 	switch ((radio->registers[SYSCONFIG2] & SYSCONFIG2_BAND) >> 6) {
271 	/* 0: 87.5 - 108 MHz (USA, Europe) */
272 	case 0:
273 		band_bottom = 87.5 * FREQ_MUL; break;
274 	/* 1: 76   - 108 MHz (Japan wide band) */
275 	default:
276 		band_bottom = 76   * FREQ_MUL; break;
277 	/* 2: 76   -  90 MHz (Japan) */
278 	case 2:
279 		band_bottom = 76   * FREQ_MUL; break;
280 	};
281 
282 	/* Chan = [ Freq (Mhz) - Bottom of Band (MHz) ] / Spacing (kHz) */
283 	chan = (freq - band_bottom) / spacing;
284 
285 	return si470x_set_chan(radio, chan);
286 }
287 
288 
289 /*
290  * si470x_set_seek - set seek
291  */
292 static int si470x_set_seek(struct si470x_device *radio,
293 		unsigned int wrap_around, unsigned int seek_upward)
294 {
295 	int retval = 0;
296 	unsigned long timeout;
297 	bool timed_out = 0;
298 
299 	/* start seeking */
300 	radio->registers[POWERCFG] |= POWERCFG_SEEK;
301 	if (wrap_around == 1)
302 		radio->registers[POWERCFG] &= ~POWERCFG_SKMODE;
303 	else
304 		radio->registers[POWERCFG] |= POWERCFG_SKMODE;
305 	if (seek_upward == 1)
306 		radio->registers[POWERCFG] |= POWERCFG_SEEKUP;
307 	else
308 		radio->registers[POWERCFG] &= ~POWERCFG_SEEKUP;
309 	retval = si470x_set_register(radio, POWERCFG);
310 	if (retval < 0)
311 		goto done;
312 
313 	/* wait till seek operation has completed */
314 	timeout = jiffies + msecs_to_jiffies(seek_timeout);
315 	do {
316 		retval = si470x_get_register(radio, STATUSRSSI);
317 		if (retval < 0)
318 			goto stop;
319 		timed_out = time_after(jiffies, timeout);
320 	} while (((radio->registers[STATUSRSSI] & STATUSRSSI_STC) == 0) &&
321 		(!timed_out));
322 	if ((radio->registers[STATUSRSSI] & STATUSRSSI_STC) == 0)
323 		dev_warn(&radio->videodev->dev, "seek does not complete\n");
324 	if (radio->registers[STATUSRSSI] & STATUSRSSI_SF)
325 		dev_warn(&radio->videodev->dev,
326 			"seek failed / band limit reached\n");
327 	if (timed_out)
328 		dev_warn(&radio->videodev->dev,
329 			"seek timed out after %u ms\n", seek_timeout);
330 
331 stop:
332 	/* stop seeking */
333 	radio->registers[POWERCFG] &= ~POWERCFG_SEEK;
334 	retval = si470x_set_register(radio, POWERCFG);
335 
336 done:
337 	/* try again, if timed out */
338 	if ((retval == 0) && timed_out)
339 		retval = -EAGAIN;
340 
341 	return retval;
342 }
343 
344 
345 /*
346  * si470x_start - switch on radio
347  */
348 int si470x_start(struct si470x_device *radio)
349 {
350 	int retval;
351 
352 	/* powercfg */
353 	radio->registers[POWERCFG] =
354 		POWERCFG_DMUTE | POWERCFG_ENABLE | POWERCFG_RDSM;
355 	retval = si470x_set_register(radio, POWERCFG);
356 	if (retval < 0)
357 		goto done;
358 
359 	/* sysconfig 1 */
360 	radio->registers[SYSCONFIG1] =
361 		(de << 11) & SYSCONFIG1_DE;		/* DE*/
362 	retval = si470x_set_register(radio, SYSCONFIG1);
363 	if (retval < 0)
364 		goto done;
365 
366 	/* sysconfig 2 */
367 	radio->registers[SYSCONFIG2] =
368 		(0x3f  << 8) |				/* SEEKTH */
369 		((band  << 6) & SYSCONFIG2_BAND)  |	/* BAND */
370 		((space << 4) & SYSCONFIG2_SPACE) |	/* SPACE */
371 		15;					/* VOLUME (max) */
372 	retval = si470x_set_register(radio, SYSCONFIG2);
373 	if (retval < 0)
374 		goto done;
375 
376 	/* reset last channel */
377 	retval = si470x_set_chan(radio,
378 		radio->registers[CHANNEL] & CHANNEL_CHAN);
379 
380 done:
381 	return retval;
382 }
383 
384 
385 /*
386  * si470x_stop - switch off radio
387  */
388 int si470x_stop(struct si470x_device *radio)
389 {
390 	int retval;
391 
392 	/* sysconfig 1 */
393 	radio->registers[SYSCONFIG1] &= ~SYSCONFIG1_RDS;
394 	retval = si470x_set_register(radio, SYSCONFIG1);
395 	if (retval < 0)
396 		goto done;
397 
398 	/* powercfg */
399 	radio->registers[POWERCFG] &= ~POWERCFG_DMUTE;
400 	/* POWERCFG_ENABLE has to automatically go low */
401 	radio->registers[POWERCFG] |= POWERCFG_ENABLE |	POWERCFG_DISABLE;
402 	retval = si470x_set_register(radio, POWERCFG);
403 
404 done:
405 	return retval;
406 }
407 
408 
409 /*
410  * si470x_rds_on - switch on rds reception
411  */
412 static int si470x_rds_on(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 		radio->registers[SYSCONFIG1] &= ~SYSCONFIG1_RDS;
421 
422 	return retval;
423 }
424 
425 
426 
427 /**************************************************************************
428  * File Operations Interface
429  **************************************************************************/
430 
431 /*
432  * si470x_fops_read - read RDS data
433  */
434 static ssize_t si470x_fops_read(struct file *file, char __user *buf,
435 		size_t count, loff_t *ppos)
436 {
437 	struct si470x_device *radio = video_drvdata(file);
438 	int retval = 0;
439 	unsigned int block_count = 0;
440 
441 	/* switch on rds reception */
442 	mutex_lock(&radio->lock);
443 	if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0)
444 		si470x_rds_on(radio);
445 
446 	/* block if no new data available */
447 	while (radio->wr_index == radio->rd_index) {
448 		if (file->f_flags & O_NONBLOCK) {
449 			retval = -EWOULDBLOCK;
450 			goto done;
451 		}
452 		if (wait_event_interruptible(radio->read_queue,
453 			radio->wr_index != radio->rd_index) < 0) {
454 			retval = -EINTR;
455 			goto done;
456 		}
457 	}
458 
459 	/* calculate block count from byte count */
460 	count /= 3;
461 
462 	/* copy RDS block out of internal buffer and to user buffer */
463 	mutex_lock(&radio->lock);
464 	while (block_count < count) {
465 		if (radio->rd_index == radio->wr_index)
466 			break;
467 
468 		/* always transfer rds complete blocks */
469 		if (copy_to_user(buf, &radio->buffer[radio->rd_index], 3))
470 			/* retval = -EFAULT; */
471 			break;
472 
473 		/* increment and wrap read pointer */
474 		radio->rd_index += 3;
475 		if (radio->rd_index >= radio->buf_size)
476 			radio->rd_index = 0;
477 
478 		/* increment counters */
479 		block_count++;
480 		buf += 3;
481 		retval += 3;
482 	}
483 
484 done:
485 	mutex_unlock(&radio->lock);
486 	return retval;
487 }
488 
489 
490 /*
491  * si470x_fops_poll - poll RDS data
492  */
493 static unsigned int si470x_fops_poll(struct file *file,
494 		struct poll_table_struct *pts)
495 {
496 	struct si470x_device *radio = video_drvdata(file);
497 	int retval = 0;
498 
499 	/* switch on rds reception */
500 
501 	mutex_lock(&radio->lock);
502 	if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0)
503 		si470x_rds_on(radio);
504 	mutex_unlock(&radio->lock);
505 
506 	poll_wait(file, &radio->read_queue, pts);
507 
508 	if (radio->rd_index != radio->wr_index)
509 		retval = POLLIN | POLLRDNORM;
510 
511 	return retval;
512 }
513 
514 
515 /*
516  * si470x_fops - file operations interface
517  */
518 static const struct v4l2_file_operations si470x_fops = {
519 	.owner			= THIS_MODULE,
520 	.read			= si470x_fops_read,
521 	.poll			= si470x_fops_poll,
522 	.unlocked_ioctl		= video_ioctl2,
523 	.open			= si470x_fops_open,
524 	.release		= si470x_fops_release,
525 };
526 
527 
528 
529 /**************************************************************************
530  * Video4Linux Interface
531  **************************************************************************/
532 
533 /*
534  * si470x_vidioc_queryctrl - enumerate control items
535  */
536 static int si470x_vidioc_queryctrl(struct file *file, void *priv,
537 		struct v4l2_queryctrl *qc)
538 {
539 	struct si470x_device *radio = video_drvdata(file);
540 	int retval = -EINVAL;
541 
542 	/* abort if qc->id is below V4L2_CID_BASE */
543 	if (qc->id < V4L2_CID_BASE)
544 		goto done;
545 
546 	/* search video control */
547 	switch (qc->id) {
548 	case V4L2_CID_AUDIO_VOLUME:
549 		return v4l2_ctrl_query_fill(qc, 0, 15, 1, 15);
550 	case V4L2_CID_AUDIO_MUTE:
551 		return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1);
552 	}
553 
554 	/* disable unsupported base controls */
555 	/* to satisfy kradio and such apps */
556 	if ((retval == -EINVAL) && (qc->id < V4L2_CID_LASTP1)) {
557 		qc->flags = V4L2_CTRL_FLAG_DISABLED;
558 		retval = 0;
559 	}
560 
561 done:
562 	if (retval < 0)
563 		dev_warn(&radio->videodev->dev,
564 			"query controls failed with %d\n", retval);
565 	return retval;
566 }
567 
568 
569 /*
570  * si470x_vidioc_g_ctrl - get the value of a control
571  */
572 static int si470x_vidioc_g_ctrl(struct file *file, void *priv,
573 		struct v4l2_control *ctrl)
574 {
575 	struct si470x_device *radio = video_drvdata(file);
576 	int retval = 0;
577 
578 	mutex_lock(&radio->lock);
579 	/* safety checks */
580 	retval = si470x_disconnect_check(radio);
581 	if (retval)
582 		goto done;
583 
584 	switch (ctrl->id) {
585 	case V4L2_CID_AUDIO_VOLUME:
586 		ctrl->value = radio->registers[SYSCONFIG2] &
587 				SYSCONFIG2_VOLUME;
588 		break;
589 	case V4L2_CID_AUDIO_MUTE:
590 		ctrl->value = ((radio->registers[POWERCFG] &
591 				POWERCFG_DMUTE) == 0) ? 1 : 0;
592 		break;
593 	default:
594 		retval = -EINVAL;
595 	}
596 
597 done:
598 	if (retval < 0)
599 		dev_warn(&radio->videodev->dev,
600 			"get control failed with %d\n", retval);
601 
602 	mutex_unlock(&radio->lock);
603 	return retval;
604 }
605 
606 
607 /*
608  * si470x_vidioc_s_ctrl - set the value of a control
609  */
610 static int si470x_vidioc_s_ctrl(struct file *file, void *priv,
611 		struct v4l2_control *ctrl)
612 {
613 	struct si470x_device *radio = video_drvdata(file);
614 	int retval = 0;
615 
616 	mutex_lock(&radio->lock);
617 	/* safety checks */
618 	retval = si470x_disconnect_check(radio);
619 	if (retval)
620 		goto done;
621 
622 	switch (ctrl->id) {
623 	case V4L2_CID_AUDIO_VOLUME:
624 		radio->registers[SYSCONFIG2] &= ~SYSCONFIG2_VOLUME;
625 		radio->registers[SYSCONFIG2] |= ctrl->value;
626 		retval = si470x_set_register(radio, SYSCONFIG2);
627 		break;
628 	case V4L2_CID_AUDIO_MUTE:
629 		if (ctrl->value == 1)
630 			radio->registers[POWERCFG] &= ~POWERCFG_DMUTE;
631 		else
632 			radio->registers[POWERCFG] |= POWERCFG_DMUTE;
633 		retval = si470x_set_register(radio, POWERCFG);
634 		break;
635 	default:
636 		retval = -EINVAL;
637 	}
638 
639 done:
640 	if (retval < 0)
641 		dev_warn(&radio->videodev->dev,
642 			"set control failed with %d\n", retval);
643 	mutex_unlock(&radio->lock);
644 	return retval;
645 }
646 
647 
648 /*
649  * si470x_vidioc_g_audio - get audio attributes
650  */
651 static int si470x_vidioc_g_audio(struct file *file, void *priv,
652 		struct v4l2_audio *audio)
653 {
654 	/* driver constants */
655 	audio->index = 0;
656 	strcpy(audio->name, "Radio");
657 	audio->capability = V4L2_AUDCAP_STEREO;
658 	audio->mode = 0;
659 
660 	return 0;
661 }
662 
663 
664 /*
665  * si470x_vidioc_g_tuner - get tuner attributes
666  */
667 static int si470x_vidioc_g_tuner(struct file *file, void *priv,
668 		struct v4l2_tuner *tuner)
669 {
670 	struct si470x_device *radio = video_drvdata(file);
671 	int retval = 0;
672 
673 	mutex_lock(&radio->lock);
674 	/* safety checks */
675 	retval = si470x_disconnect_check(radio);
676 	if (retval)
677 		goto done;
678 
679 	if (tuner->index != 0) {
680 		retval = -EINVAL;
681 		goto done;
682 	}
683 
684 	retval = si470x_get_register(radio, STATUSRSSI);
685 	if (retval < 0)
686 		goto done;
687 
688 	/* driver constants */
689 	strcpy(tuner->name, "FM");
690 	tuner->type = V4L2_TUNER_RADIO;
691 	tuner->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO |
692 			    V4L2_TUNER_CAP_RDS | V4L2_TUNER_CAP_RDS_BLOCK_IO;
693 
694 	/* range limits */
695 	switch ((radio->registers[SYSCONFIG2] & SYSCONFIG2_BAND) >> 6) {
696 	/* 0: 87.5 - 108 MHz (USA, Europe, default) */
697 	default:
698 		tuner->rangelow  =  87.5 * FREQ_MUL;
699 		tuner->rangehigh = 108   * FREQ_MUL;
700 		break;
701 	/* 1: 76   - 108 MHz (Japan wide band) */
702 	case 1:
703 		tuner->rangelow  =  76   * FREQ_MUL;
704 		tuner->rangehigh = 108   * FREQ_MUL;
705 		break;
706 	/* 2: 76   -  90 MHz (Japan) */
707 	case 2:
708 		tuner->rangelow  =  76   * FREQ_MUL;
709 		tuner->rangehigh =  90   * FREQ_MUL;
710 		break;
711 	};
712 
713 	/* stereo indicator == stereo (instead of mono) */
714 	if ((radio->registers[STATUSRSSI] & STATUSRSSI_ST) == 0)
715 		tuner->rxsubchans = V4L2_TUNER_SUB_MONO;
716 	else
717 		tuner->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO;
718 	/* If there is a reliable method of detecting an RDS channel,
719 	   then this code should check for that before setting this
720 	   RDS subchannel. */
721 	tuner->rxsubchans |= V4L2_TUNER_SUB_RDS;
722 
723 	/* mono/stereo selector */
724 	if ((radio->registers[POWERCFG] & POWERCFG_MONO) == 0)
725 		tuner->audmode = V4L2_TUNER_MODE_STEREO;
726 	else
727 		tuner->audmode = V4L2_TUNER_MODE_MONO;
728 
729 	/* min is worst, max is best; signal:0..0xffff; rssi: 0..0xff */
730 	/* measured in units of dbµV in 1 db increments (max at ~75 dbµV) */
731 	tuner->signal = (radio->registers[STATUSRSSI] & STATUSRSSI_RSSI);
732 	/* the ideal factor is 0xffff/75 = 873,8 */
733 	tuner->signal = (tuner->signal * 873) + (8 * tuner->signal / 10);
734 
735 	/* automatic frequency control: -1: freq to low, 1 freq to high */
736 	/* AFCRL does only indicate that freq. differs, not if too low/high */
737 	tuner->afc = (radio->registers[STATUSRSSI] & STATUSRSSI_AFCRL) ? 1 : 0;
738 
739 done:
740 	if (retval < 0)
741 		dev_warn(&radio->videodev->dev,
742 			"get tuner failed with %d\n", retval);
743 	mutex_unlock(&radio->lock);
744 	return retval;
745 }
746 
747 
748 /*
749  * si470x_vidioc_s_tuner - set tuner attributes
750  */
751 static int si470x_vidioc_s_tuner(struct file *file, void *priv,
752 		struct v4l2_tuner *tuner)
753 {
754 	struct si470x_device *radio = video_drvdata(file);
755 	int retval = 0;
756 
757 	mutex_lock(&radio->lock);
758 	/* safety checks */
759 	retval = si470x_disconnect_check(radio);
760 	if (retval)
761 		goto done;
762 
763 	if (tuner->index != 0)
764 		goto done;
765 
766 	/* mono/stereo selector */
767 	switch (tuner->audmode) {
768 	case V4L2_TUNER_MODE_MONO:
769 		radio->registers[POWERCFG] |= POWERCFG_MONO;  /* force mono */
770 		break;
771 	case V4L2_TUNER_MODE_STEREO:
772 		radio->registers[POWERCFG] &= ~POWERCFG_MONO; /* try stereo */
773 		break;
774 	default:
775 		goto done;
776 	}
777 
778 	retval = si470x_set_register(radio, POWERCFG);
779 
780 done:
781 	if (retval < 0)
782 		dev_warn(&radio->videodev->dev,
783 			"set tuner failed with %d\n", retval);
784 	mutex_unlock(&radio->lock);
785 	return retval;
786 }
787 
788 
789 /*
790  * si470x_vidioc_g_frequency - get tuner or modulator radio frequency
791  */
792 static int si470x_vidioc_g_frequency(struct file *file, void *priv,
793 		struct v4l2_frequency *freq)
794 {
795 	struct si470x_device *radio = video_drvdata(file);
796 	int retval = 0;
797 
798 	/* safety checks */
799 	mutex_lock(&radio->lock);
800 	retval = si470x_disconnect_check(radio);
801 	if (retval)
802 		goto done;
803 
804 	if (freq->tuner != 0) {
805 		retval = -EINVAL;
806 		goto done;
807 	}
808 
809 	freq->type = V4L2_TUNER_RADIO;
810 	retval = si470x_get_freq(radio, &freq->frequency);
811 
812 done:
813 	if (retval < 0)
814 		dev_warn(&radio->videodev->dev,
815 			"get frequency failed with %d\n", retval);
816 	mutex_unlock(&radio->lock);
817 	return retval;
818 }
819 
820 
821 /*
822  * si470x_vidioc_s_frequency - set tuner or modulator radio frequency
823  */
824 static int si470x_vidioc_s_frequency(struct file *file, void *priv,
825 		struct v4l2_frequency *freq)
826 {
827 	struct si470x_device *radio = video_drvdata(file);
828 	int retval = 0;
829 
830 	mutex_lock(&radio->lock);
831 	/* safety checks */
832 	retval = si470x_disconnect_check(radio);
833 	if (retval)
834 		goto done;
835 
836 	if (freq->tuner != 0) {
837 		retval = -EINVAL;
838 		goto done;
839 	}
840 
841 	retval = si470x_set_freq(radio, freq->frequency);
842 
843 done:
844 	if (retval < 0)
845 		dev_warn(&radio->videodev->dev,
846 			"set frequency failed with %d\n", retval);
847 	mutex_unlock(&radio->lock);
848 	return retval;
849 }
850 
851 
852 /*
853  * si470x_vidioc_s_hw_freq_seek - set hardware frequency seek
854  */
855 static int si470x_vidioc_s_hw_freq_seek(struct file *file, void *priv,
856 		struct v4l2_hw_freq_seek *seek)
857 {
858 	struct si470x_device *radio = video_drvdata(file);
859 	int retval = 0;
860 
861 	mutex_lock(&radio->lock);
862 	/* safety checks */
863 	retval = si470x_disconnect_check(radio);
864 	if (retval)
865 		goto done;
866 
867 	if (seek->tuner != 0) {
868 		retval = -EINVAL;
869 		goto done;
870 	}
871 
872 	retval = si470x_set_seek(radio, seek->wrap_around, seek->seek_upward);
873 
874 done:
875 	if (retval < 0)
876 		dev_warn(&radio->videodev->dev,
877 			"set hardware frequency seek failed with %d\n", retval);
878 	mutex_unlock(&radio->lock);
879 	return retval;
880 }
881 
882 
883 /*
884  * si470x_ioctl_ops - video device ioctl operations
885  */
886 static const struct v4l2_ioctl_ops si470x_ioctl_ops = {
887 	.vidioc_querycap	= si470x_vidioc_querycap,
888 	.vidioc_queryctrl	= si470x_vidioc_queryctrl,
889 	.vidioc_g_ctrl		= si470x_vidioc_g_ctrl,
890 	.vidioc_s_ctrl		= si470x_vidioc_s_ctrl,
891 	.vidioc_g_audio		= si470x_vidioc_g_audio,
892 	.vidioc_g_tuner		= si470x_vidioc_g_tuner,
893 	.vidioc_s_tuner		= si470x_vidioc_s_tuner,
894 	.vidioc_g_frequency	= si470x_vidioc_g_frequency,
895 	.vidioc_s_frequency	= si470x_vidioc_s_frequency,
896 	.vidioc_s_hw_freq_seek	= si470x_vidioc_s_hw_freq_seek,
897 };
898 
899 
900 /*
901  * si470x_viddev_template - video device interface
902  */
903 struct video_device si470x_viddev_template = {
904 	.fops			= &si470x_fops,
905 	.name			= DRIVER_NAME,
906 	.release		= video_device_release,
907 	.ioctl_ops		= &si470x_ioctl_ops,
908 };
909