aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/radio/radio-mr800.c
diff options
context:
space:
mode:
authorHans Verkuil <hans.verkuil@cisco.com>2012-04-27 11:30:40 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2012-05-07 14:28:45 -0400
commit85578b0fdc107e0d7022d38271fdcf0567afd212 (patch)
tree84fc386a4abd4d86fbbbf8800fa8432db3b96f9d /drivers/media/radio/radio-mr800.c
parentf61861fa567928614c6dd01560b320bfeb24e3e2 (diff)
[media] radio-mr800: cleanup and have it comply to the V4L2 API
Implement the control framework and update to the latest V4L2 framework. The v4l2-compliance tool now runs without errors. Fixed bad g/s_tuner handling with respect to mono/stereo. Support control events. Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/radio/radio-mr800.c')
-rw-r--r--drivers/media/radio/radio-mr800.c340
1 files changed, 112 insertions, 228 deletions
diff --git a/drivers/media/radio/radio-mr800.c b/drivers/media/radio/radio-mr800.c
index a860a72a58ec..0a96edae6786 100644
--- a/drivers/media/radio/radio-mr800.c
+++ b/drivers/media/radio/radio-mr800.c
@@ -62,6 +62,8 @@
62#include <linux/videodev2.h> 62#include <linux/videodev2.h>
63#include <media/v4l2-device.h> 63#include <media/v4l2-device.h>
64#include <media/v4l2-ioctl.h> 64#include <media/v4l2-ioctl.h>
65#include <media/v4l2-ctrls.h>
66#include <media/v4l2-event.h>
65#include <linux/usb.h> 67#include <linux/usb.h>
66#include <linux/mutex.h> 68#include <linux/mutex.h>
67 69
@@ -117,29 +119,20 @@ static int radio_nr = -1;
117module_param(radio_nr, int, 0); 119module_param(radio_nr, int, 0);
118MODULE_PARM_DESC(radio_nr, "Radio Nr"); 120MODULE_PARM_DESC(radio_nr, "Radio Nr");
119 121
120static int usb_amradio_probe(struct usb_interface *intf,
121 const struct usb_device_id *id);
122static void usb_amradio_disconnect(struct usb_interface *intf);
123static int usb_amradio_open(struct file *file);
124static int usb_amradio_close(struct file *file);
125static int usb_amradio_suspend(struct usb_interface *intf,
126 pm_message_t message);
127static int usb_amradio_resume(struct usb_interface *intf);
128
129/* Data for one (physical) device */ 122/* Data for one (physical) device */
130struct amradio_device { 123struct amradio_device {
131 /* reference to USB and video device */ 124 /* reference to USB and video device */
132 struct usb_device *usbdev; 125 struct usb_device *usbdev;
133 struct usb_interface *intf; 126 struct usb_interface *intf;
134 struct video_device videodev; 127 struct video_device vdev;
135 struct v4l2_device v4l2_dev; 128 struct v4l2_device v4l2_dev;
129 struct v4l2_ctrl_handler hdl;
136 130
137 unsigned char *buffer; 131 unsigned char *buffer;
138 struct mutex lock; /* buffer locking */ 132 struct mutex lock; /* buffer locking */
139 int curfreq; 133 int curfreq;
140 int stereo; 134 int stereo;
141 int muted; 135 int muted;
142 int initialized;
143}; 136};
144 137
145static inline struct amradio_device *to_amradio_dev(struct v4l2_device *v4l2_dev) 138static inline struct amradio_device *to_amradio_dev(struct v4l2_device *v4l2_dev)
@@ -147,27 +140,6 @@ static inline struct amradio_device *to_amradio_dev(struct v4l2_device *v4l2_dev
147 return container_of(v4l2_dev, struct amradio_device, v4l2_dev); 140 return container_of(v4l2_dev, struct amradio_device, v4l2_dev);
148} 141}
149 142
150/* USB Device ID List */
151static struct usb_device_id usb_amradio_device_table[] = {
152 {USB_DEVICE_AND_INTERFACE_INFO(USB_AMRADIO_VENDOR, USB_AMRADIO_PRODUCT,
153 USB_CLASS_HID, 0, 0) },
154 { } /* Terminating entry */
155};
156
157MODULE_DEVICE_TABLE(usb, usb_amradio_device_table);
158
159/* USB subsystem interface */
160static struct usb_driver usb_amradio_driver = {
161 .name = MR800_DRIVER_NAME,
162 .probe = usb_amradio_probe,
163 .disconnect = usb_amradio_disconnect,
164 .suspend = usb_amradio_suspend,
165 .resume = usb_amradio_resume,
166 .reset_resume = usb_amradio_resume,
167 .id_table = usb_amradio_device_table,
168 .supports_autosuspend = 1,
169};
170
171/* switch on/off the radio. Send 8 bytes to device */ 143/* switch on/off the radio. Send 8 bytes to device */
172static int amradio_set_mute(struct amradio_device *radio, char argument) 144static int amradio_set_mute(struct amradio_device *radio, char argument)
173{ 145{
@@ -187,21 +159,19 @@ static int amradio_set_mute(struct amradio_device *radio, char argument)
187 (void *) (radio->buffer), BUFFER_LENGTH, &size, USB_TIMEOUT); 159 (void *) (radio->buffer), BUFFER_LENGTH, &size, USB_TIMEOUT);
188 160
189 if (retval < 0 || size != BUFFER_LENGTH) { 161 if (retval < 0 || size != BUFFER_LENGTH) {
190 amradio_dev_warn(&radio->videodev.dev, "set mute failed\n"); 162 amradio_dev_warn(&radio->vdev.dev, "set mute failed\n");
191 return retval; 163 return retval < 0 ? retval : -EIO;
192 } 164 }
193
194 radio->muted = argument; 165 radio->muted = argument;
195 166 return 0;
196 return retval;
197} 167}
198 168
199/* set a frequency, freq is defined by v4l's TUNER_LOW, i.e. 1/16th kHz */ 169/* set a frequency, freq is defined by v4l's TUNER_LOW, i.e. 1/16th kHz */
200static int amradio_setfreq(struct amradio_device *radio, int freq) 170static int amradio_setfreq(struct amradio_device *radio, int freq)
201{ 171{
172 unsigned short freq_send = 0x10 + (freq >> 3) / 25;
202 int retval; 173 int retval;
203 int size; 174 int size;
204 unsigned short freq_send = 0x10 + (freq >> 3) / 25;
205 175
206 radio->buffer[0] = 0x00; 176 radio->buffer[0] = 0x00;
207 radio->buffer[1] = 0x55; 177 radio->buffer[1] = 0x55;
@@ -216,7 +186,7 @@ static int amradio_setfreq(struct amradio_device *radio, int freq)
216 (void *) (radio->buffer), BUFFER_LENGTH, &size, USB_TIMEOUT); 186 (void *) (radio->buffer), BUFFER_LENGTH, &size, USB_TIMEOUT);
217 187
218 if (retval < 0 || size != BUFFER_LENGTH) 188 if (retval < 0 || size != BUFFER_LENGTH)
219 goto out_err; 189 goto out;
220 190
221 /* frequency is calculated from freq_send and placed in first 2 bytes */ 191 /* frequency is calculated from freq_send and placed in first 2 bytes */
222 radio->buffer[0] = (freq_send >> 8) & 0xff; 192 radio->buffer[0] = (freq_send >> 8) & 0xff;
@@ -230,16 +200,14 @@ static int amradio_setfreq(struct amradio_device *radio, int freq)
230 retval = usb_bulk_msg(radio->usbdev, usb_sndintpipe(radio->usbdev, 2), 200 retval = usb_bulk_msg(radio->usbdev, usb_sndintpipe(radio->usbdev, 2),
231 (void *) (radio->buffer), BUFFER_LENGTH, &size, USB_TIMEOUT); 201 (void *) (radio->buffer), BUFFER_LENGTH, &size, USB_TIMEOUT);
232 202
233 if (retval < 0 || size != BUFFER_LENGTH) 203 if (retval >= 0 && size == BUFFER_LENGTH) {
234 goto out_err; 204 radio->curfreq = freq;
235 205 return 0;
236 radio->curfreq = freq; 206 }
237 goto out;
238 207
239out_err:
240 amradio_dev_warn(&radio->videodev.dev, "set frequency failed\n");
241out: 208out:
242 return retval; 209 amradio_dev_warn(&radio->vdev.dev, "set frequency failed\n");
210 return retval < 0 ? retval : -EIO;
243} 211}
244 212
245static int amradio_set_stereo(struct amradio_device *radio, char argument) 213static int amradio_set_stereo(struct amradio_device *radio, char argument)
@@ -260,16 +228,12 @@ static int amradio_set_stereo(struct amradio_device *radio, char argument)
260 (void *) (radio->buffer), BUFFER_LENGTH, &size, USB_TIMEOUT); 228 (void *) (radio->buffer), BUFFER_LENGTH, &size, USB_TIMEOUT);
261 229
262 if (retval < 0 || size != BUFFER_LENGTH) { 230 if (retval < 0 || size != BUFFER_LENGTH) {
263 amradio_dev_warn(&radio->videodev.dev, "set stereo failed\n"); 231 amradio_dev_warn(&radio->vdev.dev, "set stereo failed\n");
264 return retval; 232 return retval < 0 ? retval : -EIO;
265 } 233 }
266 234
267 if (argument == WANT_STEREO) 235 radio->stereo = (argument == WANT_STEREO);
268 radio->stereo = 1; 236 return 0;
269 else
270 radio->stereo = 0;
271
272 return retval;
273} 237}
274 238
275/* Handle unplugging the device. 239/* Handle unplugging the device.
@@ -282,25 +246,24 @@ static void usb_amradio_disconnect(struct usb_interface *intf)
282 struct amradio_device *radio = to_amradio_dev(usb_get_intfdata(intf)); 246 struct amradio_device *radio = to_amradio_dev(usb_get_intfdata(intf));
283 247
284 mutex_lock(&radio->lock); 248 mutex_lock(&radio->lock);
285 /* increase the device node's refcount */ 249 usb_set_intfdata(intf, NULL);
286 get_device(&radio->videodev.dev); 250 video_unregister_device(&radio->vdev);
287 v4l2_device_disconnect(&radio->v4l2_dev); 251 v4l2_device_disconnect(&radio->v4l2_dev);
288 video_unregister_device(&radio->videodev);
289 mutex_unlock(&radio->lock); 252 mutex_unlock(&radio->lock);
290 /* decrease the device node's refcount, allowing it to be released */ 253 v4l2_device_put(&radio->v4l2_dev);
291 put_device(&radio->videodev.dev);
292} 254}
293 255
294/* vidioc_querycap - query device capabilities */ 256/* vidioc_querycap - query device capabilities */
295static int vidioc_querycap(struct file *file, void *priv, 257static int vidioc_querycap(struct file *file, void *priv,
296 struct v4l2_capability *v) 258 struct v4l2_capability *v)
297{ 259{
298 struct amradio_device *radio = file->private_data; 260 struct amradio_device *radio = video_drvdata(file);
299 261
300 strlcpy(v->driver, "radio-mr800", sizeof(v->driver)); 262 strlcpy(v->driver, "radio-mr800", sizeof(v->driver));
301 strlcpy(v->card, "AverMedia MR 800 USB FM Radio", sizeof(v->card)); 263 strlcpy(v->card, "AverMedia MR 800 USB FM Radio", sizeof(v->card));
302 usb_make_path(radio->usbdev, v->bus_info, sizeof(v->bus_info)); 264 usb_make_path(radio->usbdev, v->bus_info, sizeof(v->bus_info));
303 v->capabilities = V4L2_CAP_TUNER; 265 v->device_caps = V4L2_CAP_RADIO | V4L2_CAP_TUNER;
266 v->capabilities = v->device_caps | V4L2_CAP_DEVICE_CAPS;
304 return 0; 267 return 0;
305} 268}
306 269
@@ -308,44 +271,31 @@ static int vidioc_querycap(struct file *file, void *priv,
308static int vidioc_g_tuner(struct file *file, void *priv, 271static int vidioc_g_tuner(struct file *file, void *priv,
309 struct v4l2_tuner *v) 272 struct v4l2_tuner *v)
310{ 273{
311 struct amradio_device *radio = file->private_data; 274 struct amradio_device *radio = video_drvdata(file);
312 int retval;
313 275
314 if (v->index > 0) 276 if (v->index > 0)
315 return -EINVAL; 277 return -EINVAL;
316 278
317/* TODO: Add function which look is signal stereo or not
318 * amradio_getstat(radio);
319 */
320
321/* we call amradio_set_stereo to set radio->stereo
322 * Honestly, amradio_getstat should cover this in future and
323 * amradio_set_stereo shouldn't be here
324 */
325 retval = amradio_set_stereo(radio, WANT_STEREO);
326
327 strcpy(v->name, "FM"); 279 strcpy(v->name, "FM");
328 v->type = V4L2_TUNER_RADIO; 280 v->type = V4L2_TUNER_RADIO;
329 v->rangelow = FREQ_MIN * FREQ_MUL; 281 v->rangelow = FREQ_MIN * FREQ_MUL;
330 v->rangehigh = FREQ_MAX * FREQ_MUL; 282 v->rangehigh = FREQ_MAX * FREQ_MUL;
331 v->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO; 283 v->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO;
332 v->capability = V4L2_TUNER_CAP_LOW; 284 /* We do not know how to get hold of the stereo indicator, so
333 if (radio->stereo) 285 all we can do is give back both mono and stereo, which
334 v->audmode = V4L2_TUNER_MODE_STEREO; 286 effectively means that we don't know. */
335 else 287 v->rxsubchans = V4L2_TUNER_SUB_STEREO | V4L2_TUNER_SUB_MONO;
336 v->audmode = V4L2_TUNER_MODE_MONO; 288 v->signal = 0xffff;
337 v->signal = 0xffff; /* Can't get the signal strength, sad.. */ 289 v->audmode = radio->stereo ?
338 v->afc = 0; /* Don't know what is this */ 290 V4L2_TUNER_MODE_STEREO : V4L2_TUNER_MODE_MONO;
339 291 return 0;
340 return retval;
341} 292}
342 293
343/* vidioc_s_tuner - set tuner attributes */ 294/* vidioc_s_tuner - set tuner attributes */
344static int vidioc_s_tuner(struct file *file, void *priv, 295static int vidioc_s_tuner(struct file *file, void *priv,
345 struct v4l2_tuner *v) 296 struct v4l2_tuner *v)
346{ 297{
347 struct amradio_device *radio = file->private_data; 298 struct amradio_device *radio = video_drvdata(file);
348 int retval = -EINVAL;
349 299
350 if (v->index > 0) 300 if (v->index > 0)
351 return -EINVAL; 301 return -EINVAL;
@@ -353,34 +303,31 @@ static int vidioc_s_tuner(struct file *file, void *priv,
353 /* mono/stereo selector */ 303 /* mono/stereo selector */
354 switch (v->audmode) { 304 switch (v->audmode) {
355 case V4L2_TUNER_MODE_MONO: 305 case V4L2_TUNER_MODE_MONO:
356 retval = amradio_set_stereo(radio, WANT_MONO); 306 return amradio_set_stereo(radio, WANT_MONO);
357 break; 307 default:
358 case V4L2_TUNER_MODE_STEREO: 308 return amradio_set_stereo(radio, WANT_STEREO);
359 retval = amradio_set_stereo(radio, WANT_STEREO);
360 break;
361 } 309 }
362
363 return retval;
364} 310}
365 311
366/* vidioc_s_frequency - set tuner radio frequency */ 312/* vidioc_s_frequency - set tuner radio frequency */
367static int vidioc_s_frequency(struct file *file, void *priv, 313static int vidioc_s_frequency(struct file *file, void *priv,
368 struct v4l2_frequency *f) 314 struct v4l2_frequency *f)
369{ 315{
370 struct amradio_device *radio = file->private_data; 316 struct amradio_device *radio = video_drvdata(file);
371 317
372 if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO) 318 if (f->tuner != 0)
373 return -EINVAL; 319 return -EINVAL;
374 return amradio_setfreq(radio, f->frequency); 320 return amradio_setfreq(radio, clamp_t(unsigned, f->frequency,
321 FREQ_MIN * FREQ_MUL, FREQ_MAX * FREQ_MUL));
375} 322}
376 323
377/* vidioc_g_frequency - get tuner radio frequency */ 324/* vidioc_g_frequency - get tuner radio frequency */
378static int vidioc_g_frequency(struct file *file, void *priv, 325static int vidioc_g_frequency(struct file *file, void *priv,
379 struct v4l2_frequency *f) 326 struct v4l2_frequency *f)
380{ 327{
381 struct amradio_device *radio = file->private_data; 328 struct amradio_device *radio = video_drvdata(file);
382 329
383 if (f->tuner != 0) 330 if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO)
384 return -EINVAL; 331 return -EINVAL;
385 f->type = V4L2_TUNER_RADIO; 332 f->type = V4L2_TUNER_RADIO;
386 f->frequency = radio->curfreq; 333 f->frequency = radio->curfreq;
@@ -388,89 +335,20 @@ static int vidioc_g_frequency(struct file *file, void *priv,
388 return 0; 335 return 0;
389} 336}
390 337
391/* vidioc_queryctrl - enumerate control items */ 338static int usb_amradio_s_ctrl(struct v4l2_ctrl *ctrl)
392static int vidioc_queryctrl(struct file *file, void *priv,
393 struct v4l2_queryctrl *qc)
394{ 339{
395 switch (qc->id) { 340 struct amradio_device *radio =
396 case V4L2_CID_AUDIO_MUTE: 341 container_of(ctrl->handler, struct amradio_device, hdl);
397 return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1);
398 }
399
400 return -EINVAL;
401}
402
403/* vidioc_g_ctrl - get the value of a control */
404static int vidioc_g_ctrl(struct file *file, void *priv,
405 struct v4l2_control *ctrl)
406{
407 struct amradio_device *radio = file->private_data;
408 342
409 switch (ctrl->id) { 343 switch (ctrl->id) {
410 case V4L2_CID_AUDIO_MUTE: 344 case V4L2_CID_AUDIO_MUTE:
411 ctrl->value = radio->muted; 345 return amradio_set_mute(radio,
412 return 0; 346 ctrl->val ? AMRADIO_STOP : AMRADIO_START);
413 } 347 }
414 348
415 return -EINVAL; 349 return -EINVAL;
416} 350}
417 351
418/* vidioc_s_ctrl - set the value of a control */
419static int vidioc_s_ctrl(struct file *file, void *priv,
420 struct v4l2_control *ctrl)
421{
422 struct amradio_device *radio = file->private_data;
423 int retval = -EINVAL;
424
425 switch (ctrl->id) {
426 case V4L2_CID_AUDIO_MUTE:
427 if (ctrl->value)
428 retval = amradio_set_mute(radio, AMRADIO_STOP);
429 else
430 retval = amradio_set_mute(radio, AMRADIO_START);
431
432 break;
433 }
434
435 return retval;
436}
437
438/* vidioc_g_audio - get audio attributes */
439static int vidioc_g_audio(struct file *file, void *priv,
440 struct v4l2_audio *a)
441{
442 if (a->index > 1)
443 return -EINVAL;
444
445 strcpy(a->name, "Radio");
446 a->capability = V4L2_AUDCAP_STEREO;
447 return 0;
448}
449
450/* vidioc_s_audio - set audio attributes */
451static int vidioc_s_audio(struct file *file, void *priv,
452 struct v4l2_audio *a)
453{
454 if (a->index != 0)
455 return -EINVAL;
456 return 0;
457}
458
459/* vidioc_g_input - get input */
460static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i)
461{
462 *i = 0;
463 return 0;
464}
465
466/* vidioc_s_input - set input */
467static int vidioc_s_input(struct file *filp, void *priv, unsigned int i)
468{
469 if (i != 0)
470 return -EINVAL;
471 return 0;
472}
473
474static int usb_amradio_init(struct amradio_device *radio) 352static int usb_amradio_init(struct amradio_device *radio)
475{ 353{
476 int retval; 354 int retval;
@@ -483,51 +361,21 @@ static int usb_amradio_init(struct amradio_device *radio)
483 if (retval) 361 if (retval)
484 goto out_err; 362 goto out_err;
485 363
486 radio->initialized = 1;
487 goto out; 364 goto out;
488 365
489out_err: 366out_err:
490 amradio_dev_err(&radio->videodev.dev, "initialization failed\n"); 367 amradio_dev_err(&radio->vdev.dev, "initialization failed\n");
491out: 368out:
492 return retval; 369 return retval;
493} 370}
494 371
495/* open device - amradio_start() and amradio_setfreq() */
496static int usb_amradio_open(struct file *file)
497{
498 struct amradio_device *radio = video_drvdata(file);
499 int retval;
500
501 file->private_data = radio;
502 retval = usb_autopm_get_interface(radio->intf);
503 if (retval)
504 return retval;
505
506 if (unlikely(!radio->initialized)) {
507 retval = usb_amradio_init(radio);
508 if (retval)
509 usb_autopm_put_interface(radio->intf);
510 }
511 return retval;
512}
513
514/*close device */
515static int usb_amradio_close(struct file *file)
516{
517 struct amradio_device *radio = file->private_data;
518
519 if (video_is_registered(&radio->videodev))
520 usb_autopm_put_interface(radio->intf);
521 return 0;
522}
523
524/* Suspend device - stop device. Need to be checked and fixed */ 372/* Suspend device - stop device. Need to be checked and fixed */
525static int usb_amradio_suspend(struct usb_interface *intf, pm_message_t message) 373static int usb_amradio_suspend(struct usb_interface *intf, pm_message_t message)
526{ 374{
527 struct amradio_device *radio = to_amradio_dev(usb_get_intfdata(intf)); 375 struct amradio_device *radio = to_amradio_dev(usb_get_intfdata(intf));
528 376
529 mutex_lock(&radio->lock); 377 mutex_lock(&radio->lock);
530 if (!radio->muted && radio->initialized) { 378 if (!radio->muted) {
531 amradio_set_mute(radio, AMRADIO_STOP); 379 amradio_set_mute(radio, AMRADIO_STOP);
532 radio->muted = 0; 380 radio->muted = 0;
533 } 381 }
@@ -543,9 +391,6 @@ static int usb_amradio_resume(struct usb_interface *intf)
543 struct amradio_device *radio = to_amradio_dev(usb_get_intfdata(intf)); 391 struct amradio_device *radio = to_amradio_dev(usb_get_intfdata(intf));
544 392
545 mutex_lock(&radio->lock); 393 mutex_lock(&radio->lock);
546 if (unlikely(!radio->initialized))
547 goto unlock;
548
549 if (radio->stereo) 394 if (radio->stereo)
550 amradio_set_stereo(radio, WANT_STEREO); 395 amradio_set_stereo(radio, WANT_STEREO);
551 else 396 else
@@ -556,18 +401,22 @@ static int usb_amradio_resume(struct usb_interface *intf)
556 if (!radio->muted) 401 if (!radio->muted)
557 amradio_set_mute(radio, AMRADIO_START); 402 amradio_set_mute(radio, AMRADIO_START);
558 403
559unlock:
560 mutex_unlock(&radio->lock); 404 mutex_unlock(&radio->lock);
561 405
562 dev_info(&intf->dev, "coming out of suspend..\n"); 406 dev_info(&intf->dev, "coming out of suspend..\n");
563 return 0; 407 return 0;
564} 408}
565 409
410static const struct v4l2_ctrl_ops usb_amradio_ctrl_ops = {
411 .s_ctrl = usb_amradio_s_ctrl,
412};
413
566/* File system interface */ 414/* File system interface */
567static const struct v4l2_file_operations usb_amradio_fops = { 415static const struct v4l2_file_operations usb_amradio_fops = {
568 .owner = THIS_MODULE, 416 .owner = THIS_MODULE,
569 .open = usb_amradio_open, 417 .open = v4l2_fh_open,
570 .release = usb_amradio_close, 418 .release = v4l2_fh_release,
419 .poll = v4l2_ctrl_poll,
571 .unlocked_ioctl = video_ioctl2, 420 .unlocked_ioctl = video_ioctl2,
572}; 421};
573 422
@@ -577,20 +426,18 @@ static const struct v4l2_ioctl_ops usb_amradio_ioctl_ops = {
577 .vidioc_s_tuner = vidioc_s_tuner, 426 .vidioc_s_tuner = vidioc_s_tuner,
578 .vidioc_g_frequency = vidioc_g_frequency, 427 .vidioc_g_frequency = vidioc_g_frequency,
579 .vidioc_s_frequency = vidioc_s_frequency, 428 .vidioc_s_frequency = vidioc_s_frequency,
580 .vidioc_queryctrl = vidioc_queryctrl, 429 .vidioc_log_status = v4l2_ctrl_log_status,
581 .vidioc_g_ctrl = vidioc_g_ctrl, 430 .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
582 .vidioc_s_ctrl = vidioc_s_ctrl, 431 .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
583 .vidioc_g_audio = vidioc_g_audio,
584 .vidioc_s_audio = vidioc_s_audio,
585 .vidioc_g_input = vidioc_g_input,
586 .vidioc_s_input = vidioc_s_input,
587}; 432};
588 433
589static void usb_amradio_video_device_release(struct video_device *videodev) 434static void usb_amradio_release(struct v4l2_device *v4l2_dev)
590{ 435{
591 struct amradio_device *radio = video_get_drvdata(videodev); 436 struct amradio_device *radio = to_amradio_dev(v4l2_dev);
592 437
593 /* free rest memory */ 438 /* free rest memory */
439 v4l2_ctrl_handler_free(&radio->hdl);
440 v4l2_device_unregister(&radio->v4l2_dev);
594 kfree(radio->buffer); 441 kfree(radio->buffer);
595 kfree(radio); 442 kfree(radio);
596} 443}
@@ -624,23 +471,38 @@ static int usb_amradio_probe(struct usb_interface *intf,
624 goto err_v4l2; 471 goto err_v4l2;
625 } 472 }
626 473
474 v4l2_ctrl_handler_init(&radio->hdl, 1);
475 v4l2_ctrl_new_std(&radio->hdl, &usb_amradio_ctrl_ops,
476 V4L2_CID_AUDIO_MUTE, 0, 1, 1, 1);
477 if (radio->hdl.error) {
478 retval = radio->hdl.error;
479 dev_err(&intf->dev, "couldn't register control\n");
480 goto err_ctrl;
481 }
627 mutex_init(&radio->lock); 482 mutex_init(&radio->lock);
628 483
629 strlcpy(radio->videodev.name, radio->v4l2_dev.name, 484 radio->v4l2_dev.ctrl_handler = &radio->hdl;
630 sizeof(radio->videodev.name)); 485 radio->v4l2_dev.release = usb_amradio_release;
631 radio->videodev.v4l2_dev = &radio->v4l2_dev; 486 strlcpy(radio->vdev.name, radio->v4l2_dev.name,
632 radio->videodev.fops = &usb_amradio_fops; 487 sizeof(radio->vdev.name));
633 radio->videodev.ioctl_ops = &usb_amradio_ioctl_ops; 488 radio->vdev.v4l2_dev = &radio->v4l2_dev;
634 radio->videodev.release = usb_amradio_video_device_release; 489 radio->vdev.fops = &usb_amradio_fops;
635 radio->videodev.lock = &radio->lock; 490 radio->vdev.ioctl_ops = &usb_amradio_ioctl_ops;
491 radio->vdev.release = video_device_release_empty;
492 radio->vdev.lock = &radio->lock;
493 set_bit(V4L2_FL_USE_FH_PRIO, &radio->vdev.flags);
636 494
637 radio->usbdev = interface_to_usbdev(intf); 495 radio->usbdev = interface_to_usbdev(intf);
638 radio->intf = intf; 496 radio->intf = intf;
497 usb_set_intfdata(intf, &radio->v4l2_dev);
639 radio->curfreq = 95.16 * FREQ_MUL; 498 radio->curfreq = 95.16 * FREQ_MUL;
640 499
641 video_set_drvdata(&radio->videodev, radio); 500 video_set_drvdata(&radio->vdev, radio);
501 retval = usb_amradio_init(radio);
502 if (retval)
503 goto err_vdev;
642 504
643 retval = video_register_device(&radio->videodev, VFL_TYPE_RADIO, 505 retval = video_register_device(&radio->vdev, VFL_TYPE_RADIO,
644 radio_nr); 506 radio_nr);
645 if (retval < 0) { 507 if (retval < 0) {
646 dev_err(&intf->dev, "could not register video device\n"); 508 dev_err(&intf->dev, "could not register video device\n");
@@ -650,6 +512,8 @@ static int usb_amradio_probe(struct usb_interface *intf,
650 return 0; 512 return 0;
651 513
652err_vdev: 514err_vdev:
515 v4l2_ctrl_handler_free(&radio->hdl);
516err_ctrl:
653 v4l2_device_unregister(&radio->v4l2_dev); 517 v4l2_device_unregister(&radio->v4l2_dev);
654err_v4l2: 518err_v4l2:
655 kfree(radio->buffer); 519 kfree(radio->buffer);
@@ -659,4 +523,24 @@ err:
659 return retval; 523 return retval;
660} 524}
661 525
526/* USB Device ID List */
527static struct usb_device_id usb_amradio_device_table[] = {
528 { USB_DEVICE_AND_INTERFACE_INFO(USB_AMRADIO_VENDOR, USB_AMRADIO_PRODUCT,
529 USB_CLASS_HID, 0, 0) },
530 { } /* Terminating entry */
531};
532
533MODULE_DEVICE_TABLE(usb, usb_amradio_device_table);
534
535/* USB subsystem interface */
536static struct usb_driver usb_amradio_driver = {
537 .name = MR800_DRIVER_NAME,
538 .probe = usb_amradio_probe,
539 .disconnect = usb_amradio_disconnect,
540 .suspend = usb_amradio_suspend,
541 .resume = usb_amradio_resume,
542 .reset_resume = usb_amradio_resume,
543 .id_table = usb_amradio_device_table,
544};
545
662module_usb_driver(usb_amradio_driver); 546module_usb_driver(usb_amradio_driver);