OpenCores
URL https://opencores.org/ocsvn/test_project/test_project/trunk

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [drivers/] [media/] [radio/] [radio-aztech.c] - Blame information for rev 62

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/* radio-aztech.c - Aztech radio card driver for Linux 2.2
2
 *
3
 * Converted to V4L2 API by Mauro Carvalho Chehab <mchehab@infradead.org>
4
 * Adapted to support the Video for Linux API by
5
 * Russell Kroll <rkroll@exploits.org>.  Based on original tuner code by:
6
 *
7
 * Quay Ly
8
 * Donald Song
9
 * Jason Lewis      (jlewis@twilight.vtc.vsc.edu)
10
 * Scott McGrath    (smcgrath@twilight.vtc.vsc.edu)
11
 * William McGrath  (wmcgrath@twilight.vtc.vsc.edu)
12
 *
13
 * The basis for this code may be found at http://bigbang.vtc.vsc.edu/fmradio/
14
 * along with more information on the card itself.
15
 *
16
 * History:
17
 * 1999-02-24   Russell Kroll <rkroll@exploits.org>
18
 *              Fine tuning/VIDEO_TUNER_LOW
19
 *              Range expanded to 87-108 MHz (from 87.9-107.8)
20
 *
21
 * Notable changes from the original source:
22
 * - includes stripped down to the essentials
23
 * - for loops used as delays replaced with udelay()
24
 * - #defines removed, changed to static values
25
 * - tuning structure changed - no more character arrays, other changes
26
*/
27
 
28
#include <linux/module.h>       /* Modules                      */
29
#include <linux/init.h>         /* Initdata                     */
30
#include <linux/ioport.h>       /* request_region               */
31
#include <linux/delay.h>        /* udelay                       */
32
#include <asm/io.h>             /* outb, outb_p                 */
33
#include <asm/uaccess.h>        /* copy to/from user            */
34
#include <linux/videodev2.h>    /* kernel radio structs         */
35
#include <media/v4l2-common.h>
36
 
37
#include <linux/version.h>      /* for KERNEL_VERSION MACRO     */
38
#define RADIO_VERSION KERNEL_VERSION(0,0,2)
39
 
40
static struct v4l2_queryctrl radio_qctrl[] = {
41
        {
42
                .id            = V4L2_CID_AUDIO_MUTE,
43
                .name          = "Mute",
44
                .minimum       = 0,
45
                .maximum       = 1,
46
                .default_value = 1,
47
                .type          = V4L2_CTRL_TYPE_BOOLEAN,
48
        },{
49
                .id            = V4L2_CID_AUDIO_VOLUME,
50
                .name          = "Volume",
51
                .minimum       = 0,
52
                .maximum       = 0xff,
53
                .step          = 1,
54
                .default_value = 0xff,
55
                .type          = V4L2_CTRL_TYPE_INTEGER,
56
        }
57
};
58
 
59
/* acceptable ports: 0x350 (JP3 shorted), 0x358 (JP3 open) */
60
 
61
#ifndef CONFIG_RADIO_AZTECH_PORT
62
#define CONFIG_RADIO_AZTECH_PORT -1
63
#endif
64
 
65
static int io = CONFIG_RADIO_AZTECH_PORT;
66
static int radio_nr = -1;
67
static int radio_wait_time = 1000;
68
static struct mutex lock;
69
 
70
struct az_device
71
{
72
        int curvol;
73
        unsigned long curfreq;
74
        int stereo;
75
};
76
 
77
static int volconvert(int level)
78
{
79
        level>>=14;             /* Map 16bits down to 2 bit */
80
        level&=3;
81
 
82
        /* convert to card-friendly values */
83
        switch (level)
84
        {
85
                case 0:
86
                        return 0;
87
                case 1:
88
                        return 1;
89
                case 2:
90
                        return 4;
91
                case 3:
92
                        return 5;
93
        }
94
        return 0;        /* Quieten gcc */
95
}
96
 
97
static void send_0_byte (struct az_device *dev)
98
{
99
        udelay(radio_wait_time);
100
        outb_p(2+volconvert(dev->curvol), io);
101
        outb_p(64+2+volconvert(dev->curvol), io);
102
}
103
 
104
static void send_1_byte (struct az_device *dev)
105
{
106
        udelay (radio_wait_time);
107
        outb_p(128+2+volconvert(dev->curvol), io);
108
        outb_p(128+64+2+volconvert(dev->curvol), io);
109
}
110
 
111
static int az_setvol(struct az_device *dev, int vol)
112
{
113
        mutex_lock(&lock);
114
        outb (volconvert(vol), io);
115
        mutex_unlock(&lock);
116
        return 0;
117
}
118
 
119
/* thanks to Michael Dwyer for giving me a dose of clues in
120
 * the signal strength department..
121
 *
122
 * This card has a stereo bit - bit 0 set = mono, not set = stereo
123
 * It also has a "signal" bit - bit 1 set = bad signal, not set = good
124
 *
125
 */
126
 
127
static int az_getsigstr(struct az_device *dev)
128
{
129
        if (inb(io) & 2)        /* bit set = no signal present */
130
                return 0;
131
        return 1;               /* signal present */
132
}
133
 
134
static int az_getstereo(struct az_device *dev)
135
{
136
        if (inb(io) & 1)        /* bit set = mono */
137
                return 0;
138
        return 1;               /* stereo */
139
}
140
 
141
static int az_setfreq(struct az_device *dev, unsigned long frequency)
142
{
143
        int  i;
144
 
145
        frequency += 171200;            /* Add 10.7 MHz IF              */
146
        frequency /= 800;               /* Convert to 50 kHz units      */
147
 
148
        mutex_lock(&lock);
149
 
150
        send_0_byte (dev);              /*  0: LSB of frequency       */
151
 
152
        for (i = 0; i < 13; i++) /*   : frequency bits (1-13)  */
153
                if (frequency & (1 << i))
154
                        send_1_byte (dev);
155
                else
156
                        send_0_byte (dev);
157
 
158
        send_0_byte (dev);              /* 14: test bit - always 0    */
159
        send_0_byte (dev);              /* 15: test bit - always 0    */
160
        send_0_byte (dev);              /* 16: band data 0 - always 0 */
161
        if (dev->stereo)                /* 17: stereo (1 to enable)   */
162
                send_1_byte (dev);
163
        else
164
                send_0_byte (dev);
165
 
166
        send_1_byte (dev);              /* 18: band data 1 - unknown  */
167
        send_0_byte (dev);              /* 19: time base - always 0   */
168
        send_0_byte (dev);              /* 20: spacing (0 = 25 kHz)   */
169
        send_1_byte (dev);              /* 21: spacing (1 = 25 kHz)   */
170
        send_0_byte (dev);              /* 22: spacing (0 = 25 kHz)   */
171
        send_1_byte (dev);              /* 23: AM/FM (FM = 1, always) */
172
 
173
        /* latch frequency */
174
 
175
        udelay (radio_wait_time);
176
        outb_p(128+64+volconvert(dev->curvol), io);
177
 
178
        mutex_unlock(&lock);
179
 
180
        return 0;
181
}
182
 
183
static int vidioc_querycap (struct file *file, void  *priv,
184
                                        struct v4l2_capability *v)
185
{
186
        strlcpy(v->driver, "radio-aztech", sizeof (v->driver));
187
        strlcpy(v->card, "Aztech Radio", sizeof (v->card));
188
        sprintf(v->bus_info,"ISA");
189
        v->version = RADIO_VERSION;
190
        v->capabilities = V4L2_CAP_TUNER;
191
        return 0;
192
}
193
 
194
static int vidioc_g_tuner (struct file *file, void *priv,
195
                                struct v4l2_tuner *v)
196
{
197
        struct video_device *dev = video_devdata(file);
198
        struct az_device *az = dev->priv;
199
 
200
        if (v->index > 0)
201
                return -EINVAL;
202
 
203
        strcpy(v->name, "FM");
204
        v->type = V4L2_TUNER_RADIO;
205
 
206
        v->rangelow=(87*16000);
207
        v->rangehigh=(108*16000);
208
        v->rxsubchans =V4L2_TUNER_SUB_MONO|V4L2_TUNER_SUB_STEREO;
209
        v->capability=V4L2_TUNER_CAP_LOW;
210
        if(az_getstereo(az))
211
                v->audmode = V4L2_TUNER_MODE_STEREO;
212
        else
213
                v->audmode = V4L2_TUNER_MODE_MONO;
214
        v->signal=0xFFFF*az_getsigstr(az);
215
 
216
        return 0;
217
}
218
 
219
 
220
static int vidioc_s_tuner (struct file *file, void *priv,
221
                                struct v4l2_tuner *v)
222
{
223
        if (v->index > 0)
224
                return -EINVAL;
225
 
226
        return 0;
227
}
228
 
229
static int vidioc_g_audio (struct file *file, void *priv,
230
                           struct v4l2_audio *a)
231
{
232
        if (a->index > 1)
233
                return -EINVAL;
234
 
235
        strcpy(a->name, "Radio");
236
        a->capability = V4L2_AUDCAP_STEREO;
237
        return 0;
238
}
239
 
240
static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i)
241
{
242
        *i = 0;
243
        return 0;
244
}
245
 
246
static int vidioc_s_input(struct file *filp, void *priv, unsigned int i)
247
{
248
        if (i != 0)
249
                return -EINVAL;
250
        return 0;
251
}
252
 
253
 
254
static int vidioc_s_audio (struct file *file, void *priv,
255
                           struct v4l2_audio *a)
256
{
257
        if (a->index != 0)
258
                return -EINVAL;
259
 
260
        return 0;
261
}
262
 
263
static int vidioc_s_frequency (struct file *file, void *priv,
264
                                struct v4l2_frequency *f)
265
{
266
        struct video_device *dev = video_devdata(file);
267
        struct az_device *az = dev->priv;
268
 
269
        az->curfreq = f->frequency;
270
        az_setfreq(az, az->curfreq);
271
        return 0;
272
}
273
 
274
static int vidioc_g_frequency (struct file *file, void *priv,
275
                                struct v4l2_frequency *f)
276
{
277
        struct video_device *dev = video_devdata(file);
278
        struct az_device *az = dev->priv;
279
 
280
        f->type = V4L2_TUNER_RADIO;
281
        f->frequency = az->curfreq;
282
 
283
        return 0;
284
}
285
 
286
static int vidioc_queryctrl (struct file *file, void *priv,
287
                            struct v4l2_queryctrl *qc)
288
{
289
        int i;
290
 
291
        for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) {
292
                if (qc->id && qc->id == radio_qctrl[i].id) {
293
                        memcpy(qc, &(radio_qctrl[i]),
294
                                                sizeof(*qc));
295
                        return (0);
296
                }
297
        }
298
        return -EINVAL;
299
}
300
 
301
static int vidioc_g_ctrl (struct file *file, void *priv,
302
                            struct v4l2_control *ctrl)
303
{
304
        struct video_device *dev = video_devdata(file);
305
        struct az_device *az = dev->priv;
306
 
307
        switch (ctrl->id) {
308
                case V4L2_CID_AUDIO_MUTE:
309
                        if (az->curvol==0)
310
                                ctrl->value=1;
311
                        else
312
                                ctrl->value=0;
313
                        return (0);
314
                case V4L2_CID_AUDIO_VOLUME:
315
                        ctrl->value=az->curvol * 6554;
316
                        return (0);
317
        }
318
        return -EINVAL;
319
}
320
 
321
static int vidioc_s_ctrl (struct file *file, void *priv,
322
                            struct v4l2_control *ctrl)
323
{
324
        struct video_device *dev = video_devdata(file);
325
        struct az_device *az = dev->priv;
326
 
327
        switch (ctrl->id) {
328
                case V4L2_CID_AUDIO_MUTE:
329
                        if (ctrl->value) {
330
                                az_setvol(az,0);
331
                        } else {
332
                                az_setvol(az,az->curvol);
333
                        }
334
                        return (0);
335
                case V4L2_CID_AUDIO_VOLUME:
336
                        az_setvol(az,ctrl->value);
337
                        return (0);
338
        }
339
        return -EINVAL;
340
}
341
 
342
static struct az_device aztech_unit;
343
 
344
static const struct file_operations aztech_fops = {
345
        .owner          = THIS_MODULE,
346
        .open           = video_exclusive_open,
347
        .release        = video_exclusive_release,
348
        .ioctl          = video_ioctl2,
349
        .compat_ioctl   = v4l_compat_ioctl32,
350
        .llseek         = no_llseek,
351
};
352
 
353
static struct video_device aztech_radio=
354
{
355
        .owner              = THIS_MODULE,
356
        .name               = "Aztech radio",
357
        .type               = VID_TYPE_TUNER,
358
        .fops               = &aztech_fops,
359
        .vidioc_querycap    = vidioc_querycap,
360
        .vidioc_g_tuner     = vidioc_g_tuner,
361
        .vidioc_s_tuner     = vidioc_s_tuner,
362
        .vidioc_g_audio     = vidioc_g_audio,
363
        .vidioc_s_audio     = vidioc_s_audio,
364
        .vidioc_g_input     = vidioc_g_input,
365
        .vidioc_s_input     = vidioc_s_input,
366
        .vidioc_g_frequency = vidioc_g_frequency,
367
        .vidioc_s_frequency = vidioc_s_frequency,
368
        .vidioc_queryctrl   = vidioc_queryctrl,
369
        .vidioc_g_ctrl      = vidioc_g_ctrl,
370
        .vidioc_s_ctrl      = vidioc_s_ctrl,
371
};
372
 
373
module_param_named(debug,aztech_radio.debug, int, 0644);
374
MODULE_PARM_DESC(debug,"activates debug info");
375
 
376
static int __init aztech_init(void)
377
{
378
        if(io==-1)
379
        {
380
                printk(KERN_ERR "You must set an I/O address with io=0x???\n");
381
                return -EINVAL;
382
        }
383
 
384
        if (!request_region(io, 2, "aztech"))
385
        {
386
                printk(KERN_ERR "aztech: port 0x%x already in use\n", io);
387
                return -EBUSY;
388
        }
389
 
390
        mutex_init(&lock);
391
        aztech_radio.priv=&aztech_unit;
392
 
393
        if(video_register_device(&aztech_radio, VFL_TYPE_RADIO, radio_nr)==-1)
394
        {
395
                release_region(io,2);
396
                return -EINVAL;
397
        }
398
 
399
        printk(KERN_INFO "Aztech radio card driver v1.00/19990224 rkroll@exploits.org\n");
400
        /* mute card - prevents noisy bootups */
401
        outb (0, io);
402
        return 0;
403
}
404
 
405
MODULE_AUTHOR("Russell Kroll, Quay Lu, Donald Song, Jason Lewis, Scott McGrath, William McGrath");
406
MODULE_DESCRIPTION("A driver for the Aztech radio card.");
407
MODULE_LICENSE("GPL");
408
 
409
module_param(io, int, 0);
410
module_param(radio_nr, int, 0);
411
MODULE_PARM_DESC(io, "I/O address of the Aztech card (0x350 or 0x358)");
412
 
413
static void __exit aztech_cleanup(void)
414
{
415
        video_unregister_device(&aztech_radio);
416
        release_region(io,2);
417
}
418
 
419
module_init(aztech_init);
420
module_exit(aztech_cleanup);

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.