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