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

📄 saa6752hs.c

📁 底层驱动开发
💻 C
📖 第 1 页 / 共 2 页
字号:
#include <linux/module.h>#include <linux/kernel.h>#include <linux/sched.h>#include <linux/string.h>#include <linux/timer.h>#include <linux/delay.h>#include <linux/errno.h>#include <linux/slab.h>#include <linux/poll.h>#include <linux/i2c.h>#include <linux/types.h>#include <linux/videodev.h>#include <linux/init.h>#include <linux/crc32.h>#include <media/id.h>#define MPEG_VIDEO_TARGET_BITRATE_MAX  27000#define MPEG_VIDEO_MAX_BITRATE_MAX     27000#define MPEG_TOTAL_TARGET_BITRATE_MAX  27000#define MPEG_PID_MAX ((1 << 14) - 1)/* Addresses to scan */static unsigned short normal_i2c[] = {0x20, I2C_CLIENT_END};I2C_CLIENT_INSMOD;MODULE_DESCRIPTION("device driver for saa6752hs MPEG2 encoder");MODULE_AUTHOR("Andrew de Quincey");MODULE_LICENSE("GPL");static struct i2c_driver driver;static struct i2c_client client_template;enum saa6752hs_videoformat {	SAA6752HS_VF_D1 = 0,    /* standard D1 video format: 720x576 */	SAA6752HS_VF_2_3_D1 = 1,/* 2/3D1 video format: 480x576 */	SAA6752HS_VF_1_2_D1 = 2,/* 1/2D1 video format: 352x576 */	SAA6752HS_VF_SIF = 3,   /* SIF video format: 352x288 */	SAA6752HS_VF_UNKNOWN,};static const struct v4l2_format v4l2_format_table[] ={	[SAA6752HS_VF_D1] =		{ .fmt = { .pix = { .width = 720, .height = 576 }}},	[SAA6752HS_VF_2_3_D1] =		{ .fmt = { .pix = { .width = 480, .height = 576 }}},	[SAA6752HS_VF_1_2_D1] =		{ .fmt = { .pix = { .width = 352, .height = 576 }}},	[SAA6752HS_VF_SIF] =		{ .fmt = { .pix = { .width = 352, .height = 288 }}},	[SAA6752HS_VF_UNKNOWN] =		{ .fmt = { .pix = { .width = 0, .height = 0}}},};struct saa6752hs_state {	struct i2c_client             client;	struct v4l2_mpeg_compression  params;	enum saa6752hs_videoformat    video_format;};enum saa6752hs_command {	SAA6752HS_COMMAND_RESET = 0,    	SAA6752HS_COMMAND_STOP = 1,    	SAA6752HS_COMMAND_START = 2,    	SAA6752HS_COMMAND_PAUSE = 3,    	SAA6752HS_COMMAND_RECONFIGURE = 4,    	SAA6752HS_COMMAND_SLEEP = 5,	SAA6752HS_COMMAND_RECONFIGURE_FORCE = 6,	SAA6752HS_COMMAND_MAX};/* ---------------------------------------------------------------------- */static u8 PAT[] = {	0xc2, // i2c register	0x00, // table number for encoder	0x47, // sync	0x40, 0x00, // transport_error_indicator(0), payload_unit_start(1), transport_priority(0), pid(0)	0x10, // transport_scrambling_control(00), adaptation_field_control(01), continuity_counter(0)	0x00, // PSI pointer to start of table	0x00, // tid(0)	0xb0, 0x0d, // section_syntax_indicator(1), section_length(13)	0x00, 0x01, // transport_stream_id(1)	0xc1, // version_number(0), current_next_indicator(1)	0x00, 0x00, // section_number(0), last_section_number(0)	0x00, 0x01, // program_number(1)	0xe0, 0x00, // PMT PID	0x00, 0x00, 0x00, 0x00 // CRC32};static u8 PMT[] = {	0xc2, // i2c register	0x01, // table number for encoder	0x47, // sync	0x40, 0x00, // transport_error_indicator(0), payload_unit_start(1), transport_priority(0), pid	0x10, // transport_scrambling_control(00), adaptation_field_control(01), continuity_counter(0)	0x00, // PSI pointer to start of table	0x02, // tid(2)	0xb0, 0x17, // section_syntax_indicator(1), section_length(23)	0x00, 0x01, // program_number(1)	0xc1, // version_number(0), current_next_indicator(1)	0x00, 0x00, // section_number(0), last_section_number(0)	0xe0, 0x00, // PCR_PID	0xf0, 0x00, // program_info_length(0)	0x02, 0xe0, 0x00, 0xf0, 0x00, // video stream type(2), pid	0x04, 0xe0, 0x00, 0xf0, 0x00, // audio stream type(4), pid	0x00, 0x00, 0x00, 0x00 // CRC32};static struct v4l2_mpeg_compression param_defaults ={	.st_type         = V4L2_MPEG_TS_2,	.st_bitrate      = {		.mode    = V4L2_BITRATE_CBR,		.target  = 7000,	},	.ts_pid_pmt      = 16,	.ts_pid_video    = 260,	.ts_pid_audio    = 256,	.ts_pid_pcr      = 259,	.vi_type         = V4L2_MPEG_VI_2,	.vi_aspect_ratio = V4L2_MPEG_ASPECT_4_3,	.vi_bitrate      = {		.mode    = V4L2_BITRATE_VBR,		.target  = 4000,		.max     = 6000,	},	.au_type         = V4L2_MPEG_AU_2_II,	.au_bitrate      = {		.mode    = V4L2_BITRATE_CBR,		.target  = 256,	},};/* ---------------------------------------------------------------------- */static int saa6752hs_chip_command(struct i2c_client* client,				  enum saa6752hs_command command){	unsigned char buf[3];	unsigned long timeout;	int status = 0;	// execute the command	switch(command) {  	case SAA6752HS_COMMAND_RESET:  		buf[0] = 0x00;		break;	case SAA6752HS_COMMAND_STOP:	  	buf[0] = 0x03;		break;	case SAA6752HS_COMMAND_START:  		buf[0] = 0x02;		break;	case SAA6752HS_COMMAND_PAUSE:  		buf[0] = 0x04;		break;	case SAA6752HS_COMMAND_RECONFIGURE:		buf[0] = 0x05;		break;  	case SAA6752HS_COMMAND_SLEEP:  		buf[0] = 0x06;		break;  	case SAA6752HS_COMMAND_RECONFIGURE_FORCE:		buf[0] = 0x07;		break;	default:		return -EINVAL;	}  	// set it and wait for it to be so	i2c_master_send(client, buf, 1);	timeout = jiffies + HZ * 3;	for (;;) {		// get the current status		buf[0] = 0x10;	  	i2c_master_send(client, buf, 1);		i2c_master_recv(client, buf, 1);		if (!(buf[0] & 0x20))			break;		if (time_after(jiffies,timeout)) {			status = -ETIMEDOUT;			break;		}		// wait a bit		msleep(10);	}	// delay a bit to let encoder settle	msleep(50);	// done  	return status;}static int saa6752hs_set_bitrate(struct i2c_client* client,				 struct v4l2_mpeg_compression* params){  	u8 buf[3];	// set the bitrate mode	buf[0] = 0x71;	buf[1] = (params->vi_bitrate.mode == V4L2_BITRATE_VBR) ? 0 : 1;	i2c_master_send(client, buf, 2);	// set the video bitrate	if (params->vi_bitrate.mode == V4L2_BITRATE_VBR) {		// set the target bitrate		buf[0] = 0x80;	    	buf[1] = params->vi_bitrate.target >> 8;	  	buf[2] = params->vi_bitrate.target & 0xff;		i2c_master_send(client, buf, 3);		// set the max bitrate		buf[0] = 0x81;	    	buf[1] = params->vi_bitrate.max >> 8;	  	buf[2] = params->vi_bitrate.max & 0xff;		i2c_master_send(client, buf, 3);	} else {		// set the target bitrate (no max bitrate for CBR)  		buf[0] = 0x81;	    	buf[1] = params->vi_bitrate.target >> 8;	  	buf[2] = params->vi_bitrate.target & 0xff;		i2c_master_send(client, buf, 3);	}	// set the audio bitrate 	buf[0] = 0x94;	buf[1] = (256 == params->au_bitrate.target) ? 0 : 1;	i2c_master_send(client, buf, 2);	// set the total bitrate	buf[0] = 0xb1;  	buf[1] = params->st_bitrate.target >> 8;  	buf[2] = params->st_bitrate.target & 0xff;	i2c_master_send(client, buf, 3);	// return success	return 0;}static void saa6752hs_set_subsampling(struct i2c_client* client,				      struct v4l2_format* f){	struct saa6752hs_state *h = i2c_get_clientdata(client);	int dist_352, dist_480, dist_720;	/*	  FIXME: translate and round width/height into EMPRESS	  subsample type:	  type   |   PAL   |  NTSC	  ---------------------------	  SIF    | 352x288 | 352x240	  1/2 D1 | 352x576 | 352x480	  2/3 D1 | 480x576 | 480x480	  D1     | 720x576 | 720x480	*/	dist_352 = abs(f->fmt.pix.width - 352);	dist_480 = abs(f->fmt.pix.width - 480);	dist_720 = abs(f->fmt.pix.width - 720);	if (dist_720 < dist_480) {		f->fmt.pix.width = 720;		f->fmt.pix.height = 576;		h->video_format = SAA6752HS_VF_D1;	}	else if (dist_480 < dist_352) {		f->fmt.pix.width = 480;		f->fmt.pix.height = 576;		h->video_format = SAA6752HS_VF_2_3_D1;	}	else {		f->fmt.pix.width = 352;		if (abs(f->fmt.pix.height - 576) <		    abs(f->fmt.pix.height - 288)) {			f->fmt.pix.height = 576;			h->video_format = SAA6752HS_VF_1_2_D1;

⌨️ 快捷键说明

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