diff options
author | Hans Verkuil <hverkuil@xs4all.nl> | 2009-03-06 11:50:07 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2009-03-30 11:43:12 -0400 |
commit | 79f94878bb8013b4043d51ec241d7fdc9a6a0312 (patch) | |
tree | fccc57dd7adbb6dbd3ac62c44ab409dd11c7c186 /drivers/media/radio | |
parent | bec2aec56561b70787ef62f070988594bd6d1b5f (diff) |
V4L/DVB (10883): radio-gemtek-pci: convert to v4l2_device.
Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/radio')
-rw-r--r-- | drivers/media/radio/radio-gemtek-pci.c | 330 |
1 files changed, 160 insertions, 170 deletions
diff --git a/drivers/media/radio/radio-gemtek-pci.c b/drivers/media/radio/radio-gemtek-pci.c index 0c96bf8525b0..dbc6097a51e5 100644 --- a/drivers/media/radio/radio-gemtek-pci.c +++ b/drivers/media/radio/radio-gemtek-pci.c | |||
@@ -45,34 +45,26 @@ | |||
45 | #include <linux/init.h> | 45 | #include <linux/init.h> |
46 | #include <linux/pci.h> | 46 | #include <linux/pci.h> |
47 | #include <linux/videodev2.h> | 47 | #include <linux/videodev2.h> |
48 | #include <media/v4l2-common.h> | ||
49 | #include <media/v4l2-ioctl.h> | ||
50 | #include <linux/errno.h> | 48 | #include <linux/errno.h> |
51 | |||
52 | #include <linux/version.h> /* for KERNEL_VERSION MACRO */ | 49 | #include <linux/version.h> /* for KERNEL_VERSION MACRO */ |
53 | #define RADIO_VERSION KERNEL_VERSION(0,0,2) | 50 | #include <linux/io.h> |
54 | 51 | #include <linux/uaccess.h> | |
55 | static struct v4l2_queryctrl radio_qctrl[] = { | 52 | #include <media/v4l2-device.h> |
56 | { | 53 | #include <media/v4l2-ioctl.h> |
57 | .id = V4L2_CID_AUDIO_MUTE, | ||
58 | .name = "Mute", | ||
59 | .minimum = 0, | ||
60 | .maximum = 1, | ||
61 | .default_value = 1, | ||
62 | .type = V4L2_CTRL_TYPE_BOOLEAN, | ||
63 | },{ | ||
64 | .id = V4L2_CID_AUDIO_VOLUME, | ||
65 | .name = "Volume", | ||
66 | .minimum = 0, | ||
67 | .maximum = 65535, | ||
68 | .step = 65535, | ||
69 | .default_value = 0xff, | ||
70 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
71 | } | ||
72 | }; | ||
73 | 54 | ||
74 | #include <asm/io.h> | 55 | MODULE_AUTHOR("Vladimir Shebordaev <vshebordaev@mail.ru>"); |
75 | #include <asm/uaccess.h> | 56 | MODULE_DESCRIPTION("The video4linux driver for the Gemtek PCI Radio Card"); |
57 | MODULE_LICENSE("GPL"); | ||
58 | |||
59 | static int nr_radio = -1; | ||
60 | static int mx = 1; | ||
61 | |||
62 | module_param(mx, bool, 0); | ||
63 | MODULE_PARM_DESC(mx, "single digit: 1 - turn off the turner upon module exit (default), 0 - do not"); | ||
64 | module_param(nr_radio, int, 0); | ||
65 | MODULE_PARM_DESC(nr_radio, "video4linux device number to use"); | ||
66 | |||
67 | #define RADIO_VERSION KERNEL_VERSION(0, 0, 2) | ||
76 | 68 | ||
77 | #ifndef PCI_VENDOR_ID_GEMTEK | 69 | #ifndef PCI_VENDOR_ID_GEMTEK |
78 | #define PCI_VENDOR_ID_GEMTEK 0x5046 | 70 | #define PCI_VENDOR_ID_GEMTEK 0x5046 |
@@ -90,8 +82,11 @@ static struct v4l2_queryctrl radio_qctrl[] = { | |||
90 | #define GEMTEK_PCI_RANGE_HIGH (108*16000) | 82 | #define GEMTEK_PCI_RANGE_HIGH (108*16000) |
91 | #endif | 83 | #endif |
92 | 84 | ||
93 | struct gemtek_pci_card { | 85 | struct gemtek_pci { |
94 | struct video_device *videodev; | 86 | struct v4l2_device v4l2_dev; |
87 | struct video_device vdev; | ||
88 | struct mutex lock; | ||
89 | struct pci_dev *pdev; | ||
95 | 90 | ||
96 | u32 iobase; | 91 | u32 iobase; |
97 | u32 length; | 92 | u32 length; |
@@ -100,116 +95,133 @@ struct gemtek_pci_card { | |||
100 | u8 mute; | 95 | u8 mute; |
101 | }; | 96 | }; |
102 | 97 | ||
103 | static int nr_radio = -1; | 98 | static inline struct gemtek_pci *to_gemtek_pci(struct v4l2_device *v4l2_dev) |
104 | static unsigned long in_use; | 99 | { |
100 | return container_of(v4l2_dev, struct gemtek_pci, v4l2_dev); | ||
101 | } | ||
105 | 102 | ||
106 | static inline u8 gemtek_pci_out( u16 value, u32 port ) | 103 | static inline u8 gemtek_pci_out(u16 value, u32 port) |
107 | { | 104 | { |
108 | outw( value, port ); | 105 | outw(value, port); |
109 | 106 | ||
110 | return (u8)value; | 107 | return (u8)value; |
111 | } | 108 | } |
112 | 109 | ||
113 | #define _b0( v ) *((u8 *)&v) | 110 | #define _b0(v) (*((u8 *)&v)) |
114 | static void __gemtek_pci_cmd( u16 value, u32 port, u8 *last_byte, int keep ) | 111 | |
112 | static void __gemtek_pci_cmd(u16 value, u32 port, u8 *last_byte, int keep) | ||
115 | { | 113 | { |
116 | register u8 byte = *last_byte; | 114 | u8 byte = *last_byte; |
117 | 115 | ||
118 | if ( !value ) { | 116 | if (!value) { |
119 | if ( !keep ) | 117 | if (!keep) |
120 | value = (u16)port; | 118 | value = (u16)port; |
121 | byte &= 0xfd; | 119 | byte &= 0xfd; |
122 | } else | 120 | } else |
123 | byte |= 2; | 121 | byte |= 2; |
124 | 122 | ||
125 | _b0( value ) = byte; | 123 | _b0(value) = byte; |
126 | outw( value, port ); | 124 | outw(value, port); |
127 | byte |= 1; | 125 | byte |= 1; |
128 | _b0( value ) = byte; | 126 | _b0(value) = byte; |
129 | outw( value, port ); | 127 | outw(value, port); |
130 | byte &= 0xfe; | 128 | byte &= 0xfe; |
131 | _b0( value ) = byte; | 129 | _b0(value) = byte; |
132 | outw( value, port ); | 130 | outw(value, port); |
133 | 131 | ||
134 | *last_byte = byte; | 132 | *last_byte = byte; |
135 | } | 133 | } |
136 | 134 | ||
137 | static inline void gemtek_pci_nil( u32 port, u8 *last_byte ) | 135 | static inline void gemtek_pci_nil(u32 port, u8 *last_byte) |
138 | { | 136 | { |
139 | __gemtek_pci_cmd( 0x00, port, last_byte, false ); | 137 | __gemtek_pci_cmd(0x00, port, last_byte, false); |
140 | } | 138 | } |
141 | 139 | ||
142 | static inline void gemtek_pci_cmd( u16 cmd, u32 port, u8 *last_byte ) | 140 | static inline void gemtek_pci_cmd(u16 cmd, u32 port, u8 *last_byte) |
143 | { | 141 | { |
144 | __gemtek_pci_cmd( cmd, port, last_byte, true ); | 142 | __gemtek_pci_cmd(cmd, port, last_byte, true); |
145 | } | 143 | } |
146 | 144 | ||
147 | static void gemtek_pci_setfrequency( struct gemtek_pci_card *card, unsigned long frequency ) | 145 | static void gemtek_pci_setfrequency(struct gemtek_pci *card, unsigned long frequency) |
148 | { | 146 | { |
149 | register int i; | 147 | int i; |
150 | register u32 value = frequency / 200 + 856; | 148 | u32 value = frequency / 200 + 856; |
151 | register u16 mask = 0x8000; | 149 | u16 mask = 0x8000; |
152 | u8 last_byte; | 150 | u8 last_byte; |
153 | u32 port = card->iobase; | 151 | u32 port = card->iobase; |
154 | 152 | ||
155 | last_byte = gemtek_pci_out( 0x06, port ); | 153 | mutex_lock(&card->lock); |
154 | card->current_frequency = frequency; | ||
155 | last_byte = gemtek_pci_out(0x06, port); | ||
156 | 156 | ||
157 | i = 0; | 157 | i = 0; |
158 | do { | 158 | do { |
159 | gemtek_pci_nil( port, &last_byte ); | 159 | gemtek_pci_nil(port, &last_byte); |
160 | i++; | 160 | i++; |
161 | } while ( i < 9 ); | 161 | } while (i < 9); |
162 | 162 | ||
163 | i = 0; | 163 | i = 0; |
164 | do { | 164 | do { |
165 | gemtek_pci_cmd( value & mask, port, &last_byte ); | 165 | gemtek_pci_cmd(value & mask, port, &last_byte); |
166 | mask >>= 1; | 166 | mask >>= 1; |
167 | i++; | 167 | i++; |
168 | } while ( i < 16 ); | 168 | } while (i < 16); |
169 | 169 | ||
170 | outw( 0x10, port ); | 170 | outw(0x10, port); |
171 | mutex_unlock(&card->lock); | ||
171 | } | 172 | } |
172 | 173 | ||
173 | 174 | ||
174 | static inline void gemtek_pci_mute( struct gemtek_pci_card *card ) | 175 | static void gemtek_pci_mute(struct gemtek_pci *card) |
175 | { | 176 | { |
176 | outb( 0x1f, card->iobase ); | 177 | mutex_lock(&card->lock); |
178 | outb(0x1f, card->iobase); | ||
177 | card->mute = true; | 179 | card->mute = true; |
180 | mutex_unlock(&card->lock); | ||
178 | } | 181 | } |
179 | 182 | ||
180 | static inline void gemtek_pci_unmute( struct gemtek_pci_card *card ) | 183 | static void gemtek_pci_unmute(struct gemtek_pci *card) |
181 | { | 184 | { |
182 | if ( card->mute ) { | 185 | mutex_lock(&card->lock); |
183 | gemtek_pci_setfrequency( card, card->current_frequency ); | 186 | if (card->mute) { |
187 | gemtek_pci_setfrequency(card, card->current_frequency); | ||
184 | card->mute = false; | 188 | card->mute = false; |
185 | } | 189 | } |
190 | mutex_unlock(&card->lock); | ||
186 | } | 191 | } |
187 | 192 | ||
188 | static inline unsigned int gemtek_pci_getsignal( struct gemtek_pci_card *card ) | 193 | static int gemtek_pci_getsignal(struct gemtek_pci *card) |
189 | { | 194 | { |
190 | return ( inb( card->iobase ) & 0x08 ) ? 0 : 1; | 195 | int sig; |
196 | |||
197 | mutex_lock(&card->lock); | ||
198 | sig = (inb(card->iobase) & 0x08) ? 0 : 1; | ||
199 | mutex_unlock(&card->lock); | ||
200 | return sig; | ||
191 | } | 201 | } |
192 | 202 | ||
193 | static int vidioc_querycap(struct file *file, void *priv, | 203 | static int vidioc_querycap(struct file *file, void *priv, |
194 | struct v4l2_capability *v) | 204 | struct v4l2_capability *v) |
195 | { | 205 | { |
206 | struct gemtek_pci *card = video_drvdata(file); | ||
207 | |||
196 | strlcpy(v->driver, "radio-gemtek-pci", sizeof(v->driver)); | 208 | strlcpy(v->driver, "radio-gemtek-pci", sizeof(v->driver)); |
197 | strlcpy(v->card, "GemTek PCI Radio", sizeof(v->card)); | 209 | strlcpy(v->card, "GemTek PCI Radio", sizeof(v->card)); |
198 | sprintf(v->bus_info, "ISA"); | 210 | snprintf(v->bus_info, sizeof(v->bus_info), "PCI:%s", pci_name(card->pdev)); |
199 | v->version = RADIO_VERSION; | 211 | v->version = RADIO_VERSION; |
200 | v->capabilities = V4L2_CAP_TUNER; | 212 | v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO; |
201 | return 0; | 213 | return 0; |
202 | } | 214 | } |
203 | 215 | ||
204 | static int vidioc_g_tuner(struct file *file, void *priv, | 216 | static int vidioc_g_tuner(struct file *file, void *priv, |
205 | struct v4l2_tuner *v) | 217 | struct v4l2_tuner *v) |
206 | { | 218 | { |
207 | struct gemtek_pci_card *card = video_drvdata(file); | 219 | struct gemtek_pci *card = video_drvdata(file); |
208 | 220 | ||
209 | if (v->index > 0) | 221 | if (v->index > 0) |
210 | return -EINVAL; | 222 | return -EINVAL; |
211 | 223 | ||
212 | strcpy(v->name, "FM"); | 224 | strlcpy(v->name, "FM", sizeof(v->name)); |
213 | v->type = V4L2_TUNER_RADIO; | 225 | v->type = V4L2_TUNER_RADIO; |
214 | v->rangelow = GEMTEK_PCI_RANGE_LOW; | 226 | v->rangelow = GEMTEK_PCI_RANGE_LOW; |
215 | v->rangehigh = GEMTEK_PCI_RANGE_HIGH; | 227 | v->rangehigh = GEMTEK_PCI_RANGE_HIGH; |
@@ -223,21 +235,18 @@ static int vidioc_g_tuner(struct file *file, void *priv, | |||
223 | static int vidioc_s_tuner(struct file *file, void *priv, | 235 | static int vidioc_s_tuner(struct file *file, void *priv, |
224 | struct v4l2_tuner *v) | 236 | struct v4l2_tuner *v) |
225 | { | 237 | { |
226 | if (v->index > 0) | 238 | return v->index ? -EINVAL : 0; |
227 | return -EINVAL; | ||
228 | return 0; | ||
229 | } | 239 | } |
230 | 240 | ||
231 | static int vidioc_s_frequency(struct file *file, void *priv, | 241 | static int vidioc_s_frequency(struct file *file, void *priv, |
232 | struct v4l2_frequency *f) | 242 | struct v4l2_frequency *f) |
233 | { | 243 | { |
234 | struct gemtek_pci_card *card = video_drvdata(file); | 244 | struct gemtek_pci *card = video_drvdata(file); |
235 | 245 | ||
236 | if ( (f->frequency < GEMTEK_PCI_RANGE_LOW) || | 246 | if (f->frequency < GEMTEK_PCI_RANGE_LOW || |
237 | (f->frequency > GEMTEK_PCI_RANGE_HIGH) ) | 247 | f->frequency > GEMTEK_PCI_RANGE_HIGH) |
238 | return -EINVAL; | 248 | return -EINVAL; |
239 | gemtek_pci_setfrequency(card, f->frequency); | 249 | gemtek_pci_setfrequency(card, f->frequency); |
240 | card->current_frequency = f->frequency; | ||
241 | card->mute = false; | 250 | card->mute = false; |
242 | return 0; | 251 | return 0; |
243 | } | 252 | } |
@@ -245,7 +254,7 @@ static int vidioc_s_frequency(struct file *file, void *priv, | |||
245 | static int vidioc_g_frequency(struct file *file, void *priv, | 254 | static int vidioc_g_frequency(struct file *file, void *priv, |
246 | struct v4l2_frequency *f) | 255 | struct v4l2_frequency *f) |
247 | { | 256 | { |
248 | struct gemtek_pci_card *card = video_drvdata(file); | 257 | struct gemtek_pci *card = video_drvdata(file); |
249 | 258 | ||
250 | f->type = V4L2_TUNER_RADIO; | 259 | f->type = V4L2_TUNER_RADIO; |
251 | f->frequency = card->current_frequency; | 260 | f->frequency = card->current_frequency; |
@@ -255,13 +264,11 @@ static int vidioc_g_frequency(struct file *file, void *priv, | |||
255 | static int vidioc_queryctrl(struct file *file, void *priv, | 264 | static int vidioc_queryctrl(struct file *file, void *priv, |
256 | struct v4l2_queryctrl *qc) | 265 | struct v4l2_queryctrl *qc) |
257 | { | 266 | { |
258 | int i; | 267 | switch (qc->id) { |
259 | for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) { | 268 | case V4L2_CID_AUDIO_MUTE: |
260 | if (qc->id && qc->id == radio_qctrl[i].id) { | 269 | return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1); |
261 | memcpy(qc, &(radio_qctrl[i]), | 270 | case V4L2_CID_AUDIO_VOLUME: |
262 | sizeof(*qc)); | 271 | return v4l2_ctrl_query_fill(qc, 0, 65535, 65535, 65535); |
263 | return 0; | ||
264 | } | ||
265 | } | 272 | } |
266 | return -EINVAL; | 273 | return -EINVAL; |
267 | } | 274 | } |
@@ -269,7 +276,7 @@ static int vidioc_queryctrl(struct file *file, void *priv, | |||
269 | static int vidioc_g_ctrl(struct file *file, void *priv, | 276 | static int vidioc_g_ctrl(struct file *file, void *priv, |
270 | struct v4l2_control *ctrl) | 277 | struct v4l2_control *ctrl) |
271 | { | 278 | { |
272 | struct gemtek_pci_card *card = video_drvdata(file); | 279 | struct gemtek_pci *card = video_drvdata(file); |
273 | 280 | ||
274 | switch (ctrl->id) { | 281 | switch (ctrl->id) { |
275 | case V4L2_CID_AUDIO_MUTE: | 282 | case V4L2_CID_AUDIO_MUTE: |
@@ -288,7 +295,7 @@ static int vidioc_g_ctrl(struct file *file, void *priv, | |||
288 | static int vidioc_s_ctrl(struct file *file, void *priv, | 295 | static int vidioc_s_ctrl(struct file *file, void *priv, |
289 | struct v4l2_control *ctrl) | 296 | struct v4l2_control *ctrl) |
290 | { | 297 | { |
291 | struct gemtek_pci_card *card = video_drvdata(file); | 298 | struct gemtek_pci *card = video_drvdata(file); |
292 | 299 | ||
293 | switch (ctrl->id) { | 300 | switch (ctrl->id) { |
294 | case V4L2_CID_AUDIO_MUTE: | 301 | case V4L2_CID_AUDIO_MUTE: |
@@ -307,17 +314,6 @@ static int vidioc_s_ctrl(struct file *file, void *priv, | |||
307 | return -EINVAL; | 314 | return -EINVAL; |
308 | } | 315 | } |
309 | 316 | ||
310 | static int vidioc_g_audio(struct file *file, void *priv, | ||
311 | struct v4l2_audio *a) | ||
312 | { | ||
313 | if (a->index > 1) | ||
314 | return -EINVAL; | ||
315 | |||
316 | strcpy(a->name, "Radio"); | ||
317 | a->capability = V4L2_AUDCAP_STEREO; | ||
318 | return 0; | ||
319 | } | ||
320 | |||
321 | static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) | 317 | static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) |
322 | { | 318 | { |
323 | *i = 0; | 319 | *i = 0; |
@@ -326,17 +322,22 @@ static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) | |||
326 | 322 | ||
327 | static int vidioc_s_input(struct file *filp, void *priv, unsigned int i) | 323 | static int vidioc_s_input(struct file *filp, void *priv, unsigned int i) |
328 | { | 324 | { |
329 | if (i != 0) | 325 | return i ? -EINVAL : 0; |
330 | return -EINVAL; | 326 | } |
327 | |||
328 | static int vidioc_g_audio(struct file *file, void *priv, | ||
329 | struct v4l2_audio *a) | ||
330 | { | ||
331 | a->index = 0; | ||
332 | strlcpy(a->name, "Radio", sizeof(a->name)); | ||
333 | a->capability = V4L2_AUDCAP_STEREO; | ||
331 | return 0; | 334 | return 0; |
332 | } | 335 | } |
333 | 336 | ||
334 | static int vidioc_s_audio(struct file *file, void *priv, | 337 | static int vidioc_s_audio(struct file *file, void *priv, |
335 | struct v4l2_audio *a) | 338 | struct v4l2_audio *a) |
336 | { | 339 | { |
337 | if (a->index != 0) | 340 | return a->index ? -EINVAL : 0; |
338 | return -EINVAL; | ||
339 | return 0; | ||
340 | } | 341 | } |
341 | 342 | ||
342 | enum { | 343 | enum { |
@@ -354,25 +355,22 @@ static struct pci_device_id gemtek_pci_id[] = | |||
354 | { 0 } | 355 | { 0 } |
355 | }; | 356 | }; |
356 | 357 | ||
357 | MODULE_DEVICE_TABLE( pci, gemtek_pci_id ); | 358 | MODULE_DEVICE_TABLE(pci, gemtek_pci_id); |
358 | |||
359 | static int mx = 1; | ||
360 | 359 | ||
361 | static int gemtek_pci_exclusive_open(struct file *file) | 360 | static int gemtek_pci_open(struct file *file) |
362 | { | 361 | { |
363 | return test_and_set_bit(0, &in_use) ? -EBUSY : 0; | 362 | return 0; |
364 | } | 363 | } |
365 | 364 | ||
366 | static int gemtek_pci_exclusive_release(struct file *file) | 365 | static int gemtek_pci_release(struct file *file) |
367 | { | 366 | { |
368 | clear_bit(0, &in_use); | ||
369 | return 0; | 367 | return 0; |
370 | } | 368 | } |
371 | 369 | ||
372 | static const struct v4l2_file_operations gemtek_pci_fops = { | 370 | static const struct v4l2_file_operations gemtek_pci_fops = { |
373 | .owner = THIS_MODULE, | 371 | .owner = THIS_MODULE, |
374 | .open = gemtek_pci_exclusive_open, | 372 | .open = gemtek_pci_open, |
375 | .release = gemtek_pci_exclusive_release, | 373 | .release = gemtek_pci_release, |
376 | .ioctl = video_ioctl2, | 374 | .ioctl = video_ioctl2, |
377 | }; | 375 | }; |
378 | 376 | ||
@@ -391,108 +389,100 @@ static const struct v4l2_ioctl_ops gemtek_pci_ioctl_ops = { | |||
391 | .vidioc_s_ctrl = vidioc_s_ctrl, | 389 | .vidioc_s_ctrl = vidioc_s_ctrl, |
392 | }; | 390 | }; |
393 | 391 | ||
394 | static struct video_device vdev_template = { | 392 | static int __devinit gemtek_pci_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id) |
395 | .name = "Gemtek PCI Radio", | ||
396 | .fops = &gemtek_pci_fops, | ||
397 | .ioctl_ops = &gemtek_pci_ioctl_ops, | ||
398 | .release = video_device_release_empty, | ||
399 | }; | ||
400 | |||
401 | static int __devinit gemtek_pci_probe( struct pci_dev *pci_dev, const struct pci_device_id *pci_id ) | ||
402 | { | 393 | { |
403 | struct gemtek_pci_card *card; | 394 | struct gemtek_pci *card; |
404 | struct video_device *devradio; | 395 | struct v4l2_device *v4l2_dev; |
396 | int res; | ||
405 | 397 | ||
406 | if ( (card = kzalloc( sizeof( struct gemtek_pci_card ), GFP_KERNEL )) == NULL ) { | 398 | card = kzalloc(sizeof(struct gemtek_pci), GFP_KERNEL); |
407 | printk( KERN_ERR "gemtek_pci: out of memory\n" ); | 399 | if (card == NULL) { |
400 | dev_err(&pdev->dev, "out of memory\n"); | ||
408 | return -ENOMEM; | 401 | return -ENOMEM; |
409 | } | 402 | } |
410 | 403 | ||
411 | if ( pci_enable_device( pci_dev ) ) | 404 | v4l2_dev = &card->v4l2_dev; |
412 | goto err_pci; | 405 | mutex_init(&card->lock); |
406 | card->pdev = pdev; | ||
413 | 407 | ||
414 | card->iobase = pci_resource_start( pci_dev, 0 ); | 408 | strlcpy(v4l2_dev->name, "gemtek_pci", sizeof(v4l2_dev->name)); |
415 | card->length = pci_resource_len( pci_dev, 0 ); | ||
416 | 409 | ||
417 | if ( request_region( card->iobase, card->length, card_names[pci_id->driver_data] ) == NULL ) { | 410 | res = v4l2_device_register(&pdev->dev, v4l2_dev); |
418 | printk( KERN_ERR "gemtek_pci: i/o port already in use\n" ); | 411 | if (res < 0) { |
419 | goto err_pci; | 412 | v4l2_err(v4l2_dev, "Could not register v4l2_device\n"); |
413 | kfree(card); | ||
414 | return res; | ||
420 | } | 415 | } |
421 | 416 | ||
422 | pci_set_drvdata( pci_dev, card ); | 417 | if (pci_enable_device(pdev)) |
418 | goto err_pci; | ||
423 | 419 | ||
424 | if ( (devradio = kmalloc( sizeof( struct video_device ), GFP_KERNEL )) == NULL ) { | 420 | card->iobase = pci_resource_start(pdev, 0); |
425 | printk( KERN_ERR "gemtek_pci: out of memory\n" ); | 421 | card->length = pci_resource_len(pdev, 0); |
426 | goto err_video; | 422 | |
423 | if (request_region(card->iobase, card->length, card_names[pci_id->driver_data]) == NULL) { | ||
424 | v4l2_err(v4l2_dev, "i/o port already in use\n"); | ||
425 | goto err_pci; | ||
427 | } | 426 | } |
428 | *devradio = vdev_template; | ||
429 | 427 | ||
430 | if (video_register_device(devradio, VFL_TYPE_RADIO, nr_radio) < 0) { | 428 | strlcpy(card->vdev.name, v4l2_dev->name, sizeof(card->vdev.name)); |
431 | kfree( devradio ); | 429 | card->vdev.v4l2_dev = v4l2_dev; |
430 | card->vdev.fops = &gemtek_pci_fops; | ||
431 | card->vdev.ioctl_ops = &gemtek_pci_ioctl_ops; | ||
432 | card->vdev.release = video_device_release_empty; | ||
433 | video_set_drvdata(&card->vdev, card); | ||
434 | |||
435 | if (video_register_device(&card->vdev, VFL_TYPE_RADIO, nr_radio) < 0) | ||
432 | goto err_video; | 436 | goto err_video; |
433 | } | ||
434 | 437 | ||
435 | card->videodev = devradio; | 438 | gemtek_pci_mute(card); |
436 | video_set_drvdata(devradio, card); | ||
437 | gemtek_pci_mute( card ); | ||
438 | 439 | ||
439 | printk( KERN_INFO "Gemtek PCI Radio (rev. %d) found at 0x%04x-0x%04x.\n", | 440 | v4l2_info(v4l2_dev, "Gemtek PCI Radio (rev. %d) found at 0x%04x-0x%04x.\n", |
440 | pci_dev->revision, card->iobase, card->iobase + card->length - 1 ); | 441 | pdev->revision, card->iobase, card->iobase + card->length - 1); |
441 | 442 | ||
442 | return 0; | 443 | return 0; |
443 | 444 | ||
444 | err_video: | 445 | err_video: |
445 | release_region( card->iobase, card->length ); | 446 | release_region(card->iobase, card->length); |
446 | 447 | ||
447 | err_pci: | 448 | err_pci: |
448 | kfree( card ); | 449 | v4l2_device_unregister(v4l2_dev); |
450 | kfree(card); | ||
449 | return -ENODEV; | 451 | return -ENODEV; |
450 | } | 452 | } |
451 | 453 | ||
452 | static void __devexit gemtek_pci_remove( struct pci_dev *pci_dev ) | 454 | static void __devexit gemtek_pci_remove(struct pci_dev *pdev) |
453 | { | 455 | { |
454 | struct gemtek_pci_card *card = pci_get_drvdata( pci_dev ); | 456 | struct v4l2_device *v4l2_dev = dev_get_drvdata(&pdev->dev); |
457 | struct gemtek_pci *card = to_gemtek_pci(v4l2_dev); | ||
455 | 458 | ||
456 | video_unregister_device( card->videodev ); | 459 | video_unregister_device(&card->vdev); |
457 | kfree( card->videodev ); | 460 | v4l2_device_unregister(v4l2_dev); |
458 | 461 | ||
459 | release_region( card->iobase, card->length ); | 462 | release_region(card->iobase, card->length); |
460 | 463 | ||
461 | if ( mx ) | 464 | if (mx) |
462 | gemtek_pci_mute( card ); | 465 | gemtek_pci_mute(card); |
463 | 466 | ||
464 | kfree( card ); | 467 | kfree(card); |
465 | |||
466 | pci_set_drvdata( pci_dev, NULL ); | ||
467 | } | 468 | } |
468 | 469 | ||
469 | static struct pci_driver gemtek_pci_driver = | 470 | static struct pci_driver gemtek_pci_driver = { |
470 | { | ||
471 | .name = "gemtek_pci", | 471 | .name = "gemtek_pci", |
472 | .id_table = gemtek_pci_id, | 472 | .id_table = gemtek_pci_id, |
473 | .probe = gemtek_pci_probe, | 473 | .probe = gemtek_pci_probe, |
474 | .remove = __devexit_p(gemtek_pci_remove), | 474 | .remove = __devexit_p(gemtek_pci_remove), |
475 | }; | 475 | }; |
476 | 476 | ||
477 | static int __init gemtek_pci_init_module( void ) | 477 | static int __init gemtek_pci_init(void) |
478 | { | 478 | { |
479 | return pci_register_driver( &gemtek_pci_driver ); | 479 | return pci_register_driver(&gemtek_pci_driver); |
480 | } | 480 | } |
481 | 481 | ||
482 | static void __exit gemtek_pci_cleanup_module( void ) | 482 | static void __exit gemtek_pci_exit(void) |
483 | { | 483 | { |
484 | pci_unregister_driver(&gemtek_pci_driver); | 484 | pci_unregister_driver(&gemtek_pci_driver); |
485 | } | 485 | } |
486 | 486 | ||
487 | MODULE_AUTHOR( "Vladimir Shebordaev <vshebordaev@mail.ru>" ); | 487 | module_init(gemtek_pci_init); |
488 | MODULE_DESCRIPTION( "The video4linux driver for the Gemtek PCI Radio Card" ); | 488 | module_exit(gemtek_pci_exit); |
489 | MODULE_LICENSE("GPL"); | ||
490 | |||
491 | module_param(mx, bool, 0); | ||
492 | MODULE_PARM_DESC( mx, "single digit: 1 - turn off the turner upon module exit (default), 0 - do not" ); | ||
493 | module_param(nr_radio, int, 0); | ||
494 | MODULE_PARM_DESC( nr_radio, "video4linux device number to use"); | ||
495 | |||
496 | module_init( gemtek_pci_init_module ); | ||
497 | module_exit( gemtek_pci_cleanup_module ); | ||
498 | |||