aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/radio/radio-mr800.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2009-12-09 22:50:49 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2009-12-09 22:50:49 -0500
commit3e7468313758913c5e4d372f35b271b96bad1298 (patch)
treeeb612d252a9e2349a1173451cd779beebd18a33e /drivers/media/radio/radio-mr800.c
parent6825fbc4cb219f2c98bb7d157915d797cf5cb823 (diff)
parente97f4677961f68e29bd906022ebf60a6df7f530a (diff)
Merge branch 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6
* 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6: (345 commits) V4L/DVB (13542): ir-keytable: Allow dynamic table change V4L/DVB (13541): atbm8830: replace 64-bit division and floating point usage V4L/DVB (13540): ir-common: Cleanup get key evdev code V4L/DVB (13539): ir-common: add __func__ for debug messages V4L/DVB (13538): ir-common: Use a dynamic keycode table V4L/DVB (13537): ir: Prepare the code for dynamic keycode table allocation V4L/DVB (13536): em28xx: Use the full RC5 code on HVR-950 Remote Controller V4L/DVB (13535): ir-common: Add a hauppauge new table with the complete RC5 code V4L/DVB (13534): ir-common: Remove some unused fields/structs V4L/DVB (13533): ir: use dynamic tables, instead of static ones V4L/DVB (13532): ir-common: Add infrastructure to use a dynamic keycode table V4L/DVB (13531): ir-common: rename the debug routine to allow exporting it V4L/DVB (13458): go7007: subdev conversion V4L/DVB (13457): s2250: subdev conversion V4L/DVB (13456): s2250: Change module structure V4L/DVB (13528): em28xx: add support for em2800 VC211A card em28xx: don't reduce scale to half size for em2800 em28xx: don't load audio modules when AC97 is mis-detected em28xx: em2800 chips support max width of 640 V4L/DVB (13523): dvb-bt8xx: fix compile warning ... Fix up trivial conflicts due to spelling fixes from the trivial tree in Documentation/video4linux/gspca.txt drivers/media/video/cx18/cx18-mailbox.h
Diffstat (limited to 'drivers/media/radio/radio-mr800.c')
-rw-r--r--drivers/media/radio/radio-mr800.c358
1 files changed, 167 insertions, 191 deletions
diff --git a/drivers/media/radio/radio-mr800.c b/drivers/media/radio/radio-mr800.c
index 5f79acb56e48..949f60513d9e 100644
--- a/drivers/media/radio/radio-mr800.c
+++ b/drivers/media/radio/radio-mr800.c
@@ -85,6 +85,9 @@ MODULE_LICENSE("GPL");
85#define amradio_dev_warn(dev, fmt, arg...) \ 85#define amradio_dev_warn(dev, fmt, arg...) \
86 dev_warn(dev, MR800_DRIVER_NAME " - " fmt, ##arg) 86 dev_warn(dev, MR800_DRIVER_NAME " - " fmt, ##arg)
87 87
88#define amradio_dev_err(dev, fmt, arg...) \
89 dev_err(dev, MR800_DRIVER_NAME " - " fmt, ##arg)
90
88/* Probably USB_TIMEOUT should be modified in module parameter */ 91/* Probably USB_TIMEOUT should be modified in module parameter */
89#define BUFFER_LENGTH 8 92#define BUFFER_LENGTH 8
90#define USB_TIMEOUT 500 93#define USB_TIMEOUT 500
@@ -129,18 +132,20 @@ static int usb_amradio_resume(struct usb_interface *intf);
129struct amradio_device { 132struct amradio_device {
130 /* reference to USB and video device */ 133 /* reference to USB and video device */
131 struct usb_device *usbdev; 134 struct usb_device *usbdev;
132 struct video_device *videodev; 135 struct usb_interface *intf;
136 struct video_device videodev;
133 struct v4l2_device v4l2_dev; 137 struct v4l2_device v4l2_dev;
134 138
135 unsigned char *buffer; 139 unsigned char *buffer;
136 struct mutex lock; /* buffer locking */ 140 struct mutex lock; /* buffer locking */
137 int curfreq; 141 int curfreq;
138 int stereo; 142 int stereo;
139 int users;
140 int removed;
141 int muted; 143 int muted;
144 int initialized;
142}; 145};
143 146
147#define vdev_to_amradio(r) container_of(r, struct amradio_device, videodev)
148
144/* USB Device ID List */ 149/* USB Device ID List */
145static struct usb_device_id usb_amradio_device_table[] = { 150static struct usb_device_id usb_amradio_device_table[] = {
146 {USB_DEVICE_AND_INTERFACE_INFO(USB_AMRADIO_VENDOR, USB_AMRADIO_PRODUCT, 151 {USB_DEVICE_AND_INTERFACE_INFO(USB_AMRADIO_VENDOR, USB_AMRADIO_PRODUCT,
@@ -159,7 +164,7 @@ static struct usb_driver usb_amradio_driver = {
159 .resume = usb_amradio_resume, 164 .resume = usb_amradio_resume,
160 .reset_resume = usb_amradio_resume, 165 .reset_resume = usb_amradio_resume,
161 .id_table = usb_amradio_device_table, 166 .id_table = usb_amradio_device_table,
162 .supports_autosuspend = 0, 167 .supports_autosuspend = 1,
163}; 168};
164 169
165/* switch on/off the radio. Send 8 bytes to device */ 170/* switch on/off the radio. Send 8 bytes to device */
@@ -168,11 +173,7 @@ static int amradio_set_mute(struct amradio_device *radio, char argument)
168 int retval; 173 int retval;
169 int size; 174 int size;
170 175
171 /* safety check */ 176 BUG_ON(!mutex_is_locked(&radio->lock));
172 if (radio->removed)
173 return -EIO;
174
175 mutex_lock(&radio->lock);
176 177
177 radio->buffer[0] = 0x00; 178 radio->buffer[0] = 0x00;
178 radio->buffer[1] = 0x55; 179 radio->buffer[1] = 0x55;
@@ -187,14 +188,12 @@ static int amradio_set_mute(struct amradio_device *radio, char argument)
187 (void *) (radio->buffer), BUFFER_LENGTH, &size, USB_TIMEOUT); 188 (void *) (radio->buffer), BUFFER_LENGTH, &size, USB_TIMEOUT);
188 189
189 if (retval < 0 || size != BUFFER_LENGTH) { 190 if (retval < 0 || size != BUFFER_LENGTH) {
190 mutex_unlock(&radio->lock); 191 amradio_dev_warn(&radio->videodev.dev, "set mute failed\n");
191 return retval; 192 return retval;
192 } 193 }
193 194
194 radio->muted = argument; 195 radio->muted = argument;
195 196
196 mutex_unlock(&radio->lock);
197
198 return retval; 197 return retval;
199} 198}
200 199
@@ -205,11 +204,7 @@ static int amradio_setfreq(struct amradio_device *radio, int freq)
205 int size; 204 int size;
206 unsigned short freq_send = 0x10 + (freq >> 3) / 25; 205 unsigned short freq_send = 0x10 + (freq >> 3) / 25;
207 206
208 /* safety check */ 207 BUG_ON(!mutex_is_locked(&radio->lock));
209 if (radio->removed)
210 return -EIO;
211
212 mutex_lock(&radio->lock);
213 208
214 radio->buffer[0] = 0x00; 209 radio->buffer[0] = 0x00;
215 radio->buffer[1] = 0x55; 210 radio->buffer[1] = 0x55;
@@ -223,10 +218,8 @@ static int amradio_setfreq(struct amradio_device *radio, int freq)
223 retval = usb_bulk_msg(radio->usbdev, usb_sndintpipe(radio->usbdev, 2), 218 retval = usb_bulk_msg(radio->usbdev, usb_sndintpipe(radio->usbdev, 2),
224 (void *) (radio->buffer), BUFFER_LENGTH, &size, USB_TIMEOUT); 219 (void *) (radio->buffer), BUFFER_LENGTH, &size, USB_TIMEOUT);
225 220
226 if (retval < 0 || size != BUFFER_LENGTH) { 221 if (retval < 0 || size != BUFFER_LENGTH)
227 mutex_unlock(&radio->lock); 222 goto out_err;
228 return retval;
229 }
230 223
231 /* frequency is calculated from freq_send and placed in first 2 bytes */ 224 /* frequency is calculated from freq_send and placed in first 2 bytes */
232 radio->buffer[0] = (freq_send >> 8) & 0xff; 225 radio->buffer[0] = (freq_send >> 8) & 0xff;
@@ -240,13 +233,15 @@ static int amradio_setfreq(struct amradio_device *radio, int freq)
240 retval = usb_bulk_msg(radio->usbdev, usb_sndintpipe(radio->usbdev, 2), 233 retval = usb_bulk_msg(radio->usbdev, usb_sndintpipe(radio->usbdev, 2),
241 (void *) (radio->buffer), BUFFER_LENGTH, &size, USB_TIMEOUT); 234 (void *) (radio->buffer), BUFFER_LENGTH, &size, USB_TIMEOUT);
242 235
243 if (retval < 0 || size != BUFFER_LENGTH) { 236 if (retval < 0 || size != BUFFER_LENGTH)
244 mutex_unlock(&radio->lock); 237 goto out_err;
245 return retval;
246 }
247 238
248 mutex_unlock(&radio->lock); 239 radio->curfreq = freq;
240 goto out;
249 241
242out_err:
243 amradio_dev_warn(&radio->videodev.dev, "set frequency failed\n");
244out:
250 return retval; 245 return retval;
251} 246}
252 247
@@ -255,11 +250,7 @@ static int amradio_set_stereo(struct amradio_device *radio, char argument)
255 int retval; 250 int retval;
256 int size; 251 int size;
257 252
258 /* safety check */ 253 BUG_ON(!mutex_is_locked(&radio->lock));
259 if (radio->removed)
260 return -EIO;
261
262 mutex_lock(&radio->lock);
263 254
264 radio->buffer[0] = 0x00; 255 radio->buffer[0] = 0x00;
265 radio->buffer[1] = 0x55; 256 radio->buffer[1] = 0x55;
@@ -274,14 +265,14 @@ static int amradio_set_stereo(struct amradio_device *radio, char argument)
274 (void *) (radio->buffer), BUFFER_LENGTH, &size, USB_TIMEOUT); 265 (void *) (radio->buffer), BUFFER_LENGTH, &size, USB_TIMEOUT);
275 266
276 if (retval < 0 || size != BUFFER_LENGTH) { 267 if (retval < 0 || size != BUFFER_LENGTH) {
277 radio->stereo = -1; 268 amradio_dev_warn(&radio->videodev.dev, "set stereo failed\n");
278 mutex_unlock(&radio->lock);
279 return retval; 269 return retval;
280 } 270 }
281 271
282 radio->stereo = 1; 272 if (argument == WANT_STEREO)
283 273 radio->stereo = 1;
284 mutex_unlock(&radio->lock); 274 else
275 radio->stereo = 0;
285 276
286 return retval; 277 return retval;
287} 278}
@@ -296,19 +287,19 @@ static void usb_amradio_disconnect(struct usb_interface *intf)
296 struct amradio_device *radio = usb_get_intfdata(intf); 287 struct amradio_device *radio = usb_get_intfdata(intf);
297 288
298 mutex_lock(&radio->lock); 289 mutex_lock(&radio->lock);
299 radio->removed = 1; 290 radio->usbdev = NULL;
300 mutex_unlock(&radio->lock); 291 mutex_unlock(&radio->lock);
301 292
302 usb_set_intfdata(intf, NULL); 293 usb_set_intfdata(intf, NULL);
303 video_unregister_device(radio->videodev);
304 v4l2_device_disconnect(&radio->v4l2_dev); 294 v4l2_device_disconnect(&radio->v4l2_dev);
295 video_unregister_device(&radio->videodev);
305} 296}
306 297
307/* vidioc_querycap - query device capabilities */ 298/* vidioc_querycap - query device capabilities */
308static int vidioc_querycap(struct file *file, void *priv, 299static int vidioc_querycap(struct file *file, void *priv,
309 struct v4l2_capability *v) 300 struct v4l2_capability *v)
310{ 301{
311 struct amradio_device *radio = video_drvdata(file); 302 struct amradio_device *radio = file->private_data;
312 303
313 strlcpy(v->driver, "radio-mr800", sizeof(v->driver)); 304 strlcpy(v->driver, "radio-mr800", sizeof(v->driver));
314 strlcpy(v->card, "AverMedia MR 800 USB FM Radio", sizeof(v->card)); 305 strlcpy(v->card, "AverMedia MR 800 USB FM Radio", sizeof(v->card));
@@ -322,13 +313,9 @@ static int vidioc_querycap(struct file *file, void *priv,
322static int vidioc_g_tuner(struct file *file, void *priv, 313static int vidioc_g_tuner(struct file *file, void *priv,
323 struct v4l2_tuner *v) 314 struct v4l2_tuner *v)
324{ 315{
325 struct amradio_device *radio = video_get_drvdata(video_devdata(file)); 316 struct amradio_device *radio = file->private_data;
326 int retval; 317 int retval;
327 318
328 /* safety check */
329 if (radio->removed)
330 return -EIO;
331
332 if (v->index > 0) 319 if (v->index > 0)
333 return -EINVAL; 320 return -EINVAL;
334 321
@@ -341,9 +328,6 @@ static int vidioc_g_tuner(struct file *file, void *priv,
341 * amradio_set_stereo shouldn't be here 328 * amradio_set_stereo shouldn't be here
342 */ 329 */
343 retval = amradio_set_stereo(radio, WANT_STEREO); 330 retval = amradio_set_stereo(radio, WANT_STEREO);
344 if (retval < 0)
345 amradio_dev_warn(&radio->videodev->dev,
346 "set stereo failed\n");
347 331
348 strcpy(v->name, "FM"); 332 strcpy(v->name, "FM");
349 v->type = V4L2_TUNER_RADIO; 333 v->type = V4L2_TUNER_RADIO;
@@ -357,19 +341,16 @@ static int vidioc_g_tuner(struct file *file, void *priv,
357 v->audmode = V4L2_TUNER_MODE_MONO; 341 v->audmode = V4L2_TUNER_MODE_MONO;
358 v->signal = 0xffff; /* Can't get the signal strength, sad.. */ 342 v->signal = 0xffff; /* Can't get the signal strength, sad.. */
359 v->afc = 0; /* Don't know what is this */ 343 v->afc = 0; /* Don't know what is this */
360 return 0; 344
345 return retval;
361} 346}
362 347
363/* vidioc_s_tuner - set tuner attributes */ 348/* vidioc_s_tuner - set tuner attributes */
364static int vidioc_s_tuner(struct file *file, void *priv, 349static int vidioc_s_tuner(struct file *file, void *priv,
365 struct v4l2_tuner *v) 350 struct v4l2_tuner *v)
366{ 351{
367 struct amradio_device *radio = video_get_drvdata(video_devdata(file)); 352 struct amradio_device *radio = file->private_data;
368 int retval; 353 int retval = -EINVAL;
369
370 /* safety check */
371 if (radio->removed)
372 return -EIO;
373 354
374 if (v->index > 0) 355 if (v->index > 0)
375 return -EINVAL; 356 return -EINVAL;
@@ -378,57 +359,33 @@ static int vidioc_s_tuner(struct file *file, void *priv,
378 switch (v->audmode) { 359 switch (v->audmode) {
379 case V4L2_TUNER_MODE_MONO: 360 case V4L2_TUNER_MODE_MONO:
380 retval = amradio_set_stereo(radio, WANT_MONO); 361 retval = amradio_set_stereo(radio, WANT_MONO);
381 if (retval < 0)
382 amradio_dev_warn(&radio->videodev->dev,
383 "set mono failed\n");
384 break; 362 break;
385 case V4L2_TUNER_MODE_STEREO: 363 case V4L2_TUNER_MODE_STEREO:
386 retval = amradio_set_stereo(radio, WANT_STEREO); 364 retval = amradio_set_stereo(radio, WANT_STEREO);
387 if (retval < 0)
388 amradio_dev_warn(&radio->videodev->dev,
389 "set stereo failed\n");
390 break; 365 break;
391 default:
392 return -EINVAL;
393 } 366 }
394 367
395 return 0; 368 return retval;
396} 369}
397 370
398/* vidioc_s_frequency - set tuner radio frequency */ 371/* vidioc_s_frequency - set tuner radio frequency */
399static int vidioc_s_frequency(struct file *file, void *priv, 372static int vidioc_s_frequency(struct file *file, void *priv,
400 struct v4l2_frequency *f) 373 struct v4l2_frequency *f)
401{ 374{
402 struct amradio_device *radio = video_get_drvdata(video_devdata(file)); 375 struct amradio_device *radio = file->private_data;
403 int retval;
404 376
405 /* safety check */ 377 return amradio_setfreq(radio, f->frequency);
406 if (radio->removed)
407 return -EIO;
408
409 mutex_lock(&radio->lock);
410 radio->curfreq = f->frequency;
411 mutex_unlock(&radio->lock);
412
413 retval = amradio_setfreq(radio, radio->curfreq);
414 if (retval < 0)
415 amradio_dev_warn(&radio->videodev->dev,
416 "set frequency failed\n");
417 return 0;
418} 378}
419 379
420/* vidioc_g_frequency - get tuner radio frequency */ 380/* vidioc_g_frequency - get tuner radio frequency */
421static int vidioc_g_frequency(struct file *file, void *priv, 381static int vidioc_g_frequency(struct file *file, void *priv,
422 struct v4l2_frequency *f) 382 struct v4l2_frequency *f)
423{ 383{
424 struct amradio_device *radio = video_get_drvdata(video_devdata(file)); 384 struct amradio_device *radio = file->private_data;
425
426 /* safety check */
427 if (radio->removed)
428 return -EIO;
429 385
430 f->type = V4L2_TUNER_RADIO; 386 f->type = V4L2_TUNER_RADIO;
431 f->frequency = radio->curfreq; 387 f->frequency = radio->curfreq;
388
432 return 0; 389 return 0;
433} 390}
434 391
@@ -448,17 +405,14 @@ static int vidioc_queryctrl(struct file *file, void *priv,
448static int vidioc_g_ctrl(struct file *file, void *priv, 405static int vidioc_g_ctrl(struct file *file, void *priv,
449 struct v4l2_control *ctrl) 406 struct v4l2_control *ctrl)
450{ 407{
451 struct amradio_device *radio = video_get_drvdata(video_devdata(file)); 408 struct amradio_device *radio = file->private_data;
452
453 /* safety check */
454 if (radio->removed)
455 return -EIO;
456 409
457 switch (ctrl->id) { 410 switch (ctrl->id) {
458 case V4L2_CID_AUDIO_MUTE: 411 case V4L2_CID_AUDIO_MUTE:
459 ctrl->value = radio->muted; 412 ctrl->value = radio->muted;
460 return 0; 413 return 0;
461 } 414 }
415
462 return -EINVAL; 416 return -EINVAL;
463} 417}
464 418
@@ -466,33 +420,20 @@ static int vidioc_g_ctrl(struct file *file, void *priv,
466static int vidioc_s_ctrl(struct file *file, void *priv, 420static int vidioc_s_ctrl(struct file *file, void *priv,
467 struct v4l2_control *ctrl) 421 struct v4l2_control *ctrl)
468{ 422{
469 struct amradio_device *radio = video_get_drvdata(video_devdata(file)); 423 struct amradio_device *radio = file->private_data;
470 int retval; 424 int retval = -EINVAL;
471
472 /* safety check */
473 if (radio->removed)
474 return -EIO;
475 425
476 switch (ctrl->id) { 426 switch (ctrl->id) {
477 case V4L2_CID_AUDIO_MUTE: 427 case V4L2_CID_AUDIO_MUTE:
478 if (ctrl->value) { 428 if (ctrl->value)
479 retval = amradio_set_mute(radio, AMRADIO_STOP); 429 retval = amradio_set_mute(radio, AMRADIO_STOP);
480 if (retval < 0) { 430 else
481 amradio_dev_warn(&radio->videodev->dev,
482 "amradio_stop failed\n");
483 return -1;
484 }
485 } else {
486 retval = amradio_set_mute(radio, AMRADIO_START); 431 retval = amradio_set_mute(radio, AMRADIO_START);
487 if (retval < 0) { 432
488 amradio_dev_warn(&radio->videodev->dev, 433 break;
489 "amradio_start failed\n");
490 return -1;
491 }
492 }
493 return 0;
494 } 434 }
495 return -EINVAL; 435
436 return retval;
496} 437}
497 438
498/* vidioc_g_audio - get audio attributes */ 439/* vidioc_g_audio - get audio attributes */
@@ -531,75 +472,108 @@ static int vidioc_s_input(struct file *filp, void *priv, unsigned int i)
531 return 0; 472 return 0;
532} 473}
533 474
534/* open device - amradio_start() and amradio_setfreq() */ 475static int usb_amradio_init(struct amradio_device *radio)
535static int usb_amradio_open(struct file *file)
536{ 476{
537 struct amradio_device *radio = video_get_drvdata(video_devdata(file));
538 int retval; 477 int retval;
539 478
540 lock_kernel(); 479 retval = amradio_set_mute(radio, AMRADIO_STOP);
480 if (retval)
481 goto out_err;
541 482
542 radio->users = 1; 483 retval = amradio_set_stereo(radio, WANT_STEREO);
543 radio->muted = 1; 484 if (retval)
485 goto out_err;
544 486
545 retval = amradio_set_mute(radio, AMRADIO_START); 487 radio->initialized = 1;
546 if (retval < 0) { 488 goto out;
547 amradio_dev_warn(&radio->videodev->dev, 489
548 "radio did not start up properly\n"); 490out_err:
549 radio->users = 0; 491 amradio_dev_err(&radio->videodev.dev, "initialization failed\n");
550 unlock_kernel(); 492out:
551 return -EIO; 493 return retval;
494}
495
496/* open device - amradio_start() and amradio_setfreq() */
497static int usb_amradio_open(struct file *file)
498{
499 struct amradio_device *radio = vdev_to_amradio(video_devdata(file));
500 int retval = 0;
501
502 mutex_lock(&radio->lock);
503
504 if (!radio->usbdev) {
505 retval = -EIO;
506 goto unlock;
552 } 507 }
553 508
554 retval = amradio_set_stereo(radio, WANT_STEREO); 509 file->private_data = radio;
555 if (retval < 0) 510 retval = usb_autopm_get_interface(radio->intf);
556 amradio_dev_warn(&radio->videodev->dev, 511 if (retval)
557 "set stereo failed\n"); 512 goto unlock;
558 513
559 retval = amradio_setfreq(radio, radio->curfreq); 514 if (unlikely(!radio->initialized)) {
560 if (retval < 0) 515 retval = usb_amradio_init(radio);
561 amradio_dev_warn(&radio->videodev->dev, 516 if (retval)
562 "set frequency failed\n"); 517 usb_autopm_put_interface(radio->intf);
518 }
563 519
564 unlock_kernel(); 520unlock:
565 return 0; 521 mutex_unlock(&radio->lock);
522 return retval;
566} 523}
567 524
568/*close device */ 525/*close device */
569static int usb_amradio_close(struct file *file) 526static int usb_amradio_close(struct file *file)
570{ 527{
571 struct amradio_device *radio = video_get_drvdata(video_devdata(file)); 528 struct amradio_device *radio = file->private_data;
572 int retval; 529 int retval = 0;
573
574 if (!radio)
575 return -ENODEV;
576 530
577 mutex_lock(&radio->lock); 531 mutex_lock(&radio->lock);
578 radio->users = 0; 532
533 if (!radio->usbdev)
534 retval = -EIO;
535 else
536 usb_autopm_put_interface(radio->intf);
537
579 mutex_unlock(&radio->lock); 538 mutex_unlock(&radio->lock);
539 return retval;
540}
580 541
581 if (!radio->removed) { 542static long usb_amradio_ioctl(struct file *file, unsigned int cmd,
582 retval = amradio_set_mute(radio, AMRADIO_STOP); 543 unsigned long arg)
583 if (retval < 0) 544{
584 amradio_dev_warn(&radio->videodev->dev, 545 struct amradio_device *radio = file->private_data;
585 "amradio_stop failed\n"); 546 long retval = 0;
547
548 mutex_lock(&radio->lock);
549
550 if (!radio->usbdev) {
551 retval = -EIO;
552 goto unlock;
586 } 553 }
587 554
588 return 0; 555 retval = video_ioctl2(file, cmd, arg);
556
557unlock:
558 mutex_unlock(&radio->lock);
559 return retval;
589} 560}
590 561
591/* Suspend device - stop device. Need to be checked and fixed */ 562/* Suspend device - stop device. Need to be checked and fixed */
592static int usb_amradio_suspend(struct usb_interface *intf, pm_message_t message) 563static int usb_amradio_suspend(struct usb_interface *intf, pm_message_t message)
593{ 564{
594 struct amradio_device *radio = usb_get_intfdata(intf); 565 struct amradio_device *radio = usb_get_intfdata(intf);
595 int retval;
596 566
597 retval = amradio_set_mute(radio, AMRADIO_STOP); 567 mutex_lock(&radio->lock);
598 if (retval < 0) 568
599 dev_warn(&intf->dev, "amradio_stop failed\n"); 569 if (!radio->muted && radio->initialized) {
570 amradio_set_mute(radio, AMRADIO_STOP);
571 radio->muted = 0;
572 }
600 573
601 dev_info(&intf->dev, "going into suspend..\n"); 574 dev_info(&intf->dev, "going into suspend..\n");
602 575
576 mutex_unlock(&radio->lock);
603 return 0; 577 return 0;
604} 578}
605 579
@@ -607,14 +581,26 @@ static int usb_amradio_suspend(struct usb_interface *intf, pm_message_t message)
607static int usb_amradio_resume(struct usb_interface *intf) 581static int usb_amradio_resume(struct usb_interface *intf)
608{ 582{
609 struct amradio_device *radio = usb_get_intfdata(intf); 583 struct amradio_device *radio = usb_get_intfdata(intf);
610 int retval;
611 584
612 retval = amradio_set_mute(radio, AMRADIO_START); 585 mutex_lock(&radio->lock);
613 if (retval < 0) 586
614 dev_warn(&intf->dev, "amradio_start failed\n"); 587 if (unlikely(!radio->initialized))
588 goto unlock;
589
590 if (radio->stereo)
591 amradio_set_stereo(radio, WANT_STEREO);
592 else
593 amradio_set_stereo(radio, WANT_MONO);
594
595 amradio_setfreq(radio, radio->curfreq);
615 596
597 if (!radio->muted)
598 amradio_set_mute(radio, AMRADIO_START);
599
600unlock:
616 dev_info(&intf->dev, "coming out of suspend..\n"); 601 dev_info(&intf->dev, "coming out of suspend..\n");
617 602
603 mutex_unlock(&radio->lock);
618 return 0; 604 return 0;
619} 605}
620 606
@@ -623,7 +609,7 @@ static const struct v4l2_file_operations usb_amradio_fops = {
623 .owner = THIS_MODULE, 609 .owner = THIS_MODULE,
624 .open = usb_amradio_open, 610 .open = usb_amradio_open,
625 .release = usb_amradio_close, 611 .release = usb_amradio_close,
626 .ioctl = video_ioctl2, 612 .ioctl = usb_amradio_ioctl,
627}; 613};
628 614
629static const struct v4l2_ioctl_ops usb_amradio_ioctl_ops = { 615static const struct v4l2_ioctl_ops usb_amradio_ioctl_ops = {
@@ -643,10 +629,7 @@ static const struct v4l2_ioctl_ops usb_amradio_ioctl_ops = {
643 629
644static void usb_amradio_video_device_release(struct video_device *videodev) 630static void usb_amradio_video_device_release(struct video_device *videodev)
645{ 631{
646 struct amradio_device *radio = video_get_drvdata(videodev); 632 struct amradio_device *radio = vdev_to_amradio(videodev);
647
648 /* we call v4l to free radio->videodev */
649 video_device_release(videodev);
650 633
651 v4l2_device_unregister(&radio->v4l2_dev); 634 v4l2_device_unregister(&radio->v4l2_dev);
652 635
@@ -660,70 +643,63 @@ static int usb_amradio_probe(struct usb_interface *intf,
660 const struct usb_device_id *id) 643 const struct usb_device_id *id)
661{ 644{
662 struct amradio_device *radio; 645 struct amradio_device *radio;
663 struct v4l2_device *v4l2_dev; 646 int retval = 0;
664 int retval;
665 647
666 radio = kzalloc(sizeof(struct amradio_device), GFP_KERNEL); 648 radio = kzalloc(sizeof(struct amradio_device), GFP_KERNEL);
667 649
668 if (!radio) { 650 if (!radio) {
669 dev_err(&intf->dev, "kmalloc for amradio_device failed\n"); 651 dev_err(&intf->dev, "kmalloc for amradio_device failed\n");
670 return -ENOMEM; 652 retval = -ENOMEM;
653 goto err;
671 } 654 }
672 655
673 radio->buffer = kmalloc(BUFFER_LENGTH, GFP_KERNEL); 656 radio->buffer = kmalloc(BUFFER_LENGTH, GFP_KERNEL);
674 657
675 if (!radio->buffer) { 658 if (!radio->buffer) {
676 dev_err(&intf->dev, "kmalloc for radio->buffer failed\n"); 659 dev_err(&intf->dev, "kmalloc for radio->buffer failed\n");
677 kfree(radio); 660 retval = -ENOMEM;
678 return -ENOMEM; 661 goto err_nobuf;
679 } 662 }
680 663
681 v4l2_dev = &radio->v4l2_dev; 664 retval = v4l2_device_register(&intf->dev, &radio->v4l2_dev);
682 retval = v4l2_device_register(&intf->dev, v4l2_dev);
683 if (retval < 0) { 665 if (retval < 0) {
684 dev_err(&intf->dev, "couldn't register v4l2_device\n"); 666 dev_err(&intf->dev, "couldn't register v4l2_device\n");
685 kfree(radio->buffer); 667 goto err_v4l2;
686 kfree(radio);
687 return retval;
688 } 668 }
689 669
690 radio->videodev = video_device_alloc(); 670 strlcpy(radio->videodev.name, radio->v4l2_dev.name,
691 671 sizeof(radio->videodev.name));
692 if (!radio->videodev) { 672 radio->videodev.v4l2_dev = &radio->v4l2_dev;
693 dev_err(&intf->dev, "video_device_alloc failed\n"); 673 radio->videodev.fops = &usb_amradio_fops;
694 kfree(radio->buffer); 674 radio->videodev.ioctl_ops = &usb_amradio_ioctl_ops;
695 kfree(radio); 675 radio->videodev.release = usb_amradio_video_device_release;
696 return -ENOMEM;
697 }
698 676
699 strlcpy(radio->videodev->name, v4l2_dev->name, sizeof(radio->videodev->name));
700 radio->videodev->v4l2_dev = v4l2_dev;
701 radio->videodev->fops = &usb_amradio_fops;
702 radio->videodev->ioctl_ops = &usb_amradio_ioctl_ops;
703 radio->videodev->release = usb_amradio_video_device_release;
704
705 radio->removed = 0;
706 radio->users = 0;
707 radio->usbdev = interface_to_usbdev(intf); 677 radio->usbdev = interface_to_usbdev(intf);
678 radio->intf = intf;
708 radio->curfreq = 95.16 * FREQ_MUL; 679 radio->curfreq = 95.16 * FREQ_MUL;
709 radio->stereo = -1;
710 680
711 mutex_init(&radio->lock); 681 mutex_init(&radio->lock);
712 682
713 video_set_drvdata(radio->videodev, radio); 683 video_set_drvdata(&radio->videodev, radio);
714 684
715 retval = video_register_device(radio->videodev, VFL_TYPE_RADIO, radio_nr); 685 retval = video_register_device(&radio->videodev, VFL_TYPE_RADIO,
686 radio_nr);
716 if (retval < 0) { 687 if (retval < 0) {
717 dev_err(&intf->dev, "could not register video device\n"); 688 dev_err(&intf->dev, "could not register video device\n");
718 video_device_release(radio->videodev); 689 goto err_vdev;
719 v4l2_device_unregister(v4l2_dev);
720 kfree(radio->buffer);
721 kfree(radio);
722 return -EIO;
723 } 690 }
724 691
725 usb_set_intfdata(intf, radio); 692 usb_set_intfdata(intf, radio);
726 return 0; 693 return 0;
694
695err_vdev:
696 v4l2_device_unregister(&radio->v4l2_dev);
697err_v4l2:
698 kfree(radio->buffer);
699err_nobuf:
700 kfree(radio);
701err:
702 return retval;
727} 703}
728 704
729static int __init amradio_init(void) 705static int __init amradio_init(void)