cx25840-core.c

来自「linux2.6.16版本」· C语言 代码 · 共 1,135 行 · 第 1/3 页

C
1,135
字号
	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:		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:		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_pal = !(cx25840_get_v4lstd(client) & V4L2_STD_NTSC);	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_pal ? 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 struct v4l2_queryctrl cx25840_qctrl[] = {	{		.id            = V4L2_CID_BRIGHTNESS,		.type          = V4L2_CTRL_TYPE_INTEGER,		.name          = "Brightness",		.minimum       = 0,		.maximum       = 255,		.step          = 1,		.default_value = 128,		.flags         = 0,	}, {		.id            = V4L2_CID_CONTRAST,		.type          = V4L2_CTRL_TYPE_INTEGER,		.name          = "Contrast",		.minimum       = 0,		.maximum       = 127,		.step          = 1,		.default_value = 64,		.flags         = 0,	}, {		.id            = V4L2_CID_SATURATION,		.type          = V4L2_CTRL_TYPE_INTEGER,		.name          = "Saturation",		.minimum       = 0,		.maximum       = 127,		.step          = 1,		.default_value = 64,		.flags         = 0,	}, {		.id            = V4L2_CID_HUE,		.type          = V4L2_CTRL_TYPE_INTEGER,		.name          = "Hue",		.minimum       = -128,		.maximum       = 127,		.step          = 1,		.default_value = 0,		.flags 	       = 0,	}, {		.id            = V4L2_CID_AUDIO_VOLUME,		.type          = V4L2_CTRL_TYPE_INTEGER,		.name          = "Volume",		.minimum       = 0,		.maximum       = 65535,		.step          = 65535/100,		.default_value = 58880,		.flags         = 0,	}, {		.id            = V4L2_CID_AUDIO_BALANCE,		.type          = V4L2_CTRL_TYPE_INTEGER,		.name          = "Balance",		.minimum       = 0,		.maximum       = 65535,		.step          = 65535/100,		.default_value = 32768,		.flags         = 0,	}, {		.id            = V4L2_CID_AUDIO_MUTE,		.type          = V4L2_CTRL_TYPE_BOOLEAN,		.name          = "Mute",		.minimum       = 0,		.maximum       = 1,		.step          = 1,		.default_value = 1,		.flags         = 0,	}, {		.id            = V4L2_CID_AUDIO_BASS,		.type          = V4L2_CTRL_TYPE_INTEGER,		.name          = "Bass",		.minimum       = 0,		.maximum       = 65535,		.step          = 65535/100,		.default_value = 32768,	}, {		.id            = V4L2_CID_AUDIO_TREBLE,		.type          = V4L2_CTRL_TYPE_INTEGER,		.name          = "Treble",		.minimum       = 0,		.maximum       = 65535,		.step          = 65535/100,		.default_value = 32768,	},};/* ----------------------------------------------------------------------- */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;	switch (cmd) {#ifdef CONFIG_VIDEO_ADV_DEBUG	/* ioctls to allow direct access to the	 * cx25840 registers for testing */	case VIDIOC_INT_G_REGISTER:	{		struct v4l2_register *reg = arg;		if (reg->i2c_id != I2C_DRIVERID_CX25840)			return -EINVAL;		reg->val = cx25840_read(client, reg->reg & 0x0fff);		break;	}	case VIDIOC_INT_S_REGISTER:	{		struct v4l2_register *reg = arg;		if (reg->i2c_id != I2C_DRIVERID_CX25840)			return -EINVAL;		if (!capable(CAP_SYS_ADMIN))			return -EPERM;		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, 0x8c);		cx25840_write(client, 0x116, 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_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;		int i;		for (i = 0; i < ARRAY_SIZE(cx25840_qctrl); i++)			if (qc->id && qc->id == cx25840_qctrl[i].id) {				memcpy(qc, &cx25840_qctrl[i], sizeof(*qc));				return 0;			}		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_G_INPUT:		*(int *)arg = state->vid_input;		break;	case VIDIOC_S_INPUT:		return set_input(client, *(enum cx25840_video_input *)arg, state->aud_input);	case VIDIOC_S_AUDIO:	{		struct v4l2_audio *input = arg;		return set_input(client, state->vid_input, input->index);	}	case VIDIOC_G_AUDIO:	{		struct v4l2_audio *input = arg;		memset(input, 0, sizeof(*input));		input->index = state->aud_input;		break;	}	case VIDIOC_S_FREQUENCY:		input_change(client);		break;	case VIDIOC_G_TUNER:	{		u8 mode = cx25840_read(client, 0x804);		u8 pref = cx25840_read(client, 0x809) & 0xf;		u8 vpres = cx25840_read(client, 0x80a) & 0x10;		int val = 0;

⌨️ 快捷键说明

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