aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/radio/radio-maestro.c
diff options
context:
space:
mode:
authorMauro Carvalho Chehab <mchehab@infradead.org>2006-08-08 08:10:02 -0400
committerMauro Carvalho Chehab <mchehab@infradead.org>2006-09-26 10:53:12 -0400
commitb6055d7b1841e14ecc8c72a11490b42c85bf7bec (patch)
tree7c2d82befc5c79b719b5b2f805f8810664728343 /drivers/media/radio/radio-maestro.c
parent52afbc2f4f1ab78c038bc0d56273ca68021bd3d5 (diff)
V4L/DVB (4351): V4L2 conversion: radio-maestro
Driver conversion to V4L2 API. Require some testing, since I don't have such hardware Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Diffstat (limited to 'drivers/media/radio/radio-maestro.c')
-rw-r--r--drivers/media/radio/radio-maestro.c197
1 files changed, 130 insertions, 67 deletions
diff --git a/drivers/media/radio/radio-maestro.c b/drivers/media/radio/radio-maestro.c
index fcfa6c9fe225..e8ce5f75cf12 100644
--- a/drivers/media/radio/radio-maestro.c
+++ b/drivers/media/radio/radio-maestro.c
@@ -14,6 +14,8 @@
14 * version 0.04 14 * version 0.04
15 * + code improvements 15 * + code improvements
16 * + VIDEO_TUNER_LOW is permanent 16 * + VIDEO_TUNER_LOW is permanent
17 *
18 * Converted to V4L2 API by Mauro Carvalho Chehab <mchehab@infradead.org>
17 */ 19 */
18 20
19#include <linux/module.h> 21#include <linux/module.h>
@@ -25,10 +27,23 @@
25#include <asm/uaccess.h> 27#include <asm/uaccess.h>
26#include <linux/mutex.h> 28#include <linux/mutex.h>
27#include <linux/pci.h> 29#include <linux/pci.h>
28#include <linux/videodev.h> 30#include <linux/videodev2.h>
29#include <media/v4l2-common.h> 31#include <media/v4l2-common.h>
30 32
31#define DRIVER_VERSION "0.05" 33#include <linux/version.h> /* for KERNEL_VERSION MACRO */
34#define RADIO_VERSION KERNEL_VERSION(0,0,6)
35#define DRIVER_VERSION "0.06"
36
37static struct v4l2_queryctrl radio_qctrl[] = {
38 {
39 .id = V4L2_CID_AUDIO_MUTE,
40 .name = "Mute",
41 .minimum = 0,
42 .maximum = 1,
43 .default_value = 1,
44 .type = V4L2_CTRL_TYPE_BOOLEAN,
45 }
46};
32 47
33#define GPIO_DATA 0x60 /* port offset from ESS_IO_BASE */ 48#define GPIO_DATA 0x60 /* port offset from ESS_IO_BASE */
34 49
@@ -96,7 +111,7 @@ static struct file_operations maestro_fops = {
96static struct video_device maestro_radio = { 111static struct video_device maestro_radio = {
97 .name = "Maestro radio", 112 .name = "Maestro radio",
98 .type = VID_TYPE_TUNER, 113 .type = VID_TYPE_TUNER,
99 .hardware = VID_HARDWARE_SF16MI, 114 .hardware = 0,
100 .fops = &maestro_fops, 115 .fops = &maestro_fops,
101}; 116};
102 117
@@ -130,7 +145,7 @@ static u32 radio_bits_get(struct radio_device *dev)
130 rdata = inw(io); 145 rdata = inw(io);
131 if(!l) 146 if(!l)
132 dev->stereo = rdata & STR_MOST ? 147 dev->stereo = rdata & STR_MOST ?
133 0 : VIDEO_TUNER_STEREO_ON; 148 0 : 1;
134 else 149 else
135 if(rdata & STR_DATA) 150 if(rdata & STR_DATA)
136 data++; 151 data++;
@@ -183,72 +198,120 @@ static inline int radio_function(struct inode *inode, struct file *file,
183 struct radio_device *card = video_get_drvdata(dev); 198 struct radio_device *card = video_get_drvdata(dev);
184 199
185 switch (cmd) { 200 switch (cmd) {
186 case VIDIOCGCAP: { 201 case VIDIOC_QUERYCAP:
187 struct video_capability *v = arg; 202 {
188 memset(v, 0, sizeof(*v)); 203 struct v4l2_capability *v = arg;
189 strcpy(v->name, "Maestro radio"); 204 memset(v,0,sizeof(*v));
190 v->type = VID_TYPE_TUNER; 205 strlcpy(v->driver, "radio-maestro", sizeof (v->driver));
191 v->channels = v->audios = 1; 206 strlcpy(v->card, "Maestro Radio", sizeof (v->card));
192 return 0; 207 sprintf(v->bus_info,"PCI");
193 } case VIDIOCGTUNER: { 208 v->version = RADIO_VERSION;
194 struct video_tuner *v = arg; 209 v->capabilities = V4L2_CAP_TUNER;
195 if (v->tuner) 210
196 return -EINVAL; 211 return 0;
197 (void)radio_bits_get(card); 212 }
198 v->flags = VIDEO_TUNER_LOW | card->stereo; 213 case VIDIOC_G_TUNER:
199 v->signal = card->tuned; 214 {
200 strcpy(v->name, "FM"); 215 struct v4l2_tuner *v = arg;
201 v->rangelow = FREQ_LO; 216
202 v->rangehigh = FREQ_HI; 217 if (v->index > 0)
203 v->mode = VIDEO_MODE_AUTO; 218 return -EINVAL;
204 return 0; 219
205 } case VIDIOCSTUNER: { 220 (void)radio_bits_get(card);
206 struct video_tuner *v = arg; 221
207 if (v->tuner != 0) 222 memset(v,0,sizeof(*v));
208 return -EINVAL; 223 strcpy(v->name, "FM");
209 return 0; 224 v->type = V4L2_TUNER_RADIO;
210 } case VIDIOCGFREQ: { 225
211 unsigned long *freq = arg; 226 v->rangelow = FREQ_LO;
212 *freq = BITS2FREQ(radio_bits_get(card)); 227 v->rangehigh = FREQ_HI;
213 return 0; 228 v->rxsubchans =V4L2_TUNER_SUB_MONO|V4L2_TUNER_SUB_STEREO;
214 } case VIDIOCSFREQ: { 229 v->capability=V4L2_TUNER_CAP_LOW;
215 unsigned long *freq = arg; 230 if(card->stereo)
216 if (*freq < FREQ_LO || *freq > FREQ_HI) 231 v->audmode = V4L2_TUNER_MODE_STEREO;
232 else
233 v->audmode = V4L2_TUNER_MODE_MONO;
234 v->signal=card->tuned;
235
236 return 0;
237 }
238 case VIDIOC_S_TUNER:
239 {
240 struct v4l2_tuner *v = arg;
241
242 if (v->index > 0)
243 return -EINVAL;
244
245 return 0;
246 }
247 case VIDIOC_S_FREQUENCY:
248 {
249 struct v4l2_frequency *f = arg;
250
251 if (f->frequency < FREQ_LO || f->frequency > FREQ_HI)
252 return -EINVAL;
253 radio_bits_set(card, FREQ2BITS(f->frequency));
254
255 return 0;
256 }
257 case VIDIOC_G_FREQUENCY:
258 {
259 struct v4l2_frequency *f = arg;
260
261 f->type = V4L2_TUNER_RADIO;
262 f->frequency = BITS2FREQ(radio_bits_get(card));
263
264 return 0;
265 }
266 case VIDIOC_QUERYCTRL:
267 {
268 struct v4l2_queryctrl *qc = arg;
269 int i;
270
271 for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) {
272 if (qc->id && qc->id == radio_qctrl[i].id) {
273 memcpy(qc, &(radio_qctrl[i]),
274 sizeof(*qc));
275 return (0);
276 }
277 }
217 return -EINVAL; 278 return -EINVAL;
218 radio_bits_set(card, FREQ2BITS(*freq)); 279 }
219 return 0; 280 case VIDIOC_G_CTRL:
220 } case VIDIOCGAUDIO: { 281 {
221 struct video_audio *v = arg; 282 struct v4l2_control *ctrl= arg;
222 memset(v, 0, sizeof(*v)); 283
223 strcpy(v->name, "Radio"); 284 switch (ctrl->id) {
224 v->flags = VIDEO_AUDIO_MUTABLE | card->muted; 285 case V4L2_CID_AUDIO_MUTE:
225 v->mode = VIDEO_SOUND_STEREO; 286 ctrl->value=card->muted;
226 return 0; 287 return (0);
227 } case VIDIOCSAUDIO: { 288 }
228 struct video_audio *v = arg;
229 if (v->audio)
230 return -EINVAL; 289 return -EINVAL;
290 }
291 case VIDIOC_S_CTRL:
231 { 292 {
232 register u16 io = card->io; 293 struct v4l2_control *ctrl= arg;
233 register u16 omask = inw(io + IO_MASK); 294
234 outw(~STR_WREN, io + IO_MASK); 295 switch (ctrl->id) {
235 outw((card->muted = v->flags & VIDEO_AUDIO_MUTE) ? 296 case V4L2_CID_AUDIO_MUTE:
236 STR_WREN : 0, io); 297 {
237 udelay(4); 298 register u16 io = card->io;
238 outw(omask, io + IO_MASK); 299 register u16 omask = inw(io + IO_MASK);
239 msleep(125); 300 outw(~STR_WREN, io + IO_MASK);
240 return 0; 301 outw((card->muted = ctrl->value ) ?
302 STR_WREN : 0, io);
303 udelay(4);
304 outw(omask, io + IO_MASK);
305 msleep(125);
306
307 return (0);
308 }
309 }
310 return -EINVAL;
241 } 311 }
242 } case VIDIOCGUNIT: { 312 default:
243 struct video_unit *v = arg; 313 return v4l_compat_translate_ioctl(inode,file,cmd,arg,
244 v->video = VIDEO_NO_UNIT; 314 radio_function);
245 v->vbi = VIDEO_NO_UNIT;
246 v->radio = dev->minor;
247 v->audio = 0;
248 v->teletext = VIDEO_NO_UNIT;
249 return 0;
250 } default:
251 return -ENOIOCTLCMD;
252 } 315 }
253} 316}
254 317
@@ -275,7 +338,7 @@ static u16 __devinit radio_power_on(struct radio_device *dev)
275 omask = inw(io + IO_MASK); 338 omask = inw(io + IO_MASK);
276 odir = (inw(io + IO_DIR) & ~STR_DATA) | (STR_CLK | STR_WREN); 339 odir = (inw(io + IO_DIR) & ~STR_DATA) | (STR_CLK | STR_WREN);
277 outw(odir & ~STR_WREN, io + IO_DIR); 340 outw(odir & ~STR_WREN, io + IO_DIR);
278 dev->muted = inw(io) & STR_WREN ? 0 : VIDEO_AUDIO_MUTE; 341 dev->muted = inw(io) & STR_WREN ? 0 : 1;
279 outw(odir, io + IO_DIR); 342 outw(odir, io + IO_DIR);
280 outw(~(STR_WREN | STR_CLK), io + IO_MASK); 343 outw(~(STR_WREN | STR_CLK), io + IO_MASK);
281 outw(dev->muted ? 0 : STR_WREN, io); 344 outw(dev->muted ? 0 : STR_WREN, io);