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

📄 saa7115.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
		break;	case 4:		if (!saa711x_odd_parity(p[0]) || !saa711x_odd_parity(p[1]))			return;		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 saa711x_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;		v4l_dbg(1, debug, client, "decoder set input %d output %d\n", route->input, route->output);		/* saa7113 does not have these inputs */		if (state->ident == V4L2_IDENT_SAA7113 &&		    (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;		/* select mode */		saa711x_write(client, R_02_INPUT_CNTL_1,			      (saa711x_read(client, R_02_INPUT_CNTL_1) & 0xf0) |			       state->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_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 struct i2c_driver i2c_driver_saa711x;static int saa711x_attach(struct i2c_adapter *adapter, int address, int kind){	struct i2c_client *client;	struct saa711x_state *state;	int	i;	char	name[17];	u8 chip_id;	/* Check if the adapter supports the needed features */	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))		return 0;	client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);	if (client == 0)		return -ENOMEM;	client->addr = address;	client->adapter = adapter;	client->driver = &i2c_driver_saa711x;	snprintf(client->name, sizeof(client->name) - 1, "saa7115");	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';	saa711x_write(client, 0, 5);	chip_id = saa711x_read(client, 0) & 0x0f;	/* 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",			address << 1, name);		kfree(client);		return 0;	}	snprintf(client->name, sizeof(client->name) - 1, "saa711%d",chip_id);	v4l_info(client, "saa711%d found (%s) @ 0x%x (%s)\n", chip_id, name, address << 1, adapter->name);	state = kzalloc(sizeof(struct saa711x_state), GFP_KERNEL);	i2c_set_clientdata(client, state);	if (state == NULL) {		kfree(client);		return -ENOMEM;	}	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);	}	saa711x_writeregs(client, saa7115_init_misc);	saa711x_set_v4lstd(client, V4L2_STD_NTSC);	i2c_attach_client(client);	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 saa711x_probe(struct i2c_adapter *adapter){	if (adapter->class & I2C_CLASS_TV_ANALOG || adapter->class & I2C_CLASS_TV_DIGITAL)		return i2c_probe(adapter, &addr_data, &saa711x_attach);	return 0;}static int saa711x_detach(struct i2c_client *client){	struct saa711x_state *state = i2c_get_clientdata(client);	int err;	err = i2c_detach_client(client);	if (err) {		return err;	}	kfree(state);	kfree(client);	return 0;}/* ----------------------------------------------------------------------- *//* i2c implementation */static struct i2c_driver i2c_driver_saa711x = {	.driver = {		.name = "saa7115",	},	.id = I2C_DRIVERID_SAA711X,	.attach_adapter = saa711x_probe,	.detach_client = saa711x_detach,	.command = saa711x_command,};static int __init saa711x_init_module(void){	return i2c_add_driver(&i2c_driver_saa711x);}static void __exit saa711x_cleanup_module(void){	i2c_del_driver(&i2c_driver_saa711x);}module_init(saa711x_init_module);module_exit(saa711x_cleanup_module);

⌨️ 快捷键说明

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