Linux 2.2.0
[davej-history.git] / drivers / char / msp3400.c
blobabf08764d9d823dc9ea16ff737f10f54ab558993
1 /*
2 * programming the msp34* sound processor family
4 * (c) 1997,1998 Gerd Knorr <kraxel@goldbach.in-berlin.de>
6 * what works and what doesn't:
8 * AM-Mono
9 * probably doesn't (untested)
11 * FM-Mono
12 * should work. The stereo modes are backward compatible to FM-mono,
13 * therefore FM-Mono should be allways 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
31 * 980623 Thomas Sailer (sailer@ife.ee.ethz.ch)
32 * using soundcore instead of OSS
36 #include <linux/module.h>
37 #include <linux/version.h>
38 #include <linux/kernel.h>
39 #include <linux/sched.h>
40 #include <linux/string.h>
41 #include <linux/timer.h>
42 #include <linux/delay.h>
43 #include <linux/errno.h>
44 #include <linux/malloc.h>
45 #ifdef __SMP__
46 #include <asm/pgtable.h>
47 #include <linux/smp_lock.h>
48 #endif
50 /* kernel_thread */
51 #define __KERNEL_SYSCALLS__
52 #include <linux/unistd.h>
54 #include <linux/i2c.h>
55 #include <linux/videodev.h>
57 #include "msp3400.h"
60 /* sound mixer stuff */
61 #include <linux/config.h>
63 #if LINUX_VERSION_CODE > 0x020140 /* need modular sound driver */
64 # if defined(CONFIG_SOUND) || defined(CONFIG_SOUND_MODULE)
65 # define REGISTER_MIXER 1
66 # endif
67 #endif
70 static int debug = 0; /* insmod parameter */
72 struct msp3400c {
73 struct i2c_bus *bus;
75 int nicam;
76 int mode;
77 int norm;
78 int stereo;
79 int main, second; /* sound carrier */
81 int left, right; /* volume */
82 int bass, treble;
84 /* thread */
85 struct task_struct *thread;
86 struct wait_queue *wq;
87 struct semaphore *notify;
88 int active,restart,rmmod;
90 int watch_stereo;
91 struct timer_list wake_stereo;
94 #define VIDEO_MODE_RADIO 16 /* norm magic for radio mode */
96 /* ---------------------------------------------------------------------- */
98 #define dprintk if (debug) printk
100 #if LINUX_VERSION_CODE < 0x020100
101 /* 2.0.x */
102 #define signal_pending(current) (current->signal & ~current->blocked)
103 #define sigfillset(set)
104 #define mdelay(x) udelay(1000*x)
105 #else
106 MODULE_PARM(debug,"i");
107 #endif
109 #if LINUX_VERSION_CODE < 0x02017f
110 void schedule_timeout(int j)
112 current->timeout = jiffies + j;
113 schedule();
115 #endif
117 /* ---------------------------------------------------------------------- */
119 #define I2C_MSP3400C 0x80
120 #define I2C_MSP3400C_DEM 0x10
121 #define I2C_MSP3400C_DFP 0x12
123 /* ----------------------------------------------------------------------- */
124 /* functions for talking to the MSP3400C Sound processor */
126 static int msp3400c_reset(struct i2c_bus *bus)
128 int ret = 0;
130 mdelay(2);
131 i2c_start(bus);
132 i2c_sendbyte(bus, I2C_MSP3400C,2000);
133 i2c_sendbyte(bus, 0x00,0);
134 i2c_sendbyte(bus, 0x80,0);
135 i2c_sendbyte(bus, 0x00,0);
136 i2c_stop(bus);
137 mdelay(2);
138 i2c_start(bus);
139 if (0 != i2c_sendbyte(bus, I2C_MSP3400C,2000) ||
140 0 != i2c_sendbyte(bus, 0x00,0) ||
141 0 != i2c_sendbyte(bus, 0x00,0) ||
142 0 != i2c_sendbyte(bus, 0x00,0)) {
143 ret = -1;
144 printk(KERN_ERR "msp3400: chip reset failed, penguin on i2c bus?\n");
146 i2c_stop(bus);
147 mdelay(2);
148 return ret;
151 static int
152 msp3400c_read(struct i2c_bus *bus, int dev, int addr)
154 int ret=0;
155 short val = 0;
156 i2c_start(bus);
157 if (0 != i2c_sendbyte(bus, I2C_MSP3400C,2000) ||
158 0 != i2c_sendbyte(bus, dev+1, 0) ||
159 0 != i2c_sendbyte(bus, addr >> 8, 0) ||
160 0 != i2c_sendbyte(bus, addr & 0xff, 0)) {
161 ret = -1;
162 } else {
163 i2c_start(bus);
164 if (0 != i2c_sendbyte(bus, I2C_MSP3400C+1,2000)) {
165 ret = -1;
166 } else {
167 val |= (int)i2c_readbyte(bus,0) << 8;
168 val |= (int)i2c_readbyte(bus,1);
171 i2c_stop(bus);
172 if (-1 == ret) {
173 printk(KERN_WARNING "msp3400: I/O error, trying reset (read %s 0x%x)\n",
174 (dev == I2C_MSP3400C_DEM) ? "Demod" : "Audio", addr);
175 msp3400c_reset(bus);
177 return val;
180 static int
181 msp3400c_write(struct i2c_bus *bus, int dev, int addr, int val)
183 int ret = 0;
185 i2c_start(bus);
186 if (0 != i2c_sendbyte(bus, I2C_MSP3400C,2000) ||
187 0 != i2c_sendbyte(bus, dev, 0) ||
188 0 != i2c_sendbyte(bus, addr >> 8, 0) ||
189 0 != i2c_sendbyte(bus, addr & 0xff, 0) ||
190 0 != i2c_sendbyte(bus, val >> 8, 0) ||
191 0 != i2c_sendbyte(bus, val & 0xff, 0))
192 ret = -1;
193 i2c_stop(bus);
194 if (-1 == ret) {
195 printk(KERN_WARNING "msp3400: I/O error, trying reset (write %s 0x%x)\n",
196 (dev == I2C_MSP3400C_DEM) ? "Demod" : "Audio", addr);
197 msp3400c_reset(bus);
199 return ret;
202 /* ------------------------------------------------------------------------ */
204 /* This macro is allowed for *constants* only, gcc must calculate it
205 at compile time. Remember -- no floats in kernel mode */
206 #define MSP_CARRIER(freq) ((int)((float)(freq/18.432)*(1<<24)))
208 #define MSP_MODE_AM_DETECT 0
209 #define MSP_MODE_FM_RADIO 2
210 #define MSP_MODE_FM_TERRA 3
211 #define MSP_MODE_FM_SAT 4
212 #define MSP_MODE_FM_NICAM1 5
213 #define MSP_MODE_FM_NICAM2 6
215 static struct MSP_INIT_DATA_DEM {
216 int fir1[6];
217 int fir2[6];
218 int cdo1;
219 int cdo2;
220 int ad_cv;
221 int mode_reg;
222 int dfp_src;
223 int dfp_matrix;
224 } msp_init_data[] = {
225 /* AM (for carrier detect / msp3400) */
226 { { 75, 19, 36, 35, 39, 40 }, { 75, 19, 36, 35, 39, 40 },
227 MSP_CARRIER(5.5), MSP_CARRIER(5.5),
228 0x00d0, 0x0500, 0x0020, 0x3000},
230 /* AM (for carrier detect / msp3410) */
231 { { -1, -1, -8, 2, 59, 126 }, { -1, -1, -8, 2, 59, 126 },
232 MSP_CARRIER(5.5), MSP_CARRIER(5.5),
233 0x00d0, 0x0100, 0x0020, 0x3000},
235 /* FM Radio */
236 { { -8, -8, 4, 6, 78, 107 }, { -8, -8, 4, 6, 78, 107 },
237 MSP_CARRIER(10.7), MSP_CARRIER(10.7),
238 0x00d0, 0x0480, 0x0020, 0x3000 },
240 /* Terrestial FM-mono + FM-stereo */
241 { { 3, 18, 27, 48, 66, 72 }, { 3, 18, 27, 48, 66, 72 },
242 MSP_CARRIER(5.5), MSP_CARRIER(5.5),
243 0x00d0, 0x0480, 0x0030, 0x3000},
245 /* Sat FM-mono */
246 { { 1, 9, 14, 24, 33, 37 }, { 3, 18, 27, 48, 66, 72 },
247 MSP_CARRIER(6.5), MSP_CARRIER(6.5),
248 0x00c6, 0x0480, 0x0000, 0x3000},
250 /* NICAM B/G, D/K */
251 { { -2, -8, -10, 10, 50, 86 }, { 3, 18, 27, 48, 66, 72 },
252 MSP_CARRIER(5.5), MSP_CARRIER(5.5),
253 0x00d0, 0x0040, 0x0120, 0x3000},
255 /* NICAM I */
256 { { 2, 4, -6, -4, 40, 94 }, { 3, 18, 27, 48, 66, 72 },
257 MSP_CARRIER(6.0), MSP_CARRIER(6.0),
258 0x00d0, 0x0040, 0x0120, 0x3000},
261 struct CARRIER_DETECT {
262 int cdo;
263 char *name;
266 static struct CARRIER_DETECT carrier_detect_main[] = {
267 /* main carrier */
268 { MSP_CARRIER(4.5), "4.5 NTSC" },
269 { MSP_CARRIER(5.5), "5.5 PAL B/G" },
270 { MSP_CARRIER(6.0), "6.0 PAL I" },
271 { MSP_CARRIER(6.5), "6.5 PAL D/K + SAT + SECAM" }
274 static struct CARRIER_DETECT carrier_detect_55[] = {
275 /* PAL B/G */
276 { MSP_CARRIER(5.7421875), "5.742 PAL B/G FM-stereo" },
277 { MSP_CARRIER(5.85), "5.85 PAL B/G NICAM" }
280 static struct CARRIER_DETECT carrier_detect_65[] = {
281 /* PAL SAT / SECAM */
282 { MSP_CARRIER(5.85), "5.85 PAL D/K NICAM" },
283 { MSP_CARRIER(6.2578125), "6.25 PAL D/K1 FM-stereo" },
284 { MSP_CARRIER(6.7421875), "6.74 PAL D/K2 FM-stereo" },
285 { MSP_CARRIER(7.02), "7.02 PAL SAT FM-stereo s/b" },
286 { MSP_CARRIER(7.20), "7.20 PAL SAT FM-stereo s" },
287 { MSP_CARRIER(7.38), "7.38 PAL SAT FM-stereo b" },
290 #define CARRIER_COUNT(x) (sizeof(x)/sizeof(struct CARRIER_DETECT))
292 /* ------------------------------------------------------------------------ */
294 static void msp3400c_setcarrier(struct i2c_bus *bus, int cdo1, int cdo2)
296 msp3400c_write(bus,I2C_MSP3400C_DEM, 0x0093, cdo1 & 0xfff);
297 msp3400c_write(bus,I2C_MSP3400C_DEM, 0x009b, cdo1 >> 12);
298 msp3400c_write(bus,I2C_MSP3400C_DEM, 0x00a3, cdo2 & 0xfff);
299 msp3400c_write(bus,I2C_MSP3400C_DEM, 0x00ab, cdo2 >> 12);
300 msp3400c_write(bus,I2C_MSP3400C_DEM, 0x0056, 0); /*LOAD_REG_1/2*/
303 static void msp3400c_setvolume(struct i2c_bus *bus, int left, int right)
305 int vol,val,balance;
307 vol = (left > right) ? left : right;
308 val = (vol * 0x73 / 65535) << 8;
309 balance = 0;
310 if (vol > 0)
311 balance = ((right-left) * 127) / vol;
313 dprintk("msp3400: setvolume: %d:%d 0x%02x 0x%02x\n",
314 left,right,val>>8,balance);
315 msp3400c_write(bus,I2C_MSP3400C_DFP, 0x0000, val); /* loudspeaker */
316 msp3400c_write(bus,I2C_MSP3400C_DFP, 0x0006, val); /* headphones */
317 /* scart - on/off only */
318 msp3400c_write(bus,I2C_MSP3400C_DFP, 0x0007, val ? 0x4000 : 0);
319 msp3400c_write(bus,I2C_MSP3400C_DFP, 0x0001, balance << 8);
322 static void msp3400c_setbass(struct i2c_bus *bus, int bass)
324 int val = ((bass-32768) * 0x60 / 65535) << 8;
326 dprintk("msp3400: setbass: %d 0x%02x\n",bass, val>>8);
327 msp3400c_write(bus,I2C_MSP3400C_DFP, 0x0002, val); /* loudspeaker */
330 static void msp3400c_settreble(struct i2c_bus *bus, int treble)
332 int val = ((treble-32768) * 0x60 / 65535) << 8;
334 dprintk("msp3400: settreble: %d 0x%02x\n",treble, val>>8);
335 msp3400c_write(bus,I2C_MSP3400C_DFP, 0x0003, val); /* loudspeaker */
338 static void msp3400c_setmode(struct msp3400c *msp, int type)
340 int i;
342 dprintk("msp3400: setmode: %d\n",type);
343 msp->mode = type;
344 msp->stereo = VIDEO_SOUND_MONO;
346 msp3400c_write(msp->bus,I2C_MSP3400C_DEM, 0x00bb, /* ad_cv */
347 msp_init_data[type].ad_cv);
349 for (i = 5; i >= 0; i--) /* fir 1 */
350 msp3400c_write(msp->bus,I2C_MSP3400C_DEM, 0x0001,
351 msp_init_data[type].fir1[i]);
353 msp3400c_write(msp->bus,I2C_MSP3400C_DEM, 0x0005, 0x0004); /* fir 2 */
354 msp3400c_write(msp->bus,I2C_MSP3400C_DEM, 0x0005, 0x0040);
355 msp3400c_write(msp->bus,I2C_MSP3400C_DEM, 0x0005, 0x0000);
356 for (i = 5; i >= 0; i--)
357 msp3400c_write(msp->bus,I2C_MSP3400C_DEM, 0x0005,
358 msp_init_data[type].fir2[i]);
360 msp3400c_write(msp->bus,I2C_MSP3400C_DEM, 0x0083, /* MODE_REG */
361 msp_init_data[type].mode_reg);
363 msp3400c_setcarrier(msp->bus, msp_init_data[type].cdo1,
364 msp_init_data[type].cdo2);
366 msp3400c_write(msp->bus,I2C_MSP3400C_DEM, 0x0056, 0); /*LOAD_REG_1/2*/
368 msp3400c_write(msp->bus,I2C_MSP3400C_DFP, 0x0008,
369 msp_init_data[type].dfp_src);
370 msp3400c_write(msp->bus,I2C_MSP3400C_DFP, 0x0009,
371 msp_init_data[type].dfp_src);
372 msp3400c_write(msp->bus,I2C_MSP3400C_DFP, 0x000a,
373 msp_init_data[type].dfp_src);
374 msp3400c_write(msp->bus,I2C_MSP3400C_DFP, 0x000e,
375 msp_init_data[type].dfp_matrix);
377 if (msp->nicam) {
378 /* msp3410 needs some more initialization */
379 msp3400c_write(msp->bus,I2C_MSP3400C_DFP, 0x0010, 0x3000);
383 static void msp3400c_setstereo(struct msp3400c *msp, int mode)
385 int nicam=0; /* channel source: FM/AM or nicam */
387 /* switch demodulator */
388 switch (msp->mode) {
389 case MSP_MODE_FM_TERRA:
390 dprintk("msp3400: FM setstereo: %d\n",mode);
391 msp->stereo = mode;
392 msp3400c_setcarrier(msp->bus,msp->second,msp->main);
393 switch (mode) {
394 case VIDEO_SOUND_STEREO:
395 msp3400c_write(msp->bus,I2C_MSP3400C_DFP, 0x000e, 0x3001);
396 break;
397 case VIDEO_SOUND_MONO:
398 case VIDEO_SOUND_LANG1:
399 case VIDEO_SOUND_LANG2:
400 msp3400c_write(msp->bus,I2C_MSP3400C_DFP, 0x000e, 0x3000);
401 break;
403 break;
404 case MSP_MODE_FM_SAT:
405 dprintk("msp3400: SAT setstereo: %d\n",mode);
406 msp->stereo = mode;
407 switch (mode) {
408 case VIDEO_SOUND_MONO:
409 msp3400c_setcarrier(msp->bus, MSP_CARRIER(6.5), MSP_CARRIER(6.5));
410 break;
411 case VIDEO_SOUND_STEREO:
412 msp3400c_setcarrier(msp->bus, MSP_CARRIER(7.2), MSP_CARRIER(7.02));
413 break;
414 case VIDEO_SOUND_LANG1:
415 msp3400c_setcarrier(msp->bus, MSP_CARRIER(7.38), MSP_CARRIER(7.02));
416 break;
417 case VIDEO_SOUND_LANG2:
418 msp3400c_setcarrier(msp->bus, MSP_CARRIER(7.38), MSP_CARRIER(7.02));
419 break;
421 break;
422 case MSP_MODE_FM_NICAM1:
423 case MSP_MODE_FM_NICAM2:
424 dprintk("msp3400: NICAM setstereo: %d\n",mode);
425 msp->stereo = mode;
426 msp3400c_setcarrier(msp->bus,msp->second,msp->main);
427 nicam=0x0100;
428 break;
429 default:
430 /* can't do stereo - abort here */
431 return;
434 /* switch audio */
435 switch (mode) {
436 case VIDEO_SOUND_STEREO:
437 msp3400c_write(msp->bus,I2C_MSP3400C_DFP, 0x0008,0x0020|nicam);
438 msp3400c_write(msp->bus,I2C_MSP3400C_DFP, 0x0009,0x0020|nicam);
439 msp3400c_write(msp->bus,I2C_MSP3400C_DFP, 0x000a,0x0020|nicam);
440 #if 0
441 msp3400c_write(msp->bus,I2C_MSP3400C_DFP, 0x0005,0x4000);
442 #endif
443 break;
444 case VIDEO_SOUND_MONO:
445 case VIDEO_SOUND_LANG1:
446 msp3400c_write(msp->bus,I2C_MSP3400C_DFP, 0x0008,0x0000|nicam);
447 msp3400c_write(msp->bus,I2C_MSP3400C_DFP, 0x0009,0x0000|nicam);
448 msp3400c_write(msp->bus,I2C_MSP3400C_DFP, 0x000a,0x0000|nicam);
449 break;
450 case VIDEO_SOUND_LANG2:
451 msp3400c_write(msp->bus,I2C_MSP3400C_DFP, 0x0008,0x0010|nicam);
452 msp3400c_write(msp->bus,I2C_MSP3400C_DFP, 0x0009,0x0010|nicam);
453 msp3400c_write(msp->bus,I2C_MSP3400C_DFP, 0x000a,0x0010|nicam);
454 break;
458 static void
459 msp3400c_print_mode(struct msp3400c *msp)
461 if (msp->main == msp->second) {
462 printk("msp3400: mono sound carrier: %d.%03d MHz\n",
463 msp->main/910000,(msp->main/910)%1000);
464 } else {
465 printk("msp3400: main sound carrier: %d.%03d MHz\n",
466 msp->main/910000,(msp->main/910)%1000);
468 if (msp->mode == MSP_MODE_FM_NICAM1 ||
469 msp->mode == MSP_MODE_FM_NICAM2)
470 printk("msp3400: NICAM carrier : %d.%03d MHz\n",
471 msp->second/910000,(msp->second/910)%1000);
472 if (msp->mode == MSP_MODE_FM_TERRA &&
473 msp->main != msp->second) {
474 printk("msp3400: FM-stereo carrier : %d.%03d MHz\n",
475 msp->second/910000,(msp->second/910)%1000);
479 /* ----------------------------------------------------------------------- */
481 struct REGISTER_DUMP {
482 int addr;
483 char *name;
486 struct REGISTER_DUMP d1[] = {
487 { 0x007e, "autodetect" },
488 { 0x0023, "C_AD_BITS " },
489 { 0x0038, "ADD_BITS " },
490 { 0x003e, "CIB_BITS " },
491 { 0x0057, "ERROR_RATE" },
495 * A kernel thread for msp3400 control -- we don't want to block the
496 * in the ioctl while doing the sound carrier & stereo detect
499 static void msp3400c_stereo_wake(unsigned long data)
501 struct msp3400c *msp = (struct msp3400c*)data; /* XXX alpha ??? */
503 wake_up_interruptible(&msp->wq);
506 static int msp3400c_thread(void *data)
508 struct msp3400c *msp = data;
510 struct CARRIER_DETECT *cd;
511 int count, max1,max2,val1,val2, val,this;
512 int newstereo;
513 LOCK_FLAGS;
515 #ifdef __SMP__
516 lock_kernel();
517 #endif
519 exit_mm(current);
520 current->session = 1;
521 current->pgrp = 1;
522 sigfillset(&current->blocked);
523 current->fs->umask = 0;
524 strcpy(current->comm,"msp3400");
526 msp->wq = NULL;
527 msp->thread = current;
529 #ifdef __SMP__
530 unlock_kernel();
531 #endif
533 dprintk("msp3400: thread: start\n");
534 if(msp->notify != NULL)
535 up(msp->notify);
537 for (;;) {
538 if (msp->rmmod)
539 goto done;
540 if (debug > 1)
541 printk("msp3400: thread: sleep\n");
542 interruptible_sleep_on(&msp->wq);
543 if (debug > 1)
544 printk("msp3400: thread: wakeup\n");
545 if (msp->rmmod || signal_pending(current))
546 goto done;
548 if (VIDEO_MODE_RADIO == msp->norm)
549 continue; /* nothing to do */
551 msp->active = 1;
553 if (msp->watch_stereo) {
554 /* do that stereo/multilang handling */
555 LOCK_I2C_BUS(msp->bus);
556 newstereo = msp->stereo;
557 switch (msp->mode) {
558 case MSP_MODE_FM_TERRA:
559 val = msp3400c_read(msp->bus, I2C_MSP3400C_DFP, 0x18);
560 dprintk("msp3400: stereo detect register: %d\n",val);
562 if (val > 4096) {
563 newstereo = VIDEO_SOUND_STEREO;
564 } else if (val < -4096) {
565 newstereo = VIDEO_SOUND_LANG1;
566 } else {
567 newstereo = VIDEO_SOUND_MONO;
569 break;
570 case MSP_MODE_FM_NICAM1:
571 case MSP_MODE_FM_NICAM2:
572 val = msp3400c_read(msp->bus, I2C_MSP3400C_DEM, 0x23);
573 switch ((val & 0x1e) >> 1) {
574 case 0:
575 case 8:
576 newstereo = VIDEO_SOUND_STEREO;
577 break;
578 default:
579 newstereo = VIDEO_SOUND_MONO;
580 break;
582 break;
584 if (msp->stereo != newstereo) {
585 dprintk("msp3400: watch: stereo %d ==> %d\n",
586 msp->stereo,newstereo);
587 msp3400c_setstereo(msp,newstereo);
589 UNLOCK_I2C_BUS(msp->bus);
590 if (msp->watch_stereo) {
591 del_timer(&msp->wake_stereo);
592 msp->wake_stereo.expires = jiffies + 5*HZ;
593 add_timer(&msp->wake_stereo);
596 msp->active = 0;
597 continue;
600 restart:
601 LOCK_I2C_BUS(msp->bus);
602 msp3400c_setvolume(msp->bus, 0, 0);
603 msp3400c_setmode(msp, MSP_MODE_AM_DETECT);
604 val1 = val2 = 0;
605 max1 = max2 = -1;
606 del_timer(&msp->wake_stereo);
607 msp->watch_stereo = 0;
609 /* carrier detect pass #1 -- main carrier */
610 cd = carrier_detect_main; count = CARRIER_COUNT(carrier_detect_main);
611 for (this = 0; this < count; this++) {
612 msp3400c_setcarrier(msp->bus, cd[this].cdo,cd[this].cdo);
613 UNLOCK_I2C_BUS(msp->bus);
615 current->state = TASK_INTERRUPTIBLE;
616 schedule_timeout(HZ/25);
617 if (signal_pending(current))
618 goto done;
619 if (msp->restart) {
620 msp->restart = 0;
621 goto restart;
624 LOCK_I2C_BUS(msp->bus);
625 val = msp3400c_read(msp->bus, I2C_MSP3400C_DFP, 0x1b);
626 if (val1 < val)
627 val1 = val, max1 = this;
628 dprintk("msp3400: carrier1 val: %5d / %s\n", val,cd[this].name);
631 /* carrier detect pass #2 -- second (stereo) carrier */
632 switch (max1) {
633 case 1: /* 5.5 */
634 cd = carrier_detect_55; count = CARRIER_COUNT(carrier_detect_55);
635 break;
636 case 3: /* 6.5 */
637 cd = carrier_detect_65; count = CARRIER_COUNT(carrier_detect_65);
638 break;
639 case 0: /* 4.5 */
640 case 2: /* 6.0 */
641 default:
642 cd = NULL; count = 0;
643 break;
645 for (this = 0; this < count; this++) {
646 msp3400c_setcarrier(msp->bus, cd[this].cdo,cd[this].cdo);
647 UNLOCK_I2C_BUS(msp->bus);
649 current->state = TASK_INTERRUPTIBLE;
650 schedule_timeout(HZ/25);
651 if (signal_pending(current))
652 goto done;
653 if (msp->restart) {
654 msp->restart = 0;
655 goto restart;
658 LOCK_I2C_BUS(msp->bus);
659 val = msp3400c_read(msp->bus, I2C_MSP3400C_DFP, 0x1b);
660 if (val2 < val)
661 val2 = val, max2 = this;
662 dprintk("msp3400: carrier2 val: %5d / %s\n", val,cd[this].name);
665 /* programm the msp3400 according to the results */
666 msp->main = carrier_detect_main[max1].cdo;
667 switch (max1) {
668 case 1: /* 5.5 */
669 if (max2 == 0) {
670 /* B/G FM-stereo */
671 msp->second = carrier_detect_55[max2].cdo;
672 msp3400c_setmode(msp, MSP_MODE_FM_TERRA);
673 msp3400c_setstereo(msp, VIDEO_SOUND_MONO);
674 msp->watch_stereo = 1;
675 } else if (max2 == 1 && msp->nicam) {
676 /* B/G NICAM */
677 msp->second = carrier_detect_55[max2].cdo;
678 msp3400c_setmode(msp, MSP_MODE_FM_NICAM1);
679 msp3400c_setcarrier(msp->bus, msp->second, msp->main);
680 msp->watch_stereo = 1;
681 } else {
682 goto no_second;
684 break;
685 case 2: /* 6.0 */
686 /* PAL I NICAM */
687 msp->second = MSP_CARRIER(6.552);
688 msp3400c_setmode(msp, MSP_MODE_FM_NICAM2);
689 msp3400c_setcarrier(msp->bus, msp->second, msp->main);
690 msp->watch_stereo = 1;
691 break;
692 case 3: /* 6.5 */
693 if (max2 == 1 || max2 == 2) {
694 /* D/K FM-stereo */
695 msp->second = carrier_detect_65[max2].cdo;
696 msp3400c_setmode(msp, MSP_MODE_FM_TERRA);
697 msp3400c_setstereo(msp, VIDEO_SOUND_MONO);
698 msp->watch_stereo = 1;
699 } else if (max2 == 0 && msp->nicam) {
700 /* D/K NICAM */
701 msp->second = carrier_detect_65[max2].cdo;
702 msp3400c_setmode(msp, MSP_MODE_FM_NICAM1);
703 msp3400c_setcarrier(msp->bus, msp->second, msp->main);
704 msp->watch_stereo = 1;
705 } else {
706 goto no_second;
708 break;
709 case 0: /* 4.5 */
710 default:
711 no_second:
712 msp->second = carrier_detect_main[max1].cdo;
713 msp3400c_setmode(msp, MSP_MODE_FM_TERRA);
714 msp3400c_setcarrier(msp->bus, msp->second, msp->main);
715 break;
718 /* unmute */
719 msp3400c_setvolume(msp->bus, msp->left, msp->right);
720 UNLOCK_I2C_BUS(msp->bus);
722 if (msp->watch_stereo) {
723 del_timer(&msp->wake_stereo);
724 msp->wake_stereo.expires = jiffies + 2*HZ;
725 add_timer(&msp->wake_stereo);
728 if (debug)
729 msp3400c_print_mode(msp);
731 msp->active = 0;
734 done:
735 dprintk("msp3400: thread: exit\n");
736 msp->active = 0;
737 msp->thread = NULL;
739 if(msp->notify != NULL)
740 up(msp->notify);
741 return 0;
745 #if 0 /* not finished yet */
747 static int msp3410d_thread(void *data)
749 unsigned long flags;
750 struct msp3400c *msp = data;
751 struct semaphore sem = MUTEX_LOCKED;
752 int i, val;
754 /* lock_kernel(); */
756 exit_mm(current);
757 current->session = 1;
758 current->pgrp = 1;
759 sigfillset(&current->blocked);
760 current->fs->umask = 0;
761 strcpy(current->comm,"msp3410 (nicam)");
763 msp->wait = &sem;
764 msp->thread = current;
766 /* unlock_kernel(); */
768 dprintk("msp3410: thread: start\n");
769 if(msp->notify != NULL)
770 up(msp->notify);
772 for (;;) {
773 if (msp->rmmod)
774 goto done;
775 dprintk("msp3410: thread: sleep\n");
776 down_interruptible(&sem);
777 sem.owner = 0;
778 dprintk("msp3410: thread: wakeup\n");
779 if (msp->rmmod)
780 goto done;
782 if (VIDEO_MODE_RADIO == msp->norm)
783 continue; /* nothing to do */
785 msp->active = 1;
787 restart:
788 LOCK_I2C_BUS(msp->bus);
789 /* mute */
790 msp3400c_setvolume(msp->bus, 0);
791 /* quick & dirty hack:
792 get the audio proccessor into some useful state */
793 msp3400c_setmode(msp, MSP_MODE_FM_NICAM1);
794 /* kick autodetect */
795 msp3400c_write(msp->bus, I2C_MSP3400C_DFP, 0x20, 0x01);
796 msp3400c_write(msp->bus, I2C_MSP3400C_DFP, 0x21, 0x01);
797 UNLOCK_I2C_BUS(msp->bus);
799 /* wait 1 sec */
800 current->state = TASK_INTERRUPTIBLE;
801 current->timeout = jiffies + HZ;
802 schedule();
803 if (signal_pending(current))
804 goto done;
805 if (msp->restart) {
806 msp->restart = 0;
807 goto restart;
810 LOCK_I2C_BUS(msp->bus);
811 /* debug register dump */
812 for (i = 0; i < sizeof(d1)/sizeof(struct REGISTER_DUMP); i++) {
813 val = msp3400c_read(msp->bus,I2C_MSP3400C_DEM,d1[i].addr);
814 printk(KERN_DEBUG "msp3400: %s = 0x%x\n",d1[i].name,val);
816 /* unmute */
817 msp3400c_setvolume(msp->bus, msp->volume);
818 UNLOCK_I2C_BUS(msp->bus);
820 msp->active = 0;
823 done:
824 dprintk("msp3410: thread: exit\n");
825 msp->wait = NULL;
826 msp->active = 0;
827 msp->thread = NULL;
829 if(msp->notify != NULL)
830 up(msp->notify);
831 return 0;
833 #endif
835 /* ----------------------------------------------------------------------- */
836 /* mixer stuff -- with the modular sound driver in 2.1.x we can easily */
837 /* register the msp3400 as mixer device */
839 #ifdef REGISTER_MIXER
841 #include <linux/sound.h>
842 #include <linux/soundcard.h>
843 #include <asm/uaccess.h>
845 static struct msp3400c *mspmix = NULL; /* ugly hack, should do something more sensible */
846 static int mixer_num;
847 static int mixer_modcnt = 0;
848 static struct semaphore mixer_sem = MUTEX;
850 static int mix_to_v4l(int i)
852 int r;
854 r = ((i & 0xff) * 65536 + 50) / 100;
855 if (r > 65535) r = 65535;
856 if (r < 0) r = 0;
857 return r;
860 static int v4l_to_mix(int i)
862 int r;
864 r = (i * 100 + 32768) / 65536;
865 if (r > 100) r = 100;
866 if (r < 0) r = 0;
867 return r | (r << 8);
870 static int v4l_to_mix2(int l, int r)
872 r = (r * 100 + 32768) / 65536;
873 if (r > 100) r = 100;
874 if (r < 0) r = 0;
875 l = (l * 100 + 32768) / 65536;
876 if (l > 100) l = 100;
877 if (l < 0) l = 0;
878 return (r << 8) | l;
881 static int
882 msp3400c_mixer_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
884 int ret,val = 0;
885 LOCK_FLAGS;
887 if (cmd == SOUND_MIXER_INFO) {
888 mixer_info info;
889 strncpy(info.id, "MSP3400", sizeof(info.id));
890 strncpy(info.name, "MSP 3400", sizeof(info.name));
891 info.modify_counter = mixer_modcnt;
892 if (copy_to_user((void *)arg, &info, sizeof(info)))
893 return -EFAULT;
894 return 0;
896 if (cmd == SOUND_OLD_MIXER_INFO) {
897 _old_mixer_info info;
898 strncpy(info.id, "MSP3400", sizeof(info.id));
899 strncpy(info.name, "MSP 3400", sizeof(info.name));
900 if (copy_to_user((void *)arg, &info, sizeof(info)))
901 return -EFAULT;
902 return 0;
904 if (cmd == OSS_GETVERSION)
905 return put_user(SOUND_VERSION, (int *)arg);
907 if (_SIOC_DIR(cmd) & _SIOC_WRITE)
908 if (get_user(val, (int *)arg))
909 return -EFAULT;
911 down(&mixer_sem);
912 if (!mspmix) {
913 up(&mixer_sem);
914 return -ENODEV;
917 switch (cmd) {
918 case MIXER_READ(SOUND_MIXER_RECMASK):
919 case MIXER_READ(SOUND_MIXER_CAPS):
920 case MIXER_READ(SOUND_MIXER_RECSRC):
921 case MIXER_WRITE(SOUND_MIXER_RECSRC):
922 ret = 0;
923 break;
925 case MIXER_READ(SOUND_MIXER_STEREODEVS):
926 ret = SOUND_MASK_VOLUME;
927 break;
928 case MIXER_READ(SOUND_MIXER_DEVMASK):
929 ret = SOUND_MASK_VOLUME | SOUND_MASK_BASS | SOUND_MASK_TREBLE;
930 break;
932 case MIXER_WRITE(SOUND_MIXER_VOLUME):
933 mspmix->left = mix_to_v4l(val);
934 mspmix->right = mix_to_v4l(val >> 8);
935 LOCK_I2C_BUS(mspmix->bus);
936 msp3400c_setvolume(mspmix->bus,mspmix->left,mspmix->right);
937 UNLOCK_I2C_BUS(mspmix->bus);
938 mixer_modcnt++;
939 /* fall */
940 case MIXER_READ(SOUND_MIXER_VOLUME):
941 ret = v4l_to_mix2(mspmix->left, mspmix->right);
942 break;
944 case MIXER_WRITE(SOUND_MIXER_BASS):
945 mspmix->bass = mix_to_v4l(val);
946 LOCK_I2C_BUS(mspmix->bus);
947 msp3400c_setbass(mspmix->bus,mspmix->bass);
948 UNLOCK_I2C_BUS(mspmix->bus);
949 mixer_modcnt++;
950 /* fall */
951 case MIXER_READ(SOUND_MIXER_BASS):
952 ret = v4l_to_mix(mspmix->bass);
953 break;
955 case MIXER_WRITE(SOUND_MIXER_TREBLE):
956 mspmix->treble = mix_to_v4l(val);
957 LOCK_I2C_BUS(mspmix->bus);
958 msp3400c_settreble(mspmix->bus,mspmix->treble);
959 UNLOCK_I2C_BUS(mspmix->bus);
960 mixer_modcnt++;
961 /* fall */
962 case MIXER_READ(SOUND_MIXER_TREBLE):
963 ret = v4l_to_mix(mspmix->treble);
964 break;
966 default:
967 up(&mixer_sem);
968 return -EINVAL;
970 up(&mixer_sem);
971 if (put_user(ret, (int *)arg))
972 return -EFAULT;
973 return 0;
976 static int
977 msp3400c_mixer_open(struct inode *inode, struct file *file)
979 MOD_INC_USE_COUNT;
980 return 0;
983 static int
984 msp3400c_mixer_release(struct inode *inode, struct file *file)
986 MOD_DEC_USE_COUNT;
987 return 0;
990 static loff_t
991 msp3400c_mixer_llseek(struct file *file, loff_t offset, int origin)
993 return -ESPIPE;
996 static /*const*/ struct file_operations msp3400c_mixer_fops = {
997 &msp3400c_mixer_llseek,
998 NULL, /* read */
999 NULL, /* write */
1000 NULL, /* readdir */
1001 NULL, /* poll */
1002 &msp3400c_mixer_ioctl,
1003 NULL, /* mmap */
1004 &msp3400c_mixer_open,
1005 NULL,
1006 &msp3400c_mixer_release,
1007 NULL, /* fsync */
1008 NULL, /* fasync */
1009 NULL, /* check_media_change */
1010 NULL, /* revalidate */
1011 NULL, /* lock */
1014 #endif
1016 /* ----------------------------------------------------------------------- */
1018 static int msp3400c_attach(struct i2c_device *device)
1020 struct semaphore sem = MUTEX_LOCKED;
1021 struct msp3400c *msp;
1022 int rev1,rev2;
1023 LOCK_FLAGS;
1025 device->data = msp = kmalloc(sizeof(struct msp3400c),GFP_KERNEL);
1026 if (NULL == msp)
1027 return -ENOMEM;
1028 memset(msp,0,sizeof(struct msp3400c));
1029 msp->bus = device->bus;
1030 msp->left = 65535;
1031 msp->right = 65535;
1032 msp->bass = 32768;
1033 msp->treble = 32768;
1035 LOCK_I2C_BUS(msp->bus);
1036 if (-1 == msp3400c_reset(msp->bus)) {
1037 UNLOCK_I2C_BUS(msp->bus);
1038 kfree(msp);
1039 dprintk("msp3400: no chip found\n");
1040 return -1;
1043 rev1 = msp3400c_read(msp->bus, I2C_MSP3400C_DFP, 0x1e);
1044 rev2 = msp3400c_read(msp->bus, I2C_MSP3400C_DFP, 0x1f);
1045 if (0 == rev1 && 0 == rev2) {
1046 UNLOCK_I2C_BUS(msp->bus);
1047 kfree(msp);
1048 printk("msp3400: error while reading chip version\n");
1049 return -1;
1052 msp3400c_setmode(msp, MSP_MODE_FM_TERRA);
1053 msp3400c_setvolume(msp->bus, msp->left, msp->right);
1054 msp3400c_setbass(msp->bus, msp->bass);
1055 msp3400c_settreble(msp->bus, msp->treble);
1057 #if 0
1058 /* this will turn on a 1kHz beep - might be useful for debugging... */
1059 msp3400c_write(msp->bus,I2C_MSP3400C_DFP, 0x0014, 0x1040);
1060 #endif
1061 UNLOCK_I2C_BUS(msp->bus);
1063 sprintf(device->name,"MSP34%02d%c-%c%d",
1064 (rev2>>8)&0xff, (rev1&0xff)+'@', ((rev1>>8)&0xff)+'@', rev2&0x1f);
1065 msp->nicam = (((rev2>>8)&0xff) != 00) ? 1 : 0;
1067 /* timer for stereo checking */
1068 msp->wake_stereo.function = msp3400c_stereo_wake;
1069 msp->wake_stereo.data = (unsigned long)msp;
1071 /* startup control thread */
1072 MOD_INC_USE_COUNT;
1073 msp->wq = NULL;
1074 msp->notify = &sem;
1075 kernel_thread(msp3400c_thread, (void *)msp, 0);
1076 down(&sem);
1077 msp->notify = NULL;
1078 wake_up_interruptible(&msp->wq);
1080 printk(KERN_INFO "msp3400: init: chip=%s",device->name);
1081 if (msp->nicam)
1082 printk(", has NICAM support");
1083 #ifdef REGISTER_MIXER
1084 down(&mixer_sem);
1085 mspmix = msp;
1086 up(&mixer_sem);
1087 #endif
1088 printk("\n");
1089 return 0;
1092 static int msp3400c_detach(struct i2c_device *device)
1094 struct semaphore sem = MUTEX_LOCKED;
1095 struct msp3400c *msp = (struct msp3400c*)device->data;
1096 LOCK_FLAGS;
1098 #ifdef REGISTER_MIXER
1099 down(&mixer_sem);
1100 mspmix = NULL;
1101 up(&mixer_sem);
1102 #endif
1104 /* shutdown control thread */
1105 del_timer(&msp->wake_stereo);
1106 if (msp->thread)
1108 msp->notify = &sem;
1109 msp->rmmod = 1;
1110 wake_up_interruptible(&msp->wq);
1111 down(&sem);
1112 msp->notify = NULL;
1115 LOCK_I2C_BUS(msp->bus);
1116 msp3400c_reset(msp->bus);
1117 UNLOCK_I2C_BUS(msp->bus);
1119 kfree(msp);
1120 MOD_DEC_USE_COUNT;
1121 return 0;
1124 static int msp3400c_command(struct i2c_device *device,
1125 unsigned int cmd, void *arg)
1127 struct msp3400c *msp = (struct msp3400c*)device->data;
1128 int *iarg = (int*)arg;
1129 __u16 *sarg = arg;
1130 LOCK_FLAGS;
1132 switch (cmd) {
1133 case MSP_SET_RADIO:
1134 msp->norm = VIDEO_MODE_RADIO;
1135 msp->watch_stereo=0;
1136 del_timer(&msp->wake_stereo);
1137 LOCK_I2C_BUS(msp->bus);
1138 msp3400c_setmode(msp,MSP_MODE_FM_RADIO);
1139 msp3400c_setcarrier(msp->bus, MSP_CARRIER(10.7),MSP_CARRIER(10.7));
1140 msp3400c_setvolume(msp->bus,msp->left, msp->right);
1141 UNLOCK_I2C_BUS(msp->bus);
1142 break;
1143 case MSP_SET_TVNORM:
1144 msp->norm = *iarg;
1145 break;
1146 case MSP_SWITCH_MUTE:
1147 /* channels switching step one -- mute */
1148 msp->watch_stereo=0;
1149 del_timer(&msp->wake_stereo);
1150 LOCK_I2C_BUS(msp->bus);
1151 msp3400c_setvolume(msp->bus,0,0);
1152 UNLOCK_I2C_BUS(msp->bus);
1153 break;
1154 case MSP_NEWCHANNEL:
1155 /* channels switching step two -- trigger sound carrier scan */
1156 msp->watch_stereo=0;
1157 del_timer(&msp->wake_stereo);
1158 if (msp->active)
1159 msp->restart = 1;
1160 wake_up_interruptible(&msp->wq);
1161 break;
1163 case MSP_GET_VOLUME:
1164 *sarg = (msp->left > msp->right) ? msp->left : msp->right;
1165 break;
1166 case MSP_SET_VOLUME:
1167 msp->left = msp->right = *sarg;
1168 LOCK_I2C_BUS(msp->bus);
1169 msp3400c_setvolume(msp->bus,msp->left, msp->right);
1170 UNLOCK_I2C_BUS(msp->bus);
1171 break;
1173 case MSP_GET_BASS:
1174 *sarg = msp->bass;
1175 break;
1176 case MSP_SET_BASS:
1177 msp->bass = *sarg;
1178 LOCK_I2C_BUS(msp->bus);
1179 msp3400c_setbass(msp->bus,msp->bass);
1180 UNLOCK_I2C_BUS(msp->bus);
1181 break;
1183 case MSP_GET_TREBLE:
1184 *sarg = msp->treble;
1185 break;
1186 case MSP_SET_TREBLE:
1187 msp->treble = *sarg;
1188 LOCK_I2C_BUS(msp->bus);
1189 msp3400c_settreble(msp->bus,msp->treble);
1190 UNLOCK_I2C_BUS(msp->bus);
1191 break;
1193 case MSP_GET_STEREO:
1194 *sarg = msp->stereo;
1195 break;
1196 case MSP_SET_STEREO:
1197 if (*sarg) {
1198 msp->watch_stereo=0;
1199 del_timer(&msp->wake_stereo);
1200 LOCK_I2C_BUS(msp->bus);
1201 msp3400c_setstereo(msp,*sarg);
1202 UNLOCK_I2C_BUS(msp->bus);
1204 break;
1206 case MSP_GET_DC:
1207 LOCK_I2C_BUS(msp->bus);
1208 *sarg = ((int)msp3400c_read(msp->bus, I2C_MSP3400C_DFP, 0x1b) +
1209 (int)msp3400c_read(msp->bus, I2C_MSP3400C_DFP, 0x1c));
1210 UNLOCK_I2C_BUS(msp->bus);
1211 break;
1213 default:
1214 return -EINVAL;
1216 return 0;
1219 /* ----------------------------------------------------------------------- */
1221 struct i2c_driver i2c_driver_msp = {
1222 "msp3400", /* name */
1223 I2C_DRIVERID_MSP3400, /* ID */
1224 I2C_MSP3400C, I2C_MSP3400C, /* addr range */
1226 msp3400c_attach,
1227 msp3400c_detach,
1228 msp3400c_command
1231 #ifdef MODULE
1232 int init_module(void)
1233 #else
1234 int msp3400c_init(void)
1235 #endif
1237 i2c_register_driver(&i2c_driver_msp);
1238 #ifdef REGISTER_MIXER
1239 if ((mixer_num = register_sound_mixer(&msp3400c_mixer_fops, -1)) < 0)
1240 printk(KERN_ERR "msp3400c: cannot allocate mixer device\n");
1241 #endif
1242 return 0;
1245 #ifdef MODULE
1246 void cleanup_module(void)
1248 i2c_unregister_driver(&i2c_driver_msp);
1249 #ifdef REGISTER_MIXER
1250 if (mixer_num >= 0)
1251 unregister_sound_mixer(mixer_num);
1252 #endif
1254 #endif
1257 * Overrides for Emacs so that we follow Linus's tabbing style.
1258 * ---------------------------------------------------------------------------
1259 * Local variables:
1260 * c-basic-offset: 8
1261 * End: