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

📄 saa7115.c

📁 trident tm5600的linux驱动
💻 C
📖 第 1 页 / 共 4 页
字号:
		vbi->type = V4L2_SLICED_CAPTION_525;		break;	case 5:		wss = saa711x_decode_wss(p);		if (wss == -1)			return;		p[0] = wss & 0xff;		p[1] = wss >> 8;		vbi->type = V4L2_SLICED_WSS_625;		break;	case 7:		if (saa711x_decode_vps(p, p) != 0)			return;		vbi->type = V4L2_SLICED_VPS;		break;	default:		return;	}}/* ============ SAA7115 AUDIO settings (end) ============= */static int saa7115_command(struct i2c_client *client, unsigned int cmd, void *arg){	struct saa711x_state *state = i2c_get_clientdata(client);	/* ioctls to allow direct access to the saa7115 registers for testing */	switch (cmd) {	case VIDIOC_S_FMT:		return saa711x_set_v4lfmt(client, (struct v4l2_format *)arg);	case VIDIOC_G_FMT:		return saa711x_get_v4lfmt(client, (struct v4l2_format *)arg);	case VIDIOC_INT_AUDIO_CLOCK_FREQ:		return saa711x_set_audio_clock_freq(client, *(u32 *)arg);	case VIDIOC_G_TUNER:	{		struct v4l2_tuner *vt = arg;		int status;		if (state->radio)			break;		status = saa711x_read(client, R_1F_STATUS_BYTE_2_VD_DEC);		v4l_dbg(1, debug, client, "status: 0x%02x\n", status);		vt->signal = ((status & (1 << 6)) == 0) ? 0xffff : 0x0;		break;	}	case VIDIOC_LOG_STATUS:		saa711x_log_status(client);		break;	case VIDIOC_G_CTRL:		return saa711x_get_v4lctrl(client, (struct v4l2_control *)arg);	case VIDIOC_S_CTRL:		return saa711x_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:				return -EINVAL;		}	}	case VIDIOC_G_STD:		*(v4l2_std_id *)arg = saa711x_get_v4lstd(client);		break;	case VIDIOC_S_STD:		state->radio = 0;		saa711x_set_v4lstd(client, *(v4l2_std_id *)arg);		break;	case AUDC_SET_RADIO:		state->radio = 1;		break;	case VIDIOC_INT_G_VIDEO_ROUTING:	{		struct v4l2_routing *route = arg;		route->input = state->input;		route->output = state->output;		break;	}	case VIDIOC_INT_S_VIDEO_ROUTING:	{		struct v4l2_routing *route = arg;		u32 input = route->input;		u8 mask = (state->ident == V4L2_IDENT_SAA7111) ? 0xf8 : 0xf0;		v4l_dbg(1, debug, client, "decoder set input %d output %d\n", route->input, route->output);		/* saa7111/3 does not have these inputs */		if ((state->ident == V4L2_IDENT_SAA7113 ||		     state->ident == V4L2_IDENT_SAA7111) &&		    (route->input == SAA7115_COMPOSITE4 ||		     route->input == SAA7115_COMPOSITE5)) {			return -EINVAL;		}		if (route->input > SAA7115_SVIDEO3)			return -EINVAL;		if (route->output > SAA7115_IPORT_ON)			return -EINVAL;		if (state->input == route->input && state->output == route->output)			break;		v4l_dbg(1, debug, client, "now setting %s input %s output\n",			(route->input >= SAA7115_SVIDEO0) ? "S-Video" : "Composite", (route->output == SAA7115_IPORT_ON) ? "iport on" : "iport off");		state->input = route->input;		/* saa7111 has slightly different input numbering */		if (state->ident == V4L2_IDENT_SAA7111) {			if (input >= SAA7115_COMPOSITE4)				input -= 2;			/* saa7111 specific */			saa711x_write(client, R_10_CHROMA_CNTL_2,					(saa711x_read(client, R_10_CHROMA_CNTL_2) & 0x3f) |					((route->output & 0xc0) ^ 0x40));			saa711x_write(client, R_13_RT_X_PORT_OUT_CNTL,					(saa711x_read(client, R_13_RT_X_PORT_OUT_CNTL) & 0xf0) |					((route->output & 2) ? 0x0a : 0));		}		/* select mode */		saa711x_write(client, R_02_INPUT_CNTL_1,			      (saa711x_read(client, R_02_INPUT_CNTL_1) & mask) |			       input);		/* bypass chrominance trap for S-Video modes */		saa711x_write(client, R_09_LUMA_CNTL,			      (saa711x_read(client, R_09_LUMA_CNTL) & 0x7f) |			       (state->input >= SAA7115_SVIDEO0 ? 0x80 : 0x0));		state->output = route->output;		if (state->ident == V4L2_IDENT_SAA7114 ||			state->ident == V4L2_IDENT_SAA7115) {			saa711x_write(client, R_83_X_PORT_I_O_ENA_AND_OUT_CLK,			      (saa711x_read(client, R_83_X_PORT_I_O_ENA_AND_OUT_CLK) & 0xfe) |			       (state->output & 0x01));		}		break;	}	case VIDIOC_STREAMON:	case VIDIOC_STREAMOFF:		v4l_dbg(1, debug, client, "%s output\n",			(cmd == VIDIOC_STREAMON) ? "enable" : "disable");		if (state->enable != (cmd == VIDIOC_STREAMON)) {			state->enable = (cmd == VIDIOC_STREAMON);			saa711x_write(client,				R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED,				state->enable);		}		break;	case VIDIOC_INT_S_CRYSTAL_FREQ:	{		struct v4l2_crystal_freq *freq = arg;		if (freq->freq != SAA7115_FREQ_32_11_MHZ &&		    freq->freq != SAA7115_FREQ_24_576_MHZ)			return -EINVAL;		state->crystal_freq = freq->freq;		state->cgcdiv = (freq->flags & SAA7115_FREQ_FL_CGCDIV) ? 3 : 4;		state->ucgc = (freq->flags & SAA7115_FREQ_FL_UCGC) ? 1 : 0;		state->apll = (freq->flags & SAA7115_FREQ_FL_APLL) ? 1 : 0;		saa711x_set_audio_clock_freq(client, state->audclk_freq);		break;	}	case VIDIOC_INT_DECODE_VBI_LINE:		saa711x_decode_vbi_line(client, arg);		break;	case VIDIOC_INT_RESET:		v4l_dbg(1, debug, client, "decoder RESET\n");		saa711x_writeregs(client, saa7115_cfg_reset_scaler);		break;	case VIDIOC_INT_S_GPIO:		if (state->ident != V4L2_IDENT_SAA7111)			return -EINVAL;		saa711x_write(client, 0x11, (saa711x_read(client, 0x11) & 0x7f) |			(*(u32 *)arg ? 0x80 : 0));		break;	case VIDIOC_INT_G_VBI_DATA:	{		struct v4l2_sliced_vbi_data *data = arg;		/* Note: the internal field ID is inverted for NTSC,		   so data->field 0 maps to the saa7115 even field,		   whereas for PAL it maps to the saa7115 odd field. */		switch (data->id) {		case V4L2_SLICED_WSS_625:			if (saa711x_read(client, 0x6b) & 0xc0)				return -EIO;			data->data[0] = saa711x_read(client, 0x6c);			data->data[1] = saa711x_read(client, 0x6d);			return 0;		case V4L2_SLICED_CAPTION_525:			if (data->field == 0) {				/* CC */				if (saa711x_read(client, 0x66) & 0x30)					return -EIO;				data->data[0] = saa711x_read(client, 0x69);				data->data[1] = saa711x_read(client, 0x6a);				return 0;			}			/* XDS */			if (saa711x_read(client, 0x66) & 0xc0)				return -EIO;			data->data[0] = saa711x_read(client, 0x67);			data->data[1] = saa711x_read(client, 0x68);			return 0;		default:			return -EINVAL;		}		break;	}#ifdef CONFIG_VIDEO_ADV_DEBUG	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 = saa711x_read(client, reg->reg & 0xff);		else			saa711x_write(client, reg->reg & 0xff, reg->val & 0xff);		break;	}#endif	case VIDIOC_G_CHIP_IDENT:		return v4l2_chip_ident_i2c_client(client, arg, state->ident, 0);	default:		return -EINVAL;	}	return 0;}/* ----------------------------------------------------------------------- */static int saa7115_probe(struct i2c_client *client,			 const struct i2c_device_id *id){	struct saa711x_state *state;	int	i;	char	name[17];	char chip_id;#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)	int autodetect = !id || id->driver_data == 1;#endif	/* Check if the adapter supports the needed features */	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))		return -EIO;#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26)	snprintf(client->name, sizeof(client->name) - 1, "saa7115");#endif	for (i = 0; i < 0x0f; i++) {		saa711x_write(client, 0, i);		name[i] = (saa711x_read(client, 0) & 0x0f) + '0';		if (name[i] > '9')			name[i] += 'a' - '9' - 1;	}	name[i] = '\0';	chip_id = name[5];	/* Check whether this chip is part of the saa711x series */	if (memcmp(name, "1f711", 5)) {		v4l_dbg(1, debug, client, "chip found @ 0x%x (ID %s) does not match a known saa711x chip.\n",			client->addr << 1, name);		return -ENODEV;	}#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)	/* Safety check */	if (!autodetect && id->name[6] != chip_id) {		v4l_warn(client, "found saa711%c while %s was expected\n",			 chip_id, id->name);	}#endif	snprintf(client->name, sizeof(client->name), "saa711%c", chip_id);	v4l_info(client, "saa711%c found (%s) @ 0x%x (%s)\n", chip_id, name,		 client->addr << 1, client->adapter->name);	state = kzalloc(sizeof(struct saa711x_state), GFP_KERNEL);	if (state == NULL)		return -ENOMEM;	i2c_set_clientdata(client, state);	state->input = -1;	state->output = SAA7115_IPORT_ON;	state->enable = 1;	state->radio = 0;	state->bright = 128;	state->contrast = 64;	state->hue = 0;	state->sat = 64;	switch (chip_id) {	case '1':		state->ident = V4L2_IDENT_SAA7111;		break;	case '3':		state->ident = V4L2_IDENT_SAA7113;		break;	case '4':		state->ident = V4L2_IDENT_SAA7114;		break;	case '5':		state->ident = V4L2_IDENT_SAA7115;		break;	case '8':		state->ident = V4L2_IDENT_SAA7118;		break;	default:		state->ident = V4L2_IDENT_SAA7111;		v4l_info(client, "WARNING: Chip is not known - Falling back to saa7111\n");	}	state->audclk_freq = 48000;	v4l_dbg(1, debug, client, "writing init values\n");	/* init to 60hz/48khz */	state->crystal_freq = SAA7115_FREQ_24_576_MHZ;	switch (state->ident) {	case V4L2_IDENT_SAA7111:		saa711x_writeregs(client, saa7111_init);		break;	case V4L2_IDENT_SAA7113:		saa711x_writeregs(client, saa7113_init);		break;	default:		state->crystal_freq = SAA7115_FREQ_32_11_MHZ;		saa711x_writeregs(client, saa7115_init_auto_input);	}	if (state->ident != V4L2_IDENT_SAA7111)		saa711x_writeregs(client, saa7115_init_misc);	saa711x_set_v4lstd(client, V4L2_STD_NTSC);	v4l_dbg(1, debug, client, "status: (1E) 0x%02x, (1F) 0x%02x\n",		saa711x_read(client, R_1E_STATUS_BYTE_1_VD_DEC), saa711x_read(client, R_1F_STATUS_BYTE_2_VD_DEC));	return 0;}/* ----------------------------------------------------------------------- */static int saa7115_remove(struct i2c_client *client){	kfree(i2c_get_clientdata(client));	return 0;}#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)static const struct i2c_device_id saa7115_id[] = {	{ "saa7115_auto", 1 }, /* autodetect */	{ "saa7111", 0 },	{ "saa7113", 0 },	{ "saa7114", 0 },	{ "saa7115", 0 },	{ "saa7118", 0 },	{ }};MODULE_DEVICE_TABLE(i2c, saa7115_id);#endifstatic struct v4l2_i2c_driver_data v4l2_i2c_data = {	.name = "saa7115",	.driverid = I2C_DRIVERID_SAA711X,	.command = saa7115_command,	.probe = saa7115_probe,	.remove = saa7115_remove,	.legacy_class = I2C_CLASS_TV_ANALOG | I2C_CLASS_TV_DIGITAL,#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)	.id_table = saa7115_id,#endif};

⌨️ 快捷键说明

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