From 9ca8dbcc65cfc63d6f5ef3312a33184e1d726e00 Mon Sep 17 00:00:00 2001 From: Yunhong Jiang Date: Tue, 4 Aug 2015 12:17:53 -0700 Subject: Add the rt linux 4.1.3-rt3 as base Import the rt linux 4.1.3-rt3 as OPNFV kvm base. It's from git://git.kernel.org/pub/scm/linux/kernel/git/rt/linux-rt-devel.git linux-4.1.y-rt and the base is: commit 0917f823c59692d751951bf5ea699a2d1e2f26a2 Author: Sebastian Andrzej Siewior Date: Sat Jul 25 12:13:34 2015 +0200 Prepare v4.1.3-rt3 Signed-off-by: Sebastian Andrzej Siewior We lose all the git history this way and it's not good. We should apply another opnfv project repo in future. Change-Id: I87543d81c9df70d99c5001fbdf646b202c19f423 Signed-off-by: Yunhong Jiang --- kernel/drivers/media/radio/radio-zoltrix.c | 248 +++++++++++++++++++++++++++++ 1 file changed, 248 insertions(+) create mode 100644 kernel/drivers/media/radio/radio-zoltrix.c (limited to 'kernel/drivers/media/radio/radio-zoltrix.c') diff --git a/kernel/drivers/media/radio/radio-zoltrix.c b/kernel/drivers/media/radio/radio-zoltrix.c new file mode 100644 index 000000000..026e88eef --- /dev/null +++ b/kernel/drivers/media/radio/radio-zoltrix.c @@ -0,0 +1,248 @@ +/* + * Zoltrix Radio Plus driver + * Copyright 1998 C. van Schaik + * + * BUGS + * Due to the inconsistency in reading from the signal flags + * it is difficult to get an accurate tuned signal. + * + * It seems that the card is not linear to 0 volume. It cuts off + * at a low volume, and it is not possible (at least I have not found) + * to get fine volume control over the low volume range. + * + * Some code derived from code by Romolo Manfredini + * romolo@bicnet.it + * + * 1999-05-06 - (C. van Schaik) + * - Make signal strength and stereo scans + * kinder to cpu while in delay + * 1999-01-05 - (C. van Schaik) + * - Changed tuning to 1/160Mhz accuracy + * - Added stereo support + * (card defaults to stereo) + * (can explicitly force mono on the card) + * (can detect if station is in stereo) + * - Added unmute function + * - Reworked ioctl functions + * 2002-07-15 - Fix Stereo typo + * + * 2006-07-24 - Converted to V4L2 API + * by Mauro Carvalho Chehab + * + * Converted to the radio-isa framework by Hans Verkuil + * + * Note that this is the driver for the Zoltrix Radio Plus. + * This driver does not work for the Zoltrix Radio Plus 108 or the + * Zoltrix Radio Plus for Windows. + * + * Fully tested with the Keene USB FM Transmitter and the v4l2-compliance tool. + */ + +#include /* Modules */ +#include /* Initdata */ +#include /* request_region */ +#include /* udelay, msleep */ +#include /* kernel radio structs */ +#include +#include /* outb, outb_p */ +#include +#include +#include +#include "radio-isa.h" + +MODULE_AUTHOR("C. van Schaik"); +MODULE_DESCRIPTION("A driver for the Zoltrix Radio Plus."); +MODULE_LICENSE("GPL"); +MODULE_VERSION("0.1.99"); + +#ifndef CONFIG_RADIO_ZOLTRIX_PORT +#define CONFIG_RADIO_ZOLTRIX_PORT -1 +#endif + +#define ZOLTRIX_MAX 2 + +static int io[ZOLTRIX_MAX] = { [0] = CONFIG_RADIO_ZOLTRIX_PORT, + [1 ... (ZOLTRIX_MAX - 1)] = -1 }; +static int radio_nr[ZOLTRIX_MAX] = { [0 ... (ZOLTRIX_MAX - 1)] = -1 }; + +module_param_array(io, int, NULL, 0444); +MODULE_PARM_DESC(io, "I/O addresses of the Zoltrix Radio Plus card (0x20c or 0x30c)"); +module_param_array(radio_nr, int, NULL, 0444); +MODULE_PARM_DESC(radio_nr, "Radio device numbers"); + +struct zoltrix { + struct radio_isa_card isa; + int curvol; + bool muted; +}; + +static struct radio_isa_card *zoltrix_alloc(void) +{ + struct zoltrix *zol = kzalloc(sizeof(*zol), GFP_KERNEL); + + return zol ? &zol->isa : NULL; +} + +static int zoltrix_s_mute_volume(struct radio_isa_card *isa, bool mute, int vol) +{ + struct zoltrix *zol = container_of(isa, struct zoltrix, isa); + + zol->curvol = vol; + zol->muted = mute; + if (mute || vol == 0) { + outb(0, isa->io); + outb(0, isa->io); + inb(isa->io + 3); /* Zoltrix needs to be read to confirm */ + return 0; + } + + outb(vol - 1, isa->io); + msleep(10); + inb(isa->io + 2); + return 0; +} + +/* tunes the radio to the desired frequency */ +static int zoltrix_s_frequency(struct radio_isa_card *isa, u32 freq) +{ + struct zoltrix *zol = container_of(isa, struct zoltrix, isa); + struct v4l2_device *v4l2_dev = &isa->v4l2_dev; + unsigned long long bitmask, f, m; + bool stereo = isa->stereo; + int i; + + if (freq == 0) { + v4l2_warn(v4l2_dev, "cannot set a frequency of 0.\n"); + return -EINVAL; + } + + m = (freq / 160 - 8800) * 2; + f = (unsigned long long)m + 0x4d1c; + + bitmask = 0xc480402c10080000ull; + i = 45; + + outb(0, isa->io); + outb(0, isa->io); + inb(isa->io + 3); /* Zoltrix needs to be read to confirm */ + + outb(0x40, isa->io); + outb(0xc0, isa->io); + + bitmask = (bitmask ^ ((f & 0xff) << 47) ^ ((f & 0xff00) << 30) ^ (stereo << 31)); + while (i--) { + if ((bitmask & 0x8000000000000000ull) != 0) { + outb(0x80, isa->io); + udelay(50); + outb(0x00, isa->io); + udelay(50); + outb(0x80, isa->io); + udelay(50); + } else { + outb(0xc0, isa->io); + udelay(50); + outb(0x40, isa->io); + udelay(50); + outb(0xc0, isa->io); + udelay(50); + } + bitmask *= 2; + } + /* termination sequence */ + outb(0x80, isa->io); + outb(0xc0, isa->io); + outb(0x40, isa->io); + udelay(1000); + inb(isa->io + 2); + udelay(1000); + + return zoltrix_s_mute_volume(isa, zol->muted, zol->curvol); +} + +/* Get signal strength */ +static u32 zoltrix_g_rxsubchans(struct radio_isa_card *isa) +{ + struct zoltrix *zol = container_of(isa, struct zoltrix, isa); + int a, b; + + outb(0x00, isa->io); /* This stuff I found to do nothing */ + outb(zol->curvol, isa->io); + msleep(20); + + a = inb(isa->io); + msleep(10); + b = inb(isa->io); + + return (a == b && a == 0xcf) ? + V4L2_TUNER_SUB_STEREO : V4L2_TUNER_SUB_MONO; +} + +static u32 zoltrix_g_signal(struct radio_isa_card *isa) +{ + struct zoltrix *zol = container_of(isa, struct zoltrix, isa); + int a, b; + + outb(0x00, isa->io); /* This stuff I found to do nothing */ + outb(zol->curvol, isa->io); + msleep(20); + + a = inb(isa->io); + msleep(10); + b = inb(isa->io); + + if (a != b) + return 0; + + /* I found this out by playing with a binary scanner on the card io */ + return (a == 0xcf || a == 0xdf || a == 0xef) ? 0xffff : 0; +} + +static int zoltrix_s_stereo(struct radio_isa_card *isa, bool stereo) +{ + return zoltrix_s_frequency(isa, isa->freq); +} + +static const struct radio_isa_ops zoltrix_ops = { + .alloc = zoltrix_alloc, + .s_mute_volume = zoltrix_s_mute_volume, + .s_frequency = zoltrix_s_frequency, + .s_stereo = zoltrix_s_stereo, + .g_rxsubchans = zoltrix_g_rxsubchans, + .g_signal = zoltrix_g_signal, +}; + +static const int zoltrix_ioports[] = { 0x20c, 0x30c }; + +static struct radio_isa_driver zoltrix_driver = { + .driver = { + .match = radio_isa_match, + .probe = radio_isa_probe, + .remove = radio_isa_remove, + .driver = { + .name = "radio-zoltrix", + }, + }, + .io_params = io, + .radio_nr_params = radio_nr, + .io_ports = zoltrix_ioports, + .num_of_io_ports = ARRAY_SIZE(zoltrix_ioports), + .region_size = 2, + .card = "Zoltrix Radio Plus", + .ops = &zoltrix_ops, + .has_stereo = true, + .max_volume = 15, +}; + +static int __init zoltrix_init(void) +{ + return isa_register_driver(&zoltrix_driver.driver, ZOLTRIX_MAX); +} + +static void __exit zoltrix_exit(void) +{ + isa_unregister_driver(&zoltrix_driver.driver); +} + +module_init(zoltrix_init); +module_exit(zoltrix_exit); + -- cgit 1.2.3-korg