1 // SPDX-License-Identifier: GPL-2.0-only
3 * Framework for ISA radio drivers.
4 * This takes care of all the V4L2 scaffolding, allowing the ISA drivers
5 * to concentrate on the actual hardware operation.
7 * Copyright (C) 2012 Hans Verkuil <hans.verkuil@cisco.com>
10 #include <linux/module.h>
11 #include <linux/init.h>
12 #include <linux/ioport.h>
13 #include <linux/delay.h>
14 #include <linux/videodev2.h>
16 #include <linux/slab.h>
17 #include <media/v4l2-device.h>
18 #include <media/v4l2-ioctl.h>
19 #include <media/v4l2-fh.h>
20 #include <media/v4l2-ctrls.h>
21 #include <media/v4l2-event.h>
23 #include "radio-isa.h"
25 MODULE_AUTHOR("Hans Verkuil");
26 MODULE_DESCRIPTION("A framework for ISA radio drivers.");
27 MODULE_LICENSE("GPL");
29 #define FREQ_LOW (87U * 16000U)
30 #define FREQ_HIGH (108U * 16000U)
32 static int radio_isa_querycap(struct file
*file
, void *priv
,
33 struct v4l2_capability
*v
)
35 struct radio_isa_card
*isa
= video_drvdata(file
);
37 strscpy(v
->driver
, isa
->drv
->driver
.driver
.name
, sizeof(v
->driver
));
38 strscpy(v
->card
, isa
->drv
->card
, sizeof(v
->card
));
39 snprintf(v
->bus_info
, sizeof(v
->bus_info
), "ISA:%s", isa
->v4l2_dev
.name
);
43 static int radio_isa_g_tuner(struct file
*file
, void *priv
,
46 struct radio_isa_card
*isa
= video_drvdata(file
);
47 const struct radio_isa_ops
*ops
= isa
->drv
->ops
;
52 strscpy(v
->name
, "FM", sizeof(v
->name
));
53 v
->type
= V4L2_TUNER_RADIO
;
54 v
->rangelow
= FREQ_LOW
;
55 v
->rangehigh
= FREQ_HIGH
;
56 v
->capability
= V4L2_TUNER_CAP_LOW
;
57 if (isa
->drv
->has_stereo
)
58 v
->capability
|= V4L2_TUNER_CAP_STEREO
;
60 if (ops
->g_rxsubchans
)
61 v
->rxsubchans
= ops
->g_rxsubchans(isa
);
63 v
->rxsubchans
= V4L2_TUNER_SUB_MONO
| V4L2_TUNER_SUB_STEREO
;
64 v
->audmode
= isa
->stereo
? V4L2_TUNER_MODE_STEREO
: V4L2_TUNER_MODE_MONO
;
66 v
->signal
= ops
->g_signal(isa
);
68 v
->signal
= (v
->rxsubchans
& V4L2_TUNER_SUB_STEREO
) ?
73 static int radio_isa_s_tuner(struct file
*file
, void *priv
,
74 const struct v4l2_tuner
*v
)
76 struct radio_isa_card
*isa
= video_drvdata(file
);
77 const struct radio_isa_ops
*ops
= isa
->drv
->ops
;
82 isa
->stereo
= (v
->audmode
== V4L2_TUNER_MODE_STEREO
);
83 return ops
->s_stereo(isa
, isa
->stereo
);
88 static int radio_isa_s_frequency(struct file
*file
, void *priv
,
89 const struct v4l2_frequency
*f
)
91 struct radio_isa_card
*isa
= video_drvdata(file
);
92 u32 freq
= f
->frequency
;
95 if (f
->tuner
!= 0 || f
->type
!= V4L2_TUNER_RADIO
)
97 freq
= clamp(freq
, FREQ_LOW
, FREQ_HIGH
);
98 res
= isa
->drv
->ops
->s_frequency(isa
, freq
);
104 static int radio_isa_g_frequency(struct file
*file
, void *priv
,
105 struct v4l2_frequency
*f
)
107 struct radio_isa_card
*isa
= video_drvdata(file
);
111 f
->type
= V4L2_TUNER_RADIO
;
112 f
->frequency
= isa
->freq
;
116 static int radio_isa_s_ctrl(struct v4l2_ctrl
*ctrl
)
118 struct radio_isa_card
*isa
=
119 container_of(ctrl
->handler
, struct radio_isa_card
, hdl
);
122 case V4L2_CID_AUDIO_MUTE
:
123 return isa
->drv
->ops
->s_mute_volume(isa
, ctrl
->val
,
124 isa
->volume
? isa
->volume
->val
: 0);
129 static int radio_isa_log_status(struct file
*file
, void *priv
)
131 struct radio_isa_card
*isa
= video_drvdata(file
);
133 v4l2_info(&isa
->v4l2_dev
, "I/O Port = 0x%03x\n", isa
->io
);
134 v4l2_ctrl_handler_log_status(&isa
->hdl
, isa
->v4l2_dev
.name
);
138 static const struct v4l2_ctrl_ops radio_isa_ctrl_ops
= {
139 .s_ctrl
= radio_isa_s_ctrl
,
142 static const struct v4l2_file_operations radio_isa_fops
= {
143 .owner
= THIS_MODULE
,
144 .open
= v4l2_fh_open
,
145 .release
= v4l2_fh_release
,
146 .poll
= v4l2_ctrl_poll
,
147 .unlocked_ioctl
= video_ioctl2
,
150 static const struct v4l2_ioctl_ops radio_isa_ioctl_ops
= {
151 .vidioc_querycap
= radio_isa_querycap
,
152 .vidioc_g_tuner
= radio_isa_g_tuner
,
153 .vidioc_s_tuner
= radio_isa_s_tuner
,
154 .vidioc_g_frequency
= radio_isa_g_frequency
,
155 .vidioc_s_frequency
= radio_isa_s_frequency
,
156 .vidioc_log_status
= radio_isa_log_status
,
157 .vidioc_subscribe_event
= v4l2_ctrl_subscribe_event
,
158 .vidioc_unsubscribe_event
= v4l2_event_unsubscribe
,
161 int radio_isa_match(struct device
*pdev
, unsigned int dev
)
163 struct radio_isa_driver
*drv
= pdev
->platform_data
;
165 return drv
->probe
|| drv
->io_params
[dev
] >= 0;
167 EXPORT_SYMBOL_GPL(radio_isa_match
);
169 static bool radio_isa_valid_io(const struct radio_isa_driver
*drv
, int io
)
173 for (i
= 0; i
< drv
->num_of_io_ports
; i
++)
174 if (drv
->io_ports
[i
] == io
)
179 static struct radio_isa_card
*radio_isa_alloc(struct radio_isa_driver
*drv
,
182 struct v4l2_device
*v4l2_dev
;
183 struct radio_isa_card
*isa
= drv
->ops
->alloc();
187 dev_set_drvdata(pdev
, isa
);
189 v4l2_dev
= &isa
->v4l2_dev
;
190 strscpy(v4l2_dev
->name
, dev_name(pdev
), sizeof(v4l2_dev
->name
));
195 static int radio_isa_common_probe(struct radio_isa_card
*isa
,
197 int radio_nr
, unsigned region_size
)
199 const struct radio_isa_driver
*drv
= isa
->drv
;
200 const struct radio_isa_ops
*ops
= drv
->ops
;
201 struct v4l2_device
*v4l2_dev
= &isa
->v4l2_dev
;
204 if (!request_region(isa
->io
, region_size
, v4l2_dev
->name
)) {
205 v4l2_err(v4l2_dev
, "port 0x%x already in use\n", isa
->io
);
210 res
= v4l2_device_register(pdev
, v4l2_dev
);
212 v4l2_err(v4l2_dev
, "Could not register v4l2_device\n");
216 v4l2_ctrl_handler_init(&isa
->hdl
, 1);
217 isa
->mute
= v4l2_ctrl_new_std(&isa
->hdl
, &radio_isa_ctrl_ops
,
218 V4L2_CID_AUDIO_MUTE
, 0, 1, 1, 1);
220 isa
->volume
= v4l2_ctrl_new_std(&isa
->hdl
, &radio_isa_ctrl_ops
,
221 V4L2_CID_AUDIO_VOLUME
, 0, drv
->max_volume
, 1,
223 v4l2_dev
->ctrl_handler
= &isa
->hdl
;
224 if (isa
->hdl
.error
) {
225 res
= isa
->hdl
.error
;
226 v4l2_err(v4l2_dev
, "Could not register controls\n");
230 v4l2_ctrl_cluster(2, &isa
->mute
);
231 v4l2_dev
->ctrl_handler
= &isa
->hdl
;
233 mutex_init(&isa
->lock
);
234 isa
->vdev
.lock
= &isa
->lock
;
235 strscpy(isa
->vdev
.name
, v4l2_dev
->name
, sizeof(isa
->vdev
.name
));
236 isa
->vdev
.v4l2_dev
= v4l2_dev
;
237 isa
->vdev
.fops
= &radio_isa_fops
;
238 isa
->vdev
.ioctl_ops
= &radio_isa_ioctl_ops
;
239 isa
->vdev
.release
= video_device_release_empty
;
240 isa
->vdev
.device_caps
= V4L2_CAP_TUNER
| V4L2_CAP_RADIO
;
241 video_set_drvdata(&isa
->vdev
, isa
);
242 isa
->freq
= FREQ_LOW
;
243 isa
->stereo
= drv
->has_stereo
;
246 res
= ops
->init(isa
);
248 res
= v4l2_ctrl_handler_setup(&isa
->hdl
);
250 res
= ops
->s_frequency(isa
, isa
->freq
);
251 if (!res
&& ops
->s_stereo
)
252 res
= ops
->s_stereo(isa
, isa
->stereo
);
254 v4l2_err(v4l2_dev
, "Could not setup card\n");
257 res
= video_register_device(&isa
->vdev
, VFL_TYPE_RADIO
, radio_nr
);
260 v4l2_err(v4l2_dev
, "Could not register device node\n");
264 v4l2_info(v4l2_dev
, "Initialized radio card %s on port 0x%03x\n",
269 v4l2_ctrl_handler_free(&isa
->hdl
);
271 release_region(isa
->io
, region_size
);
276 static int radio_isa_common_remove(struct radio_isa_card
*isa
,
277 unsigned region_size
)
279 const struct radio_isa_ops
*ops
= isa
->drv
->ops
;
281 ops
->s_mute_volume(isa
, true, isa
->volume
? isa
->volume
->cur
.val
: 0);
282 video_unregister_device(&isa
->vdev
);
283 v4l2_ctrl_handler_free(&isa
->hdl
);
284 v4l2_device_unregister(&isa
->v4l2_dev
);
285 release_region(isa
->io
, region_size
);
286 v4l2_info(&isa
->v4l2_dev
, "Removed radio card %s\n", isa
->drv
->card
);
291 int radio_isa_probe(struct device
*pdev
, unsigned int dev
)
293 struct radio_isa_driver
*drv
= pdev
->platform_data
;
294 const struct radio_isa_ops
*ops
= drv
->ops
;
295 struct v4l2_device
*v4l2_dev
;
296 struct radio_isa_card
*isa
;
298 isa
= radio_isa_alloc(drv
, pdev
);
301 isa
->io
= drv
->io_params
[dev
];
302 v4l2_dev
= &isa
->v4l2_dev
;
304 if (drv
->probe
&& ops
->probe
) {
307 for (i
= 0; i
< drv
->num_of_io_ports
; ++i
) {
308 int io
= drv
->io_ports
[i
];
310 if (request_region(io
, drv
->region_size
, v4l2_dev
->name
)) {
311 bool found
= ops
->probe(isa
, io
);
313 release_region(io
, drv
->region_size
);
322 if (!radio_isa_valid_io(drv
, isa
->io
)) {
327 v4l2_err(v4l2_dev
, "you must set an I/O address with io=0x%03x",
329 for (i
= 1; i
< drv
->num_of_io_ports
; i
++)
330 printk(KERN_CONT
"/0x%03x", drv
->io_ports
[i
]);
331 printk(KERN_CONT
".\n");
336 return radio_isa_common_probe(isa
, pdev
, drv
->radio_nr_params
[dev
],
339 EXPORT_SYMBOL_GPL(radio_isa_probe
);
341 int radio_isa_remove(struct device
*pdev
, unsigned int dev
)
343 struct radio_isa_card
*isa
= dev_get_drvdata(pdev
);
345 return radio_isa_common_remove(isa
, isa
->drv
->region_size
);
347 EXPORT_SYMBOL_GPL(radio_isa_remove
);
350 int radio_isa_pnp_probe(struct pnp_dev
*dev
, const struct pnp_device_id
*dev_id
)
352 struct pnp_driver
*pnp_drv
= to_pnp_driver(dev
->dev
.driver
);
353 struct radio_isa_driver
*drv
= container_of(pnp_drv
,
354 struct radio_isa_driver
, pnp_driver
);
355 struct radio_isa_card
*isa
;
357 if (!pnp_port_valid(dev
, 0))
360 isa
= radio_isa_alloc(drv
, &dev
->dev
);
364 isa
->io
= pnp_port_start(dev
, 0);
366 return radio_isa_common_probe(isa
, &dev
->dev
, drv
->radio_nr_params
[0],
367 pnp_port_len(dev
, 0));
369 EXPORT_SYMBOL_GPL(radio_isa_pnp_probe
);
371 void radio_isa_pnp_remove(struct pnp_dev
*dev
)
373 struct radio_isa_card
*isa
= dev_get_drvdata(&dev
->dev
);
375 radio_isa_common_remove(isa
, pnp_port_len(dev
, 0));
377 EXPORT_SYMBOL_GPL(radio_isa_pnp_remove
);