>> Btw, I've been looking at why Andrea thinks he's patches are needed,
[davej-history.git] / drivers / char / msp3400.c
blob651d5b733a05a070aaaa2392fd38f204b0e946d2
1 /*
2 * programming the msp34* sound processor family
4 * (c) 1997,1998 Gerd Knorr <kraxel@cs.tu-berlin.de>
6 * what works and what doesn't:
8 * AM mono
9 * probably doesn't (untested)
11 * FM-mono
12 * should work. FM stereo modes are backward-compatible to mono.
13 * Therefore FM mono should always be available.
15 * FM stereo (B/G, used in Germany)
16 * should work, with autodetect
18 * FM stereo (satellite)
19 * should work, no autodetect (i.e. default is mono, but you can
20 * switch to stereo -- untested)
22 * NICAM (B/G, used in UK, Scandinavia and Spain)
23 * should work, with autodetect. Support for NICAM was added by
24 * Pekka Pietikainen <pp@netppl.fi>
27 * TODO:
28 * - better SAT support
32 #include <linux/module.h>
33 #include <linux/kernel.h>
34 #include <linux/sched.h>
35 #include <linux/string.h>
36 #include <linux/timer.h>
37 #include <linux/delay.h>
38 #include <linux/errno.h>
39 #include <linux/malloc.h>
41 /* kernel_thread */
42 #define __KERNEL_SYSCALLS__
43 #include <linux/unistd.h>
45 #include <linux/i2c.h>
46 #include <linux/videodev.h>
48 #include "msp3400.h"
51 /* sound mixer stuff */
52 #include <linux/config.h>
54 #if LINUX_VERSION_CODE > 0x020140 /* need modular sound driver */
55 # if defined(CONFIG_SOUND) || defined(CONFIG_SOUND_MODULE)
56 # define REGISTER_MIXER 1
57 # endif
58 #endif
61 static int debug = 0; /* insmod parameter */
63 struct msp3400c {
64 struct i2c_bus *bus;
66 int nicam;
67 int mode;
68 int norm;
69 int stereo;
71 int mixer;
72 int left, right; /* volume */
73 int bass, treble;
75 /* thread */
76 struct task_struct *thread;
77 struct semaphore *wait;
78 struct semaphore *notify;
79 int active,restart,rmmod;
81 int watch_stereo;
82 struct timer_list wake_stereo;
85 #define VIDEO_MODE_RADIO 16 /* norm magic for radio mode */
87 /* ---------------------------------------------------------------------- */
89 #define dprintk if (debug) printk
91 MODULE_PARM(debug,"i");
93 /* ---------------------------------------------------------------------- */
95 #define I2C_MSP3400C 0x80
96 #define I2C_MSP3400C_DEM 0x10
97 #define I2C_MSP3400C_DFP 0x12
99 /* ----------------------------------------------------------------------- */
100 /* functions for talking to the MSP3400C Sound processor */
102 static int msp3400c_reset(struct i2c_bus *bus)
104 int ret = 0;
106 mdelay(2);
107 i2c_start(bus);
108 i2c_sendbyte(bus, I2C_MSP3400C,2000);
109 i2c_sendbyte(bus, 0x00,0);
110 i2c_sendbyte(bus, 0x80,0);
111 i2c_sendbyte(bus, 0x00,0);
112 i2c_stop(bus);
113 mdelay(2);
114 i2c_start(bus);
115 if (0 != i2c_sendbyte(bus, I2C_MSP3400C,2000) ||
116 0 != i2c_sendbyte(bus, 0x00,0) ||
117 0 != i2c_sendbyte(bus, 0x00,0) ||
118 0 != i2c_sendbyte(bus, 0x00,0)) {
119 ret = -1;
120 printk(KERN_ERR "msp3400: chip reset failed, penguin on i2c bus?\n");
122 i2c_stop(bus);
123 mdelay(2);
124 return ret;
127 static int
128 msp3400c_read(struct i2c_bus *bus, int dev, int addr)
130 int ret=0;
131 short val = 0;
132 i2c_start(bus);
133 if (0 != i2c_sendbyte(bus, I2C_MSP3400C,2000) ||
134 0 != i2c_sendbyte(bus, dev+1, 0) ||
135 0 != i2c_sendbyte(bus, addr >> 8, 0) ||
136 0 != i2c_sendbyte(bus, addr & 0xff, 0)) {
137 ret = -1;
138 } else {
139 i2c_start(bus);
140 if (0 != i2c_sendbyte(bus, I2C_MSP3400C+1,2000)) {
141 ret = -1;
142 } else {
143 val |= (int)i2c_readbyte(bus,0) << 8;
144 val |= (int)i2c_readbyte(bus,1);
147 i2c_stop(bus);
148 if (-1 == ret) {
149 printk(KERN_WARNING "msp3400: I/O error, trying reset (read %s 0x%x)\n",
150 (dev == I2C_MSP3400C_DEM) ? "Demod" : "Audio", addr);
151 msp3400c_reset(bus);
153 return val;
156 static int
157 msp3400c_write(struct i2c_bus *bus, int dev, int addr, int val)
159 int ret = 0;
161 i2c_start(bus);
162 if (0 != i2c_sendbyte(bus, I2C_MSP3400C,2000) ||
163 0 != i2c_sendbyte(bus, dev, 0) ||
164 0 != i2c_sendbyte(bus, addr >> 8, 0) ||
165 0 != i2c_sendbyte(bus, addr & 0xff, 0) ||
166 0 != i2c_sendbyte(bus, val >> 8, 0) ||
167 0 != i2c_sendbyte(bus, val & 0xff, 0))
168 ret = -1;
169 i2c_stop(bus);
170 if (-1 == ret) {
171 printk(KERN_WARNING "msp3400: I/O error, trying reset (write %s 0x%x)\n",
172 (dev == I2C_MSP3400C_DEM) ? "Demod" : "Audio", addr);
173 msp3400c_reset(bus);
175 return ret;
178 /* ------------------------------------------------------------------------ */
180 /* This macro is allowed for *constants* only, gcc must calculate it
181 at compile time. Remember -- no floats in kernel mode */
182 #define MSP_CARRIER(freq) ((int)((float)(freq/18.432)*(1<<24)))
184 #define MSP_MODE_AM_DETECT 0
185 #define MSP_MODE_FM_RADIO 2
186 #define MSP_MODE_FM_TERRA 3
187 #define MSP_MODE_FM_SAT 4
188 #define MSP_MODE_FM_NICAM1 5
189 #define MSP_MODE_FM_NICAM2 6
191 static struct MSP_INIT_DATA_DEM {
192 int fir1[6];
193 int fir2[6];
194 int cdo1;
195 int cdo2;
196 int ad_cv;
197 int mode_reg;
198 int dfp_src;
199 int dfp_matrix;
200 } msp_init_data[] = {
201 /* AM (for carrier detect / msp3400) */
202 { { 75, 19, 36, 35, 39, 40 }, { 75, 19, 36, 35, 39, 40 },
203 MSP_CARRIER(5.5), MSP_CARRIER(5.5),
204 0x00d0, 0x0500, 0x0020, 0x3000},
206 /* AM (for carrier detect / msp3410) */
207 { { -1, -1, -8, 2, 59, 126 }, { -1, -1, -8, 2, 59, 126 },
208 MSP_CARRIER(5.5), MSP_CARRIER(5.5),
209 0x00d0, 0x0100, 0x0020, 0x3000},
211 /* FM Radio */
212 { { -8, -8, 4, 6, 78, 107 }, { -8, -8, 4, 6, 78, 107 },
213 MSP_CARRIER(10.7), MSP_CARRIER(10.7),
214 0x00d0, 0x0480, 0x0020, 0x3002 },
216 /* Terrestial FM-mono */
217 { { 3, 18, 27, 48, 66, 72 }, { 3, 18, 27, 48, 66, 72 },
218 MSP_CARRIER(5.5), MSP_CARRIER(5.5),
219 0x00d0, 0x0480, 0x0030, 0x3000},
221 /* Sat FM-mono */
222 { { 1, 9, 14, 24, 33, 37 }, { 3, 18, 27, 48, 66, 72 },
223 MSP_CARRIER(6.5), MSP_CARRIER(6.5),
224 0x00c6, 0x0480, 0x0000, 0x3000},
226 /* NICAM B/G, D/K */
227 { { -2, -8, -10, 10, 50, 86 }, { 3, 18, 27, 48, 66, 72 },
228 MSP_CARRIER(5.5), MSP_CARRIER(5.5),
229 0x00d0, 0x0040, 0x0120, 0x3000},
231 /* NICAM I */
232 { { 2, 4, -6, -4, 40, 94 }, { 3, 18, 27, 48, 66, 72 },
233 MSP_CARRIER(5.5), MSP_CARRIER(5.5),
234 0x00d0, 0x0040, 0x0120, 0x3000},
237 struct CARRIER_DETECT {
238 int cdo;
239 char *name;
242 static struct CARRIER_DETECT carrier_detect_main[] = {
243 /* main carrier */
244 { MSP_CARRIER(4.5), "4.5 NTSC" },
245 { MSP_CARRIER(5.5), "5.5 PAL B/G" },
246 { MSP_CARRIER(6.0), "6.0 PAL I" },
247 { MSP_CARRIER(6.5), "6.5 PAL SAT / SECAM" }
250 static struct CARRIER_DETECT carrier_detect_55[] = {
251 /* PAL B/G */
252 { MSP_CARRIER(5.7421875), "5.742 PAL B/G FM-stereo" },
253 { MSP_CARRIER(5.85), "5.85 PAL B/G NICAM" }
256 static struct CARRIER_DETECT carrier_detect_65[] = {
257 /* PAL SAT / SECAM */
258 { MSP_CARRIER(7.02), "7.02 PAL SAT FM-stereo s/b" },
259 { MSP_CARRIER(7.20), "7.20 PAL SAT FM-stereo s" },
260 { MSP_CARRIER(7.38), "7.38 PAL SAT FM-stereo b" },
263 #define CARRIER_COUNT(x) (sizeof(x)/sizeof(struct CARRIER_DETECT))
265 /* ------------------------------------------------------------------------ */
267 static void msp3400c_setcarrier(struct i2c_bus *bus, int cdo1, int cdo2)
269 msp3400c_write(bus,I2C_MSP3400C_DEM, 0x0093, cdo1 & 0xfff);
270 msp3400c_write(bus,I2C_MSP3400C_DEM, 0x009b, cdo1 >> 12);
271 msp3400c_write(bus,I2C_MSP3400C_DEM, 0x00a3, cdo2 & 0xfff);
272 msp3400c_write(bus,I2C_MSP3400C_DEM, 0x00ab, cdo2 >> 12);
275 static void msp3400c_setvolume(struct i2c_bus *bus, int left, int right)
277 int vol,val,balance;
279 vol = (left > right) ? left : right;
280 val = (vol * 0x73 / 65535) << 8;
281 balance = 0;
282 if (vol > 0)
283 balance = ((right-left) * 127) / vol;
285 dprintk("msp3400: setvolume: %d:%d 0x%02x 0x%02x\n",
286 left,right,val>>8,balance);
287 msp3400c_write(bus,I2C_MSP3400C_DFP, 0x0000, val); /* loudspeaker */
288 msp3400c_write(bus,I2C_MSP3400C_DFP, 0x0006, val); /* headphones */
289 /* scart - on/off only */
290 msp3400c_write(bus,I2C_MSP3400C_DFP, 0x0007, val ? 0x4000 : 0);
291 msp3400c_write(bus,I2C_MSP3400C_DFP, 0x0001, balance << 8);
294 static void msp3400c_setbass(struct i2c_bus *bus, int bass)
296 int val = ((bass-32768) * 0x60 / 65535) << 8;
298 dprintk("msp3400: setbass: %d 0x%02x\n",bass, val>>8);
299 msp3400c_write(bus,I2C_MSP3400C_DFP, 0x0002, val); /* loudspeaker */
302 static void msp3400c_settreble(struct i2c_bus *bus, int treble)
304 int val = ((treble-32768) * 0x60 / 65535) << 8;
306 dprintk("msp3400: settreble: %d 0x%02x\n",treble, val>>8);
307 msp3400c_write(bus,I2C_MSP3400C_DFP, 0x0003, val); /* loudspeaker */
310 static void msp3400c_setmode(struct msp3400c *msp, int type)
312 int i;
314 dprintk("msp3400: setmode: %d\n",type);
315 msp->mode = type;
316 msp->stereo = VIDEO_SOUND_MONO;
318 msp3400c_write(msp->bus,I2C_MSP3400C_DEM, 0x00bb, /* ad_cv */
319 msp_init_data[type].ad_cv);
321 for (i = 5; i >= 0; i--) /* fir 1 */
322 msp3400c_write(msp->bus,I2C_MSP3400C_DEM, 0x0001,
323 msp_init_data[type].fir1[i]);
325 msp3400c_write(msp->bus,I2C_MSP3400C_DEM, 0x0005, 0x0004); /* fir 2 */
326 msp3400c_write(msp->bus,I2C_MSP3400C_DEM, 0x0005, 0x0040);
327 msp3400c_write(msp->bus,I2C_MSP3400C_DEM, 0x0005, 0x0000);
328 for (i = 5; i >= 0; i--)
329 msp3400c_write(msp->bus,I2C_MSP3400C_DEM, 0x0005,
330 msp_init_data[type].fir2[i]);
332 msp3400c_write(msp->bus,I2C_MSP3400C_DEM, 0x0083, /* MODE_REG */
333 msp_init_data[type].mode_reg);
335 msp3400c_setcarrier(msp->bus, msp_init_data[type].cdo1,
336 msp_init_data[type].cdo2);
338 msp3400c_write(msp->bus,I2C_MSP3400C_DFP, 0x0008,
339 msp_init_data[type].dfp_src);
340 msp3400c_write(msp->bus,I2C_MSP3400C_DFP, 0x0009,
341 msp_init_data[type].dfp_src);
342 msp3400c_write(msp->bus,I2C_MSP3400C_DFP, 0x000a,
343 msp_init_data[type].dfp_src);
344 msp3400c_write(msp->bus,I2C_MSP3400C_DFP, 0x000e,
345 msp_init_data[type].dfp_matrix);
347 if (msp->nicam) {
348 /* msp3410 needs some more initialization */
349 msp3400c_write(msp->bus,I2C_MSP3400C_DFP, 0x0010, 0x3000);
353 static void msp3400c_setstereo(struct msp3400c *msp, int mode)
355 int nicam=0; /* channel source: FM/AM or nicam */
357 /* switch demodulator */
358 switch (msp->mode) {
359 case MSP_MODE_FM_TERRA:
360 dprintk("msp3400: B/G setstereo: %d\n",mode);
361 msp->stereo = mode;
362 msp3400c_setcarrier(msp->bus,MSP_CARRIER(5.7421875),MSP_CARRIER(5.5));
363 switch (mode) {
364 case VIDEO_SOUND_STEREO:
365 msp3400c_write(msp->bus,I2C_MSP3400C_DFP, 0x000e, 0x3001);
366 break;
367 case VIDEO_SOUND_MONO:
368 case VIDEO_SOUND_LANG1:
369 case VIDEO_SOUND_LANG2:
370 msp3400c_write(msp->bus,I2C_MSP3400C_DFP, 0x000e, 0x3000);
371 break;
373 break;
374 case MSP_MODE_FM_SAT:
375 dprintk("msp3400: sat setstereo: %d\n",mode);
376 msp->stereo = mode;
377 switch (mode) {
378 case VIDEO_SOUND_MONO:
379 msp3400c_setcarrier(msp->bus, MSP_CARRIER(6.5), MSP_CARRIER(6.5));
380 break;
381 case VIDEO_SOUND_STEREO:
382 msp3400c_setcarrier(msp->bus, MSP_CARRIER(7.2), MSP_CARRIER(7.02));
383 break;
384 case VIDEO_SOUND_LANG1:
385 msp3400c_setcarrier(msp->bus, MSP_CARRIER(7.38), MSP_CARRIER(7.02));
386 break;
387 case VIDEO_SOUND_LANG2:
388 msp3400c_setcarrier(msp->bus, MSP_CARRIER(7.38), MSP_CARRIER(7.02));
389 break;
391 break;
392 case MSP_MODE_FM_NICAM1:
393 dprintk("msp3400: NICAM1 setstereo: %d\n",mode);
394 msp->stereo = mode;
395 msp3400c_setcarrier(msp->bus,MSP_CARRIER(5.85),MSP_CARRIER(5.5));
396 nicam=0x0100;
397 break;
398 default:
399 /* can't do stereo - abort here */
400 return;
403 /* switch audio */
404 switch (mode) {
405 case VIDEO_SOUND_STEREO:
406 msp3400c_write(msp->bus,I2C_MSP3400C_DFP, 0x0008,0x0020|nicam);
407 msp3400c_write(msp->bus,I2C_MSP3400C_DFP, 0x0009,0x0020|nicam);
408 msp3400c_write(msp->bus,I2C_MSP3400C_DFP, 0x000a,0x0020|nicam);
409 msp3400c_write(msp->bus,I2C_MSP3400C_DFP, 0x0005,0x4000);
410 break;
411 case VIDEO_SOUND_MONO:
412 case VIDEO_SOUND_LANG1:
413 msp3400c_write(msp->bus,I2C_MSP3400C_DFP, 0x0008,0x0000|nicam);
414 msp3400c_write(msp->bus,I2C_MSP3400C_DFP, 0x0009,0x0000|nicam);
415 msp3400c_write(msp->bus,I2C_MSP3400C_DFP, 0x000a,0x0000|nicam);
416 break;
417 case VIDEO_SOUND_LANG2:
418 msp3400c_write(msp->bus,I2C_MSP3400C_DFP, 0x0008,0x0010|nicam);
419 msp3400c_write(msp->bus,I2C_MSP3400C_DFP, 0x0009,0x0010|nicam);
420 msp3400c_write(msp->bus,I2C_MSP3400C_DFP, 0x000a,0x0010|nicam);
421 break;
425 /* ----------------------------------------------------------------------- */
427 struct REGISTER_DUMP {
428 int addr;
429 char *name;
432 struct REGISTER_DUMP d1[] = {
433 { 0x007e, "autodetect" },
434 { 0x0023, "C_AD_BITS " },
435 { 0x0038, "ADD_BITS " },
436 { 0x003e, "CIB_BITS " },
437 { 0x0057, "ERROR_RATE" },
441 * A kernel thread for msp3400 control -- we don't want to block the
442 * in the ioctl while doing the sound carrier & stereo detect
445 static void msp3400c_stereo_wake(unsigned long data)
447 struct msp3400c *msp = (struct msp3400c*)data; /* XXX alpha ??? */
449 if (!msp->active)
450 up(msp->wait);
453 static int msp3400c_thread(void *data)
455 unsigned long flags;
456 struct msp3400c *msp = data;
457 struct semaphore sem = MUTEX_LOCKED;
459 struct CARRIER_DETECT *cd;
460 int count, max1,max2,val1,val2, val,this;
461 int newstereo;
463 /* lock_kernel(); */
465 exit_mm(current);
466 current->session = 1;
467 current->pgrp = 1;
468 sigfillset(&current->blocked);
469 current->fs->umask = 0;
470 strcpy(current->comm,"msp3400");
472 msp->wait = &sem;
473 msp->thread = current;
475 /* unlock_kernel(); */
477 dprintk("msp3400: thread: start\n");
478 if(msp->notify != NULL)
479 up(msp->notify);
481 for (;;) {
482 if (msp->rmmod)
483 goto done;
484 dprintk("msp3400: thread: sleep\n");
485 down_interruptible(&sem);
486 dprintk("msp3400: thread: wakeup\n");
487 if (msp->rmmod || signal_pending(current))
488 goto done;
490 if (VIDEO_MODE_RADIO == msp->norm)
491 continue; /* nothing to do */
493 msp->active = 1;
495 if (msp->watch_stereo) {
496 /* do that stereo/multilang handling */
497 LOCK_I2C_BUS(msp->bus);
498 newstereo = msp->stereo;
499 switch (msp->mode) {
500 case MSP_MODE_FM_TERRA:
501 val = msp3400c_read(msp->bus, I2C_MSP3400C_DFP, 0x18);
502 dprintk("msp3400: stereo detect register: %d\n",val);
504 if (val > 4096) {
505 newstereo = VIDEO_SOUND_STEREO;
506 } else if (val < -4096) {
507 newstereo = VIDEO_SOUND_LANG1;
508 } else {
509 newstereo = VIDEO_SOUND_MONO;
511 break;
512 case MSP_MODE_FM_NICAM1:
513 val = msp3400c_read(msp->bus, I2C_MSP3400C_DEM, 0x23);
514 switch ((val & 0x1e) >> 1) {
515 case 0:
516 case 8:
517 newstereo = VIDEO_SOUND_STEREO;
518 break;
519 default:
520 newstereo = VIDEO_SOUND_MONO;
521 break;
523 break;
525 if (msp->stereo != newstereo) {
526 dprintk("msp3400: watch: stereo %d ==> %d\n",
527 msp->stereo,newstereo);
528 msp3400c_setstereo(msp,newstereo);
530 UNLOCK_I2C_BUS(msp->bus);
531 if (msp->watch_stereo) {
532 del_timer(&msp->wake_stereo);
533 msp->wake_stereo.expires = jiffies + 5*HZ;
534 add_timer(&msp->wake_stereo);
537 msp->active = 0;
538 continue;
541 restart:
542 LOCK_I2C_BUS(msp->bus);
543 msp3400c_setvolume(msp->bus, 0, 0);
544 msp3400c_setmode(msp, MSP_MODE_AM_DETECT);
545 val1 = val2 = 0;
546 max1 = max2 = -1;
547 del_timer(&msp->wake_stereo);
548 msp->watch_stereo = 0;
550 /* carrier detect pass #1 -- main carrier */
551 cd = carrier_detect_main; count = CARRIER_COUNT(carrier_detect_main);
552 for (this = 0; this < count; this++) {
553 msp3400c_setcarrier(msp->bus, cd[this].cdo,cd[this].cdo);
554 UNLOCK_I2C_BUS(msp->bus);
556 current->state = TASK_INTERRUPTIBLE;
557 schedule_timeout(HZ/25);
558 if (signal_pending(current))
559 goto done;
560 if (msp->restart) {
561 msp->restart = 0;
562 goto restart;
565 LOCK_I2C_BUS(msp->bus);
566 val = msp3400c_read(msp->bus, I2C_MSP3400C_DFP, 0x1b);
567 if (val1 < val)
568 val1 = val, max1 = this;
569 dprintk("msp3400: carrier1 val: %5d / %s\n", val,cd[this].name);
572 /* carrier detect pass #2 -- second (stereo) carrier */
573 switch (max1) {
574 case 1: /* 5.5 */
575 cd = carrier_detect_55; count = CARRIER_COUNT(carrier_detect_55);
576 break;
577 case 3: /* 6.5 */
578 cd = carrier_detect_65; count = CARRIER_COUNT(carrier_detect_65);
579 break;
580 case 0: /* 4.5 */
581 case 2: /* 6.0 */
582 default:
583 cd = NULL; count = 0;
584 break;
586 for (this = 0; this < count; this++) {
587 msp3400c_setcarrier(msp->bus, cd[this].cdo,cd[this].cdo);
588 UNLOCK_I2C_BUS(msp->bus);
590 current->state = TASK_INTERRUPTIBLE;
591 schedule_timeout(HZ/25);
592 if (signal_pending(current))
593 goto done;
594 if (msp->restart) {
595 msp->restart = 0;
596 goto restart;
599 LOCK_I2C_BUS(msp->bus);
600 val = msp3400c_read(msp->bus, I2C_MSP3400C_DFP, 0x1b);
601 if (val2 < val)
602 val2 = val, max2 = this;
603 dprintk("msp3400: carrier2 val: %5d / %s\n", val,cd[this].name);
606 /* program the msp3400 according to the results */
607 switch (max1) {
608 case 0: /* 4.5 */
609 case 1: /* 5.5 */
610 msp3400c_setmode(msp, MSP_MODE_FM_TERRA);
611 msp3400c_setcarrier(msp->bus, carrier_detect_main[max1].cdo,
612 carrier_detect_main[max1].cdo);
613 if (max2 == 0) {
614 /* B/G FM-stereo */
615 msp3400c_setstereo(msp, VIDEO_SOUND_MONO);
616 msp->watch_stereo = 1;
618 if (max2 == 1 && msp->nicam) {
619 /* B/G NICAM */
620 msp3400c_setmode(msp, MSP_MODE_FM_NICAM1);
621 /* msp3400c_write(msp->bus, I2C_MSP3400C_DFP, 0x21, 0x01); */
622 msp3400c_setcarrier(msp->bus, MSP_CARRIER(5.85),
623 MSP_CARRIER(5.5));
624 msp->watch_stereo = 1;
626 break;
627 case 2: /* 6.0 */
628 case 3: /* 6.5 */
629 default:
630 msp3400c_setmode(msp, MSP_MODE_FM_TERRA);
631 msp3400c_setcarrier(msp->bus, carrier_detect_main[max1].cdo,
632 carrier_detect_main[max1].cdo);
633 msp3400c_setstereo(msp, VIDEO_SOUND_STEREO);
634 break;
637 /* unmute */
638 msp3400c_setvolume(msp->bus, msp->left, msp->right);
639 UNLOCK_I2C_BUS(msp->bus);
641 if (msp->watch_stereo) {
642 del_timer(&msp->wake_stereo);
643 msp->wake_stereo.expires = jiffies + HZ;
644 add_timer(&msp->wake_stereo);
646 msp->active = 0;
649 done:
650 dprintk("msp3400: thread: exit\n");
651 msp->wait = NULL;
652 msp->active = 0;
653 msp->thread = NULL;
655 if(msp->notify != NULL)
656 up(msp->notify);
657 return 0;
661 #if 0 /* not finished yet */
663 static int msp3410d_thread(void *data)
665 unsigned long flags;
666 struct msp3400c *msp = data;
667 struct semaphore sem = MUTEX_LOCKED;
668 int i, val;
670 /* lock_kernel(); */
672 exit_mm(current);
673 current->session = 1;
674 current->pgrp = 1;
675 sigfillset(&current->blocked);
676 current->fs->umask = 0;
677 strcpy(current->comm,"msp3410 (nicam)");
679 msp->wait = &sem;
680 msp->thread = current;
682 /* unlock_kernel(); */
684 dprintk("msp3410: thread: start\n");
685 if(msp->notify != NULL)
686 up(msp->notify);
688 for (;;) {
689 if (msp->rmmod)
690 goto done;
691 dprintk("msp3410: thread: sleep\n");
692 down_interruptible(&sem);
693 dprintk("msp3410: thread: wakeup\n");
694 if (msp->rmmod)
695 goto done;
697 if (VIDEO_MODE_RADIO == msp->norm)
698 continue; /* nothing to do */
700 msp->active = 1;
702 restart:
703 LOCK_I2C_BUS(msp->bus);
704 /* mute */
705 msp3400c_setvolume(msp->bus, 0);
706 /* quick & dirty hack:
707 get the audio proccessor into some useful state */
708 msp3400c_setmode(msp, MSP_MODE_FM_NICAM1);
709 /* kick autodetect */
710 msp3400c_write(msp->bus, I2C_MSP3400C_DFP, 0x20, 0x01);
711 msp3400c_write(msp->bus, I2C_MSP3400C_DFP, 0x21, 0x01);
712 UNLOCK_I2C_BUS(msp->bus);
714 /* wait 1 sec */
715 current->state = TASK_INTERRUPTIBLE;
716 schedule_timeout(HZ);
717 if (signal_pending(current))
718 goto done;
719 if (msp->restart) {
720 msp->restart = 0;
721 goto restart;
724 LOCK_I2C_BUS(msp->bus);
725 /* debug register dump */
726 for (i = 0; i < sizeof(d1)/sizeof(struct REGISTER_DUMP); i++) {
727 val = msp3400c_read(msp->bus,I2C_MSP3400C_DEM,d1[i].addr);
728 printk(KERN_DEBUG "msp3400: %s = 0x%x\n",d1[i].name,val);
730 /* unmute */
731 msp3400c_setvolume(msp->bus, msp->volume);
732 UNLOCK_I2C_BUS(msp->bus);
734 msp->active = 0;
737 done:
738 dprintk("msp3410: thread: exit\n");
739 msp->wait = NULL;
740 msp->active = 0;
741 msp->thread = NULL;
743 if(msp->notify != NULL)
744 up(msp->notify);
745 return 0;
747 #endif
749 /* ----------------------------------------------------------------------- */
750 /* mixer stuff -- with the modular sound driver in 2.1.x we can easily */
751 /* register the msp3400 as mixer device */
753 #ifdef REGISTER_MIXER
755 #include <linux/soundcard.h>
756 #include <../drivers/sound/sound_config.h>
757 #include <../drivers/sound/dev_table.h>
759 static int mix_to_v4l(int i)
761 int r;
763 r = ((i & 0xff) * 65536 + 50) / 100;
764 if (r > 65535) r = 65535;
765 if (r < 0) r = 0;
766 return r;
769 static int v4l_to_mix(int i)
771 int r;
773 r = (i * 100 + 32768) / 65536;
774 if (r > 100) r = 100;
775 if (r < 0) r = 0;
776 return r | (r << 8);
779 static int v4l_to_mix2(int l, int r)
781 r = (r * 100 + 32768) / 65536;
782 if (r > 100) r = 100;
783 if (r < 0) r = 0;
784 l = (l * 100 + 32768) / 65536;
785 if (l > 100) l = 100;
786 if (l < 0) l = 0;
787 return (r << 8) | l;
790 static int msp3400c_mixer_ioctl(int dev, unsigned int cmd, caddr_t arg)
792 struct msp3400c *msp = mixer_devs[dev]->devc;
793 unsigned long flags;
794 int ret,val = 0;
796 if (_SIOC_DIR(cmd) & _SIOC_WRITE)
797 if (get_user(val, (int *)arg))
798 return -EFAULT;
800 switch (cmd) {
801 case MIXER_READ(SOUND_MIXER_RECMASK):
802 case MIXER_READ(SOUND_MIXER_CAPS):
803 case MIXER_READ(SOUND_MIXER_RECSRC):
804 case MIXER_WRITE(SOUND_MIXER_RECSRC):
805 ret = 0;
806 break;
808 case MIXER_READ(SOUND_MIXER_STEREODEVS):
809 ret = SOUND_MASK_VOLUME;
810 break;
811 case MIXER_READ(SOUND_MIXER_DEVMASK):
812 ret = SOUND_MASK_VOLUME | SOUND_MASK_BASS | SOUND_MASK_TREBLE;
813 break;
815 case MIXER_WRITE(SOUND_MIXER_VOLUME):
816 msp->left = mix_to_v4l(val);
817 msp->right = mix_to_v4l(val >> 8);
818 LOCK_I2C_BUS(msp->bus);
819 msp3400c_setvolume(msp->bus,msp->left,msp->right);
820 UNLOCK_I2C_BUS(msp->bus);
821 /* fall */
822 case MIXER_READ(SOUND_MIXER_VOLUME):
823 ret = v4l_to_mix2(msp->left, msp->right);
824 break;
826 case MIXER_WRITE(SOUND_MIXER_BASS):
827 msp->bass = mix_to_v4l(val);
828 LOCK_I2C_BUS(msp->bus);
829 msp3400c_setbass(msp->bus,msp->bass);
830 UNLOCK_I2C_BUS(msp->bus);
831 /* fall */
832 case MIXER_READ(SOUND_MIXER_BASS):
833 ret = v4l_to_mix(msp->bass);
834 break;
836 case MIXER_WRITE(SOUND_MIXER_TREBLE):
837 msp->treble = mix_to_v4l(val);
838 LOCK_I2C_BUS(msp->bus);
839 msp3400c_settreble(msp->bus,msp->treble);
840 UNLOCK_I2C_BUS(msp->bus);
841 /* fall */
842 case MIXER_READ(SOUND_MIXER_TREBLE):
843 ret = v4l_to_mix(msp->treble);
844 break;
846 default:
847 return -EINVAL;
849 if (put_user(ret, (int *)arg))
850 return -EFAULT;
851 return 0;
854 struct mixer_operations msp3400c_mixer = {
855 "video4linux",
856 "TV card sound (msp3400)",
857 msp3400c_mixer_ioctl
860 static int msp3400c_mixer_init(struct msp3400c *msp)
862 int m;
864 msp->mixer = m = sound_alloc_mixerdev();
865 if (m == -1)
866 return -1;
868 mixer_devs[m] = (struct mixer_operations *)
869 kmalloc(sizeof(struct mixer_operations), GFP_KERNEL);
870 if (mixer_devs[m] == NULL) {
871 printk(KERN_ERR "msp3400c: can't allocate memory\n");
872 sound_unload_mixerdev(m);
873 return -1;
875 memcpy(mixer_devs[m],&msp3400c_mixer,sizeof(struct mixer_operations));
876 mixer_devs[m]->devc = msp;
877 return 0;
880 static int msp3400c_mixer_close(struct msp3400c *msp)
882 int m = msp->mixer;
884 if (m != -1 ) {
885 sound_unload_mixerdev(m);
886 kfree(mixer_devs[m]);
888 return 0;
891 #endif
893 /* ----------------------------------------------------------------------- */
895 static int msp3400c_attach(struct i2c_device *device)
897 unsigned long flags;
898 struct semaphore sem = MUTEX_LOCKED;
899 struct msp3400c *msp;
900 int rev1,rev2;
902 device->data = msp = kmalloc(sizeof(struct msp3400c),GFP_KERNEL);
903 if (NULL == msp)
904 return -ENOMEM;
905 memset(msp,0,sizeof(struct msp3400c));
906 msp->bus = device->bus;
907 msp->left = 65535;
908 msp->right = 65535;
909 msp->bass = 32768;
910 msp->treble = 32768;
912 LOCK_I2C_BUS(msp->bus);
913 if (-1 == msp3400c_reset(msp->bus)) {
914 UNLOCK_I2C_BUS(msp->bus);
915 kfree(msp);
916 return -EIO;
919 msp3400c_setmode(msp, MSP_MODE_FM_TERRA);
920 msp3400c_setvolume(msp->bus, msp->left, msp->right);
921 msp3400c_setbass(msp->bus, msp->bass);
922 msp3400c_settreble(msp->bus, msp->treble);
924 rev1 = msp3400c_read(msp->bus, I2C_MSP3400C_DFP, 0x1e);
925 rev2 = msp3400c_read(msp->bus, I2C_MSP3400C_DFP, 0x1f);
927 #if 0
928 /* this will turn on a 1kHz beep - might be useful for debugging... */
929 msp3400c_write(msp->bus,I2C_MSP3400C_DFP, 0x0014, 0x1040);
930 #endif
931 UNLOCK_I2C_BUS(msp->bus);
933 sprintf(device->name,"MSP34%02d%c-%c%d",
934 (rev2>>8)&0xff, (rev1&0xff)+'@', ((rev1>>8)&0xff)+'@', rev2&0x1f);
935 msp->nicam = (((rev2>>8)&0xff) == 10) ? 1 : 0;
937 /* timer for stereo checking */
938 msp->wake_stereo.function = msp3400c_stereo_wake;
939 msp->wake_stereo.data = (unsigned long)msp;
941 /* startup control thread */
942 MOD_INC_USE_COUNT;
943 msp->notify = &sem;
944 kernel_thread(msp3400c_thread, (void *)msp, 0);
945 down(&sem);
946 msp->notify = NULL;
947 if (!msp->active)
948 up(msp->wait);
950 printk(KERN_INFO "msp3400: init: chip=%s",device->name);
951 if (msp->nicam)
952 printk(", has NICAM support");
953 #ifdef REGISTER_MIXER
954 if (0 == msp3400c_mixer_init(msp))
955 printk(", registered as sound mixer");
956 #endif
957 printk("\n");
958 return 0;
961 static int msp3400c_detach(struct i2c_device *device)
963 unsigned long flags;
964 struct semaphore sem = MUTEX_LOCKED;
965 struct msp3400c *msp = (struct msp3400c*)device->data;
967 #ifdef REGISTER_MIXER
968 msp3400c_mixer_close(msp);
969 #endif
971 /* shutdown control thread */
972 del_timer(&msp->wake_stereo);
973 if (msp->thread)
975 msp->notify = &sem;
976 msp->rmmod = 1;
977 if (!msp->active)
978 up(msp->wait);
979 down(&sem);
980 msp->notify = NULL;
983 LOCK_I2C_BUS(msp->bus);
984 msp3400c_reset(msp->bus);
985 UNLOCK_I2C_BUS(msp->bus);
987 kfree(msp);
988 MOD_DEC_USE_COUNT;
989 return 0;
992 static int msp3400c_command(struct i2c_device *device,
993 unsigned int cmd, void *arg)
995 unsigned long flags;
996 struct msp3400c *msp = (struct msp3400c*)device->data;
997 int *iarg = (int*)arg;
999 switch (cmd) {
1000 case MSP_SET_RADIO:
1001 msp->norm = VIDEO_MODE_RADIO;
1002 msp->watch_stereo=0;
1003 del_timer(&msp->wake_stereo);
1004 LOCK_I2C_BUS(msp->bus);
1005 msp3400c_setmode(msp,MSP_MODE_FM_RADIO);
1006 msp3400c_setcarrier(msp->bus, MSP_CARRIER(10.7),MSP_CARRIER(10.7));
1007 UNLOCK_I2C_BUS(msp->bus);
1008 break;
1009 case MSP_SET_TVNORM:
1010 msp->norm = *iarg;
1011 break;
1012 case MSP_NEWCHANNEL:
1013 msp->watch_stereo=0;
1014 del_timer(&msp->wake_stereo);
1015 if (!msp->active)
1016 up(msp->wait);
1017 else
1018 msp->restart = 1;
1019 break;
1021 case MSP_GET_VOLUME:
1022 *iarg = (msp->left > msp->right) ? msp->left : msp->right;
1023 break;
1024 case MSP_SET_VOLUME:
1025 msp->left = msp->right = *iarg;
1026 LOCK_I2C_BUS(msp->bus);
1027 msp3400c_setvolume(msp->bus,msp->left, msp->right);
1028 UNLOCK_I2C_BUS(msp->bus);
1029 break;
1031 case MSP_GET_BASS:
1032 *iarg = msp->bass;
1033 break;
1034 case MSP_SET_BASS:
1035 msp->bass = *iarg;
1036 LOCK_I2C_BUS(msp->bus);
1037 msp3400c_setbass(msp->bus,msp->bass);
1038 UNLOCK_I2C_BUS(msp->bus);
1039 break;
1041 case MSP_GET_TREBLE:
1042 *iarg = msp->treble;
1043 break;
1044 case MSP_SET_TREBLE:
1045 msp->treble = *iarg;
1046 LOCK_I2C_BUS(msp->bus);
1047 msp3400c_settreble(msp->bus,msp->treble);
1048 UNLOCK_I2C_BUS(msp->bus);
1049 break;
1051 case MSP_GET_STEREO:
1052 *iarg = msp->stereo;
1053 break;
1054 case MSP_SET_STEREO:
1055 if (*iarg) {
1056 msp->watch_stereo=0;
1057 del_timer(&msp->wake_stereo);
1058 LOCK_I2C_BUS(msp->bus);
1059 msp3400c_setstereo(msp,*iarg);
1060 UNLOCK_I2C_BUS(msp->bus);
1062 break;
1064 case MSP_GET_DC:
1065 LOCK_I2C_BUS(msp->bus);
1066 *iarg = (int)msp3400c_read(msp->bus, I2C_MSP3400C_DFP, 0x1b) +
1067 (int)msp3400c_read(msp->bus, I2C_MSP3400C_DFP, 0x1c);
1068 UNLOCK_I2C_BUS(msp->bus);
1069 break;
1071 case MSP_GET_UNIT:
1072 *iarg = msp->mixer;
1073 break;
1075 default:
1076 return -EINVAL;
1078 return 0;
1081 /* ----------------------------------------------------------------------- */
1083 struct i2c_driver i2c_driver_msp = {
1084 "msp3400", /* name */
1085 I2C_DRIVERID_MSP3400, /* ID */
1086 I2C_MSP3400C, I2C_MSP3400C, /* addr range */
1088 msp3400c_attach,
1089 msp3400c_detach,
1090 msp3400c_command
1093 EXPORT_NO_SYMBOLS;
1095 #ifdef MODULE
1096 int init_module(void)
1097 #else
1098 int msp3400c_init(void)
1099 #endif
1101 i2c_register_driver(&i2c_driver_msp);
1102 return 0;
1105 #ifdef MODULE
1106 void cleanup_module(void)
1108 i2c_unregister_driver(&i2c_driver_msp);
1110 #endif
1113 * Overrides for Emacs so that we follow Linus's tabbing style.
1114 * ---------------------------------------------------------------------------
1115 * Local variables:
1116 * c-basic-offset: 8
1117 * End: