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

📄 msp3400-kthreads.c

📁 V4l driver for DVB HD
💻 C
📖 第 1 页 / 共 3 页
字号:
			else				state->mode = MSP_MODE_FM_NICAM1;			/* just turn on stereo */			state->nicam_on = 1;			state->watch_stereo = 1;			break;		case 0x0009:			state->mode = MSP_MODE_AM_NICAM;			state->nicam_on = 1;			state->watch_stereo = 1;			break;		case 0x0020: /* BTSC */			/* The pre-'G' models only have BTSC-mono */			state->mode = MSP_MODE_BTSC;			break;		case 0x0040: /* FM radio */			state->mode = MSP_MODE_FM_RADIO;			state->rxsubchans = V4L2_TUNER_SUB_STEREO;			/* not needed in theory if we have radio, but			   short programming enables carrier mute */			msp3400c_set_mode(client, MSP_MODE_FM_RADIO);			msp3400c_set_carrier(client, MSP_CARRIER(10.7),					    MSP_CARRIER(10.7));			break;		case 0x0002:		case 0x0003:		case 0x0004:		case 0x0005:			state->mode = MSP_MODE_FM_TERRA;			state->watch_stereo = 1;			break;		}		/* set various prescales */		msp_write_dsp(client, 0x0d, 0x1900); /* scart */		msp_write_dsp(client, 0x0e, 0x3000); /* FM */		if (state->has_nicam)			msp_write_dsp(client, 0x10, 0x5a00); /* nicam */		if (state->has_i2s_conf)			msp_write_dem(client, 0x40, state->i2s_mode);		/* unmute */		msp3400c_set_audmode(client);		state->scan_in_progress = 0;		msp_set_audio(client);		/* monitor tv audio mode, the first time don't wait		   so long to get a quick stereo/bilingual result */		count = 3;		while (state->watch_stereo) {			if (msp_sleep(state, count ? 1000 : 5000))				goto restart;			if (count) count--;			watch_stereo(client);		}	}	v4l_dbg(1, msp_debug, client, "thread: exit\n");#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)	state->kthread = NULL;	if (state->notify != NULL)		up(state->notify);#endif	return 0;}/* ----------------------------------------------------------------------- *//* msp34xxG + (autoselect no-thread) * this one uses both automatic standard detection and automatic sound * select which are available in the newer G versions * struct msp: only norm, acb and source are really used in this mode */static int msp34xxg_modus(struct i2c_client *client){	struct msp_state *state = i2c_get_clientdata(client);	if (state->radio) {		v4l_dbg(1, msp_debug, client, "selected radio modus\n");		return 0x0001;	}	if (state->v4l2_std & V4L2_STD_PAL) {		v4l_dbg(1, msp_debug, client, "selected PAL modus\n");		return 0x7001;	}	if (state->v4l2_std == V4L2_STD_NTSC_M_JP) {		v4l_dbg(1, msp_debug, client, "selected M (EIA-J) modus\n");		return 0x4001;	}	if (state->v4l2_std == V4L2_STD_NTSC_M_KR) {		v4l_dbg(1, msp_debug, client, "selected M (A2) modus\n");		return 0x0001;	}	if (state->v4l2_std & V4L2_STD_MN) {		v4l_dbg(1, msp_debug, client, "selected M (BTSC) modus\n");		return 0x2001;	}	if (state->v4l2_std & V4L2_STD_SECAM) {		v4l_dbg(1, msp_debug, client, "selected SECAM modus\n");		return 0x6001;	}	return 0x0001;}static void msp34xxg_set_source(struct i2c_client *client, u16 reg, int in) {	struct msp_state *state = i2c_get_clientdata(client);	int source, matrix;	switch (state->audmode) {	case V4L2_TUNER_MODE_MONO:		source = 0; /* mono only */		matrix = 0x30;		break;	case V4L2_TUNER_MODE_LANG2:		source = 4; /* stereo or B */		matrix = 0x10;		break;	case V4L2_TUNER_MODE_LANG1_LANG2:		source = 1; /* stereo or A|B */		matrix = 0x20;		break;	case V4L2_TUNER_MODE_STEREO:	case V4L2_TUNER_MODE_LANG1:	default:		source = 3; /* stereo or A */		matrix = 0x00;		break;	}	if (in == MSP_DSP_IN_TUNER)		source = (source << 8) | 0x20;	/* the msp34x2g puts the MAIN_AVC, MAIN and AUX sources in 12, 13, 14	   instead of 11, 12, 13. So we add one for that msp version. */	else if (in >= MSP_DSP_IN_MAIN_AVC && state->has_dolby_pro_logic)		source = ((in + 1) << 8) | matrix;	else		source = (in << 8) | matrix;	v4l_dbg(1, msp_debug, client, "set source to %d (0x%x) for output %02x\n",			in, source, reg);	msp_write_dsp(client, reg, source);}static void msp34xxg_set_sources(struct i2c_client *client){	struct msp_state *state = i2c_get_clientdata(client);	u32 in = state->routing.input;	msp34xxg_set_source(client, 0x0008, (in >> 4) & 0xf);	/* quasi-peak detector is set to same input as the loudspeaker (MAIN) */	msp34xxg_set_source(client, 0x000c, (in >> 4) & 0xf);	msp34xxg_set_source(client, 0x0009, (in >> 8) & 0xf);	msp34xxg_set_source(client, 0x000a, (in >> 12) & 0xf);	if (state->has_scart2_out)		msp34xxg_set_source(client, 0x0041, (in >> 16) & 0xf);	msp34xxg_set_source(client, 0x000b, (in >> 20) & 0xf);}/* (re-)initialize the msp34xxg */static void msp34xxg_reset(struct i2c_client *client){	struct msp_state *state = i2c_get_clientdata(client);	int tuner = (state->routing.input >> 3) & 1;	int modus;	/* initialize std to 1 (autodetect) to signal that no standard is	   selected yet. */	state->std = 1;	msp_reset(client);	if (state->has_i2s_conf)		msp_write_dem(client, 0x40, state->i2s_mode);	/* step-by-step initialisation, as described in the manual */	modus = msp34xxg_modus(client);	modus |= tuner ? 0x100 : 0;	msp_write_dem(client, 0x30, modus);	/* write the dsps that may have an influence on	   standard/audio autodetection right now */	msp34xxg_set_sources(client);	msp_write_dsp(client, 0x0d, 0x1900); /* scart */	msp_write_dsp(client, 0x0e, 0x3000); /* FM */	if (state->has_nicam)		msp_write_dsp(client, 0x10, 0x5a00); /* nicam */	/* set identification threshold. Personally, I	 * I set it to a higher value than the default	 * of 0x190 to ignore noisy stereo signals.	 * this needs tuning. (recommended range 0x00a0-0x03c0)	 * 0x7f0 = forced mono mode	 *	 * a2 threshold for stereo/bilingual.	 * Note: this register is part of the Manual/Compatibility mode.	 * It is supported by all 'G'-family chips.	 */	msp_write_dem(client, 0x22, msp_stereo_thresh);}int msp34xxg_thread(void *data){	struct i2c_client *client = data;	struct msp_state *state = i2c_get_clientdata(client);	int val, i;#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)	msp_setup_thread(state);#endif	v4l_dbg(1, msp_debug, client, "msp34xxg daemon started\n");	for (;;) {		v4l_dbg(2, msp_debug, client, "msp34xxg thread: sleep\n");		msp_sleep(state, -1);		v4l_dbg(2, msp_debug, client, "msp34xxg thread: wakeup\n");	restart:		v4l_dbg(1, msp_debug, client, "thread: restart scan\n");		state->restart = 0;#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)		if (state->rmmod || signal_pending(current))#else		if (kthread_should_stop())#endif			break;		if (state->mode == MSP_MODE_EXTERN) {			/* no carrier scan needed, just unmute */			v4l_dbg(1, msp_debug, client, "thread: no carrier scan\n");			state->scan_in_progress = 0;			msp_set_audio(client);			continue;		}		/* setup the chip*/		msp34xxg_reset(client);		state->std = state->radio ? 0x40 : msp_standard;		if (state->std != 1)			goto unmute;		/* start autodetect */		msp_write_dem(client, 0x20, state->std);		/* watch autodetect */		v4l_dbg(1, msp_debug, client, "started autodetect, waiting for result\n");		for (i = 0; i < 10; i++) {			if (msp_sleep(state, 100))				goto restart;			/* check results */			val = msp_read_dem(client, 0x7e);			if (val < 0x07ff) {				state->std = val;				break;			}			v4l_dbg(2, msp_debug, client, "detection still in progress\n");		}		if (state->std == 1) {			v4l_dbg(1, msp_debug, client, "detection still in progress after 10 tries. giving up.\n");			continue;		}	unmute:		v4l_dbg(1, msp_debug, client, "detected standard: %s (0x%04x)\n",			msp_standard_std_name(state->std), state->std);		if (state->std == 9) {			/* AM NICAM mode */			msp_write_dsp(client, 0x0e, 0x7c00);		}		/* unmute: dispatch sound to scart output, set scart volume */		msp_set_audio(client);		/* restore ACB */		if (msp_write_dsp(client, 0x13, state->acb))			return -1;		/* the periodic stereo/SAP check is only relevant for		   the 0x20 standard (BTSC) */		if (state->std != 0x20)			continue;		state->watch_stereo = 1;		/* monitor tv audio mode, the first time don't wait		   in order to get a quick stereo/SAP update */		watch_stereo(client);		while (state->watch_stereo) {			watch_stereo(client);			if (msp_sleep(state, 5000))				goto restart;		}	}	v4l_dbg(1, msp_debug, client, "thread: exit\n");#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)	state->kthread = NULL;	if (state->notify != NULL)		up(state->notify);#endif	return 0;}static int msp34xxg_detect_stereo(struct i2c_client *client){	struct msp_state *state = i2c_get_clientdata(client);	int status = msp_read_dem(client, 0x0200);	int is_bilingual = status & 0x100;	int is_stereo = status & 0x40;	int oldrx = state->rxsubchans;	state->rxsubchans = 0;	if (is_stereo)		state->rxsubchans = V4L2_TUNER_SUB_STEREO;	else		state->rxsubchans = V4L2_TUNER_SUB_MONO;	if (is_bilingual) {		if (state->std == 0x20)			state->rxsubchans |= V4L2_TUNER_SUB_SAP;		else			state->rxsubchans = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2;	}	v4l_dbg(1, msp_debug, client, "status=0x%x, stereo=%d, bilingual=%d -> rxsubchans=%d\n",		status, is_stereo, is_bilingual, state->rxsubchans);	return (oldrx != state->rxsubchans);}static void msp34xxg_set_audmode(struct i2c_client *client){	struct msp_state *state = i2c_get_clientdata(client);	if (state->std == 0x20) {	       if ((state->rxsubchans & V4L2_TUNER_SUB_SAP) &&		   (state->audmode == V4L2_TUNER_MODE_LANG1_LANG2 ||		    state->audmode == V4L2_TUNER_MODE_LANG2)) {			msp_write_dem(client, 0x20, 0x21);	       } else {			msp_write_dem(client, 0x20, 0x20);	       }	}	msp34xxg_set_sources(client);}void msp_set_audmode(struct i2c_client *client){	struct msp_state *state = i2c_get_clientdata(client);	switch (state->opmode) {	case OPMODE_MANUAL:	case OPMODE_AUTODETECT:		msp3400c_set_audmode(client);		break;	case OPMODE_AUTOSELECT:		msp34xxg_set_audmode(client);		break;	}}int msp_detect_stereo(struct i2c_client *client){	struct msp_state *state  = i2c_get_clientdata(client);	switch (state->opmode) {	case OPMODE_MANUAL:	case OPMODE_AUTODETECT:		return msp3400c_detect_stereo(client);	case OPMODE_AUTOSELECT:		return msp34xxg_detect_stereo(client);	}	return 0;}

⌨️ 快捷键说明

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