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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [drivers/] [media/] [radio/] [miropcm20-radio.c] - Blame information for rev 1275

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

Line No. Rev Author Line
1 1275 phoenix
/* Miro PCM20 radio driver for Linux radio support
2
 * (c) 1998 Ruurd Reitsma <R.A.Reitsma@wbmt.tudelft.nl>
3
 * Thanks to Norberto Pellici for the ACI device interface specification
4
 * The API part is based on the radiotrack driver by M. Kirkwood
5
 * This driver relies on the aci mixer (drivers/sound/aci.c)
6
 * Look there for further info...
7
 */
8
 
9
/* Revision history:
10
 *
11
 *   1998        Ruurd Reitsma <R.A.Reitsma@wbmt.tudelft.nl>
12
 *   2000-09-05  Robert Siemer <Robert.Siemer@gmx.de>
13
 *        removed unfinished volume control (maybe adding it later again)
14
 *        use OSS-mixer; added stereo control
15
 */
16
 
17
/* What ever you think about the ACI, version 0x07 is not very well!
18
 * I cant get frequency, 'tuner status', 'tuner flags' or mute/mono
19
 * conditions...                Robert
20
 */
21
 
22
#include <linux/module.h>
23
#include <linux/init.h>
24
#include <linux/videodev.h>
25
#include "../../sound/aci.h"
26
#include "miropcm20-rds-core.h"
27
 
28
static int users = 0;
29
static int radio_nr = -1;
30
MODULE_PARM(radio_nr, "i");
31
 
32
struct pcm20_device {
33
        unsigned long freq;
34
        int muted;
35
        int stereo;
36
};
37
 
38
 
39
static int pcm20_mute(struct pcm20_device *dev, unsigned char mute)
40
{
41
        dev->muted = mute;
42
        return aci_write_cmd(ACI_SET_TUNERMUTE, mute);
43
}
44
 
45
static int pcm20_stereo(struct pcm20_device *dev, unsigned char stereo)
46
{
47
        dev->stereo = stereo;
48
        return aci_write_cmd(ACI_SET_TUNERMONO, !stereo);
49
}
50
 
51
static int pcm20_setfreq(struct pcm20_device *dev, unsigned long freq)
52
{
53
        unsigned char freql;
54
        unsigned char freqh;
55
 
56
        dev->freq=freq;
57
 
58
        freq /= 160;
59
        if (!(aci_version==0x07 || aci_version>=0xb0))
60
                freq /= 10;  /* I don't know exactly which version
61
                              * needs this hack */
62
        freql = freq & 0xff;
63
        freqh = freq >> 8;
64
 
65
        aci_rds_cmd(RDS_RESET, 0, 0);
66
        pcm20_stereo(dev, 1);
67
 
68
        return aci_rw_cmd(ACI_WRITE_TUNE, freql, freqh);
69
}
70
 
71
static int pcm20_getflags(struct pcm20_device *dev, __u32 *flags, __u16 *signal)
72
{
73
        /* okay, check for signal, stereo and rds here... */
74
        int i;
75
        unsigned char buf;
76
 
77
        if ((i=aci_rw_cmd(ACI_READ_TUNERSTATION, -1, -1))<0)
78
                return i;
79
#if DEBUG
80
        printk("check_sig: 0x%x\n", i);
81
#endif
82
        if (i & 0x80) {
83
                /* no signal from tuner */
84
                *flags=0;
85
                *signal=0;
86
                return 0;
87
        } else
88
                *signal=0xffff;
89
 
90
        if ((i=aci_rw_cmd(ACI_READ_TUNERSTEREO, -1, -1))<0)
91
                return i;
92
        if (i & 0x40) {
93
                *flags=0;
94
        } else {
95
                /* stereo */
96
                *flags=VIDEO_TUNER_STEREO_ON;
97
                /* I cant see stereo, when forced to mono */
98
                dev->stereo=1;
99
        }
100
 
101
        if ((i=aci_rds_cmd(RDS_STATUS, &buf, 1))<0)
102
                return i;
103
        if (buf & 1)
104
                /* RDS available */
105
                *flags|=VIDEO_TUNER_RDS_ON;
106
        else
107
                return 0;
108
 
109
        if ((i=aci_rds_cmd(RDS_RXVALUE, &buf, 1))<0)
110
                return i;
111
#if DEBUG
112
        printk("rds-signal: %d\n", buf);
113
#endif
114
        if (buf > 15) {
115
                printk("miropcm20-radio: RX strengths unexpected high...\n");
116
                buf=15;
117
        }
118
        /* refine signal */
119
        if ((*signal=SCALE(15, 0xffff, buf))==0)
120
                *signal = 1;
121
 
122
        return 0;
123
}
124
 
125
static int pcm20_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
126
{
127
        struct pcm20_device *pcm20=dev->priv;
128
        int i;
129
 
130
        switch(cmd)
131
        {
132
                case VIDIOCGCAP:
133
                {
134
                        struct video_capability v;
135
                        v.type=VID_TYPE_TUNER;
136
                        strcpy(v.name, "Miro PCM20");
137
                        v.channels=1;
138
                        v.audios=1;
139
                        /* No we don't do pictures */
140
                        v.maxwidth=0;
141
                        v.maxheight=0;
142
                        v.minwidth=0;
143
                        v.minheight=0;
144
                        if(copy_to_user(arg,&v,sizeof(v)))
145
                                return -EFAULT;
146
                        return 0;
147
                }
148
                case VIDIOCGTUNER:
149
                {
150
                        struct video_tuner v;
151
                        if(copy_from_user(&v, arg,sizeof(v))!=0)
152
                                return -EFAULT;
153
                        if(v.tuner)     /* Only 1 tuner */
154
                                return -EINVAL;
155
                        v.rangelow=87*16000;
156
                        v.rangehigh=108*16000;
157
                        pcm20_getflags(pcm20, &v.flags, &v.signal);
158
                        v.flags|=VIDEO_TUNER_LOW;
159
                        v.mode=VIDEO_MODE_AUTO;
160
                        strcpy(v.name, "FM");
161
                        if(copy_to_user(arg,&v, sizeof(v)))
162
                                return -EFAULT;
163
                        return 0;
164
                }
165
                case VIDIOCSTUNER:
166
                {
167
                        struct video_tuner v;
168
                        if(copy_from_user(&v, arg, sizeof(v)))
169
                                return -EFAULT;
170
                        if(v.tuner!=0)
171
                                return -EINVAL;
172
                        /* Only 1 tuner so no setting needed ! */
173
                        return 0;
174
                }
175
                case VIDIOCGFREQ:
176
                        if(copy_to_user(arg, &pcm20->freq, sizeof(pcm20->freq)))
177
                                return -EFAULT;
178
                        return 0;
179
                case VIDIOCSFREQ:
180
                        if(copy_from_user(&pcm20->freq, arg, sizeof(pcm20->freq)))
181
                                return -EFAULT;
182
                        i=pcm20_setfreq(pcm20, pcm20->freq);
183
#if DEBUG
184
                        printk("First view (setfreq): 0x%x\n", i);
185
#endif
186
                        return i;
187
                case VIDIOCGAUDIO:
188
                {
189
                        struct video_audio v;
190
                        memset(&v,0, sizeof(v));
191
                        v.flags=VIDEO_AUDIO_MUTABLE;
192
                        if (pcm20->muted)
193
                                v.flags|=VIDEO_AUDIO_MUTE;
194
                        v.mode=VIDEO_SOUND_STEREO;
195
                        if (pcm20->stereo)
196
                                v.mode|=VIDEO_SOUND_MONO;
197
                        /* v.step=2048; */
198
                        strcpy(v.name, "Radio");
199
                        if(copy_to_user(arg,&v, sizeof(v)))
200
                                return -EFAULT;
201
                        return 0;
202
                }
203
                case VIDIOCSAUDIO:
204
                {
205
                        struct video_audio v;
206
                        if(copy_from_user(&v, arg, sizeof(v)))
207
                                return -EFAULT;
208
                        if(v.audio)
209
                                return -EINVAL;
210
 
211
                        pcm20_mute(pcm20, !!(v.flags&VIDEO_AUDIO_MUTE));
212
                        if(v.flags&VIDEO_SOUND_MONO)
213
                                pcm20_stereo(pcm20, 0);
214
                        if(v.flags&VIDEO_SOUND_STEREO)
215
                                pcm20_stereo(pcm20, 1);
216
 
217
                        return 0;
218
                }
219
                default:
220
                        return -ENOIOCTLCMD;
221
        }
222
}
223
 
224
static int pcm20_open(struct video_device *dev, int flags)
225
{
226
        if(users)
227
                return -EBUSY;
228
        users++;
229
        MOD_INC_USE_COUNT;
230
        return 0;
231
}
232
 
233
static void pcm20_close(struct video_device *dev)
234
{
235
        users--;
236
        MOD_DEC_USE_COUNT;
237
}
238
 
239
static struct pcm20_device pcm20_unit = {
240
        freq:   87*16000,
241
        muted:  1,
242
        stereo: 0
243
};
244
 
245
static struct video_device pcm20_radio = {
246
        owner:          THIS_MODULE,
247
        name:           "Miro PCM 20 radio",
248
        type:           VID_TYPE_TUNER,
249
        hardware:       VID_HARDWARE_RTRACK,
250
        open:           pcm20_open,
251
        close:          pcm20_close,
252
        ioctl:          pcm20_ioctl,
253
        priv:           &pcm20_unit
254
};
255
 
256
static int __init pcm20_init(void)
257
{
258
        if(video_register_device(&pcm20_radio, VFL_TYPE_RADIO, radio_nr)==-1)
259
                goto video_register_device;
260
 
261
        if(attach_aci_rds()<0)
262
                goto attach_aci_rds;
263
 
264
        printk(KERN_INFO "Miro PCM20 radio card driver.\n");
265
 
266
        return 0;
267
 
268
 attach_aci_rds:
269
        video_unregister_device(&pcm20_radio);
270
 video_register_device:
271
        return -EINVAL;
272
}
273
 
274
MODULE_AUTHOR("Ruurd Reitsma");
275
MODULE_DESCRIPTION("A driver for the Miro PCM20 radio card.");
276
MODULE_LICENSE("GPL");
277
 
278
EXPORT_NO_SYMBOLS;
279
 
280
static void __exit pcm20_cleanup(void)
281
{
282
        unload_aci_rds();
283
        video_unregister_device(&pcm20_radio);
284
}
285
 
286
module_init(pcm20_init);
287
module_exit(pcm20_cleanup);

powered by: WebSVN 2.1.0

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