aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/radio/radio-sf16fmr2.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@g5.osdl.org>2006-09-30 12:39:15 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-09-30 12:39:15 -0400
commit5ffd1a6aaacc25be8cd0770a51ec6d46add3a276 (patch)
tree5b076c44f8b7ff88dba9a554d7748c6f083c9071 /drivers/media/radio/radio-sf16fmr2.c
parent0cd43f83d381c4246a08cd775834833d6fd64805 (diff)
parent8dd86eebc5315910ebfd9f30f1674254308be4b3 (diff)
Merge master.kernel.org:/pub/scm/linux/kernel/git/mchehab/v4l-dvb
* master.kernel.org:/pub/scm/linux/kernel/git/mchehab/v4l-dvb: (180 commits) V4L/DVB (4641): Trivial: use lowercase letters in hex subsystem ids V4L/DVB (4639): Cx88: add autodetection for alternate revision of Leadtek PVR V4L/DVB (4638): Basic DVB-T and analog TV support for the HVR1300. V4L/DVB (4637): Add a default method for VIDIOC_G_PARM V4L/DVB (4635): Extend bttv and saa7134 to check for both AGP and PCI PCI failure case V4L/DVB (4634): Zr36120: implement pcipci checks V4L/DVB (4632): Zoran: Implement pcipci failure check V4L/DVB (4631): Av7110: remove V4L2_CAP_VBI_CAPTURE flag V4L/DVB (4630): Av7110: FW_LOADER depemdency fixed V4L/DVB (4629): Saa7134: add card support for Proteus Pro 2309 V4L/DVB (4628): Fix VIDIOC_ENUMSTD ioctl in videodev.c V4L/DVB (4627): Vivi crashes with mplayer V4L/DVB (4626): On saa7111/7113, LUMA_CTRL need a different value V4L/DVB (4624): Tvaudio: Replaced kernel_thread() with kthread_run() V4L/DVB (4622): Copy-paste bug in videodev.c V4L/DVB (4620): Fix AGC configuration for MOD3000P-based boards V4L/DVB (4619): Fixes some I2C dependencies on V4L devices V4L/DVB (4617): Problem with dibusb-mb.c USB IDs V4L/DVB (4616): [PATCH] Nebula DigiTV USB RC support V4L/DVB (4614): Export symbol saa7134_tvaudio_setmute from saa7134 for saa7134-alsa ...
Diffstat (limited to 'drivers/media/radio/radio-sf16fmr2.c')
-rw-r--r--drivers/media/radio/radio-sf16fmr2.c223
1 files changed, 140 insertions, 83 deletions
diff --git a/drivers/media/radio/radio-sf16fmr2.c b/drivers/media/radio/radio-sf16fmr2.c
index 3483b2c7bc9d..4444dce864a9 100644
--- a/drivers/media/radio/radio-sf16fmr2.c
+++ b/drivers/media/radio/radio-sf16fmr2.c
@@ -10,6 +10,8 @@
10 * For read stereo/mono you must wait 0.1 sec after set frequency and 10 * For read stereo/mono you must wait 0.1 sec after set frequency and
11 * card unmuted so I set frequency on unmute 11 * card unmuted so I set frequency on unmute
12 * Signal handling seem to work only on autoscanning (not implemented) 12 * Signal handling seem to work only on autoscanning (not implemented)
13 *
14 * Converted to V4L2 API by Mauro Carvalho Chehab <mchehab@infradead.org>
13 */ 15 */
14 16
15#include <linux/module.h> /* Modules */ 17#include <linux/module.h> /* Modules */
@@ -18,12 +20,34 @@
18#include <linux/delay.h> /* udelay */ 20#include <linux/delay.h> /* udelay */
19#include <asm/io.h> /* outb, outb_p */ 21#include <asm/io.h> /* outb, outb_p */
20#include <asm/uaccess.h> /* copy to/from user */ 22#include <asm/uaccess.h> /* copy to/from user */
21#include <linux/videodev.h> /* kernel radio structs */ 23#include <linux/videodev2.h> /* kernel radio structs */
22#include <media/v4l2-common.h> 24#include <media/v4l2-common.h>
23#include <linux/mutex.h> 25#include <linux/mutex.h>
24 26
25static struct mutex lock; 27static struct mutex lock;
26 28
29#include <linux/version.h> /* for KERNEL_VERSION MACRO */
30#define RADIO_VERSION KERNEL_VERSION(0,0,2)
31
32static struct v4l2_queryctrl radio_qctrl[] = {
33 {
34 .id = V4L2_CID_AUDIO_MUTE,
35 .name = "Mute",
36 .minimum = 0,
37 .maximum = 1,
38 .default_value = 1,
39 .type = V4L2_CTRL_TYPE_BOOLEAN,
40 },{
41 .id = V4L2_CID_AUDIO_VOLUME,
42 .name = "Volume",
43 .minimum = 0,
44 .maximum = 65535,
45 .step = 1<<12,
46 .default_value = 0xff,
47 .type = V4L2_CTRL_TYPE_INTEGER,
48 }
49};
50
27#undef DEBUG 51#undef DEBUG
28//#define DEBUG 1 52//#define DEBUG 1
29 53
@@ -214,63 +238,65 @@ static int fmr2_do_ioctl(struct inode *inode, struct file *file,
214 238
215 switch(cmd) 239 switch(cmd)
216 { 240 {
217 case VIDIOCGCAP: 241 case VIDIOC_QUERYCAP:
218 { 242 {
219 struct video_capability *v = arg; 243 struct v4l2_capability *v = arg;
220 memset(v,0,sizeof(*v)); 244 memset(v,0,sizeof(*v));
221 strcpy(v->name, "SF16-FMR2 radio"); 245 strlcpy(v->driver, "radio-sf16fmr2", sizeof (v->driver));
222 v->type=VID_TYPE_TUNER; 246 strlcpy(v->card, "SF16-FMR2 radio", sizeof (v->card));
223 v->channels=1; 247 sprintf(v->bus_info,"ISA");
224 v->audios=1; 248 v->version = RADIO_VERSION;
249 v->capabilities = V4L2_CAP_TUNER;
250
225 return 0; 251 return 0;
226 } 252 }
227 case VIDIOCGTUNER: 253 case VIDIOC_G_TUNER:
228 { 254 {
229 struct video_tuner *v = arg; 255 struct v4l2_tuner *v = arg;
230 int mult; 256 int mult;
231 257
232 if(v->tuner) /* Only 1 tuner */ 258 if (v->index > 0)
233 return -EINVAL; 259 return -EINVAL;
260
261 memset(v,0,sizeof(*v));
234 strcpy(v->name, "FM"); 262 strcpy(v->name, "FM");
235 mult = (fmr2->flags & VIDEO_TUNER_LOW) ? 1 : 1000; 263 v->type = V4L2_TUNER_RADIO;
264
265 mult = (fmr2->flags & V4L2_TUNER_CAP_LOW) ? 1 : 1000;
236 v->rangelow = RSF16_MINFREQ/mult; 266 v->rangelow = RSF16_MINFREQ/mult;
237 v->rangehigh = RSF16_MAXFREQ/mult; 267 v->rangehigh = RSF16_MAXFREQ/mult;
238 v->flags = fmr2->flags | VIDEO_AUDIO_MUTABLE; 268 v->rxsubchans =V4L2_TUNER_SUB_MONO | V4L2_TUNER_MODE_STEREO;
239 if (fmr2->mute) 269 v->capability=fmr2->flags&V4L2_TUNER_CAP_LOW;
240 v->flags |= VIDEO_AUDIO_MUTE; 270
241 v->mode=VIDEO_MODE_AUTO; 271 v->audmode = fmr2->stereo ? V4L2_TUNER_MODE_STEREO:
272 V4L2_TUNER_MODE_MONO;
242 mutex_lock(&lock); 273 mutex_lock(&lock);
243 v->signal = fmr2_getsigstr(fmr2); 274 v->signal = fmr2_getsigstr(fmr2);
244 mutex_unlock(&lock); 275 mutex_unlock(&lock);
276
245 return 0; 277 return 0;
246 } 278 }
247 case VIDIOCSTUNER: 279 case VIDIOC_S_TUNER:
248 { 280 {
249 struct video_tuner *v = arg; 281 struct v4l2_tuner *v = arg;
250 if (v->tuner!=0) 282
283 if (v->index > 0)
251 return -EINVAL; 284 return -EINVAL;
252 fmr2->flags = v->flags & VIDEO_TUNER_LOW; 285
253 return 0;
254 }
255 case VIDIOCGFREQ:
256 {
257 unsigned long *freq = arg;
258 *freq = fmr2->curfreq;
259 if (!(fmr2->flags & VIDEO_TUNER_LOW))
260 *freq /= 1000;
261 return 0; 286 return 0;
262 } 287 }
263 case VIDIOCSFREQ: 288 case VIDIOC_S_FREQUENCY:
264 { 289 {
265 unsigned long *freq = arg; 290 struct v4l2_frequency *f = arg;
266 if (!(fmr2->flags & VIDEO_TUNER_LOW)) 291
267 *freq *= 1000; 292 if (!(fmr2->flags & V4L2_TUNER_CAP_LOW))
268 if ( *freq < RSF16_MINFREQ || *freq > RSF16_MAXFREQ ) 293 f->frequency *= 1000;
294 if (f->frequency < RSF16_MINFREQ ||
295 f->frequency > RSF16_MAXFREQ )
269 return -EINVAL; 296 return -EINVAL;
270 /* rounding in steps of 200 to match th freq 297 /*rounding in steps of 200 to match th freq
271 * that will be used 298 that will be used */
272 */ 299 fmr2->curfreq = (f->frequency/200)*200;
273 fmr2->curfreq = (*freq/200)*200;
274 300
275 /* set card freq (if not muted) */ 301 /* set card freq (if not muted) */
276 if (fmr2->curvol && !fmr2->mute) 302 if (fmr2->curvol && !fmr2->mute)
@@ -279,40 +305,81 @@ static int fmr2_do_ioctl(struct inode *inode, struct file *file,
279 fmr2_setfreq(fmr2); 305 fmr2_setfreq(fmr2);
280 mutex_unlock(&lock); 306 mutex_unlock(&lock);
281 } 307 }
308
282 return 0; 309 return 0;
283 } 310 }
284 case VIDIOCGAUDIO: 311 case VIDIOC_G_FREQUENCY:
285 { 312 {
286 struct video_audio *v = arg; 313 struct v4l2_frequency *f = arg;
287 memset(v,0,sizeof(*v)); 314
288 /* !!! do not return VIDEO_AUDIO_MUTE */ 315 f->type = V4L2_TUNER_RADIO;
289 v->flags = VIDEO_AUDIO_MUTABLE; 316 f->frequency = fmr2->curfreq;
290 strcpy(v->name, "Radio"); 317 if (!(fmr2->flags & V4L2_TUNER_CAP_LOW))
291 /* get current stereo mode */ 318 f->frequency /= 1000;
292 v->mode = fmr2->stereo ? VIDEO_SOUND_STEREO: VIDEO_SOUND_MONO; 319
293 /* volume supported ? */
294 if (fmr2->card_type == 11)
295 {
296 v->flags |= VIDEO_AUDIO_VOLUME;
297 v->step = 1 << 12;
298 v->volume = fmr2->curvol;
299 }
300 debug_print((KERN_DEBUG "Get flags %d vol %d\n", v->flags, v->volume));
301 return 0; 320 return 0;
302 } 321 }
303 case VIDIOCSAUDIO: 322 case VIDIOC_QUERYCTRL:
304 { 323 {
305 struct video_audio *v = arg; 324 struct v4l2_queryctrl *qc = arg;
306 if(v->audio) 325 int i;
307 return -EINVAL; 326
308 debug_print((KERN_DEBUG "Set flags %d vol %d\n", v->flags, v->volume)); 327 for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) {
309 /* set volume */ 328 if ((fmr2->card_type != 11)
310 if (v->flags & VIDEO_AUDIO_VOLUME) 329 && V4L2_CID_AUDIO_VOLUME)
311 fmr2->curvol = v->volume; /* !!! set with precision */ 330 radio_qctrl[i].step=65535;
312 if (fmr2->card_type != 11) fmr2->curvol = 65535; 331 if (qc->id && qc->id == radio_qctrl[i].id) {
313 fmr2->mute = 0; 332 memcpy(qc, &(radio_qctrl[i]),
314 if (v->flags & VIDEO_AUDIO_MUTE) 333 sizeof(*qc));
315 fmr2->mute = 1; 334 return (0);
335 }
336 }
337 return -EINVAL;
338 }
339 case VIDIOC_G_CTRL:
340 {
341 struct v4l2_control *ctrl= arg;
342
343 switch (ctrl->id) {
344 case V4L2_CID_AUDIO_MUTE:
345 ctrl->value=fmr2->mute;
346 return (0);
347 case V4L2_CID_AUDIO_VOLUME:
348 ctrl->value=fmr2->curvol;
349 return (0);
350 }
351 return -EINVAL;
352 }
353 case VIDIOC_S_CTRL:
354 {
355 struct v4l2_control *ctrl= arg;
356
357 switch (ctrl->id) {
358 case V4L2_CID_AUDIO_MUTE:
359 fmr2->mute=ctrl->value;
360 if (fmr2->card_type != 11) {
361 if (!fmr2->mute) {
362 fmr2->curvol = 65535;
363 } else {
364 fmr2->curvol = 0;
365 }
366 }
367 break;
368 case V4L2_CID_AUDIO_VOLUME:
369 fmr2->curvol = ctrl->value;
370 if (fmr2->card_type != 11) {
371 if (fmr2->curvol) {
372 fmr2->curvol = 65535;
373 fmr2->mute = 0;
374 } else {
375 fmr2->curvol = 0;
376 fmr2->mute = 1;
377 }
378 }
379 break;
380 default:
381 return -EINVAL;
382 }
316#ifdef DEBUG 383#ifdef DEBUG
317 if (fmr2->curvol && !fmr2->mute) 384 if (fmr2->curvol && !fmr2->mute)
318 printk(KERN_DEBUG "unmute\n"); 385 printk(KERN_DEBUG "unmute\n");
@@ -320,27 +387,18 @@ static int fmr2_do_ioctl(struct inode *inode, struct file *file,
320 printk(KERN_DEBUG "mute\n"); 387 printk(KERN_DEBUG "mute\n");
321#endif 388#endif
322 mutex_lock(&lock); 389 mutex_lock(&lock);
323 if (fmr2->curvol && !fmr2->mute) 390 if (fmr2->curvol && !fmr2->mute) {
324 {
325 fmr2_setvolume(fmr2); 391 fmr2_setvolume(fmr2);
326 fmr2_setfreq(fmr2); 392 fmr2_setfreq(fmr2);
327 } 393 } else
328 else fmr2_mute(fmr2->port); 394 fmr2_mute(fmr2->port);
329 mutex_unlock(&lock); 395 mutex_unlock(&lock);
330 return 0; 396 return (0);
331 }
332 case VIDIOCGUNIT:
333 {
334 struct video_unit *v = arg;
335 v->video=VIDEO_NO_UNIT;
336 v->vbi=VIDEO_NO_UNIT;
337 v->radio=dev->minor;
338 v->audio=0; /* How do we find out this??? */
339 v->teletext=VIDEO_NO_UNIT;
340 return 0;
341 } 397 }
342 default: 398 default:
343 return -ENOIOCTLCMD; 399 return v4l_compat_translate_ioctl(inode,file,cmd,arg,
400 fmr2_do_ioctl);
401
344 } 402 }
345} 403}
346 404
@@ -366,7 +424,7 @@ static struct video_device fmr2_radio=
366 .owner = THIS_MODULE, 424 .owner = THIS_MODULE,
367 .name = "SF16FMR2 radio", 425 .name = "SF16FMR2 radio",
368 . type = VID_TYPE_TUNER, 426 . type = VID_TYPE_TUNER,
369 .hardware = VID_HARDWARE_SF16FMR2, 427 .hardware = 0,
370 .fops = &fmr2_fops, 428 .fops = &fmr2_fops,
371}; 429};
372 430
@@ -377,7 +435,7 @@ static int __init fmr2_init(void)
377 fmr2_unit.mute = 0; 435 fmr2_unit.mute = 0;
378 fmr2_unit.curfreq = 0; 436 fmr2_unit.curfreq = 0;
379 fmr2_unit.stereo = 1; 437 fmr2_unit.stereo = 1;
380 fmr2_unit.flags = VIDEO_TUNER_LOW; 438 fmr2_unit.flags = V4L2_TUNER_CAP_LOW;
381 fmr2_unit.card_type = 0; 439 fmr2_unit.card_type = 0;
382 fmr2_radio.priv = &fmr2_unit; 440 fmr2_radio.priv = &fmr2_unit;
383 441
@@ -396,7 +454,6 @@ static int __init fmr2_init(void)
396 } 454 }
397 455
398 printk(KERN_INFO "SF16FMR2 radio card driver at 0x%x.\n", io); 456 printk(KERN_INFO "SF16FMR2 radio card driver at 0x%x.\n", io);
399 debug_print((KERN_DEBUG "Mute %d Low %d\n",VIDEO_AUDIO_MUTE,VIDEO_TUNER_LOW));
400 /* mute card - prevents noisy bootups */ 457 /* mute card - prevents noisy bootups */
401 mutex_lock(&lock); 458 mutex_lock(&lock);
402 fmr2_mute(io); 459 fmr2_mute(io);