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

📄 cx25840-core.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
	} else {		/* Then, test against generic ones */		if (std & V4L2_STD_NTSC) {			fmt=0x1;		} else if (std & V4L2_STD_PAL) {			fmt=0x4;		} else if (std & V4L2_STD_SECAM) {			fmt=0xc;		}	}	v4l_dbg(1, cx25840_debug, client, "changing video std to fmt %i\n",fmt);	/* Follow step 9 of section 3.16 in the cx25840 datasheet.	   Without this PAL may display a vertical ghosting effect.	   This happens for example with the Yuan MPC622. */	if (fmt >= 4 && fmt < 8) {		/* Set format to NTSC-M */		cx25840_and_or(client, 0x400, ~0xf, 1);		/* Turn off LCOMB */		cx25840_and_or(client, 0x47b, ~6, 0);	}	cx25840_and_or(client, 0x400, ~0xf, fmt);	cx25840_vbi_setup(client);	return 0;}v4l2_std_id cx25840_get_v4lstd(struct i2c_client * client){	struct cx25840_state *state = i2c_get_clientdata(client);	/* check VID_FMT_SEL first */	u8 fmt = cx25840_read(client, 0x400) & 0xf;	if (!fmt) {		/* check AFD_FMT_STAT if set to autodetect */		fmt = cx25840_read(client, 0x40d) & 0xf;	}	switch (fmt) {	case 0x1:	{		/* if the audio std is A2-M, then this is the South Korean		   NTSC standard */		if (!state->is_cx25836 && cx25840_read(client, 0x805) == 2)			return V4L2_STD_NTSC_M_KR;		return V4L2_STD_NTSC_M;	}	case 0x2: return V4L2_STD_NTSC_M_JP;	case 0x3: return V4L2_STD_NTSC_443;	case 0x4: return V4L2_STD_PAL;	case 0x5: return V4L2_STD_PAL_M;	case 0x6: return V4L2_STD_PAL_N;	case 0x7: return V4L2_STD_PAL_Nc;	case 0x8: return V4L2_STD_PAL_60;	case 0xc: return V4L2_STD_SECAM;	default: return V4L2_STD_UNKNOWN;	}}/* ----------------------------------------------------------------------- */static int set_v4lctrl(struct i2c_client *client, struct v4l2_control *ctrl){	struct cx25840_state *state = i2c_get_clientdata(client);	switch (ctrl->id) {	case CX25840_CID_ENABLE_PVR150_WORKAROUND:		state->pvr150_workaround = ctrl->value;		set_input(client, state->vid_input, state->aud_input);		break;	case V4L2_CID_BRIGHTNESS:		if (ctrl->value < 0 || ctrl->value > 255) {			v4l_err(client, "invalid brightness setting %d\n",				    ctrl->value);			return -ERANGE;		}		cx25840_write(client, 0x414, ctrl->value - 128);		break;	case V4L2_CID_CONTRAST:		if (ctrl->value < 0 || ctrl->value > 127) {			v4l_err(client, "invalid contrast setting %d\n",				    ctrl->value);			return -ERANGE;		}		cx25840_write(client, 0x415, ctrl->value << 1);		break;	case V4L2_CID_SATURATION:		if (ctrl->value < 0 || ctrl->value > 127) {			v4l_err(client, "invalid saturation setting %d\n",				    ctrl->value);			return -ERANGE;		}		cx25840_write(client, 0x420, ctrl->value << 1);		cx25840_write(client, 0x421, ctrl->value << 1);		break;	case V4L2_CID_HUE:		if (ctrl->value < -127 || ctrl->value > 127) {			v4l_err(client, "invalid hue setting %d\n", ctrl->value);			return -ERANGE;		}		cx25840_write(client, 0x422, ctrl->value);		break;	case V4L2_CID_AUDIO_VOLUME:	case V4L2_CID_AUDIO_BASS:	case V4L2_CID_AUDIO_TREBLE:	case V4L2_CID_AUDIO_BALANCE:	case V4L2_CID_AUDIO_MUTE:		if (state->is_cx25836)			return -EINVAL;		return cx25840_audio(client, VIDIOC_S_CTRL, ctrl);	default:		return -EINVAL;	}	return 0;}static int get_v4lctrl(struct i2c_client *client, struct v4l2_control *ctrl){	struct cx25840_state *state = i2c_get_clientdata(client);	switch (ctrl->id) {	case CX25840_CID_ENABLE_PVR150_WORKAROUND:		ctrl->value = state->pvr150_workaround;		break;	case V4L2_CID_BRIGHTNESS:		ctrl->value = (s8)cx25840_read(client, 0x414) + 128;		break;	case V4L2_CID_CONTRAST:		ctrl->value = cx25840_read(client, 0x415) >> 1;		break;	case V4L2_CID_SATURATION:		ctrl->value = cx25840_read(client, 0x420) >> 1;		break;	case V4L2_CID_HUE:		ctrl->value = (s8)cx25840_read(client, 0x422);		break;	case V4L2_CID_AUDIO_VOLUME:	case V4L2_CID_AUDIO_BASS:	case V4L2_CID_AUDIO_TREBLE:	case V4L2_CID_AUDIO_BALANCE:	case V4L2_CID_AUDIO_MUTE:		if (state->is_cx25836)			return -EINVAL;		return cx25840_audio(client, VIDIOC_G_CTRL, ctrl);	default:		return -EINVAL;	}	return 0;}/* ----------------------------------------------------------------------- */static int get_v4lfmt(struct i2c_client *client, struct v4l2_format *fmt){	switch (fmt->type) {	case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:		return cx25840_vbi(client, VIDIOC_G_FMT, fmt);	default:		return -EINVAL;	}	return 0;}static int set_v4lfmt(struct i2c_client *client, struct v4l2_format *fmt){	struct v4l2_pix_format *pix;	int HSC, VSC, Vsrc, Hsrc, filter, Vlines;	int is_50Hz = !(cx25840_get_v4lstd(client) & V4L2_STD_525_60);	switch (fmt->type) {	case V4L2_BUF_TYPE_VIDEO_CAPTURE:		pix = &(fmt->fmt.pix);		Vsrc = (cx25840_read(client, 0x476) & 0x3f) << 4;		Vsrc |= (cx25840_read(client, 0x475) & 0xf0) >> 4;		Hsrc = (cx25840_read(client, 0x472) & 0x3f) << 4;		Hsrc |= (cx25840_read(client, 0x471) & 0xf0) >> 4;		Vlines = pix->height + (is_50Hz ? 4 : 7);		if ((pix->width * 16 < Hsrc) || (Hsrc < pix->width) ||		    (Vlines * 8 < Vsrc) || (Vsrc < Vlines)) {			v4l_err(client, "%dx%d is not a valid size!\n",				    pix->width, pix->height);			return -ERANGE;		}		HSC = (Hsrc * (1 << 20)) / pix->width - (1 << 20);		VSC = (1 << 16) - (Vsrc * (1 << 9) / Vlines - (1 << 9));		VSC &= 0x1fff;		if (pix->width >= 385)			filter = 0;		else if (pix->width > 192)			filter = 1;		else if (pix->width > 96)			filter = 2;		else			filter = 3;		v4l_dbg(1, cx25840_debug, client, "decoder set size %dx%d -> scale  %ux%u\n",			    pix->width, pix->height, HSC, VSC);		/* HSCALE=HSC */		cx25840_write(client, 0x418, HSC & 0xff);		cx25840_write(client, 0x419, (HSC >> 8) & 0xff);		cx25840_write(client, 0x41a, HSC >> 16);		/* VSCALE=VSC */		cx25840_write(client, 0x41c, VSC & 0xff);		cx25840_write(client, 0x41d, VSC >> 8);		/* VS_INTRLACE=1 VFILT=filter */		cx25840_write(client, 0x41e, 0x8 | filter);		break;	case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:		return cx25840_vbi(client, VIDIOC_S_FMT, fmt);	case V4L2_BUF_TYPE_VBI_CAPTURE:		return cx25840_vbi(client, VIDIOC_S_FMT, fmt);	default:		return -EINVAL;	}	return 0;}/* ----------------------------------------------------------------------- */static int cx25840_command(struct i2c_client *client, unsigned int cmd,			   void *arg){	struct cx25840_state *state = i2c_get_clientdata(client);	struct v4l2_tuner *vt = arg;	struct v4l2_routing *route = arg;	/* ignore these commands */	switch (cmd) {		case TUNER_SET_TYPE_ADDR:			return 0;	}	if (!state->is_initialized) {		v4l_dbg(1, cx25840_debug, client, "cmd %08x triggered fw load\n", cmd);		/* initialize on first use */		state->is_initialized = 1;		if (state->is_cx25836)			cx25836_initialize(client);		else			cx25840_initialize(client);	}	switch (cmd) {#ifdef CONFIG_VIDEO_ADV_DEBUG	/* ioctls to allow direct access to the	 * cx25840 registers for testing */	case VIDIOC_DBG_G_REGISTER:	case VIDIOC_DBG_S_REGISTER:	{		struct v4l2_register *reg = arg;		if (!v4l2_chip_match_i2c_client(client, reg->match_type, reg->match_chip))			return -EINVAL;		if (!capable(CAP_SYS_ADMIN))			return -EPERM;		if (cmd == VIDIOC_DBG_G_REGISTER)			reg->val = cx25840_read(client, reg->reg & 0x0fff);		else			cx25840_write(client, reg->reg & 0x0fff, reg->val & 0xff);		break;	}#endif	case VIDIOC_INT_DECODE_VBI_LINE:		return cx25840_vbi(client, cmd, arg);	case VIDIOC_INT_AUDIO_CLOCK_FREQ:		return cx25840_audio(client, cmd, arg);	case VIDIOC_STREAMON:		v4l_dbg(1, cx25840_debug, client, "enable output\n");		cx25840_write(client, 0x115, state->is_cx25836 ? 0x0c : 0x8c);		cx25840_write(client, 0x116, state->is_cx25836 ? 0x04 : 0x07);		break;	case VIDIOC_STREAMOFF:		v4l_dbg(1, cx25840_debug, client, "disable output\n");		cx25840_write(client, 0x115, 0x00);		cx25840_write(client, 0x116, 0x00);		break;	case VIDIOC_LOG_STATUS:		log_video_status(client);		if (!state->is_cx25836)			log_audio_status(client);		break;	case VIDIOC_G_CTRL:		return get_v4lctrl(client, (struct v4l2_control *)arg);	case VIDIOC_S_CTRL:		return set_v4lctrl(client, (struct v4l2_control *)arg);	case VIDIOC_QUERYCTRL:	{		struct v4l2_queryctrl *qc = arg;		switch (qc->id) {			case V4L2_CID_BRIGHTNESS:			case V4L2_CID_CONTRAST:			case V4L2_CID_SATURATION:			case V4L2_CID_HUE:				return v4l2_ctrl_query_fill_std(qc);			default:				break;		}		if (state->is_cx25836)			return -EINVAL;		switch (qc->id) {			case V4L2_CID_AUDIO_VOLUME:			case V4L2_CID_AUDIO_MUTE:			case V4L2_CID_AUDIO_BALANCE:			case V4L2_CID_AUDIO_BASS:			case V4L2_CID_AUDIO_TREBLE:				return v4l2_ctrl_query_fill_std(qc);			default:				return -EINVAL;		}		return -EINVAL;	}	case VIDIOC_G_STD:		*(v4l2_std_id *)arg = cx25840_get_v4lstd(client);		break;	case VIDIOC_S_STD:		state->radio = 0;		return set_v4lstd(client, *(v4l2_std_id *)arg);	case AUDC_SET_RADIO:		state->radio = 1;		break;	case VIDIOC_INT_G_VIDEO_ROUTING:		route->input = state->vid_input;		route->output = 0;		break;	case VIDIOC_INT_S_VIDEO_ROUTING:		return set_input(client, route->input, state->aud_input);	case VIDIOC_INT_G_AUDIO_ROUTING:		if (state->is_cx25836)			return -EINVAL;		route->input = state->aud_input;		route->output = 0;		break;	case VIDIOC_INT_S_AUDIO_ROUTING:		if (state->is_cx25836)			return -EINVAL;		return set_input(client, state->vid_input, route->input);	case VIDIOC_S_FREQUENCY:		if (!state->is_cx25836) {			input_change(client);		}		break;	case VIDIOC_G_TUNER:	{		u8 vpres = cx25840_read(client, 0x40e) & 0x20;		u8 mode;		int val = 0;		if (state->radio)			break;		vt->signal = vpres ? 0xffff : 0x0;		if (state->is_cx25836)			break;		vt->capability |=		    V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_LANG1 |		    V4L2_TUNER_CAP_LANG2 | V4L2_TUNER_CAP_SAP;

⌨️ 快捷键说明

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