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

📄 saa7134-video.c

📁 优龙2410linux2.6.8内核源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * device driver for philips saa7134 based TV cards * video4linux video interface * * (c) 2001-03 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs] * *  This program is free software; you can redistribute it and/or modify *  it under the terms of the GNU General Public License as published by *  the Free Software Foundation; either version 2 of the License, or *  (at your option) any later version. * *  This program is distributed in the hope that it will be useful, *  but WITHOUT ANY WARRANTY; without even the implied warranty of *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *  GNU General Public License for more details. * *  You should have received a copy of the GNU General Public License *  along with this program; if not, write to the Free Software *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */#include <linux/init.h>#include <linux/list.h>#include <linux/module.h>#include <linux/kernel.h>#include <linux/slab.h>#include "saa7134-reg.h"#include "saa7134.h"#define V4L2_I2C_CLIENTS 1/* ------------------------------------------------------------------ */static unsigned int video_debug   = 0;static unsigned int gbuffers      = 8;static unsigned int noninterlaced = 0;static unsigned int gbufsize      = 720*576*4;static unsigned int gbufsize_max  = 720*576*4;MODULE_PARM(video_debug,"i");MODULE_PARM_DESC(video_debug,"enable debug messages [video]");MODULE_PARM(gbuffers,"i");MODULE_PARM_DESC(gbuffers,"number of capture buffers, range 2-32");MODULE_PARM(noninterlaced,"i");MODULE_PARM_DESC(noninterlaced,"video input is noninterlaced");#define dprintk(fmt, arg...)	if (video_debug) \	printk(KERN_DEBUG "%s/video: " fmt, dev->name , ## arg)/* ------------------------------------------------------------------ *//* data structs for video                                             */static int video_out[][9] = {	[CCIR656] = { 0x00, 0xb1, 0x00, 0xa1, 0x00, 0x04, 0x06, 0x00, 0x00 },};		static struct saa7134_format formats[] = {	{		.name     = "8 bpp gray",		.fourcc   = V4L2_PIX_FMT_GREY,		.depth    = 8,		.pm       = 0x06,	},{		.name     = "15 bpp RGB, le",		.fourcc   = V4L2_PIX_FMT_RGB555,		.depth    = 16,		.pm       = 0x13 | 0x80,	},{		.name     = "15 bpp RGB, be",		.fourcc   = V4L2_PIX_FMT_RGB555X,		.depth    = 16,		.pm       = 0x13 | 0x80,		.bswap    = 1,	},{		.name     = "16 bpp RGB, le",		.fourcc   = V4L2_PIX_FMT_RGB565,		.depth    = 16,		.pm       = 0x10 | 0x80,	},{		.name     = "16 bpp RGB, be",		.fourcc   = V4L2_PIX_FMT_RGB565X,		.depth    = 16,		.pm       = 0x10 | 0x80,		.bswap    = 1,	},{		.name     = "24 bpp RGB, le",		.fourcc   = V4L2_PIX_FMT_BGR24,		.depth    = 24,		.pm       = 0x11,	},{		.name     = "24 bpp RGB, be",		.fourcc   = V4L2_PIX_FMT_RGB24,		.depth    = 24,		.pm       = 0x11,		.bswap    = 1,	},{		.name     = "32 bpp RGB, le",		.fourcc   = V4L2_PIX_FMT_BGR32,		.depth    = 32,		.pm       = 0x12,	},{		.name     = "32 bpp RGB, be",		.fourcc   = V4L2_PIX_FMT_RGB32,		.depth    = 32,		.pm       = 0x12,		.bswap    = 1,		.wswap    = 1,	},{		.name     = "4:2:2 packed, YUYV",		.fourcc   = V4L2_PIX_FMT_YUYV,		.depth    = 16,		.pm       = 0x00,		.bswap    = 1,		.yuv      = 1,	},{		.name     = "4:2:2 packed, UYVY",		.fourcc   = V4L2_PIX_FMT_UYVY,		.depth    = 16,		.pm       = 0x00,		.yuv      = 1,	},{		.name     = "4:2:2 planar, Y-Cb-Cr",		.fourcc   = V4L2_PIX_FMT_YUV422P,		.depth    = 16,		.pm       = 0x09,		.yuv      = 1,		.planar   = 1,		.hshift   = 1,		.vshift   = 0,	},{		.name     = "4:2:0 planar, Y-Cb-Cr",		.fourcc   = V4L2_PIX_FMT_YUV420,		.depth    = 12,		.pm       = 0x0a,		.yuv      = 1,		.planar   = 1,		.hshift   = 1,		.vshift   = 1,	},{		.name     = "4:2:0 planar, Y-Cb-Cr",		.fourcc   = V4L2_PIX_FMT_YVU420,		.depth    = 12,		.pm       = 0x0a,		.yuv      = 1,		.planar   = 1,		.uvswap   = 1,		.hshift   = 1,		.vshift   = 1,	}};#define FORMATS ARRAY_SIZE(formats)#define NORM_625_50			\		.h_start       = 0,	\		.h_stop        = 719,	\		.video_v_start = 24,	\		.video_v_stop  = 311,	\		.vbi_v_start   = 7,	\		.vbi_v_stop    = 22,	\		.src_timing    = 4#define NORM_525_60			\		.h_start       = 0,	\		.h_stop        = 703,	\		.video_v_start = 22,	\		.video_v_stop  = 22+239, \		.vbi_v_start   = 10, /* FIXME */ \		.vbi_v_stop    = 21, /* FIXME */ \		.src_timing    = 1static struct saa7134_tvnorm tvnorms[] = {	{		.name          = "PAL", /* autodetect */		.id            = V4L2_STD_PAL,		NORM_625_50,		.sync_control  = 0x18,		.luma_control  = 0x40,		.chroma_ctrl1  = 0x81,		.chroma_gain   = 0x2a,		.chroma_ctrl2  = 0x06,		.vgate_misc    = 0x1c,	},{		.name          = "PAL-BG",		.id            = V4L2_STD_PAL_BG,		NORM_625_50,		.sync_control  = 0x18,		.luma_control  = 0x40,		.chroma_ctrl1  = 0x81,		.chroma_gain   = 0x2a,		.chroma_ctrl2  = 0x06,		.vgate_misc    = 0x1c,	},{		.name          = "PAL-I",		.id            = V4L2_STD_PAL_I,		NORM_625_50,		.sync_control  = 0x18,		.luma_control  = 0x40,		.chroma_ctrl1  = 0x81,		.chroma_gain   = 0x2a,		.chroma_ctrl2  = 0x06,		.vgate_misc    = 0x1c,	},{		.name          = "PAL-DK",		.id            = V4L2_STD_PAL_DK,		NORM_625_50,		.sync_control  = 0x18,		.luma_control  = 0x40,		.chroma_ctrl1  = 0x81,		.chroma_gain   = 0x2a,		.chroma_ctrl2  = 0x06,		.vgate_misc    = 0x1c,	},{		.name          = "NTSC",		.id            = V4L2_STD_NTSC,		NORM_525_60,		.sync_control  = 0x59,		.luma_control  = 0x40,		.chroma_ctrl1  = 0x89,		.chroma_gain   = 0x2a,		.chroma_ctrl2  = 0x0e,		.vgate_misc    = 0x18,	},{		.name          = "SECAM",		.id            = V4L2_STD_SECAM,		NORM_625_50,		.sync_control  = 0x18, /* old: 0x58, */		.luma_control  = 0x1b,		.chroma_ctrl1  = 0xd1,		.chroma_gain   = 0x80,		.chroma_ctrl2  = 0x00,		.vgate_misc    = 0x1c,	},{		.name          = "PAL-M",		.id            = V4L2_STD_PAL_M,		NORM_525_60,		.sync_control  = 0x59,		.luma_control  = 0x40,		.chroma_ctrl1  = 0xb9,		.chroma_gain   = 0x2a,		.chroma_ctrl2  = 0x0e,		.vgate_misc    = 0x18,	},{		.name          = "PAL-Nc",		.id            = V4L2_STD_PAL_Nc,		NORM_625_50,		.sync_control  = 0x18,		.luma_control  = 0x40,		.chroma_ctrl1  = 0xa1,		.chroma_gain   = 0x2a,		.chroma_ctrl2  = 0x06,		.vgate_misc    = 0x1c,	}};#define TVNORMS ARRAY_SIZE(tvnorms)#define V4L2_CID_PRIVATE_INVERT      (V4L2_CID_PRIVATE_BASE + 0)#define V4L2_CID_PRIVATE_Y_ODD       (V4L2_CID_PRIVATE_BASE + 1)#define V4L2_CID_PRIVATE_Y_EVEN      (V4L2_CID_PRIVATE_BASE + 2)#define V4L2_CID_PRIVATE_LASTP1      (V4L2_CID_PRIVATE_BASE + 3)static const struct v4l2_queryctrl no_ctrl = {	.name  = "42",	.flags = V4L2_CTRL_FLAG_DISABLED,};static const struct v4l2_queryctrl video_ctrls[] = {	/* --- video --- */	{		.id            = V4L2_CID_BRIGHTNESS,		.name          = "Brightness",		.minimum       = 0,		.maximum       = 255,		.step          = 1,		.default_value = 128,		.type          = V4L2_CTRL_TYPE_INTEGER,	},{		.id            = V4L2_CID_CONTRAST,		.name          = "Contrast",		.minimum       = 0,		.maximum       = 127,		.step          = 1,		.default_value = 68,		.type          = V4L2_CTRL_TYPE_INTEGER,	},{		.id            = V4L2_CID_SATURATION,		.name          = "Saturation",		.minimum       = 0,		.maximum       = 127,		.step          = 1,		.default_value = 64,		.type          = V4L2_CTRL_TYPE_INTEGER,	},{		.id            = V4L2_CID_HUE,		.name          = "Hue",		.minimum       = -128,		.maximum       = 127,		.step          = 1,		.default_value = 0,		.type          = V4L2_CTRL_TYPE_INTEGER,	},{		.id            = V4L2_CID_VFLIP,		.name          = "vertical flip",		.minimum       = 0,		.maximum       = 1,		.type          = V4L2_CTRL_TYPE_BOOLEAN,	},	/* --- audio --- */	{		.id            = V4L2_CID_AUDIO_MUTE,		.name          = "Mute",		.minimum       = 0,		.maximum       = 1,		.type          = V4L2_CTRL_TYPE_BOOLEAN,	},{		.id            = V4L2_CID_AUDIO_VOLUME,		.name          = "Volume",		.minimum       = -15,		.maximum       = 15,		.step          = 1,		.default_value = 0,		.type          = V4L2_CTRL_TYPE_INTEGER,	},	/* --- private --- */	{		.id            = V4L2_CID_PRIVATE_INVERT,		.name          = "Invert",		.minimum       = 0,		.maximum       = 1,		.type          = V4L2_CTRL_TYPE_BOOLEAN,	},{		.id            = V4L2_CID_PRIVATE_Y_ODD,		.name          = "y offset odd field",		.minimum       = 0,		.maximum       = 128,		.default_value = 0,		.type          = V4L2_CTRL_TYPE_INTEGER,	},{		.id            = V4L2_CID_PRIVATE_Y_EVEN,		.name          = "y offset even field",		.minimum       = 0,		.maximum       = 128,		.default_value = 0,		.type          = V4L2_CTRL_TYPE_INTEGER,	}};static const unsigned int CTRLS = ARRAY_SIZE(video_ctrls);static const struct v4l2_queryctrl* ctrl_by_id(unsigned int id){	unsigned int i;		for (i = 0; i < CTRLS; i++)		if (video_ctrls[i].id == id)			return video_ctrls+i;	return NULL;}static struct saa7134_format* format_by_fourcc(unsigned int fourcc){	unsigned int i;	for (i = 0; i < FORMATS; i++)		if (formats[i].fourcc == fourcc)			return formats+i;	return NULL;}/* ----------------------------------------------------------------------- *//* resource management                                                     */static int res_get(struct saa7134_dev *dev, struct saa7134_fh *fh, unsigned int bit){	if (fh->resources & bit)		/* have it already allocated */		return 1;	/* is it free? */	down(&dev->lock);	if (dev->resources & bit) {		/* no, someone else uses it */		up(&dev->lock);		return 0;	}	/* it's free, grab it */	fh->resources  |= bit;	dev->resources |= bit;	dprintk("res: get %d\n",bit);	up(&dev->lock);	return 1;}staticint res_check(struct saa7134_fh *fh, unsigned int bit){	return (fh->resources & bit);}staticint res_locked(struct saa7134_dev *dev, unsigned int bit){	return (dev->resources & bit);}staticvoid res_free(struct saa7134_dev *dev, struct saa7134_fh *fh, unsigned int bits){	if ((fh->resources & bits) != bits)		BUG();	down(&dev->lock);	fh->resources  &= ~bits;	dev->resources &= ~bits;	dprintk("res: put %d\n",bits);	up(&dev->lock);}/* ------------------------------------------------------------------ */static void set_tvnorm(struct saa7134_dev *dev, struct saa7134_tvnorm *norm){	int luma_control,sync_control,mux;	dprintk("set tv norm = %s\n",norm->name);	dev->tvnorm = norm;	mux = card_in(dev,dev->ctl_input).vmux;	luma_control = norm->luma_control;	sync_control = norm->sync_control;	if (mux > 5)		luma_control |= 0x80; /* svideo */	if (noninterlaced)		sync_control |= 0x20;	/* setup cropping */	dev->crop_bounds.left    = norm->h_start;	dev->crop_defrect.left   = norm->h_start;	dev->crop_bounds.width   = norm->h_stop - norm->h_start +1;	dev->crop_defrect.width  = norm->h_stop - norm->h_start +1;	dev->crop_bounds.top     = (norm->vbi_v_stop+1)*2;	dev->crop_defrect.top    = norm->video_v_start*2;	dev->crop_bounds.height  = ((norm->id & V4L2_STD_525_60) ? 524 : 624)		- dev->crop_bounds.top;	dev->crop_defrect.height = (norm->video_v_stop - norm->video_v_start +1)*2;	dev->crop_current = dev->crop_defrect;	/* setup video decoder */	saa_writeb(SAA7134_INCR_DELAY,            0x08);	saa_writeb(SAA7134_ANALOG_IN_CTRL1,       0xc0 | mux);	saa_writeb(SAA7134_ANALOG_IN_CTRL2,       0x00);	saa_writeb(SAA7134_ANALOG_IN_CTRL3,       0x90);	saa_writeb(SAA7134_ANALOG_IN_CTRL4,       0x90);	saa_writeb(SAA7134_HSYNC_START,           0xeb);	saa_writeb(SAA7134_HSYNC_STOP,            0xe0);	saa_writeb(SAA7134_SOURCE_TIMING1,        norm->src_timing);		saa_writeb(SAA7134_SYNC_CTRL,             sync_control);	saa_writeb(SAA7134_LUMA_CTRL,             luma_control);	saa_writeb(SAA7134_DEC_LUMA_BRIGHT,       dev->ctl_bright);	saa_writeb(SAA7134_DEC_LUMA_CONTRAST,     dev->ctl_contrast); 	saa_writeb(SAA7134_DEC_CHROMA_SATURATION, dev->ctl_saturation);	saa_writeb(SAA7134_DEC_CHROMA_HUE,        dev->ctl_hue);	saa_writeb(SAA7134_CHROMA_CTRL1,          norm->chroma_ctrl1);	saa_writeb(SAA7134_CHROMA_GAIN,           norm->chroma_gain);	saa_writeb(SAA7134_CHROMA_CTRL2,          norm->chroma_ctrl2);	saa_writeb(SAA7134_MODE_DELAY_CTRL,       0x00);	saa_writeb(SAA7134_ANALOG_ADC,            0x01);	saa_writeb(SAA7134_VGATE_START,           0x11);	saa_writeb(SAA7134_VGATE_STOP,            0xfe);	saa_writeb(SAA7134_MISC_VGATE_MSB,        norm->vgate_misc);	saa_writeb(SAA7134_RAW_DATA_GAIN,         0x40);	saa_writeb(SAA7134_RAW_DATA_OFFSET,       0x80);#ifdef V4L2_I2C_CLIENTS	saa7134_i2c_call_clients(dev,VIDIOC_S_STD,&norm->id);#else	{		/* pass down info to the i2c chips (v4l1) */		struct video_channel c;		memset(&c,0,sizeof(c));		c.channel = dev->ctl_input;		c.norm = VIDEO_MODE_PAL;		if (norm->id & V4L2_STD_NTSC)			c.norm = VIDEO_MODE_NTSC;		if (norm->id & V4L2_STD_SECAM)			c.norm = VIDEO_MODE_SECAM;		saa7134_i2c_call_clients(dev,VIDIOCSCHAN,&c);	}#endif}static void video_mux(struct saa7134_dev *dev, int input){	dprintk("video input = %d [%s]\n",input,card_in(dev,input).name);	dev->ctl_input = input;	set_tvnorm(dev,dev->tvnorm);	saa7134_tvaudio_setinput(dev,&card_in(dev,input));}static void set_h_prescale(struct saa7134_dev *dev, int task, int prescale){	static const struct {		int xpsc;		int xacl;		int xc2_1;		int xdcg;		int vpfy;	} vals[] = {		/* XPSC XACL XC2_1 XDCG VPFY */		{    1,   0,    0,    0,   0 },		{    2,   2,    1,    2,   2 },		{    3,   4,    1,    3,   2 },		{    4,   8,    1,    4,   2 },		{    5,   8,    1,    4,   2 },		{    6,   8,    1,    4,   3 },		{    7,   8,    1,    4,   3 },		{    8,  15,    0,    4,   3 },		{    9,  15,    0,    4,   3 },		{   10,  16,    1,    5,   3 },	};	static const int count = ARRAY_SIZE(vals);	int i;	for (i = 0; i < count; i++)		if (vals[i].xpsc == prescale)			break;	if (i == count)		return;	saa_writeb(SAA7134_H_PRESCALE(task), vals[i].xpsc);	saa_writeb(SAA7134_ACC_LENGTH(task), vals[i].xacl);	saa_writeb(SAA7134_LEVEL_CTRL(task),		   (vals[i].xc2_1 << 3) | (vals[i].xdcg));	saa_andorb(SAA7134_FIR_PREFILTER_CTRL(task), 0x0f,		   (vals[i].vpfy << 2) | vals[i].vpfy);}static void set_v_scale(struct saa7134_dev *dev, int task, int yscale){	int val,mirror;		saa_writeb(SAA7134_V_SCALE_RATIO1(task), yscale &  0xff);	saa_writeb(SAA7134_V_SCALE_RATIO2(task), yscale >> 8);	mirror = (dev->ctl_mirror) ? 0x02 : 0x00;	if (yscale < 2048) {		/* LPI */		dprintk("yscale LPI yscale=%d\n",yscale);		saa_writeb(SAA7134_V_FILTER(task), 0x00 | mirror);		saa_writeb(SAA7134_LUMA_CONTRAST(task), 0x40);		saa_writeb(SAA7134_CHROMA_SATURATION(task), 0x40);	} else {		/* ACM */		val = 0x40 * 1024 / yscale;		dprintk("yscale ACM yscale=%d val=0x%x\n",yscale,val);		saa_writeb(SAA7134_V_FILTER(task), 0x01 | mirror);		saa_writeb(SAA7134_LUMA_CONTRAST(task), val);		saa_writeb(SAA7134_CHROMA_SATURATION(task), val);	}	saa_writeb(SAA7134_LUMA_BRIGHT(task),       0x80);}static void set_size(struct saa7134_dev *dev, int task,		     int width, int height, int interlace){	int prescale,xscale,yscale,y_even,y_odd;

⌨️ 快捷键说明

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