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

📄 msp3400.c

📁 该代码是天敏电视卡天敏大师4的核心芯片在linux下面的驱动
💻 C
📖 第 1 页 / 共 3 页
字号:
		break;	case MSP_MODE_EXTERN:		dprintk(KERN_DEBUG "msp3400: extern setstereo: %s\n",strmode[mode]);		nicam = 0x0200;		break;	case MSP_MODE_FM_RADIO:		dprintk(KERN_DEBUG "msp3400: FM-Radio setstereo: %s\n",strmode[mode]);		break;	default:		dprintk(KERN_DEBUG "msp3400: mono setstereo\n");		return;	}	/* switch audio */	switch (mode) {	case VIDEO_SOUND_STEREO:		src = 0x0020 | nicam;#if 0 		/* spatial effect */		msp3400c_write(client,I2C_MSP3400C_DFP, 0x0005,0x4000);#endif		break;	case VIDEO_SOUND_MONO:		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;	}	dprintk(KERN_DEBUG		"msp3400: setstereo final source/matrix = 0x%x\n", src);	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);		msp3400c_write(client,I2C_MSP3400C_DFP, 0x000b,src);	}}static voidmsp3400c_print_mode(struct msp3400c *msp){	if (msp->main == msp->second) {		printk(KERN_DEBUG "msp3400: mono sound carrier: %d.%03d MHz\n",		       msp->main/910000,(msp->main/910)%1000);	} else {		printk(KERN_DEBUG "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(KERN_DEBUG "msp3400: NICAM/FM carrier   : %d.%03d MHz\n",		       msp->second/910000,(msp->second/910)%1000);	if (msp->mode == MSP_MODE_AM_NICAM)		printk(KERN_DEBUG "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(KERN_DEBUG "msp3400: FM-stereo carrier : %d.%03d MHz\n",		       msp->second/910000,(msp->second/910)%1000);	}}static voidmsp3400c_restore_dfp(struct i2c_client *client){	struct msp3400c *msp = i2c_get_clientdata(client);	int i;	for (i = 0; i < DFP_COUNT; i++) {		if (-1 == msp->dfp_regs[i])			continue;		msp3400c_write(client,I2C_MSP3400C_DFP, i, msp->dfp_regs[i]);	}}/* ----------------------------------------------------------------------- */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 = i2c_get_clientdata(client);	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 > 32767)			val -= 65536;		dprintk(KERN_DEBUG			"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(KERN_DEBUG			"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(KERN_DEBUG			"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(KERN_DEBUG "msp34xx: watch: stereo %d => %d\n",			msp->stereo,newstereo);		msp->stereo   = newstereo;	}	if (newnicam != msp->nicam_on) {		update = 1;		dprintk(KERN_DEBUG "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 int msp34xx_sleep(struct msp3400c *msp, int timeout){	DECLARE_WAITQUEUE(wait, current);		add_wait_queue(&msp->wq, &wait);	if (!msp->rmmod) {		set_current_state(TASK_INTERRUPTIBLE);		if (timeout < 0)			schedule();		else			schedule_timeout(timeout);	}	remove_wait_queue(&msp->wq, &wait);	return msp->rmmod || signal_pending(current);}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 = i2c_get_clientdata(client);	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 if (msp->stereo & VIDEO_SOUND_LANG2)			msp3400c_setstereo(client,VIDEO_SOUND_LANG2);		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 = i2c_get_clientdata(client);		struct CARRIER_DETECT *cd;	int count, max1,max2,val1,val2, val,this;	#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,61)	lock_kernel();	daemonize();	sigfillset(&current->blocked);	strcpy(current->comm,"msp3400");	unlock_kernel();#else	daemonize("msp3400");	allow_signal(SIGTERM);#endif	printk("msp3400: daemon started\n");	for (;;) {		d2printk("msp3400: thread: sleep\n");		if (msp34xx_sleep(msp,-1))			goto done;		d2printk("msp3400: thread: wakeup\n");		msp->active = 1;		if (msp->watch_stereo) {			watch_stereo(client);			msp->active = 0;			continue;		}		/* some time for the tuner to sync */		if (msp34xx_sleep(msp,HZ/5))			goto done;			restart:		if (VIDEO_MODE_RADIO == msp->norm ||		    MSP_MODE_EXTERN  == msp->mode) {			/* no carrier scan, just unmute */			printk("msp3400: thread: no carrier scan\n");			msp3400c_setvolume(client, msp->muted,					   msp->left, msp->right);			continue;		}		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);			if (msp34xx_sleep(msp,HZ/10))				goto done;			if (msp->restart)				msp->restart = 0;			val = msp3400c_read(client, I2C_MSP3400C_DFP, 0x1b);			if (val > 32767)				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);			if (msp34xx_sleep(msp,HZ/10))				goto done;			if (msp->restart)				goto restart;			val = msp3400c_read(client, I2C_MSP3400C_DFP, 0x1b);			if (val > 32767)				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 && HAVE_NICAM(msp)) {				/* 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 && HAVE_NICAM(msp)) {				/* 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 + restore dfp registers */		msp3400c_setvolume(client, msp->muted, msp->left, msp->right);		msp3400c_restore_dfp(client);		if (msp->watch_stereo)			mod_timer(&msp->wake_stereo, jiffies+5*HZ);		if (debug)			msp3400c_print_mode(msp);				msp->active = 0;	}done:	msp->active = 0;	dprintk(KERN_DEBUG "msp3400: thread: exit\n");        complete_and_exit(&msp->texit, 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 = i2c_get_clientdata(client);	int mode,val,i,std;    #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,61)	lock_kernel();	daemonize();	sigfillset(&current->blocked);	strcpy(current->comm,"msp3410 [auto]");	unlock_kernel();#else	daemonize("msp3410 [auto]");	allow_signal(SIGTERM);#endif	printk("msp3410: daemon started\n");	for (;;) {		d2printk(KERN_DEBUG "msp3410: thread: sleep\n");		if (msp34xx_sleep(msp,-1))			goto done;		d2printk(KERN_DEBUG "msp3410: thread: wakeup\n");		msp->active = 1;		if (msp->watch_stereo) {			watch_stereo(client);			msp->active = 0;			continue;		}			/* some time for the tuner to sync */		if (msp34xx_sleep(msp,HZ/5))			goto done;	restart:		if (msp->mode == MSP_MODE_EXTERN) {			/* no carrier scan needed, just unmute */			dprintk(KERN_DEBUG "msp3410: thread: no carrier scan\n");			msp3400c_setvolume(client, msp->muted,					   msp->left, msp->right);			continue;		}		msp->restart = 0;		del_timer(&msp->wake_stereo);		msp->watch_stereo = 0;		/* put into sane state (and mute) */		msp3400c_reset(client);		/* start autodetect */		switch (msp->norm) {		case VIDEO_MODE_PAL:			mode = 0x1003;			std  = 1;

⌨️ 快捷键说明

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