diff options
author | Mauro Carvalho Chehab <mchehab@infradead.org> | 2006-08-08 08:10:02 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@infradead.org> | 2006-09-26 10:53:13 -0400 |
commit | a2ef73af4cd6cb46be13b11f9ce64d6b44f0350b (patch) | |
tree | d1bec6b312ff5861f32fb84dfa3b946f35f8bc65 /drivers/media/radio/radio-sf16fmi.c | |
parent | f8c559f8c066a045fb3f70bbb35f9e7c2064b8ae (diff) |
V4L/DVB (4353): V4L2 conversion: radio-sf16fmi
Driver conversion to V4L2 API.
Require some testing, since this obsolete hardware is not
common those days.
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Diffstat (limited to 'drivers/media/radio/radio-sf16fmi.c')
-rw-r--r-- | drivers/media/radio/radio-sf16fmi.c | 157 |
1 files changed, 100 insertions, 57 deletions
diff --git a/drivers/media/radio/radio-sf16fmi.c b/drivers/media/radio/radio-sf16fmi.c index efee6e339d15..43524119ac1c 100644 --- a/drivers/media/radio/radio-sf16fmi.c +++ b/drivers/media/radio/radio-sf16fmi.c | |||
@@ -13,6 +13,7 @@ | |||
13 | * No volume control - only mute/unmute - you have to use line volume | 13 | * No volume control - only mute/unmute - you have to use line volume |
14 | * control on SB-part of SF16FMI | 14 | * control on SB-part of SF16FMI |
15 | * | 15 | * |
16 | * Converted to V4L2 API by Mauro Carvalho Chehab <mchehab@infradead.org> | ||
16 | */ | 17 | */ |
17 | 18 | ||
18 | #include <linux/kernel.h> /* __setup */ | 19 | #include <linux/kernel.h> /* __setup */ |
@@ -20,13 +21,26 @@ | |||
20 | #include <linux/init.h> /* Initdata */ | 21 | #include <linux/init.h> /* Initdata */ |
21 | #include <linux/ioport.h> /* request_region */ | 22 | #include <linux/ioport.h> /* request_region */ |
22 | #include <linux/delay.h> /* udelay */ | 23 | #include <linux/delay.h> /* udelay */ |
23 | #include <linux/videodev.h> /* kernel radio structs */ | 24 | #include <linux/videodev2.h> /* kernel radio structs */ |
24 | #include <media/v4l2-common.h> | 25 | #include <media/v4l2-common.h> |
25 | #include <linux/isapnp.h> | 26 | #include <linux/isapnp.h> |
26 | #include <asm/io.h> /* outb, outb_p */ | 27 | #include <asm/io.h> /* outb, outb_p */ |
27 | #include <asm/uaccess.h> /* copy to/from user */ | 28 | #include <asm/uaccess.h> /* copy to/from user */ |
28 | #include <linux/mutex.h> | 29 | #include <linux/mutex.h> |
29 | 30 | ||
31 | #define RADIO_VERSION KERNEL_VERSION(0,0,2) | ||
32 | |||
33 | static struct v4l2_queryctrl radio_qctrl[] = { | ||
34 | { | ||
35 | .id = V4L2_CID_AUDIO_MUTE, | ||
36 | .name = "Mute", | ||
37 | .minimum = 0, | ||
38 | .maximum = 1, | ||
39 | .default_value = 1, | ||
40 | .type = V4L2_CTRL_TYPE_BOOLEAN, | ||
41 | } | ||
42 | }; | ||
43 | |||
30 | struct fmi_device | 44 | struct fmi_device |
31 | { | 45 | { |
32 | int port; | 46 | int port; |
@@ -123,93 +137,122 @@ static int fmi_do_ioctl(struct inode *inode, struct file *file, | |||
123 | 137 | ||
124 | switch(cmd) | 138 | switch(cmd) |
125 | { | 139 | { |
126 | case VIDIOCGCAP: | 140 | case VIDIOC_QUERYCAP: |
127 | { | 141 | { |
128 | struct video_capability *v = arg; | 142 | struct v4l2_capability *v = arg; |
129 | memset(v,0,sizeof(*v)); | 143 | memset(v,0,sizeof(*v)); |
130 | strcpy(v->name, "SF16-FMx radio"); | 144 | strlcpy(v->driver, "radio-sf16fmi", sizeof (v->driver)); |
131 | v->type=VID_TYPE_TUNER; | 145 | strlcpy(v->card, "SF16-FMx radio", sizeof (v->card)); |
132 | v->channels=1; | 146 | sprintf(v->bus_info,"ISA"); |
133 | v->audios=1; | 147 | v->version = RADIO_VERSION; |
148 | v->capabilities = V4L2_CAP_TUNER; | ||
149 | |||
134 | return 0; | 150 | return 0; |
135 | } | 151 | } |
136 | case VIDIOCGTUNER: | 152 | case VIDIOC_G_TUNER: |
137 | { | 153 | { |
138 | struct video_tuner *v = arg; | 154 | struct v4l2_tuner *v = arg; |
139 | int mult; | 155 | int mult; |
140 | 156 | ||
141 | if(v->tuner) /* Only 1 tuner */ | 157 | if (v->index > 0) |
142 | return -EINVAL; | 158 | return -EINVAL; |
159 | |||
160 | memset(v,0,sizeof(*v)); | ||
143 | strcpy(v->name, "FM"); | 161 | strcpy(v->name, "FM"); |
144 | mult = (fmi->flags & VIDEO_TUNER_LOW) ? 1 : 1000; | 162 | v->type = V4L2_TUNER_RADIO; |
163 | |||
164 | mult = (fmi->flags & V4L2_TUNER_CAP_LOW) ? 1 : 1000; | ||
145 | v->rangelow = RSF16_MINFREQ/mult; | 165 | v->rangelow = RSF16_MINFREQ/mult; |
146 | v->rangehigh = RSF16_MAXFREQ/mult; | 166 | v->rangehigh = RSF16_MAXFREQ/mult; |
147 | v->flags=fmi->flags; | 167 | v->rxsubchans =V4L2_TUNER_SUB_MONO | V4L2_TUNER_MODE_STEREO; |
148 | v->mode=VIDEO_MODE_AUTO; | 168 | v->capability=fmi->flags; |
169 | v->audmode = V4L2_TUNER_MODE_STEREO; | ||
149 | v->signal = fmi_getsigstr(fmi); | 170 | v->signal = fmi_getsigstr(fmi); |
171 | |||
150 | return 0; | 172 | return 0; |
151 | } | 173 | } |
152 | case VIDIOCSTUNER: | 174 | case VIDIOC_S_TUNER: |
153 | { | 175 | { |
154 | struct video_tuner *v = arg; | 176 | struct v4l2_tuner *v = arg; |
155 | if(v->tuner!=0) | 177 | |
178 | if (v->index > 0) | ||
156 | return -EINVAL; | 179 | return -EINVAL; |
157 | fmi->flags = v->flags & VIDEO_TUNER_LOW; | 180 | |
158 | /* Only 1 tuner so no setting needed ! */ | ||
159 | return 0; | ||
160 | } | ||
161 | case VIDIOCGFREQ: | ||
162 | { | ||
163 | unsigned long *freq = arg; | ||
164 | *freq = fmi->curfreq; | ||
165 | if (!(fmi->flags & VIDEO_TUNER_LOW)) | ||
166 | *freq /= 1000; | ||
167 | return 0; | 181 | return 0; |
168 | } | 182 | } |
169 | case VIDIOCSFREQ: | 183 | case VIDIOC_S_FREQUENCY: |
170 | { | 184 | { |
171 | unsigned long *freq = arg; | 185 | struct v4l2_frequency *f = arg; |
172 | if (!(fmi->flags & VIDEO_TUNER_LOW)) | 186 | |
173 | *freq *= 1000; | 187 | if (!(fmi->flags & V4L2_TUNER_CAP_LOW)) |
174 | if (*freq < RSF16_MINFREQ || *freq > RSF16_MAXFREQ ) | 188 | f->frequency *= 1000; |
189 | if (f->frequency < RSF16_MINFREQ || | ||
190 | f->frequency > RSF16_MAXFREQ ) | ||
175 | return -EINVAL; | 191 | return -EINVAL; |
176 | /*rounding in steps of 800 to match th freq | 192 | /*rounding in steps of 800 to match th freq |
177 | that will be used */ | 193 | that will be used */ |
178 | fmi->curfreq = (*freq/800)*800; | 194 | fmi->curfreq = (f->frequency/800)*800; |
179 | fmi_setfreq(fmi); | 195 | fmi_setfreq(fmi); |
196 | |||
180 | return 0; | 197 | return 0; |
181 | } | 198 | } |
182 | case VIDIOCGAUDIO: | 199 | case VIDIOC_G_FREQUENCY: |
183 | { | 200 | { |
184 | struct video_audio *v = arg; | 201 | struct v4l2_frequency *f = arg; |
185 | memset(v,0,sizeof(*v)); | 202 | |
186 | v->flags=( (!fmi->curvol)*VIDEO_AUDIO_MUTE | VIDEO_AUDIO_MUTABLE); | 203 | f->type = V4L2_TUNER_RADIO; |
187 | strcpy(v->name, "Radio"); | 204 | f->frequency = fmi->curfreq; |
188 | v->mode=VIDEO_SOUND_STEREO; | 205 | if (!(fmi->flags & V4L2_TUNER_CAP_LOW)) |
206 | f->frequency /= 1000; | ||
207 | |||
189 | return 0; | 208 | return 0; |
190 | } | 209 | } |
191 | case VIDIOCSAUDIO: | 210 | case VIDIOC_QUERYCTRL: |
192 | { | 211 | { |
193 | struct video_audio *v = arg; | 212 | struct v4l2_queryctrl *qc = arg; |
194 | if(v->audio) | 213 | int i; |
195 | return -EINVAL; | 214 | |
196 | fmi->curvol= v->flags&VIDEO_AUDIO_MUTE ? 0 : 1; | 215 | for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) { |
197 | fmi->curvol ? | 216 | if (qc->id && qc->id == radio_qctrl[i].id) { |
198 | fmi_unmute(fmi->port) : fmi_mute(fmi->port); | 217 | memcpy(qc, &(radio_qctrl[i]), |
199 | return 0; | 218 | sizeof(*qc)); |
219 | return (0); | ||
220 | } | ||
221 | } | ||
222 | return -EINVAL; | ||
200 | } | 223 | } |
201 | case VIDIOCGUNIT: | 224 | case VIDIOC_G_CTRL: |
202 | { | 225 | { |
203 | struct video_unit *v = arg; | 226 | struct v4l2_control *ctrl= arg; |
204 | v->video=VIDEO_NO_UNIT; | 227 | |
205 | v->vbi=VIDEO_NO_UNIT; | 228 | switch (ctrl->id) { |
206 | v->radio=dev->minor; | 229 | case V4L2_CID_AUDIO_MUTE: |
207 | v->audio=0; /* How do we find out this??? */ | 230 | ctrl->value=fmi->curvol; |
208 | v->teletext=VIDEO_NO_UNIT; | 231 | return (0); |
209 | return 0; | 232 | } |
233 | return -EINVAL; | ||
234 | } | ||
235 | case VIDIOC_S_CTRL: | ||
236 | { | ||
237 | struct v4l2_control *ctrl= arg; | ||
238 | |||
239 | switch (ctrl->id) { | ||
240 | case V4L2_CID_AUDIO_MUTE: | ||
241 | { | ||
242 | if (ctrl->value) | ||
243 | fmi_mute(fmi->port); | ||
244 | else | ||
245 | fmi_unmute(fmi->port); | ||
246 | |||
247 | fmi->curvol=ctrl->value; | ||
248 | return (0); | ||
249 | } | ||
250 | } | ||
251 | return -EINVAL; | ||
210 | } | 252 | } |
211 | default: | 253 | default: |
212 | return -ENOIOCTLCMD; | 254 | return v4l_compat_translate_ioctl(inode,file,cmd,arg, |
255 | fmi_do_ioctl); | ||
213 | } | 256 | } |
214 | } | 257 | } |
215 | 258 | ||
@@ -235,7 +278,7 @@ static struct video_device fmi_radio= | |||
235 | .owner = THIS_MODULE, | 278 | .owner = THIS_MODULE, |
236 | .name = "SF16FMx radio", | 279 | .name = "SF16FMx radio", |
237 | .type = VID_TYPE_TUNER, | 280 | .type = VID_TYPE_TUNER, |
238 | .hardware = VID_HARDWARE_SF16MI, | 281 | .hardware = 0, |
239 | .fops = &fmi_fops, | 282 | .fops = &fmi_fops, |
240 | }; | 283 | }; |
241 | 284 | ||
@@ -294,7 +337,7 @@ static int __init fmi_init(void) | |||
294 | fmi_unit.port = io; | 337 | fmi_unit.port = io; |
295 | fmi_unit.curvol = 0; | 338 | fmi_unit.curvol = 0; |
296 | fmi_unit.curfreq = 0; | 339 | fmi_unit.curfreq = 0; |
297 | fmi_unit.flags = VIDEO_TUNER_LOW; | 340 | fmi_unit.flags = V4L2_TUNER_CAP_LOW; |
298 | fmi_radio.priv = &fmi_unit; | 341 | fmi_radio.priv = &fmi_unit; |
299 | 342 | ||
300 | mutex_init(&lock); | 343 | mutex_init(&lock); |