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 	/* 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  */
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  */
263 int si470x_set_freq(struct si470x_device *radio, unsigned int freq)
264 {
265 	unsigned int spacing, band_bottom, band_top;
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/Top 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;
286 		band_top = 108 * FREQ_MUL;
287 		break;
288 	/* 1: 76   - 108 MHz (Japan wide band) */
289 	default:
290 		band_bottom = 76 * FREQ_MUL;
291 		band_top = 108 * FREQ_MUL;
292 		break;
293 	/* 2: 76   -  90 MHz (Japan) */
294 	case 2:
295 		band_bottom = 76 * FREQ_MUL;
296 		band_top = 90 * FREQ_MUL;
297 		break;
298 	};
299 
300 	freq = clamp(freq, band_bottom, band_top);
301 	/* Chan = [ Freq (Mhz) - Bottom of Band (MHz) ] / Spacing (kHz) */
302 	chan = (freq - band_bottom) / spacing;
303 
304 	return si470x_set_chan(radio, chan);
305 }
306 
307 
308 /*
309  * si470x_set_seek - set seek
310  */
311 static int si470x_set_seek(struct si470x_device *radio,
312 		unsigned int wrap_around, unsigned int seek_upward)
313 {
314 	int retval = 0;
315 	unsigned long timeout;
316 	bool timed_out = 0;
317 
318 	/* start seeking */
319 	radio->registers[POWERCFG] |= POWERCFG_SEEK;
320 	if (wrap_around == 1)
321 		radio->registers[POWERCFG] &= ~POWERCFG_SKMODE;
322 	else
323 		radio->registers[POWERCFG] |= POWERCFG_SKMODE;
324 	if (seek_upward == 1)
325 		radio->registers[POWERCFG] |= POWERCFG_SEEKUP;
326 	else
327 		radio->registers[POWERCFG] &= ~POWERCFG_SEEKUP;
328 	retval = si470x_set_register(radio, POWERCFG);
329 	if (retval < 0)
330 		return retval;
331 
332 	/* currently I2C driver only uses interrupt way to seek */
333 	if (radio->stci_enabled) {
334 		INIT_COMPLETION(radio->completion);
335 
336 		/* wait till seek operation has completed */
337 		retval = wait_for_completion_timeout(&radio->completion,
338 				msecs_to_jiffies(seek_timeout));
339 		if (!retval)
340 			timed_out = true;
341 	} else {
342 		/* wait till seek operation has completed */
343 		timeout = jiffies + msecs_to_jiffies(seek_timeout);
344 		do {
345 			retval = si470x_get_register(radio, STATUSRSSI);
346 			if (retval < 0)
347 				goto stop;
348 			timed_out = time_after(jiffies, timeout);
349 		} while (((radio->registers[STATUSRSSI] & STATUSRSSI_STC) == 0)
350 				&& (!timed_out));
351 	}
352 
353 	if ((radio->registers[STATUSRSSI] & STATUSRSSI_STC) == 0)
354 		dev_warn(&radio->videodev.dev, "seek does not complete\n");
355 	if (radio->registers[STATUSRSSI] & STATUSRSSI_SF)
356 		dev_warn(&radio->videodev.dev,
357 			"seek failed / band limit reached\n");
358 
359 stop:
360 	/* stop seeking */
361 	radio->registers[POWERCFG] &= ~POWERCFG_SEEK;
362 	retval = si470x_set_register(radio, POWERCFG);
363 
364 	/* try again, if timed out */
365 	if (retval == 0 && timed_out)
366 		return -EAGAIN;
367 	return retval;
368 }
369 
370 
371 /*
372  * si470x_start - switch on radio
373  */
374 int si470x_start(struct si470x_device *radio)
375 {
376 	int retval;
377 
378 	/* powercfg */
379 	radio->registers[POWERCFG] =
380 		POWERCFG_DMUTE | POWERCFG_ENABLE | POWERCFG_RDSM;
381 	retval = si470x_set_register(radio, POWERCFG);
382 	if (retval < 0)
383 		goto done;
384 
385 	/* sysconfig 1 */
386 	radio->registers[SYSCONFIG1] =
387 		(de << 11) & SYSCONFIG1_DE;		/* DE*/
388 	retval = si470x_set_register(radio, SYSCONFIG1);
389 	if (retval < 0)
390 		goto done;
391 
392 	/* sysconfig 2 */
393 	radio->registers[SYSCONFIG2] =
394 		(0x3f  << 8) |				/* SEEKTH */
395 		((band  << 6) & SYSCONFIG2_BAND)  |	/* BAND */
396 		((space << 4) & SYSCONFIG2_SPACE) |	/* SPACE */
397 		15;					/* VOLUME (max) */
398 	retval = si470x_set_register(radio, SYSCONFIG2);
399 	if (retval < 0)
400 		goto done;
401 
402 	/* reset last channel */
403 	retval = si470x_set_chan(radio,
404 		radio->registers[CHANNEL] & CHANNEL_CHAN);
405 
406 done:
407 	return retval;
408 }
409 
410 
411 /*
412  * si470x_stop - switch off radio
413  */
414 int si470x_stop(struct si470x_device *radio)
415 {
416 	int retval;
417 
418 	/* sysconfig 1 */
419 	radio->registers[SYSCONFIG1] &= ~SYSCONFIG1_RDS;
420 	retval = si470x_set_register(radio, SYSCONFIG1);
421 	if (retval < 0)
422 		goto done;
423 
424 	/* powercfg */
425 	radio->registers[POWERCFG] &= ~POWERCFG_DMUTE;
426 	/* POWERCFG_ENABLE has to automatically go low */
427 	radio->registers[POWERCFG] |= POWERCFG_ENABLE |	POWERCFG_DISABLE;
428 	retval = si470x_set_register(radio, POWERCFG);
429 
430 done:
431 	return retval;
432 }
433 
434 
435 /*
436  * si470x_rds_on - switch on rds reception
437  */
438 static int si470x_rds_on(struct si470x_device *radio)
439 {
440 	int retval;
441 
442 	/* sysconfig 1 */
443 	radio->registers[SYSCONFIG1] |= SYSCONFIG1_RDS;
444 	retval = si470x_set_register(radio, SYSCONFIG1);
445 	if (retval < 0)
446 		radio->registers[SYSCONFIG1] &= ~SYSCONFIG1_RDS;
447 
448 	return retval;
449 }
450 
451 
452 
453 /**************************************************************************
454  * File Operations Interface
455  **************************************************************************/
456 
457 /*
458  * si470x_fops_read - read RDS data
459  */
460 static ssize_t si470x_fops_read(struct file *file, char __user *buf,
461 		size_t count, loff_t *ppos)
462 {
463 	struct si470x_device *radio = video_drvdata(file);
464 	int retval = 0;
465 	unsigned int block_count = 0;
466 
467 	/* switch on rds reception */
468 	if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0)
469 		si470x_rds_on(radio);
470 
471 	/* block if no new data available */
472 	while (radio->wr_index == radio->rd_index) {
473 		if (file->f_flags & O_NONBLOCK) {
474 			retval = -EWOULDBLOCK;
475 			goto done;
476 		}
477 		if (wait_event_interruptible(radio->read_queue,
478 			radio->wr_index != radio->rd_index) < 0) {
479 			retval = -EINTR;
480 			goto done;
481 		}
482 	}
483 
484 	/* calculate block count from byte count */
485 	count /= 3;
486 
487 	/* copy RDS block out of internal buffer and to user buffer */
488 	while (block_count < count) {
489 		if (radio->rd_index == radio->wr_index)
490 			break;
491 
492 		/* always transfer rds complete blocks */
493 		if (copy_to_user(buf, &radio->buffer[radio->rd_index], 3))
494 			/* retval = -EFAULT; */
495 			break;
496 
497 		/* increment and wrap read pointer */
498 		radio->rd_index += 3;
499 		if (radio->rd_index >= radio->buf_size)
500 			radio->rd_index = 0;
501 
502 		/* increment counters */
503 		block_count++;
504 		buf += 3;
505 		retval += 3;
506 	}
507 
508 done:
509 	return retval;
510 }
511 
512 
513 /*
514  * si470x_fops_poll - poll RDS data
515  */
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 	unsigned long req_events = poll_requested_events(pts);
521 	int retval = v4l2_ctrl_poll(file, pts);
522 
523 	if (req_events & (POLLIN | POLLRDNORM)) {
524 		/* switch on rds reception */
525 		if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0)
526 			si470x_rds_on(radio);
527 
528 		poll_wait(file, &radio->read_queue, pts);
529 
530 		if (radio->rd_index != radio->wr_index)
531 			retval |= POLLIN | POLLRDNORM;
532 	}
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 static int si470x_s_ctrl(struct v4l2_ctrl *ctrl)
558 {
559 	struct si470x_device *radio =
560 		container_of(ctrl->handler, struct si470x_device, hdl);
561 
562 	switch (ctrl->id) {
563 	case V4L2_CID_AUDIO_VOLUME:
564 		radio->registers[SYSCONFIG2] &= ~SYSCONFIG2_VOLUME;
565 		radio->registers[SYSCONFIG2] |= ctrl->val;
566 		return si470x_set_register(radio, SYSCONFIG2);
567 	case V4L2_CID_AUDIO_MUTE:
568 		if (ctrl->val)
569 			radio->registers[POWERCFG] &= ~POWERCFG_DMUTE;
570 		else
571 			radio->registers[POWERCFG] |= POWERCFG_DMUTE;
572 		return si470x_set_register(radio, POWERCFG);
573 	default:
574 		return -EINVAL;
575 	}
576 }
577 
578 
579 /*
580  * si470x_vidioc_g_tuner - get tuner attributes
581  */
582 static int si470x_vidioc_g_tuner(struct file *file, void *priv,
583 		struct v4l2_tuner *tuner)
584 {
585 	struct si470x_device *radio = video_drvdata(file);
586 	int retval;
587 
588 	if (tuner->index != 0)
589 		return -EINVAL;
590 
591 	retval = si470x_get_register(radio, STATUSRSSI);
592 	if (retval < 0)
593 		return retval;
594 
595 	/* driver constants */
596 	strcpy(tuner->name, "FM");
597 	tuner->type = V4L2_TUNER_RADIO;
598 	tuner->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO |
599 			    V4L2_TUNER_CAP_RDS | V4L2_TUNER_CAP_RDS_BLOCK_IO;
600 
601 	/* range limits */
602 	switch ((radio->registers[SYSCONFIG2] & SYSCONFIG2_BAND) >> 6) {
603 	/* 0: 87.5 - 108 MHz (USA, Europe, default) */
604 	default:
605 		tuner->rangelow  =  87.5 * FREQ_MUL;
606 		tuner->rangehigh = 108   * FREQ_MUL;
607 		break;
608 	/* 1: 76   - 108 MHz (Japan wide band) */
609 	case 1:
610 		tuner->rangelow  =  76   * FREQ_MUL;
611 		tuner->rangehigh = 108   * FREQ_MUL;
612 		break;
613 	/* 2: 76   -  90 MHz (Japan) */
614 	case 2:
615 		tuner->rangelow  =  76   * FREQ_MUL;
616 		tuner->rangehigh =  90   * FREQ_MUL;
617 		break;
618 	};
619 
620 	/* stereo indicator == stereo (instead of mono) */
621 	if ((radio->registers[STATUSRSSI] & STATUSRSSI_ST) == 0)
622 		tuner->rxsubchans = V4L2_TUNER_SUB_MONO;
623 	else
624 		tuner->rxsubchans = V4L2_TUNER_SUB_STEREO;
625 	/* If there is a reliable method of detecting an RDS channel,
626 	   then this code should check for that before setting this
627 	   RDS subchannel. */
628 	tuner->rxsubchans |= V4L2_TUNER_SUB_RDS;
629 
630 	/* mono/stereo selector */
631 	if ((radio->registers[POWERCFG] & POWERCFG_MONO) == 0)
632 		tuner->audmode = V4L2_TUNER_MODE_STEREO;
633 	else
634 		tuner->audmode = V4L2_TUNER_MODE_MONO;
635 
636 	/* min is worst, max is best; signal:0..0xffff; rssi: 0..0xff */
637 	/* measured in units of dbµV in 1 db increments (max at ~75 dbµV) */
638 	tuner->signal = (radio->registers[STATUSRSSI] & STATUSRSSI_RSSI);
639 	/* the ideal factor is 0xffff/75 = 873,8 */
640 	tuner->signal = (tuner->signal * 873) + (8 * tuner->signal / 10);
641 	if (tuner->signal > 0xffff)
642 		tuner->signal = 0xffff;
643 
644 	/* automatic frequency control: -1: freq to low, 1 freq to high */
645 	/* AFCRL does only indicate that freq. differs, not if too low/high */
646 	tuner->afc = (radio->registers[STATUSRSSI] & STATUSRSSI_AFCRL) ? 1 : 0;
647 
648 	return retval;
649 }
650 
651 
652 /*
653  * si470x_vidioc_s_tuner - set tuner attributes
654  */
655 static int si470x_vidioc_s_tuner(struct file *file, void *priv,
656 		struct v4l2_tuner *tuner)
657 {
658 	struct si470x_device *radio = video_drvdata(file);
659 
660 	if (tuner->index != 0)
661 		return -EINVAL;
662 
663 	/* mono/stereo selector */
664 	switch (tuner->audmode) {
665 	case V4L2_TUNER_MODE_MONO:
666 		radio->registers[POWERCFG] |= POWERCFG_MONO;  /* force mono */
667 		break;
668 	case V4L2_TUNER_MODE_STEREO:
669 	default:
670 		radio->registers[POWERCFG] &= ~POWERCFG_MONO; /* try stereo */
671 		break;
672 	}
673 
674 	return si470x_set_register(radio, POWERCFG);
675 }
676 
677 
678 /*
679  * si470x_vidioc_g_frequency - get tuner or modulator radio frequency
680  */
681 static int si470x_vidioc_g_frequency(struct file *file, void *priv,
682 		struct v4l2_frequency *freq)
683 {
684 	struct si470x_device *radio = video_drvdata(file);
685 
686 	if (freq->tuner != 0)
687 		return -EINVAL;
688 
689 	freq->type = V4L2_TUNER_RADIO;
690 	return si470x_get_freq(radio, &freq->frequency);
691 }
692 
693 
694 /*
695  * si470x_vidioc_s_frequency - set tuner or modulator radio frequency
696  */
697 static int si470x_vidioc_s_frequency(struct file *file, void *priv,
698 		struct v4l2_frequency *freq)
699 {
700 	struct si470x_device *radio = video_drvdata(file);
701 
702 	if (freq->tuner != 0)
703 		return -EINVAL;
704 
705 	return si470x_set_freq(radio, freq->frequency);
706 }
707 
708 
709 /*
710  * si470x_vidioc_s_hw_freq_seek - set hardware frequency seek
711  */
712 static int si470x_vidioc_s_hw_freq_seek(struct file *file, void *priv,
713 		struct v4l2_hw_freq_seek *seek)
714 {
715 	struct si470x_device *radio = video_drvdata(file);
716 
717 	if (seek->tuner != 0)
718 		return -EINVAL;
719 
720 	return si470x_set_seek(radio, seek->wrap_around, seek->seek_upward);
721 }
722 
723 const struct v4l2_ctrl_ops si470x_ctrl_ops = {
724 	.s_ctrl = si470x_s_ctrl,
725 };
726 
727 /*
728  * si470x_ioctl_ops - video device ioctl operations
729  */
730 static const struct v4l2_ioctl_ops si470x_ioctl_ops = {
731 	.vidioc_querycap	= si470x_vidioc_querycap,
732 	.vidioc_g_tuner		= si470x_vidioc_g_tuner,
733 	.vidioc_s_tuner		= si470x_vidioc_s_tuner,
734 	.vidioc_g_frequency	= si470x_vidioc_g_frequency,
735 	.vidioc_s_frequency	= si470x_vidioc_s_frequency,
736 	.vidioc_s_hw_freq_seek	= si470x_vidioc_s_hw_freq_seek,
737 	.vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
738 	.vidioc_unsubscribe_event = v4l2_event_unsubscribe,
739 };
740 
741 
742 /*
743  * si470x_viddev_template - video device interface
744  */
745 struct video_device si470x_viddev_template = {
746 	.fops			= &si470x_fops,
747 	.name			= DRIVER_NAME,
748 	.release		= video_device_release_empty,
749 	.ioctl_ops		= &si470x_ioctl_ops,
750 };
751