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.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
23 #include <linux/module.h>
24 #include <linux/init.h>
25 #include <linux/ioport.h>
26 #include <linux/delay.h>
27 #include <linux/videodev2.h>
29 #include <linux/slab.h>
30 #include <media/v4l2-device.h>
31 #include <media/v4l2-ioctl.h>
32 #include <media/v4l2-fh.h>
33 #include <media/v4l2-ctrls.h>
34 #include <media/v4l2-event.h>
36 #include "radio-isa.h"
38 MODULE_AUTHOR("Hans Verkuil");
39 MODULE_DESCRIPTION("A framework for ISA radio drivers.");
40 MODULE_LICENSE("GPL");
42 #define FREQ_LOW (87U * 16000U)
43 #define FREQ_HIGH (108U * 16000U)
45 static int radio_isa_querycap(struct file
*file
, void *priv
,
46 struct v4l2_capability
*v
)
48 struct radio_isa_card
*isa
= video_drvdata(file
);
50 strlcpy(v
->driver
, isa
->drv
->driver
.driver
.name
, sizeof(v
->driver
));
51 strlcpy(v
->card
, isa
->drv
->card
, sizeof(v
->card
));
52 snprintf(v
->bus_info
, sizeof(v
->bus_info
), "ISA:%s", isa
->v4l2_dev
.name
);
54 v
->device_caps
= V4L2_CAP_TUNER
| V4L2_CAP_RADIO
;
55 v
->capabilities
= v
->device_caps
| V4L2_CAP_DEVICE_CAPS
;
59 static int radio_isa_g_tuner(struct file
*file
, void *priv
,
62 struct radio_isa_card
*isa
= video_drvdata(file
);
63 const struct radio_isa_ops
*ops
= isa
->drv
->ops
;
68 strlcpy(v
->name
, "FM", sizeof(v
->name
));
69 v
->type
= V4L2_TUNER_RADIO
;
70 v
->rangelow
= FREQ_LOW
;
71 v
->rangehigh
= FREQ_HIGH
;
72 v
->capability
= V4L2_TUNER_CAP_LOW
;
73 if (isa
->drv
->has_stereo
)
74 v
->capability
|= V4L2_TUNER_CAP_STEREO
;
76 if (ops
->g_rxsubchans
)
77 v
->rxsubchans
= ops
->g_rxsubchans(isa
);
79 v
->rxsubchans
= V4L2_TUNER_SUB_MONO
| V4L2_TUNER_SUB_STEREO
;
80 v
->audmode
= isa
->stereo
? V4L2_TUNER_MODE_STEREO
: V4L2_TUNER_MODE_MONO
;
82 v
->signal
= ops
->g_signal(isa
);
84 v
->signal
= (v
->rxsubchans
& V4L2_TUNER_SUB_STEREO
) ?
89 static int radio_isa_s_tuner(struct file
*file
, void *priv
,
90 const struct v4l2_tuner
*v
)
92 struct radio_isa_card
*isa
= video_drvdata(file
);
93 const struct radio_isa_ops
*ops
= isa
->drv
->ops
;
98 isa
->stereo
= (v
->audmode
== V4L2_TUNER_MODE_STEREO
);
99 return ops
->s_stereo(isa
, isa
->stereo
);
104 static int radio_isa_s_frequency(struct file
*file
, void *priv
,
105 const struct v4l2_frequency
*f
)
107 struct radio_isa_card
*isa
= video_drvdata(file
);
108 u32 freq
= f
->frequency
;
111 if (f
->tuner
!= 0 || f
->type
!= V4L2_TUNER_RADIO
)
113 freq
= clamp(freq
, FREQ_LOW
, FREQ_HIGH
);
114 res
= isa
->drv
->ops
->s_frequency(isa
, freq
);
120 static int radio_isa_g_frequency(struct file
*file
, void *priv
,
121 struct v4l2_frequency
*f
)
123 struct radio_isa_card
*isa
= video_drvdata(file
);
127 f
->type
= V4L2_TUNER_RADIO
;
128 f
->frequency
= isa
->freq
;
132 static int radio_isa_s_ctrl(struct v4l2_ctrl
*ctrl
)
134 struct radio_isa_card
*isa
=
135 container_of(ctrl
->handler
, struct radio_isa_card
, hdl
);
138 case V4L2_CID_AUDIO_MUTE
:
139 return isa
->drv
->ops
->s_mute_volume(isa
, ctrl
->val
,
140 isa
->volume
? isa
->volume
->val
: 0);
145 static int radio_isa_log_status(struct file
*file
, void *priv
)
147 struct radio_isa_card
*isa
= video_drvdata(file
);
149 v4l2_info(&isa
->v4l2_dev
, "I/O Port = 0x%03x\n", isa
->io
);
150 v4l2_ctrl_handler_log_status(&isa
->hdl
, isa
->v4l2_dev
.name
);
154 static const struct v4l2_ctrl_ops radio_isa_ctrl_ops
= {
155 .s_ctrl
= radio_isa_s_ctrl
,
158 static const struct v4l2_file_operations radio_isa_fops
= {
159 .owner
= THIS_MODULE
,
160 .open
= v4l2_fh_open
,
161 .release
= v4l2_fh_release
,
162 .poll
= v4l2_ctrl_poll
,
163 .unlocked_ioctl
= video_ioctl2
,
166 static const struct v4l2_ioctl_ops radio_isa_ioctl_ops
= {
167 .vidioc_querycap
= radio_isa_querycap
,
168 .vidioc_g_tuner
= radio_isa_g_tuner
,
169 .vidioc_s_tuner
= radio_isa_s_tuner
,
170 .vidioc_g_frequency
= radio_isa_g_frequency
,
171 .vidioc_s_frequency
= radio_isa_s_frequency
,
172 .vidioc_log_status
= radio_isa_log_status
,
173 .vidioc_subscribe_event
= v4l2_ctrl_subscribe_event
,
174 .vidioc_unsubscribe_event
= v4l2_event_unsubscribe
,
177 int radio_isa_match(struct device
*pdev
, unsigned int dev
)
179 struct radio_isa_driver
*drv
= pdev
->platform_data
;
181 return drv
->probe
|| drv
->io_params
[dev
] >= 0;
183 EXPORT_SYMBOL_GPL(radio_isa_match
);
185 static bool radio_isa_valid_io(const struct radio_isa_driver
*drv
, int io
)
189 for (i
= 0; i
< drv
->num_of_io_ports
; i
++)
190 if (drv
->io_ports
[i
] == io
)
195 static struct radio_isa_card
*radio_isa_alloc(struct radio_isa_driver
*drv
,
198 struct v4l2_device
*v4l2_dev
;
199 struct radio_isa_card
*isa
= drv
->ops
->alloc();
203 dev_set_drvdata(pdev
, isa
);
205 v4l2_dev
= &isa
->v4l2_dev
;
206 strlcpy(v4l2_dev
->name
, dev_name(pdev
), sizeof(v4l2_dev
->name
));
211 static int radio_isa_common_probe(struct radio_isa_card
*isa
,
213 int radio_nr
, unsigned region_size
)
215 const struct radio_isa_driver
*drv
= isa
->drv
;
216 const struct radio_isa_ops
*ops
= drv
->ops
;
217 struct v4l2_device
*v4l2_dev
= &isa
->v4l2_dev
;
220 if (!request_region(isa
->io
, region_size
, v4l2_dev
->name
)) {
221 v4l2_err(v4l2_dev
, "port 0x%x already in use\n", isa
->io
);
226 res
= v4l2_device_register(pdev
, v4l2_dev
);
228 v4l2_err(v4l2_dev
, "Could not register v4l2_device\n");
232 v4l2_ctrl_handler_init(&isa
->hdl
, 1);
233 isa
->mute
= v4l2_ctrl_new_std(&isa
->hdl
, &radio_isa_ctrl_ops
,
234 V4L2_CID_AUDIO_MUTE
, 0, 1, 1, 1);
236 isa
->volume
= v4l2_ctrl_new_std(&isa
->hdl
, &radio_isa_ctrl_ops
,
237 V4L2_CID_AUDIO_VOLUME
, 0, drv
->max_volume
, 1,
239 v4l2_dev
->ctrl_handler
= &isa
->hdl
;
240 if (isa
->hdl
.error
) {
241 res
= isa
->hdl
.error
;
242 v4l2_err(v4l2_dev
, "Could not register controls\n");
246 v4l2_ctrl_cluster(2, &isa
->mute
);
247 v4l2_dev
->ctrl_handler
= &isa
->hdl
;
249 mutex_init(&isa
->lock
);
250 isa
->vdev
.lock
= &isa
->lock
;
251 strlcpy(isa
->vdev
.name
, v4l2_dev
->name
, sizeof(isa
->vdev
.name
));
252 isa
->vdev
.v4l2_dev
= v4l2_dev
;
253 isa
->vdev
.fops
= &radio_isa_fops
;
254 isa
->vdev
.ioctl_ops
= &radio_isa_ioctl_ops
;
255 isa
->vdev
.release
= video_device_release_empty
;
256 set_bit(V4L2_FL_USE_FH_PRIO
, &isa
->vdev
.flags
);
257 video_set_drvdata(&isa
->vdev
, isa
);
258 isa
->freq
= FREQ_LOW
;
259 isa
->stereo
= drv
->has_stereo
;
262 res
= ops
->init(isa
);
264 res
= v4l2_ctrl_handler_setup(&isa
->hdl
);
266 res
= ops
->s_frequency(isa
, isa
->freq
);
267 if (!res
&& ops
->s_stereo
)
268 res
= ops
->s_stereo(isa
, isa
->stereo
);
270 v4l2_err(v4l2_dev
, "Could not setup card\n");
273 res
= video_register_device(&isa
->vdev
, VFL_TYPE_RADIO
, radio_nr
);
276 v4l2_err(v4l2_dev
, "Could not register device node\n");
280 v4l2_info(v4l2_dev
, "Initialized radio card %s on port 0x%03x\n",
285 v4l2_ctrl_handler_free(&isa
->hdl
);
287 release_region(isa
->io
, region_size
);
292 static int radio_isa_common_remove(struct radio_isa_card
*isa
,
293 unsigned region_size
)
295 const struct radio_isa_ops
*ops
= isa
->drv
->ops
;
297 ops
->s_mute_volume(isa
, true, isa
->volume
? isa
->volume
->cur
.val
: 0);
298 video_unregister_device(&isa
->vdev
);
299 v4l2_ctrl_handler_free(&isa
->hdl
);
300 v4l2_device_unregister(&isa
->v4l2_dev
);
301 release_region(isa
->io
, region_size
);
302 v4l2_info(&isa
->v4l2_dev
, "Removed radio card %s\n", isa
->drv
->card
);
307 int radio_isa_probe(struct device
*pdev
, unsigned int dev
)
309 struct radio_isa_driver
*drv
= pdev
->platform_data
;
310 const struct radio_isa_ops
*ops
= drv
->ops
;
311 struct v4l2_device
*v4l2_dev
;
312 struct radio_isa_card
*isa
;
314 isa
= radio_isa_alloc(drv
, pdev
);
317 isa
->io
= drv
->io_params
[dev
];
318 v4l2_dev
= &isa
->v4l2_dev
;
320 if (drv
->probe
&& ops
->probe
) {
323 for (i
= 0; i
< drv
->num_of_io_ports
; ++i
) {
324 int io
= drv
->io_ports
[i
];
326 if (request_region(io
, drv
->region_size
, v4l2_dev
->name
)) {
327 bool found
= ops
->probe(isa
, io
);
329 release_region(io
, drv
->region_size
);
338 if (!radio_isa_valid_io(drv
, isa
->io
)) {
343 v4l2_err(v4l2_dev
, "you must set an I/O address with io=0x%03x",
345 for (i
= 1; i
< drv
->num_of_io_ports
; i
++)
346 printk(KERN_CONT
"/0x%03x", drv
->io_ports
[i
]);
347 printk(KERN_CONT
".\n");
352 return radio_isa_common_probe(isa
, pdev
, drv
->radio_nr_params
[dev
],
355 EXPORT_SYMBOL_GPL(radio_isa_probe
);
357 int radio_isa_remove(struct device
*pdev
, unsigned int dev
)
359 struct radio_isa_card
*isa
= dev_get_drvdata(pdev
);
361 return radio_isa_common_remove(isa
, isa
->drv
->region_size
);
363 EXPORT_SYMBOL_GPL(radio_isa_remove
);
366 int radio_isa_pnp_probe(struct pnp_dev
*dev
, const struct pnp_device_id
*dev_id
)
368 struct pnp_driver
*pnp_drv
= to_pnp_driver(dev
->dev
.driver
);
369 struct radio_isa_driver
*drv
= container_of(pnp_drv
,
370 struct radio_isa_driver
, pnp_driver
);
371 struct radio_isa_card
*isa
;
373 if (!pnp_port_valid(dev
, 0))
376 isa
= radio_isa_alloc(drv
, &dev
->dev
);
380 isa
->io
= pnp_port_start(dev
, 0);
382 return radio_isa_common_probe(isa
, &dev
->dev
, drv
->radio_nr_params
[0],
383 pnp_port_len(dev
, 0));
385 EXPORT_SYMBOL_GPL(radio_isa_pnp_probe
);
387 void radio_isa_pnp_remove(struct pnp_dev
*dev
)
389 struct radio_isa_card
*isa
= dev_get_drvdata(&dev
->dev
);
391 radio_isa_common_remove(isa
, pnp_port_len(dev
, 0));
393 EXPORT_SYMBOL_GPL(radio_isa_pnp_remove
);