aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/radio/radio-sf16fmi.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/radio/radio-sf16fmi.c')
-rw-r--r--drivers/media/radio/radio-sf16fmi.c158
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
34static 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
30struct fmi_device 45struct 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);