Re: [RFC PATCH 1/4] si470x: Clean up, introduce the control framework.

2012-05-05 Thread Tobias Lorenz
Hello Hans,

thanks for the improvements. Looks good to me.

Acked-by: Tobias Lorenz tobias.lor...@gmx.net

Bye,
Toby

Am Freitag, 4. Mai 2012, 15:30:29 schrieb Hans Verkuil:
 From: Hans Verkuil hans.verk...@cisco.com
 
 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.verk...@cisco.com
 ---
  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

Re: [RFC PATCH 2/4] si470x: add control event support and more v4l2 compliancy fixes.

2012-05-05 Thread Tobias Lorenz
Hello Hans,

thanks for the improvements. Looks good to me.

Acked-by: Tobias Lorenz tobias.lor...@gmx.net

Bye,
Toby

Am Freitag, 4. Mai 2012, 15:30:30 schrieb Hans Verkuil:
 From: Hans Verkuil hans.verk...@cisco.com
 
 Signed-off-by: Hans Verkuil hans.verk...@cisco.com
 ---
  drivers/media/radio/si470x/radio-si470x-common.c |   45
 ++ 1 file changed, 28 insertions(+), 17 deletions(-)
 
 diff --git a/drivers/media/radio/si470x/radio-si470x-common.c
 b/drivers/media/radio/si470x/radio-si470x-common.c index de9475f..e70badf
 100644
 --- a/drivers/media/radio/si470x/radio-si470x-common.c
 +++ b/drivers/media/radio/si470x/radio-si470x-common.c
 @@ -262,7 +262,7 @@ static int si470x_get_freq(struct si470x_device *radio,
 unsigned int *freq) */
  int si470x_set_freq(struct si470x_device *radio, unsigned int freq)
  {
 - unsigned int spacing, band_bottom;
 + unsigned int spacing, band_bottom, band_top;
   unsigned short chan;
 
   /* Spacing (kHz) */
 @@ -278,19 +278,26 @@ int si470x_set_freq(struct si470x_device *radio,
 unsigned int freq) spacing = 0.050 * FREQ_MUL; break;
   };
 
 - /* Bottom of Band (MHz) */
 + /* Bottom/Top of Band (MHz) */
   switch ((radio-registers[SYSCONFIG2]  SYSCONFIG2_BAND)  6) {
   /* 0: 87.5 - 108 MHz (USA, Europe) */
   case 0:
 - band_bottom = 87.5 * FREQ_MUL; break;
 + band_bottom = 87.5 * FREQ_MUL;
 + band_top = 108 * FREQ_MUL;
 + break;
   /* 1: 76   - 108 MHz (Japan wide band) */
   default:
 - band_bottom = 76   * FREQ_MUL; break;
 + band_bottom = 76 * FREQ_MUL;
 + band_top = 108 * FREQ_MUL;
 + break;
   /* 2: 76   -  90 MHz (Japan) */
   case 2:
 - band_bottom = 76   * FREQ_MUL; break;
 + band_bottom = 76 * FREQ_MUL;
 + band_top = 90 * FREQ_MUL;
 + break;
   };
 
 + freq = clamp(freq, band_bottom, band_top);
   /* Chan = [ Freq (Mhz) - Bottom of Band (MHz) ] / Spacing (kHz) */
   chan = (freq - band_bottom) / spacing;
 
 @@ -515,17 +522,19 @@ static unsigned int si470x_fops_poll(struct file
 *file, struct poll_table_struct *pts)
  {
   struct si470x_device *radio = video_drvdata(file);
 - int retval = 0;
 -
 - /* switch on rds reception */
 + unsigned long req_events = poll_requested_events(pts);
 + int retval = v4l2_ctrl_poll(file, pts);
 
 - if ((radio-registers[SYSCONFIG1]  SYSCONFIG1_RDS) == 0)
 - si470x_rds_on(radio);
 + if (req_events  (POLLIN | POLLRDNORM)) {
 + /* switch on rds reception */
 + if ((radio-registers[SYSCONFIG1]  SYSCONFIG1_RDS) == 0)
 + si470x_rds_on(radio);
 
 - poll_wait(file, radio-read_queue, pts);
 + poll_wait(file, radio-read_queue, pts);
 
 - if (radio-rd_index != radio-wr_index)
 - retval = POLLIN | POLLRDNORM;
 + if (radio-rd_index != radio-wr_index)
 + retval |= POLLIN | POLLRDNORM;
 + }
 
   return retval;
  }
 @@ -637,6 +646,8 @@ static int si470x_vidioc_g_tuner(struct file *file,
 void *priv, tuner-signal = (radio-registers[STATUSRSSI] 
 STATUSRSSI_RSSI); /* the ideal factor is 0x/75 = 873,8 */
   tuner-signal = (tuner-signal * 873) + (8 * tuner-signal / 10);
 + if (tuner-signal  0x)
 + tuner-signal = 0x;
 
   /* automatic frequency control: -1: freq to low, 1 freq to high */
   /* AFCRL does only indicate that freq. differs, not if too low/high */
 @@ -660,7 +671,7 @@ static int si470x_vidioc_s_tuner(struct file *file,
 void *priv, int retval = 0;
 
   if (tuner-index != 0)
 - goto done;
 + return -EINVAL;
 
   /* mono/stereo selector */
   switch (tuner-audmode) {
 @@ -668,15 +679,13 @@ static int si470x_vidioc_s_tuner(struct file *file,
 void *priv, radio-registers[POWERCFG] |= POWERCFG_MONO;  /* force mono */
   break;
   case V4L2_TUNER_MODE_STEREO:
 + default:
   radio-registers[POWERCFG] = ~POWERCFG_MONO; /* try stereo */
   break;
 - default:
 - goto done;
   }
 
   retval = si470x_set_register(radio, POWERCFG);
 
 -done:
   if (retval  0)
   dev_warn(radio-videodev.dev,
   set tuner failed with %d\n, retval);
 @@ -770,6 +779,8 @@ static const struct v4l2_ioctl_ops si470x_ioctl_ops = {
   .vidioc_g_frequency = si470x_vidioc_g_frequency,
   .vidioc_s_frequency = si470x_vidioc_s_frequency,
   .vidioc_s_hw_freq_seek  = si470x_vidioc_s_hw_freq_seek,
 + .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
 + .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
  };

--
To unsubscribe from this list: send the line unsubscribe linux-media in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo

Re: [RFC PATCH 3/4] radio-si470x-common.c: remove unnecessary kernel log spam.

2012-05-05 Thread Tobias Lorenz
Hello Hans,

thanks for the improvements. Looks good to me.

Acked-by: Tobias Lorenz tobias.lor...@gmx.net

Bye,
Toby

Am Freitag, 4. Mai 2012, 15:30:31 schrieb Hans Verkuil:
 From: Hans Verkuil hans.verk...@cisco.com
 
 There is no need to report an error in the log, you are already returning
 that error to userspace after all.
 
 Signed-off-by: Hans Verkuil hans.verk...@cisco.com
 ---
  drivers/media/radio/si470x/radio-si470x-common.c |   78
 +- 1 file changed, 17 insertions(+), 61 deletions(-)
 
 diff --git a/drivers/media/radio/si470x/radio-si470x-common.c
 b/drivers/media/radio/si470x/radio-si470x-common.c index e70badf..b9a44d4
 100644
 --- a/drivers/media/radio/si470x/radio-si470x-common.c
 +++ b/drivers/media/radio/si470x/radio-si470x-common.c
 @@ -327,7 +327,7 @@ static int si470x_set_seek(struct si470x_device *radio,
   radio-registers[POWERCFG] = ~POWERCFG_SEEKUP;
   retval = si470x_set_register(radio, POWERCFG);
   if (retval  0)
 - goto done;
 + return retval;
 
   /* currently I2C driver only uses interrupt way to seek */
   if (radio-stci_enabled) {
 @@ -355,20 +355,15 @@ static int si470x_set_seek(struct si470x_device
 *radio, if (radio-registers[STATUSRSSI]  STATUSRSSI_SF)
   dev_warn(radio-videodev.dev,
   seek failed / band limit reached\n);
 - if (timed_out)
 - dev_warn(radio-videodev.dev,
 - seek timed out after %u ms\n, seek_timeout);
 
  stop:
   /* stop seeking */
   radio-registers[POWERCFG] = ~POWERCFG_SEEK;
   retval = si470x_set_register(radio, POWERCFG);
 
 -done:
   /* try again, if timed out */
 - if ((retval == 0)  timed_out)
 - retval = -EAGAIN;
 -
 + if (retval == 0  timed_out)
 + return -EAGAIN;
   return retval;
  }
 
 @@ -589,16 +584,14 @@ static int si470x_vidioc_g_tuner(struct file *file,
 void *priv, struct v4l2_tuner *tuner)
  {
   struct si470x_device *radio = video_drvdata(file);
 - int retval = 0;
 + int retval;
 
 - if (tuner-index != 0) {
 - retval = -EINVAL;
 - goto done;
 - }
 + if (tuner-index != 0)
 + return -EINVAL;
 
   retval = si470x_get_register(radio, STATUSRSSI);
   if (retval  0)
 - goto done;
 + return retval;
 
   /* driver constants */
   strcpy(tuner-name, FM);
 @@ -653,10 +646,6 @@ static int si470x_vidioc_g_tuner(struct file *file,
 void *priv, /* AFCRL does only indicate that freq. differs, not if too
 low/high */ tuner-afc = (radio-registers[STATUSRSSI]  STATUSRSSI_AFCRL)
 ? 1 : 0;
 
 -done:
 - if (retval  0)
 - dev_warn(radio-videodev.dev,
 - get tuner failed with %d\n, retval);
   return retval;
  }
 
 @@ -668,7 +657,6 @@ static int si470x_vidioc_s_tuner(struct file *file,
 void *priv, struct v4l2_tuner *tuner)
  {
   struct si470x_device *radio = video_drvdata(file);
 - int retval = 0;
 
   if (tuner-index != 0)
   return -EINVAL;
 @@ -684,12 +672,7 @@ static int si470x_vidioc_s_tuner(struct file *file,
 void *priv, break;
   }
 
 - retval = si470x_set_register(radio, POWERCFG);
 -
 - if (retval  0)
 - dev_warn(radio-videodev.dev,
 - set tuner failed with %d\n, retval);
 - return retval;
 + return si470x_set_register(radio, POWERCFG);
  }
 
 
 @@ -700,21 +683,12 @@ static int si470x_vidioc_g_frequency(struct file
 *file, void *priv, struct v4l2_frequency *freq)
  {
   struct si470x_device *radio = video_drvdata(file);
 - int retval = 0;
 
 - if (freq-tuner != 0) {
 - retval = -EINVAL;
 - goto done;
 - }
 + if (freq-tuner != 0)
 + return -EINVAL;
 
   freq-type = V4L2_TUNER_RADIO;
 - retval = si470x_get_freq(radio, freq-frequency);
 -
 -done:
 - if (retval  0)
 - dev_warn(radio-videodev.dev,
 - get frequency failed with %d\n, retval);
 - return retval;
 + return si470x_get_freq(radio, freq-frequency);
  }
 
 
 @@ -725,20 +699,11 @@ static int si470x_vidioc_s_frequency(struct file
 *file, void *priv, struct v4l2_frequency *freq)
  {
   struct si470x_device *radio = video_drvdata(file);
 - int retval = 0;
 -
 - if (freq-tuner != 0) {
 - retval = -EINVAL;
 - goto done;
 - }
 
 - retval = si470x_set_freq(radio, freq-frequency);
 + if (freq-tuner != 0)
 + return -EINVAL;
 
 -done:
 - if (retval  0)
 - dev_warn(radio-videodev.dev,
 - set frequency failed with %d\n, retval);
 - return retval;
 + return si470x_set_freq(radio, freq-frequency);
  }
 
 
 @@ -749,20 +714,11 @@ static int si470x_vidioc_s_hw_freq_seek(struct file
 *file, void *priv, struct v4l2_hw_freq_seek *seek)
  {
   struct si470x_device *radio = video_drvdata(file

Re: [RFC PATCH 4/4] radio-si470x-usb: remove autosuspend, implement suspend/resume.

2012-05-05 Thread Tobias Lorenz
Hello Hans,

thanks for the improvements. Looks good to me.

Acked-by: Tobias Lorenz tobias.lor...@gmx.net

Bye,
Toby

Am Freitag, 4. Mai 2012, 15:30:32 schrieb Hans Verkuil:
 From: Hans Verkuil hans.verk...@cisco.com
 
 The radio-si470x-usb driver supported both autosuspend and it stopped the
 radio the moment the last user of the radio device closed it. However, that
 was very confusing since if you play the audio from the device (e.g.
 through arecord -D ... | aplay) then no sound would play unless you had
 the radio device open at the same time, even though there is no need to do
 anything with that node.
 
 On the other hand, the actual suspend/resume functions didn't do anything,
 which would fail if you *did* have the radio node open at that time.
 
 So:
 
 - remove autosuspend (bad idea in general for USB radio devices)
 - move the start/stop out of the open/release functions into the
 resume/suspend functions.
 
 Signed-off-by: Hans Verkuil hans.verk...@cisco.com
 ---
  drivers/media/radio/si470x/radio-si470x-common.c |1 -
  drivers/media/radio/si470x/radio-si470x-usb.c|  149
 ++ 2 files changed, 70 insertions(+), 80 deletions(-)
 
 diff --git a/drivers/media/radio/si470x/radio-si470x-common.c
 b/drivers/media/radio/si470x/radio-si470x-common.c index b9a44d4..969cf49
 100644
 --- a/drivers/media/radio/si470x/radio-si470x-common.c
 +++ b/drivers/media/radio/si470x/radio-si470x-common.c
 @@ -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;
   }
 diff --git a/drivers/media/radio/si470x/radio-si470x-usb.c
 b/drivers/media/radio/si470x/radio-si470x-usb.c index f133c3d..e9f6387
 100644
 --- a/drivers/media/radio/si470x/radio-si470x-usb.c
 +++ b/drivers/media/radio/si470x/radio-si470x-usb.c
 @@ -481,91 +481,20 @@ resubmit:
  }
 
 
 -
 -/*
 * - * 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

Re: radio-si470x-usb.c warning: can I remove 'buf'?

2011-08-26 Thread Tobias Lorenz
Hi Hans,

 While going through the compile warnings generated in the daily build I
 came
 across this one:
 
 v4l-dvb-git/drivers/media/radio/si470x/radio-si470x-usb.c: In function
 'si470x_int_in_callback':
 v4l-dvb-git/drivers/media/radio/si470x/radio-si470x-usb.c:398:16:
warning:
 variable 'buf' set but not used [-Wunused-but-set-variable]
 
 The 'unsigned char buf[RDS_REPORT_SIZE];' is indeed unused, but can I
just
 remove it? There is this single assignment to buf: 'buf[0] =
RDS_REPORT;'.
 
 This makes me wonder if it is perhaps supposed to be used after all.
 
 Please let me know if I can remove it, or if it is a bug that someone
needs
 to fix.

this is an artifact from shifting the rds processing function into
interrupt context.
Yes, this can safely be removed.

Can you do this?

Bye,
Toby

--
To unsubscribe from this list: send the line unsubscribe linux-media in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 3/6] remove #ifdef to show rds support by i2c driver.

2011-05-01 Thread Tobias Lorenz
This removes some #ifdef statements.
RDS support is now indicated by I2C driver too.
The functionality was already in the driver.

Signed-off-by: Tobias Lorenz tobias.lor...@gmx.net
---
 drivers/media/radio/si470x/radio-si470x-common.c |6 --
 1 files changed, 0 insertions(+), 6 deletions(-)

diff --git a/drivers/media/radio/si470x/radio-si470x-common.c 
b/drivers/media/radio/si470x/radio-si470x-common.c
index f016220..bf58931 100644
--- a/drivers/media/radio/si470x/radio-si470x-common.c
+++ b/drivers/media/radio/si470x/radio-si470x-common.c
@@ -687,12 +687,8 @@ static int si470x_vidioc_g_tuner(struct file *file, void 
*priv,
/* driver constants */
strcpy(tuner-name, FM);
tuner-type = V4L2_TUNER_RADIO;
-#if defined(CONFIG_USB_SI470X) || defined(CONFIG_USB_SI470X_MODULE)
tuner-capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO |
V4L2_TUNER_CAP_RDS | V4L2_TUNER_CAP_RDS_BLOCK_IO;
-#else
-   tuner-capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO;
-#endif
 
/* range limits */
switch ((radio-registers[SYSCONFIG2]  SYSCONFIG2_BAND)  6) {
@@ -718,12 +714,10 @@ static int si470x_vidioc_g_tuner(struct file *file, void 
*priv,
tuner-rxsubchans = V4L2_TUNER_SUB_MONO;
else
tuner-rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO;
-#if defined(CONFIG_USB_SI470X) || defined(CONFIG_USB_SI470X_MODULE)
/* If there is a reliable method of detecting an RDS channel,
   then this code should check for that before setting this
   RDS subchannel. */
tuner-rxsubchans |= V4L2_TUNER_SUB_RDS;
-#endif
 
/* mono/stereo selector */
if ((radio-registers[POWERCFG]  POWERCFG_MONO) == 0)
-- 
1.7.4.1

--
To unsubscribe from this list: send the line unsubscribe linux-media in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 1/6] important fix for rds locking

2011-05-01 Thread Tobias Lorenz
This patch removes a redundant mutex_lock in fops_read.
Every rds read attempt would stall otherwise.

Signed-off-by: Tobias Lorenz tobias.lor...@gmx.net
---
 drivers/media/radio/si470x/radio-si470x-common.c |3 +--
 1 files changed, 1 insertions(+), 2 deletions(-)

diff --git a/drivers/media/radio/si470x/radio-si470x-common.c 
b/drivers/media/radio/si470x/radio-si470x-common.c
index ac76dfe..5cbeeb3 100644
--- a/drivers/media/radio/si470x/radio-si470x-common.c
+++ b/drivers/media/radio/si470x/radio-si470x-common.c
@@ -438,7 +438,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);
 
@@ -479,9 +478,9 @@ static ssize_t si470x_fops_read(struct file *file, char 
__user *buf,
buf += 3;
retval += 3;
}
+   mutex_unlock(radio-lock);
 
 done:
-   mutex_unlock(radio-lock);
return retval;
 }
 
-- 
1.7.4.1

--
To unsubscribe from this list: send the line unsubscribe linux-media in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 5/6] documentation improvements

2011-05-01 Thread Tobias Lorenz
This patch moves the history to the documentation and updated the copyrights.

Signed-off-by: Tobias Lorenz tobias.lor...@gmx.net
---
 Documentation/video4linux/si470x.txt |   94 
++-
 drivers/media/radio/si470x/radio-si470x-common.c |   91 
--
 drivers/media/radio/si470x/radio-si470x-usb.c|8 -
 drivers/media/radio/si470x/radio-si470x.h|2 
 4 files changed, 93 insertions(+), 102 deletions(-)

diff --git a/Documentation/video4linux/si470x.txt 
b/Documentation/video4linux/si470x.txt
index 3a7823e..8fc6edb 100644
--- a/Documentation/video4linux/si470x.txt
+++ b/Documentation/video4linux/si470x.txt
@@ -1,6 +1,6 @@
 Driver for USB radios for the Silicon Labs Si470x FM Radio Receivers
 
-Copyright (c) 2009 Tobias Lorenz tobias.lor...@gmx.net
+Copyright (c) 2011 Tobias Lorenz tobias.lor...@gmx.net
 
 
 Information from Silicon Labs
@@ -86,6 +86,7 @@ mplayer -radio adevice=hw=1.0:arate=96000 \
-rawaudio rate=96000 \
radio://frequency/capture
 
+
 Module Parameters
 =
 After loading the module, you still have access to some of them in the sysfs
@@ -111,9 +111,6 @@ currently under discussion.
 There is an USB interface for downloading/uploading new firmware images. 
Support
 for it can be implemented using the request_firmware interface.
 
-There is a RDS interrupt mode. The driver is already using the same interface
-for polling RDS information, but is currently not using the interrupt mode.
-
 There is a LED interface, which can be used to override the LED control
 programmed in the firmware. This can be made available using the LED support
 functions in the kernel.
@@ -122,3 +119,91 @@ functions in the kernel.
 Other useful information and links
 ==
 http://www.silabs.com/usbradio
+
+
+History
+===
+2008-01-12 Tobias Lorenz tobias.lor...@gmx.net
+   Version 1.0.0
+   - First working version
+2008-01-13 Tobias Lorenz tobias.lor...@gmx.net
+   Version 1.0.1
+   - Improved error handling, every function now returns errno
+   - Improved multi user access (start/mute/stop)
+   - Channel doesn't get lost anymore after start/mute/stop
+   - RDS support added (polling mode via interrupt EP 1)
+   - marked default module parameters with *value*
+   - switched from bit structs to bit masks
+   - header file cleaned and integrated
+2008-01-14 Tobias Lorenz tobias.lor...@gmx.net
+   Version 1.0.2
+   - hex values are now lower case
+   - commented USB ID for ADS/Tech moved on todo list
+   - blacklisted si470x in hid-quirks.c
+   - rds buffer handling functions integrated into *_work, *_read
+   - rds_command in si470x_poll exchanged against simple retval
+   - check for firmware version 15
+   - code order and prototypes still remain the same
+   - spacing and bottom of band codes remain the same
+2008-01-16 Tobias Lorenz tobias.lor...@gmx.net
+   Version 1.0.3
+   - code reordered to avoid function prototypes
+   - switch/case defaults are now more user-friendly
+   - unified comment style
+   - applied all checkpatch.pl v1.12 suggestions
+ except the warning about the too long lines with bit comments
+   - renamed FMRADIO to RADIO to cut line length (checkpatch.pl)
+2008-01-22 Tobias Lorenz tobias.lor...@gmx.net
+   Version 1.0.4
+   - avoid poss. locking when doing copy_to_user which may sleep
+   - RDS is automatically activated on read now
+   - code cleaned of unnecessary rds_commands
+   - USB Vendor/Product ID for ADS/Tech FM Radio Receiver verified
+ (thanks to Guillaume RAMOUSSE)
+2008-01-27 Tobias Lorenz tobias.lor...@gmx.net
+   Version 1.0.5
+   - number of seek_retries changed to tune_timeout
+   - fixed problem with incomplete tune operations by own buffers
+   - optimization of variables and printf types
+   - improved error logging
+2008-01-31 Tobias Lorenz tobias.lor...@gmx.net
+   Oliver Neukum oli...@neukum.org
+   Version 1.0.6
+   - fixed coverity checker warnings in *_usb_driver_disconnect
+   - probe()/open() race by correct ordering in probe()
+   - DMA coherency rules by separate allocation of all buffers
+   - use of endianness macros
+   - abuse of spinlock, replaced by mutex
+   - racy handling of timer in disconnect,
+ replaced by delayed_work
+   - racy interruptible_sleep_on(),
+ replaced with wait_event_interruptible()
+   - handle

[PATCH 6/6] removement of locking mechanisms

2011-05-01 Thread Tobias Lorenz
This patch minimized the use of locking.
Basically locking is only required where open/close/disconnect is done.

Interfering calls usually happen only to rds read/write operations.
The code for ring buffer handling is changed in a way that makes locking there 
unnecessary.
In case of extensive compiler optimization, the worst that can happen is 
dropped new data or redundant read of data.

The good thing is that the clicking noise problem seems finally resolved with 
that patch!

Signed-off-by: Tobias Lorenz tobias.lor...@gmx.net
---
 drivers/media/radio/si470x/radio-si470x-common.c |   39 +
 drivers/media/radio/si470x/radio-si470x-i2c.c|   16 ++---
 drivers/media/radio/si470x/radio-si470x-usb.c|   19 +++
 drivers/media/radio/si470x/radio-si470x.h|2 +-
 4 files changed, 34 insertions(+), 42 deletions(-)

diff --git a/drivers/media/radio/si470x/radio-si470x-common.c 
b/drivers/media/radio/si470x/radio-si470x-common.c
index 60bd95d..b184292 100644
--- a/drivers/media/radio/si470x/radio-si470x-common.c
+++ b/drivers/media/radio/si470x/radio-si470x-common.c
@@ -347,7 +347,8 @@ static ssize_t si470x_fops_read(struct file *file, char 
__user *buf,
 {
struct si470x_device *radio = video_drvdata(file);
int retval = 0;
-   unsigned int block_count = 0;
+   size_t copied = 0;
+   unsigned int new_rd_index = 0;
 
/* switch on rds reception */
if ((radio-registers[SYSCONFIG1]  SYSCONFIG1_RDS) == 0)
@@ -366,31 +367,28 @@ static ssize_t si470x_fops_read(struct file *file, char 
__user *buf,
}
}
 
-   /* calculate block count from byte count */
-   count /= 3;
-
/* copy RDS block out of internal buffer and to user buffer */
-   mutex_lock(radio-lock);
-   while (block_count  count) {
+   while (copied  count) {
if (radio-rd_index == radio-wr_index)
break;
 
-   /* always transfer rds complete blocks */
+   /* always transfer complete rds blocks */
if (copy_to_user(buf, radio-buffer[radio-rd_index], 3))
/* retval = -EFAULT; */
break;
 
/* increment and wrap read pointer */
-   radio-rd_index += 3;
-   if (radio-rd_index = radio-buf_size)
+   new_rd_index = radio-rd_index + 3;
+   if (new_rd_index  radio-buf_size)
+   radio-rd_index = new_rd_index;
+   else
radio-rd_index = 0;
 
/* increment counters */
-   block_count++;
+   copied += 3;
buf += 3;
-   retval += 3;
}
-   mutex_unlock(radio-lock);
+   retval = copied;
 
 done:
return retval;
@@ -407,11 +405,8 @@ static unsigned int si470x_fops_poll(struct file *file,
int retval = 0;
 
/* 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);
 
@@ -485,7 +480,6 @@ static int si470x_vidioc_g_ctrl(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)
@@ -509,7 +503,6 @@ done:
dev_warn(radio-videodev-dev,
get control failed with %d\n, retval);
 
-   mutex_unlock(radio-lock);
return retval;
 }
 
@@ -523,7 +516,6 @@ static int si470x_vidioc_s_ctrl(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)
@@ -550,7 +542,6 @@ done:
if (retval  0)
dev_warn(radio-videodev-dev,
set control failed with %d\n, retval);
-   mutex_unlock(radio-lock);
return retval;
 }
 
@@ -580,7 +571,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)
@@ -650,7 +640,6 @@ done:
if (retval  0)
dev_warn(radio-videodev-dev,
get tuner failed with %d\n, retval);
-   mutex_unlock(radio-lock);
return retval;
 }
 
@@ -664,7 +653,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

[PATCH] fix of mutex locking bug in fops_read

2011-03-14 Thread Tobias Lorenz
This patch fixes a mutex locking bug causing userspace processes
to hang indefinitely upon reading the radio device for RDS data.

Signed-off-by: Nils Faerber nils.faer...@kernelconcepts.de
Acked-by: Tobias Lorenz tobias.lor...@gmx.net
---
 drivers/media/radio/si470x/radio-si470x-common.c |1 -
 1 files changed, 0 insertions(+), 1 deletions(-)

diff --git a/drivers/media/radio/si470x/radio-si470x-common.c
b/drivers/media/radio/si470x/radio-si470x-common.c
index 4c69698..41ee757 100644
--- a/drivers/media/radio/si470x/radio-si470x-common.c
+++ b/drivers/media/radio/si470x/radio-si470x-common.c
@@ -483,7 +483,6 @@ static ssize_t si470x_fops_read(struct file *file,
char __user *buf,
count /= 3;
 
/* copy RDS block out of internal buffer and to user buffer */
-   mutex_lock(radio-lock);
while (block_count  count) {
if (radio-rd_index == radio-wr_index)
break;
-- 
1.7.2.3


--
To unsubscribe from this list: send the line unsubscribe linux-media in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 1/1] Media: radio: si470x: remove double mutex lock

2011-01-23 Thread Tobias Lorenz
Hi,

good catch! Thanks.

Acked-by: Tobias Lorenz tobias.lor...@gmx.net

Bye,
Toby

On Sun, 23 Jan 2011 12:16:54 +0300, Alexander Strakh croml...@gmail.com
wrote:
 From: Alexander Strakh croml...@gmail.com
 
 
 1. First mutex_lock on radio-lock in line 441
 2. Second in line 462
 
 I think that mutex in line 462 is not needed. In kernel v2.6.36.3
function
 si470
 x_rds_on contains mutex_lock/mutex_unlock. Have no mutex_lock in line
441.
 In kernel v2.6.37 mutex_lock/mutex_unlock has been moved from
si470x_rds_on
 to fops_read. But old mutex_lock (line 462) forgot to remove. 
 
  433static ssize_t si470x_fops_read(struct file *file, char __user *buf,
  434size_t count, loff_t *ppos)
  435{
 
  441mutex_lock(radio-lock);
  442if ((radio-registers[SYSCONFIG1]  SYSCONFIG1_RDS) == 0)
  443si470x_rds_on(radio);
  444
  445/* block if no new data available */
  446while (radio-wr_index == radio-rd_index) {
  447if (file-f_flags  O_NONBLOCK) {
  448retval = -EWOULDBLOCK;
  449goto done;
  450}
  451if (wait_event_interruptible(radio-read_queue,
  452radio-wr_index != radio-rd_index)  0) {
  453retval = -EINTR;
  454goto done;
  455}
  456}
  457
  458/* calculate block count from byte count */
  459count /= 3;
  460
  461/* copy RDS block out of internal buffer and to user buffer
*/
  462mutex_lock(radio-lock);
 
 Found by Linux Device Drivers Verification Project
 
 Remove second mutex_lock from fops_read
 
 Signed-off-by: Alexander Strakh str...@ispras.ru
 ---
  drivers/media/radio/si470x/radio-si470x-common.c |1 -
  1 files changed, 0 insertions(+), 1 deletions(-)
 
 diff --git a/drivers/media/radio/si470x/radio-si470x-common.c
 b/drivers/media/radio/si470x/radio-si470x-common.c
 index 60c176f..38ae6cd 100644
 --- a/drivers/media/radio/si470x/radio-si470x-common.c
 +++ b/drivers/media/radio/si470x/radio-si470x-common.c
 @@ -460,7 +460,6 @@ static ssize_t si470x_fops_read(struct file *file,
 char __user *buf,
   count /= 3;
  
   /* copy RDS block out of internal buffer and to user buffer */
 - mutex_lock(radio-lock);
   while (block_count  count) {
   if (radio-rd_index == radio-wr_index)
   break;
--
To unsubscribe from this list: send the line unsubscribe linux-media in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PULL] radio-si470x

2011-01-09 Thread Tobias Lorenz
Hi Mauro,

Please pull from http://linuxtv.org/hg/~tlorenz/v4l-dvb

for the following 5 changesets:

01/05: The de-emphasis should be setted if requested by module parameter
http://linuxtv.org/hg/~tlorenz/v4l-dvb/rev/b29f01f1b11d

02/05: The si470x i2c and usb driver support the RDS, so this ifdef statement
http://linuxtv.org/hg/~tlorenz/v4l-dvb/rev/74bf5826ae4e

03/05: We should go to err_video instead of err_all if this error is occured
http://linuxtv.org/hg/~tlorenz/v4l-dvb/rev/7ea10526e134

04/05: V4L/DVB: radio-si470x: remove the BKL lock used internally at the driver
http://linuxtv.org/hg/~tlorenz/v4l-dvb/rev/9ddfe7347b9a

05/05: V4L/DVB: radio-si470x: use unlocked ioctl
http://linuxtv.org/hg/~tlorenz/v4l-dvb/rev/87712135ac8d

Thanks,
Tobias
--
To unsubscribe from this list: send the line unsubscribe linux-media in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: Status of the patches under review at LMML (60 patches)

2010-07-08 Thread Tobias Lorenz
Hi Mauro,

   == Waiting for Tobias Lorenz tobias.lor...@gmx.net review == 
 
 Feb, 3 2010: radio-si470x-common: -EINVAL overwritten in 
 si470x_vidioc_s_tuner()http://patchwork.kernel.org/patch/76786

This patch was superseded by the following patch:

http://linuxtv.org/hg/~tlorenz/v4l-dvb/raw-rev/72a2f38d5956

Please use this instead.

Bye,
Toby
--
To unsubscribe from this list: send the line unsubscribe linux-media in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] radio-si470x-common: -EINVAL overwritten in si470x_vidioc_s_tuner()

2010-02-18 Thread Tobias Lorenz
Hello Mauro,

  no, the default value of retval makes no difference to the function.
  
  Retval is set by si470x_disconnect_check and si470x_set_register.
  After each call, retval is checked.
  There is no need to reset it passed.

 You may just do then:
 
   int retval = si470x_disconnect_check(radio);

In all other set/get functions of v4l2_ioctl_ops in the driver, I just set the 
default value of retval to 0.
To be identical in si470x_vidioc_s_tuner, I modified the patch to the one below.
I already pushed this and another cosmetic patch into mercurial:

http://linuxtv.org/hg/~tlorenz/v4l-dvb/rev/72a2f38d5956
http://linuxtv.org/hg/~tlorenz/v4l-dvb/rev/3efd5d32a618

Mauro, can you pull them?

Bye,
Tobias

--- a/linux/drivers/media/radio/si470x/radio-si470x-common.cThu Feb 11 
23:11:30 2010 -0200
+++ b/linux/drivers/media/radio/si470x/radio-si470x-common.cThu Feb 18 
20:31:33 2010 +0100
@@ -748,7 +748,7 @@
struct v4l2_tuner *tuner)
 {
struct si470x_device *radio = video_drvdata(file);
-   int retval = -EINVAL;
+   int retval = 0;
 
/* safety checks */
retval = si470x_disconnect_check(radio);
--
To unsubscribe from this list: send the line unsubscribe linux-media in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] radio-si470x-common: -EINVAL overwritten in si470x_vidioc_s_tuner()

2010-02-03 Thread Tobias Lorenz
Hello Roel,

no, the default value of retval makes no difference to the function.

Retval is set by si470x_disconnect_check and si470x_set_register.
After each call, retval is checked.
There is no need to reset it passed.

The only reason, there is a default value is my static code checker, saying 
variables should have default values.
Setting it to -EINVAL seems more reasonable to me than setting it 0.
In fact the patch would bring up the warning on setting default values again.

Bye,
Toby

Am Mittwoch 03 Februar 2010 20:48:05 schrieb Roel Kluin:
 The -EINVAL was overwritten by the si470x_disconnect_check().
 
 Signed-off-by: Roel Kluin roel.kl...@gmail.com
 ---
 Is this needed?
 
 diff --git a/drivers/media/radio/si470x/radio-si470x-common.c 
 b/drivers/media/radio/si470x/radio-si470x-common.c
 index 4da0f15..65b4a92 100644
 --- a/drivers/media/radio/si470x/radio-si470x-common.c
 +++ b/drivers/media/radio/si470x/radio-si470x-common.c
 @@ -748,12 +748,13 @@ static int si470x_vidioc_s_tuner(struct file *file, 
 void *priv,
   struct v4l2_tuner *tuner)
  {
   struct si470x_device *radio = video_drvdata(file);
 - int retval = -EINVAL;
 + int retval;
  
   /* safety checks */
   retval = si470x_disconnect_check(radio);
   if (retval)
   goto done;
 + retval = -EINVAL;
  
   if (tuner-index != 0)
   goto done;
 
--
To unsubscribe from this list: send the line unsubscribe linux-media in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v2 1/3] radio-si470x: move some file operations to common file

2009-12-09 Thread Tobias Lorenz
Hi,

good patch. This saves quite some code in the I2C part of the driver...

Acked-by: Tobias Lorenz tobias.lor...@gmx.net

Bye,
Toby

Am Donnerstag 03 Dezember 2009 13:57:22 schrieb Joonyoung Shim:
 The read and poll file operations of the si470x usb driver can be used
 also equally on the si470x i2c driver, so they go to the common file.
 
 Signed-off-by: Joonyoung Shim jy0922.s...@samsung.com
 ---
  drivers/media/radio/si470x/radio-si470x-common.c |   98 
 ++
  drivers/media/radio/si470x/radio-si470x-i2c.c|   15 +---
  drivers/media/radio/si470x/radio-si470x-usb.c|   97 
 +-
  drivers/media/radio/si470x/radio-si470x.h|3 +-
  4 files changed, 104 insertions(+), 109 deletions(-)
 
 diff --git a/drivers/media/radio/si470x/radio-si470x-common.c 
 b/drivers/media/radio/si470x/radio-si470x-common.c
 index 7296cf4..f4645d4 100644
 --- a/drivers/media/radio/si470x/radio-si470x-common.c
 +++ b/drivers/media/radio/si470x/radio-si470x-common.c
 @@ -426,6 +426,104 @@ int si470x_rds_on(struct si470x_device *radio)
  
  
  /**
 + * File Operations Interface
 + **/
 +
 +/*
 + * si470x_fops_read - read RDS data
 + */
 +static ssize_t si470x_fops_read(struct file *file, char __user *buf,
 + size_t count, loff_t *ppos)
 +{
 + struct si470x_device *radio = video_drvdata(file);
 + int retval = 0;
 + unsigned int block_count = 0;
 +
 + /* switch on rds reception */
 + if ((radio-registers[SYSCONFIG1]  SYSCONFIG1_RDS) == 0)
 + si470x_rds_on(radio);
 +
 + /* block if no new data available */
 + while (radio-wr_index == radio-rd_index) {
 + if (file-f_flags  O_NONBLOCK) {
 + retval = -EWOULDBLOCK;
 + goto done;
 + }
 + if (wait_event_interruptible(radio-read_queue,
 + radio-wr_index != radio-rd_index)  0) {
 + retval = -EINTR;
 + goto done;
 + }
 + }
 +
 + /* calculate block count from byte count */
 + count /= 3;
 +
 + /* copy RDS block out of internal buffer and to user buffer */
 + mutex_lock(radio-lock);
 + while (block_count  count) {
 + if (radio-rd_index == radio-wr_index)
 + break;
 +
 + /* always transfer rds complete blocks */
 + if (copy_to_user(buf, radio-buffer[radio-rd_index], 3))
 + /* retval = -EFAULT; */
 + break;
 +
 + /* increment and wrap read pointer */
 + radio-rd_index += 3;
 + if (radio-rd_index = radio-buf_size)
 + radio-rd_index = 0;
 +
 + /* increment counters */
 + block_count++;
 + buf += 3;
 + retval += 3;
 + }
 + mutex_unlock(radio-lock);
 +
 +done:
 + return retval;
 +}
 +
 +
 +/*
 + * si470x_fops_poll - poll RDS data
 + */
 +static unsigned int si470x_fops_poll(struct file *file,
 + struct poll_table_struct *pts)
 +{
 + struct si470x_device *radio = video_drvdata(file);
 + int retval = 0;
 +
 + /* switch on rds reception */
 + if ((radio-registers[SYSCONFIG1]  SYSCONFIG1_RDS) == 0)
 + si470x_rds_on(radio);
 +
 + poll_wait(file, radio-read_queue, pts);
 +
 + if (radio-rd_index != radio-wr_index)
 + retval = POLLIN | POLLRDNORM;
 +
 + return retval;
 +}
 +
 +
 +/*
 + * si470x_fops - file operations interface
 + */
 +static const struct v4l2_file_operations si470x_fops = {
 + .owner  = THIS_MODULE,
 + .read   = si470x_fops_read,
 + .poll   = si470x_fops_poll,
 + .ioctl  = video_ioctl2,
 + .open   = si470x_fops_open,
 + .release= si470x_fops_release,
 +};
 +
 +
 +
 +/**
   * Video4Linux Interface
   **/
  
 diff --git a/drivers/media/radio/si470x/radio-si470x-i2c.c 
 b/drivers/media/radio/si470x/radio-si470x-i2c.c
 index 2d53b6a..4816a6d 100644
 --- a/drivers/media/radio/si470x/radio-si470x-i2c.c
 +++ b/drivers/media/radio/si470x/radio-si470x-i2c.c
 @@ -173,7 +173,7 @@ int si470x_disconnect_check(struct si470x_device *radio)
  /*
   * si470x_fops_open - file open
   */
 -static int si470x_fops_open(struct file *file)
 +int si470x_fops_open(struct file *file)
  {
   struct si470x_device *radio = video_drvdata(file);
   int retval = 0;
 @@ -194,7 +194,7 @@ static int si470x_fops_open(struct file *file)
  /*
   * si470x_fops_release - file release
   */
 -static int si470x_fops_release(struct file *file)
 +int si470x_fops_release(struct file

Re: [PATCH v2 2/3] radio-si470x: support RDS on si470x i2c driver

2009-12-09 Thread Tobias Lorenz
Hi,

I'm unable to test the functionality, due to missing devices.
But the code compiles cleanly.

Acked-by: Tobias Lorenz tobias.lor...@gmx.net

Bye,
Toby

Am Donnerstag 03 Dezember 2009 13:57:27 schrieb Joonyoung Shim:
 This patch is to support RDS on si470x i2c driver. The routine of RDS
 operation is almost same with thing of usb driver, but this uses RDS
 interrupt.
 
 Signed-off-by: Joonyoung Shim jy0922.s...@samsung.com
 ---
  drivers/media/radio/si470x/radio-si470x-i2c.c |  164 
 +++--
  drivers/media/radio/si470x/radio-si470x.h |1 +
  2 files changed, 155 insertions(+), 10 deletions(-)
 
 diff --git a/drivers/media/radio/si470x/radio-si470x-i2c.c 
 b/drivers/media/radio/si470x/radio-si470x-i2c.c
 index 6a40db8..5466015 100644
 --- a/drivers/media/radio/si470x/radio-si470x-i2c.c
 +++ b/drivers/media/radio/si470x/radio-si470x-i2c.c
 @@ -22,22 +22,17 @@
   */
  
  
 -/*
 - * ToDo:
 - * - RDS support
 - */
 -
 -
  /* driver definitions */
  #define DRIVER_AUTHOR Joonyoung Shim jy0922.s...@samsung.com;
 -#define DRIVER_KERNEL_VERSION KERNEL_VERSION(1, 0, 0)
 +#define DRIVER_KERNEL_VERSION KERNEL_VERSION(1, 0, 1)
  #define DRIVER_CARD Silicon Labs Si470x FM Radio Receiver
  #define DRIVER_DESC I2C radio driver for Si470x FM Radio Receivers
 -#define DRIVER_VERSION 1.0.0
 +#define DRIVER_VERSION 1.0.1
  
  /* kernel includes */
  #include linux/i2c.h
  #include linux/delay.h
 +#include linux/interrupt.h
  
  #include radio-si470x.h
  
 @@ -62,6 +57,20 @@ static int radio_nr = -1;
  module_param(radio_nr, int, 0444);
  MODULE_PARM_DESC(radio_nr, Radio Nr);
  
 +/* RDS buffer blocks */
 +static unsigned int rds_buf = 100;
 +module_param(rds_buf, uint, 0444);
 +MODULE_PARM_DESC(rds_buf, RDS buffer entries: *100*);
 +
 +/* RDS maximum block errors */
 +static unsigned short max_rds_errors = 1;
 +/* 0 means   0  errors requiring correction */
 +/* 1 means 1-2  errors requiring correction (used by original USBRadio.exe) 
 */
 +/* 2 means 3-5  errors requiring correction */
 +/* 3 means   6+ errors or errors in checkword, correction not possible */
 +module_param(max_rds_errors, ushort, 0644);
 +MODULE_PARM_DESC(max_rds_errors, RDS maximum block errors: *1*);
 +
  
  
  /**
 @@ -181,12 +190,21 @@ int si470x_fops_open(struct file *file)
   mutex_lock(radio-lock);
   radio-users++;
  
 - if (radio-users == 1)
 + if (radio-users == 1) {
   /* start radio */
   retval = si470x_start(radio);
 + if (retval  0)
 + goto done;
 +
 + /* enable RDS interrupt */
 + radio-registers[SYSCONFIG1] |= SYSCONFIG1_RDSIEN;
 + radio-registers[SYSCONFIG1] = ~SYSCONFIG1_GPIO2;
 + radio-registers[SYSCONFIG1] |= 0x1  2;
 + retval = si470x_set_register(radio, SYSCONFIG1);
 + }
  
 +done:
   mutex_unlock(radio-lock);
 -
   return retval;
  }
  
 @@ -242,6 +260,105 @@ int si470x_vidioc_querycap(struct file *file, void 
 *priv,
   **/
  
  /*
 + * si470x_i2c_interrupt_work - rds processing function
 + */
 +static void si470x_i2c_interrupt_work(struct work_struct *work)
 +{
 + struct si470x_device *radio = container_of(work,
 + struct si470x_device, radio_work);
 + unsigned char regnr;
 + unsigned char blocknum;
 + unsigned short bler; /* rds block errors */
 + unsigned short rds;
 + unsigned char tmpbuf[3];
 + int retval = 0;
 +
 + /* safety checks */
 + if ((radio-registers[SYSCONFIG1]  SYSCONFIG1_RDS) == 0)
 + return;
 +
 + /* Update RDS registers */
 + for (regnr = 0; regnr  RDS_REGISTER_NUM; regnr++) {
 + retval = si470x_get_register(radio, STATUSRSSI + regnr);
 + if (retval  0)
 + return;
 + }
 +
 + /* get rds blocks */
 + if ((radio-registers[STATUSRSSI]  STATUSRSSI_RDSR) == 0)
 + /* No RDS group ready, better luck next time */
 + return;
 +
 + for (blocknum = 0; blocknum  4; blocknum++) {
 + switch (blocknum) {
 + default:
 + bler = (radio-registers[STATUSRSSI] 
 + STATUSRSSI_BLERA)  9;
 + rds = radio-registers[RDSA];
 + break;
 + case 1:
 + bler = (radio-registers[READCHAN] 
 + READCHAN_BLERB)  14;
 + rds = radio-registers[RDSB];
 + break;
 + case 2:
 + bler = (radio-registers[READCHAN] 
 + READCHAN_BLERC)  12;
 + rds = radio-registers[RDSC];
 + break;
 + case 3:
 + bler = (radio-registers[READCHAN

Re: [PATCH v2 3/3] radio-si470x: support PM functions

2009-12-09 Thread Tobias Lorenz
Hi,

the same here. I'm unable to test it, but it compiles cleanly.

Acked-by: Tobias Lorenz tobias.lor...@gmx.net

Bye,
Toby

Am Donnerstag 03 Dezember 2009 13:57:29 schrieb Joonyoung Shim:
 This patch is to support PM of the si470x i2c driver.
 
 Signed-off-by: Joonyoung Shim jy0922.s...@samsung.com
 ---
  drivers/media/radio/si470x/radio-si470x-i2c.c |   40 
 +
  1 files changed, 40 insertions(+), 0 deletions(-)
 
 diff --git a/drivers/media/radio/si470x/radio-si470x-i2c.c 
 b/drivers/media/radio/si470x/radio-si470x-i2c.c
 index 77532e6..4c6e586 100644
 --- a/drivers/media/radio/si470x/radio-si470x-i2c.c
 +++ b/drivers/media/radio/si470x/radio-si470x-i2c.c
 @@ -486,6 +486,44 @@ static __devexit int si470x_i2c_remove(struct i2c_client 
 *client)
  }
  
  
 +#ifdef CONFIG_PM
 +/*
 + * si470x_i2c_suspend - suspend the device
 + */
 +static int si470x_i2c_suspend(struct i2c_client *client, pm_message_t mesg)
 +{
 + struct si470x_device *radio = i2c_get_clientdata(client);
 +
 + /* power down */
 + radio-registers[POWERCFG] |= POWERCFG_DISABLE;
 + if (si470x_set_register(radio, POWERCFG)  0)
 + return -EIO;
 +
 + return 0;
 +}
 +
 +
 +/*
 + * si470x_i2c_resume - resume the device
 + */
 +static int si470x_i2c_resume(struct i2c_client *client)
 +{
 + struct si470x_device *radio = i2c_get_clientdata(client);
 +
 + /* power up : need 110ms */
 + radio-registers[POWERCFG] |= POWERCFG_ENABLE;
 + if (si470x_set_register(radio, POWERCFG)  0)
 + return -EIO;
 + msleep(110);
 +
 + return 0;
 +}
 +#else
 +#define si470x_i2c_suspend   NULL
 +#define si470x_i2c_resumeNULL
 +#endif
 +
 +
  /*
   * si470x_i2c_driver - i2c driver interface
   */
 @@ -496,6 +534,8 @@ static struct i2c_driver si470x_i2c_driver = {
   },
   .probe  = si470x_i2c_probe,
   .remove = __devexit_p(si470x_i2c_remove),
 + .suspend= si470x_i2c_suspend,
 + .resume = si470x_i2c_resume,
   .id_table   = si470x_i2c_id,
  };
  
 
--
To unsubscribe from this list: send the line unsubscribe linux-media in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 2/3] radio-si470x: move some file operations to common file

2009-12-01 Thread Tobias Lorenz
Hi,

yes, good point.

Acked-by: Tobias Lorenz tobias.lor...@gmx.net

Bye,
Toby

Am Mittwoch 18 November 2009 07:21:30 schrieb Joonyoung Shim:
 The read and poll file operations of the si470x usb driver can be used
 also equally on the si470x i2c driver, so they go to the common file.
 
 Signed-off-by: Joonyoung Shim jy0922.s...@samsung.com
 ---
  drivers/media/radio/si470x/radio-si470x-common.c |   98 
 ++
  drivers/media/radio/si470x/radio-si470x-i2c.c|   15 +---
  drivers/media/radio/si470x/radio-si470x-usb.c|   97 
 +-
  drivers/media/radio/si470x/radio-si470x.h|3 +-
  4 files changed, 104 insertions(+), 109 deletions(-)
 
 diff --git a/drivers/media/radio/si470x/radio-si470x-common.c 
 b/drivers/media/radio/si470x/radio-si470x-common.c
 index 7296cf4..f4645d4 100644
 --- a/drivers/media/radio/si470x/radio-si470x-common.c
 +++ b/drivers/media/radio/si470x/radio-si470x-common.c
 @@ -426,6 +426,104 @@ int si470x_rds_on(struct si470x_device *radio)
  
  
  /**
 + * File Operations Interface
 + **/
 +
 +/*
 + * si470x_fops_read - read RDS data
 + */
 +static ssize_t si470x_fops_read(struct file *file, char __user *buf,
 + size_t count, loff_t *ppos)
 +{
 + struct si470x_device *radio = video_drvdata(file);
 + int retval = 0;
 + unsigned int block_count = 0;
 +
 + /* switch on rds reception */
 + if ((radio-registers[SYSCONFIG1]  SYSCONFIG1_RDS) == 0)
 + si470x_rds_on(radio);
 +
 + /* block if no new data available */
 + while (radio-wr_index == radio-rd_index) {
 + if (file-f_flags  O_NONBLOCK) {
 + retval = -EWOULDBLOCK;
 + goto done;
 + }
 + if (wait_event_interruptible(radio-read_queue,
 + radio-wr_index != radio-rd_index)  0) {
 + retval = -EINTR;
 + goto done;
 + }
 + }
 +
 + /* calculate block count from byte count */
 + count /= 3;
 +
 + /* copy RDS block out of internal buffer and to user buffer */
 + mutex_lock(radio-lock);
 + while (block_count  count) {
 + if (radio-rd_index == radio-wr_index)
 + break;
 +
 + /* always transfer rds complete blocks */
 + if (copy_to_user(buf, radio-buffer[radio-rd_index], 3))
 + /* retval = -EFAULT; */
 + break;
 +
 + /* increment and wrap read pointer */
 + radio-rd_index += 3;
 + if (radio-rd_index = radio-buf_size)
 + radio-rd_index = 0;
 +
 + /* increment counters */
 + block_count++;
 + buf += 3;
 + retval += 3;
 + }
 + mutex_unlock(radio-lock);
 +
 +done:
 + return retval;
 +}
 +
 +
 +/*
 + * si470x_fops_poll - poll RDS data
 + */
 +static unsigned int si470x_fops_poll(struct file *file,
 + struct poll_table_struct *pts)
 +{
 + struct si470x_device *radio = video_drvdata(file);
 + int retval = 0;
 +
 + /* switch on rds reception */
 + if ((radio-registers[SYSCONFIG1]  SYSCONFIG1_RDS) == 0)
 + si470x_rds_on(radio);
 +
 + poll_wait(file, radio-read_queue, pts);
 +
 + if (radio-rd_index != radio-wr_index)
 + retval = POLLIN | POLLRDNORM;
 +
 + return retval;
 +}
 +
 +
 +/*
 + * si470x_fops - file operations interface
 + */
 +static const struct v4l2_file_operations si470x_fops = {
 + .owner  = THIS_MODULE,
 + .read   = si470x_fops_read,
 + .poll   = si470x_fops_poll,
 + .ioctl  = video_ioctl2,
 + .open   = si470x_fops_open,
 + .release= si470x_fops_release,
 +};
 +
 +
 +
 +/**
   * Video4Linux Interface
   **/
  
 diff --git a/drivers/media/radio/si470x/radio-si470x-i2c.c 
 b/drivers/media/radio/si470x/radio-si470x-i2c.c
 index 2d53b6a..4816a6d 100644
 --- a/drivers/media/radio/si470x/radio-si470x-i2c.c
 +++ b/drivers/media/radio/si470x/radio-si470x-i2c.c
 @@ -173,7 +173,7 @@ int si470x_disconnect_check(struct si470x_device *radio)
  /*
   * si470x_fops_open - file open
   */
 -static int si470x_fops_open(struct file *file)
 +int si470x_fops_open(struct file *file)
  {
   struct si470x_device *radio = video_drvdata(file);
   int retval = 0;
 @@ -194,7 +194,7 @@ static int si470x_fops_open(struct file *file)
  /*
   * si470x_fops_release - file release
   */
 -static int si470x_fops_release(struct file *file)
 +int si470x_fops_release(struct file *file)
  {
   struct si470x_device *radio

Re: [v4l-dvb-maintainer] [PULL] radio-si470x: I2C support

2009-08-14 Thread Tobias Lorenz
Hi Mauro,

 Could you please verify if everything is correct at my git tree:
 
 http://git.kernel.org/?p=linux/kernel/git/mchehab/linux-next.git;a=shortlog

Yes. It looks okay. Thanks,
Toby
--
To unsubscribe from this list: send the line unsubscribe linux-media in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v2 0/4] radio-si470x: separate usb and i2c interface

2009-08-09 Thread Tobias Lorenz
Hi,

 I am concerned about one thing. I cannot test the si470x usb radio 
 driver because i don't have the si470x usb radio device, so i believe
 you would have probably tested it.

It is working. I tested it with the most common radio applications and with 
some RDS decoders.

As the I2C part is working, I will send Mauro a pull request.

  The patch 1/4 is for separating common and usb code.
  The patch 2/4 is about using dev_* macro instead of printk.
  The patch 3/4 is about adding disconnect check function for i2c interface.
  The patch 4/4 is for supporting si470x i2c interface.

Bye,
Toby
--
To unsubscribe from this list: send the line unsubscribe linux-media in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v2 2/4] radio-si470x: change to dev_* macro from printk

2009-07-30 Thread Tobias Lorenz
Hi,

Acked-by: Tobias Lorenz tobias.lor...@gmx.net

Bye,
Toby

On Tuesday 14 July 2009 07:11:44 Joonyoung Shim wrote:
 This patch is for using dev_* macro instead of printk.
 
 Signed-off-by: Joonyoung Shim jy0922.s...@samsung.com
 ---
  .../media/radio/si470x/radio-si470x-common.c   |   50 +-
  .../drivers/media/radio/si470x/radio-si470x-usb.c  |   58 
 +---
  2 files changed, 52 insertions(+), 56 deletions(-)
 
 diff --git a/linux/drivers/media/radio/si470x/radio-si470x-common.c 
 b/linux/drivers/media/radio/si470x/radio-si470x-common.c
 index d2dc1ff..2be22bd 100644
 --- a/linux/drivers/media/radio/si470x/radio-si470x-common.c
 +++ b/linux/drivers/media/radio/si470x/radio-si470x-common.c
 @@ -184,10 +184,10 @@ static int si470x_set_chan(struct si470x_device *radio, 
 unsigned short chan)
   } while (((radio-registers[STATUSRSSI]  STATUSRSSI_STC) == 0) 
   (!timed_out));
   if ((radio-registers[STATUSRSSI]  STATUSRSSI_STC) == 0)
 - printk(KERN_WARNING DRIVER_NAME : tune does not complete\n);
 + dev_warn(radio-videodev-dev, tune does not complete\n);
   if (timed_out)
 - printk(KERN_WARNING DRIVER_NAME
 - : tune timed out after %u ms\n, tune_timeout);
 + dev_warn(radio-videodev-dev,
 + tune timed out after %u ms\n, tune_timeout);
  
  stop:
   /* stop tuning */
 @@ -320,13 +320,13 @@ static int si470x_set_seek(struct si470x_device *radio,
   } while (((radio-registers[STATUSRSSI]  STATUSRSSI_STC) == 0) 
   (!timed_out));
   if ((radio-registers[STATUSRSSI]  STATUSRSSI_STC) == 0)
 - printk(KERN_WARNING DRIVER_NAME : seek does not complete\n);
 + dev_warn(radio-videodev-dev, seek does not complete\n);
   if (radio-registers[STATUSRSSI]  STATUSRSSI_SF)
 - printk(KERN_WARNING DRIVER_NAME
 - : seek failed / band limit reached\n);
 + dev_warn(radio-videodev-dev,
 + seek failed / band limit reached\n);
   if (timed_out)
 - printk(KERN_WARNING DRIVER_NAME
 - : seek timed out after %u ms\n, seek_timeout);
 + dev_warn(radio-videodev-dev,
 + seek timed out after %u ms\n, seek_timeout);
  
  stop:
   /* stop seeking */
 @@ -435,6 +435,7 @@ int si470x_rds_on(struct si470x_device *radio)
  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 */
 @@ -458,8 +459,8 @@ static int si470x_vidioc_queryctrl(struct file *file, 
 void *priv,
  
  done:
   if (retval  0)
 - printk(KERN_WARNING DRIVER_NAME
 - : query controls failed with %d\n, retval);
 + dev_warn(radio-videodev-dev,
 + query controls failed with %d\n, retval);
   return retval;
  }
  
 @@ -494,8 +495,8 @@ static int si470x_vidioc_g_ctrl(struct file *file, void 
 *priv,
  
  done:
   if (retval  0)
 - printk(KERN_WARNING DRIVER_NAME
 - : get control failed with %d\n, retval);
 + dev_warn(radio-videodev-dev,
 + get control failed with %d\n, retval);
   return retval;
  }
  
 @@ -534,8 +535,8 @@ static int si470x_vidioc_s_ctrl(struct file *file, void 
 *priv,
  
  done:
   if (retval  0)
 - printk(KERN_WARNING DRIVER_NAME
 - : set control failed with %d\n, retval);
 + dev_warn(radio-videodev-dev,
 + set control failed with %d\n, retval);
   return retval;
  }
  
 @@ -632,8 +633,8 @@ static int si470x_vidioc_g_tuner(struct file *file, void 
 *priv,
  
  done:
   if (retval  0)
 - printk(KERN_WARNING DRIVER_NAME
 - : get tuner failed with %d\n, retval);
 + dev_warn(radio-videodev-dev,
 + get tuner failed with %d\n, retval);
   return retval;
  }
  
 @@ -671,8 +672,8 @@ static int si470x_vidioc_s_tuner(struct file *file, void 
 *priv,
  
  done:
   if (retval  0)
 - printk(KERN_WARNING DRIVER_NAME
 - : set tuner failed with %d\n, retval);
 + dev_warn(radio-videodev-dev,
 + set tuner failed with %d\n, retval);
   return retval;
  }
  
 @@ -701,8 +702,8 @@ static int si470x_vidioc_g_frequency(struct file *file, 
 void *priv,
  
  done:
   if (retval  0)
 - printk(KERN_WARNING DRIVER_NAME
 - : get frequency failed with %d\n, retval);
 + dev_warn(radio-videodev-dev,
 + get frequency failed with %d\n, retval);
   return retval;
  }
  
 @@ -730,8 +731,8 @@ static int si470x_vidioc_s_frequency(struct file *file, 
 void *priv

Re: [PATCH v2 4/4] radio-si470x: add i2c driver for si470x

2009-07-30 Thread Tobias Lorenz
Hi,

okay for the moment. We can later think about optimizations, like return 0 
functions.
I have no possibility of testing this functionality. But I guess it works with 
your device, so

Acked-by: Tobias Lorenz tobias.lor...@gmx.net

Bye,
Toby

On Sunday 19 July 2009 16:19:24 Alexey Klimov wrote:
 Hello,
 
 On Tue, Jul 14, 2009 at 9:15 AM, Joonyoung Shimjy0922.s...@samsung.com 
 wrote:
  This patch supports i2c interface of si470x. The i2c specific part
  exists in radio-si470x-i2c.c file and the common part uses
  radio-si470x-common.c file. The '#if defined' is inserted inevitably
  because of parts used only si470x usb in the common file.
 
  The current driver version doesn't support the RDS.
 
  Signed-off-by: Joonyoung Shim jy0922.s...@samsung.com
  ---
   linux/drivers/media/radio/si470x/Kconfig   |   13 +
   linux/drivers/media/radio/si470x/Makefile  |2 +
   .../media/radio/si470x/radio-si470x-common.c   |6 +
   .../drivers/media/radio/si470x/radio-si470x-i2c.c  |  254 
  
   linux/drivers/media/radio/si470x/radio-si470x.h|6 +
   5 files changed, 281 insertions(+), 0 deletions(-)
   create mode 100644 linux/drivers/media/radio/si470x/radio-si470x-i2c.c
 
  diff --git a/linux/drivers/media/radio/si470x/Kconfig 
  b/linux/drivers/media/radio/si470x/Kconfig
  index 20d05c0..a466654 100644
  --- a/linux/drivers/media/radio/si470x/Kconfig
  +++ b/linux/drivers/media/radio/si470x/Kconfig
  @@ -22,3 +22,16 @@ config USB_SI470X
 
   To compile this driver as a module, choose M here: the
   module will be called radio-usb-si470x.
  +
  +config I2C_SI470X
  +   tristate Silicon Labs Si470x FM Radio Receiver support with I2C
  +   depends on I2C  RADIO_SI470X  !USB_SI470X
  +   ---help---
  + This is a driver for I2C devices with the Silicon Labs SI470x
  + chip.
  +
  + Say Y here if you want to connect this type of radio to your
  + computer's I2C port.
  +
  + To compile this driver as a module, choose M here: the
  + module will be called radio-i2c-si470x.
  diff --git a/linux/drivers/media/radio/si470x/Makefile 
  b/linux/drivers/media/radio/si470x/Makefile
  index 3cb777f..0696481 100644
  --- a/linux/drivers/media/radio/si470x/Makefile
  +++ b/linux/drivers/media/radio/si470x/Makefile
  @@ -3,5 +3,7 @@
   #
 
   radio-usb-si470x-objs  := radio-si470x-usb.o radio-si470x-common.o
  +radio-i2c-si470x-objs  := radio-si470x-i2c.o radio-si470x-common.o
 
   obj-$(CONFIG_USB_SI470X) += radio-usb-si470x.o
  +obj-$(CONFIG_I2C_SI470X) += radio-i2c-si470x.o
  diff --git a/linux/drivers/media/radio/si470x/radio-si470x-common.c 
  b/linux/drivers/media/radio/si470x/radio-si470x-common.c
  index 84cbea3..0a48159 100644
  --- a/linux/drivers/media/radio/si470x/radio-si470x-common.c
  +++ b/linux/drivers/media/radio/si470x/radio-si470x-common.c
  @@ -581,8 +581,12 @@ static int si470x_vidioc_g_tuner(struct file *file, 
  void *priv,
 /* driver constants */
 strcpy(tuner-name, FM);
 tuner-type = V4L2_TUNER_RADIO;
  +#if defined(CONFIG_USB_SI470X) || defined(CONFIG_USB_SI470X_MODULE)
 tuner-capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO |
 V4L2_TUNER_CAP_RDS;
  +#else
  +   tuner-capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO;
  +#endif
 
 /* range limits */
 switch ((radio-registers[SYSCONFIG2]  SYSCONFIG2_BAND)  6) {
  @@ -608,10 +612,12 @@ static int si470x_vidioc_g_tuner(struct file *file, 
  void *priv,
 tuner-rxsubchans = V4L2_TUNER_SUB_MONO;
 else
 tuner-rxsubchans = V4L2_TUNER_SUB_MONO | 
  V4L2_TUNER_SUB_STEREO;
  +#if defined(CONFIG_USB_SI470X) || defined(CONFIG_USB_SI470X_MODULE)
 /* If there is a reliable method of detecting an RDS channel,
then this code should check for that before setting this
RDS subchannel. */
 tuner-rxsubchans |= V4L2_TUNER_SUB_RDS;
  +#endif
 
 /* mono/stereo selector */
 if ((radio-registers[POWERCFG]  POWERCFG_MONO) == 0)
  diff --git a/linux/drivers/media/radio/si470x/radio-si470x-i2c.c 
  b/linux/drivers/media/radio/si470x/radio-si470x-i2c.c
  new file mode 100644
  index 000..2181021
  --- /dev/null
  +++ b/linux/drivers/media/radio/si470x/radio-si470x-i2c.c
  @@ -0,0 +1,254 @@
  +/*
  + * drivers/media/radio/si470x/radio-si470x-i2c.c
  + *
  + * I2C driver for radios with Silicon Labs Si470x FM Radio Receivers
  + *
  + * Copyright (C) 2009 Samsung Electronics Co.Ltd
  + * Author: Joonyoung Shim jy0922.s...@samsung.com
  + *
  + *  This program is free software; you can redistribute  it and/or modify 
  it
  + *  under  the terms of  the GNU General  Public License as published by 
  the
  + *  Free Software Foundation;  either version 2 of the  License, or (at 
  your
  + *  option) any later version.
  + *
  + *
  + * TODO:
  + * - RDS support