📄 msp3400.c
字号:
case MSP_MODE_FM_NICAM1: case MSP_MODE_FM_NICAM2: dprintk("msp3400: NICAM setstereo: %d\n",mode); msp->stereo = mode; msp3400c_setcarrier(msp->bus,msp->second,msp->main); nicam=0x0100; break; default: /* can't do stereo - abort here */ return; } /* switch audio */ switch (mode) { case VIDEO_SOUND_STEREO: msp3400c_write(msp->bus,I2C_MSP3400C_DFP, 0x0008,0x0020|nicam); msp3400c_write(msp->bus,I2C_MSP3400C_DFP, 0x0009,0x0020|nicam); msp3400c_write(msp->bus,I2C_MSP3400C_DFP, 0x000a,0x0020|nicam);#if 0 msp3400c_write(msp->bus,I2C_MSP3400C_DFP, 0x0005,0x4000);#endif break; case VIDEO_SOUND_MONO: case VIDEO_SOUND_LANG1: msp3400c_write(msp->bus,I2C_MSP3400C_DFP, 0x0008,0x0000|nicam); msp3400c_write(msp->bus,I2C_MSP3400C_DFP, 0x0009,0x0000|nicam); msp3400c_write(msp->bus,I2C_MSP3400C_DFP, 0x000a,0x0000|nicam); break; case VIDEO_SOUND_LANG2: msp3400c_write(msp->bus,I2C_MSP3400C_DFP, 0x0008,0x0010|nicam); msp3400c_write(msp->bus,I2C_MSP3400C_DFP, 0x0009,0x0010|nicam); msp3400c_write(msp->bus,I2C_MSP3400C_DFP, 0x000a,0x0010|nicam); break; }}static voidmsp3400c_print_mode(struct msp3400c *msp){ if (msp->main == msp->second) { printk("msp3400: mono sound carrier: %d.%03d MHz\n", msp->main/910000,(msp->main/910)%1000); } else { printk("msp3400: main sound carrier: %d.%03d MHz\n", msp->main/910000,(msp->main/910)%1000); } if (msp->mode == MSP_MODE_FM_NICAM1 || msp->mode == MSP_MODE_FM_NICAM2) printk("msp3400: NICAM carrier : %d.%03d MHz\n", msp->second/910000,(msp->second/910)%1000); if (msp->mode == MSP_MODE_FM_TERRA && msp->main != msp->second) { printk("msp3400: FM-stereo carrier : %d.%03d MHz\n", msp->second/910000,(msp->second/910)%1000); }}/* ----------------------------------------------------------------------- */struct REGISTER_DUMP { int addr; char *name;};struct REGISTER_DUMP d1[] = { { 0x007e, "autodetect" }, { 0x0023, "C_AD_BITS " }, { 0x0038, "ADD_BITS " }, { 0x003e, "CIB_BITS " }, { 0x0057, "ERROR_RATE" },};/* * A kernel thread for msp3400 control -- we don't want to block the * in the ioctl while doing the sound carrier & stereo detect */static void msp3400c_stereo_wake(unsigned long data){ struct msp3400c *msp = (struct msp3400c*)data; /* XXX alpha ??? */ wake_up_interruptible(&msp->wq);}static int msp3400c_thread(void *data){ struct msp3400c *msp = data; struct CARRIER_DETECT *cd; int count, max1,max2,val1,val2, val,this; int newstereo; LOCK_FLAGS; #ifdef __SMP__ lock_kernel();#endif exit_mm(current); current->session = 1; current->pgrp = 1; sigfillset(¤t->blocked); current->fs->umask = 0; strcpy(current->comm,"msp3400"); msp->wq = NULL; msp->thread = current;#ifdef __SMP__ unlock_kernel();#endif dprintk("msp3400: thread: start\n"); if(msp->notify != NULL) up(msp->notify); for (;;) { if (msp->rmmod) goto done; if (debug > 1) printk("msp3400: thread: sleep\n"); interruptible_sleep_on(&msp->wq); if (debug > 1) printk("msp3400: thread: wakeup\n"); if (msp->rmmod || signal_pending(current)) goto done; if (VIDEO_MODE_RADIO == msp->norm) continue; /* nothing to do */ msp->active = 1; if (msp->watch_stereo) { /* do that stereo/multilang handling */ LOCK_I2C_BUS(msp->bus); newstereo = msp->stereo; switch (msp->mode) { case MSP_MODE_FM_TERRA: val = msp3400c_read(msp->bus, I2C_MSP3400C_DFP, 0x18); dprintk("msp3400: stereo detect register: %d\n",val); if (val > 4096) { newstereo = VIDEO_SOUND_STEREO; } else if (val < -4096) { newstereo = VIDEO_SOUND_LANG1; } else { newstereo = VIDEO_SOUND_MONO; } break; case MSP_MODE_FM_NICAM1: case MSP_MODE_FM_NICAM2: val = msp3400c_read(msp->bus, I2C_MSP3400C_DEM, 0x23); switch ((val & 0x1e) >> 1) { case 0: case 8: newstereo = VIDEO_SOUND_STEREO; break; default: newstereo = VIDEO_SOUND_MONO; break; } break; } if (msp->stereo != newstereo) { dprintk("msp3400: watch: stereo %d ==> %d\n", msp->stereo,newstereo); msp3400c_setstereo(msp,newstereo); } UNLOCK_I2C_BUS(msp->bus); if (msp->watch_stereo) { del_timer(&msp->wake_stereo); msp->wake_stereo.expires = jiffies + 5*HZ; add_timer(&msp->wake_stereo); } msp->active = 0; continue; } restart: LOCK_I2C_BUS(msp->bus); msp3400c_setvolume(msp->bus, 0, 0); msp3400c_setmode(msp, MSP_MODE_AM_DETECT); val1 = val2 = 0; max1 = max2 = -1; del_timer(&msp->wake_stereo); msp->watch_stereo = 0; /* carrier detect pass #1 -- main carrier */ cd = carrier_detect_main; count = CARRIER_COUNT(carrier_detect_main); for (this = 0; this < count; this++) { msp3400c_setcarrier(msp->bus, cd[this].cdo,cd[this].cdo); UNLOCK_I2C_BUS(msp->bus); current->state = TASK_INTERRUPTIBLE; schedule_timeout(HZ/25); if (signal_pending(current)) goto done; if (msp->restart) { msp->restart = 0; goto restart; } LOCK_I2C_BUS(msp->bus); val = msp3400c_read(msp->bus, I2C_MSP3400C_DFP, 0x1b); if (val1 < val) val1 = val, max1 = this; dprintk("msp3400: carrier1 val: %5d / %s\n", val,cd[this].name); } /* carrier detect pass #2 -- second (stereo) carrier */ switch (max1) { case 1: /* 5.5 */ cd = carrier_detect_55; count = CARRIER_COUNT(carrier_detect_55); break; case 3: /* 6.5 */ cd = carrier_detect_65; count = CARRIER_COUNT(carrier_detect_65); break; case 0: /* 4.5 */ case 2: /* 6.0 */ default: cd = NULL; count = 0; break; } for (this = 0; this < count; this++) { msp3400c_setcarrier(msp->bus, cd[this].cdo,cd[this].cdo); UNLOCK_I2C_BUS(msp->bus); current->state = TASK_INTERRUPTIBLE; schedule_timeout(HZ/25); if (signal_pending(current)) goto done; if (msp->restart) { msp->restart = 0; goto restart; } LOCK_I2C_BUS(msp->bus); val = msp3400c_read(msp->bus, I2C_MSP3400C_DFP, 0x1b); if (val2 < val) val2 = val, max2 = this; dprintk("msp3400: carrier2 val: %5d / %s\n", val,cd[this].name); } /* programm the msp3400 according to the results */ msp->main = carrier_detect_main[max1].cdo; switch (max1) { case 1: /* 5.5 */ if (max2 == 0) { /* B/G FM-stereo */ msp->second = carrier_detect_55[max2].cdo; msp3400c_setmode(msp, MSP_MODE_FM_TERRA); msp3400c_setstereo(msp, VIDEO_SOUND_MONO); msp->watch_stereo = 1; } else if (max2 == 1 && msp->nicam) { /* B/G NICAM */ msp->second = carrier_detect_55[max2].cdo; msp3400c_setmode(msp, MSP_MODE_FM_NICAM1); msp3400c_setcarrier(msp->bus, msp->second, msp->main); msp->watch_stereo = 1; } else { goto no_second; } break; case 2: /* 6.0 */ /* PAL I NICAM */ msp->second = MSP_CARRIER(6.552); msp3400c_setmode(msp, MSP_MODE_FM_NICAM2); msp3400c_setcarrier(msp->bus, msp->second, msp->main); msp->watch_stereo = 1; break; case 3: /* 6.5 */ if (max2 == 1 || max2 == 2) { /* D/K FM-stereo */ msp->second = carrier_detect_65[max2].cdo; msp3400c_setmode(msp, MSP_MODE_FM_TERRA); msp3400c_setstereo(msp, VIDEO_SOUND_MONO); msp->watch_stereo = 1; } else if (max2 == 0 && msp->nicam) { /* D/K NICAM */ msp->second = carrier_detect_65[max2].cdo; msp3400c_setmode(msp, MSP_MODE_FM_NICAM1); msp3400c_setcarrier(msp->bus, msp->second, msp->main); msp->watch_stereo = 1; } else { goto no_second; } break; case 0: /* 4.5 */ default: no_second: msp->second = carrier_detect_main[max1].cdo; msp3400c_setmode(msp, MSP_MODE_FM_TERRA); msp3400c_setcarrier(msp->bus, msp->second, msp->main); break; } /* unmute */ msp3400c_setvolume(msp->bus, msp->left, msp->right); UNLOCK_I2C_BUS(msp->bus); if (msp->watch_stereo) { del_timer(&msp->wake_stereo); msp->wake_stereo.expires = jiffies + 2*HZ; add_timer(&msp->wake_stereo); } if (debug) msp3400c_print_mode(msp); msp->active = 0; }done: dprintk("msp3400: thread: exit\n"); msp->active = 0; msp->thread = NULL; if(msp->notify != NULL) up(msp->notify); return 0;}#if 0 /* not finished yet */static int msp3410d_thread(void *data){ unsigned long flags; struct msp3400c *msp = data; struct semaphore sem = MUTEX_LOCKED; int i, val; /* lock_kernel(); */ exit_mm(current); current->session = 1; current->pgrp = 1; sigfillset(¤t->blocked); current->fs->umask = 0; strcpy(current->comm,"msp3410 (nicam)"); msp->wait = &sem; msp->thread = current; /* unlock_kernel(); */ dprintk("msp3410: thread: start\n"); if(msp->notify != NULL) up(msp->notify); for (;;) { if (msp->rmmod) goto done; dprintk("msp3410: thread: sleep\n"); down_interruptible(&sem); dprintk("msp3410: thread: wakeup\n"); if (msp->rmmod) goto done; if (VIDEO_MODE_RADIO == msp->norm) continue; /* nothing to do */ msp->active = 1; restart: LOCK_I2C_BUS(msp->bus); /* mute */ msp3400c_setvolume(msp->bus, 0); /* quick & dirty hack: get the audio proccessor into some useful state */ msp3400c_setmode(msp, MSP_MODE_FM_NICAM1); /* kick autodetect */ msp3400c_write(msp->bus, I2C_MSP3400C_DFP, 0x20, 0x01); msp3400c_write(msp->bus, I2C_MSP3400C_DFP, 0x21, 0x01); UNLOCK_I2C_BUS(msp->bus); /* wait 1 sec */ current->state = TASK_INTERRUPTIBLE; current->timeout = jiffies + HZ; schedule(); if (signal_pending(current)) goto done; if (msp->restart) { msp->restart = 0; goto restart; } LOCK_I2C_BUS(msp->bus); /* debug register dump */ for (i = 0; i < sizeof(d1)/sizeof(struct REGISTER_DUMP); i++) { val = msp3400c_read(msp->bus,I2C_MSP3400C_DEM,d1[i].addr); printk(KERN_DEBUG "msp3400: %s = 0x%x\n",d1[i].name,val); } /* unmute */ msp3400c_setvolume(msp->bus, msp->volume); UNLOCK_I2C_BUS(msp->bus); msp->active = 0; }done: dprintk("msp3410: thread: exit\n"); msp->wait = NULL; msp->active = 0; msp->thread = NULL; if(msp->notify != NULL) up(msp->notify); return 0;}#endif/* ----------------------------------------------------------------------- *//* mixer stuff -- with the modular sound driver in 2.1.x we can easily *//* register the msp3400 as mixer device */#ifdef REGISTER_MIXER#include <linux/sound.h>#include <linux/soundcard.h>#include <asm/uaccess.h>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -