Re: [RFC PATCH 1/4] si470x: Clean up, introduce the control framework.
Hello Hans,
thanks for the improvements. Looks good to me.
Acked-by: Tobias Lorenz <tobias.lorenz@xxxxxxx>
Bye,
Toby
Am Freitag, 4. Mai 2012, 15:30:29 schrieb Hans Verkuil:
> From: Hans Verkuil <hans.verkuil@xxxxxxxxx>
>
> This cleans up the code and si470x now uses the proper v4l2 frameworks
> and passes most of the v4l2-compliance tests.
>
> Signed-off-by: Hans Verkuil <hans.verkuil@xxxxxxxxx>
> ---
> drivers/media/radio/si470x/radio-si470x-common.c | 193
> +++------------------- drivers/media/radio/si470x/radio-si470x-i2c.c |
> 65 ++------
> drivers/media/radio/si470x/radio-si470x-usb.c | 146 +++++++---------
> drivers/media/radio/si470x/radio-si470x.h | 14 +-
> 4 files changed, 105 insertions(+), 313 deletions(-)
>
> diff --git a/drivers/media/radio/si470x/radio-si470x-common.c
> b/drivers/media/radio/si470x/radio-si470x-common.c index 0e740c9..de9475f
> 100644
> --- a/drivers/media/radio/si470x/radio-si470x-common.c
> +++ b/drivers/media/radio/si470x/radio-si470x-common.c
> @@ -196,9 +196,9 @@ static int si470x_set_chan(struct si470x_device *radio,
> unsigned short chan) }
>
> if ((radio->registers[STATUSRSSI] & STATUSRSSI_STC) == 0)
> - dev_warn(&radio->videodev->dev, "tune does not complete\n");
> + dev_warn(&radio->videodev.dev, "tune does not complete\n");
> if (timed_out)
> - dev_warn(&radio->videodev->dev,
> + dev_warn(&radio->videodev.dev,
> "tune timed out after %u ms\n", tune_timeout);
>
> stop:
> @@ -344,12 +344,12 @@ static int si470x_set_seek(struct si470x_device
> *radio, }
>
> if ((radio->registers[STATUSRSSI] & STATUSRSSI_STC) == 0)
> - dev_warn(&radio->videodev->dev, "seek does not complete\n");
> + dev_warn(&radio->videodev.dev, "seek does not complete\n");
> if (radio->registers[STATUSRSSI] & STATUSRSSI_SF)
> - dev_warn(&radio->videodev->dev,
> + dev_warn(&radio->videodev.dev,
> "seek failed / band limit reached\n");
> if (timed_out)
> - dev_warn(&radio->videodev->dev,
> + dev_warn(&radio->videodev.dev,
> "seek timed out after %u ms\n", seek_timeout);
>
> stop:
> @@ -463,7 +463,6 @@ static ssize_t si470x_fops_read(struct file *file, char
> __user *buf, unsigned int block_count = 0;
>
> /* switch on rds reception */
> - mutex_lock(&radio->lock);
> if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0)
> si470x_rds_on(radio);
>
> @@ -505,7 +504,6 @@ static ssize_t si470x_fops_read(struct file *file, char
> __user *buf, }
>
> done:
> - mutex_unlock(&radio->lock);
> return retval;
> }
>
> @@ -521,10 +519,8 @@ static unsigned int si470x_fops_poll(struct file
> *file,
>
> /* switch on rds reception */
>
> - mutex_lock(&radio->lock);
> if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0)
> si470x_rds_on(radio);
> - mutex_unlock(&radio->lock);
>
> poll_wait(file, &radio->read_queue, pts);
>
> @@ -553,134 +549,27 @@ static const struct v4l2_file_operations si470x_fops
> = { * Video4Linux Interface
>
> **************************************************************************
> /
>
> -/*
> - * si470x_vidioc_queryctrl - enumerate control items
> - */
> -static int si470x_vidioc_queryctrl(struct file *file, void *priv,
> - struct v4l2_queryctrl *qc)
> -{
> - struct si470x_device *radio = video_drvdata(file);
> - int retval = -EINVAL;
> -
> - /* abort if qc->id is below V4L2_CID_BASE */
> - if (qc->id < V4L2_CID_BASE)
> - goto done;
> -
> - /* search video control */
> - switch (qc->id) {
> - case V4L2_CID_AUDIO_VOLUME:
> - return v4l2_ctrl_query_fill(qc, 0, 15, 1, 15);
> - case V4L2_CID_AUDIO_MUTE:
> - return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1);
> - }
>
> - /* disable unsupported base controls */
> - /* to satisfy kradio and such apps */
> - if ((retval == -EINVAL) && (qc->id < V4L2_CID_LASTP1)) {
> - qc->flags = V4L2_CTRL_FLAG_DISABLED;
> - retval = 0;
> - }
> -
> -done:
> - if (retval < 0)
> - dev_warn(&radio->videodev->dev,
> - "query controls failed with %d\n", retval);
> - return retval;
> -}
> -
> -
> -/*
> - * si470x_vidioc_g_ctrl - get the value of a control
> - */
> -static int si470x_vidioc_g_ctrl(struct file *file, void *priv,
> - struct v4l2_control *ctrl)
> +static int si470x_s_ctrl(struct v4l2_ctrl *ctrl)
> {
> - struct si470x_device *radio = video_drvdata(file);
> - int retval = 0;
> -
> - mutex_lock(&radio->lock);
> - /* safety checks */
> - retval = si470x_disconnect_check(radio);
> - if (retval)
> - goto done;
> -
> - switch (ctrl->id) {
> - case V4L2_CID_AUDIO_VOLUME:
> - ctrl->value = radio->registers[SYSCONFIG2] &
> - SYSCONFIG2_VOLUME;
> - break;
> - case V4L2_CID_AUDIO_MUTE:
> - ctrl->value = ((radio->registers[POWERCFG] &
> - POWERCFG_DMUTE) == 0) ? 1 : 0;
> - break;
> - default:
> - retval = -EINVAL;
> - }
> -
> -done:
> - if (retval < 0)
> - dev_warn(&radio->videodev->dev,
> - "get control failed with %d\n", retval);
> -
> - mutex_unlock(&radio->lock);
> - return retval;
> -}
> -
> -
> -/*
> - * si470x_vidioc_s_ctrl - set the value of a control
> - */
> -static int si470x_vidioc_s_ctrl(struct file *file, void *priv,
> - struct v4l2_control *ctrl)
> -{
> - struct si470x_device *radio = video_drvdata(file);
> - int retval = 0;
> -
> - mutex_lock(&radio->lock);
> - /* safety checks */
> - retval = si470x_disconnect_check(radio);
> - if (retval)
> - goto done;
> + struct si470x_device *radio =
> + container_of(ctrl->handler, struct si470x_device, hdl);
>
> switch (ctrl->id) {
> case V4L2_CID_AUDIO_VOLUME:
> radio->registers[SYSCONFIG2] &= ~SYSCONFIG2_VOLUME;
> - radio->registers[SYSCONFIG2] |= ctrl->value;
> - retval = si470x_set_register(radio, SYSCONFIG2);
> - break;
> + radio->registers[SYSCONFIG2] |= ctrl->val;
> + return si470x_set_register(radio, SYSCONFIG2);
> case V4L2_CID_AUDIO_MUTE:
> - if (ctrl->value == 1)
> + if (ctrl->val)
> radio->registers[POWERCFG] &= ~POWERCFG_DMUTE;
> else
> radio->registers[POWERCFG] |= POWERCFG_DMUTE;
> - retval = si470x_set_register(radio, POWERCFG);
> + return si470x_set_register(radio, POWERCFG);
> break;
> default:
> - retval = -EINVAL;
> + return -EINVAL;
> }
> -
> -done:
> - if (retval < 0)
> - dev_warn(&radio->videodev->dev,
> - "set control failed with %d\n", retval);
> - mutex_unlock(&radio->lock);
> - return retval;
> -}
> -
> -
> -/*
> - * si470x_vidioc_g_audio - get audio attributes
> - */
> -static int si470x_vidioc_g_audio(struct file *file, void *priv,
> - struct v4l2_audio *audio)
> -{
> - /* driver constants */
> - audio->index = 0;
> - strcpy(audio->name, "Radio");
> - audio->capability = V4L2_AUDCAP_STEREO;
> - audio->mode = 0;
> -
> - return 0;
> }
>
>
> @@ -693,12 +582,6 @@ static int si470x_vidioc_g_tuner(struct file *file,
> void *priv, struct si470x_device *radio = video_drvdata(file);
> int retval = 0;
>
> - mutex_lock(&radio->lock);
> - /* safety checks */
> - retval = si470x_disconnect_check(radio);
> - if (retval)
> - goto done;
> -
> if (tuner->index != 0) {
> retval = -EINVAL;
> goto done;
> @@ -737,7 +620,7 @@ static int si470x_vidioc_g_tuner(struct file *file,
> void *priv, if ((radio->registers[STATUSRSSI] & STATUSRSSI_ST) == 0)
> tuner->rxsubchans = V4L2_TUNER_SUB_MONO;
> else
> - tuner->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO;
> + tuner->rxsubchans = V4L2_TUNER_SUB_STEREO;
> /* If there is a reliable method of detecting an RDS channel,
> then this code should check for that before setting this
> RDS subchannel. */
> @@ -761,9 +644,8 @@ static int si470x_vidioc_g_tuner(struct file *file,
> void *priv,
>
> done:
> if (retval < 0)
> - dev_warn(&radio->videodev->dev,
> + dev_warn(&radio->videodev.dev,
> "get tuner failed with %d\n", retval);
> - mutex_unlock(&radio->lock);
> return retval;
> }
>
> @@ -777,12 +659,6 @@ static int si470x_vidioc_s_tuner(struct file *file,
> void *priv, struct si470x_device *radio = video_drvdata(file);
> int retval = 0;
>
> - mutex_lock(&radio->lock);
> - /* safety checks */
> - retval = si470x_disconnect_check(radio);
> - if (retval)
> - goto done;
> -
> if (tuner->index != 0)
> goto done;
>
> @@ -802,9 +678,8 @@ static int si470x_vidioc_s_tuner(struct file *file,
> void *priv,
>
> done:
> if (retval < 0)
> - dev_warn(&radio->videodev->dev,
> + dev_warn(&radio->videodev.dev,
> "set tuner failed with %d\n", retval);
> - mutex_unlock(&radio->lock);
> return retval;
> }
>
> @@ -818,12 +693,6 @@ static int si470x_vidioc_g_frequency(struct file
> *file, void *priv, struct si470x_device *radio = video_drvdata(file);
> int retval = 0;
>
> - /* safety checks */
> - mutex_lock(&radio->lock);
> - retval = si470x_disconnect_check(radio);
> - if (retval)
> - goto done;
> -
> if (freq->tuner != 0) {
> retval = -EINVAL;
> goto done;
> @@ -834,9 +703,8 @@ static int si470x_vidioc_g_frequency(struct file *file,
> void *priv,
>
> done:
> if (retval < 0)
> - dev_warn(&radio->videodev->dev,
> + dev_warn(&radio->videodev.dev,
> "get frequency failed with %d\n", retval);
> - mutex_unlock(&radio->lock);
> return retval;
> }
>
> @@ -850,12 +718,6 @@ static int si470x_vidioc_s_frequency(struct file
> *file, void *priv, struct si470x_device *radio = video_drvdata(file);
> int retval = 0;
>
> - mutex_lock(&radio->lock);
> - /* safety checks */
> - retval = si470x_disconnect_check(radio);
> - if (retval)
> - goto done;
> -
> if (freq->tuner != 0) {
> retval = -EINVAL;
> goto done;
> @@ -865,9 +727,8 @@ static int si470x_vidioc_s_frequency(struct file *file,
> void *priv,
>
> done:
> if (retval < 0)
> - dev_warn(&radio->videodev->dev,
> + dev_warn(&radio->videodev.dev,
> "set frequency failed with %d\n", retval);
> - mutex_unlock(&radio->lock);
> return retval;
> }
>
> @@ -881,12 +742,6 @@ static int si470x_vidioc_s_hw_freq_seek(struct file
> *file, void *priv, struct si470x_device *radio = video_drvdata(file);
> int retval = 0;
>
> - mutex_lock(&radio->lock);
> - /* safety checks */
> - retval = si470x_disconnect_check(radio);
> - if (retval)
> - goto done;
> -
> if (seek->tuner != 0) {
> retval = -EINVAL;
> goto done;
> @@ -896,22 +751,20 @@ static int si470x_vidioc_s_hw_freq_seek(struct file
> *file, void *priv,
>
> done:
> if (retval < 0)
> - dev_warn(&radio->videodev->dev,
> + dev_warn(&radio->videodev.dev,
> "set hardware frequency seek failed with %d\n", retval);
> - mutex_unlock(&radio->lock);
> return retval;
> }
>
> +const struct v4l2_ctrl_ops si470x_ctrl_ops = {
> + .s_ctrl = si470x_s_ctrl,
> +};
>
> /*
> * si470x_ioctl_ops - video device ioctl operations
> */
> static const struct v4l2_ioctl_ops si470x_ioctl_ops = {
> .vidioc_querycap = si470x_vidioc_querycap,
> - .vidioc_queryctrl = si470x_vidioc_queryctrl,
> - .vidioc_g_ctrl = si470x_vidioc_g_ctrl,
> - .vidioc_s_ctrl = si470x_vidioc_s_ctrl,
> - .vidioc_g_audio = si470x_vidioc_g_audio,
> .vidioc_g_tuner = si470x_vidioc_g_tuner,
> .vidioc_s_tuner = si470x_vidioc_s_tuner,
> .vidioc_g_frequency = si470x_vidioc_g_frequency,
> @@ -926,6 +779,6 @@ static const struct v4l2_ioctl_ops si470x_ioctl_ops = {
> struct video_device si470x_viddev_template = {
> .fops = &si470x_fops,
> .name = DRIVER_NAME,
> - .release = video_device_release,
> + .release = video_device_release_empty,
> .ioctl_ops = &si470x_ioctl_ops,
> };
> diff --git a/drivers/media/radio/si470x/radio-si470x-i2c.c
> b/drivers/media/radio/si470x/radio-si470x-i2c.c index 9b546a5..a80044c
> 100644
> --- a/drivers/media/radio/si470x/radio-si470x-i2c.c
> +++ b/drivers/media/radio/si470x/radio-si470x-i2c.c
> @@ -162,20 +162,6 @@ static int si470x_get_all_registers(struct
> si470x_device *radio)
>
>
> /*************************************************************************
> * - * General Driver Functions - DISCONNECT_CHECK
> -
> **************************************************************************
> / -
> -/*
> - * si470x_disconnect_check - check whether radio disconnects
> - */
> -int si470x_disconnect_check(struct si470x_device *radio)
> -{
> - return 0;
> -}
> -
> -
> -
> -/*************************************************************************
> * * File Operations Interface
>
> **************************************************************************
> /
>
> @@ -185,12 +171,12 @@ int si470x_disconnect_check(struct si470x_device
> *radio) int si470x_fops_open(struct file *file)
> {
> struct si470x_device *radio = video_drvdata(file);
> - int retval = 0;
> + int retval = v4l2_fh_open(file);
>
> - mutex_lock(&radio->lock);
> - radio->users++;
> + if (retval)
> + return retval;
>
> - if (radio->users == 1) {
> + if (v4l2_fh_is_singular_file(file)) {
> /* start radio */
> retval = si470x_start(radio);
> if (retval < 0)
> @@ -205,7 +191,8 @@ int si470x_fops_open(struct file *file)
> }
>
> done:
> - mutex_unlock(&radio->lock);
> + if (retval)
> + v4l2_fh_release(file);
> return retval;
> }
>
> @@ -216,21 +203,12 @@ done:
> int si470x_fops_release(struct file *file)
> {
> struct si470x_device *radio = video_drvdata(file);
> - int retval = 0;
> -
> - /* safety check */
> - if (!radio)
> - return -ENODEV;
>
> - mutex_lock(&radio->lock);
> - radio->users--;
> - if (radio->users == 0)
> + if (v4l2_fh_is_singular_file(file))
> /* stop radio */
> - retval = si470x_stop(radio);
> + si470x_stop(radio);
>
> - mutex_unlock(&radio->lock);
> -
> - return retval;
> + return v4l2_fh_release(file);
> }
>
>
> @@ -371,32 +349,25 @@ static int __devinit si470x_i2c_probe(struct
> i2c_client *client, goto err_initial;
> }
>
> - radio->users = 0;
> radio->client = client;
> mutex_init(&radio->lock);
>
> - /* video device allocation and initialization */
> - radio->videodev = video_device_alloc();
> - if (!radio->videodev) {
> - retval = -ENOMEM;
> - goto err_radio;
> - }
> - memcpy(radio->videodev, &si470x_viddev_template,
> - sizeof(si470x_viddev_template));
> - video_set_drvdata(radio->videodev, radio);
> + /* video device initialization */
> + radio->videodev = si470x_viddev_template;
> + video_set_drvdata(&radio->videodev, radio);
>
> /* power up : need 110ms */
> radio->registers[POWERCFG] = POWERCFG_ENABLE;
> if (si470x_set_register(radio, POWERCFG) < 0) {
> retval = -EIO;
> - goto err_video;
> + goto err_radio;
> }
> msleep(110);
>
> /* get device and chip versions */
> if (si470x_get_all_registers(radio) < 0) {
> retval = -EIO;
> - goto err_video;
> + goto err_radio;
> }
> dev_info(&client->dev, "DeviceID=0x%4.4hx ChipID=0x%4.4hx\n",
> radio->registers[DEVICEID], radio->registers[CHIPID]);
> @@ -427,7 +398,7 @@ static int __devinit si470x_i2c_probe(struct i2c_client
> *client, radio->buffer = kmalloc(radio->buf_size, GFP_KERNEL);
> if (!radio->buffer) {
> retval = -EIO;
> - goto err_video;
> + goto err_radio;
> }
>
> /* rds buffer configuration */
> @@ -447,7 +418,7 @@ static int __devinit si470x_i2c_probe(struct i2c_client
> *client, }
>
> /* register video device */
> - retval = video_register_device(radio->videodev, VFL_TYPE_RADIO,
> + retval = video_register_device(&radio->videodev, VFL_TYPE_RADIO,
> radio_nr);
> if (retval) {
> dev_warn(&client->dev, "Could not register video device\n");
> @@ -460,8 +431,6 @@ err_all:
> free_irq(client->irq, radio);
> err_rds:
> kfree(radio->buffer);
> -err_video:
> - video_device_release(radio->videodev);
> err_radio:
> kfree(radio);
> err_initial:
> @@ -477,7 +446,7 @@ static __devexit int si470x_i2c_remove(struct
> i2c_client *client) struct si470x_device *radio =
> i2c_get_clientdata(client);
>
> free_irq(client->irq, radio);
> - video_unregister_device(radio->videodev);
> + video_unregister_device(&radio->videodev);
> kfree(radio);
>
> return 0;
> diff --git a/drivers/media/radio/si470x/radio-si470x-usb.c
> b/drivers/media/radio/si470x/radio-si470x-usb.c index b7debb6..f133c3d
> 100644
> --- a/drivers/media/radio/si470x/radio-si470x-usb.c
> +++ b/drivers/media/radio/si470x/radio-si470x-usb.c
> @@ -367,23 +367,6 @@ static int si470x_get_scratch_page_versions(struct
> si470x_device *radio)
>
>
> /*************************************************************************
> * - * General Driver Functions - DISCONNECT_CHECK
> -
> **************************************************************************
> / -
> -/*
> - * si470x_disconnect_check - check whether radio disconnects
> - */
> -int si470x_disconnect_check(struct si470x_device *radio)
> -{
> - if (radio->disconnected)
> - return -EIO;
> - else
> - return 0;
> -}
> -
> -
> -
> -/*************************************************************************
> * * RDS Driver Functions
>
> **************************************************************************
> /
>
> @@ -414,9 +397,6 @@ static void si470x_int_in_callback(struct urb *urb)
> }
> }
>
> - /* safety checks */
> - if (radio->disconnected)
> - return;
> if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0)
> goto resubmit;
>
> @@ -512,19 +492,16 @@ resubmit:
> int si470x_fops_open(struct file *file)
> {
> struct si470x_device *radio = video_drvdata(file);
> - int retval;
> + int retval = v4l2_fh_open(file);
>
> - mutex_lock(&radio->lock);
> - radio->users++;
> + if (retval)
> + return retval;
>
> retval = usb_autopm_get_interface(radio->intf);
> - if (retval < 0) {
> - radio->users--;
> - retval = -EIO;
> + if (retval < 0)
> goto done;
> - }
>
> - if (radio->users == 1) {
> + if (v4l2_fh_is_singular_file(file)) {
> /* start radio */
> retval = si470x_start(radio);
> if (retval < 0) {
> @@ -555,7 +532,8 @@ int si470x_fops_open(struct file *file)
> }
>
> done:
> - mutex_unlock(&radio->lock);
> + if (retval)
> + v4l2_fh_release(file);
> return retval;
> }
>
> @@ -566,45 +544,36 @@ done:
> int si470x_fops_release(struct file *file)
> {
> struct si470x_device *radio = video_drvdata(file);
> - int retval = 0;
>
> - /* safety check */
> - if (!radio) {
> - retval = -ENODEV;
> - goto done;
> - }
> -
> - mutex_lock(&radio->lock);
> - radio->users--;
> - if (radio->users == 0) {
> + 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);
> - }
> -
> - if (radio->disconnected) {
> - video_unregister_device(radio->videodev);
> - kfree(radio->int_in_buffer);
> - kfree(radio->buffer);
> - mutex_unlock(&radio->lock);
> - kfree(radio);
> - goto done;
> + if (radio->int_in_urb)
> + usb_kill_urb(radio->int_in_urb);
> }
>
> /* cancel read processes */
> wake_up_interruptible(&radio->read_queue);
>
> /* stop radio */
> - retval = si470x_stop(radio);
> + si470x_stop(radio);
> usb_autopm_put_interface(radio->intf);
> }
> - mutex_unlock(&radio->lock);
> -done:
> - return retval;
> + return v4l2_fh_release(file);
> }
>
> +static void si470x_usb_release(struct video_device *vdev)
> +{
> + struct si470x_device *radio = video_get_drvdata(vdev);
> +
> + usb_free_urb(radio->int_in_urb);
> + v4l2_ctrl_handler_free(&radio->hdl);
> + v4l2_device_unregister(&radio->v4l2_dev);
> + kfree(radio->int_in_buffer);
> + kfree(radio->buffer);
> + kfree(radio);
> +}
>
>
> /*************************************************************************
> * @@ -623,9 +592,9 @@ int si470x_vidioc_querycap(struct file *file, void
> *priv, strlcpy(capability->card, DRIVER_CARD, sizeof(capability->card));
> usb_make_path(radio->usbdev, capability->bus_info,
> sizeof(capability->bus_info));
> - capability->capabilities = V4L2_CAP_HW_FREQ_SEEK |
> + capability->device_caps = V4L2_CAP_HW_FREQ_SEEK |
> V4L2_CAP_TUNER | V4L2_CAP_RADIO | V4L2_CAP_RDS_CAPTURE;
> -
> + capability->capabilities = capability->device_caps |
> V4L2_CAP_DEVICE_CAPS; return 0;
> }
>
> @@ -653,8 +622,6 @@ static int si470x_usb_driver_probe(struct usb_interface
> *intf, retval = -ENOMEM;
> goto err_initial;
> }
> - radio->users = 0;
> - radio->disconnected = 0;
> radio->usbdev = interface_to_usbdev(intf);
> radio->intf = intf;
> mutex_init(&radio->lock);
> @@ -691,20 +658,34 @@ static int si470x_usb_driver_probe(struct
> usb_interface *intf, goto err_intbuffer;
> }
>
> - /* video device allocation and initialization */
> - radio->videodev = video_device_alloc();
> - if (!radio->videodev) {
> - retval = -ENOMEM;
> + retval = v4l2_device_register(&intf->dev, &radio->v4l2_dev);
> + if (retval < 0) {
> + dev_err(&intf->dev, "couldn't register v4l2_device\n");
> goto err_urb;
> }
> - memcpy(radio->videodev, &si470x_viddev_template,
> - sizeof(si470x_viddev_template));
> - video_set_drvdata(radio->videodev, radio);
> +
> + v4l2_ctrl_handler_init(&radio->hdl, 2);
> + v4l2_ctrl_new_std(&radio->hdl, &si470x_ctrl_ops,
> + V4L2_CID_AUDIO_MUTE, 0, 1, 1, 1);
> + v4l2_ctrl_new_std(&radio->hdl, &si470x_ctrl_ops,
> + V4L2_CID_AUDIO_VOLUME, 0, 15, 1, 15);
> + if (radio->hdl.error) {
> + retval = radio->hdl.error;
> + dev_err(&intf->dev, "couldn't register control\n");
> + goto err_dev;
> + }
> + radio->videodev = si470x_viddev_template;
> + radio->videodev.ctrl_handler = &radio->hdl;
> + radio->videodev.lock = &radio->lock;
> + radio->videodev.v4l2_dev = &radio->v4l2_dev;
> + radio->videodev.release = si470x_usb_release;
> + set_bit(V4L2_FL_USE_FH_PRIO, &radio->videodev.flags);
> + video_set_drvdata(&radio->videodev, radio);
>
> /* get device and chip versions */
> if (si470x_get_all_registers(radio) < 0) {
> retval = -EIO;
> - goto err_video;
> + goto err_ctrl;
> }
> dev_info(&intf->dev, "DeviceID=0x%4.4hx ChipID=0x%4.4hx\n",
> radio->registers[DEVICEID], radio->registers[CHIPID]);
> @@ -721,7 +702,7 @@ static int si470x_usb_driver_probe(struct usb_interface
> *intf, /* get software and hardware versions */
> if (si470x_get_scratch_page_versions(radio) < 0) {
> retval = -EIO;
> - goto err_video;
> + goto err_ctrl;
> }
> dev_info(&intf->dev, "software version %d, hardware version %d\n",
> radio->software_version, radio->hardware_version);
> @@ -764,28 +745,30 @@ static int si470x_usb_driver_probe(struct
> usb_interface *intf, radio->buffer = kmalloc(radio->buf_size, GFP_KERNEL);
> if (!radio->buffer) {
> retval = -EIO;
> - goto err_video;
> + goto err_ctrl;
> }
>
> /* rds buffer configuration */
> radio->wr_index = 0;
> radio->rd_index = 0;
> init_waitqueue_head(&radio->read_queue);
> + usb_set_intfdata(intf, radio);
>
> /* register video device */
> - retval = video_register_device(radio->videodev, VFL_TYPE_RADIO,
> + retval = video_register_device(&radio->videodev, VFL_TYPE_RADIO,
> radio_nr);
> if (retval) {
> dev_warn(&intf->dev, "Could not register video device\n");
> goto err_all;
> }
> - usb_set_intfdata(intf, radio);
>
> return 0;
> err_all:
> kfree(radio->buffer);
> -err_video:
> - video_device_release(radio->videodev);
> +err_ctrl:
> + v4l2_ctrl_handler_free(&radio->hdl);
> +err_dev:
> + v4l2_device_unregister(&radio->v4l2_dev);
> err_urb:
> usb_free_urb(radio->int_in_urb);
> err_intbuffer:
> @@ -828,23 +811,10 @@ static void si470x_usb_driver_disconnect(struct
> usb_interface *intf) struct si470x_device *radio = usb_get_intfdata(intf);
>
> mutex_lock(&radio->lock);
> - radio->disconnected = 1;
> + v4l2_device_disconnect(&radio->v4l2_dev);
> + video_unregister_device(&radio->videodev);
> usb_set_intfdata(intf, NULL);
> - if (radio->users == 0) {
> - /* set led to disconnect state */
> - si470x_set_led_state(radio, BLINK_ORANGE_LED);
> -
> - /* Free data structures. */
> - usb_free_urb(radio->int_in_urb);
> -
> - kfree(radio->int_in_buffer);
> - video_unregister_device(radio->videodev);
> - kfree(radio->buffer);
> - mutex_unlock(&radio->lock);
> - kfree(radio);
> - } else {
> - mutex_unlock(&radio->lock);
> - }
> + mutex_unlock(&radio->lock);
> }
>
>
> diff --git a/drivers/media/radio/si470x/radio-si470x.h
> b/drivers/media/radio/si470x/radio-si470x.h index f300a55..4921cab 100644
> --- a/drivers/media/radio/si470x/radio-si470x.h
> +++ b/drivers/media/radio/si470x/radio-si470x.h
> @@ -36,6 +36,9 @@
> #include <linux/mutex.h>
> #include <media/v4l2-common.h>
> #include <media/v4l2-ioctl.h>
> +#include <media/v4l2-ctrls.h>
> +#include <media/v4l2-event.h>
> +#include <media/v4l2-device.h>
> #include <asm/unaligned.h>
>
>
> @@ -141,10 +144,9 @@
> * si470x_device - private data
> */
> struct si470x_device {
> - struct video_device *videodev;
> -
> - /* driver management */
> - unsigned int users;
> + struct v4l2_device v4l2_dev;
> + struct video_device videodev;
> + struct v4l2_ctrl_handler hdl;
>
> /* Silabs internal registers (0..15) */
> unsigned short registers[RADIO_REGISTER_NUM];
> @@ -174,9 +176,6 @@ struct si470x_device {
> /* scratch page */
> unsigned char software_version;
> unsigned char hardware_version;
> -
> - /* driver management */
> - unsigned char disconnected;
> #endif
>
> #if defined(CONFIG_I2C_SI470X) || defined(CONFIG_I2C_SI470X_MODULE)
> @@ -213,6 +212,7 @@ struct si470x_device {
> * Common Functions
>
> **************************************************************************
> / extern struct video_device si470x_viddev_template;
> +extern const struct v4l2_ctrl_ops si470x_ctrl_ops;
> int si470x_get_register(struct si470x_device *radio, int regnr);
> int si470x_set_register(struct si470x_device *radio, int regnr);
> int si470x_disconnect_check(struct si470x_device *radio);
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
[Linux Input]
[Video for Linux]
[Mplayer Users]
[Linux USB Devel]
[Linux Audio Users]
[Photos]
[Yosemite Photos]
[Linux Kernel]
[Linux SCSI]
[XFree86]
[Devices]
[Yosemite Backpacking]