diff options
-rw-r--r-- | drivers/media/radio/radio-sf16fmr2.c | 102 |
1 files changed, 39 insertions, 63 deletions
diff --git a/drivers/media/radio/radio-sf16fmr2.c b/drivers/media/radio/radio-sf16fmr2.c index ebc5fbbc38bb..7bf7d534c042 100644 --- a/drivers/media/radio/radio-sf16fmr2.c +++ b/drivers/media/radio/radio-sf16fmr2.c | |||
@@ -29,6 +29,8 @@ static struct mutex lock; | |||
29 | #include <linux/version.h> /* for KERNEL_VERSION MACRO */ | 29 | #include <linux/version.h> /* for KERNEL_VERSION MACRO */ |
30 | #define RADIO_VERSION KERNEL_VERSION(0,0,2) | 30 | #define RADIO_VERSION KERNEL_VERSION(0,0,2) |
31 | 31 | ||
32 | #define AUD_VOL_INDEX 1 | ||
33 | |||
32 | static struct v4l2_queryctrl radio_qctrl[] = { | 34 | static struct v4l2_queryctrl radio_qctrl[] = { |
33 | { | 35 | { |
34 | .id = V4L2_CID_AUDIO_MUTE, | 36 | .id = V4L2_CID_AUDIO_MUTE, |
@@ -37,13 +39,14 @@ static struct v4l2_queryctrl radio_qctrl[] = { | |||
37 | .maximum = 1, | 39 | .maximum = 1, |
38 | .default_value = 1, | 40 | .default_value = 1, |
39 | .type = V4L2_CTRL_TYPE_BOOLEAN, | 41 | .type = V4L2_CTRL_TYPE_BOOLEAN, |
40 | },{ | 42 | }, |
43 | [AUD_VOL_INDEX] = { | ||
41 | .id = V4L2_CID_AUDIO_VOLUME, | 44 | .id = V4L2_CID_AUDIO_VOLUME, |
42 | .name = "Volume", | 45 | .name = "Volume", |
43 | .minimum = 0, | 46 | .minimum = 0, |
44 | .maximum = 65535, | 47 | .maximum = 15, |
45 | .step = 1<<12, | 48 | .step = 1, |
46 | .default_value = 0xff, | 49 | .default_value = 0, |
47 | .type = V4L2_CTRL_TYPE_INTEGER, | 50 | .type = V4L2_CTRL_TYPE_INTEGER, |
48 | } | 51 | } |
49 | }; | 52 | }; |
@@ -61,7 +64,7 @@ static struct v4l2_queryctrl radio_qctrl[] = { | |||
61 | struct fmr2_device | 64 | struct fmr2_device |
62 | { | 65 | { |
63 | int port; | 66 | int port; |
64 | int curvol; /* 0-65535, if not volume 0 or 65535 */ | 67 | int curvol; /* 0-15 */ |
65 | int mute; | 68 | int mute; |
66 | int stereo; /* card is producing stereo audio */ | 69 | int stereo; /* card is producing stereo audio */ |
67 | unsigned long curfreq; /* freq in kHz */ | 70 | unsigned long curfreq; /* freq in kHz */ |
@@ -176,51 +179,35 @@ static int fmr2_setfreq(struct fmr2_device *dev) | |||
176 | /* !!! not tested, in my card this does't work !!! */ | 179 | /* !!! not tested, in my card this does't work !!! */ |
177 | static int fmr2_setvolume(struct fmr2_device *dev) | 180 | static int fmr2_setvolume(struct fmr2_device *dev) |
178 | { | 181 | { |
179 | int i,a,n, port = dev->port; | 182 | int vol[16] = { 0x021, 0x084, 0x090, 0x104, |
183 | 0x110, 0x204, 0x210, 0x402, | ||
184 | 0x404, 0x408, 0x410, 0x801, | ||
185 | 0x802, 0x804, 0x808, 0x810 }; | ||
186 | int i, a, port = dev->port; | ||
187 | int n = vol[dev->curvol & 0x0f]; | ||
180 | 188 | ||
181 | if (dev->card_type != 11) return 1; | 189 | if (dev->card_type != 11) |
190 | return 1; | ||
182 | 191 | ||
183 | switch( (dev->curvol+(1<<11)) >> 12 ) | 192 | for (i = 12; --i >= 0; ) { |
184 | { | ||
185 | case 0: case 1: n = 0x21; break; | ||
186 | case 2: n = 0x84; break; | ||
187 | case 3: n = 0x90; break; | ||
188 | case 4: n = 0x104; break; | ||
189 | case 5: n = 0x110; break; | ||
190 | case 6: n = 0x204; break; | ||
191 | case 7: n = 0x210; break; | ||
192 | case 8: n = 0x402; break; | ||
193 | case 9: n = 0x404; break; | ||
194 | default: | ||
195 | case 10: n = 0x408; break; | ||
196 | case 11: n = 0x410; break; | ||
197 | case 12: n = 0x801; break; | ||
198 | case 13: n = 0x802; break; | ||
199 | case 14: n = 0x804; break; | ||
200 | case 15: n = 0x808; break; | ||
201 | case 16: n = 0x810; break; | ||
202 | } | ||
203 | for(i=12;--i>=0;) | ||
204 | { | ||
205 | a = ((n >> i) & 1) << 6; /* if (a=0) a= 0; else a= 0x40; */ | 193 | a = ((n >> i) & 1) << 6; /* if (a=0) a= 0; else a= 0x40; */ |
206 | outb(a|4, port); | 194 | outb(a | 4, port); |
207 | wait(4,port); | 195 | wait(4, port); |
208 | outb(a|0x24, port); | 196 | outb(a | 0x24, port); |
209 | wait(4,port); | 197 | wait(4, port); |
210 | outb(a|4, port); | 198 | outb(a | 4, port); |
211 | wait(4,port); | 199 | wait(4, port); |
212 | } | 200 | } |
213 | for(i=6;--i>=0;) | 201 | for (i = 6; --i >= 0; ) { |
214 | { | ||
215 | a = ((0x18 >> i) & 1) << 6; | 202 | a = ((0x18 >> i) & 1) << 6; |
216 | outb(a|4, port); | 203 | outb(a | 4, port); |
217 | wait(4,port); | 204 | wait(4,port); |
218 | outb(a|0x24, port); | 205 | outb(a | 0x24, port); |
219 | wait(4,port); | 206 | wait(4,port); |
220 | outb(a|4, port); | 207 | outb(a|4, port); |
221 | wait(4,port); | 208 | wait(4,port); |
222 | } | 209 | } |
223 | wait(4,port); | 210 | wait(4, port); |
224 | outb(0x14, port); | 211 | outb(0x14, port); |
225 | 212 | ||
226 | return 0; | 213 | return 0; |
@@ -312,16 +299,10 @@ static int vidioc_queryctrl(struct file *file, void *priv, | |||
312 | struct v4l2_queryctrl *qc) | 299 | struct v4l2_queryctrl *qc) |
313 | { | 300 | { |
314 | int i; | 301 | int i; |
315 | struct video_device *dev = video_devdata(file); | ||
316 | struct fmr2_device *fmr2 = dev->priv; | ||
317 | 302 | ||
318 | for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) { | 303 | for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) { |
319 | if ((fmr2->card_type != 11) | ||
320 | && V4L2_CID_AUDIO_VOLUME) | ||
321 | radio_qctrl[i].step = 65535; | ||
322 | if (qc->id && qc->id == radio_qctrl[i].id) { | 304 | if (qc->id && qc->id == radio_qctrl[i].id) { |
323 | memcpy(qc, &(radio_qctrl[i]), | 305 | memcpy(qc, &radio_qctrl[i], sizeof(*qc)); |
324 | sizeof(*qc)); | ||
325 | return 0; | 306 | return 0; |
326 | } | 307 | } |
327 | } | 308 | } |
@@ -354,24 +335,13 @@ static int vidioc_s_ctrl(struct file *file, void *priv, | |||
354 | switch (ctrl->id) { | 335 | switch (ctrl->id) { |
355 | case V4L2_CID_AUDIO_MUTE: | 336 | case V4L2_CID_AUDIO_MUTE: |
356 | fmr2->mute = ctrl->value; | 337 | fmr2->mute = ctrl->value; |
357 | if (fmr2->card_type != 11) { | ||
358 | if (!fmr2->mute) | ||
359 | fmr2->curvol = 65535; | ||
360 | else | ||
361 | fmr2->curvol = 0; | ||
362 | } | ||
363 | break; | 338 | break; |
364 | case V4L2_CID_AUDIO_VOLUME: | 339 | case V4L2_CID_AUDIO_VOLUME: |
365 | fmr2->curvol = ctrl->value; | 340 | if (ctrl->value > radio_qctrl[AUD_VOL_INDEX].maximum) |
366 | if (fmr2->card_type != 11) { | 341 | fmr2->curvol = radio_qctrl[AUD_VOL_INDEX].maximum; |
367 | if (fmr2->curvol) { | 342 | else |
368 | fmr2->curvol = 65535; | 343 | fmr2->curvol = ctrl->value; |
369 | fmr2->mute = 0; | 344 | |
370 | } else { | ||
371 | fmr2->curvol = 0; | ||
372 | fmr2->mute = 1; | ||
373 | } | ||
374 | } | ||
375 | break; | 345 | break; |
376 | default: | 346 | default: |
377 | return -EINVAL; | 347 | return -EINVAL; |
@@ -387,6 +357,7 @@ static int vidioc_s_ctrl(struct file *file, void *priv, | |||
387 | mutex_lock(&lock); | 357 | mutex_lock(&lock); |
388 | if (fmr2->curvol && !fmr2->mute) { | 358 | if (fmr2->curvol && !fmr2->mute) { |
389 | fmr2_setvolume(fmr2); | 359 | fmr2_setvolume(fmr2); |
360 | /* Set frequency and unmute card */ | ||
390 | fmr2_setfreq(fmr2); | 361 | fmr2_setfreq(fmr2); |
391 | } else | 362 | } else |
392 | fmr2_mute(fmr2->port); | 363 | fmr2_mute(fmr2->port); |
@@ -487,6 +458,11 @@ static int __init fmr2_init(void) | |||
487 | fmr2_product_info(&fmr2_unit); | 458 | fmr2_product_info(&fmr2_unit); |
488 | mutex_unlock(&lock); | 459 | mutex_unlock(&lock); |
489 | debug_print((KERN_DEBUG "card_type %d\n", fmr2_unit.card_type)); | 460 | debug_print((KERN_DEBUG "card_type %d\n", fmr2_unit.card_type)); |
461 | |||
462 | /* Only card_type == 11 implements volume */ | ||
463 | if (fmr2_unit.card_type != 11) | ||
464 | radio_qctrl[AUD_VOL_INDEX].maximum = 1; | ||
465 | |||
490 | return 0; | 466 | return 0; |
491 | } | 467 | } |
492 | 468 | ||