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

📄 saa6752hs.c

📁 trident tm5600的linux驱动
💻 C
📖 第 1 页 / 共 2 页
字号:
			    (!has_ac3 || new != V4L2_MPEG_AUDIO_ENCODING_AC3))				return -ERANGE;			new = old;			break;		case V4L2_CID_MPEG_AUDIO_L2_BITRATE:			old = params->au_l2_bitrate;			if (set && new != V4L2_MPEG_AUDIO_L2_BITRATE_256K &&				   new != V4L2_MPEG_AUDIO_L2_BITRATE_384K)				return -ERANGE;			if (new <= V4L2_MPEG_AUDIO_L2_BITRATE_256K)				new = V4L2_MPEG_AUDIO_L2_BITRATE_256K;			else				new = V4L2_MPEG_AUDIO_L2_BITRATE_384K;			params->au_l2_bitrate = new;			break;		case V4L2_CID_MPEG_AUDIO_AC3_BITRATE:			if (!has_ac3)				return -EINVAL;			old = params->au_ac3_bitrate;			if (set && new != V4L2_MPEG_AUDIO_AC3_BITRATE_256K &&				   new != V4L2_MPEG_AUDIO_AC3_BITRATE_384K)				return -ERANGE;			if (new <= V4L2_MPEG_AUDIO_AC3_BITRATE_256K)				new = V4L2_MPEG_AUDIO_AC3_BITRATE_256K;			else				new = V4L2_MPEG_AUDIO_AC3_BITRATE_384K;			params->au_ac3_bitrate = new;			break;		case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ:			old = V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000;			if (set && new != old)				return -ERANGE;			new = old;			break;		case V4L2_CID_MPEG_VIDEO_ENCODING:			old = V4L2_MPEG_VIDEO_ENCODING_MPEG_2;			if (set && new != old)				return -ERANGE;			new = old;			break;		case V4L2_CID_MPEG_VIDEO_ASPECT:			old = params->vi_aspect;			if (set && new != V4L2_MPEG_VIDEO_ASPECT_16x9 &&				   new != V4L2_MPEG_VIDEO_ASPECT_4x3)				return -ERANGE;			if (new != V4L2_MPEG_VIDEO_ASPECT_16x9)				new = V4L2_MPEG_VIDEO_ASPECT_4x3;			params->vi_aspect = new;			break;		case V4L2_CID_MPEG_VIDEO_BITRATE:			old = params->vi_bitrate * 1000;			new = 1000 * (new / 1000);			if (set && new > MPEG_VIDEO_TARGET_BITRATE_MAX * 1000)				return -ERANGE;			if (new > MPEG_VIDEO_TARGET_BITRATE_MAX * 1000)				new = MPEG_VIDEO_TARGET_BITRATE_MAX * 1000;			params->vi_bitrate = new / 1000;			break;		case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:			old = params->vi_bitrate_peak * 1000;			new = 1000 * (new / 1000);			if (set && new > MPEG_VIDEO_TARGET_BITRATE_MAX * 1000)				return -ERANGE;			if (new > MPEG_VIDEO_TARGET_BITRATE_MAX * 1000)				new = MPEG_VIDEO_TARGET_BITRATE_MAX * 1000;			params->vi_bitrate_peak = new / 1000;			break;		case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:			old = params->vi_bitrate_mode;			params->vi_bitrate_mode = new;			break;		default:			return -EINVAL;	}	if (cmd == VIDIOC_G_EXT_CTRLS)		ctrl->value = old;	else		ctrl->value = new;	return 0;}static int saa6752hs_qctrl(struct saa6752hs_state *h,		struct v4l2_queryctrl *qctrl){	struct saa6752hs_mpeg_params *params = &h->params;	int err;	switch (qctrl->id) {	case V4L2_CID_MPEG_AUDIO_ENCODING:		return v4l2_ctrl_query_fill(qctrl,				V4L2_MPEG_AUDIO_ENCODING_LAYER_2,				h->has_ac3 ? V4L2_MPEG_AUDIO_ENCODING_AC3 :					V4L2_MPEG_AUDIO_ENCODING_LAYER_2,				1, V4L2_MPEG_AUDIO_ENCODING_LAYER_2);	case V4L2_CID_MPEG_AUDIO_L2_BITRATE:		return v4l2_ctrl_query_fill(qctrl,				V4L2_MPEG_AUDIO_L2_BITRATE_256K,				V4L2_MPEG_AUDIO_L2_BITRATE_384K, 1,				V4L2_MPEG_AUDIO_L2_BITRATE_256K);	case V4L2_CID_MPEG_AUDIO_AC3_BITRATE:		if (!h->has_ac3)			return -EINVAL;		return v4l2_ctrl_query_fill(qctrl,				V4L2_MPEG_AUDIO_AC3_BITRATE_256K,				V4L2_MPEG_AUDIO_AC3_BITRATE_384K, 1,				V4L2_MPEG_AUDIO_AC3_BITRATE_256K);	case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ:		return v4l2_ctrl_query_fill(qctrl,				V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000,				V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000, 1,				V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000);	case V4L2_CID_MPEG_VIDEO_ENCODING:		return v4l2_ctrl_query_fill(qctrl,				V4L2_MPEG_VIDEO_ENCODING_MPEG_2,				V4L2_MPEG_VIDEO_ENCODING_MPEG_2, 1,				V4L2_MPEG_VIDEO_ENCODING_MPEG_2);	case V4L2_CID_MPEG_VIDEO_ASPECT:		return v4l2_ctrl_query_fill(qctrl,				V4L2_MPEG_VIDEO_ASPECT_4x3,				V4L2_MPEG_VIDEO_ASPECT_16x9, 1,				V4L2_MPEG_VIDEO_ASPECT_4x3);	case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:		err = v4l2_ctrl_query_fill_std(qctrl);		if (err == 0 &&		    params->vi_bitrate_mode ==				V4L2_MPEG_VIDEO_BITRATE_MODE_CBR)			qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;		return err;	case V4L2_CID_MPEG_STREAM_TYPE:		return v4l2_ctrl_query_fill(qctrl,				V4L2_MPEG_STREAM_TYPE_MPEG2_TS,				V4L2_MPEG_STREAM_TYPE_MPEG2_TS, 1,				V4L2_MPEG_STREAM_TYPE_MPEG2_TS);	case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:	case V4L2_CID_MPEG_VIDEO_BITRATE:	case V4L2_CID_MPEG_STREAM_PID_PMT:	case V4L2_CID_MPEG_STREAM_PID_AUDIO:	case V4L2_CID_MPEG_STREAM_PID_VIDEO:	case V4L2_CID_MPEG_STREAM_PID_PCR:		return v4l2_ctrl_query_fill_std(qctrl);	default:		break;	}	return -EINVAL;}static int saa6752hs_qmenu(struct saa6752hs_state *h,		struct v4l2_querymenu *qmenu){	static const u32 mpeg_audio_encoding[] = {		V4L2_MPEG_AUDIO_ENCODING_LAYER_2,		V4L2_CTRL_MENU_IDS_END	};	static const u32 mpeg_audio_ac3_encoding[] = {		V4L2_MPEG_AUDIO_ENCODING_LAYER_2,		V4L2_MPEG_AUDIO_ENCODING_AC3,		V4L2_CTRL_MENU_IDS_END	};	static u32 mpeg_audio_l2_bitrate[] = {		V4L2_MPEG_AUDIO_L2_BITRATE_256K,		V4L2_MPEG_AUDIO_L2_BITRATE_384K,		V4L2_CTRL_MENU_IDS_END	};	static u32 mpeg_audio_ac3_bitrate[] = {		V4L2_MPEG_AUDIO_AC3_BITRATE_256K,		V4L2_MPEG_AUDIO_AC3_BITRATE_384K,		V4L2_CTRL_MENU_IDS_END	};	struct v4l2_queryctrl qctrl;	int err;	qctrl.id = qmenu->id;	err = saa6752hs_qctrl(h, &qctrl);	if (err)		return err;	switch (qmenu->id) {	case V4L2_CID_MPEG_AUDIO_L2_BITRATE:		return v4l2_ctrl_query_menu_valid_items(qmenu,				mpeg_audio_l2_bitrate);	case V4L2_CID_MPEG_AUDIO_AC3_BITRATE:		if (!h->has_ac3)			return -EINVAL;		return v4l2_ctrl_query_menu_valid_items(qmenu,				mpeg_audio_ac3_bitrate);	case V4L2_CID_MPEG_AUDIO_ENCODING:		return v4l2_ctrl_query_menu_valid_items(qmenu,			h->has_ac3 ? mpeg_audio_ac3_encoding :				mpeg_audio_encoding);	}	return v4l2_ctrl_query_menu(qmenu, &qctrl, NULL);}static int saa6752hs_init(struct i2c_client *client, u32 leading_null_bytes){	unsigned char buf[9], buf2[4];	struct saa6752hs_state *h;	unsigned size;	u32 crc;	unsigned char localPAT[256];	unsigned char localPMT[256];	h = i2c_get_clientdata(client);	/* Set video format - must be done first as it resets other settings */	set_reg8(client, 0x41, h->video_format);	/* Set number of lines in input signal */	set_reg8(client, 0x40, (h->standard & V4L2_STD_525_60) ? 1 : 0);	/* set bitrate */	saa6752hs_set_bitrate(client, h);	/* Set GOP structure {3, 13} */	set_reg16(client, 0x72, 0x030d);	/* Set minimum Q-scale {4} */	set_reg8(client, 0x82, 0x04);	/* Set maximum Q-scale {12} */	set_reg8(client, 0x83, 0x0c);	/* Set Output Protocol */	set_reg8(client, 0xd0, 0x81);	/* Set video output stream format {TS} */	set_reg8(client, 0xb0, 0x05);	/* Set leading null byte for TS */	set_reg16(client, 0xf6, leading_null_bytes);	/* compute PAT */	memcpy(localPAT, PAT, sizeof(PAT));	localPAT[17] = 0xe0 | ((h->params.ts_pid_pmt >> 8) & 0x0f);	localPAT[18] = h->params.ts_pid_pmt & 0xff;	crc = crc32_be(~0, &localPAT[7], sizeof(PAT) - 7 - 4);	localPAT[sizeof(PAT) - 4] = (crc >> 24) & 0xFF;	localPAT[sizeof(PAT) - 3] = (crc >> 16) & 0xFF;	localPAT[sizeof(PAT) - 2] = (crc >> 8) & 0xFF;	localPAT[sizeof(PAT) - 1] = crc & 0xFF;	/* compute PMT */	if (h->params.au_encoding == V4L2_MPEG_AUDIO_ENCODING_AC3) {		size = sizeof(PMT_AC3);		memcpy(localPMT, PMT_AC3, size);	} else {		size = sizeof(PMT);		memcpy(localPMT, PMT, size);	}	localPMT[3] = 0x40 | ((h->params.ts_pid_pmt >> 8) & 0x0f);	localPMT[4] = h->params.ts_pid_pmt & 0xff;	localPMT[15] = 0xE0 | ((h->params.ts_pid_pcr >> 8) & 0x0F);	localPMT[16] = h->params.ts_pid_pcr & 0xFF;	localPMT[20] = 0xE0 | ((h->params.ts_pid_video >> 8) & 0x0F);	localPMT[21] = h->params.ts_pid_video & 0xFF;	localPMT[25] = 0xE0 | ((h->params.ts_pid_audio >> 8) & 0x0F);	localPMT[26] = h->params.ts_pid_audio & 0xFF;	crc = crc32_be(~0, &localPMT[7], size - 7 - 4);	localPMT[size - 4] = (crc >> 24) & 0xFF;	localPMT[size - 3] = (crc >> 16) & 0xFF;	localPMT[size - 2] = (crc >> 8) & 0xFF;	localPMT[size - 1] = crc & 0xFF;	/* Set Audio PID */	set_reg16(client, 0xc1, h->params.ts_pid_audio);	/* Set Video PID */	set_reg16(client, 0xc0, h->params.ts_pid_video);	/* Set PCR PID */	set_reg16(client, 0xc4, h->params.ts_pid_pcr);	/* Send SI tables */	i2c_master_send(client, localPAT, sizeof(PAT));	i2c_master_send(client, localPMT, size);	/* mute then unmute audio. This removes buzzing artefacts */	set_reg8(client, 0xa4, 1);	set_reg8(client, 0xa4, 0);	/* start it going */	saa6752hs_chip_command(client, SAA6752HS_COMMAND_START);	/* readout current state */	buf[0] = 0xE1;	buf[1] = 0xA7;	buf[2] = 0xFE;	buf[3] = 0x82;	buf[4] = 0xB0;	i2c_master_send(client, buf, 5);	i2c_master_recv(client, buf2, 4);	/* change aspect ratio */	buf[0] = 0xE0;	buf[1] = 0xA7;	buf[2] = 0xFE;	buf[3] = 0x82;	buf[4] = 0xB0;	buf[5] = buf2[0];	switch(h->params.vi_aspect) {	case V4L2_MPEG_VIDEO_ASPECT_16x9:		buf[6] = buf2[1] | 0x40;		break;	case V4L2_MPEG_VIDEO_ASPECT_4x3:	default:		buf[6] = buf2[1] & 0xBF;		break;		break;	}	buf[7] = buf2[2];	buf[8] = buf2[3];	i2c_master_send(client, buf, 9);	return 0;}static intsaa6752hs_command(struct i2c_client *client, unsigned int cmd, void *arg){	struct saa6752hs_state *h = i2c_get_clientdata(client);	struct v4l2_ext_controls *ctrls = arg;	struct saa6752hs_mpeg_params params;	int err = 0;	int i;	switch (cmd) {	case VIDIOC_INT_INIT:		/* apply settings and start encoder */		saa6752hs_init(client, *(u32 *)arg);		break;	case VIDIOC_S_EXT_CTRLS:		if (ctrls->ctrl_class != V4L2_CTRL_CLASS_MPEG)			return -EINVAL;		/* fall through */	case VIDIOC_TRY_EXT_CTRLS:	case VIDIOC_G_EXT_CTRLS:		if (ctrls->ctrl_class != V4L2_CTRL_CLASS_MPEG)			return -EINVAL;		params = h->params;		for (i = 0; i < ctrls->count; i++) {			err = handle_ctrl(h->has_ac3, &params, ctrls->controls + i, cmd);			if (err) {				ctrls->error_idx = i;				return err;			}		}		h->params = params;		break;	case VIDIOC_QUERYCTRL:		return saa6752hs_qctrl(h, arg);	case VIDIOC_QUERYMENU:		return saa6752hs_qmenu(h, arg);	case VIDIOC_G_FMT:	{	   struct v4l2_format *f = arg;	   if (h->video_format == SAA6752HS_VF_UNKNOWN)		   h->video_format = SAA6752HS_VF_D1;	   f->fmt.pix.width =		   v4l2_format_table[h->video_format].fmt.pix.width;	   f->fmt.pix.height =		   v4l2_format_table[h->video_format].fmt.pix.height;	   break ;	}	case VIDIOC_S_FMT:	{		struct v4l2_format *f = arg;		saa6752hs_set_subsampling(client, f);		break;	}	case VIDIOC_S_STD:		h->standard = *((v4l2_std_id *) arg);		break;	case VIDIOC_G_CHIP_IDENT:		return v4l2_chip_ident_i2c_client(client,				arg, h->chip, h->revision);	default:		/* nothing */		break;	}	return err;}static int saa6752hs_probe(struct i2c_client *client,			const struct i2c_device_id *id){	struct saa6752hs_state *h = kzalloc(sizeof(*h), GFP_KERNEL);	u8 addr = 0x13;	u8 data[12];	v4l_info(client, "chip found @ 0x%x (%s)\n",			client->addr << 1, client->adapter->name);	if (h == NULL)		return -ENOMEM;	i2c_master_send(client, &addr, 1);	i2c_master_recv(client, data, sizeof(data));	h->chip = V4L2_IDENT_SAA6752HS;	h->revision = (data[8] << 8) | data[9];	h->has_ac3 = 0;	if (h->revision == 0x0206) {		h->chip = V4L2_IDENT_SAA6752HS_AC3;		h->has_ac3 = 1;		v4l_info(client, "support AC-3\n");	}	h->params = param_defaults;	h->standard = 0; /* Assume 625 input lines */	i2c_set_clientdata(client, h);	return 0;}static int saa6752hs_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 saa6752hs_id[] = {	{ "saa6752hs", 0 },	{ }};MODULE_DEVICE_TABLE(i2c, saa6752hs_id);#endifstatic struct v4l2_i2c_driver_data v4l2_i2c_data = {	.name = "saa6752hs",	.driverid = I2C_DRIVERID_SAA6752HS,	.command = saa6752hs_command,	.probe = saa6752hs_probe,	.remove = saa6752hs_remove,#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)	.id_table = saa6752hs_id,#endif};/* * Overrides for Emacs so that we follow Linus's tabbing style. * --------------------------------------------------------------------------- * Local variables: * c-basic-offset: 8 * End: */

⌨️ 快捷键说明

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