aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/radio
diff options
context:
space:
mode:
authorHans Verkuil <hverkuil@xs4all.nl>2009-03-06 11:54:23 -0500
committerMauro Carvalho Chehab <mchehab@redhat.com>2009-03-30 11:43:13 -0400
commit1dc8aafc79ab9bde6b53cc3696cb0b032fb2fc3d (patch)
treeafe330c3324a0d048d00ff98e3a1a92643ca9bdc /drivers/media/radio
parent5ac3d5bf4aedf55721cf4f65ab44fb1f598585ce (diff)
V4L/DVB (10891): radio-trust: 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-trust.c344
1 files changed, 179 insertions, 165 deletions
diff --git a/drivers/media/radio/radio-trust.c b/drivers/media/radio/radio-trust.c
index bdf9cb6a75f4..fe964b45fdf5 100644
--- a/drivers/media/radio/radio-trust.c
+++ b/drivers/media/radio/radio-trust.c
@@ -19,49 +19,16 @@
19#include <linux/module.h> 19#include <linux/module.h>
20#include <linux/init.h> 20#include <linux/init.h>
21#include <linux/ioport.h> 21#include <linux/ioport.h>
22#include <asm/io.h> 22#include <linux/version.h> /* for KERNEL_VERSION MACRO */
23#include <asm/uaccess.h>
24#include <linux/videodev2.h> 23#include <linux/videodev2.h>
25#include <media/v4l2-common.h> 24#include <linux/io.h>
25#include <linux/uaccess.h>
26#include <media/v4l2-device.h>
26#include <media/v4l2-ioctl.h> 27#include <media/v4l2-ioctl.h>
27 28
28#include <linux/version.h> /* for KERNEL_VERSION MACRO */ 29MODULE_AUTHOR("Eric Lammerts, Russell Kroll, Quay Lu, Donald Song, Jason Lewis, Scott McGrath, William McGrath");
29#define RADIO_VERSION KERNEL_VERSION(0,0,2) 30MODULE_DESCRIPTION("A driver for the Trust FM Radio card.");
30 31MODULE_LICENSE("GPL");
31static struct v4l2_queryctrl radio_qctrl[] = {
32 {
33 .id = V4L2_CID_AUDIO_MUTE,
34 .name = "Mute",
35 .minimum = 0,
36 .maximum = 1,
37 .default_value = 1,
38 .type = V4L2_CTRL_TYPE_BOOLEAN,
39 },{
40 .id = V4L2_CID_AUDIO_VOLUME,
41 .name = "Volume",
42 .minimum = 0,
43 .maximum = 65535,
44 .step = 2048,
45 .default_value = 65535,
46 .type = V4L2_CTRL_TYPE_INTEGER,
47 },{
48 .id = V4L2_CID_AUDIO_BASS,
49 .name = "Bass",
50 .minimum = 0,
51 .maximum = 65535,
52 .step = 4370,
53 .default_value = 32768,
54 .type = V4L2_CTRL_TYPE_INTEGER,
55 },{
56 .id = V4L2_CID_AUDIO_TREBLE,
57 .name = "Treble",
58 .minimum = 0,
59 .maximum = 65535,
60 .step = 4370,
61 .default_value = 32768,
62 .type = V4L2_CTRL_TYPE_INTEGER,
63 },
64};
65 32
66/* acceptable ports: 0x350 (JP3 shorted), 0x358 (JP3 open) */ 33/* acceptable ports: 0x350 (JP3 shorted), 0x358 (JP3 open) */
67 34
@@ -71,26 +38,41 @@ static struct v4l2_queryctrl radio_qctrl[] = {
71 38
72static int io = CONFIG_RADIO_TRUST_PORT; 39static int io = CONFIG_RADIO_TRUST_PORT;
73static int radio_nr = -1; 40static int radio_nr = -1;
74static int ioval = 0xf; 41
75static __u16 curvol; 42module_param(io, int, 0);
76static __u16 curbass; 43MODULE_PARM_DESC(io, "I/O address of the Trust FM Radio card (0x350 or 0x358)");
77static __u16 curtreble; 44module_param(radio_nr, int, 0);
78static unsigned long curfreq; 45
79static int curstereo; 46#define RADIO_VERSION KERNEL_VERSION(0, 0, 2)
80static int curmute; 47
81static unsigned long in_use; 48struct trust {
49 struct v4l2_device v4l2_dev;
50 struct video_device vdev;
51 int io;
52 int ioval;
53 __u16 curvol;
54 __u16 curbass;
55 __u16 curtreble;
56 int muted;
57 unsigned long curfreq;
58 int curstereo;
59 int curmute;
60 struct mutex lock;
61};
62
63static struct trust trust_card;
82 64
83/* i2c addresses */ 65/* i2c addresses */
84#define TDA7318_ADDR 0x88 66#define TDA7318_ADDR 0x88
85#define TSA6060T_ADDR 0xc4 67#define TSA6060T_ADDR 0xc4
86 68
87#define TR_DELAY do { inb(io); inb(io); inb(io); } while(0) 69#define TR_DELAY do { inb(tr->io); inb(tr->io); inb(tr->io); } while (0)
88#define TR_SET_SCL outb(ioval |= 2, io) 70#define TR_SET_SCL outb(tr->ioval |= 2, tr->io)
89#define TR_CLR_SCL outb(ioval &= 0xfd, io) 71#define TR_CLR_SCL outb(tr->ioval &= 0xfd, tr->io)
90#define TR_SET_SDA outb(ioval |= 1, io) 72#define TR_SET_SDA outb(tr->ioval |= 1, tr->io)
91#define TR_CLR_SDA outb(ioval &= 0xfe, io) 73#define TR_CLR_SDA outb(tr->ioval &= 0xfe, tr->io)
92 74
93static void write_i2c(int n, ...) 75static void write_i2c(struct trust *tr, int n, ...)
94{ 76{
95 unsigned char val, mask; 77 unsigned char val, mask;
96 va_list args; 78 va_list args;
@@ -136,62 +118,77 @@ static void write_i2c(int n, ...)
136 va_end(args); 118 va_end(args);
137} 119}
138 120
139static void tr_setvol(__u16 vol) 121static void tr_setvol(struct trust *tr, __u16 vol)
140{ 122{
141 curvol = vol / 2048; 123 mutex_lock(&tr->lock);
142 write_i2c(2, TDA7318_ADDR, curvol ^ 0x1f); 124 tr->curvol = vol / 2048;
125 write_i2c(tr, 2, TDA7318_ADDR, tr->curvol ^ 0x1f);
126 mutex_unlock(&tr->lock);
143} 127}
144 128
145static int basstreble2chip[15] = { 129static int basstreble2chip[15] = {
146 0, 1, 2, 3, 4, 5, 6, 7, 14, 13, 12, 11, 10, 9, 8 130 0, 1, 2, 3, 4, 5, 6, 7, 14, 13, 12, 11, 10, 9, 8
147}; 131};
148 132
149static void tr_setbass(__u16 bass) 133static void tr_setbass(struct trust *tr, __u16 bass)
150{ 134{
151 curbass = bass / 4370; 135 mutex_lock(&tr->lock);
152 write_i2c(2, TDA7318_ADDR, 0x60 | basstreble2chip[curbass]); 136 tr->curbass = bass / 4370;
137 write_i2c(tr, 2, TDA7318_ADDR, 0x60 | basstreble2chip[tr->curbass]);
138 mutex_unlock(&tr->lock);
153} 139}
154 140
155static void tr_settreble(__u16 treble) 141static void tr_settreble(struct trust *tr, __u16 treble)
156{ 142{
157 curtreble = treble / 4370; 143 mutex_lock(&tr->lock);
158 write_i2c(2, TDA7318_ADDR, 0x70 | basstreble2chip[curtreble]); 144 tr->curtreble = treble / 4370;
145 write_i2c(tr, 2, TDA7318_ADDR, 0x70 | basstreble2chip[tr->curtreble]);
146 mutex_unlock(&tr->lock);
159} 147}
160 148
161static void tr_setstereo(int stereo) 149static void tr_setstereo(struct trust *tr, int stereo)
162{ 150{
163 curstereo = !!stereo; 151 mutex_lock(&tr->lock);
164 ioval = (ioval & 0xfb) | (!curstereo << 2); 152 tr->curstereo = !!stereo;
165 outb(ioval, io); 153 tr->ioval = (tr->ioval & 0xfb) | (!tr->curstereo << 2);
154 outb(tr->ioval, tr->io);
155 mutex_unlock(&tr->lock);
166} 156}
167 157
168static void tr_setmute(int mute) 158static void tr_setmute(struct trust *tr, int mute)
169{ 159{
170 curmute = !!mute; 160 mutex_lock(&tr->lock);
171 ioval = (ioval & 0xf7) | (curmute << 3); 161 tr->curmute = !!mute;
172 outb(ioval, io); 162 tr->ioval = (tr->ioval & 0xf7) | (tr->curmute << 3);
163 outb(tr->ioval, tr->io);
164 mutex_unlock(&tr->lock);
173} 165}
174 166
175static int tr_getsigstr(void) 167static int tr_getsigstr(struct trust *tr)
176{ 168{
177 int i, v; 169 int i, v;
178 170
179 for(i = 0, v = 0; i < 100; i++) v |= inb(io); 171 mutex_lock(&tr->lock);
180 return (v & 1)? 0 : 0xffff; 172 for (i = 0, v = 0; i < 100; i++)
173 v |= inb(tr->io);
174 mutex_unlock(&tr->lock);
175 return (v & 1) ? 0 : 0xffff;
181} 176}
182 177
183static int tr_getstereo(void) 178static int tr_getstereo(struct trust *tr)
184{ 179{
185 /* don't know how to determine it, just return the setting */ 180 /* don't know how to determine it, just return the setting */
186 return curstereo; 181 return tr->curstereo;
187} 182}
188 183
189static void tr_setfreq(unsigned long f) 184static void tr_setfreq(struct trust *tr, unsigned long f)
190{ 185{
186 mutex_lock(&tr->lock);
187 tr->curfreq = f;
191 f /= 160; /* Convert to 10 kHz units */ 188 f /= 160; /* Convert to 10 kHz units */
192 f += 1070; /* Add 10.7 MHz IF */ 189 f += 1070; /* Add 10.7 MHz IF */
193 190 write_i2c(tr, 5, TSA6060T_ADDR, (f << 1) | 1, f >> 7, 0x60 | ((f >> 15) & 1), 0);
194 write_i2c(5, TSA6060T_ADDR, (f << 1) | 1, f >> 7, 0x60 | ((f >> 15) & 1), 0); 191 mutex_unlock(&tr->lock);
195} 192}
196 193
197static int vidioc_querycap(struct file *file, void *priv, 194static int vidioc_querycap(struct file *file, void *priv,
@@ -199,68 +196,75 @@ static int vidioc_querycap(struct file *file, void *priv,
199{ 196{
200 strlcpy(v->driver, "radio-trust", sizeof(v->driver)); 197 strlcpy(v->driver, "radio-trust", sizeof(v->driver));
201 strlcpy(v->card, "Trust FM Radio", sizeof(v->card)); 198 strlcpy(v->card, "Trust FM Radio", sizeof(v->card));
202 sprintf(v->bus_info, "ISA"); 199 strlcpy(v->bus_info, "ISA", sizeof(v->bus_info));
203 v->version = RADIO_VERSION; 200 v->version = RADIO_VERSION;
204 v->capabilities = V4L2_CAP_TUNER; 201 v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO;
205 return 0; 202 return 0;
206} 203}
207 204
208static int vidioc_g_tuner(struct file *file, void *priv, 205static int vidioc_g_tuner(struct file *file, void *priv,
209 struct v4l2_tuner *v) 206 struct v4l2_tuner *v)
210{ 207{
208 struct trust *tr = video_drvdata(file);
209
211 if (v->index > 0) 210 if (v->index > 0)
212 return -EINVAL; 211 return -EINVAL;
213 212
214 strcpy(v->name, "FM"); 213 strlcpy(v->name, "FM", sizeof(v->name));
215 v->type = V4L2_TUNER_RADIO; 214 v->type = V4L2_TUNER_RADIO;
216 v->rangelow = (87.5*16000); 215 v->rangelow = 87.5 * 16000;
217 v->rangehigh = (108*16000); 216 v->rangehigh = 108 * 16000;
218 v->rxsubchans = V4L2_TUNER_SUB_MONO|V4L2_TUNER_SUB_STEREO; 217 v->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO;
219 v->capability = V4L2_TUNER_CAP_LOW; 218 v->capability = V4L2_TUNER_CAP_LOW;
220 if (tr_getstereo()) 219 if (tr_getstereo(tr))
221 v->audmode = V4L2_TUNER_MODE_STEREO; 220 v->audmode = V4L2_TUNER_MODE_STEREO;
222 else 221 else
223 v->audmode = V4L2_TUNER_MODE_MONO; 222 v->audmode = V4L2_TUNER_MODE_MONO;
224 v->signal = tr_getsigstr(); 223 v->signal = tr_getsigstr(tr);
225 return 0; 224 return 0;
226} 225}
227 226
228static int vidioc_s_tuner(struct file *file, void *priv, 227static int vidioc_s_tuner(struct file *file, void *priv,
229 struct v4l2_tuner *v) 228 struct v4l2_tuner *v)
230{ 229{
231 if (v->index > 0) 230 struct trust *tr = video_drvdata(file);
232 return -EINVAL;
233 231
232 if (v->index)
233 return -EINVAL;
234 tr_setstereo(tr, v->audmode == V4L2_TUNER_MODE_STEREO);
234 return 0; 235 return 0;
235} 236}
236 237
237static int vidioc_s_frequency(struct file *file, void *priv, 238static int vidioc_s_frequency(struct file *file, void *priv,
238 struct v4l2_frequency *f) 239 struct v4l2_frequency *f)
239{ 240{
240 curfreq = f->frequency; 241 struct trust *tr = video_drvdata(file);
241 tr_setfreq(curfreq); 242
243 tr_setfreq(tr, f->frequency);
242 return 0; 244 return 0;
243} 245}
244 246
245static int vidioc_g_frequency(struct file *file, void *priv, 247static int vidioc_g_frequency(struct file *file, void *priv,
246 struct v4l2_frequency *f) 248 struct v4l2_frequency *f)
247{ 249{
250 struct trust *tr = video_drvdata(file);
251
248 f->type = V4L2_TUNER_RADIO; 252 f->type = V4L2_TUNER_RADIO;
249 f->frequency = curfreq; 253 f->frequency = tr->curfreq;
250 return 0; 254 return 0;
251} 255}
252 256
253static int vidioc_queryctrl(struct file *file, void *priv, 257static int vidioc_queryctrl(struct file *file, void *priv,
254 struct v4l2_queryctrl *qc) 258 struct v4l2_queryctrl *qc)
255{ 259{
256 int i; 260 switch (qc->id) {
257 261 case V4L2_CID_AUDIO_MUTE:
258 for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) { 262 return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1);
259 if (qc->id && qc->id == radio_qctrl[i].id) { 263 case V4L2_CID_AUDIO_VOLUME:
260 memcpy(qc, &(radio_qctrl[i]), 264 return v4l2_ctrl_query_fill(qc, 0, 65535, 2048, 65535);
261 sizeof(*qc)); 265 case V4L2_CID_AUDIO_BASS:
262 return 0; 266 case V4L2_CID_AUDIO_TREBLE:
263 } 267 return v4l2_ctrl_query_fill(qc, 0, 65535, 4370, 32768);
264 } 268 }
265 return -EINVAL; 269 return -EINVAL;
266} 270}
@@ -268,18 +272,20 @@ static int vidioc_queryctrl(struct file *file, void *priv,
268static int vidioc_g_ctrl(struct file *file, void *priv, 272static int vidioc_g_ctrl(struct file *file, void *priv,
269 struct v4l2_control *ctrl) 273 struct v4l2_control *ctrl)
270{ 274{
275 struct trust *tr = video_drvdata(file);
276
271 switch (ctrl->id) { 277 switch (ctrl->id) {
272 case V4L2_CID_AUDIO_MUTE: 278 case V4L2_CID_AUDIO_MUTE:
273 ctrl->value = curmute; 279 ctrl->value = tr->curmute;
274 return 0; 280 return 0;
275 case V4L2_CID_AUDIO_VOLUME: 281 case V4L2_CID_AUDIO_VOLUME:
276 ctrl->value = curvol * 2048; 282 ctrl->value = tr->curvol * 2048;
277 return 0; 283 return 0;
278 case V4L2_CID_AUDIO_BASS: 284 case V4L2_CID_AUDIO_BASS:
279 ctrl->value = curbass * 4370; 285 ctrl->value = tr->curbass * 4370;
280 return 0; 286 return 0;
281 case V4L2_CID_AUDIO_TREBLE: 287 case V4L2_CID_AUDIO_TREBLE:
282 ctrl->value = curtreble * 4370; 288 ctrl->value = tr->curtreble * 4370;
283 return 0; 289 return 0;
284 } 290 }
285 return -EINVAL; 291 return -EINVAL;
@@ -288,34 +294,25 @@ static int vidioc_g_ctrl(struct file *file, void *priv,
288static int vidioc_s_ctrl(struct file *file, void *priv, 294static int vidioc_s_ctrl(struct file *file, void *priv,
289 struct v4l2_control *ctrl) 295 struct v4l2_control *ctrl)
290{ 296{
297 struct trust *tr = video_drvdata(file);
298
291 switch (ctrl->id) { 299 switch (ctrl->id) {
292 case V4L2_CID_AUDIO_MUTE: 300 case V4L2_CID_AUDIO_MUTE:
293 tr_setmute(ctrl->value); 301 tr_setmute(tr, ctrl->value);
294 return 0; 302 return 0;
295 case V4L2_CID_AUDIO_VOLUME: 303 case V4L2_CID_AUDIO_VOLUME:
296 tr_setvol(ctrl->value); 304 tr_setvol(tr, ctrl->value);
297 return 0; 305 return 0;
298 case V4L2_CID_AUDIO_BASS: 306 case V4L2_CID_AUDIO_BASS:
299 tr_setbass(ctrl->value); 307 tr_setbass(tr, ctrl->value);
300 return 0; 308 return 0;
301 case V4L2_CID_AUDIO_TREBLE: 309 case V4L2_CID_AUDIO_TREBLE:
302 tr_settreble(ctrl->value); 310 tr_settreble(tr, ctrl->value);
303 return 0; 311 return 0;
304 } 312 }
305 return -EINVAL; 313 return -EINVAL;
306} 314}
307 315
308static int vidioc_g_audio(struct file *file, void *priv,
309 struct v4l2_audio *a)
310{
311 if (a->index > 1)
312 return -EINVAL;
313
314 strcpy(a->name, "Radio");
315 a->capability = V4L2_AUDCAP_STEREO;
316 return 0;
317}
318
319static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) 316static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i)
320{ 317{
321 *i = 0; 318 *i = 0;
@@ -324,34 +321,38 @@ static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i)
324 321
325static int vidioc_s_input(struct file *filp, void *priv, unsigned int i) 322static int vidioc_s_input(struct file *filp, void *priv, unsigned int i)
326{ 323{
327 if (i != 0) 324 return i ? -EINVAL : 0;
328 return -EINVAL; 325}
326
327static int vidioc_g_audio(struct file *file, void *priv,
328 struct v4l2_audio *a)
329{
330 a->index = 0;
331 strlcpy(a->name, "Radio", sizeof(a->name));
332 a->capability = V4L2_AUDCAP_STEREO;
329 return 0; 333 return 0;
330} 334}
331 335
332static int vidioc_s_audio(struct file *file, void *priv, 336static int vidioc_s_audio(struct file *file, void *priv,
333 struct v4l2_audio *a) 337 struct v4l2_audio *a)
334{ 338{
335 if (a->index != 0) 339 return a->index ? -EINVAL : 0;
336 return -EINVAL;
337 return 0;
338} 340}
339 341
340static int trust_exclusive_open(struct file *file) 342static int trust_open(struct file *file)
341{ 343{
342 return test_and_set_bit(0, &in_use) ? -EBUSY : 0; 344 return 0;
343} 345}
344 346
345static int trust_exclusive_release(struct file *file) 347static int trust_release(struct file *file)
346{ 348{
347 clear_bit(0, &in_use);
348 return 0; 349 return 0;
349} 350}
350 351
351static const struct v4l2_file_operations trust_fops = { 352static const struct v4l2_file_operations trust_fops = {
352 .owner = THIS_MODULE, 353 .owner = THIS_MODULE,
353 .open = trust_exclusive_open, 354 .open = trust_open,
354 .release = trust_exclusive_release, 355 .release = trust_release,
355 .ioctl = video_ioctl2, 356 .ioctl = video_ioctl2,
356}; 357};
357 358
@@ -370,59 +371,72 @@ static const struct v4l2_ioctl_ops trust_ioctl_ops = {
370 .vidioc_s_input = vidioc_s_input, 371 .vidioc_s_input = vidioc_s_input,
371}; 372};
372 373
373static struct video_device trust_radio = {
374 .name = "Trust FM Radio",
375 .fops = &trust_fops,
376 .ioctl_ops = &trust_ioctl_ops,
377 .release = video_device_release_empty,
378};
379
380static int __init trust_init(void) 374static int __init trust_init(void)
381{ 375{
382 if(io == -1) { 376 struct trust *tr = &trust_card;
383 printk(KERN_ERR "You must set an I/O address with io=0x???\n"); 377 struct v4l2_device *v4l2_dev = &tr->v4l2_dev;
378 int res;
379
380 strlcpy(v4l2_dev->name, "trust", sizeof(v4l2_dev->name));
381 tr->io = io;
382 tr->ioval = 0xf;
383 mutex_init(&tr->lock);
384
385 if (tr->io == -1) {
386 v4l2_err(v4l2_dev, "You must set an I/O address with io=0x???\n");
384 return -EINVAL; 387 return -EINVAL;
385 } 388 }
386 if(!request_region(io, 2, "Trust FM Radio")) { 389 if (!request_region(tr->io, 2, "Trust FM Radio")) {
387 printk(KERN_ERR "trust: port 0x%x already in use\n", io); 390 v4l2_err(v4l2_dev, "port 0x%x already in use\n", tr->io);
388 return -EBUSY; 391 return -EBUSY;
389 } 392 }
390 if (video_register_device(&trust_radio, VFL_TYPE_RADIO, radio_nr) < 0) { 393
391 release_region(io, 2); 394 res = v4l2_device_register(NULL, v4l2_dev);
395 if (res < 0) {
396 release_region(tr->io, 2);
397 v4l2_err(v4l2_dev, "Could not register v4l2_device\n");
398 return res;
399 }
400
401 strlcpy(tr->vdev.name, v4l2_dev->name, sizeof(tr->vdev.name));
402 tr->vdev.v4l2_dev = v4l2_dev;
403 tr->vdev.fops = &trust_fops;
404 tr->vdev.ioctl_ops = &trust_ioctl_ops;
405 tr->vdev.release = video_device_release_empty;
406 video_set_drvdata(&tr->vdev, tr);
407
408 if (video_register_device(&tr->vdev, VFL_TYPE_RADIO, radio_nr) < 0) {
409 v4l2_device_unregister(v4l2_dev);
410 release_region(tr->io, 2);
392 return -EINVAL; 411 return -EINVAL;
393 } 412 }
394 413
395 printk(KERN_INFO "Trust FM Radio card driver v1.0.\n"); 414 v4l2_info(v4l2_dev, "Trust FM Radio card driver v1.0.\n");
396 415
397 write_i2c(2, TDA7318_ADDR, 0x80); /* speaker att. LF = 0 dB */ 416 write_i2c(tr, 2, TDA7318_ADDR, 0x80); /* speaker att. LF = 0 dB */
398 write_i2c(2, TDA7318_ADDR, 0xa0); /* speaker att. RF = 0 dB */ 417 write_i2c(tr, 2, TDA7318_ADDR, 0xa0); /* speaker att. RF = 0 dB */
399 write_i2c(2, TDA7318_ADDR, 0xc0); /* speaker att. LR = 0 dB */ 418 write_i2c(tr, 2, TDA7318_ADDR, 0xc0); /* speaker att. LR = 0 dB */
400 write_i2c(2, TDA7318_ADDR, 0xe0); /* speaker att. RR = 0 dB */ 419 write_i2c(tr, 2, TDA7318_ADDR, 0xe0); /* speaker att. RR = 0 dB */
401 write_i2c(2, TDA7318_ADDR, 0x40); /* stereo 1 input, gain = 18.75 dB */ 420 write_i2c(tr, 2, TDA7318_ADDR, 0x40); /* stereo 1 input, gain = 18.75 dB */
402 421
403 tr_setvol(0x8000); 422 tr_setvol(tr, 0xffff);
404 tr_setbass(0x8000); 423 tr_setbass(tr, 0x8000);
405 tr_settreble(0x8000); 424 tr_settreble(tr, 0x8000);
406 tr_setstereo(1); 425 tr_setstereo(tr, 1);
407 426
408 /* mute card - prevents noisy bootups */ 427 /* mute card - prevents noisy bootups */
409 tr_setmute(1); 428 tr_setmute(tr, 1);
410 429
411 return 0; 430 return 0;
412} 431}
413 432
414MODULE_AUTHOR("Eric Lammerts, Russell Kroll, Quay Lu, Donald Song, Jason Lewis, Scott McGrath, William McGrath");
415MODULE_DESCRIPTION("A driver for the Trust FM Radio card.");
416MODULE_LICENSE("GPL");
417
418module_param(io, int, 0);
419MODULE_PARM_DESC(io, "I/O address of the Trust FM Radio card (0x350 or 0x358)");
420module_param(radio_nr, int, 0);
421
422static void __exit cleanup_trust_module(void) 433static void __exit cleanup_trust_module(void)
423{ 434{
424 video_unregister_device(&trust_radio); 435 struct trust *tr = &trust_card;
425 release_region(io, 2); 436
437 video_unregister_device(&tr->vdev);
438 v4l2_device_unregister(&tr->v4l2_dev);
439 release_region(tr->io, 2);
426} 440}
427 441
428module_init(trust_init); 442module_init(trust_init);