aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/radio/radio-maestro.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/radio/radio-maestro.c')
-rw-r--r--drivers/media/radio/radio-maestro.c266
1 files changed, 143 insertions, 123 deletions
diff --git a/drivers/media/radio/radio-maestro.c b/drivers/media/radio/radio-maestro.c
index e67b7f258029..11f80cacd6ed 100644
--- a/drivers/media/radio/radio-maestro.c
+++ b/drivers/media/radio/radio-maestro.c
@@ -75,8 +75,6 @@ static struct v4l2_queryctrl radio_qctrl[] = {
75static int radio_nr = -1; 75static int radio_nr = -1;
76module_param(radio_nr, int, 0); 76module_param(radio_nr, int, 0);
77 77
78static int radio_ioctl(struct inode *inode, struct file *file,
79 unsigned int cmd, unsigned long arg);
80static int maestro_probe(struct pci_dev *pdev, const struct pci_device_id *ent); 78static int maestro_probe(struct pci_dev *pdev, const struct pci_device_id *ent);
81static void maestro_remove(struct pci_dev *pdev); 79static void maestro_remove(struct pci_dev *pdev);
82 80
@@ -102,18 +100,11 @@ static const struct file_operations maestro_fops = {
102 .owner = THIS_MODULE, 100 .owner = THIS_MODULE,
103 .open = video_exclusive_open, 101 .open = video_exclusive_open,
104 .release = video_exclusive_release, 102 .release = video_exclusive_release,
105 .ioctl = radio_ioctl, 103 .ioctl = video_ioctl2,
106 .compat_ioctl = v4l_compat_ioctl32, 104 .compat_ioctl = v4l_compat_ioctl32,
107 .llseek = no_llseek, 105 .llseek = no_llseek,
108}; 106};
109 107
110static struct video_device maestro_radio = {
111 .name = "Maestro radio",
112 .type = VID_TYPE_TUNER,
113 .hardware = 0,
114 .fops = &maestro_fops,
115};
116
117struct radio_device { 108struct radio_device {
118 u16 io, /* base of Maestro card radio io (GPIO_DATA)*/ 109 u16 io, /* base of Maestro card radio io (GPIO_DATA)*/
119 muted, /* VIDEO_AUDIO_MUTE */ 110 muted, /* VIDEO_AUDIO_MUTE */
@@ -190,142 +181,153 @@ static void radio_bits_set(struct radio_device *dev, u32 data)
190 msleep(125); 181 msleep(125);
191} 182}
192 183
193static inline int radio_function(struct inode *inode, struct file *file, 184static int vidioc_querycap(struct file *file, void *priv,
194 unsigned int cmd, void *arg) 185 struct v4l2_capability *v)
186{
187 strlcpy(v->driver, "radio-maestro", sizeof(v->driver));
188 strlcpy(v->card, "Maestro Radio", sizeof(v->card));
189 sprintf(v->bus_info, "PCI");
190 v->version = RADIO_VERSION;
191 v->capabilities = V4L2_CAP_TUNER;
192 return 0;
193}
194
195static int vidioc_g_tuner(struct file *file, void *priv,
196 struct v4l2_tuner *v)
195{ 197{
196 struct video_device *dev = video_devdata(file); 198 struct video_device *dev = video_devdata(file);
197 struct radio_device *card = video_get_drvdata(dev); 199 struct radio_device *card = video_get_drvdata(dev);
198 200
199 switch (cmd) { 201 if (v->index > 0)
200 case VIDIOC_QUERYCAP: 202 return -EINVAL;
201 { 203
202 struct v4l2_capability *v = arg; 204 (void)radio_bits_get(card);
203 memset(v,0,sizeof(*v)); 205
204 strlcpy(v->driver, "radio-maestro", sizeof (v->driver)); 206 strcpy(v->name, "FM");
205 strlcpy(v->card, "Maestro Radio", sizeof (v->card)); 207 v->type = V4L2_TUNER_RADIO;
206 sprintf(v->bus_info,"PCI"); 208 v->rangelow = FREQ_LO;
207 v->version = RADIO_VERSION; 209 v->rangehigh = FREQ_HI;
208 v->capabilities = V4L2_CAP_TUNER; 210 v->rxsubchans = V4L2_TUNER_SUB_MONO|V4L2_TUNER_SUB_STEREO;
209 211 v->capability = V4L2_TUNER_CAP_LOW;
210 return 0; 212 if(card->stereo)
211 } 213 v->audmode = V4L2_TUNER_MODE_STEREO;
212 case VIDIOC_G_TUNER: 214 else
213 { 215 v->audmode = V4L2_TUNER_MODE_MONO;
214 struct v4l2_tuner *v = arg; 216 v->signal = card->tuned;
215 217 return 0;
216 if (v->index > 0) 218}
217 return -EINVAL;
218
219 (void)radio_bits_get(card);
220 219
221 memset(v,0,sizeof(*v)); 220static int vidioc_s_tuner(struct file *file, void *priv,
222 strcpy(v->name, "FM"); 221 struct v4l2_tuner *v)
223 v->type = V4L2_TUNER_RADIO; 222{
223 if (v->index > 0)
224 return -EINVAL;
225 return 0;
226}
224 227
225 v->rangelow = FREQ_LO; 228static int vidioc_s_frequency(struct file *file, void *priv,
226 v->rangehigh = FREQ_HI; 229 struct v4l2_frequency *f)
227 v->rxsubchans =V4L2_TUNER_SUB_MONO|V4L2_TUNER_SUB_STEREO; 230{
228 v->capability=V4L2_TUNER_CAP_LOW; 231 struct video_device *dev = video_devdata(file);
229 if(card->stereo) 232 struct radio_device *card = video_get_drvdata(dev);
230 v->audmode = V4L2_TUNER_MODE_STEREO;
231 else
232 v->audmode = V4L2_TUNER_MODE_MONO;
233 v->signal=card->tuned;
234 233
235 return 0; 234 if (f->frequency < FREQ_LO || f->frequency > FREQ_HI)
236 } 235 return -EINVAL;
237 case VIDIOC_S_TUNER: 236 radio_bits_set(card, FREQ2BITS(f->frequency));
238 { 237 return 0;
239 struct v4l2_tuner *v = arg; 238}
240 239
241 if (v->index > 0) 240static int vidioc_g_frequency(struct file *file, void *priv,
242 return -EINVAL; 241 struct v4l2_frequency *f)
242{
243 struct video_device *dev = video_devdata(file);
244 struct radio_device *card = video_get_drvdata(dev);
243 245
244 return 0; 246 f->type = V4L2_TUNER_RADIO;
245 } 247 f->frequency = BITS2FREQ(radio_bits_get(card));
246 case VIDIOC_S_FREQUENCY: 248 return 0;
247 { 249}
248 struct v4l2_frequency *f = arg;
249 250
250 if (f->frequency < FREQ_LO || f->frequency > FREQ_HI) 251static int vidioc_queryctrl(struct file *file, void *priv,
251 return -EINVAL; 252 struct v4l2_queryctrl *qc)
252 radio_bits_set(card, FREQ2BITS(f->frequency)); 253{
254 int i;
253 255
256 for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) {
257 if (qc->id && qc->id == radio_qctrl[i].id) {
258 memcpy(qc, &(radio_qctrl[i]),
259 sizeof(*qc));
254 return 0; 260 return 0;
255 } 261 }
256 case VIDIOC_G_FREQUENCY: 262 }
257 { 263 return -EINVAL;
258 struct v4l2_frequency *f = arg; 264}
259 265
260 f->type = V4L2_TUNER_RADIO; 266static int vidioc_g_ctrl(struct file *file, void *priv,
261 f->frequency = BITS2FREQ(radio_bits_get(card)); 267 struct v4l2_control *ctrl)
268{
269 struct video_device *dev = video_devdata(file);
270 struct radio_device *card = video_get_drvdata(dev);
262 271
263 return 0; 272 switch (ctrl->id) {
264 } 273 case V4L2_CID_AUDIO_MUTE:
265 case VIDIOC_QUERYCTRL: 274 ctrl->value = card->muted;
266 { 275 return 0;
267 struct v4l2_queryctrl *qc = arg;
268 int i;
269
270 for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) {
271 if (qc->id && qc->id == radio_qctrl[i].id) {
272 memcpy(qc, &(radio_qctrl[i]),
273 sizeof(*qc));
274 return (0);
275 }
276 }
277 return -EINVAL;
278 }
279 case VIDIOC_G_CTRL:
280 {
281 struct v4l2_control *ctrl= arg;
282
283 switch (ctrl->id) {
284 case V4L2_CID_AUDIO_MUTE:
285 ctrl->value=card->muted;
286 return (0);
287 }
288 return -EINVAL;
289 }
290 case VIDIOC_S_CTRL:
291 {
292 struct v4l2_control *ctrl= arg;
293
294 switch (ctrl->id) {
295 case V4L2_CID_AUDIO_MUTE:
296 {
297 register u16 io = card->io;
298 register u16 omask = inw(io + IO_MASK);
299 outw(~STR_WREN, io + IO_MASK);
300 outw((card->muted = ctrl->value ) ?
301 STR_WREN : 0, io);
302 udelay(4);
303 outw(omask, io + IO_MASK);
304 msleep(125);
305
306 return (0);
307 }
308 }
309 return -EINVAL;
310 }
311 default:
312 return v4l_compat_translate_ioctl(inode,file,cmd,arg,
313 radio_function);
314 } 276 }
277 return -EINVAL;
315} 278}
316 279
317static int radio_ioctl(struct inode *inode, struct file *file, 280static int vidioc_s_ctrl(struct file *file, void *priv,
318 unsigned int cmd, unsigned long arg) 281 struct v4l2_control *ctrl)
319{ 282{
320 struct video_device *dev = video_devdata(file); 283 struct video_device *dev = video_devdata(file);
321 struct radio_device *card = video_get_drvdata(dev); 284 struct radio_device *card = video_get_drvdata(dev);
322 int ret; 285 register u16 io = card->io;
286 register u16 omask = inw(io + IO_MASK);
287
288 switch (ctrl->id) {
289 case V4L2_CID_AUDIO_MUTE:
290 outw(~STR_WREN, io + IO_MASK);
291 outw((card->muted = ctrl->value ) ?
292 STR_WREN : 0, io);
293 udelay(4);
294 outw(omask, io + IO_MASK);
295 msleep(125);
296 return 0;
297 }
298 return -EINVAL;
299}
323 300
324 mutex_lock(&card->lock); 301static int vidioc_g_audio(struct file *file, void *priv,
325 ret = video_usercopy(inode, file, cmd, arg, radio_function); 302 struct v4l2_audio *a)
326 mutex_unlock(&card->lock); 303{
304 if (a->index > 1)
305 return -EINVAL;
327 306
328 return ret; 307 strcpy(a->name, "Radio");
308 a->capability = V4L2_AUDCAP_STEREO;
309 return 0;
310}
311
312static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i)
313{
314 *i = 0;
315 return 0;
316}
317
318static int vidioc_s_input(struct file *filp, void *priv, unsigned int i)
319{
320 if (i != 0)
321 return -EINVAL;
322 return 0;
323}
324
325static int vidioc_s_audio(struct file *file, void *priv,
326 struct v4l2_audio *a)
327{
328 if (a->index != 0)
329 return -EINVAL;
330 return 0;
329} 331}
330 332
331static u16 __devinit radio_power_on(struct radio_device *dev) 333static u16 __devinit radio_power_on(struct radio_device *dev)
@@ -352,6 +354,24 @@ static u16 __devinit radio_power_on(struct radio_device *dev)
352 return (ofreq == radio_bits_get(dev)); 354 return (ofreq == radio_bits_get(dev));
353} 355}
354 356
357static struct video_device maestro_radio = {
358 .name = "Maestro radio",
359 .type = VID_TYPE_TUNER,
360 .fops = &maestro_fops,
361 .vidioc_querycap = vidioc_querycap,
362 .vidioc_g_tuner = vidioc_g_tuner,
363 .vidioc_s_tuner = vidioc_s_tuner,
364 .vidioc_g_audio = vidioc_g_audio,
365 .vidioc_s_audio = vidioc_s_audio,
366 .vidioc_g_input = vidioc_g_input,
367 .vidioc_s_input = vidioc_s_input,
368 .vidioc_g_frequency = vidioc_g_frequency,
369 .vidioc_s_frequency = vidioc_s_frequency,
370 .vidioc_queryctrl = vidioc_queryctrl,
371 .vidioc_g_ctrl = vidioc_g_ctrl,
372 .vidioc_s_ctrl = vidioc_s_ctrl,
373};
374
355static int __devinit maestro_probe(struct pci_dev *pdev, 375static int __devinit maestro_probe(struct pci_dev *pdev,
356 const struct pci_device_id *ent) 376 const struct pci_device_id *ent)
357{ 377{