2 * Framework for ISA radio drivers.
3 * This takes care of all the V4L2 scaffolding, allowing the ISA drivers
4 * to concentrate on the actual hardware operation.
6 * Copyright (C) 2012 Hans Verkuil <hans.verkuil@cisco.com>
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * version 2 as published by the Free Software Foundation.
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
18 #include <linux/module.h>
19 #include <linux/init.h>
20 #include <linux/ioport.h>
21 #include <linux/delay.h>
22 #include <linux/videodev2.h>
24 #include <linux/slab.h>
25 #include <media/v4l2-device.h>
26 #include <media/v4l2-ioctl.h>
27 #include <media/v4l2-fh.h>
28 #include <media/v4l2-ctrls.h>
29 #include <media/v4l2-event.h>
31 #include "radio-isa.h"
33 MODULE_AUTHOR("Hans Verkuil");
34 MODULE_DESCRIPTION("A framework for ISA radio drivers.");
35 MODULE_LICENSE("GPL");
37 #define FREQ_LOW (87U * 16000U)
38 #define FREQ_HIGH (108U * 16000U)
40 static int radio_isa_querycap(struct file
*file
, void *priv
,
41 struct v4l2_capability
*v
)
43 struct radio_isa_card
*isa
= video_drvdata(file
);
45 strlcpy(v
->driver
, isa
->drv
->driver
.driver
.name
, sizeof(v
->driver
));
46 strlcpy(v
->card
, isa
->drv
->card
, sizeof(v
->card
));
47 snprintf(v
->bus_info
, sizeof(v
->bus_info
), "ISA:%s", isa
->v4l2_dev
.name
);
49 v
->device_caps
= V4L2_CAP_TUNER
| V4L2_CAP_RADIO
;
50 v
->capabilities
= v
->device_caps
| V4L2_CAP_DEVICE_CAPS
;
54 static int radio_isa_g_tuner(struct file
*file
, void *priv
,
57 struct radio_isa_card
*isa
= video_drvdata(file
);
58 const struct radio_isa_ops
*ops
= isa
->drv
->ops
;
63 strlcpy(v
->name
, "FM", sizeof(v
->name
));
64 v
->type
= V4L2_TUNER_RADIO
;
65 v
->rangelow
= FREQ_LOW
;
66 v
->rangehigh
= FREQ_HIGH
;
67 v
->capability
= V4L2_TUNER_CAP_LOW
;
68 if (isa
->drv
->has_stereo
)
69 v
->capability
|= V4L2_TUNER_CAP_STEREO
;
71 if (ops
->g_rxsubchans
)
72 v
->rxsubchans
= ops
->g_rxsubchans(isa
);
74 v
->rxsubchans
= V4L2_TUNER_SUB_MONO
| V4L2_TUNER_SUB_STEREO
;
75 v
->audmode
= isa
->stereo
? V4L2_TUNER_MODE_STEREO
: V4L2_TUNER_MODE_MONO
;
77 v
->signal
= ops
->g_signal(isa
);
79 v
->signal
= (v
->rxsubchans
& V4L2_TUNER_SUB_STEREO
) ?
84 static int radio_isa_s_tuner(struct file
*file
, void *priv
,
85 const struct v4l2_tuner
*v
)
87 struct radio_isa_card
*isa
= video_drvdata(file
);
88 const struct radio_isa_ops
*ops
= isa
->drv
->ops
;
93 isa
->stereo
= (v
->audmode
== V4L2_TUNER_MODE_STEREO
);
94 return ops
->s_stereo(isa
, isa
->stereo
);
99 static int radio_isa_s_frequency(struct file
*file
, void *priv
,
100 const struct v4l2_frequency
*f
)
102 struct radio_isa_card
*isa
= video_drvdata(file
);
103 u32 freq
= f
->frequency
;
106 if (f
->tuner
!= 0 || f
->type
!= V4L2_TUNER_RADIO
)
108 freq
= clamp(freq
, FREQ_LOW
, FREQ_HIGH
);
109 res
= isa
->drv
->ops
->s_frequency(isa
, freq
);
115 static int radio_isa_g_frequency(struct file
*file
, void *priv
,
116 struct v4l2_frequency
*f
)
118 struct radio_isa_card
*isa
= video_drvdata(file
);
122 f
->type
= V4L2_TUNER_RADIO
;
123 f
->frequency
= isa
->freq
;
127 static int radio_isa_s_ctrl(struct v4l2_ctrl
*ctrl
)
129 struct radio_isa_card
*isa
=
130 container_of(ctrl
->handler
, struct radio_isa_card
, hdl
);
133 case V4L2_CID_AUDIO_MUTE
:
134 return isa
->drv
->ops
->s_mute_volume(isa
, ctrl
->val
,
135 isa
->volume
? isa
->volume
->val
: 0);
140 static int radio_isa_log_status(struct file
*file
, void *priv
)
142 struct radio_isa_card
*isa
= video_drvdata(file
);
144 v4l2_info(&isa
->v4l2_dev
, "I/O Port = 0x%03x\n", isa
->io
);
145 v4l2_ctrl_handler_log_status(&isa
->hdl
, isa
->v4l2_dev
.name
);
149 static const struct v4l2_ctrl_ops radio_isa_ctrl_ops
= {
150 .s_ctrl
= radio_isa_s_ctrl
,
153 static const struct v4l2_file_operations radio_isa_fops
= {
154 .owner
= THIS_MODULE
,
155 .open
= v4l2_fh_open
,
156 .release
= v4l2_fh_release
,
157 .poll
= v4l2_ctrl_poll
,
158 .unlocked_ioctl
= video_ioctl2
,
161 static const struct v4l2_ioctl_ops radio_isa_ioctl_ops
= {
162 .vidioc_querycap
= radio_isa_querycap
,
163 .vidioc_g_tuner
= radio_isa_g_tuner
,
164 .vidioc_s_tuner
= radio_isa_s_tuner
,
165 .vidioc_g_frequency
= radio_isa_g_frequency
,
166 .vidioc_s_frequency
= radio_isa_s_frequency
,
167 .vidioc_log_status
= radio_isa_log_status
,
168 .vidioc_subscribe_event
= v4l2_ctrl_subscribe_event
,
169 .vidioc_unsubscribe_event
= v4l2_event_unsubscribe
,
172 int radio_isa_match(struct device
*pdev
, unsigned int dev
)
174 struct radio_isa_driver
*drv
= pdev
->platform_data
;
176 return drv
->probe
|| drv
->io_params
[dev
] >= 0;
178 EXPORT_SYMBOL_GPL(radio_isa_match
);
180 static bool radio_isa_valid_io(const struct radio_isa_driver
*drv
, int io
)
184 for (i
= 0; i
< drv
->num_of_io_ports
; i
++)
185 if (drv
->io_ports
[i
] == io
)
190 static struct radio_isa_card
*radio_isa_alloc(struct radio_isa_driver
*drv
,
193 struct v4l2_device
*v4l2_dev
;
194 struct radio_isa_card
*isa
= drv
->ops
->alloc();
198 dev_set_drvdata(pdev
, isa
);
200 v4l2_dev
= &isa
->v4l2_dev
;
201 strlcpy(v4l2_dev
->name
, dev_name(pdev
), sizeof(v4l2_dev
->name
));
206 static int radio_isa_common_probe(struct radio_isa_card
*isa
,
208 int radio_nr
, unsigned region_size
)
210 const struct radio_isa_driver
*drv
= isa
->drv
;
211 const struct radio_isa_ops
*ops
= drv
->ops
;
212 struct v4l2_device
*v4l2_dev
= &isa
->v4l2_dev
;
215 if (!request_region(isa
->io
, region_size
, v4l2_dev
->name
)) {
216 v4l2_err(v4l2_dev
, "port 0x%x already in use\n", isa
->io
);
221 res
= v4l2_device_register(pdev
, v4l2_dev
);
223 v4l2_err(v4l2_dev
, "Could not register v4l2_device\n");
227 v4l2_ctrl_handler_init(&isa
->hdl
, 1);
228 isa
->mute
= v4l2_ctrl_new_std(&isa
->hdl
, &radio_isa_ctrl_ops
,
229 V4L2_CID_AUDIO_MUTE
, 0, 1, 1, 1);
231 isa
->volume
= v4l2_ctrl_new_std(&isa
->hdl
, &radio_isa_ctrl_ops
,
232 V4L2_CID_AUDIO_VOLUME
, 0, drv
->max_volume
, 1,
234 v4l2_dev
->ctrl_handler
= &isa
->hdl
;
235 if (isa
->hdl
.error
) {
236 res
= isa
->hdl
.error
;
237 v4l2_err(v4l2_dev
, "Could not register controls\n");
241 v4l2_ctrl_cluster(2, &isa
->mute
);
242 v4l2_dev
->ctrl_handler
= &isa
->hdl
;
244 mutex_init(&isa
->lock
);
245 isa
->vdev
.lock
= &isa
->lock
;
246 strlcpy(isa
->vdev
.name
, v4l2_dev
->name
, sizeof(isa
->vdev
.name
));
247 isa
->vdev
.v4l2_dev
= v4l2_dev
;
248 isa
->vdev
.fops
= &radio_isa_fops
;
249 isa
->vdev
.ioctl_ops
= &radio_isa_ioctl_ops
;
250 isa
->vdev
.release
= video_device_release_empty
;
251 video_set_drvdata(&isa
->vdev
, isa
);
252 isa
->freq
= FREQ_LOW
;
253 isa
->stereo
= drv
->has_stereo
;
256 res
= ops
->init(isa
);
258 res
= v4l2_ctrl_handler_setup(&isa
->hdl
);
260 res
= ops
->s_frequency(isa
, isa
->freq
);
261 if (!res
&& ops
->s_stereo
)
262 res
= ops
->s_stereo(isa
, isa
->stereo
);
264 v4l2_err(v4l2_dev
, "Could not setup card\n");
267 res
= video_register_device(&isa
->vdev
, VFL_TYPE_RADIO
, radio_nr
);
270 v4l2_err(v4l2_dev
, "Could not register device node\n");
274 v4l2_info(v4l2_dev
, "Initialized radio card %s on port 0x%03x\n",
279 v4l2_ctrl_handler_free(&isa
->hdl
);
281 release_region(isa
->io
, region_size
);
286 static int radio_isa_common_remove(struct radio_isa_card
*isa
,
287 unsigned region_size
)
289 const struct radio_isa_ops
*ops
= isa
->drv
->ops
;
291 ops
->s_mute_volume(isa
, true, isa
->volume
? isa
->volume
->cur
.val
: 0);
292 video_unregister_device(&isa
->vdev
);
293 v4l2_ctrl_handler_free(&isa
->hdl
);
294 v4l2_device_unregister(&isa
->v4l2_dev
);
295 release_region(isa
->io
, region_size
);
296 v4l2_info(&isa
->v4l2_dev
, "Removed radio card %s\n", isa
->drv
->card
);
301 int radio_isa_probe(struct device
*pdev
, unsigned int dev
)
303 struct radio_isa_driver
*drv
= pdev
->platform_data
;
304 const struct radio_isa_ops
*ops
= drv
->ops
;
305 struct v4l2_device
*v4l2_dev
;
306 struct radio_isa_card
*isa
;
308 isa
= radio_isa_alloc(drv
, pdev
);
311 isa
->io
= drv
->io_params
[dev
];
312 v4l2_dev
= &isa
->v4l2_dev
;
314 if (drv
->probe
&& ops
->probe
) {
317 for (i
= 0; i
< drv
->num_of_io_ports
; ++i
) {
318 int io
= drv
->io_ports
[i
];
320 if (request_region(io
, drv
->region_size
, v4l2_dev
->name
)) {
321 bool found
= ops
->probe(isa
, io
);
323 release_region(io
, drv
->region_size
);
332 if (!radio_isa_valid_io(drv
, isa
->io
)) {
337 v4l2_err(v4l2_dev
, "you must set an I/O address with io=0x%03x",
339 for (i
= 1; i
< drv
->num_of_io_ports
; i
++)
340 printk(KERN_CONT
"/0x%03x", drv
->io_ports
[i
]);
341 printk(KERN_CONT
".\n");
346 return radio_isa_common_probe(isa
, pdev
, drv
->radio_nr_params
[dev
],
349 EXPORT_SYMBOL_GPL(radio_isa_probe
);
351 int radio_isa_remove(struct device
*pdev
, unsigned int dev
)
353 struct radio_isa_card
*isa
= dev_get_drvdata(pdev
);
355 return radio_isa_common_remove(isa
, isa
->drv
->region_size
);
357 EXPORT_SYMBOL_GPL(radio_isa_remove
);
360 int radio_isa_pnp_probe(struct pnp_dev
*dev
, const struct pnp_device_id
*dev_id
)
362 struct pnp_driver
*pnp_drv
= to_pnp_driver(dev
->dev
.driver
);
363 struct radio_isa_driver
*drv
= container_of(pnp_drv
,
364 struct radio_isa_driver
, pnp_driver
);
365 struct radio_isa_card
*isa
;
367 if (!pnp_port_valid(dev
, 0))
370 isa
= radio_isa_alloc(drv
, &dev
->dev
);
374 isa
->io
= pnp_port_start(dev
, 0);
376 return radio_isa_common_probe(isa
, &dev
->dev
, drv
->radio_nr_params
[0],
377 pnp_port_len(dev
, 0));
379 EXPORT_SYMBOL_GPL(radio_isa_pnp_probe
);
381 void radio_isa_pnp_remove(struct pnp_dev
*dev
)
383 struct radio_isa_card
*isa
= dev_get_drvdata(&dev
->dev
);
385 radio_isa_common_remove(isa
, pnp_port_len(dev
, 0));
387 EXPORT_SYMBOL_GPL(radio_isa_pnp_remove
);