Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 306354
b: refs/heads/master
c: 6fd522a
h: refs/heads/master
v: v3
  • Loading branch information
Hans Verkuil authored and Mauro Carvalho Chehab committed May 14, 2012
1 parent 34a42bf commit bad4c68
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 81 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 340bd4c16cead8bf8f5205c7d283a3bd9d699f76
refs/heads/master: 6fd522a6d12d0ebac528f2d4553c4bf51c0c3275
1 change: 0 additions & 1 deletion trunk/drivers/media/radio/si470x/radio-si470x-common.c
Original file line number Diff line number Diff line change
Expand Up @@ -570,7 +570,6 @@ static int si470x_s_ctrl(struct v4l2_ctrl *ctrl)
else
radio->registers[POWERCFG] |= POWERCFG_DMUTE;
return si470x_set_register(radio, POWERCFG);
break;
default:
return -EINVAL;
}
Expand Down
149 changes: 70 additions & 79 deletions trunk/drivers/media/radio/si470x/radio-si470x-usb.c
Original file line number Diff line number Diff line change
Expand Up @@ -481,91 +481,20 @@ static void si470x_int_in_callback(struct urb *urb)
}



/**************************************************************************
* File Operations Interface
**************************************************************************/

/*
* si470x_fops_open - file open
*/
int si470x_fops_open(struct file *file)
{
struct si470x_device *radio = video_drvdata(file);
int retval = v4l2_fh_open(file);

if (retval)
return retval;

retval = usb_autopm_get_interface(radio->intf);
if (retval < 0)
goto done;

if (v4l2_fh_is_singular_file(file)) {
/* start radio */
retval = si470x_start(radio);
if (retval < 0) {
usb_autopm_put_interface(radio->intf);
goto done;
}

/* initialize interrupt urb */
usb_fill_int_urb(radio->int_in_urb, radio->usbdev,
usb_rcvintpipe(radio->usbdev,
radio->int_in_endpoint->bEndpointAddress),
radio->int_in_buffer,
le16_to_cpu(radio->int_in_endpoint->wMaxPacketSize),
si470x_int_in_callback,
radio,
radio->int_in_endpoint->bInterval);

radio->int_in_running = 1;
mb();

retval = usb_submit_urb(radio->int_in_urb, GFP_KERNEL);
if (retval) {
dev_info(&radio->intf->dev,
"submitting int urb failed (%d)\n", retval);
radio->int_in_running = 0;
usb_autopm_put_interface(radio->intf);
}
}

done:
if (retval)
v4l2_fh_release(file);
return retval;
return v4l2_fh_open(file);
}


/*
* si470x_fops_release - file release
*/
int si470x_fops_release(struct file *file)
{
struct si470x_device *radio = video_drvdata(file);

if (v4l2_fh_is_singular_file(file)) {
/* shutdown interrupt handler */
if (radio->int_in_running) {
radio->int_in_running = 0;
if (radio->int_in_urb)
usb_kill_urb(radio->int_in_urb);
}

/* cancel read processes */
wake_up_interruptible(&radio->read_queue);

/* stop radio */
si470x_stop(radio);
usb_autopm_put_interface(radio->intf);
}
return v4l2_fh_release(file);
}

static void si470x_usb_release(struct video_device *vdev)
static void si470x_usb_release(struct v4l2_device *v4l2_dev)
{
struct si470x_device *radio = video_get_drvdata(vdev);
struct si470x_device *radio =
container_of(v4l2_dev, struct si470x_device, v4l2_dev);

usb_free_urb(radio->int_in_urb);
v4l2_ctrl_handler_free(&radio->hdl);
Expand Down Expand Up @@ -599,6 +528,38 @@ int si470x_vidioc_querycap(struct file *file, void *priv,
}


static int si470x_start_usb(struct si470x_device *radio)
{
int retval;

/* start radio */
retval = si470x_start(radio);
if (retval < 0)
return retval;

v4l2_ctrl_handler_setup(&radio->hdl);

/* initialize interrupt urb */
usb_fill_int_urb(radio->int_in_urb, radio->usbdev,
usb_rcvintpipe(radio->usbdev,
radio->int_in_endpoint->bEndpointAddress),
radio->int_in_buffer,
le16_to_cpu(radio->int_in_endpoint->wMaxPacketSize),
si470x_int_in_callback,
radio,
radio->int_in_endpoint->bInterval);

radio->int_in_running = 1;
mb();

retval = usb_submit_urb(radio->int_in_urb, GFP_KERNEL);
if (retval) {
dev_info(&radio->intf->dev,
"submitting int urb failed (%d)\n", retval);
radio->int_in_running = 0;
}
return retval;
}

/**************************************************************************
* USB Interface
Expand Down Expand Up @@ -658,6 +619,7 @@ static int si470x_usb_driver_probe(struct usb_interface *intf,
goto err_intbuffer;
}

radio->v4l2_dev.release = si470x_usb_release;
retval = v4l2_device_register(&intf->dev, &radio->v4l2_dev);
if (retval < 0) {
dev_err(&intf->dev, "couldn't register v4l2_device\n");
Expand All @@ -678,7 +640,7 @@ static int si470x_usb_driver_probe(struct usb_interface *intf,
radio->videodev.ctrl_handler = &radio->hdl;
radio->videodev.lock = &radio->lock;
radio->videodev.v4l2_dev = &radio->v4l2_dev;
radio->videodev.release = si470x_usb_release;
radio->videodev.release = video_device_release_empty;
set_bit(V4L2_FL_USE_FH_PRIO, &radio->videodev.flags);
video_set_drvdata(&radio->videodev, radio);

Expand Down Expand Up @@ -754,11 +716,16 @@ static int si470x_usb_driver_probe(struct usb_interface *intf,
init_waitqueue_head(&radio->read_queue);
usb_set_intfdata(intf, radio);

/* start radio */
retval = si470x_start_usb(radio);
if (retval < 0)
goto err_all;

/* register video device */
retval = video_register_device(&radio->videodev, VFL_TYPE_RADIO,
radio_nr);
if (retval) {
dev_warn(&intf->dev, "Could not register video device\n");
dev_err(&intf->dev, "Could not register video device\n");
goto err_all;
}

Expand Down Expand Up @@ -786,8 +753,22 @@ static int si470x_usb_driver_probe(struct usb_interface *intf,
static int si470x_usb_driver_suspend(struct usb_interface *intf,
pm_message_t message)
{
struct si470x_device *radio = usb_get_intfdata(intf);

dev_info(&intf->dev, "suspending now...\n");

/* shutdown interrupt handler */
if (radio->int_in_running) {
radio->int_in_running = 0;
if (radio->int_in_urb)
usb_kill_urb(radio->int_in_urb);
}

/* cancel read processes */
wake_up_interruptible(&radio->read_queue);

/* stop radio */
si470x_stop(radio);
return 0;
}

Expand All @@ -797,9 +778,12 @@ static int si470x_usb_driver_suspend(struct usb_interface *intf,
*/
static int si470x_usb_driver_resume(struct usb_interface *intf)
{
struct si470x_device *radio = usb_get_intfdata(intf);

dev_info(&intf->dev, "resuming now...\n");

return 0;
/* start radio */
return si470x_start_usb(radio);
}


Expand All @@ -815,20 +799,27 @@ static void si470x_usb_driver_disconnect(struct usb_interface *intf)
video_unregister_device(&radio->videodev);
usb_set_intfdata(intf, NULL);
mutex_unlock(&radio->lock);
v4l2_device_put(&radio->v4l2_dev);
}


/*
* si470x_usb_driver - usb driver interface
*
* A note on suspend/resume: this driver had only empty suspend/resume
* functions, and when I tried to test suspend/resume it always disconnected
* instead of resuming (using my ADS InstantFM stick). So I've decided to
* remove these callbacks until someone else with better hardware can
* implement and test this.
*/
static struct usb_driver si470x_usb_driver = {
.name = DRIVER_NAME,
.probe = si470x_usb_driver_probe,
.disconnect = si470x_usb_driver_disconnect,
.suspend = si470x_usb_driver_suspend,
.resume = si470x_usb_driver_resume,
.reset_resume = si470x_usb_driver_resume,
.id_table = si470x_usb_driver_id_table,
.supports_autosuspend = 1,
};

module_usb_driver(si470x_usb_driver);
Expand Down

0 comments on commit bad4c68

Please sign in to comment.