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

📄 msp3400-driver.c

📁 V4l driver for DVB HD
💻 C
📖 第 1 页 / 共 3 页
字号:
#endif		}	}#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,12)) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0))	if (current->flags & PF_FREEZE) {		refrigerator (PF_FREEZE);	}#endif	remove_wait_queue(&state->wq, &wait);#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,12)	try_to_freeze();#endif	return state->restart;}/* ------------------------------------------------------------------------ */static int msp_mode_v4l2_to_v4l1(int rxsubchans, int audmode){	if (rxsubchans == V4L2_TUNER_SUB_MONO)		return VIDEO_SOUND_MONO;	if (rxsubchans == V4L2_TUNER_SUB_STEREO)		return VIDEO_SOUND_STEREO;	if (audmode == V4L2_TUNER_MODE_LANG2)		return VIDEO_SOUND_LANG2;	return VIDEO_SOUND_LANG1;}static int msp_mode_v4l1_to_v4l2(int mode){	if (mode & VIDEO_SOUND_STEREO)		return V4L2_TUNER_MODE_STEREO;	if (mode & VIDEO_SOUND_LANG2)		return V4L2_TUNER_MODE_LANG2;	if (mode & VIDEO_SOUND_LANG1)		return V4L2_TUNER_MODE_LANG1;	return V4L2_TUNER_MODE_MONO;}static struct v4l2_queryctrl msp_qctrl_std[] = {	{		.id            = V4L2_CID_AUDIO_VOLUME,		.name          = "Volume",		.minimum       = 0,		.maximum       = 65535,		.step          = 65535/100,		.default_value = 58880,		.flags         = 0,		.type          = V4L2_CTRL_TYPE_INTEGER,	},{		.id            = V4L2_CID_AUDIO_MUTE,		.name          = "Mute",		.minimum       = 0,		.maximum       = 1,		.step          = 1,		.default_value = 1,		.flags         = 0,		.type          = V4L2_CTRL_TYPE_BOOLEAN,	},};static struct v4l2_queryctrl msp_qctrl_sound_processing[] = {	{		.id            = V4L2_CID_AUDIO_BALANCE,		.name          = "Balance",		.minimum       = 0,		.maximum       = 65535,		.step          = 65535/100,		.default_value = 32768,		.flags         = 0,		.type          = V4L2_CTRL_TYPE_INTEGER,	},{		.id            = V4L2_CID_AUDIO_BASS,		.name          = "Bass",		.minimum       = 0,		.maximum       = 65535,		.step          = 65535/100,		.default_value = 32768,		.type          = V4L2_CTRL_TYPE_INTEGER,	},{		.id            = V4L2_CID_AUDIO_TREBLE,		.name          = "Treble",		.minimum       = 0,		.maximum       = 65535,		.step          = 65535/100,		.default_value = 32768,		.type          = V4L2_CTRL_TYPE_INTEGER,	},{		.id            = V4L2_CID_AUDIO_LOUDNESS,		.name          = "Loudness",		.minimum       = 0,		.maximum       = 1,		.step          = 1,		.default_value = 1,		.flags         = 0,		.type          = V4L2_CTRL_TYPE_BOOLEAN,	},};static int msp_get_ctrl(struct i2c_client *client, struct v4l2_control *ctrl){	struct msp_state *state = i2c_get_clientdata(client);	switch (ctrl->id) {	case V4L2_CID_AUDIO_VOLUME:		ctrl->value = state->volume;		break;	case V4L2_CID_AUDIO_MUTE:		ctrl->value = state->muted;		break;	case V4L2_CID_AUDIO_BALANCE:		if (!state->has_sound_processing)			return -EINVAL;		ctrl->value = state->balance;		break;	case V4L2_CID_AUDIO_BASS:		if (!state->has_sound_processing)			return -EINVAL;		ctrl->value = state->bass;		break;	case V4L2_CID_AUDIO_TREBLE:		if (!state->has_sound_processing)			return -EINVAL;		ctrl->value = state->treble;		break;	case V4L2_CID_AUDIO_LOUDNESS:		if (!state->has_sound_processing)			return -EINVAL;		ctrl->value = state->loudness;		break;	default:		return -EINVAL;	}	return 0;}static int msp_set_ctrl(struct i2c_client *client, struct v4l2_control *ctrl){	struct msp_state *state = i2c_get_clientdata(client);	switch (ctrl->id) {	case V4L2_CID_AUDIO_VOLUME:		state->volume = ctrl->value;		if (state->volume == 0)			state->balance = 32768;		break;	case V4L2_CID_AUDIO_MUTE:		if (ctrl->value < 0 || ctrl->value >= 2)			return -ERANGE;		state->muted = ctrl->value;		break;	case V4L2_CID_AUDIO_BASS:		if (!state->has_sound_processing)			return -EINVAL;		state->bass = ctrl->value;		break;	case V4L2_CID_AUDIO_TREBLE:		if (!state->has_sound_processing)			return -EINVAL;		state->treble = ctrl->value;		break;	case V4L2_CID_AUDIO_LOUDNESS:		if (!state->has_sound_processing)			return -EINVAL;		state->loudness = ctrl->value;		break;	case V4L2_CID_AUDIO_BALANCE:		if (!state->has_sound_processing)			return -EINVAL;		state->balance = ctrl->value;		break;	default:		return -EINVAL;	}	msp_set_audio(client);	return 0;}static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg){	struct msp_state *state = i2c_get_clientdata(client);	if (msp_debug >= 2)		v4l_i2c_print_ioctl(client, cmd);	switch (cmd) {	case AUDC_SET_RADIO:		if (state->radio)			return 0;		state->radio = 1;		v4l_dbg(1, msp_debug, client, "switching to radio mode\n");		state->watch_stereo = 0;		switch (state->opmode) {		case OPMODE_MANUAL:			/* set msp3400 to FM radio mode */			msp3400c_set_mode(client, MSP_MODE_FM_RADIO);			msp3400c_set_carrier(client, MSP_CARRIER(10.7),					    MSP_CARRIER(10.7));			msp_set_audio(client);			break;		case OPMODE_AUTODETECT:		case OPMODE_AUTOSELECT:			/* the thread will do for us */			msp_wake_thread(client);			break;		}		break;	/* --- v4l ioctls --- */	/* take care: bttv does userspace copying, we'll get a	   kernel pointer here... */	case VIDIOCGAUDIO:	{		struct video_audio *va = arg;		va->flags |= VIDEO_AUDIO_VOLUME | VIDEO_AUDIO_MUTABLE;		if (state->has_sound_processing)			va->flags |= VIDEO_AUDIO_BALANCE |				VIDEO_AUDIO_BASS |				VIDEO_AUDIO_TREBLE;		if (state->muted)			va->flags |= VIDEO_AUDIO_MUTE;		va->volume = state->volume;		va->balance = state->volume ? state->balance : 32768;		va->bass = state->bass;		va->treble = state->treble;		if (state->radio)			break;		if (state->opmode == OPMODE_AUTOSELECT)			msp_detect_stereo(client);		va->mode = msp_mode_v4l2_to_v4l1(state->rxsubchans, state->audmode);		break;	}	case VIDIOCSAUDIO:	{		struct video_audio *va = arg;		state->muted = (va->flags & VIDEO_AUDIO_MUTE);		state->volume = va->volume;		state->balance = va->balance;		state->bass = va->bass;		state->treble = va->treble;		msp_set_audio(client);		if (va->mode != 0 && state->radio == 0 &&		    state->audmode != msp_mode_v4l1_to_v4l2(va->mode)) {			state->audmode = msp_mode_v4l1_to_v4l2(va->mode);			msp_set_audmode(client);		}		break;	}	case VIDIOCSCHAN:	{		struct video_channel *vc = arg;		int update = 0;		v4l2_std_id std;		if (state->radio)			update = 1;		state->radio = 0;		if (vc->norm == VIDEO_MODE_PAL)			std = V4L2_STD_PAL;		else if (vc->norm == VIDEO_MODE_SECAM)			std = V4L2_STD_SECAM;		else			std = V4L2_STD_NTSC;		if (std != state->v4l2_std) {			state->v4l2_std = std;			update = 1;		}		if (update)			msp_wake_thread(client);		break;	}	case VIDIOCSFREQ:	case VIDIOC_S_FREQUENCY:	{		/* new channel -- kick audio carrier scan */		msp_wake_thread(client);		break;	}	/* --- v4l2 ioctls --- */	case VIDIOC_S_STD:	{		v4l2_std_id *id = arg;		int update = state->radio || state->v4l2_std != *id;		state->v4l2_std = *id;		state->radio = 0;		if (update)			msp_wake_thread(client);		return 0;	}	case VIDIOC_INT_G_AUDIO_ROUTING:	{		struct v4l2_routing *rt = arg;		*rt = state->routing;		break;	}	case VIDIOC_INT_S_AUDIO_ROUTING:	{		struct v4l2_routing *rt = arg;		int tuner = (rt->input >> 3) & 1;		int sc_in = rt->input & 0x7;		int sc1_out = rt->output & 0xf;		int sc2_out = (rt->output >> 4) & 0xf;		u16 val, reg;		int i;		int extern_input = 1;		if (state->routing.input == rt->input &&		    state->routing.output == rt->output)			break;		state->routing = *rt;		/* check if the tuner input is used */		for (i = 0; i < 5; i++) {			if (((rt->input >> (4 + i * 4)) & 0xf) == 0)				extern_input = 0;		}		if (extern_input)			state->mode = MSP_MODE_EXTERN;		else			state->mode = MSP_MODE_AM_DETECT;		msp_set_scart(client, sc_in, 0);		msp_set_scart(client, sc1_out, 1);		msp_set_scart(client, sc2_out, 2);		msp_set_audmode(client);		reg = (state->opmode == OPMODE_AUTOSELECT) ? 0x30 : 0xbb;		val = msp_read_dem(client, reg);		msp_write_dem(client, reg, (val & ~0x100) | (tuner << 8));		/* wake thread when a new input is chosen */		msp_wake_thread(client);		break;	}	case VIDIOC_G_TUNER:	{		struct v4l2_tuner *vt = arg;		if (state->radio)			break;		if (state->opmode == OPMODE_AUTOSELECT)			msp_detect_stereo(client);		vt->audmode    = state->audmode;		vt->rxsubchans = state->rxsubchans;		vt->capability |= V4L2_TUNER_CAP_STEREO |			V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2;		break;	}	case VIDIOC_S_TUNER:	{		struct v4l2_tuner *vt = (struct v4l2_tuner *)arg;		if (state->radio)  /* TODO: add mono/stereo support for radio */			break;		if (state->audmode == vt->audmode)			break;		state->audmode = vt->audmode;		/* only set audmode */		msp_set_audmode(client);		break;	}	case VIDIOC_INT_I2S_CLOCK_FREQ:	{		u32 *a = (u32 *)arg;		v4l_dbg(1, msp_debug, client, "Setting I2S speed to %d\n", *a);		switch (*a) {			case 1024000:				state->i2s_mode = 0;				break;			case 2048000:				state->i2s_mode = 1;				break;

⌨️ 快捷键说明

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