aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorHans Verkuil <hans.verkuil@cisco.com>2012-01-16 03:00:26 -0500
committerMauro Carvalho Chehab <mchehab@redhat.com>2012-02-14 14:09:39 -0500
commitf8c085244ef6a88c38db3ee49bda0ff4249edf34 (patch)
tree3d8dd9c3c7f69e9ecb6b05386ea75eb6504e1909 /drivers
parent3088fba877ee8bf284b12a73332b813b5478a64d (diff)
[media] radio-gemtek: Convert to radio-isa
Tested with actual hardware (up to two cards) and the Keene USB FM Transmitter. Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/media/radio/Kconfig17
-rw-r--r--drivers/media/radio/radio-gemtek.c493
2 files changed, 106 insertions, 404 deletions
diff --git a/drivers/media/radio/Kconfig b/drivers/media/radio/Kconfig
index 645fe571617..06a8c7a5355 100644
--- a/drivers/media/radio/Kconfig
+++ b/drivers/media/radio/Kconfig
@@ -276,6 +276,7 @@ config RADIO_AZTECH_PORT
276config RADIO_GEMTEK 276config RADIO_GEMTEK
277 tristate "GemTek Radio card (or compatible) support" 277 tristate "GemTek Radio card (or compatible) support"
278 depends on ISA && VIDEO_V4L2 278 depends on ISA && VIDEO_V4L2
279 select RADIO_ISA
279 ---help--- 280 ---help---
280 Choose Y here if you have this FM radio card, and then fill in the 281 Choose Y here if you have this FM radio card, and then fill in the
281 I/O port address and settings below. The following cards either have 282 I/O port address and settings below. The following cards either have
@@ -285,23 +286,21 @@ config RADIO_GEMTEK
285 - Typhoon Radio card (some models) 286 - Typhoon Radio card (some models)
286 - Hama Radio card 287 - Hama Radio card
287 288
288 In order to control your radio card, you will need to use programs
289 that are compatible with the Video For Linux API. Information on
290 this API and pointers to "v4l" programs may be found at
291 <file:Documentation/video4linux/API.html>.
292
293 To compile this driver as a module, choose M here: the 289 To compile this driver as a module, choose M here: the
294 module will be called radio-gemtek. 290 module will be called radio-gemtek.
295 291
296config RADIO_GEMTEK_PORT 292config RADIO_GEMTEK_PORT
297 hex "Fixed I/O port (0x20c, 0x30c, 0x24c, 0x34c, 0c24c or 0x28c)" 293 hex "Fixed I/O port (0x20c, 0x30c, 0x24c, 0x34c, 0x248 or 0x28c)"
298 depends on RADIO_GEMTEK=y 294 depends on RADIO_GEMTEK=y
299 default "34c" 295 default "34c"
300 help 296 help
301 Enter either 0x20c, 0x30c, 0x24c or 0x34c here. The card default is 297 Enter either 0x20c, 0x30c, 0x24c, 0x34c, 0x248 or 0x28c here. The
302 0x34c, if you haven't changed the jumper setting on the card. On 298 card default is 0x34c, if you haven't changed the jumper setting
303 Sound Vision 16 Gold PnP with FM Radio (ESS1869+FM Gemtek), the I/O 299 on the card.
300
301 On Sound Vision 16 Gold PnP with FM Radio (ESS1869+FM Gemtek), the I/O
304 port is 0x20c, 0x248 or 0x28c. 302 port is 0x20c, 0x248 or 0x28c.
303
305 If automatic I/O port probing is enabled this port will be used only 304 If automatic I/O port probing is enabled this port will be used only
306 in case of automatic probing failure, ie. as a fallback. 305 in case of automatic probing failure, ie. as a fallback.
307 306
diff --git a/drivers/media/radio/radio-gemtek.c b/drivers/media/radio/radio-gemtek.c
index 36ce0611c03..9d7fdaea46b 100644
--- a/drivers/media/radio/radio-gemtek.c
+++ b/drivers/media/radio/radio-gemtek.c
@@ -1,4 +1,7 @@
1/* GemTek radio card driver for Linux (C) 1998 Jonas Munsin <jmunsin@iki.fi> 1/*
2 * GemTek radio card driver
3 *
4 * Copyright 1998 Jonas Munsin <jmunsin@iki.fi>
2 * 5 *
3 * GemTek hasn't released any specs on the card, so the protocol had to 6 * GemTek hasn't released any specs on the card, so the protocol had to
4 * be reverse engineered with dosemu. 7 * be reverse engineered with dosemu.
@@ -11,9 +14,12 @@
11 * Converted to new API by Alan Cox <alan@lxorguk.ukuu.org.uk> 14 * Converted to new API by Alan Cox <alan@lxorguk.ukuu.org.uk>
12 * Various bugfixes and enhancements by Russell Kroll <rkroll@exploits.org> 15 * Various bugfixes and enhancements by Russell Kroll <rkroll@exploits.org>
13 * 16 *
14 * TODO: Allow for more than one of these foolish entities :-) 17 * Converted to the radio-isa framework by Hans Verkuil <hans.verkuil@cisco.com>
15 *
16 * Converted to V4L2 API by Mauro Carvalho Chehab <mchehab@infradead.org> 18 * Converted to V4L2 API by Mauro Carvalho Chehab <mchehab@infradead.org>
19 *
20 * Note: this card seems to swap the left and right audio channels!
21 *
22 * Fully tested with the Keene USB FM Transmitter and the v4l2-compliance tool.
17 */ 23 */
18 24
19#include <linux/module.h> /* Modules */ 25#include <linux/module.h> /* Modules */
@@ -25,6 +31,7 @@
25#include <linux/io.h> /* outb, outb_p */ 31#include <linux/io.h> /* outb, outb_p */
26#include <media/v4l2-ioctl.h> 32#include <media/v4l2-ioctl.h>
27#include <media/v4l2-device.h> 33#include <media/v4l2-device.h>
34#include "radio-isa.h"
28 35
29/* 36/*
30 * Module info. 37 * Module info.
@@ -33,7 +40,7 @@
33MODULE_AUTHOR("Jonas Munsin, Pekka Seppänen <pexu@kapsi.fi>"); 40MODULE_AUTHOR("Jonas Munsin, Pekka Seppänen <pexu@kapsi.fi>");
34MODULE_DESCRIPTION("A driver for the GemTek Radio card."); 41MODULE_DESCRIPTION("A driver for the GemTek Radio card.");
35MODULE_LICENSE("GPL"); 42MODULE_LICENSE("GPL");
36MODULE_VERSION("0.0.4"); 43MODULE_VERSION("1.0.0");
37 44
38/* 45/*
39 * Module params. 46 * Module params.
@@ -46,45 +53,29 @@ MODULE_VERSION("0.0.4");
46#define CONFIG_RADIO_GEMTEK_PROBE 1 53#define CONFIG_RADIO_GEMTEK_PROBE 1
47#endif 54#endif
48 55
49static int io = CONFIG_RADIO_GEMTEK_PORT; 56#define GEMTEK_MAX 4
50static bool probe = CONFIG_RADIO_GEMTEK_PROBE;
51static bool hardmute;
52static bool shutdown = 1;
53static bool keepmuted = 1;
54static bool initmute = 1;
55static int radio_nr = -1;
56 57
57module_param(io, int, 0444); 58static bool probe = CONFIG_RADIO_GEMTEK_PROBE;
58MODULE_PARM_DESC(io, "Force I/O port for the GemTek Radio card if automatic " 59static bool hardmute;
59 "probing is disabled or fails. The most common I/O ports are: 0x20c " 60static int io[GEMTEK_MAX] = { [0] = CONFIG_RADIO_GEMTEK_PORT,
60 "0x30c, 0x24c or 0x34c (0x20c, 0x248 and 0x28c have been reported to " 61 [1 ... (GEMTEK_MAX - 1)] = -1 };
61 "work for the combined sound/radiocard)."); 62static int radio_nr[GEMTEK_MAX] = { [0 ... (GEMTEK_MAX - 1)] = -1 };
62 63
63module_param(probe, bool, 0444); 64module_param(probe, bool, 0444);
64MODULE_PARM_DESC(probe, "Enable automatic device probing. Note: only the most " 65MODULE_PARM_DESC(probe, "Enable automatic device probing.");
65 "common I/O ports used by the card are probed.");
66 66
67module_param(hardmute, bool, 0644); 67module_param(hardmute, bool, 0644);
68MODULE_PARM_DESC(hardmute, "Enable `hard muting' by shutting down PLL, may " 68MODULE_PARM_DESC(hardmute, "Enable 'hard muting' by shutting down PLL, may "
69 "reduce static noise."); 69 "reduce static noise.");
70 70
71module_param(shutdown, bool, 0644); 71module_param_array(io, int, NULL, 0444);
72MODULE_PARM_DESC(shutdown, "Enable shutting down PLL and muting line when " 72MODULE_PARM_DESC(io, "Force I/O ports for the GemTek Radio card if automatic "
73 "module is unloaded."); 73 "probing is disabled or fails. The most common I/O ports are: 0x20c "
74 74 "0x30c, 0x24c or 0x34c (0x20c, 0x248 and 0x28c have been reported to "
75module_param(keepmuted, bool, 0644); 75 "work for the combined sound/radiocard).");
76MODULE_PARM_DESC(keepmuted, "Keep card muted even when frequency is changed.");
77
78module_param(initmute, bool, 0444);
79MODULE_PARM_DESC(initmute, "Mute card when module is loaded.");
80
81module_param(radio_nr, int, 0444);
82 76
83/* 77module_param_array(radio_nr, int, NULL, 0444);
84 * Functions for controlling the card. 78MODULE_PARM_DESC(radio_nr, "Radio device numbers");
85 */
86#define GEMTEK_LOWFREQ (87*16000)
87#define GEMTEK_HIGHFREQ (108*16000)
88 79
89/* 80/*
90 * Frequency calculation constants. Intermediate frequency 10.52 MHz (nominal 81 * Frequency calculation constants. Intermediate frequency 10.52 MHz (nominal
@@ -108,18 +99,11 @@ module_param(radio_nr, int, 0444);
108#define LONG_DELAY 75 /* usec */ 99#define LONG_DELAY 75 /* usec */
109 100
110struct gemtek { 101struct gemtek {
111 struct v4l2_device v4l2_dev; 102 struct radio_isa_card isa;
112 struct video_device vdev; 103 bool muted;
113 struct mutex lock;
114 unsigned long lastfreq;
115 int muted;
116 int verified;
117 int io;
118 u32 bu2614data; 104 u32 bu2614data;
119}; 105};
120 106
121static struct gemtek gemtek_card;
122
123#define BU2614_FREQ_BITS 16 /* D0..D15, Frequency data */ 107#define BU2614_FREQ_BITS 16 /* D0..D15, Frequency data */
124#define BU2614_PORT_BITS 3 /* P0..P2, Output port control data */ 108#define BU2614_PORT_BITS 3 /* P0..P2, Output port control data */
125#define BU2614_VOID_BITS 4 /* unused */ 109#define BU2614_VOID_BITS 4 /* unused */
@@ -166,31 +150,24 @@ static struct gemtek gemtek_card;
166 */ 150 */
167static void gemtek_bu2614_transmit(struct gemtek *gt) 151static void gemtek_bu2614_transmit(struct gemtek *gt)
168{ 152{
153 struct radio_isa_card *isa = &gt->isa;
169 int i, bit, q, mute; 154 int i, bit, q, mute;
170 155
171 mutex_lock(&gt->lock);
172
173 mute = gt->muted ? GEMTEK_MT : 0x00; 156 mute = gt->muted ? GEMTEK_MT : 0x00;
174 157
175 outb_p(mute | GEMTEK_DA | GEMTEK_CK, gt->io); 158 outb_p(mute | GEMTEK_CE | GEMTEK_DA | GEMTEK_CK, isa->io);
176 udelay(SHORT_DELAY);
177 outb_p(mute | GEMTEK_CE | GEMTEK_DA | GEMTEK_CK, gt->io);
178 udelay(LONG_DELAY); 159 udelay(LONG_DELAY);
179 160
180 for (i = 0, q = gt->bu2614data; i < 32; i++, q >>= 1) { 161 for (i = 0, q = gt->bu2614data; i < 32; i++, q >>= 1) {
181 bit = (q & 1) ? GEMTEK_DA : 0; 162 bit = (q & 1) ? GEMTEK_DA : 0;
182 outb_p(mute | GEMTEK_CE | bit, gt->io); 163 outb_p(mute | GEMTEK_CE | bit, isa->io);
183 udelay(SHORT_DELAY); 164 udelay(SHORT_DELAY);
184 outb_p(mute | GEMTEK_CE | bit | GEMTEK_CK, gt->io); 165 outb_p(mute | GEMTEK_CE | bit | GEMTEK_CK, isa->io);
185 udelay(SHORT_DELAY); 166 udelay(SHORT_DELAY);
186 } 167 }
187 168
188 outb_p(mute | GEMTEK_DA | GEMTEK_CK, gt->io); 169 outb_p(mute | GEMTEK_DA | GEMTEK_CK, isa->io);
189 udelay(SHORT_DELAY); 170 udelay(SHORT_DELAY);
190 outb_p(mute | GEMTEK_CE | GEMTEK_DA | GEMTEK_CK, gt->io);
191 udelay(LONG_DELAY);
192
193 mutex_unlock(&gt->lock);
194} 171}
195 172
196/* 173/*
@@ -198,21 +175,27 @@ static void gemtek_bu2614_transmit(struct gemtek *gt)
198 */ 175 */
199static unsigned long gemtek_convfreq(unsigned long freq) 176static unsigned long gemtek_convfreq(unsigned long freq)
200{ 177{
201 return ((freq<<FSCALE) + IF_OFFSET + REF_FREQ/2) / REF_FREQ; 178 return ((freq << FSCALE) + IF_OFFSET + REF_FREQ / 2) / REF_FREQ;
179}
180
181static struct radio_isa_card *gemtek_alloc(void)
182{
183 struct gemtek *gt = kzalloc(sizeof(*gt), GFP_KERNEL);
184
185 if (gt)
186 gt->muted = true;
187 return gt ? &gt->isa : NULL;
202} 188}
203 189
204/* 190/*
205 * Set FM-frequency. 191 * Set FM-frequency.
206 */ 192 */
207static void gemtek_setfreq(struct gemtek *gt, unsigned long freq) 193static int gemtek_s_frequency(struct radio_isa_card *isa, u32 freq)
208{ 194{
209 if (keepmuted && hardmute && gt->muted) 195 struct gemtek *gt = container_of(isa, struct gemtek, isa);
210 return;
211 196
212 freq = clamp_val(freq, GEMTEK_LOWFREQ, GEMTEK_HIGHFREQ); 197 if (hardmute && gt->muted)
213 198 return 0;
214 gt->lastfreq = freq;
215 gt->muted = 0;
216 199
217 gemtek_bu2614_set(gt, BU2614_PORT, 0); 200 gemtek_bu2614_set(gt, BU2614_PORT, 0);
218 gemtek_bu2614_set(gt, BU2614_FMES, 0); 201 gemtek_bu2614_set(gt, BU2614_FMES, 0);
@@ -220,23 +203,25 @@ static void gemtek_setfreq(struct gemtek *gt, unsigned long freq)
220 gemtek_bu2614_set(gt, BU2614_SWAL, 0); 203 gemtek_bu2614_set(gt, BU2614_SWAL, 0);
221 gemtek_bu2614_set(gt, BU2614_FMUN, 1); /* GT bit set */ 204 gemtek_bu2614_set(gt, BU2614_FMUN, 1); /* GT bit set */
222 gemtek_bu2614_set(gt, BU2614_TEST, 0); 205 gemtek_bu2614_set(gt, BU2614_TEST, 0);
223
224 gemtek_bu2614_set(gt, BU2614_STDF, GEMTEK_STDF_3_125_KHZ); 206 gemtek_bu2614_set(gt, BU2614_STDF, GEMTEK_STDF_3_125_KHZ);
225 gemtek_bu2614_set(gt, BU2614_FREQ, gemtek_convfreq(freq)); 207 gemtek_bu2614_set(gt, BU2614_FREQ, gemtek_convfreq(freq));
226
227 gemtek_bu2614_transmit(gt); 208 gemtek_bu2614_transmit(gt);
209 return 0;
228} 210}
229 211
230/* 212/*
231 * Set mute flag. 213 * Set mute flag.
232 */ 214 */
233static void gemtek_mute(struct gemtek *gt) 215static int gemtek_s_mute_volume(struct radio_isa_card *isa, bool mute, int vol)
234{ 216{
217 struct gemtek *gt = container_of(isa, struct gemtek, isa);
235 int i; 218 int i;
236 219
237 gt->muted = 1; 220 gt->muted = mute;
238
239 if (hardmute) { 221 if (hardmute) {
222 if (!mute)
223 return gemtek_s_frequency(isa, isa->freq);
224
240 /* Turn off PLL, disable data output */ 225 /* Turn off PLL, disable data output */
241 gemtek_bu2614_set(gt, BU2614_PORT, 0); 226 gemtek_bu2614_set(gt, BU2614_PORT, 0);
242 gemtek_bu2614_set(gt, BU2614_FMES, 0); /* CT bit off */ 227 gemtek_bu2614_set(gt, BU2614_FMES, 0); /* CT bit off */
@@ -247,367 +232,85 @@ static void gemtek_mute(struct gemtek *gt)
247 gemtek_bu2614_set(gt, BU2614_STDF, GEMTEK_PLL_OFF); 232 gemtek_bu2614_set(gt, BU2614_STDF, GEMTEK_PLL_OFF);
248 gemtek_bu2614_set(gt, BU2614_FREQ, 0); 233 gemtek_bu2614_set(gt, BU2614_FREQ, 0);
249 gemtek_bu2614_transmit(gt); 234 gemtek_bu2614_transmit(gt);
250 return; 235 return 0;
251 } 236 }
252 237
253 mutex_lock(&gt->lock);
254
255 /* Read bus contents (CE, CK and DA). */ 238 /* Read bus contents (CE, CK and DA). */
256 i = inb_p(gt->io); 239 i = inb_p(isa->io);
257 /* Write it back with mute flag set. */ 240 /* Write it back with mute flag set. */
258 outb_p((i >> 5) | GEMTEK_MT, gt->io); 241 outb_p((i >> 5) | (mute ? GEMTEK_MT : 0), isa->io);
259 udelay(SHORT_DELAY); 242 udelay(SHORT_DELAY);
260 243 return 0;
261 mutex_unlock(&gt->lock);
262}
263
264/*
265 * Unset mute flag.
266 */
267static void gemtek_unmute(struct gemtek *gt)
268{
269 int i;
270
271 gt->muted = 0;
272 if (hardmute) {
273 /* Turn PLL back on. */
274 gemtek_setfreq(gt, gt->lastfreq);
275 return;
276 }
277 mutex_lock(&gt->lock);
278
279 i = inb_p(gt->io);
280 outb_p(i >> 5, gt->io);
281 udelay(SHORT_DELAY);
282
283 mutex_unlock(&gt->lock);
284} 244}
285 245
286/* 246static u32 gemtek_g_rxsubchans(struct radio_isa_card *isa)
287 * Get signal strength (= stereo status).
288 */
289static inline int gemtek_getsigstr(struct gemtek *gt)
290{ 247{
291 int sig; 248 if (inb_p(isa->io) & GEMTEK_NS)
292 249 return V4L2_TUNER_SUB_MONO;
293 mutex_lock(&gt->lock); 250 return V4L2_TUNER_SUB_STEREO;
294 sig = inb_p(gt->io) & GEMTEK_NS ? 0 : 1;
295 mutex_unlock(&gt->lock);
296 return sig;
297} 251}
298 252
299/* 253/*
300 * Check if requested card acts like GemTek Radio card. 254 * Check if requested card acts like GemTek Radio card.
301 */ 255 */
302static int gemtek_verify(struct gemtek *gt, int port) 256static bool gemtek_probe(struct radio_isa_card *isa, int io)
303{ 257{
304 int i, q; 258 int i, q;
305 259
306 if (gt->verified == port) 260 q = inb_p(io); /* Read bus contents before probing. */
307 return 1;
308
309 mutex_lock(&gt->lock);
310
311 q = inb_p(port); /* Read bus contents before probing. */
312 /* Try to turn on CE, CK and DA respectively and check if card responds 261 /* Try to turn on CE, CK and DA respectively and check if card responds
313 properly. */ 262 properly. */
314 for (i = 0; i < 3; ++i) { 263 for (i = 0; i < 3; ++i) {
315 outb_p(1 << i, port); 264 outb_p(1 << i, io);
316 udelay(SHORT_DELAY); 265 udelay(SHORT_DELAY);
317 266
318 if ((inb_p(port) & (~GEMTEK_NS)) != (0x17 | (1 << (i + 5)))) { 267 if ((inb_p(io) & ~GEMTEK_NS) != (0x17 | (1 << (i + 5))))
319 mutex_unlock(&gt->lock); 268 return false;
320 return 0;
321 }
322 } 269 }
323 outb_p(q >> 5, port); /* Write bus contents back. */ 270 outb_p(q >> 5, io); /* Write bus contents back. */
324 udelay(SHORT_DELAY); 271 udelay(SHORT_DELAY);
325 272 return true;
326 mutex_unlock(&gt->lock);
327 gt->verified = port;
328
329 return 1;
330}
331
332/*
333 * Automatic probing for card.
334 */
335static int gemtek_probe(struct gemtek *gt)
336{
337 struct v4l2_device *v4l2_dev = &gt->v4l2_dev;
338 int ioports[] = { 0x20c, 0x30c, 0x24c, 0x34c, 0x248, 0x28c };
339 int i;
340
341 if (!probe) {
342 v4l2_info(v4l2_dev, "Automatic device probing disabled.\n");
343 return -1;
344 }
345
346 v4l2_info(v4l2_dev, "Automatic device probing enabled.\n");
347
348 for (i = 0; i < ARRAY_SIZE(ioports); ++i) {
349 v4l2_info(v4l2_dev, "Trying I/O port 0x%x...\n", ioports[i]);
350
351 if (!request_region(ioports[i], 1, "gemtek-probe")) {
352 v4l2_warn(v4l2_dev, "I/O port 0x%x busy!\n",
353 ioports[i]);
354 continue;
355 }
356
357 if (gemtek_verify(gt, ioports[i])) {
358 v4l2_info(v4l2_dev, "Card found from I/O port "
359 "0x%x!\n", ioports[i]);
360
361 release_region(ioports[i], 1);
362 gt->io = ioports[i];
363 return gt->io;
364 }
365
366 release_region(ioports[i], 1);
367 }
368
369 v4l2_err(v4l2_dev, "Automatic probing failed!\n");
370 return -1;
371} 273}
372 274
373/* 275static const struct radio_isa_ops gemtek_ops = {
374 * Video 4 Linux stuff. 276 .alloc = gemtek_alloc,
375 */ 277 .probe = gemtek_probe,
376 278 .s_mute_volume = gemtek_s_mute_volume,
377static const struct v4l2_file_operations gemtek_fops = { 279 .s_frequency = gemtek_s_frequency,
378 .owner = THIS_MODULE, 280 .g_rxsubchans = gemtek_g_rxsubchans,
379 .unlocked_ioctl = video_ioctl2,
380}; 281};
381 282
382static int vidioc_querycap(struct file *file, void *priv, 283static const int gemtek_ioports[] = { 0x20c, 0x30c, 0x24c, 0x34c, 0x248, 0x28c };
383 struct v4l2_capability *v) 284
384{ 285static struct radio_isa_driver gemtek_driver = {
385 strlcpy(v->driver, "radio-gemtek", sizeof(v->driver)); 286 .driver = {
386 strlcpy(v->card, "GemTek", sizeof(v->card)); 287 .match = radio_isa_match,
387 strlcpy(v->bus_info, "ISA", sizeof(v->bus_info)); 288 .probe = radio_isa_probe,
388 v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO; 289 .remove = radio_isa_remove,
389 return 0; 290 .driver = {
390} 291 .name = "radio-gemtek",
391 292 },
392static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *v) 293 },
393{ 294 .io_params = io,
394 struct gemtek *gt = video_drvdata(file); 295 .radio_nr_params = radio_nr,
395 296 .io_ports = gemtek_ioports,
396 if (v->index > 0) 297 .num_of_io_ports = ARRAY_SIZE(gemtek_ioports),
397 return -EINVAL; 298 .region_size = 1,
398 299 .card = "GemTek Radio",
399 strlcpy(v->name, "FM", sizeof(v->name)); 300 .ops = &gemtek_ops,
400 v->type = V4L2_TUNER_RADIO; 301 .has_stereo = true,
401 v->rangelow = GEMTEK_LOWFREQ;
402 v->rangehigh = GEMTEK_HIGHFREQ;
403 v->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO;
404 v->signal = 0xffff * gemtek_getsigstr(gt);
405 if (v->signal) {
406 v->audmode = V4L2_TUNER_MODE_STEREO;
407 v->rxsubchans = V4L2_TUNER_SUB_STEREO;
408 } else {
409 v->audmode = V4L2_TUNER_MODE_MONO;
410 v->rxsubchans = V4L2_TUNER_SUB_MONO;
411 }
412 return 0;
413}
414
415static int vidioc_s_tuner(struct file *file, void *priv, struct v4l2_tuner *v)
416{
417 return (v->index != 0) ? -EINVAL : 0;
418}
419
420static int vidioc_g_frequency(struct file *file, void *priv,
421 struct v4l2_frequency *f)
422{
423 struct gemtek *gt = video_drvdata(file);
424
425 if (f->tuner != 0)
426 return -EINVAL;
427 f->type = V4L2_TUNER_RADIO;
428 f->frequency = gt->lastfreq;
429 return 0;
430}
431
432static int vidioc_s_frequency(struct file *file, void *priv,
433 struct v4l2_frequency *f)
434{
435 struct gemtek *gt = video_drvdata(file);
436
437 if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO)
438 return -EINVAL;
439 gemtek_setfreq(gt, f->frequency);
440 return 0;
441}
442
443static int vidioc_queryctrl(struct file *file, void *priv,
444 struct v4l2_queryctrl *qc)
445{
446 switch (qc->id) {
447 case V4L2_CID_AUDIO_MUTE:
448 return v4l2_ctrl_query_fill(qc, 0, 1, 1, 0);
449 default:
450 return -EINVAL;
451 }
452}
453
454static int vidioc_g_ctrl(struct file *file, void *priv,
455 struct v4l2_control *ctrl)
456{
457 struct gemtek *gt = video_drvdata(file);
458
459 switch (ctrl->id) {
460 case V4L2_CID_AUDIO_MUTE:
461 ctrl->value = gt->muted;
462 return 0;
463 }
464 return -EINVAL;
465}
466
467static int vidioc_s_ctrl(struct file *file, void *priv,
468 struct v4l2_control *ctrl)
469{
470 struct gemtek *gt = video_drvdata(file);
471
472 switch (ctrl->id) {
473 case V4L2_CID_AUDIO_MUTE:
474 if (ctrl->value)
475 gemtek_mute(gt);
476 else
477 gemtek_unmute(gt);
478 return 0;
479 }
480 return -EINVAL;
481}
482
483static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i)
484{
485 *i = 0;
486 return 0;
487}
488
489static int vidioc_s_input(struct file *filp, void *priv, unsigned int i)
490{
491 return (i != 0) ? -EINVAL : 0;
492}
493
494static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a)
495{
496 a->index = 0;
497 strlcpy(a->name, "Radio", sizeof(a->name));
498 a->capability = V4L2_AUDCAP_STEREO;
499 return 0;
500}
501
502static int vidioc_s_audio(struct file *file, void *priv, struct v4l2_audio *a)
503{
504 return (a->index != 0) ? -EINVAL : 0;
505}
506
507static const struct v4l2_ioctl_ops gemtek_ioctl_ops = {
508 .vidioc_querycap = vidioc_querycap,
509 .vidioc_g_tuner = vidioc_g_tuner,
510 .vidioc_s_tuner = vidioc_s_tuner,
511 .vidioc_g_audio = vidioc_g_audio,
512 .vidioc_s_audio = vidioc_s_audio,
513 .vidioc_g_input = vidioc_g_input,
514 .vidioc_s_input = vidioc_s_input,
515 .vidioc_g_frequency = vidioc_g_frequency,
516 .vidioc_s_frequency = vidioc_s_frequency,
517 .vidioc_queryctrl = vidioc_queryctrl,
518 .vidioc_g_ctrl = vidioc_g_ctrl,
519 .vidioc_s_ctrl = vidioc_s_ctrl
520}; 302};
521 303
522/*
523 * Initialization / cleanup related stuff.
524 */
525
526static int __init gemtek_init(void) 304static int __init gemtek_init(void)
527{ 305{
528 struct gemtek *gt = &gemtek_card; 306 gemtek_driver.probe = probe;
529 struct v4l2_device *v4l2_dev = &gt->v4l2_dev; 307 return isa_register_driver(&gemtek_driver.driver, GEMTEK_MAX);
530 int res;
531
532 strlcpy(v4l2_dev->name, "gemtek", sizeof(v4l2_dev->name));
533
534 v4l2_info(v4l2_dev, "GemTek Radio card driver: v0.0.3\n");
535
536 mutex_init(&gt->lock);
537
538 gt->verified = -1;
539 gt->io = io;
540 gemtek_probe(gt);
541 if (gt->io) {
542 if (!request_region(gt->io, 1, "gemtek")) {
543 v4l2_err(v4l2_dev, "I/O port 0x%x already in use.\n", gt->io);
544 return -EBUSY;
545 }
546
547 if (!gemtek_verify(gt, gt->io))
548 v4l2_warn(v4l2_dev, "Card at I/O port 0x%x does not "
549 "respond properly, check your "
550 "configuration.\n", gt->io);
551 else
552 v4l2_info(v4l2_dev, "Using I/O port 0x%x.\n", gt->io);
553 } else if (probe) {
554 v4l2_err(v4l2_dev, "Automatic probing failed and no "
555 "fixed I/O port defined.\n");
556 return -ENODEV;
557 } else {
558 v4l2_err(v4l2_dev, "Automatic probing disabled but no fixed "
559 "I/O port defined.");
560 return -EINVAL;
561 }
562
563 res = v4l2_device_register(NULL, v4l2_dev);
564 if (res < 0) {
565 v4l2_err(v4l2_dev, "Could not register v4l2_device\n");
566 release_region(gt->io, 1);
567 return res;
568 }
569
570 strlcpy(gt->vdev.name, v4l2_dev->name, sizeof(gt->vdev.name));
571 gt->vdev.v4l2_dev = v4l2_dev;
572 gt->vdev.fops = &gemtek_fops;
573 gt->vdev.ioctl_ops = &gemtek_ioctl_ops;
574 gt->vdev.release = video_device_release_empty;
575 video_set_drvdata(&gt->vdev, gt);
576
577 /* Set defaults */
578 gt->lastfreq = GEMTEK_LOWFREQ;
579 gt->bu2614data = 0;
580
581 if (initmute)
582 gemtek_mute(gt);
583
584 if (video_register_device(&gt->vdev, VFL_TYPE_RADIO, radio_nr) < 0) {
585 v4l2_device_unregister(v4l2_dev);
586 release_region(gt->io, 1);
587 return -EBUSY;
588 }
589
590 return 0;
591} 308}
592 309
593/*
594 * Module cleanup
595 */
596static void __exit gemtek_exit(void) 310static void __exit gemtek_exit(void)
597{ 311{
598 struct gemtek *gt = &gemtek_card; 312 hardmute = 1; /* Turn off PLL */
599 struct v4l2_device *v4l2_dev = &gt->v4l2_dev; 313 isa_unregister_driver(&gemtek_driver.driver);
600
601 if (shutdown) {
602 hardmute = 1; /* Turn off PLL */
603 gemtek_mute(gt);
604 } else {
605 v4l2_info(v4l2_dev, "Module unloaded but card not muted!\n");
606 }
607
608 video_unregister_device(&gt->vdev);
609 v4l2_device_unregister(&gt->v4l2_dev);
610 release_region(gt->io, 1);
611} 314}
612 315
613module_init(gemtek_init); 316module_init(gemtek_init);