diff options
Diffstat (limited to 'drivers/media/radio')
-rw-r--r-- | drivers/media/radio/radio-sf16fmr2.c | 350 |
1 files changed, 190 insertions, 160 deletions
diff --git a/drivers/media/radio/radio-sf16fmr2.c b/drivers/media/radio/radio-sf16fmr2.c index b96fafe1f9da..e6c125def5cb 100644 --- a/drivers/media/radio/radio-sf16fmr2.c +++ b/drivers/media/radio/radio-sf16fmr2.c | |||
@@ -226,186 +226,204 @@ static int fmr2_setvolume(struct fmr2_device *dev) | |||
226 | return 0; | 226 | return 0; |
227 | } | 227 | } |
228 | 228 | ||
229 | static int fmr2_do_ioctl(struct inode *inode, struct file *file, | 229 | static int vidioc_querycap(struct file *file, void *priv, |
230 | unsigned int cmd, void *arg) | 230 | struct v4l2_capability *v) |
231 | { | 231 | { |
232 | strlcpy(v->driver, "radio-sf16fmr2", sizeof(v->driver)); | ||
233 | strlcpy(v->card, "SF16-FMR2 radio", sizeof(v->card)); | ||
234 | sprintf(v->bus_info, "ISA"); | ||
235 | v->version = RADIO_VERSION; | ||
236 | v->capabilities = V4L2_CAP_TUNER; | ||
237 | return 0; | ||
238 | } | ||
239 | |||
240 | static int vidioc_g_tuner(struct file *file, void *priv, | ||
241 | struct v4l2_tuner *v) | ||
242 | { | ||
243 | int mult; | ||
232 | struct video_device *dev = video_devdata(file); | 244 | struct video_device *dev = video_devdata(file); |
233 | struct fmr2_device *fmr2 = dev->priv; | 245 | struct fmr2_device *fmr2 = dev->priv; |
234 | debug_print((KERN_DEBUG "freq %ld flags %d vol %d mute %d " | ||
235 | "stereo %d type %d\n", | ||
236 | fmr2->curfreq, fmr2->flags, fmr2->curvol, fmr2->mute, | ||
237 | fmr2->stereo, fmr2->card_type)); | ||
238 | 246 | ||
239 | switch(cmd) | 247 | if (v->index > 0) |
240 | { | 248 | return -EINVAL; |
241 | case VIDIOC_QUERYCAP: | ||
242 | { | ||
243 | struct v4l2_capability *v = arg; | ||
244 | memset(v,0,sizeof(*v)); | ||
245 | strlcpy(v->driver, "radio-sf16fmr2", sizeof (v->driver)); | ||
246 | strlcpy(v->card, "SF16-FMR2 radio", sizeof (v->card)); | ||
247 | sprintf(v->bus_info,"ISA"); | ||
248 | v->version = RADIO_VERSION; | ||
249 | v->capabilities = V4L2_CAP_TUNER; | ||
250 | 249 | ||
251 | return 0; | 250 | strcpy(v->name, "FM"); |
252 | } | 251 | v->type = V4L2_TUNER_RADIO; |
253 | case VIDIOC_G_TUNER: | ||
254 | { | ||
255 | struct v4l2_tuner *v = arg; | ||
256 | int mult; | ||
257 | |||
258 | if (v->index > 0) | ||
259 | return -EINVAL; | ||
260 | |||
261 | memset(v,0,sizeof(*v)); | ||
262 | strcpy(v->name, "FM"); | ||
263 | v->type = V4L2_TUNER_RADIO; | ||
264 | |||
265 | mult = (fmr2->flags & V4L2_TUNER_CAP_LOW) ? 1 : 1000; | ||
266 | v->rangelow = RSF16_MINFREQ/mult; | ||
267 | v->rangehigh = RSF16_MAXFREQ/mult; | ||
268 | v->rxsubchans =V4L2_TUNER_SUB_MONO | V4L2_TUNER_MODE_STEREO; | ||
269 | v->capability=fmr2->flags&V4L2_TUNER_CAP_LOW; | ||
270 | |||
271 | v->audmode = fmr2->stereo ? V4L2_TUNER_MODE_STEREO: | ||
272 | V4L2_TUNER_MODE_MONO; | ||
273 | mutex_lock(&lock); | ||
274 | v->signal = fmr2_getsigstr(fmr2); | ||
275 | mutex_unlock(&lock); | ||
276 | 252 | ||
277 | return 0; | 253 | mult = (fmr2->flags & V4L2_TUNER_CAP_LOW) ? 1 : 1000; |
278 | } | 254 | v->rangelow = RSF16_MINFREQ/mult; |
279 | case VIDIOC_S_TUNER: | 255 | v->rangehigh = RSF16_MAXFREQ/mult; |
280 | { | 256 | v->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_MODE_STEREO; |
281 | struct v4l2_tuner *v = arg; | 257 | v->capability = fmr2->flags&V4L2_TUNER_CAP_LOW; |
258 | v->audmode = fmr2->stereo ? V4L2_TUNER_MODE_STEREO: | ||
259 | V4L2_TUNER_MODE_MONO; | ||
260 | mutex_lock(&lock); | ||
261 | v->signal = fmr2_getsigstr(fmr2); | ||
262 | mutex_unlock(&lock); | ||
263 | return 0; | ||
264 | } | ||
282 | 265 | ||
283 | if (v->index > 0) | 266 | static int vidioc_s_tuner(struct file *file, void *priv, |
284 | return -EINVAL; | 267 | struct v4l2_tuner *v) |
268 | { | ||
269 | if (v->index > 0) | ||
270 | return -EINVAL; | ||
271 | return 0; | ||
272 | } | ||
285 | 273 | ||
286 | return 0; | 274 | static int vidioc_s_frequency(struct file *file, void *priv, |
287 | } | 275 | struct v4l2_frequency *f) |
288 | case VIDIOC_S_FREQUENCY: | 276 | { |
289 | { | 277 | struct video_device *dev = video_devdata(file); |
290 | struct v4l2_frequency *f = arg; | 278 | struct fmr2_device *fmr2 = dev->priv; |
291 | |||
292 | if (!(fmr2->flags & V4L2_TUNER_CAP_LOW)) | ||
293 | f->frequency *= 1000; | ||
294 | if (f->frequency < RSF16_MINFREQ || | ||
295 | f->frequency > RSF16_MAXFREQ ) | ||
296 | return -EINVAL; | ||
297 | /*rounding in steps of 200 to match th freq | ||
298 | that will be used */ | ||
299 | fmr2->curfreq = (f->frequency/200)*200; | ||
300 | |||
301 | /* set card freq (if not muted) */ | ||
302 | if (fmr2->curvol && !fmr2->mute) | ||
303 | { | ||
304 | mutex_lock(&lock); | ||
305 | fmr2_setfreq(fmr2); | ||
306 | mutex_unlock(&lock); | ||
307 | } | ||
308 | 279 | ||
309 | return 0; | 280 | if (!(fmr2->flags & V4L2_TUNER_CAP_LOW)) |
310 | } | 281 | f->frequency *= 1000; |
311 | case VIDIOC_G_FREQUENCY: | 282 | if (f->frequency < RSF16_MINFREQ || |
312 | { | 283 | f->frequency > RSF16_MAXFREQ ) |
313 | struct v4l2_frequency *f = arg; | 284 | return -EINVAL; |
285 | /*rounding in steps of 200 to match th freq | ||
286 | that will be used */ | ||
287 | fmr2->curfreq = (f->frequency/200)*200; | ||
288 | |||
289 | /* set card freq (if not muted) */ | ||
290 | if (fmr2->curvol && !fmr2->mute) { | ||
291 | mutex_lock(&lock); | ||
292 | fmr2_setfreq(fmr2); | ||
293 | mutex_unlock(&lock); | ||
294 | } | ||
295 | return 0; | ||
296 | } | ||
297 | |||
298 | static int vidioc_g_frequency(struct file *file, void *priv, | ||
299 | struct v4l2_frequency *f) | ||
300 | { | ||
301 | struct video_device *dev = video_devdata(file); | ||
302 | struct fmr2_device *fmr2 = dev->priv; | ||
314 | 303 | ||
315 | f->type = V4L2_TUNER_RADIO; | 304 | f->type = V4L2_TUNER_RADIO; |
316 | f->frequency = fmr2->curfreq; | 305 | f->frequency = fmr2->curfreq; |
317 | if (!(fmr2->flags & V4L2_TUNER_CAP_LOW)) | 306 | if (!(fmr2->flags & V4L2_TUNER_CAP_LOW)) |
318 | f->frequency /= 1000; | 307 | f->frequency /= 1000; |
308 | return 0; | ||
309 | } | ||
319 | 310 | ||
311 | static int vidioc_queryctrl(struct file *file, void *priv, | ||
312 | struct v4l2_queryctrl *qc) | ||
313 | { | ||
314 | int i; | ||
315 | struct video_device *dev = video_devdata(file); | ||
316 | struct fmr2_device *fmr2 = dev->priv; | ||
317 | |||
318 | for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) { | ||
319 | if ((fmr2->card_type != 11) | ||
320 | && V4L2_CID_AUDIO_VOLUME) | ||
321 | radio_qctrl[i].step = 65535; | ||
322 | if (qc->id && qc->id == radio_qctrl[i].id) { | ||
323 | memcpy(qc, &(radio_qctrl[i]), | ||
324 | sizeof(*qc)); | ||
320 | return 0; | 325 | return 0; |
321 | } | 326 | } |
322 | case VIDIOC_QUERYCTRL: | 327 | } |
323 | { | 328 | return -EINVAL; |
324 | struct v4l2_queryctrl *qc = arg; | 329 | } |
325 | int i; | 330 | |
326 | 331 | static int vidioc_g_ctrl(struct file *file, void *priv, | |
327 | for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) { | 332 | struct v4l2_control *ctrl) |
328 | if ((fmr2->card_type != 11) | 333 | { |
329 | && V4L2_CID_AUDIO_VOLUME) | 334 | struct video_device *dev = video_devdata(file); |
330 | radio_qctrl[i].step=65535; | 335 | struct fmr2_device *fmr2 = dev->priv; |
331 | if (qc->id && qc->id == radio_qctrl[i].id) { | 336 | |
332 | memcpy(qc, &(radio_qctrl[i]), | 337 | switch (ctrl->id) { |
333 | sizeof(*qc)); | 338 | case V4L2_CID_AUDIO_MUTE: |
334 | return (0); | 339 | ctrl->value = fmr2->mute; |
335 | } | 340 | return 0; |
336 | } | 341 | case V4L2_CID_AUDIO_VOLUME: |
337 | return -EINVAL; | 342 | ctrl->value = fmr2->curvol; |
343 | return 0; | ||
344 | } | ||
345 | return -EINVAL; | ||
346 | } | ||
347 | |||
348 | static int vidioc_s_ctrl(struct file *file, void *priv, | ||
349 | struct v4l2_control *ctrl) | ||
350 | { | ||
351 | struct video_device *dev = video_devdata(file); | ||
352 | struct fmr2_device *fmr2 = dev->priv; | ||
353 | |||
354 | switch (ctrl->id) { | ||
355 | case V4L2_CID_AUDIO_MUTE: | ||
356 | fmr2->mute = ctrl->value; | ||
357 | if (fmr2->card_type != 11) { | ||
358 | if (!fmr2->mute) | ||
359 | fmr2->curvol = 65535; | ||
360 | else | ||
361 | fmr2->curvol = 0; | ||
338 | } | 362 | } |
339 | case VIDIOC_G_CTRL: | 363 | break; |
340 | { | 364 | case V4L2_CID_AUDIO_VOLUME: |
341 | struct v4l2_control *ctrl= arg; | 365 | fmr2->curvol = ctrl->value; |
342 | 366 | if (fmr2->card_type != 11) { | |
343 | switch (ctrl->id) { | 367 | if (fmr2->curvol) { |
344 | case V4L2_CID_AUDIO_MUTE: | 368 | fmr2->curvol = 65535; |
345 | ctrl->value=fmr2->mute; | 369 | fmr2->mute = 0; |
346 | return (0); | 370 | } else { |
347 | case V4L2_CID_AUDIO_VOLUME: | 371 | fmr2->curvol = 0; |
348 | ctrl->value=fmr2->curvol; | 372 | fmr2->mute = 1; |
349 | return (0); | ||
350 | } | 373 | } |
351 | return -EINVAL; | ||
352 | } | 374 | } |
353 | case VIDIOC_S_CTRL: | 375 | break; |
354 | { | 376 | default: |
355 | struct v4l2_control *ctrl= arg; | 377 | return -EINVAL; |
356 | 378 | } | |
357 | switch (ctrl->id) { | 379 | |
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 | } | ||
383 | #ifdef DEBUG | 380 | #ifdef DEBUG |
384 | if (fmr2->curvol && !fmr2->mute) | 381 | if (fmr2->curvol && !fmr2->mute) |
385 | printk(KERN_DEBUG "unmute\n"); | 382 | printk(KERN_DEBUG "unmute\n"); |
386 | else | 383 | else |
387 | printk(KERN_DEBUG "mute\n"); | 384 | printk(KERN_DEBUG "mute\n"); |
388 | #endif | 385 | #endif |
389 | mutex_lock(&lock); | ||
390 | if (fmr2->curvol && !fmr2->mute) { | ||
391 | fmr2_setvolume(fmr2); | ||
392 | fmr2_setfreq(fmr2); | ||
393 | } else | ||
394 | fmr2_mute(fmr2->port); | ||
395 | mutex_unlock(&lock); | ||
396 | return (0); | ||
397 | } | ||
398 | default: | ||
399 | return v4l_compat_translate_ioctl(inode,file,cmd,arg, | ||
400 | fmr2_do_ioctl); | ||
401 | 386 | ||
402 | } | 387 | mutex_lock(&lock); |
388 | if (fmr2->curvol && !fmr2->mute) { | ||
389 | fmr2_setvolume(fmr2); | ||
390 | fmr2_setfreq(fmr2); | ||
391 | } else | ||
392 | fmr2_mute(fmr2->port); | ||
393 | mutex_unlock(&lock); | ||
394 | return 0; | ||
403 | } | 395 | } |
404 | 396 | ||
405 | static int fmr2_ioctl(struct inode *inode, struct file *file, | 397 | static int vidioc_g_audio(struct file *file, void *priv, |
406 | unsigned int cmd, unsigned long arg) | 398 | struct v4l2_audio *a) |
407 | { | 399 | { |
408 | return video_usercopy(inode, file, cmd, arg, fmr2_do_ioctl); | 400 | if (a->index > 1) |
401 | return -EINVAL; | ||
402 | |||
403 | strcpy(a->name, "Radio"); | ||
404 | a->capability = V4L2_AUDCAP_STEREO; | ||
405 | return 0; | ||
406 | } | ||
407 | |||
408 | static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) | ||
409 | { | ||
410 | *i = 0; | ||
411 | return 0; | ||
412 | } | ||
413 | |||
414 | static int vidioc_s_input(struct file *filp, void *priv, unsigned int i) | ||
415 | { | ||
416 | if (i != 0) | ||
417 | return -EINVAL; | ||
418 | return 0; | ||
419 | } | ||
420 | |||
421 | static int vidioc_s_audio(struct file *file, void *priv, | ||
422 | struct v4l2_audio *a) | ||
423 | { | ||
424 | if (a->index != 0) | ||
425 | return -EINVAL; | ||
426 | return 0; | ||
409 | } | 427 | } |
410 | 428 | ||
411 | static struct fmr2_device fmr2_unit; | 429 | static struct fmr2_device fmr2_unit; |
@@ -414,7 +432,7 @@ static const struct file_operations fmr2_fops = { | |||
414 | .owner = THIS_MODULE, | 432 | .owner = THIS_MODULE, |
415 | .open = video_exclusive_open, | 433 | .open = video_exclusive_open, |
416 | .release = video_exclusive_release, | 434 | .release = video_exclusive_release, |
417 | .ioctl = fmr2_ioctl, | 435 | .ioctl = video_ioctl2, |
418 | .compat_ioctl = v4l_compat_ioctl32, | 436 | .compat_ioctl = v4l_compat_ioctl32, |
419 | .llseek = no_llseek, | 437 | .llseek = no_llseek, |
420 | }; | 438 | }; |
@@ -426,6 +444,18 @@ static struct video_device fmr2_radio= | |||
426 | . type = VID_TYPE_TUNER, | 444 | . type = VID_TYPE_TUNER, |
427 | .hardware = 0, | 445 | .hardware = 0, |
428 | .fops = &fmr2_fops, | 446 | .fops = &fmr2_fops, |
447 | .vidioc_querycap = vidioc_querycap, | ||
448 | .vidioc_g_tuner = vidioc_g_tuner, | ||
449 | .vidioc_s_tuner = vidioc_s_tuner, | ||
450 | .vidioc_g_audio = vidioc_g_audio, | ||
451 | .vidioc_s_audio = vidioc_s_audio, | ||
452 | .vidioc_g_input = vidioc_g_input, | ||
453 | .vidioc_s_input = vidioc_s_input, | ||
454 | .vidioc_g_frequency = vidioc_g_frequency, | ||
455 | .vidioc_s_frequency = vidioc_s_frequency, | ||
456 | .vidioc_queryctrl = vidioc_queryctrl, | ||
457 | .vidioc_g_ctrl = vidioc_g_ctrl, | ||
458 | .vidioc_s_ctrl = vidioc_s_ctrl, | ||
429 | }; | 459 | }; |
430 | 460 | ||
431 | static int __init fmr2_init(void) | 461 | static int __init fmr2_init(void) |