⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 msp3400.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
		if (msp->mode == MSP_MODE_AM_NICAM) {			dprintk("msp3400: switching to AM mono\n");			/* AM mono decoding is handled by tuner, not MSP chip */			/* SCART switching control register */			msp3400c_set_scart(client,SCART_MONO,0);			src = 0x0200;			break;		}	case VIDEO_SOUND_LANG1:		src = 0x0000 | nicam;		break;	case VIDEO_SOUND_LANG2:		src = 0x0010 | nicam;		break;	}	if (dolby) {		msp3400c_write(client,I2C_MSP3400C_DFP, 0x0008,0x0520);		msp3400c_write(client,I2C_MSP3400C_DFP, 0x0009,0x0620);		msp3400c_write(client,I2C_MSP3400C_DFP, 0x000a,src);		msp3400c_write(client,I2C_MSP3400C_DFP, 0x000b,src);	} else {		msp3400c_write(client,I2C_MSP3400C_DFP, 0x0008,src);		msp3400c_write(client,I2C_MSP3400C_DFP, 0x0009,src);		msp3400c_write(client,I2C_MSP3400C_DFP, 0x000a,src);	}}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/FM carrier   : %d.%03d MHz\n",		       msp->second/910000,(msp->second/910)%1000);	if (msp->mode == MSP_MODE_AM_NICAM)		printk("msp3400: NICAM/AM 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" },};static intautodetect_stereo(struct i2c_client *client){	struct msp3400c *msp = client->data;	int val;	int newstereo = msp->stereo;	int newnicam  = msp->nicam_on;	int update = 0;	switch (msp->mode) {	case MSP_MODE_FM_TERRA:		val = msp3400c_read(client, I2C_MSP3400C_DFP, 0x18);		if (val > 32768)			val -= 65536;		dprintk("msp34xx: stereo detect register: %d\n",val);				if (val > 4096) {			newstereo = VIDEO_SOUND_STEREO | VIDEO_SOUND_MONO;		} else if (val < -4096) {			newstereo = VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2;		} else {			newstereo = VIDEO_SOUND_MONO;		}		newnicam = 0;		break;	case MSP_MODE_FM_NICAM1:	case MSP_MODE_FM_NICAM2:	case MSP_MODE_AM_NICAM:		val = msp3400c_read(client, I2C_MSP3400C_DEM, 0x23);		dprintk("msp34xx: nicam sync=%d, mode=%d\n",val & 1, (val & 0x1e) >> 1);		if (val & 1) {			/* nicam synced */			switch ((val & 0x1e) >> 1)  {			case 0:			case 8:				newstereo = VIDEO_SOUND_STEREO;				break;			case 1:			case 9:				newstereo = VIDEO_SOUND_MONO					| VIDEO_SOUND_LANG1;				break;			case 2:			case 10:				newstereo = VIDEO_SOUND_MONO					| VIDEO_SOUND_LANG1					| VIDEO_SOUND_LANG2;				break;			default:				newstereo = VIDEO_SOUND_MONO;				break;			}			newnicam=1;		} else {			newnicam = 0;			newstereo = VIDEO_SOUND_MONO;		}		break;	case MSP_MODE_BTSC:		val = msp3400c_read(client, I2C_MSP3400C_DEM, 0x200);		dprintk("msp3410: status=0x%x (pri=%s, sec=%s, %s%s%s)\n",			val,			(val & 0x0002) ? "no"     : "yes",			(val & 0x0004) ? "no"     : "yes",			(val & 0x0040) ? "stereo" : "mono",			(val & 0x0080) ? ", nicam 2nd mono" : "",			(val & 0x0100) ? ", bilingual/SAP"  : "");		newstereo = VIDEO_SOUND_MONO;		if (val & 0x0040) newstereo |= VIDEO_SOUND_STEREO;		if (val & 0x0100) newstereo |= VIDEO_SOUND_LANG1;		break;	}	if (newstereo != msp->stereo) {		update = 1;		dprintk("msp34xx: watch: stereo %d => %d\n",			msp->stereo,newstereo);		msp->stereo   = newstereo;	}	if (newnicam != msp->nicam_on) {		update = 1;		dprintk("msp34xx: watch: nicam %d => %d\n",			msp->nicam_on,newnicam);		msp->nicam_on = newnicam;	}	return update;}/* * 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);}/* stereo/multilang monitoring */static void watch_stereo(struct i2c_client *client){	struct msp3400c *msp = client->data;	if (autodetect_stereo(client)) {		if (msp->stereo & VIDEO_SOUND_STEREO)			msp3400c_setstereo(client,VIDEO_SOUND_STEREO);		else if (msp->stereo & VIDEO_SOUND_LANG1)			msp3400c_setstereo(client,VIDEO_SOUND_LANG1);		else			msp3400c_setstereo(client,VIDEO_SOUND_MONO);	}	if (once)		msp->watch_stereo = 0;	if (msp->watch_stereo)		mod_timer(&msp->wake_stereo, jiffies+5*HZ);}static int msp3400c_thread(void *data){	struct i2c_client *client = data;	struct msp3400c *msp = client->data;    	struct CARRIER_DETECT *cd;	int                   count, max1,max2,val1,val2, val,this;    #ifdef CONFIG_SMP	lock_kernel();#endif    	daemonize();	sigfillset(&current->blocked);	strcpy(current->comm,"msp3400");	msp->thread = current;#ifdef CONFIG_SMP	unlock_kernel();#endif	printk("msp3400: daemon started\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) {			watch_stereo(client);			msp->active = 0;			continue;		}		/* some time for the tuner to sync */		current->state   = TASK_INTERRUPTIBLE;		schedule_timeout(HZ/5);		if (signal_pending(current))			goto done;			restart:		msp->restart = 0;		msp3400c_setvolume(client, msp->muted, 0, 0);		msp3400c_setmode(client, MSP_MODE_AM_DETECT /* +1 */ );		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);		if (amsound && (msp->norm == VIDEO_MODE_SECAM)) {			/* autodetect doesn't work well with AM ... */			max1 = 3;			count = 0;			dprintk("msp3400: AM sound override\n");		}		for (this = 0; this < count; this++) {			msp3400c_setcarrier(client, cd[this].cdo,cd[this].cdo);			current->state   = TASK_INTERRUPTIBLE;			schedule_timeout(HZ/10);			if (signal_pending(current))				goto done;			if (msp->restart)				msp->restart = 0;			val = msp3400c_read(client, I2C_MSP3400C_DFP, 0x1b);			if (val > 32768)				val -= 65536;			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;		}				if (amsound && (msp->norm == VIDEO_MODE_SECAM)) {			/* autodetect doesn't work well with AM ... */			cd = NULL; count = 0; max2 = 0;		}		for (this = 0; this < count; this++) {			msp3400c_setcarrier(client, cd[this].cdo,cd[this].cdo);			current->state   = TASK_INTERRUPTIBLE;			schedule_timeout(HZ/10);			if (signal_pending(current))				goto done;			if (msp->restart)				goto restart;			val = msp3400c_read(client, I2C_MSP3400C_DFP, 0x1b);			if (val > 32768)				val -= 65536;			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(client, MSP_MODE_FM_TERRA);				msp->nicam_on = 0;				msp3400c_setstereo(client, 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(client, MSP_MODE_FM_NICAM1);				msp->nicam_on = 1;				msp3400c_setcarrier(client, 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(client, MSP_MODE_FM_NICAM2);			msp->nicam_on = 1;			msp3400c_setcarrier(client, 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(client, MSP_MODE_FM_TERRA);				msp->nicam_on = 0;				msp3400c_setstereo(client, VIDEO_SOUND_MONO);				msp->watch_stereo = 1;			} else if (max2 == 0 &&				   msp->norm == VIDEO_MODE_SECAM) {				/* L NICAM or AM-mono */				msp->second = carrier_detect_65[max2].cdo;				msp3400c_setmode(client, MSP_MODE_AM_NICAM);				msp->nicam_on = 0;				msp3400c_setstereo(client, VIDEO_SOUND_MONO);				msp3400c_setcarrier(client, msp->second, msp->main);				/* volume prescale for SCART (AM mono input) */				msp3400c_write(client,I2C_MSP3400C_DFP, 0x000d, 0x1900);				msp->watch_stereo = 1;			} else if (max2 == 0 && msp->nicam) {				/* D/K NICAM */				msp->second = carrier_detect_65[max2].cdo;				msp3400c_setmode(client, MSP_MODE_FM_NICAM1);				msp->nicam_on = 1;				msp3400c_setcarrier(client, 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(client, MSP_MODE_FM_TERRA);			msp->nicam_on = 0;			msp3400c_setcarrier(client, msp->second, msp->main);			msp->stereo = VIDEO_SOUND_MONO;			msp3400c_setstereo(client, VIDEO_SOUND_MONO);			break;		}		/* unmute */		msp3400c_setvolume(client, msp->muted, msp->left, msp->right);		if (msp->watch_stereo)			mod_timer(&msp->wake_stereo, jiffies+5*HZ);		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_and_exit(msp->notify, 0);	return 0;}/* ----------------------------------------------------------------------- *//* this one uses the automatic sound standard detection of newer           *//* msp34xx chip versions                                                   */static struct MODES {	int retval;	int main, second;	char *name;} modelist[] = {	{ 0x0000, 0, 0, "ERROR" },	{ 0x0001, 0, 0, "autodetect start" },	{ 0x0002, MSP_CARRIER(4.5), MSP_CARRIER(4.72), "4.5/4.72  M Dual FM-Stereo" },	{ 0x0003, MSP_CARRIER(5.5), MSP_CARRIER(5.7421875), "5.5/5.74  B/G Dual FM-Stereo" },	{ 0x0004, MSP_CARRIER(6.5), MSP_CARRIER(6.2578125), "6.5/6.25  D/K1 Dual FM-Stereo" },	{ 0x0005, MSP_CARRIER(6.5), MSP_CARRIER(6.7421875), "6.5/6.74  D/K2 Dual FM-Stereo" },	{ 0x0006, MSP_CARRIER(6.5), MSP_CARRIER(6.5), "6.5  D/K FM-Mono (HDEV3)" },	{ 0x0008, MSP_CARRIER(5.5), MSP_CARRIER(5.85), "5.5/5.85  B/G NICAM FM" },	{ 0x0009, MSP_CARRIER(6.5), MSP_CARRIER(5.85), "6.5/5.85  L NICAM AM" },	{ 0x000a, MSP_CARRIER(6.0), MSP_CARRIER(6.55), "6.0/6.55  I NICAM FM" },	{ 0x000b, MSP_CARRIER(6.5), MSP_CARRIER(5.85), "6.5/5.85  D/K NICAM FM" },	{ 0x000c, MSP_CARRIER(6.5), MSP_CARRIER(5.85), "6.5/5.85  D/K NICAM FM (HDEV2)" },	{ 0x0020, MSP_CARRIER(4.5), MSP_CARRIER(4.5), "4.5  M BTSC-Stereo" },	{ 0x0021, MSP_CARRIER(4.5), MSP_CARRIER(4.5), "4.5  M BTSC-Mono + SAP" },	{ 0x0030, MSP_CARRIER(4.5), MSP_CARRIER(4.5), "4.5  M EIA-J Japan Stereo" },	{ 0x0040, MSP_CARRIER(10.7), MSP_CARRIER(10.7), "10.7  FM-Stereo Radio" },	{ 0x0050, MSP_CARRIER(6.5), MSP_CARRIER(6.5), "6.5  SAT-Mono" },	{ 0x0051, MSP_CARRIER(7.02), MSP_CARRIER(7.20), "7.02/7.20  SAT-Stereo" },	{ 0x0060, MSP_CARRIER(7.2), MSP_CARRIER(7.2), "7.2  SAT ADR" },	{     -1, 0, 0, NULL }, /* EOF */}; static int msp3410d_thread(void *data){	struct i2c_client *client = data;	struct msp3400c *msp = client->data;	int mode,val,i,std;    #ifdef CONFIG_SMP	lock_kernel();#endif    	daemonize();	sigfillset(&current->blocked);	strcpy(current->comm,"msp3410 [auto]");	msp->thread = current;#ifdef CONFIG_SMP	unlock_kernel();#endif	printk("msp3410: daemon started\n");	if(msp->notify != NULL)		up(msp->notify);			for (;;) {		if (msp->rmmod)			goto done;		if (debug > 1)			printk("msp3410: thread: sleep\n");		interruptible_sleep_on(&msp->wq);		if (debug > 1)			printk("msp3410: thread: wakeup\n");		if (msp->rmmod || signal_pending(current))			goto done;		msp->active = 1;		if (msp->watch_stereo) {			watch_stereo(client);			msp->active = 0;			continue;		}			/* some time for the tuner to sync */		current->state   = TASK_INTERRUPTIBLE;		schedule_timeout(HZ/5);		if (signal_pending(current))			goto done;	restart:		msp->restart = 0;		del_timer(&msp->wake_stereo);		msp->watch_stereo = 0;		/* put into sane state (and mute) */		msp3400c_reset(client);		/* set various prescales */		msp3400c_write(client, I2C_MSP3400C_DFP, 0x0d, 0x1900); /* scart */		msp3400c_write(client, I2C_MSP3400C_DFP, 0x0e, 0x2403); /* FM */		msp3400c_write(client, I2C_MSP3400C_DFP, 0x10, 0x5a00); /* nicam */		/* start autodetect */		switch (msp->norm) {		case VIDEO_MODE_PAL:			mode = 0x1003;			std  = 1;			break;		case VIDEO_MODE_NTSC:  /* BTSC */			mode = 0x2003;			std  = 0x0020;			break;		case VIDEO_MODE_SECAM: 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -