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

📄 msp3400.c

📁 This program is free software you can redistribute it and/or modify it under the terms of the GNU Ge
💻 C
📖 第 1 页 / 共 4 页
字号:
		}
		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);

			set_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 > 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);

			set_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 > 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:
	dprintk(KERN_DEBUG "msp3400: thread: exit\n");
	msp->active = 0;
	msp->thread = NULL;

	if(msp->notify != NULL)
		up(msp->notify);
	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 = i2c_get_clientdata(client);
	int mode,val,i,std;
    
	lock_kernel();
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,61)
	daemonize();
	sigfillset(&current->blocked);
	strcpy(current->comm,"msp3410 [auto]");
#else
	daemonize("msp3410 [auto]");
#endif
	msp->thread = current;
	unlock_kernel();

	printk("msp3410: daemon started\n");
	if(msp->notify != NULL)
		up(msp->notify);
		
	for (;;) {
		if (msp->rmmod)
			goto done;
		if (debug > 1)
			printk(KERN_DEBUG "msp3410: thread: sleep\n");
		interruptible_sleep_on(&msp->wq);
		if (debug > 1)
			printk(KERN_DEBUG "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 */
		set_current_state(TASK_INTERRUPTIBLE);
		schedule_timeout(HZ/5);
		if (signal_pending(current))
			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;
			break;
		case VIDEO_MODE_NTSC:  /* BTSC */
			mode = 0x2003;
			std  = 0x0020;
			break;
		case VIDEO_MODE_SECAM: 
			mode = 0x0003;
			std  = 1;
			break;
		case VIDEO_MODE_RADIO:
			mode = 0x0003;
			std  = 0x0040;
			break;
		default:
			mode = 0x0003;
			std  = 1;
			break;
		}
		msp3400c_write(client, I2C_MSP3400C_DEM, 0x30, mode);
		msp3400c_write(client, I2C_MSP3400C_DEM, 0x20, std);

		if (debug) {
			int i;
			for (i = 0; modelist[i].name != NULL; i++)
				if (modelist[i].retval == std)
					break;
			printk(KERN_DEBUG "msp3410: setting mode: %s (0x%04x)\n",
			       modelist[i].name ? modelist[i].name : "unknown",std);
		}

		if (std != 1) {
			/* programmed some specific mode */
			val = std;
		} else {
			/* triggered autodetect */
			for (;;) {
				set_current_state(TASK_INTERRUPTIBLE);
				schedule_timeout(HZ/10);
				if (signal_pending(current))
					goto done;
				if (msp->restart)
					goto restart;

				/* check results */
				val = msp3400c_read(client, I2C_MSP3400C_DEM, 0x7e);
				if (val < 0x07ff)
					break;
				dprintk(KERN_DEBUG "msp3410: detection still in progress\n");
			}
		}
		for (i = 0; modelist[i].name != NULL; i++)
			if (modelist[i].retval == val)
				break;
		dprintk(KERN_DEBUG "msp3410: current mode: %s (0x%04x)\n",
			modelist[i].name ? modelist[i].name : "unknown",
			val);
		msp->main   = modelist[i].main;
		msp->second = modelist[i].second;

		if (amsound && (msp->norm == VIDEO_MODE_SECAM) && (val != 0x0009)) {
			/* autodetection has failed, let backup */
			dprintk(KERN_DEBUG "msp3410: autodetection failed,"
				" switching to backup mode: %s (0x%04x)\n",
				modelist[8].name ? modelist[8].name : "unknown",val);
			val = 0x0009;
			msp3400c_write(client, I2C_MSP3400C_DEM, 0x20, val);
		}

		/* 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 */

		/* set stereo */
		switch (val) {
		case 0x0008: /* B/G NICAM */
		case 0x000a: /* I NICAM */
			if (val == 0x0008)
				msp->mode = MSP_MODE_FM_NICAM1;
			else
				msp->mode = MSP_MODE_FM_NICAM2;
			/* just turn on stereo */
			msp->stereo = VIDEO_SOUND_STEREO;
			msp->nicam_on = 1;
			msp->watch_stereo = 1;
			msp3400c_setstereo(client,VIDEO_SOUND_STEREO);
			break;
		case 0x0009:			
			msp->mode = MSP_MODE_AM_NICAM;
			msp->stereo = VIDEO_SOUND_MONO;
			msp->nicam_on = 1;
			msp3400c_setstereo(client,VIDEO_SOUND_MONO);
			msp->watch_stereo = 1;
			break;
		case 0x0020: /* BTSC */
			/* just turn on stereo */
			msp->mode   = MSP_MODE_BTSC;
			msp->stereo = VIDEO_SOUND_STEREO;
			msp->nicam_on = 0;
			msp->watch_stereo = 1;
			msp3400c_setstereo(client,VIDEO_SOUND_STEREO);
			break;
		case 0x0040: /* FM radio */
			msp->mode   = MSP_MODE_FM_RADIO;
			msp->stereo = VIDEO_SOUND_STEREO;
			msp->nicam_on = 0;
			msp->watch_stereo = 0;
			/* not needed in theory if HAVE_RADIO(), but
			   short programming enables carrier mute */
			msp3400c_setmode(client,MSP_MODE_FM_RADIO);
			msp3400c_setcarrier(client, MSP_CARRIER(10.7),
					    MSP_CARRIER(10.7));
			/* scart routing */
			msp3400c_set_scart(client,SCART_IN2,0);
#if 0
			/* radio from SCART_IN2 */
			msp3400c_write(client,I2C_MSP3400C_DFP, 0x08, 0x0220);
			msp3400c_write(client,I2C_MSP3400C_DFP, 0x09, 0x0220);
			msp3400c_write(client,I2C_MSP3400C_DFP, 0x0b, 0x0220);
#else
			/* msp34xx does radio decoding */
			msp3400c_write(client,I2C_MSP3400C_DFP, 0x08, 0x0020);
			msp3400c_write(client,I2C_MSP3400C_DFP, 0x09, 0x0020);
			msp3400c_write(client,I2C_MSP3400C_DFP, 0x0b, 0x0020);
#endif
			break;
		case 0x0003:
		case 0x0004:
		case 0x0005:
			msp->mode   = MSP_MODE_FM_TERRA;
			msp->stereo = VIDEO_SOUND_MONO;
			msp->nicam_on = 0;
			msp->watch_stereo = 1;
			break;
		}
		
		/* unmute + restore dfp registers */
		msp3400c_setbass(client, msp->bass);
		msp3400c_settreble(client, msp->treble);
		msp3400c_setvolume(client, msp->muted, msp->left, msp->right);
		msp3400c_restore_dfp(client);

		if (msp->watch_stereo)
			mod_timer(&msp->wake_stereo, jiffies+HZ);

		msp->active = 0;
	}

⌨️ 快捷键说明

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