summary refs log tree commit diff
path: root/drivers/media/radio/radio-sf16fmi.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-07-30 19:03:41 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2012-07-30 19:03:41 -0700
commit6df419e45d71b8d9a0de8e92a1212bbea460f0e0 (patch)
treec0902a96353391400818fe8b7adf11493b56935a /drivers/media/radio/radio-sf16fmi.c
parent27c1ee3f929555b71fa39ec0d81a7e7185de1b16 (diff)
parentc893e7c64e36087dceb4662917976a81d1754fc0 (diff)
downloadlinux-6df419e45d71b8d9a0de8e92a1212bbea460f0e0.tar.gz
Merge branch 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media
Pull media updates from Mauro Carvalho Chehab:
 "This is the first part of the media patches for v3.6.

  This patch series contain:
   - new DVB frontend: rtl2832
   - new video drivers: adv7393
   - some unused files got removed
   - a selection API cleanup between V4L2 and V4L2 subdev API's
   - a major redesign at v4l-ioctl2, in order to clean it up
   - several driver fixes and improvements."

* 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media: (174 commits)
  v4l: Export v4l2-common.h in include/linux/Kbuild
  media: Revert "[media] Terratec Cinergy S2 USB HD Rev.2"
  [media] media: Use pr_info not homegrown pr_reg macro
  [media] Terratec Cinergy S2 USB HD Rev.2
  [media] v4l: Correct conflicting V4L2 subdev selection API documentation
  [media] Feature removal: V4L2 selections API target and flag definitions
  [media] v4l: Unify selection flags documentation
  [media] v4l: Unify selection flags
  [media] v4l: Common documentation for selection targets
  [media] v4l: Unify selection targets across V4L2 and V4L2 subdev interfaces
  [media] v4l: Remove "_ACTUAL" from subdev selection API target definition names
  [media] V4L: Remove "_ACTIVE" from the selection target name definitions
  [media] media: dvb-usb: print mac address via native %pM
  [media] s5p-tv: Use module_i2c_driver in sii9234_drv.c file
  [media] media: gpio-ir-recv: add allowed_protos for platform data
  [media] s5p-jpeg: Use module_platform_driver in jpeg-core.c file
  [media] saa7134: fix spelling of detach in label
  [media] cx88-blackbird: replace ioctl by unlocked_ioctl
  [media] cx88: don't use current_norm
  [media] cx88: fix a number of v4l2-compliance violations
  ...
Diffstat (limited to 'drivers/media/radio/radio-sf16fmi.c')
-rw-r--r--drivers/media/radio/radio-sf16fmi.c61
1 files changed, 25 insertions, 36 deletions
diff --git a/drivers/media/radio/radio-sf16fmi.c b/drivers/media/radio/radio-sf16fmi.c
index a81d723b8c77..8185d5fbfa89 100644
--- a/drivers/media/radio/radio-sf16fmi.c
+++ b/drivers/media/radio/radio-sf16fmi.c
@@ -27,6 +27,7 @@
 #include <linux/io.h>		/* outb, outb_p			*/
 #include <media/v4l2-device.h>
 #include <media/v4l2-ioctl.h>
+#include "lm7000.h"
 
 MODULE_AUTHOR("Petr Vandrovec, vandrove@vc.cvut.cz and M. Kirkwood");
 MODULE_DESCRIPTION("A driver for the SF16-FMI, SF16-FMP and SF16-FMD radio.");
@@ -54,31 +55,33 @@ static struct fmi fmi_card;
 static struct pnp_dev *dev;
 bool pnp_attached;
 
-/* freq is in 1/16 kHz to internal number, hw precision is 50 kHz */
-/* It is only useful to give freq in interval of 800 (=0.05Mhz),
- * other bits will be truncated, e.g 92.7400016 -> 92.7, but
- * 92.7400017 -> 92.75
- */
-#define RSF16_ENCODE(x)	((x) / 800 + 214)
 #define RSF16_MINFREQ (87 * 16000)
 #define RSF16_MAXFREQ (108 * 16000)
 
-static void outbits(int bits, unsigned int data, int io)
+#define FMI_BIT_TUN_CE		(1 << 0)
+#define FMI_BIT_TUN_CLK		(1 << 1)
+#define FMI_BIT_TUN_DATA	(1 << 2)
+#define FMI_BIT_VOL_SW		(1 << 3)
+#define FMI_BIT_TUN_STRQ	(1 << 4)
+
+void fmi_set_pins(void *handle, u8 pins)
 {
-	while (bits--) {
-		if (data & 1) {
-			outb(5, io);
-			udelay(6);
-			outb(7, io);
-			udelay(6);
-		} else {
-			outb(1, io);
-			udelay(6);
-			outb(3, io);
-			udelay(6);
-		}
-		data >>= 1;
-	}
+	struct fmi *fmi = handle;
+	u8 bits = FMI_BIT_TUN_STRQ;
+
+	if (!fmi->mute)
+		bits |= FMI_BIT_VOL_SW;
+
+	if (pins & LM7000_DATA)
+		bits |= FMI_BIT_TUN_DATA;
+	if (pins & LM7000_CLK)
+		bits |= FMI_BIT_TUN_CLK;
+	if (pins & LM7000_CE)
+		bits |= FMI_BIT_TUN_CE;
+
+	mutex_lock(&fmi->lock);
+	outb_p(bits, fmi->io);
+	mutex_unlock(&fmi->lock);
 }
 
 static inline void fmi_mute(struct fmi *fmi)
@@ -95,20 +98,6 @@ static inline void fmi_unmute(struct fmi *fmi)
 	mutex_unlock(&fmi->lock);
 }
 
-static inline int fmi_setfreq(struct fmi *fmi, unsigned long freq)
-{
-	mutex_lock(&fmi->lock);
-	fmi->curfreq = freq;
-
-	outbits(16, RSF16_ENCODE(freq), fmi->io);
-	outbits(8, 0xC0, fmi->io);
-	msleep(143);		/* was schedule_timeout(HZ/7) */
-	mutex_unlock(&fmi->lock);
-	if (!fmi->mute)
-		fmi_unmute(fmi);
-	return 0;
-}
-
 static inline int fmi_getsigstr(struct fmi *fmi)
 {
 	int val;
@@ -173,7 +162,7 @@ static int vidioc_s_frequency(struct file *file, void *priv,
 		return -EINVAL;
 	/* rounding in steps of 800 to match the freq
 	   that will be used */
-	fmi_setfreq(fmi, (f->frequency / 800) * 800);
+	lm7000_set_freq((f->frequency / 800) * 800, fmi, fmi_set_pins);
 	return 0;
 }