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-maestro.c] - Blame information for rev 78

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/* Maestro PCI sound card radio driver for Linux support
2
 * (c) 2000 A. Tlalka, atlka@pg.gda.pl
3
 * Notes on the hardware
4
 *
5
 *  + Frequency control is done digitally
6
 *  + No volume control - only mute/unmute - you have to use Aux line volume
7
 *  control on Maestro card to set the volume
8
 *  + Radio status (tuned/not_tuned and stereo/mono) is valid some time after
9
 *  frequency setting (>100ms) and only when the radio is unmuted.
10
 *  version 0.02
11
 *  + io port is automatically detected - only the first radio is used
12
 *  version 0.03
13
 *  + thread access locking additions
14
 *  version 0.04
15
 * + code improvements
16
 * + VIDEO_TUNER_LOW is permanent
17
 *
18
 * Converted to V4L2 API by Mauro Carvalho Chehab <mchehab@infradead.org>
19
 */
20
 
21
#include <linux/module.h>
22
#include <linux/init.h>
23
#include <linux/ioport.h>
24
#include <linux/delay.h>
25
#include <asm/io.h>
26
#include <asm/uaccess.h>
27
#include <linux/pci.h>
28
#include <linux/videodev2.h>
29
#include <media/v4l2-common.h>
30
 
31
#include <linux/version.h>      /* for KERNEL_VERSION MACRO     */
32
#define RADIO_VERSION KERNEL_VERSION(0,0,6)
33
#define DRIVER_VERSION  "0.06"
34
 
35
static struct v4l2_queryctrl radio_qctrl[] = {
36
        {
37
                .id            = V4L2_CID_AUDIO_MUTE,
38
                .name          = "Mute",
39
                .minimum       = 0,
40
                .maximum       = 1,
41
                .default_value = 1,
42
                .type          = V4L2_CTRL_TYPE_BOOLEAN,
43
        }
44
};
45
 
46
#define GPIO_DATA       0x60   /* port offset from ESS_IO_BASE */
47
 
48
#define IO_MASK         4      /* mask      register offset from GPIO_DATA
49
                                bits 1=unmask write to given bit */
50
#define IO_DIR          8      /* direction register offset from GPIO_DATA
51
                                bits 0/1=read/write direction */
52
 
53
#define GPIO6           0x0040 /* mask bits for GPIO lines */
54
#define GPIO7           0x0080
55
#define GPIO8           0x0100
56
#define GPIO9           0x0200
57
 
58
#define STR_DATA        GPIO6  /* radio TEA5757 pins and GPIO bits */
59
#define STR_CLK         GPIO7
60
#define STR_WREN        GPIO8
61
#define STR_MOST        GPIO9
62
 
63
#define FREQ_LO          50*16000
64
#define FREQ_HI         150*16000
65
 
66
#define FREQ_IF         171200 /* 10.7*16000   */
67
#define FREQ_STEP       200    /* 12.5*16      */
68
 
69
#define FREQ2BITS(x)    ((((unsigned int)(x)+FREQ_IF+(FREQ_STEP<<1))\
70
                        /(FREQ_STEP<<2))<<2) /* (x==fmhz*16*1000) -> bits */
71
 
72
#define BITS2FREQ(x)    ((x) * FREQ_STEP - FREQ_IF)
73
 
74
static int radio_nr = -1;
75
module_param(radio_nr, int, 0);
76
 
77
static int maestro_probe(struct pci_dev *pdev, const struct pci_device_id *ent);
78
static void maestro_remove(struct pci_dev *pdev);
79
 
80
static struct pci_device_id maestro_r_pci_tbl[] = {
81
        { PCI_DEVICE(PCI_VENDOR_ID_ESS, PCI_DEVICE_ID_ESS_ESS1968),
82
                .class = PCI_CLASS_MULTIMEDIA_AUDIO << 8,
83
                .class_mask = 0xffff00 },
84
        { PCI_DEVICE(PCI_VENDOR_ID_ESS, PCI_DEVICE_ID_ESS_ESS1978),
85
                .class = PCI_CLASS_MULTIMEDIA_AUDIO << 8,
86
                .class_mask = 0xffff00 },
87
        { 0 }
88
};
89
MODULE_DEVICE_TABLE(pci, maestro_r_pci_tbl);
90
 
91
static struct pci_driver maestro_r_driver = {
92
        .name           = "maestro_radio",
93
        .id_table       = maestro_r_pci_tbl,
94
        .probe          = maestro_probe,
95
        .remove         = __devexit_p(maestro_remove),
96
};
97
 
98
static const struct file_operations maestro_fops = {
99
        .owner          = THIS_MODULE,
100
        .open           = video_exclusive_open,
101
        .release        = video_exclusive_release,
102
        .ioctl          = video_ioctl2,
103
        .compat_ioctl   = v4l_compat_ioctl32,
104
        .llseek         = no_llseek,
105
};
106
 
107
struct radio_device {
108
        u16     io,     /* base of Maestro card radio io (GPIO_DATA)*/
109
                muted,  /* VIDEO_AUDIO_MUTE */
110
                stereo, /* VIDEO_TUNER_STEREO_ON */
111
                tuned;  /* signal strength (0 or 0xffff) */
112
};
113
 
114
static u32 radio_bits_get(struct radio_device *dev)
115
{
116
        register u16 io=dev->io, l, rdata;
117
        register u32 data=0;
118
        u16 omask;
119
 
120
        omask = inw(io + IO_MASK);
121
        outw(~(STR_CLK | STR_WREN), io + IO_MASK);
122
        outw(0, io);
123
        udelay(16);
124
 
125
        for (l=24;l--;) {
126
                outw(STR_CLK, io);              /* HI state */
127
                udelay(2);
128
                if(!l)
129
                        dev->tuned = inw(io) & STR_MOST ? 0 : 0xffff;
130
                outw(0, io);                     /* LO state */
131
                udelay(2);
132
                data <<= 1;                     /* shift data */
133
                rdata = inw(io);
134
                if(!l)
135
                        dev->stereo =  rdata & STR_MOST ?
136
 
137
                else
138
                        if(rdata & STR_DATA)
139
                                data++;
140
                udelay(2);
141
        }
142
 
143
        if(dev->muted)
144
                outw(STR_WREN, io);
145
 
146
        udelay(4);
147
        outw(omask, io + IO_MASK);
148
 
149
        return data & 0x3ffe;
150
}
151
 
152
static void radio_bits_set(struct radio_device *dev, u32 data)
153
{
154
        register u16 io=dev->io, l, bits;
155
        u16 omask, odir;
156
 
157
        omask = inw(io + IO_MASK);
158
        odir  = (inw(io + IO_DIR) & ~STR_DATA) | (STR_CLK | STR_WREN);
159
        outw(odir | STR_DATA, io + IO_DIR);
160
        outw(~(STR_DATA | STR_CLK | STR_WREN), io + IO_MASK);
161
        udelay(16);
162
        for (l=25;l;l--) {
163
                bits = ((data >> 18) & STR_DATA) | STR_WREN ;
164
                data <<= 1;                     /* shift data */
165
                outw(bits, io);                 /* start strobe */
166
                udelay(2);
167
                outw(bits | STR_CLK, io);       /* HI level */
168
                udelay(2);
169
                outw(bits, io);                 /* LO level */
170
                udelay(4);
171
        }
172
 
173
        if(!dev->muted)
174
                outw(0, io);
175
 
176
        udelay(4);
177
        outw(omask, io + IO_MASK);
178
        outw(odir, io + IO_DIR);
179
        msleep(125);
180
}
181
 
182
static int vidioc_querycap(struct file *file, void  *priv,
183
                                        struct v4l2_capability *v)
184
{
185
        strlcpy(v->driver, "radio-maestro", sizeof(v->driver));
186
        strlcpy(v->card, "Maestro Radio", sizeof(v->card));
187
        sprintf(v->bus_info, "PCI");
188
        v->version = RADIO_VERSION;
189
        v->capabilities = V4L2_CAP_TUNER;
190
        return 0;
191
}
192
 
193
static int vidioc_g_tuner(struct file *file, void *priv,
194
                                        struct v4l2_tuner *v)
195
{
196
        struct video_device *dev = video_devdata(file);
197
        struct radio_device *card = video_get_drvdata(dev);
198
 
199
        if (v->index > 0)
200
                return -EINVAL;
201
 
202
        (void)radio_bits_get(card);
203
 
204
        strcpy(v->name, "FM");
205
        v->type = V4L2_TUNER_RADIO;
206
        v->rangelow = FREQ_LO;
207
        v->rangehigh = FREQ_HI;
208
        v->rxsubchans = V4L2_TUNER_SUB_MONO|V4L2_TUNER_SUB_STEREO;
209
        v->capability = V4L2_TUNER_CAP_LOW;
210
        if(card->stereo)
211
                v->audmode = V4L2_TUNER_MODE_STEREO;
212
        else
213
                v->audmode = V4L2_TUNER_MODE_MONO;
214
        v->signal = card->tuned;
215
        return 0;
216
}
217
 
218
static int vidioc_s_tuner(struct file *file, void *priv,
219
                                        struct v4l2_tuner *v)
220
{
221
        if (v->index > 0)
222
                return -EINVAL;
223
        return 0;
224
}
225
 
226
static int vidioc_s_frequency(struct file *file, void *priv,
227
                                        struct v4l2_frequency *f)
228
{
229
        struct video_device *dev = video_devdata(file);
230
        struct radio_device *card = video_get_drvdata(dev);
231
 
232
        if (f->frequency < FREQ_LO || f->frequency > FREQ_HI)
233
                return -EINVAL;
234
        radio_bits_set(card, FREQ2BITS(f->frequency));
235
        return 0;
236
}
237
 
238
static int vidioc_g_frequency(struct file *file, void *priv,
239
                                        struct v4l2_frequency *f)
240
{
241
        struct video_device *dev = video_devdata(file);
242
        struct radio_device *card = video_get_drvdata(dev);
243
 
244
        f->type = V4L2_TUNER_RADIO;
245
        f->frequency = BITS2FREQ(radio_bits_get(card));
246
        return 0;
247
}
248
 
249
static int vidioc_queryctrl(struct file *file, void *priv,
250
                                        struct v4l2_queryctrl *qc)
251
{
252
        int i;
253
 
254
        for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) {
255
                if (qc->id && qc->id == radio_qctrl[i].id) {
256
                        memcpy(qc, &(radio_qctrl[i]),
257
                                                sizeof(*qc));
258
                        return 0;
259
                }
260
        }
261
        return -EINVAL;
262
}
263
 
264
static int vidioc_g_ctrl(struct file *file, void *priv,
265
                                        struct v4l2_control *ctrl)
266
{
267
        struct video_device *dev = video_devdata(file);
268
        struct radio_device *card = video_get_drvdata(dev);
269
 
270
        switch (ctrl->id) {
271
        case V4L2_CID_AUDIO_MUTE:
272
                ctrl->value = card->muted;
273
                return 0;
274
        }
275
        return -EINVAL;
276
}
277
 
278
static int vidioc_s_ctrl(struct file *file, void *priv,
279
                                        struct v4l2_control *ctrl)
280
{
281
        struct video_device *dev = video_devdata(file);
282
        struct radio_device *card = video_get_drvdata(dev);
283
        register u16 io = card->io;
284
        register u16 omask = inw(io + IO_MASK);
285
 
286
        switch (ctrl->id) {
287
        case V4L2_CID_AUDIO_MUTE:
288
                outw(~STR_WREN, io + IO_MASK);
289
                outw((card->muted = ctrl->value ) ?
290
                                STR_WREN : 0, io);
291
                udelay(4);
292
                outw(omask, io + IO_MASK);
293
                msleep(125);
294
                return 0;
295
        }
296
        return -EINVAL;
297
}
298
 
299
static int vidioc_g_audio(struct file *file, void *priv,
300
                                        struct v4l2_audio *a)
301
{
302
        if (a->index > 1)
303
                return -EINVAL;
304
 
305
        strcpy(a->name, "Radio");
306
        a->capability = V4L2_AUDCAP_STEREO;
307
        return 0;
308
}
309
 
310
static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i)
311
{
312
        *i = 0;
313
        return 0;
314
}
315
 
316
static int vidioc_s_input(struct file *filp, void *priv, unsigned int i)
317
{
318
        if (i != 0)
319
                return -EINVAL;
320
        return 0;
321
}
322
 
323
static int vidioc_s_audio(struct file *file, void *priv,
324
                                        struct v4l2_audio *a)
325
{
326
        if (a->index != 0)
327
                return -EINVAL;
328
        return 0;
329
}
330
 
331
static u16 __devinit radio_power_on(struct radio_device *dev)
332
{
333
        register u16 io = dev->io;
334
        register u32 ofreq;
335
        u16 omask, odir;
336
 
337
        omask = inw(io + IO_MASK);
338
        odir = (inw(io + IO_DIR) & ~STR_DATA) | (STR_CLK | STR_WREN);
339
        outw(odir & ~STR_WREN, io + IO_DIR);
340
        dev->muted = inw(io) & STR_WREN ? 0 : 1;
341
        outw(odir, io + IO_DIR);
342
        outw(~(STR_WREN | STR_CLK), io + IO_MASK);
343
        outw(dev->muted ? 0 : STR_WREN, io);
344
        udelay(16);
345
        outw(omask, io + IO_MASK);
346
        ofreq = radio_bits_get(dev);
347
 
348
        if ((ofreq < FREQ2BITS(FREQ_LO)) || (ofreq > FREQ2BITS(FREQ_HI)))
349
                ofreq = FREQ2BITS(FREQ_LO);
350
        radio_bits_set(dev, ofreq);
351
 
352
        return (ofreq == radio_bits_get(dev));
353
}
354
 
355
static struct video_device maestro_radio = {
356
        .name           = "Maestro radio",
357
        .type           = VID_TYPE_TUNER,
358
        .fops           = &maestro_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
static int __devinit maestro_probe(struct pci_dev *pdev,
374
        const struct pci_device_id *ent)
375
{
376
        struct radio_device *radio_unit;
377
        struct video_device *maestro_radio_inst;
378
        int retval;
379
 
380
        retval = pci_enable_device(pdev);
381
        if (retval) {
382
                dev_err(&pdev->dev, "enabling pci device failed!\n");
383
                goto err;
384
        }
385
 
386
        retval = -ENOMEM;
387
 
388
        radio_unit = kzalloc(sizeof(*radio_unit), GFP_KERNEL);
389
        if (radio_unit == NULL) {
390
                dev_err(&pdev->dev, "not enough memory\n");
391
                goto err;
392
        }
393
 
394
        radio_unit->io = pci_resource_start(pdev, 0) + GPIO_DATA;
395
 
396
        maestro_radio_inst = video_device_alloc();
397
        if (maestro_radio_inst == NULL) {
398
                dev_err(&pdev->dev, "not enough memory\n");
399
                goto errfr;
400
        }
401
 
402
        memcpy(maestro_radio_inst, &maestro_radio, sizeof(maestro_radio));
403
        video_set_drvdata(maestro_radio_inst, radio_unit);
404
        pci_set_drvdata(pdev, maestro_radio_inst);
405
 
406
        retval = video_register_device(maestro_radio_inst, VFL_TYPE_RADIO,
407
                radio_nr);
408
        if (retval) {
409
                printk(KERN_ERR "can't register video device!\n");
410
                goto errfr1;
411
        }
412
 
413
        if (!radio_power_on(radio_unit)) {
414
                retval = -EIO;
415
                goto errunr;
416
        }
417
 
418
        dev_info(&pdev->dev, "version " DRIVER_VERSION " time " __TIME__ "  "
419
                 __DATE__ "\n");
420
        dev_info(&pdev->dev, "radio chip initialized\n");
421
 
422
        return 0;
423
errunr:
424
        video_unregister_device(maestro_radio_inst);
425
errfr1:
426
        kfree(maestro_radio_inst);
427
errfr:
428
        kfree(radio_unit);
429
err:
430
        return retval;
431
 
432
}
433
 
434
static void __devexit maestro_remove(struct pci_dev *pdev)
435
{
436
        struct video_device *vdev = pci_get_drvdata(pdev);
437
 
438
        video_unregister_device(vdev);
439
}
440
 
441
static int __init maestro_radio_init(void)
442
{
443
        int retval = pci_register_driver(&maestro_r_driver);
444
 
445
        if (retval)
446
                printk(KERN_ERR "error during registration pci driver\n");
447
 
448
        return retval;
449
}
450
 
451
static void __exit maestro_radio_exit(void)
452
{
453
        pci_unregister_driver(&maestro_r_driver);
454
}
455
 
456
module_init(maestro_radio_init);
457
module_exit(maestro_radio_exit);
458
 
459
MODULE_AUTHOR("Adam Tlalka, atlka@pg.gda.pl");
460
MODULE_DESCRIPTION("Radio driver for the Maestro PCI sound card radio.");
461
MODULE_LICENSE("GPL");

powered by: WebSVN 2.1.0

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